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