-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsdf.fs
112 lines (91 loc) · 3.34 KB
/
sdf.fs
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
#version 330
uniform float uTime = 3.14;
uniform vec2 uResolution = vec2(512.0, 512.0);
const int MAX_MARCHING_STEPS = 255;
const float MIN_DIST = 0.0;
const float MAX_DIST = 100.0;
const float EPSILON = 0.0001;
float sphereSDF(vec3 samplePoint) {
return length(samplePoint) - 1.0;
}
float sceneSDF(vec3 samplePoint) {
return sphereSDF(samplePoint);
}
float shortestDistanceToSurface(vec3 eye, vec3 marchingDirection, float start, float end) {
float depth = start;
for (int i = 0; i < MAX_MARCHING_STEPS; i++) {
float dist = sceneSDF(eye + depth * marchingDirection);
if (dist < EPSILON) {
return depth;
}
depth += dist;
if (depth >= end) {
return end;
}
}
return end;
}
vec3 rayDirection(float fieldOfView, vec2 size, vec2 fragCoord) {
vec2 xy = fragCoord - size / 2.0;
float z = size.y / tan(radians(fieldOfView) / 2.0);
return normalize(vec3(xy, -z));
}
vec3 estimateNormal(vec3 p) {
return normalize(vec3(
sceneSDF(vec3(p.x + EPSILON, p.y, p.z)) - sceneSDF(vec3(p.x - EPSILON, p.y, p.z)),
sceneSDF(vec3(p.x, p.y + EPSILON, p.z)) - sceneSDF(vec3(p.x, p.y - EPSILON, p.z)),
sceneSDF(vec3(p.x, p.y, p.z + EPSILON)) - sceneSDF(vec3(p.x, p.y, p.z - EPSILON))
));
}
vec3 phongContribForLight(vec3 k_d, vec3 k_s, float alpha, vec3 p, vec3 eye,
vec3 lightPos, vec3 lightIntensity) {
vec3 N = estimateNormal(p);
vec3 L = normalize(lightPos - p);
vec3 V = normalize(eye - p);
vec3 R = normalize(reflect(-L, N));
float dotLN = dot(L, N);
float dotRV = dot(R, V);
if (dotLN < 0.0) {
return vec3(0.0, 0.0, 0.0);
}
if (dotRV < 0.0) {
return lightIntensity * (k_d * dotLN);
}
return lightIntensity * (k_d * dotLN + k_s * pow(dotRV, alpha));
}
vec3 phongIllumination(vec3 k_a, vec3 k_d, vec3 k_s, float alpha, vec3 p, vec3 eye) {
const vec3 ambientLight = 0.5 * vec3(1.0, 1.0, 1.0);
vec3 color = ambientLight * k_a;
vec3 light1Pos = vec3(4.0 * sin(uTime),
2.0,
4.0 * cos(uTime));
vec3 light1Intensity = vec3(0.4, 0.4, 0.4);
color += phongContribForLight(k_d, k_s, alpha, p, eye,
light1Pos,
light1Intensity);
vec3 light2Pos = vec3(2.0 * sin(0.37 * uTime),
2.0 * cos(0.37 * uTime),
2.0);
vec3 light2Intensity = vec3(0.4, 0.4, 0.4);
color += phongContribForLight(k_d, k_s, alpha, p, eye,
light2Pos,
light2Intensity);
return color;
}
void main()
{
vec3 dir = rayDirection(45.0, uResolution.xy, gl_FragCoord.xy);
vec3 eye = vec3(0.0, 0.0, 5.0);
float dist = shortestDistanceToSurface(eye, dir, MIN_DIST, MAX_DIST);
if (dist > MAX_DIST - EPSILON) {
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
return;
}
vec3 p = eye + dist * dir;
vec3 K_a = vec3(0.329412f, 0.223529f, 0.027451f);
vec3 K_d = vec3(0.780392f, 0.568627f, 0.113725f);
vec3 K_s = vec3(0.992157f, 0.941176f, 0.807843f);
float shininess = 27.8974f;
vec3 color = phongIllumination(K_a, K_d, K_s, shininess, p, eye);
gl_FragColor = vec4(color, 1.0);
}