【GLSL】球とRGBの光源
See the Pen sphere with rgb lights by aadebdeb (@aadebdeb) on CodePen.
#define PI 3.14159265359 #define TWO_PI PI * 2.0 precision mediump float; uniform float u_time; uniform vec2 u_mouse; uniform vec2 u_resolution; float calcSphereDistance(vec3 p, float size) { return length(p) - size; } float calcDistance(vec3 p) { float d = calcSphereDistance(p, 1.0); return d; } vec3 calcNormal(vec3 p) { float delta = 0.00001; return normalize(vec3( calcDistance(p + vec3(delta, 0.0, 0.0)) - calcDistance(p - vec3(delta, 0.0, 0.0)), calcDistance(p + vec3(0.0, delta, 0.0)) - calcDistance(p - vec3(0.0, delta, 0.0)), calcDistance(p + vec3(0.0, 0.0, delta)) - calcDistance(p - vec3(0.0, 0.0, delta)) )); } void main(void) { vec2 st = (gl_FragCoord.xy * 2.0 - u_resolution) / min(u_resolution.x, u_resolution.y); vec3 cameraPosition = vec3(0.0, 0.0, 10.0); vec3 rayDirection = normalize(vec3(st, 0.0) - cameraPosition); vec3 rayPosition = cameraPosition; float radian = u_time * 0.001; vec3 lightPositionR = vec3(10.0 * sin(radian), 10.0, 10.0 * cos(radian)); vec3 lightPositionG = vec3(10.0 * sin(radian * 3.0), 10.0, 10.0 * cos(radian * 3.0)); vec3 lightPositionB = vec3(10.0 * sin(radian * 5.0), 10.0, 10.0 * cos(radian * 5.0)); vec3 color = vec3(0.0); for (int i = 0; i < 16; i++) { float d = calcDistance(rayPosition); if (d < 0.0001) { vec3 normal = calcNormal(rayPosition); float weightR = dot(normal, normalize(lightPositionR)); float weightG = dot(normal, normalize(lightPositionG)); float weightB = dot(normal, normalize(lightPositionB)); color = vec3(1.0, 0.0, 0.0) * max(weightR, 0.0) + vec3(0.0, 1.0, 0.0) * max(weightG, 0.0) + vec3(0.0, 0.0, 1.0) * max(weightB, 0.0) + vec3(0.1); break; } rayPosition += rayDirection * d; } gl_FragColor = vec4(color, 1.0); }