Skip to content

Commit 398ba72

Browse files
committed
Make raymarching example slightly more interesting
1 parent feba09b commit 398ba72

1 file changed

Lines changed: 88 additions & 23 deletions

File tree

example/raymarch.frag

Lines changed: 88 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ const float MAX_DISTANCE = 10000.0;
1010

1111
out vec4 color;
1212

13-
// TODO: a struct of dist + material id?
1413
struct Hit {
1514
float dist;
1615
int material_id;
@@ -40,37 +39,92 @@ float smin( float a, float b, float k ) {
4039
return -k*log2(r);
4140
}
4241

43-
// box, again thanks to iquilezlez
42+
// standard GLSL noise function of internet legend. Adapted to 3 dims
43+
float noise(vec3 co){
44+
return fract(sin(dot(co, vec3(12.9898, 78.233, 69.78))) * 43758.5453);
45+
}
46+
47+
// iqquillez fbm subtraction logic
48+
// renamed for clarity. Found no better way of doing it, so copy paste it is :P
49+
float random_radius_sphere( ivec3 i, vec3 f, ivec3 c ) {
50+
float rad = 0.5*noise((i + c));
51+
return length(f-vec3(c)) - rad;
52+
}
53+
54+
float eight_random_spheres(vec3 p) {
55+
ivec3 i = ivec3(floor(p));
56+
vec3 f = fract(p);
57+
return min(min(min(random_radius_sphere(i,f,ivec3(0,0,0)),
58+
random_radius_sphere(i,f,ivec3(0,0,1))),
59+
min(random_radius_sphere(i,f,ivec3(0,1,0)),
60+
random_radius_sphere(i,f,ivec3(0,1,1)))),
61+
min(min(random_radius_sphere(i,f,ivec3(1,0,0)),
62+
random_radius_sphere(i,f,ivec3(1,0,1))),
63+
min(random_radius_sphere(i,f,ivec3(1,1,0)),
64+
random_radius_sphere(i,f,ivec3(1,1,1)))));
65+
}
66+
67+
// </iqquillez fbm subtraction logic>
68+
69+
// box, again thanks to iqquillez
4470
float round_box(vec3 p, vec3 b, float r) {
4571
vec3 q = abs(p) - b + r;
4672
return length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0) - r;
4773
}
4874

