Skip to content

Instantly share code, notes, and snippets.

@krupitskas
Created August 7, 2018 21:29
Show Gist options
  • Save krupitskas/de0a8f9e587432048bc761c4a7ad84e5 to your computer and use it in GitHub Desktop.
Save krupitskas/de0a8f9e587432048bc761c4a7ad84e5 to your computer and use it in GitHub Desktop.
Shadertoy diffuse with shadow
const float EPSILON = 0.0001;
// ----- Primitives
float sdSphere(vec3 o, float r)
{
return length(o) - r;
}
float sdBox( vec3 p, vec3 b )
{
vec3 d = abs(p) - b;
return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0));
}
float sdPlane( vec3 p, vec4 n )
{
return dot(p,n.xyz) + n.w;
}
// ------ Operations
float map(vec3 p)
{
float result = 100000.;
result = min(result, sdBox(p + vec3(0, -1 ,0), vec3(1, 1, 2)));
result = min(result, sdSphere(p + vec3(-2, -0.1 ,0), 1.));
result = min(result, sdPlane(p + vec3(0, 1 ,0), vec4(0, 1, 0, 0)));
return result;
}
vec3 raydir(float fov, vec2 resolution, vec2 fragCoord)
{
return normalize(vec3(fragCoord.x - resolution.x / 2.,
fragCoord.y - resolution.y / 2.,
-resolution.y / tan(radians(fov) / 2.0)));
}
vec3 normal( in vec3 pos )
{
vec2 e = vec2(1.0,-1.0)*0.5773*0.0005;
return normalize( e.xyy*map( pos + e.xyy ) +
e.yyx*map( pos + e.yyx ) +
e.yxy*map( pos + e.yxy ) +
e.xxx*map( pos + e.xxx ) );
}
float shadow( vec3 ro, vec3 rd, float mint, float maxt )
{
for( float t = mint; t < maxt; )
{
float h = map(ro + rd * t);
if( h < EPSILON )
{
return 0.0;
}
t += h;
}
return 1.0;
}
vec4 calcLight(vec3 eye, vec3 p, vec3 dir)
{
vec3 lightPos = vec3(5. * sin(iTime),
5.,
-3. * cos(iTime));
vec3 lightRadiance = vec3(.5, .5, .5) * 2.;
vec3 N = normal(p);
vec3 L = normalize(lightPos - p);
vec3 V = normalize(eye - p);
vec3 R = normalize(reflect(-L, N));
vec3 ref = reflect( dir, N );
float dotLN = dot(L, N);
float dotRV = dot(R, V);
vec3 Kd = vec3(0.4, 0.5, 0.9);
vec3 Ks = vec3(0.4, 0.5, 0.9);
vec3 Ka = vec3(0.2, 0.2, 0.2);
float shininess = 10.;
vec3 color = vec3(0);
float s = shadow(p, lightPos, 0.02, 2.5);
//return vec4(s);
if (dotLN < 0.0)
{
return vec4(color, 1.0);
}
if (dotRV < 0.0)
{
color += lightRadiance * (Kd * dotLN);
color = pow( color, vec3(0.4545) );
return vec4(color, 1.0) * s;
}
color += lightRadiance * (Kd * dotLN + Ks * pow(dotRV, shininess));
color = pow( color, vec3(0.4545));
return vec4(color, 1.0) * s;
}
mat3 setCamera( in vec3 ro, in vec3 ta, float cr )
{
vec3 cw = normalize(ta-ro);
vec3 cp = vec3(sin(cr), cos(cr),0.0);
vec3 cu = normalize( cross(cw,cp) );
vec3 cv = normalize( cross(cu,cw) );
return mat3( cu, cv, cw );
}
float castRay( in vec3 ro, in vec3 rd )
{
float tmin = 1.0;
float tmax = 20.0;
float t = tmin;
for( int i=0; i<64; i++ )
{
float precis = 0.0004*t;
float res = map( ro + rd * t );
if( res<precis || t>tmax ) break;
t += res;
}
return t;
}
vec4 render(vec2 resolution, vec2 fragCoord)
{
vec2 point = (-iResolution.xy + 2.0 * fragCoord) / iResolution.y;
vec3 ro = vec3(4.0, 1.0, 4.0);
vec3 dir = raydir(45., resolution, fragCoord);
vec3 at = vec3(0,0,0);
mat3 ca = setCamera( ro, at, 0.0 );
vec3 rd = ca * normalize( vec3(point.xy, 2.0) );
float depth = 0.;
vec4 backColor = vec4(0.4, 0.5, 0.6, 1.);
float res = castRay(ro, rd);
vec3 pos = ro + res * rd;
vec3 lightPos = normalize( vec3(-0.4 * sin(iTime),
0.7,
-0.6 * cos(iTime)) );
vec3 lightRadiance = vec3(.5, .5, .5) * 2.;
vec3 N = normal(pos);
vec3 L = normalize(lightPos - pos);
vec3 V = normalize(ro - pos);
vec3 R = normalize(reflect(-L, N));
vec3 ref = reflect( dir, N );
float dotLN = dot(L, N);
float dotRV = dot(R, V);
vec3 Kd = vec3(0.4, 0.5, 0.9);
vec3 Ks = vec3(0.4, 0.5, 0.9);
vec3 Ka = vec3(0.2, 0.2, 0.2);
float shininess = 10.;
vec3 color = vec3(0);
float dif = clamp( dot( N, lightPos ), 0.0, 1.0 );
dif *= shadow( pos, lightPos, 0.02, 2.5 );
return vec4(vec3(dif), 1.0);
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
fragColor = render(iResolution.xy, fragCoord);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment