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