-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathshader.js
129 lines (113 loc) · 3.43 KB
/
shader.js
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
let maxDistance = 1000.0;
let maxSteps = 256;
let minDistance = 0.01;
let skyColorFunction = 'vec3(0, 0, 1)';
let colorFunction = 'vec3(diffuse)';
let lightFunction = 'vec3(0, -15, 0)';
let lightDirFunction = 'normalize(lightPos - p)';
let shadows = true;
let reflectness = 0.5;
let reflections = 0;
let extra = '';
let spin = false;
let minDistanceFactor = 0.001;
let dynamicMinDistance = true;
let calcNormal = false;
let shadowStrength = 0.6;
const vertexShaderCode = `
precision highp float;
attribute vec2 position;
void main() {
gl_Position = vec4(position, 0, 1);
}
`;
let fragmentShaderCode = `
#define PI 3.1415925359
#define MAX_STEPS #MAX_STEPS
#define MAX_DIST #MAX_DISTANCE
#define MIN_DIST #MIN_DISTANCE
precision highp float;
uniform vec2 uResolution;
uniform float uTime;
uniform vec3 uPosition;
uniform vec3 uRotation;
int steps = 0;
${TRANSFORMATIONS_GLSL}
#DISTANCE_FUNCTION
float sceneDE(vec3 position, bool isLight, int reflectionIndex) {
#SPIN
return distanceFunction(position, isLight, reflectionIndex);
}
float minDistance = MIN_DIST;
float lastDistance = 0.0;
float rayMarch(vec3 rayPos, vec3 rayDir, bool isLight, int reflectionIndex) {
float marchedDistance = 0.0;
for(int i = 0; i < MAX_STEPS; i++) {
steps = i;
vec3 p = rayPos + rayDir * marchedDistance;
float distance = sceneDE(p, isLight, reflectionIndex);
if(#DYNAMIC_MIN_DIST && !isLight)
minDistance = marchedDistance * #MIN_DIST_FACTOR;
marchedDistance += distance;
if(marchedDistance > MAX_DIST || distance < minDistance) {
lastDistance = distance;
break;
}
}
return marchedDistance;
}
vec3 getNormal(vec3 p, int reflectionIndex) {
float distance = sceneDE(p, true, reflectionIndex);
vec2 epsilon = vec2(minDistance, 0);
vec3 n = distance - vec3(
sceneDE(p - epsilon.xyy, true, reflectionIndex),
sceneDE(p - epsilon.yxy, true, reflectionIndex),
sceneDE(p - epsilon.yyx, true, reflectionIndex));
return normalize(n);
}
float getLight(vec3 p, int reflectionIndex) {
vec3 lightPos = #LIGHT_FUNCTION;
vec3 lightDir = #LIGHT_DIR_FUNCTION;
vec3 normal = getNormal(p, reflectionIndex);
float diffuse = dot(normal, lightDir);
diffuse = clamp(diffuse, 0.0, 1.0);
#SHADOWS
return diffuse;
}
#EXTRA
void main() {
vec2 uv = (gl_FragCoord.xy - 0.5 * uResolution.xy) / uResolution.y;
vec3 cameraPos = uPosition;
vec3 rayDir = normalize(vec3(uv.x, uv.y, 1.0));
rayDir = rayDir * mat3(rotateXYZ(uRotation));
vec3 fragColor;
bool isFirstSky = false;
for(int reflection = 0; reflection < #REFLECTIONS + 1; reflection++) {
vec3 normal;
if(reflection > 0 || #CALC_NORMAL) {
normal = getNormal(cameraPos, reflection);
if(reflection > 0) rayDir = reflect(rayDir, normal);
}
float distance = rayMarch(reflection > 0 ? cameraPos + normal * (1.5 * minDistance) : cameraPos, rayDir, false, reflection);
cameraPos += rayDir * distance;
float diffuse = getLight(cameraPos, reflection);
vec3 p = cameraPos;
int reflectionIndex = reflection;
vec3 lightPos = #LIGHT_FUNCTION;
vec3 lightDir = #LIGHT_DIR_FUNCTION;
vec3 color = #COLOR_FUNCTION;
if(distance > MAX_DIST) {
color = #SKY_COLOR_FUNCTION;
if(reflection == 0) isFirstSky = true;
}
else if(steps == MAX_STEPS) {
color = #SKY_COLOR_FUNCTION;
if(reflection == 0) isFirstSky = true;
}
if(reflection > 0 && !isFirstSky) fragColor = mix(fragColor, color, #REFLECTNESS);
else if(reflection > 0);
else fragColor = color;
}
gl_FragColor = vec4(fragColor, 1.0);
}
`;