I updated the code samples of the Raymarching article that were a little bit incompatible with recent versions of GLSL Hacker, especially the latest v0.6.3.11 DEV version. Now all raymarching code samples are fully operational.
I took the opportunity to add a new raymarching code sample based on iq’s article about Menger sponge.
The GLSL Hacker demo (menger_sponge.xml) is available in the host_api/GLSL_raymarching/ folder of the code sample pack (DEV version). The use of the latest DEV version of GLSL Hacker to play with demos is highly recommended!
Menger sponge demo under OS X 10.9 with a GeForce GT 650M
Menger sponge demo under Windows with A Radeon R7 (A10-7850K APU)
I don’t know what GLSL instructions are problematic with NVIDIA hardware under Windows, but the tuning of the Menger sponge with a GeForce GTX 660 was just awful. I had tons of NVIDIA OpenGL driver lost connection message boxes with countless reboots (drivers: R334.67)!
So I switched to my recent AMD A10-7850K based setup to finish and test the menger sponge demo. With the Radeon R7, there was absolutely no issue!
Here is the complete GLSL fragment shader that does the job:
#version 120 uniform vec3 cam_pos; uniform float time; uniform vec2 resolution; uniform vec2 mouse; float PI=3.14159265; vec2 obj_union(in vec2 obj0, in vec2 obj1) { if (obj0.x < obj1.x) return obj0; else return obj1; } //Floor vec2 obj_floor(in vec3 p) { return vec2(p.y+10.0,0); } //Floor Color (checkerboard) vec3 floor_color(in vec3 p) { if (fract(p.x*0.2)>0.2) { if (fract(p.z*0.2)>0.2) return vec3(0,0.1,0.2); else return vec3(1,1,1); } else { if (fract(p.z*.2)>.2) return vec3(1,1,1); else return vec3(0.3,0,0); } } // Primitive color vec3 prim_c(in vec3 p) { return vec3(0.6,0.6,0.8); } /////////////////////////////// // Menger sponge routines /////////////////////////////// float maxcomp(vec3 p) { float m1 = max(p.x, p.y); return max(m1, p.z); } vec2 obj_box_s(vec3 p, vec3 b) { vec3 di = abs(p) - b; float mc = maxcomp(di); float d = min(mc,length(max(di,0.0))); return vec2(d,1); } vec2 obj_box(vec3 p) { vec3 b=vec3(4.0, 4.0, 4.0); return obj_box_s(p, b); } vec2 obj_cross(in vec3 p) { float inf = 100; vec2 da = obj_box_s(p.xyz,vec3(inf,2.0,2.0)); vec2 db = obj_box_s(p.yzx,vec3(2.0,inf,2.0)); vec2 dc = obj_box_s(p.zxy,vec3(2.0,2.0,inf)); return vec2(min(da.x,min(db.x,dc.x)), 1); } vec2 obj_menger_simple(in vec3 p) { vec2 d1 = obj_box(p); vec2 d2 = obj_cross(p/3.0); float d = max(d1.x, -d2.x); return vec2(d,1.0); } vec2 obj_menger(in vec3 p) { vec2 d2 = obj_box(p); float s = 1.0; for (int m=0; m<3; m++) { vec3 a = mod(p*s, 2.0)-1.0; s *= 3.0; vec3 r = 1.0 - 4.0*abs(a); vec2 c = obj_cross(r)/s; d2.x = max(d2.x,c.x); } return d2; } //Objects union vec2 distance_to_obj(in vec3 p) { return obj_union(obj_floor(p), obj_menger(p)); } //Scene End void main(void) { vec2 q = gl_TexCoord[0].xy; vec2 vPos = -1.0 + 2.0 * q; //Camera animation vec3 vuv=vec3(0,1,0);//Change camere up vector here vec3 vrp=vec3(0,0,0); //Change camere view here float mx=mouse.x*PI*2.0; float my=mouse.y*PI/2.01; //vec3 prp=vec3(cos(my)*cos(mx),sin(my),cos(my)*sin(mx))*6.0; //Trackball style camera pos vec3 prp = cam_pos; //Camera setup vec3 vpn=normalize(vrp-prp); vec3 u=normalize(cross(vuv,vpn)); vec3 v=cross(vpn,u); vec3 vcv=(prp+vpn); float aspect = (resolution.x/resolution.y); vec3 scrCoord=vcv+vPos.x*u*aspect+vPos.y*v; //vec3 scrCoord=vcv+vPos.x*u*0.8+vPos.y*v*0.8; vec3 scp=normalize(scrCoord-prp); //Raymarching const vec3 e=vec3(0.02,0,0); const float maxd=100.0; //Max depth vec2 d=vec2(0.02, 0.0); vec3 d2=vec3(0.02, 0.0, 0.0); vec3 c,p,n; float f=1.0; for(int i=0;i<256;i++) { if ((abs(d.x) < .001) || (f > maxd)) break; f+=d.x; p=prp+scp*f; d = distance_to_obj(p); } if (f < maxd) { if (d.y==0) // y is used to manage materials. c=floor_color(p); else c=prim_c(p); n=normalize( vec3(d.x-distance_to_obj(p-e.xyy).x, d.x-distance_to_obj(p-e.yxy).x, d.x-distance_to_obj(p-e.yyx).x)); float b=dot(n,normalize(prp-p)); gl_FragColor=vec4((b*c+pow(b,60.0))*(1.0-f*.01),1.0); } else { gl_FragColor=vec4(0,0,0,1); //background color } }
I also added in the code sample pack two variations or the Menger sponge fractal: the Menger Journey and the Menger Tower:
Menger Journey
Menger Tower
Interesting demos.
Menger sponge demo works good on my GeGorce 660 and 331.93 driver.