3 uniform mat3 dirmatrix;
5 #define DIST_THRES 1e-3
9 vec3 raymarch(inout vec3 p, in vec3 dir, out float depth);
10 vec3 shade(in vec3 p, in vec3 dir, in float dist, in float total_dist);
11 vec3 backdrop(in vec3 dir);
12 float eval_sdf(in vec3 p);
13 vec3 eval_grad(in vec3 p, float dist);
14 vec3 primray(in vec2 uv, out vec3 org);
16 float boxdist(in vec3 p, in vec3 b);
17 float sphdist(in vec3 p, in vec3 sp, in float srad);
19 float fbm(vec3 v, int noct);
22 float eval_sdf_gen(in vec3 p);
27 vec2 uv = gl_TexCoord[0].st;
29 vec3 rdir = primray(uv, rorg);
32 gl_FragColor.rgb = raymarch(rorg, rdir, depth);
35 vec4 projp = gl_ProjectionMatrix * vec4(0.0, 0.0, -depth, 1.0);
36 float zval = projp.z / projp.w;
41 vec3 raymarch(inout vec3 p, in vec3 dir, out float depth)
43 float d, total_d = 0.0;
45 for(int i=0; i<MAX_ITER; i++) {
46 if((d = eval_sdf(p)) <= DIST_THRES) {
48 return shade(p, dir, d, total_d);
57 depth = -gl_DepthRange.far;
61 vec3 shade(in vec3 p, in vec3 dir, in float dist, in float total_dist)
63 const vec3 kd = vec3(1.0, 0.3, 0.1);
64 const vec3 ks = vec3(0.7, 0.7, 0.7);
65 const vec3 ldir = normalize(vec3(-1.0, 1.0, -1.5));
66 const vec3 vdir = vec3(0.0, 0.0, -1.0);
68 vec3 diffuse = vec3(0.0, 0.0, 0.0);
69 vec3 specular = vec3(0.0, 0.0, 0.0);
71 vec3 n = eval_grad(p, dist);
73 vec3 hdir = normalize(ldir + vdir);
75 float ndotl = max(dot(n, ldir), 0.0);
76 float ndoth = max(dot(n, hdir), 0.0);
78 diffuse += kd * ndotl;
79 specular += ks * pow(ndoth, 50.0);
81 float fog = clamp(300.0 / (total_dist * total_dist), 0.0, 1.0);
83 return mix(backdrop(dir), diffuse + specular, fog);
86 vec3 backdrop(in vec3 dir)
88 return vec3(0.1, 0.1, 0.1);
91 float eval_sdf(in vec3 p)
93 return eval_sdf_gen(p) + fbm(p, 4) * 0.05;
97 vec3 eval_grad(in vec3 p, float dist)
99 float dfdx = eval_sdf(p + vec3(DELTA, 0.0, 0.0)) - dist;
100 float dfdy = eval_sdf(p + vec3(0.0, DELTA, 0.0)) - dist;
101 float dfdz = eval_sdf(p + vec3(0.0, 0.0, DELTA)) - dist;
102 return normalize(vec3(dfdx, dfdy, dfdz));
105 vec3 primray(in vec2 uv, out vec3 org)
107 vec3 origin = (gl_ModelViewMatrixInverse * vec4(0.0, 0.0, 0.0, 1.0)).xyz;
110 vec2 nuv = uv * 2.0 - 1.0;
111 vec4 cp_near = vec4(nuv, -1.0, 1.0);
113 vec4 vdir = gl_ProjectionMatrixInverse * cp_near;
114 vec4 wdir = gl_ModelViewMatrixInverse * vec4(vdir.xyz, 0.0);
116 return normalize(wdir.xyz);
119 float boxdist(in vec3 p, in vec3 b)
122 return length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0);
125 float sphdist(in vec3 p, in vec3 sp, in float srad)
127 return length(p - sp) - srad;
131 float eval_sdf_gen(in vec3 p)
133 return boxdist(p - vec3(14.000000, 0.0, 14.000000), vec3(0.550000, 1.0, 4.550000));
137 float fbm(vec3 v, int noct)
141 for(int i=0; i<noct; i++) {
142 val += snoise(v * f) / f;
148 // Description : Array and textureless GLSL 2D/3D/4D simplex
150 // Author : Ian McEwan, Ashima Arts.
151 // Maintainer : stegu
152 // Lastmod : 20201014 (stegu)
153 // License : Copyright (C) 2011 Ashima Arts. All rights reserved.
154 // Distributed under the MIT License. See LICENSE file.
155 // https://github.com/ashima/webgl-noise
156 // https://github.com/stegu/webgl-noise
159 vec3 mod289(vec3 x) {
160 return x - floor(x * (1.0 / 289.0)) * 289.0;
163 vec4 mod289(vec4 x) {
164 return x - floor(x * (1.0 / 289.0)) * 289.0;
167 vec4 permute(vec4 x) {
168 return mod289(((x*34.0)+10.0)*x);
171 vec4 taylorInvSqrt(vec4 r)
173 return 1.79284291400159 - 0.85373472095314 * r;
178 const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;
179 const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);
182 vec3 i = floor(v + dot(v, C.yyy) );
183 vec3 x0 = v - i + dot(i, C.xxx) ;
186 vec3 g = step(x0.yzx, x0.xyz);
188 vec3 i1 = min( g.xyz, l.zxy );
189 vec3 i2 = max( g.xyz, l.zxy );
191 // x0 = x0 - 0.0 + 0.0 * C.xxx;
192 // x1 = x0 - i1 + 1.0 * C.xxx;
193 // x2 = x0 - i2 + 2.0 * C.xxx;
194 // x3 = x0 - 1.0 + 3.0 * C.xxx;
195 vec3 x1 = x0 - i1 + C.xxx;
196 vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y
197 vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y
201 vec4 p = permute( permute( permute(
202 i.z + vec4(0.0, i1.z, i2.z, 1.0 ))
203 + i.y + vec4(0.0, i1.y, i2.y, 1.0 ))
204 + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));
206 // Gradients: 7x7 points over a square, mapped onto an octahedron.
207 // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
208 float n_ = 0.142857142857; // 1.0/7.0
209 vec3 ns = n_ * D.wyz - D.xzx;
211 vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)
213 vec4 x_ = floor(j * ns.z);
214 vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)
216 vec4 x = x_ *ns.x + ns.yyyy;
217 vec4 y = y_ *ns.x + ns.yyyy;
218 vec4 h = 1.0 - abs(x) - abs(y);
220 vec4 b0 = vec4( x.xy, y.xy );
221 vec4 b1 = vec4( x.zw, y.zw );
223 //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
224 //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
225 vec4 s0 = floor(b0)*2.0 + 1.0;
226 vec4 s1 = floor(b1)*2.0 + 1.0;
227 vec4 sh = -step(h, vec4(0.0));
229 vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;
230 vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;
232 vec3 p0 = vec3(a0.xy,h.x);
233 vec3 p1 = vec3(a0.zw,h.y);
234 vec3 p2 = vec3(a1.xy,h.z);
235 vec3 p3 = vec3(a1.zw,h.w);
237 //Normalise gradients
238 vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
244 // Mix final noise value
245 vec4 m = max(0.5 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
247 return 105.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1),
248 dot(p2,x2), dot(p3,x3) ) );