1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
$input v_color0, v_texcoord0
/*
* Copyright 2011-2022 Branimir Karadzic. All rights reserved.
* License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
*/
// References:
// Sphere tracing: a geometric method for the antialiased ray tracing of implicit surfaces - John C. Hart
// http://web.archive.org/web/20110331200546/http://graphics.cs.uiuc.edu/~jch/papers/zeno.pdf
//
// Modeling with distance functions
// http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm
#include "../common/common.sh"
#include "iq_sdf.sh"
uniform mat4 u_mtx;
uniform vec4 u_lightDirTime;
#define u_lightDir u_lightDirTime.xyz
#define u_time u_lightDirTime.w
float sceneDist(vec3 _pos)
{
float d1 = udRoundBox(_pos, vec3(2.5, 2.5, 2.5), 0.5);
float d2 = sdSphere(_pos + vec3( 4.0, 0.0, 0.0), 1.0);
float d3 = sdSphere(_pos + vec3(-4.0, 0.0, 0.0), 1.0);
float d4 = sdSphere(_pos + vec3( 0.0, 4.0, 0.0), 1.0);
float d5 = sdSphere(_pos + vec3( 0.0,-4.0, 0.0), 1.0);
float d6 = sdSphere(_pos + vec3( 0.0, 0.0, 4.0), 1.0);
float d7 = sdSphere(_pos + vec3( 0.0, 0.0,-4.0), 1.0);
float dist = min(min(min(min(min(min(d1, d2), d3), d4), d5), d6), d7);
return dist;
}
vec3 calcNormal(vec3 _pos)
{
const vec2 delta = vec2(0.002, 0.0);
float nx = sceneDist(_pos + delta.xyy) - sceneDist(_pos - delta.xyy);
float ny = sceneDist(_pos + delta.yxy) - sceneDist(_pos - delta.yxy);
float nz = sceneDist(_pos + delta.yyx) - sceneDist(_pos - delta.yyx);
return normalize(vec3(nx, ny, nz) );
}
float calcAmbOcc(vec3 _pos, vec3 _normal)
{
float occ = 0.0;
float aostep = 0.2;
for (int ii = 1; ii < 4; ii++)
{
float fi = float(ii);
float dist = sceneDist(_pos + _normal * fi * aostep);
occ += (fi * aostep - dist) / pow(2.0, fi);
}
return 1.0 - occ;
}
float trace(vec3 _ray, vec3 _dir, float _maxd)
{
float tt = 0.0;
float epsilon = 0.001;
for (int ii = 0; ii < 64; ii++)
{
float dist = sceneDist(_ray + _dir*tt);
if (dist > epsilon)
{
tt += dist;
}
}
return tt < _maxd ? tt : 0.0;
}
vec2 blinn(vec3 _lightDir, vec3 _normal, vec3 _viewDir)
{
float ndotl = dot(_normal, _lightDir);
vec3 reflected = _lightDir - 2.0*ndotl*_normal; // reflect(_lightDir, _normal);
float rdotv = dot(reflected, _viewDir);
return vec2(ndotl, rdotv);
}
float fresnel(float _ndotl, float _bias, float _pow)
{
float facing = (1.0 - _ndotl);
return max(_bias + (1.0 - _bias) * pow(facing, _pow), 0.0);
}
vec4 lit(float _ndotl, float _rdotv, float _m)
{
float diff = max(0.0, _ndotl);
float spec = step(0.0, _ndotl) * max(0.0, _rdotv * _m);
return vec4(1.0, diff, spec, 1.0);
}
void main()
{
vec4 tmp;
tmp = mul(u_mtx, vec4(v_texcoord0.xy, 0.0, 1.0) );
vec3 eye = tmp.xyz/tmp.w;
tmp = mul(u_mtx, vec4(v_texcoord0.xy, 1.0, 1.0) );
vec3 at = tmp.xyz/tmp.w;
float maxd = length(at - eye);
vec3 dir = normalize(at - eye);
float dist = trace(eye, dir, maxd);
if (dist > 0.5)
{
vec3 pos = eye + dir*dist;
vec3 normal = calcNormal(pos);
vec2 bln = blinn(u_lightDir, normal, dir);
vec4 lc = lit(bln.x, bln.y, 1.0);
float fres = fresnel(bln.x, 0.2, 5.0);
float val = 0.9*lc.y + pow(lc.z, 128.0)*fres;
val *= calcAmbOcc(pos, normal);
val = pow(val, 1.0/2.2);
gl_FragColor = vec4(val, val, val, 1.0);
gl_FragDepth = dist/maxd;
}
else
{
gl_FragColor = v_color0;
gl_FragDepth = 1.0;
}
}
|