const float aR = 16.0/9.0; float remap(float value, float low1, float high1, float low2, float high2) { return low2 + (value - low1) * (high2 - low2) / (high1 - low1); } // polynomial smooth min (k = 0.1); (IQuilez) float smin(float a, float b, float k) { float h = clamp( 0.5+0.5*(b-a)/k, 0.0, 1.0 ); return mix( b, a, h ) - k*h*(1.0-h); } struct Circle { vec2 pos; float radius; }; Circle circle1 = Circle(vec2(.3, .3), .2); Circle circle2 = Circle(vec2(1, .5), .2); Circle circle3 = Circle(vec2(1, .5), .2); //settings const float timeStep = 1.0; const float smoothFactor = 0.2; float distToCenter(vec2 point, Circle circle) { return sqrt(pow(point.x - circle.pos.x, 2.0) + pow(point.y - circle.pos.y, 2.0)); } void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 uv = fragCoord/iResolution.y; //Circle Movement float timeSine = (sin(iTime/timeStep)+1.0)/2.0; float timeCos = (cos(iTime/.7)+1.0)/2.0; float timeTan = (tan(iTime/timeStep)+1.0)/2.0; circle1.pos.x = mix(0.0 + circle1.radius, aR - circle1.radius, timeSine); circle1.pos.y = mix(0.0 + circle1.radius, 1.0 - circle1.radius, timeSine); circle2.pos.x = aR-mix(0.0 + circle2.radius, aR - circle2.radius, timeSine); circle3.pos.y = mix(0.0 + circle3.radius, 1.0 - circle3.radius, timeCos); circle3.pos.x = mix(0.0 + circle3.radius, aR - circle3.radius, 1.0-timeCos); //For coloring based on distance to closest center float centerDist = distToCenter(uv, circle1); float centerDist2 = distToCenter(uv, circle2); float centerDist3 = distToCenter(uv, circle3); float closestCenterDist = min(min(centerDist, centerDist2), centerDist3); float circleDist = centerDist - circle1.radius; circleDist = smin(circleDist, centerDist2 - circle2.radius, smoothFactor); circleDist = smin(circleDist, centerDist3 - circle3.radius, smoothFactor); if(circleDist <= .01) { //centreDist ranges from 0 (center) to radius (circumpherence) //normalize in 0...1 range by dividing by radius closestCenterDist /= .2; centerDist /=.2; centerDist2 /=.2; centerDist3 /=.2; //Weighted distribution of color, the closest you are to a sphere the more its color //bleeds onto the current pixel. // distanceToCircle // ---------------- // distanceToAllCircles //Thought i had to do 1 - this but apparently it works like this so eh ill take it float c1Infl = centerDist / (centerDist + centerDist2 + centerDist3); float c2Infl = centerDist2 / (centerDist + centerDist2 + centerDist3); float c3Infl = centerDist3 / (centerDist + centerDist2 + centerDist3); vec3 col1 = vec3(146, 0, 255) * c1Infl; vec3 col2 = vec3(255, 146, 0) * c2Infl; vec3 col3 = vec3(0, 255, 146) * c3Infl; fragColor = vec4(/*closestCenterDist * */(col1+col2 + col3)/255.0, 1.0); } else { fragColor = vec4(0); } }
float distanceToSphere(vec3 sphere, vec2 point) { return sqrt(pow((point.x - sphere.x), 2.0)+pow((point.y - sphere.y), 2.0))- sphere.z; } //Position xy, Radius vec3 sphere1 = vec3(1.3, .3, .05); vec3 sphere2 = vec3(.4, .45, .05); float intensity = 2.0; struct PointLight { vec2 pos; vec3 color; float intensity; }; PointLight centerLight = PointLight(vec2(0, 0), vec3(.1, .3, .8), 2.0); PointLight rightLight = PointLight(vec2(.3, .7), vec3(.7, .2, .5), 2.0); vec3 RenderLight(PointLight light, vec2 uv) { vec3 finalColor = vec3(0); vec2 ray = normalize(light.pos - uv); int maxSteps = 200; vec2 currentPoint = uv; float travelledDist = 0.0; float dist, dist2; float smallestDistance = 1.0; for(int i = 0; i < maxSteps; i++) { dist = distanceToSphere(sphere1, currentPoint); dist2 = distanceToSphere(sphere2, currentPoint); float distToTarget = length(light.pos - currentPoint); float minDistance = min(min(dist, dist2), distToTarget); smallestDistance = min(smallestDistance, min(dist, dist2)); if(minDistance < .01) { break; } travelledDist += minDistance; currentPoint = uv + ray * travelledDist; if(length(currentPoint-light.pos)<.02) { float lightVal = .2 * (1.0 - length(uv - light.pos) + .2); if(smallestDistance < .03) { float clamper = smallestDistance / .03; finalColor = light.color * light.intensity * mix(0.0, lightVal, clamper); } else { finalColor += light.color * lightVal * light.intensity; } break; } } return finalColor; } void mainImage( out vec4 fragColor, in vec2 fragCoord ) { // Normalized pixel coordinates (from 0 to 1) vec2 uv = fragCoord/iResolution.y; vec2 mousePos = iMouse.xy / iResolution.y; // Time varying pixel color //vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4)); // Output to screen fragColor = vec4(0); centerLight.pos = mousePos; rightLight.pos.x = .30 + (sin(iTime/1.5)+1.0)/2.0; vec3 light1 = RenderLight(centerLight, uv); vec3 light2 = RenderLight(rightLight, uv); fragColor = vec4(light1 + light2, 1); float dist, dist2; dist = distanceToSphere(sphere1, uv); dist2 = distanceToSphere(sphere2, uv); if(dist < .01) { fragColor = vec4(1); } if(dist2 < .01) { fragColor = vec4(1); } }
Click on the screen to interact with the light