@@ -10,7 +10,6 @@ const float MAX_DISTANCE = 10000.0;
1010
1111out vec4 color;
1212
13- // TODO: a struct of dist + material id?
1413struct 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
4470float 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
62117vec3 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
70124float 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
85139void 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