49-
50-
// TODO: maybe have a function for our blob structure here? then the scene can just call that function and have botht he distance to it + material?
51-
// then we can have some blocks or other stone material using some noise to create them
52-
53-
float scene(vec3 pos) {
54-
int num_spheres = 10;
75+
Hit blob_structure(vec3 pos) {
76+
int num_spheres = 8;
5577
float dist = sphere(pos, vec3(0.0), 1.0);
5678
for(int i = 1; i < num_spheres; i++) {
5779
dist = smin(dist, sphere(pos, vec3(cos(elapsed_time / i), -tan(elapsed_time/i), sin(elapsed_time)), 0.7), 0.2);
5880
}
59-
return smin(dist, plane(pos, vec3(0.0, 1.0, 0.0), 4.0), 0.2);
81+
return Hit(smin(dist, round_box(pos + vec3(0.0, 4.0, 0.0), vec3(3.0, 1.0, 3.0), 0.5), 0.2), 0);
82+
}
83+
84+
float eroded_block(vec3 pos, vec3 dims) {
85+
float dist = round_box(pos, dims, 0.2);
86+
// fbm from iq
87+
float s = 1.0;
88+
for( int i=0; i<4; i++ ) {
89+
float n = s*eight_random_spheres(pos);
90+
dist = max( dist, -n);
91+
pos = mat3(0.00, 1.60, 1.20,
92+
-1.60, 0.72,-0.96,
93+
-1.20,-0.96, 1.28)*pos;
94+
s = 0.5*s;
95+
}
96+
97+
return dist;
98+
}
99+
100+
// a weird basin containing the pink blobby goo
101+
Hit basin(vec3 pos) {
102+
float dist = eroded_block(pos + vec3(4.0, 5.0, 0.0), vec3(2.0, 4.0, 4.0));
103+
dist = min(dist, eroded_block(pos + vec3(-4.0, 5.0, 0.0), vec3(2.0, 4.0, 4.0)));
104+
105+
float hole_box = eroded_block(pos + vec3(0.0, 4.0, 4.0), vec3(3.0, 10.0, 0.5));
106+
float smaller_box = round_box(pos + vec3(0.0, -4.0, 4.0), vec3(2.0, 1.0, 0.8), 0.2);
107+
dist = min(dist, max(hole_box, -smaller_box));
108+
109+
return Hit(dist, 1);
110+
}
111+
112+
Hit scene(vec3 pos) {
113+
return hit_min(hit_min(blob_structure(pos + vec3(0.0, 0.0, 2.0)), basin(pos + vec3(0.0, 0.0, 2.0))),
114+
Hit(plane(pos, vec3(0.0, 1.0, 0.0), 4.0), 2));
60115
}
61116

62117
vec3 normal(vec3 pos) {
63-
return normalize(vec3(scene(pos + vec3(0.01, 0.0, 0.0)) - scene(pos - vec3(0.01, 0.0, 0.0)),
64-
scene(pos + vec3(0.0, 0.01, 0.0)) - scene(pos - vec3(0.0, 0.01, 0.0)),
65-
scene(pos + vec3(0.0, 0.0, 0.01)) - scene(pos - vec3(0.0, 0.0, 0.01))));
118+
return normalize(vec3(scene(pos + vec3(0.01, 0.0, 0.0)).dist - scene(pos - vec3(0.01, 0.0, 0.0)).dist,
119+
scene(pos + vec3(0.0, 0.01, 0.0)).dist - scene(pos - vec3(0.0, 0.01, 0.0)).dist,
120+
scene(pos + vec3(0.0, 0.0, 0.01)).dist - scene(pos - vec3(0.0, 0.0, 0.01)).dist));
66121
}
67122

68-
// TODO: refactor to a general raymarching
69123
// probably unintuitive method as well. TOok it out of my ass
70124
float shadow_march(vec3 pos, vec3 ray_dir) {
71125
float t = 0.5;
72126
while(t < 200.0) {
73-
float dist = scene(pos + t*ray_dir);
127+
float dist = scene(pos + t*ray_dir).dist;
74128
if(dist < 0.001) {
75129
// could be 0, but like the way occluding factor 0.1 looks like
76130
return 0.1;
@@ -83,7 +137,7 @@ float shadow_march(vec3 pos, vec3 ray_dir) {
83137
}
84138

85139
void main() {
86-
// upside down?
140+
// upside down, but saves a calc
87141
vec2 uv = gl_FragCoord.xy / vec2(screen_width, screen_height);
88142
vec3 ray_dir = vec3(uv * 2.0 - 1.0, -1.0);
89143
vec3 cam_pos = vec3(0.0, 0.0, 5.0);
@@ -94,25 +148,36 @@ void main() {
94148
int i = 0;
95149
while (i < MAX_ITERATIONS && t < MAX_DISTANCE) {
96150
vec3 pos = cam_pos + t*ray_dir;
97-
float dist = scene(pos);
98-
// TODO: more advanced color
99-
if (dist < 0.001) {
151+
Hit hit = scene(pos);
152+
if (hit.dist < 0.001) {
100153
vec3 light_dir = normalize(light_pos - pos);
101154
vec3 normal = normal(pos);
102155
float diffuse_intensity = max(0.0, dot(light_dir, normal));
103156
vec3 half_vec = normalize(light_dir + -ray_dir);
104157
float specular = max(0.0, pow(dot(half_vec, normal), 256));
105158
float shadow = shadow_march(pos, light_dir);
106159

107-
// TODO: what is the best way to have different colors for each material?
108-
160+
// stupid material handling
161+
vec3 ambient_color = vec3(1.0, 0.8, 0.9);
162+
vec3 diffuse_color = vec3(1.0, 0.8, 0.9);
163+
if (hit.material_id == 1) {
164+
ambient_color = vec3(0.1, 0.1, 0.1);
165+
diffuse_color = vec3(0.4, 0.4, 0.4);
166+
specular = 0.0;
167+
} else if (hit.material_id == 2) {
168+
ambient_color = vec3(0.7, 0.9, 0.7);
169+
// TODO: more interesting material
170+
diffuse_color = noise(pos) * vec3(0.9, 0.9, 0.9);
171+
specular = 0.0;
172+
}
109173

110-
color = vec4(0.3*vec3(1.0, 0.8, 0.9) + shadow*vec3(1.0, 0.8, 0.9) * diffuse_intensity + shadow*vec3(1.0)*specular, 1.0);
174+
color = vec4(0.3*ambient_color + shadow*diffuse_color * diffuse_intensity + shadow*vec3(1.0)*specular, 1.0);
111175
return;
112176
}
113177

114-
t += dist;
178+
t += hit.dist;
115179
}
116180

117-
color = vec4(0.0);
181+
// TODO: more interesting color
182+
color = mix(vec4(0.9, 0.9, 0.9, 1.0), vec4(0.4, 0.6, 0.8, 1.0), 0.8 - uv.y / 2.0);
118183
}

0 commit comments

Comments
 (0)