v2 / examples / sokol / 04_multi_shader_glsl / rt_glsl_march.glsl
697 lines · 587 sloc · 18.99 KB · 3c68e78f32d95e0552f6fa496ed245c1304731d5
Raw
1//------------------------------------------------------------------------------
2// Shader code for texcube-sapp sample.
3//
4// NOTE: This source file also uses the '#pragma sokol' form of the
5// custom tags.
6//------------------------------------------------------------------------------
7//#pragma sokol @ctype mat4 hmm_mat4
8
9#pragma sokol @vs vs_m
10uniform vs_params_m {
11 mat4 mvp;
12};
13
14in vec4 pos;
15in vec4 color0;
16in vec2 texcoord0;
17
18out vec4 color;
19out vec2 uv;
20
21void main() {
22 gl_Position = mvp * pos;
23 color = color0;
24 uv = texcoord0;
25}
26#pragma sokol @end
27
28#pragma sokol @fs fs_m
29uniform texture2D tex;
30uniform sampler smp;
31
32uniform fs_params_m {
33 vec2 iResolution;
34 vec2 iMouse;
35 float iTime;
36 float iFrame;
37};
38
39in vec4 color;
40in vec2 uv;
41out vec4 frag_color;
42
43// change to 0 to 4 to increment the AntiAliasing,
44// increase AA will SLOW the rendering!!
45#define AA 1
46
47//*********************************************************
48// Ray Marching
49// original code from: https://www.shadertoy.com/view/Xds3zN
50//*********************************************************
51// The MIT License
52// Copyright © 2013 Inigo Quilez
53// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
54
55// A list of useful distance function to simple primitives. All
56// these functions (except for ellipsoid) return an exact
57// euclidean distance, meaning they produce a better SDF than
58// what you'd get if you were constructing them from boolean
59// operations.
60//
61// More info here:
62//
63// https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm
64
65//------------------------------------------------------------------
66float dot2( in vec2 v ) { return dot(v,v); }
67float dot2( in vec3 v ) { return dot(v,v); }
68float ndot( in vec2 a, in vec2 b ) { return a.x*b.x - a.y*b.y; }
69
70float sdPlane( vec3 p )
71{
72 return p.y;
73}
74
75float sdSphere( vec3 p, float s )
76{
77 return length(p)-s;
78}
79
80float sdBox( vec3 p, vec3 b )
81{
82 vec3 d = abs(p) - b;
83 return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0));
84}
85
86float sdBoundingBox( vec3 p, vec3 b, float e )
87{
88 p = abs(p )-b;
89 vec3 q = abs(p+e)-e;
90
91 return min(min(
92 length(max(vec3(p.x,q.y,q.z),0.0))+min(max(p.x,max(q.y,q.z)),0.0),
93 length(max(vec3(q.x,p.y,q.z),0.0))+min(max(q.x,max(p.y,q.z)),0.0)),
94 length(max(vec3(q.x,q.y,p.z),0.0))+min(max(q.x,max(q.y,p.z)),0.0));
95}
96float sdEllipsoid( in vec3 p, in vec3 r ) // approximated
97{
98 float k0 = length(p/r);
99 float k1 = length(p/(r*r));
100 return k0*(k0-1.0)/k1;
101}
102
103float sdTorus( vec3 p, vec2 t )
104{
105 return length( vec2(length(p.xz)-t.x,p.y) )-t.y;
106}
107
108float sdCappedTorus(in vec3 p, in vec2 sc, in float ra, in float rb)
109{
110 p.x = abs(p.x);
111 float k = (sc.y*p.x>sc.x*p.y) ? dot(p.xy,sc) : length(p.xy);
112 return sqrt( dot(p,p) + ra*ra - 2.0*ra*k ) - rb;
113}
114
115float sdHexPrism( vec3 p, vec2 h )
116{
117 vec3 q = abs(p);
118
119 const vec3 k = vec3(-0.8660254, 0.5, 0.57735);
120 p = abs(p);
121 p.xy -= 2.0*min(dot(k.xy, p.xy), 0.0)*k.xy;
122 vec2 d = vec2(
123 length(p.xy - vec2(clamp(p.x, -k.z*h.x, k.z*h.x), h.x))*sign(p.y - h.x),
124 p.z-h.y );
125 return min(max(d.x,d.y),0.0) + length(max(d,0.0));
126}
127
128float sdOctogonPrism( in vec3 p, in float r, float h )
129{
130 const vec3 k = vec3(-0.9238795325, // sqrt(2+sqrt(2))/2
131 0.3826834323, // sqrt(2-sqrt(2))/2
132 0.4142135623 ); // sqrt(2)-1
133 // reflections
134 p = abs(p);
135 p.xy -= 2.0*min(dot(vec2( k.x,k.y),p.xy),0.0)*vec2( k.x,k.y);
136 p.xy -= 2.0*min(dot(vec2(-k.x,k.y),p.xy),0.0)*vec2(-k.x,k.y);
137 // polygon side
138 p.xy -= vec2(clamp(p.x, -k.z*r, k.z*r), r);
139 vec2 d = vec2( length(p.xy)*sign(p.y), p.z-h );
140 return min(max(d.x,d.y),0.0) + length(max(d,0.0));
141}
142
143float sdCapsule( vec3 p, vec3 a, vec3 b, float r )
144{
145 vec3 pa = p-a, ba = b-a;
146 float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
147 return length( pa - ba*h ) - r;
148}
149
150float sdRoundCone( in vec3 p, in float r1, float r2, float h )
151{
152 vec2 q = vec2( length(p.xz), p.y );
153
154 float b = (r1-r2)/h;
155 float a = sqrt(1.0-b*b);
156 float k = dot(q,vec2(-b,a));
157
158 if( k < 0.0 ) return length(q) - r1;
159 if( k > a*h ) return length(q-vec2(0.0,h)) - r2;
160
161 return dot(q, vec2(a,b) ) - r1;
162}
163
164float sdRoundCone(vec3 p, vec3 a, vec3 b, float r1, float r2)
165{
166 // sampling independent computations (only depend on shape)
167 vec3 ba = b - a;
168 float l2 = dot(ba,ba);
169 float rr = r1 - r2;
170 float a2 = l2 - rr*rr;
171 float il2 = 1.0/l2;
172
173 // sampling dependent computations
174 vec3 pa = p - a;
175 float y = dot(pa,ba);
176 float z = y - l2;
177 float x2 = dot2( pa*l2 - ba*y );
178 float y2 = y*y*l2;
179 float z2 = z*z*l2;
180
181 // single square root!
182 float k = sign(rr)*rr*rr*x2;
183 if( sign(z)*a2*z2 > k ) return sqrt(x2 + z2) *il2 - r2;
184 if( sign(y)*a2*y2 < k ) return sqrt(x2 + y2) *il2 - r1;
185 return (sqrt(x2*a2*il2)+y*rr)*il2 - r1;
186}
187
188float sdTriPrism( vec3 p, vec2 h )
189{
190 const float k = sqrt(3.0);
191 h.x *= 0.5*k;
192 p.xy /= h.x;
193 p.x = abs(p.x) - 1.0;
194 p.y = p.y + 1.0/k;
195 if( p.x+k*p.y>0.0 ) p.xy=vec2(p.x-k*p.y,-k*p.x-p.y)/2.0;
196 p.x -= clamp( p.x, -2.0, 0.0 );
197 float d1 = length(p.xy)*sign(-p.y)*h.x;
198 float d2 = abs(p.z)-h.y;
199 return length(max(vec2(d1,d2),0.0)) + min(max(d1,d2), 0.);
200}
201
202// vertical
203float sdCylinder( vec3 p, vec2 h )
204{
205 vec2 d = abs(vec2(length(p.xz),p.y)) - h;
206 return min(max(d.x,d.y),0.0) + length(max(d,0.0));
207}
208
209// arbitrary orientation
210float sdCylinder(vec3 p, vec3 a, vec3 b, float r)
211{
212 vec3 pa = p - a;
213 vec3 ba = b - a;
214 float baba = dot(ba,ba);
215 float paba = dot(pa,ba);
216
217 float x = length(pa*baba-ba*paba) - r*baba;
218 float y = abs(paba-baba*0.5)-baba*0.5;
219 float x2 = x*x;
220 float y2 = y*y*baba;
221 float d = (max(x,y)<0.0)?-min(x2,y2):(((x>0.0)?x2:0.0)+((y>0.0)?y2:0.0));
222 return sign(d)*sqrt(abs(d))/baba;
223}
224
225// vertical
226float sdCone( in vec3 p, in vec2 c, float h )
227{
228 vec2 q = h*vec2(c.x,-c.y)/c.y;
229 vec2 w = vec2( length(p.xz), p.y );
230
231 vec2 a = w - q*clamp( dot(w,q)/dot(q,q), 0.0, 1.0 );
232 vec2 b = w - q*vec2( clamp( w.x/q.x, 0.0, 1.0 ), 1.0 );
233 float k = sign( q.y );
234 float d = min(dot( a, a ),dot(b, b));
235 float s = max( k*(w.x*q.y-w.y*q.x),k*(w.y-q.y) );
236 return sqrt(d)*sign(s);
237}
238
239float sdCappedCone( in vec3 p, in float h, in float r1, in float r2 )
240{
241 vec2 q = vec2( length(p.xz), p.y );
242
243 vec2 k1 = vec2(r2,h);
244 vec2 k2 = vec2(r2-r1,2.0*h);
245 vec2 ca = vec2(q.x-min(q.x,(q.y < 0.0)?r1:r2), abs(q.y)-h);
246 vec2 cb = q - k1 + k2*clamp( dot(k1-q,k2)/dot2(k2), 0.0, 1.0 );
247 float s = (cb.x < 0.0 && ca.y < 0.0) ? -1.0 : 1.0;
248 return s*sqrt( min(dot2(ca),dot2(cb)) );
249}
250
251float sdCappedCone(vec3 p, vec3 a, vec3 b, float ra, float rb)
252{
253 float rba = rb-ra;
254 float baba = dot(b-a,b-a);
255 float papa = dot(p-a,p-a);
256 float paba = dot(p-a,b-a)/baba;
257
258 float x = sqrt( papa - paba*paba*baba );
259
260 float cax = max(0.0,x-((paba<0.5)?ra:rb));
261 float cay = abs(paba-0.5)-0.5;
262
263 float k = rba*rba + baba;
264 float f = clamp( (rba*(x-ra)+paba*baba)/k, 0.0, 1.0 );
265
266 float cbx = x-ra - f*rba;
267 float cby = paba - f;
268
269 float s = (cbx < 0.0 && cay < 0.0) ? -1.0 : 1.0;
270
271 return s*sqrt( min(cax*cax + cay*cay*baba,
272 cbx*cbx + cby*cby*baba) );
273}
274
275// c is the sin/cos of the desired cone angle
276float sdSolidAngle(vec3 pos, vec2 c, float ra)
277{
278 vec2 p = vec2( length(pos.xz), pos.y );
279 float l = length(p) - ra;
280 float m = length(p - c*clamp(dot(p,c),0.0,ra) );
281 return max(l,m*sign(c.y*p.x-c.x*p.y));
282}
283
284float sdOctahedron(vec3 p, float s)
285{
286 p = abs(p);
287 float m = p.x + p.y + p.z - s;
288
289// exact distance
290#if 0
291 vec3 o = min(3.0*p - m, 0.0);
292 o = max(6.0*p - m*2.0 - o*3.0 + (o.x+o.y+o.z), 0.0);
293 return length(p - s*o/(o.x+o.y+o.z));
294#endif
295
296// exact distance
297#if 1
298 vec3 q;
299 if( 3.0*p.x < m ) q = p.xyz;
300 else if( 3.0*p.y < m ) q = p.yzx;
301 else if( 3.0*p.z < m ) q = p.zxy;
302 else return m*0.57735027;
303 float k = clamp(0.5*(q.z-q.y+s),0.0,s);
304 return length(vec3(q.x,q.y-s+k,q.z-k));
305#endif
306
307// bound, not exact
308#if 0
309 return m*0.57735027;
310#endif
311}
312
313float sdPyramid( in vec3 p, in float h )
314{
315 float m2 = h*h + 0.25;
316
317 // symmetry
318 p.xz = abs(p.xz);
319 p.xz = (p.z>p.x) ? p.zx : p.xz;
320 p.xz -= 0.5;
321
322 // project into face plane (2D)
323 vec3 q = vec3( p.z, h*p.y - 0.5*p.x, h*p.x + 0.5*p.y);
324
325 float s = max(-q.x,0.0);
326 float t = clamp( (q.y-0.5*p.z)/(m2+0.25), 0.0, 1.0 );
327
328 float a = m2*(q.x+s)*(q.x+s) + q.y*q.y;
329 float b = m2*(q.x+0.5*t)*(q.x+0.5*t) + (q.y-m2*t)*(q.y-m2*t);
330
331 float d2 = min(q.y,-q.x*m2-q.y*0.5) > 0.0 ? 0.0 : min(a,b);
332
333 // recover 3D and scale, and add sign
334 return sqrt( (d2+q.z*q.z)/m2 ) * sign(max(q.z,-p.y));
335}
336
337// la,lb=semi axis, h=height, ra=corner
338float sdRhombus(vec3 p, float la, float lb, float h, float ra)
339{
340 p = abs(p);
341 vec2 b = vec2(la,lb);
342 float f = clamp( (ndot(b,b-2.0*p.xz))/dot(b,b), -1.0, 1.0 );
343 vec2 q = vec2(length(p.xz-0.5*b*vec2(1.0-f,1.0+f))*sign(p.x*b.y+p.z*b.x-b.x*b.y)-ra, p.y-h);
344 return min(max(q.x,q.y),0.0) + length(max(q,0.0));
345}
346
347//------------------------------------------------------------------
348
349vec2 opU( vec2 d1, vec2 d2 )
350{
351 return (d1.x<d2.x) ? d1 : d2;
352}
353
354//------------------------------------------------------------------
355
356#define ZERO (min(int(iFrame),0))
357
358//------------------------------------------------------------------
359
360vec2 map( in vec3 pos )
361{
362 vec2 res = vec2( 1e10, 0.0 );
363
364 {
365 res = opU( res, vec2( sdSphere( pos-vec3(-2.0,0.25, 0.0), 0.25 ), 26.9 ) );
366 }
367
368 // bounding box
369 if( sdBox( pos-vec3(0.0,0.3,-1.0),vec3(0.35,0.3,2.5) )<res.x )
370 {
371 // more primitives
372 res = opU( res, vec2( sdBoundingBox( pos-vec3( 0.0,0.25, 0.0), vec3(0.3,0.25,0.2), 0.025 ), 16.9 ) );
373 res = opU( res, vec2( sdTorus( (pos-vec3( 0.0,0.30, 1.0)).xzy, vec2(0.25,0.05) ), 25.0 ) );
374 res = opU( res, vec2( sdCone( pos-vec3( 0.0,0.45,-1.0), vec2(0.6,0.8),0.45 ), 55.0 ) );
375 res = opU( res, vec2( sdCappedCone( pos-vec3( 0.0,0.25,-2.0), 0.25, 0.25, 0.1 ), 13.67 ) );
376 res = opU( res, vec2( sdSolidAngle( pos-vec3( 0.0,0.00,-3.0), vec2(3,4)/5.0, 0.4 ), 49.13 ) );
377 }
378
379 // bounding box
380 if( sdBox( pos-vec3(1.0,0.3,-1.0),vec3(0.35,0.3,2.5) )<res.x )
381 {
382 // more primitives
383 res = opU( res, vec2( sdCappedTorus((pos-vec3( 1.0,0.30, 1.0))*vec3(1,-1,1), vec2(0.866025,-0.5), 0.25, 0.05), 8.5) );
384 res = opU( res, vec2( sdBox( pos-vec3( 1.0,0.25, 0.0), vec3(0.3,0.25,0.1) ), 3.0 ) );
385 res = opU( res, vec2( sdCapsule( pos-vec3( 1.0,0.00,-1.0),vec3(-0.1,0.1,-0.1), vec3(0.2,0.4,0.2), 0.1 ), 31.9 ) );
386 res = opU( res, vec2( sdCylinder( pos-vec3( 1.0,0.25,-2.0), vec2(0.15,0.25) ), 8.0 ) );
387 res = opU( res, vec2( sdHexPrism( pos-vec3( 1.0,0.2,-3.0), vec2(0.2,0.05) ), 18.4 ) );
388 }
389
390 // bounding box
391 if( sdBox( pos-vec3(-1.0,0.35,-1.0),vec3(0.35,0.35,2.5))<res.x )
392 {
393 // more primitives
394 res = opU( res, vec2( sdPyramid( pos-vec3(-1.0,-0.6,-3.0), 1.0 ), 13.56 ) );
395 res = opU( res, vec2( sdOctahedron( pos-vec3(-1.0,0.15,-2.0), 0.35 ), 23.56 ) );
396 res = opU( res, vec2( sdTriPrism( pos-vec3(-1.0,0.15,-1.0), vec2(0.3,0.05) ),43.5 ) );
397 res = opU( res, vec2( sdEllipsoid( pos-vec3(-1.0,0.25, 0.0), vec3(0.2, 0.25, 0.05) ), 43.17 ) );
398 res = opU( res, vec2( sdRhombus( (pos-vec3(-1.0,0.34, 1.0)).xzy, 0.15, 0.25, 0.04, 0.08 ),17.0 ) );
399 }
400
401 // bounding box
402 if( sdBox( pos-vec3(2.0,0.3,-1.0),vec3(0.35,0.3,2.5) )<res.x )
403 {
404 // more primitives
405 res = opU( res, vec2( sdOctogonPrism(pos-vec3( 2.0,0.2,-3.0), 0.2, 0.05), 51.8 ) );
406 res = opU( res, vec2( sdCylinder( pos-vec3( 2.0,0.15,-2.0), vec3(0.1,-0.1,0.0), vec3(-0.2,0.35,0.1), 0.08), 31.2 ) );
407 res = opU( res, vec2( sdCappedCone( pos-vec3( 2.0,0.10,-1.0), vec3(0.1,0.0,0.0), vec3(-0.2,0.40,0.1), 0.15, 0.05), 46.1 ) );
408 res = opU( res, vec2( sdRoundCone( pos-vec3( 2.0,0.15, 0.0), vec3(0.1,0.0,0.0), vec3(-0.1,0.35,0.1), 0.15, 0.05), 51.7 ) );
409 res = opU( res, vec2( sdRoundCone( pos-vec3( 2.0,0.20, 1.0), 0.2, 0.1, 0.3 ), 37.0 ) );
410 }
411
412 return res;
413}
414
415// http://iquilezles.org/www/articles/boxfunctions/boxfunctions.htm
416vec2 iBox( in vec3 ro, in vec3 rd, in vec3 rad )
417{
418 vec3 m = 1.0/rd;
419 vec3 n = m*ro;
420 vec3 k = abs(m)*rad;
421 vec3 t1 = -n - k;
422 vec3 t2 = -n + k;
423 return vec2( max( max( t1.x, t1.y ), t1.z ),
424 min( min( t2.x, t2.y ), t2.z ) );
425}
426
427vec2 raycast( in vec3 ro, in vec3 rd )
428{
429 vec2 res = vec2(-1.0,-1.0);
430
431 float tmin = 1.0;
432 float tmax = 20.0;
433
434 // raytrace floor plane
435 float tp1 = (0.0-ro.y)/rd.y;
436 if( tp1>0.0 )
437 {
438 tmax = min( tmax, tp1 );
439 res = vec2( tp1, 1.0 );
440 }
441 //else return res;
442
443 // raymarch primitives
444 vec2 tb = iBox( ro-vec3(0.0,0.4,-0.5), rd, vec3(2.5,0.41,3.0) );
445 if( tb.x<tb.y && tb.y>0.0 && tb.x<tmax)
446 {
447 //return vec2(tb.x,2.0);
448 tmin = max(tb.x,tmin);
449 tmax = min(tb.y,tmax);
450
451 float t = tmin;
452 for( int i=0; i<70 && t<tmax; i++ )
453 {
454 vec2 h = map( ro+rd*t );
455 if( abs(h.x)<(0.0001*t) )
456 {
457 res = vec2(t,h.y);
458 break;
459 }
460 t += h.x;
461 }
462 }
463
464 return res;
465}
466
467// http://iquilezles.org/www/articles/rmshadows/rmshadows.htm
468float calcSoftshadow( in vec3 ro, in vec3 rd, in float mint, in float tmax )
469{
470 // bounding volume
471 float tp = (0.8-ro.y)/rd.y; if( tp>0.0 ) tmax = min( tmax, tp );
472
473 float res = 1.0;
474 float t = mint;
475 for( int i=ZERO; i<24; i++ )
476 {
477 float h = map( ro + rd*t ).x;
478 float s = clamp(8.0*h/t,0.0,1.0);
479 res = min( res, s*s*(3.0-2.0*s) );
480 t += clamp( h, 0.02, 0.2 );
481 if( res<0.004 || t>tmax ) break;
482 }
483 return clamp( res, 0.0, 1.0 );
484}
485
486// http://iquilezles.org/www/articles/normalsSDF/normalsSDF.htm
487vec3 calcNormal( in vec3 pos )
488{
489#if 0
490 vec2 e = vec2(1.0,-1.0)*0.5773*0.0005;
491 return normalize( e.xyy*map( pos + e.xyy ).x +
492 e.yyx*map( pos + e.yyx ).x +
493 e.yxy*map( pos + e.yxy ).x +
494 e.xxx*map( pos + e.xxx ).x );
495#else
496 // inspired by tdhooper and klems - a way to prevent the compiler from inlining map() 4 times
497 vec3 n = vec3(0.0);
498 for( int i=ZERO; i<4; i++ )
499 {
500 vec3 e = 0.5773*(2.0*vec3((((i+3)>>1)&1),((i>>1)&1),(i&1))-1.0);
501 n += e*map(pos+0.0005*e).x;
502 //if( n.x+n.y+n.z>100.0 ) break;
503 }
504 return normalize(n);
505#endif
506}
507
508float calcAO( in vec3 pos, in vec3 nor )
509{
510 float occ = 0.0;
511 float sca = 1.0;
512 for( int i=ZERO; i<5; i++ )
513 {
514 float h = 0.01 + 0.12*float(i)/4.0;
515 float d = map( pos + h*nor ).x;
516 occ += (h-d)*sca;
517 sca *= 0.95;
518 if( occ>0.35 ) break;
519 }
520 return clamp( 1.0 - 3.0*occ, 0.0, 1.0 ) * (0.5+0.5*nor.y);
521}
522
523// http://iquilezles.org/www/articles/checkerfiltering/checkerfiltering.htm
524float checkersGradBox( in vec2 p, in vec2 dpdx, in vec2 dpdy )
525{
526 // filter kernel
527 vec2 w = abs(dpdx)+abs(dpdy) + 0.001;
528 // analytical integral (box filter)
529 vec2 i = 2.0*(abs(fract((p-0.5*w)*0.5)-0.5)-abs(fract((p+0.5*w)*0.5)-0.5))/w;
530 // xor pattern
531 return 0.5 - 0.5*i.x*i.y;
532}
533
534vec3 render( in vec3 ro, in vec3 rd, in vec3 rdx, in vec3 rdy )
535{
536 // background
537 vec3 col = vec3(0.7, 0.7, 0.9) - max(rd.y,0.0)*0.3;
538
539 // raycast scene
540 vec2 res = raycast(ro,rd);
541 float t = res.x;
542 float m = res.y;
543 if( m>-0.5 )
544 {
545 vec3 pos = ro + t*rd;
546 vec3 nor = (m<1.5) ? vec3(0.0,1.0,0.0) : calcNormal( pos );
547 vec3 ref = reflect( rd, nor );
548
549 // material
550 col = 0.2 + 0.2*sin( m*2.0 + vec3(0.0,1.0,2.0) );
551 float ks = 1.0;
552
553 if( m<1.5 )
554 {
555 // project pixel footprint into the plane
556 vec3 dpdx = ro.y*(rd/rd.y-rdx/rdx.y);
557 vec3 dpdy = ro.y*(rd/rd.y-rdy/rdy.y);
558
559 float f = checkersGradBox( 3.0*pos.xz, 3.0*dpdx.xz, 3.0*dpdy.xz );
560 col = 0.15 + f*vec3(0.05);
561 ks = 0.4;
562 }
563
564 // lighting
565 float occ = calcAO( pos, nor );
566
567 vec3 lin = vec3(0.0);
568
569 // sun
570 {
571 vec3 lig = normalize( vec3(-0.5, 0.4, -0.6) );
572 vec3 hal = normalize( lig-rd );
573 float dif = clamp( dot( nor, lig ), 0.0, 1.0 );
574 //if( dif>0.0001 )
575 dif *= calcSoftshadow( pos, lig, 0.02, 2.5 );
576 float spe = pow( clamp( dot( nor, hal ), 0.0, 1.0 ),16.0);
577 spe *= dif;
578 spe *= 0.04+0.96*pow(clamp(1.0-dot(hal,lig),0.0,1.0),5.0);
579 lin += col*2.20*dif*vec3(1.30,1.00,0.70);
580 lin += 5.00*spe*vec3(1.30,1.00,0.70)*ks;
581 }
582 // sky
583 {
584 float dif = sqrt(clamp( 0.5+0.5*nor.y, 0.0, 1.0 ));
585 dif *= occ;
586 float spe = smoothstep( -0.2, 0.2, ref.y );
587 spe *= dif;
588 spe *= 0.04+0.96*pow(clamp(1.0+dot(nor,rd),0.0,1.0), 5.0 );
589 //if( spe>0.001 )
590 spe *= calcSoftshadow( pos, ref, 0.02, 2.5 );
591 lin += col*0.60*dif*vec3(0.40,0.60,1.15);
592 lin += 2.00*spe*vec3(0.40,0.60,1.30)*ks;
593 }
594 // back
595 {
596 float dif = clamp( dot( nor, normalize(vec3(0.5,0.0,0.6))), 0.0, 1.0 )*clamp( 1.0-pos.y,0.0,1.0);
597 dif *= occ;
598 lin += col*0.55*dif*vec3(0.25,0.25,0.25);
599 }
600 // sss
601 {
602 float dif = pow(clamp(1.0+dot(nor,rd),0.0,1.0),2.0);
603 dif *= occ;
604 lin += col*0.25*dif*vec3(1.00,1.00,1.00);
605 }
606
607 col = lin;
608
609 col = mix( col, vec3(0.7,0.7,0.9), 1.0-exp( -0.0001*t*t*t ) );
610 }
611
612 return vec3( clamp(col,0.0,1.0) );
613}
614
615mat3 setCamera( in vec3 ro, in vec3 ta, float cr )
616{
617 vec3 cw = normalize(ta-ro);
618 vec3 cp = vec3(sin(cr), cos(cr),0.0);
619 vec3 cu = normalize( cross(cw,cp) );
620 vec3 cv = ( cross(cu,cw) );
621 return mat3( cu, cv, cw );
622}
623
624vec4 mainImage( vec2 fragCoord )
625{
626 vec2 mo = iMouse.xy/iResolution.xy;
627 float time = 32.0 + iTime*1.5;
628
629 // camera
630 vec3 ta = vec3( 0.5, -0.5, -0.6 );
631 vec3 ro = ta + vec3( 4.5*cos(0.1*time + 7.0*mo.x), 1.3 + 2.0*mo.y, 4.5*sin(0.1*time + 7.0*mo.x) );
632 // camera-to-world transformation
633 mat3 ca = setCamera( ro, ta, 0.0 );
634
635 vec3 tot = vec3(0.0);
636#if AA>1
637 for( int m=ZERO; m<AA; m++ )
638 for( int n=ZERO; n<AA; n++ )
639 {
640 // pixel coordinates
641 vec2 o = vec2(float(m),float(n)) / float(AA) - 0.5;
642 vec2 p = (2.0*(fragCoord+o)-iResolution.xy)/iResolution.y;
643#else
644 vec2 p = (2.0*fragCoord-iResolution.xy)/iResolution.y;
645#endif
646
647 // focal length
648 const float fl = 2.5;
649
650 // ray direction
651 vec3 rd = ca * normalize( vec3(p,fl) );
652
653 // ray differentials
654 vec2 px = (2.0*(fragCoord+vec2(1.0,0.0))-iResolution.xy)/iResolution.y;
655 vec2 py = (2.0*(fragCoord+vec2(0.0,1.0))-iResolution.xy)/iResolution.y;
656 vec3 rdx = ca * normalize( vec3(px,fl) );
657 vec3 rdy = ca * normalize( vec3(py,fl) );
658
659 // render
660 vec3 col = render( ro, rd, rdx, rdy );
661
662 // gain
663 // col = col*3.0/(2.5+col);
664
665 // gamma
666 col = pow( col, vec3(0.4545) );
667
668 tot += col;
669#if AA>1
670 }
671 tot /= float(AA*AA);
672#endif
673
674 //fragColor = vec4( tot, 1.0 );
675 return vec4( tot, 1.0 );
676}
677
678//*********************************************************
679// END Ray Marching
680//*********************************************************
681
682void main() {
683 vec4 c = color;
684 vec4 txt = texture(sampler2D(tex, smp), uv);
685 c = txt * c;
686 vec2 uv1 = uv * iResolution;
687 vec4 col_ray = mainImage(uv1);
688
689 // use this to mix the chessboart texture with the ray marching
690 //frag_color = clamp(c*iMouse.y/512.0,0.0,1.0) * col_ray ;
691
692 frag_color = c*0.00001 + col_ray ;
693}
694
695#pragma sokol @end
696
697#pragma sokol @program rt_march vs_m fs_m
698