Here's an animated eyeball (hat tip chatgpt):
uniform float time; varying vec2 vUv; vec3 lighting(vec3 normal, vec3 eyeDirection, vec3 lightDirection) { float diffuse = max(dot(normal, lightDirection), 0.0); vec3 reflected = reflect(-lightDirection, normal); float specular = pow(max(dot(reflected, eyeDirection), 0.0), 16.0); return vec3(0.1) + diffuse * vec3(0.5) + specular * vec3(0.3); } void main() { float theta = vUv.x * 2.0 * 3.14159265359; float phi = (1.0 - vUv.y) * 3.14159265359; vec3 sphereCoord = vec3(sin(phi) * cos(theta), cos(phi), sin(phi) * sin(theta)); vec2 irisPosition = vec2(sin(time * 0.5) * 0.1, cos(time * 0.7) * 0.1); float irisDistance = length(sphereCoord.xy - irisPosition); float irisRadius = 0.25; float pupilRadius = 0.1; float irisEdgeSoftness = 0.02; vec3 color; if (irisDistance < pupilRadius) { color = vec3(0.0); } else if (irisDistance < irisRadius) { float t = smoothstep(irisRadius - irisEdgeSoftness, irisRadius, irisDistance); color = mix(vec3(0.0, 0.0, 1.0), vec3(0.5, 0.25, 0.0), t); color += 0.05 * sin(20.0 * irisDistance + time); } else { color = vec3(1.0); } vec3 eyelidColor = vec3(1.4, 0.90, 0.60); float blinkSpeed = 0.5; // Reduce this value to slow down the blinking float blink = abs(sin(time * 3.14159265359 * blinkSpeed)); float eyelidPosition = mix(0.4, 0.5, blink); float upperEyelid = step(eyelidPosition, vUv.y); float lowerEyelid = step(eyelidPosition, 1.0 - vUv.y); color = mix(color, eyelidColor, 1.0 - upperEyelid * lowerEyelid); vec3 normal = normalize(sphereCoord); vec3 lightDirection = normalize(vec3(0.0, 1.0, 1.0)); vec3 eyeDirection = normalize(vec3(0.0, 0.0, 1.0)); vec3 litColor = color * lighting(normal, eyeDirection, lightDirection); gl_FragColor = vec4(litColor, 1.0); }
Here's an animated eyeball (hat tip chatgpt):