pouët.net

Raymarching Beginners' Thread

category: code [glöplog]
thats it? come on, most 4k's are widows-only anyway...
added on the 2011-05-13 22:11:45 by unc unc
I don't even have a windows box anymore (other than vmware but fuck writing a raymarcher on that ;)
added on the 2011-05-13 22:15:20 by psonice psonice
@xernobyl: If I wanted to do so I would just take a photo. The algorithm may seem inficient but the computer is very powerful.

@ RareWtFailWhale: The gradient is a vector. What I called modulus is in fact the norm. Sorry!
In your second example (the one that doesn't work properly) you should have
Code:dr=sqrt(4.0*p.x*p.x + 4.0*p.y*py + (p.z*p.z + 2.0*(p.z - 1.0)*p.z)*(p.z*p.z + 2.0*(p.z - 1.0)*p.z));

It would be better (for readability) to do:
Code:vec3 gradient=vec3(2.0*p.x, 2.0*p.y, p.z*(3.0*p.z - 2.0)); dr=length(gradient);


Here is a fragmentarium script with some functions:
Code:#version 110 //to make sure it will work on glsl 1.10 compliant drivers #info algebraic surfaces (and others) Distance Estimator (knighty 2011) #include "DE-Raytracer.frag" #include "MathUtils.frag" #group DE parametres //DE correction param: scaling factor uniform float param1; slider[0,.75,1] //DE correction param: Lipschitzator (lol) factor uniform float param2; slider[0,4,10] //Level set uniform float LevelSet; slider[-1,0,1] //Size uniform float Sz; slider[-5,1,5] uniform float time; #define Phi (.5*(1.+sqrt(5.))) #define W 1.6 #define W2 2.56 #define PHI 1.618034 #define PHI2 2.618034 #define PHI4 6.854102 #define Tau (1.+2.*Phi) #define PI 3.141593 #define Eps 0.00048828125 //epsilon #define IEps 2048.0 //Inverse of epsilon void init() { } float sinesphere(in vec3 P){ P=sin(P*PI*Sz); return (dot(P,P)-LevelSet); } float sine(in vec3 P){ P.xyz=P.xzy; return (P.z-0.25*sin(length(P.xy)*5.*Sz-2.0*time)/(dot(P.xy,P.xy)+1.0)); } float absolutely(in vec3 P){ return P.z-abs(P.x*P.y); } float CrossCap(in vec3 P){//cubic P.xyz=5.*P.xzy; vec3 P2=P*P; return (-P2.x*P.y + P2.z-LevelSet); } float Chmutov8(in vec3 P){//octic vec3 P2=P*P; vec3 R=1.0+P2*32.0*Sz*(-1.0+P2*(5.0+P2*(-8.0+P2*4.0))); return R.x+R.y+R.z; } float Barth6(vec3 z)//Bart's sextic { vec3 z2=z*z; vec3 z3=0.2*Sz*PHI2*z2-z2.yzx; float p1=4.*z3.x*z3.y*z3.z; float r2=dot(z,z)-1.; float p2=Tau*(r2*r2); return p2-p1; } float Barth6Cusp(vec3 z)//Another Bart's sextic { vec3 z2=z*z; vec3 z3=0.2*Sz*PHI2*z2-z2.yzx; float p1=4.*z3.x*z3.y*z3.z; float r2=dot(z,z)-1.; float p2=Tau*(r2*r2*r2); return p2-p1; } float BarthDecic(in vec3 P){//decic float r2=dot(P,P); vec3 P2=P*P; float r4=dot(P2,P2); vec3 P4=P2*P2; return (8.0*Sz*(P2.x-PHI4*P2.y)*(P2.y-PHI4*P2.z)*(P2.z-PHI4*P2.x)*(r4-2.0*((P.x*P.y)*(P.x*P.y)+(P.x*P.z)*(P.x*P.z)+(P.y*P.z)*(P.y*P.z)))+(3.0+5.0*PHI)*(r2-W2)*(r2-W2)*(r2-(2.0-PHI)*W2)*(r2-(2.0-PHI)*W2)*W2); } float CrossCap4(vec3 P){//Quartic vec3 P2=P*P; return 4.*P2.x*dot(P,P)+P2.y*(P2.y+P2.z-1.); } float Mitchell(vec3 P){//sextic vec3 P2=P*P; float r2=dot(P,P); float r2yz=dot(P.yz,P.yz); return 4.*Sz*(P2.x*P2.x+r2yz*r2yz)+17.*P2.x*r2yz-20.*r2+17.; } float Dervish(vec3 P){//Quintic P.z=-P.z; float c=sqrt(5.-sqrt(5.))/2.; float r=(1.+3.*sqrt(5.))/4.; float q=(P.x*P.x+P.y*P.y-1.+r*P.z*P.z);q=(1.-c*P.z)*q*q; float a=-(8./5.)*(1.+1./sqrt(5.))*sqrt(5.-sqrt(5.)); float h1=P.x-P.z; float h2=cos(2.*PI/5.)*P.x-sin(2.*PI/5.)*P.y-P.z; float h3=cos(4.*PI/5.)*P.x-sin(4.*PI/5.)*P.y-P.z; float h4=cos(6.*PI/5.)*P.x-sin(6.*PI/5.)*P.y-P.z; float h5=cos(8.*PI/5.)*P.x-sin(8.*PI/5.)*P.y-P.z; float FF=h1*h2*h3*h4*h5; return a*FF+Sz*q; } float CayleyCubic(vec3 P){//cubic return 4.*Sz*dot(P,P) + 16.*P.x*P.y*P.z - 1.; } float FlipFlap(vec3 P){//cubic return Sz*dot(P.xy,P.xy)+P.x*P.y*P.z; } float heart(vec3 z)//Thanks Alex-B { vec3 z2=z*z; float lp = z2.x + Sz*z2.y + z2.z - 1.0; float rp = z2.x*z2.z*z.z + 0.08888*z2.y*z2.z*z.z; return lp*lp*lp-rp; } #define Fn Barth6Cusp//heart//sine//sinesphere//Chmutov8//BarthDecic//Dervish//CayleyCubic//FlipFlap//Barth6//Barth6//BarthDecic//Mitchell//CrossCap4//absolutely// float DE(vec3 z) { float v =Fn(z); float dv=length(IEps*(vec3(Fn(z+vec3(Eps,0.,0.)),Fn(z+vec3(0.,Eps,0.)),Fn(z+vec3(0.,0.,Eps)))-vec3(v))); v-= LevelSet; float k = 1.-1./(abs(v)+1.); return param1*abs(v)/(dv+param2*k+0.01);//adding 0.01 in case the gradient is zero on the isosurface }

The method is not perfect but seem to give some good results.
added on the 2011-05-13 22:19:46 by knighty knighty
Quote:
why you ppl are into glsl so much? if you only knew the power of the hlsl side...

oh believe me, i know :))
added on the 2011-05-14 09:37:03 by ton ton
otoh, it's true that there's still no "glsl-only" platform powerful enough for heavy raymarching
added on the 2011-05-14 09:39:56 by ton ton
HEEEEEELP - I'm going crazy over here!!!
So I've made my first attempts at porting my raymarcher to a GPU shader.
I tried downloading VVVV or whatever it was called, but I never got it to work.
Instead I settled on using Mr.Doobs WebGL base, adapting/changing a bit, and soon I had my first GLSL code up and running.
I then started porting my Processing code. I soon noticed that I had to cut down on the number of iterations I ran, otherwise the browser would hang when loading the page (I'm guessing it does some kind of shader-compile in this step).
Anyway, got it running so far that my geometry rendered correctly, that is, I got cubes where I wanted and spheres where I wanted, so the basic marcher is working. However, the shading is totally fucked, my guess is that the normal calculation borks out somehow, but since there is no way of actually debugging the GLSL code, I'm totally stuck.
Look at this:
BB Image

The sides of the cubes where X>0.0 looks somewhat correct, but spheres and X<0.0 of boxes is just way off...?
Any ideas what I'm doing wrong.

Here's the code:

Code: uniform vec2 resolution; uniform float time; float MAXD=1000.0; float perspective=1.25,zoom=2.0; vec3 cameraLocation=vec3(0.0, 0.0, -0.6); vec3 light=vec3(-0.1,-0.1, -1.0); vec3 sphere1=vec3(0.0,0.0,0); vec3 sphere2=vec3(0.25,-0.25,-0.1); vec3 sphere3=vec3(-0.25,-0.25,-0.1); vec3 cube1=vec3(0,0.75,0); vec3 cube2=vec3(-0.25,0.85,-0.25); vec3 cube3=vec3(0.25,0.65,0.25); float dist_sphere(vec3 pos, vec3 v,float r) { return distance(pos,v)-r; } float dist_cube(vec3 pos, vec3 v,float s) { float dx=abs(v.x-pos.x)-s; float dy=abs(v.y-pos.y)-s; float dz=abs(v.z-pos.z)-s; vec3 tmpV=vec3(max(dx,0.0),max(dy,0.0),max(dz,0.0)); return length(tmpV); } float dist(vec3 v) { float d,mind=MAXD; d=dist_sphere(sphere1,v,0.25); if(d<mind) mind=d; d=dist_sphere(sphere2,v,0.15); if(d<mind) mind=d; d=dist_sphere(sphere3,v,0.15); if(d<mind) mind=d; d=dist_cube(cube1,v,0.3); if(d<mind) mind=d; d=dist_cube(cube2,v,0.3); if(d<mind) mind=d; d=dist_cube(cube3,v,0.3); if(d<mind) mind=d; return mind; } vec3 calc_normal(vec3 v) { float e=0.0001; vec3 n=vec3( dist(vec3(v.x+e,v.y,v.z))-dist(vec3(v.x-e,v.y,v.z)), dist(vec3(v.x,v.y+e,v.z))-dist(vec3(v.x,v.y-e,v.z)), dist(vec3(v.x,v.y,v.z+e))-dist(vec3(v.x,v.y,v.z-e))); n/=(2.0*e); return n; } float ao(vec3 p, vec3 n, float d) { float o=1.0,ii=5.0; for(int i=0;i<5;i++) { vec3 tmpV=p+n*(ii*d); float tmp=dist(tmpV); if(tmp<0.0) tmp=0.0; o-=(ii*d-tmp)/pow(2.0,ii); ii=ii-1.0; } return o; } void main(void) { float x,y,off=0.0; vec4 col; float rx,ry,d; int steps=0; vec3 ray,direction; vec2 p = 2.0*gl_FragCoord.xy; p.x/= resolution.x; p.y/= resolution.x; p-=1.0; p.y=-p.y; p=p/zoom; ray=vec3(p.x,p.y,0); ray=ray+cameraLocation; direction=vec3(p.x*perspective,p.y*perspective,1.0); direction=normalize(direction); col=vec4(0.25+(p.y+0.5)/3.0,0.25+(p.y+0.5)/3.0,0.33+(p.y+0.5)/3.0,1.0); for(int i=0;i<50;i++) { d=dist(ray); if(d>=MAXD) { // Infinite distance break; } if(d<0.0001) { vec3 n=calc_normal(ray); float normlight=0.25*dot(light,n); float aolight=ao(ray,n,0.15); if(normlight<0.0) normlight=0.0; float ambient=0.75; float c=(normlight+ambient)*aolight; col=vec4(c,c,c,1.0); break; } ray+=direction*d*0.75; } gl_FragColor = col; }
added on the 2011-05-15 23:30:11 by Sdw Sdw
For some reason "n/=(2.0*e);" is not a good idea, use normalize.
Code: float MAXD=1000.0; float perspective=1.25,zoom=2.0; vec3 cameraLocation=vec3(0.0, 0.0, -0.6); vec3 light=vec3(-0.1,-0.1, -1.0); vec3 sphere1=vec3(0.0,0.0,0); vec3 sphere2=vec3(0.25,-0.25,-0.1); vec3 sphere3=vec3(-0.25,-0.25,-0.1); vec3 cube1=vec3(0,0.75,0); vec3 cube2=vec3(-0.25,0.85,-0.25); vec3 cube3=vec3(0.25,0.65,0.25); float dist_sphere(vec3 pos, vec3 v,float r) { return distance(pos,v)-r; } float dist_cube(vec3 pos, vec3 v,float s) { float dx=abs(v.x-pos.x)-s; float dy=abs(v.y-pos.y)-s; float dz=abs(v.z-pos.z)-s; vec3 tmpV=vec3(max(dx,0.0),max(dy,0.0),max(dz,0.0)); return length(tmpV); } float dist(vec3 v) { float d = dist_sphere(sphere1,v,0.25); d=min(d, dist_sphere(sphere2,v,0.15)); d=min(d, dist_sphere(sphere3,v,0.15)); d=min(d, dist_cube(cube1,v,0.3)); d=min(d, dist_cube(cube2,v,0.3)); d=min(d, dist_cube(cube3,v,0.3)); return d; } vec3 calc_normal(vec3 v) { float e=0.0001; vec3 n=vec3( dist(vec3(v.x+e,v.y,v.z))-dist(vec3(v.x-e,v.y,v.z)), dist(vec3(v.x,v.y+e,v.z))-dist(vec3(v.x,v.y-e,v.z)), dist(vec3(v.x,v.y,v.z+e))-dist(vec3(v.x,v.y,v.z-e))); return normalize(n); } float ao(vec3 p, vec3 n, float d) { float o=1.0,ii=5.0; for(int i=0;i<5;i++) { vec3 tmpV=p+n*(ii*d); float tmp=dist(tmpV); if(tmp<0.0) tmp=0.0; o-=(ii*d-tmp)/pow(2.0,ii); ii=ii-1.0; } return o; } void main(void) { float x,y,off=0.0; vec4 col; float rx,ry,d; int steps=0; vec3 ray,direction; vec2 p = 2.0*gl_FragCoord.xy; p.x/= resolution.x; p.y/= resolution.x; p-=1.0; p.y=-p.y; p=p/zoom; ray=vec3(p.x,p.y,0); ray=ray+cameraLocation; direction=vec3(p.x*perspective,p.y*perspective,1.0); direction=normalize(direction); col=vec4(0.25+(p.y+0.5)/3.0,0.25+(p.y+0.5)/3.0,0.33+(p.y+0.5)/3.0,1.0); for(int i=0;i<50;i++) { d=dist(ray); if(d>=MAXD) { // Infinite distance break; } if(d<0.0001) { vec3 n=calc_normal(ray); float normlight=0.25*dot(light,n); float aolight=ao(ray,n,0.15); if(normlight<0.0) normlight=0.0; float ambient=0.75; float c=(normlight+ambient)*aolight; col=vec4(c,c,c,1.0); break; } ray+=direction*d; } gl_FragColor = col; }

Works for me, I only added the normalize, changed your distance function a bit and removed the *0.75 - because you don't need that for your current scene :)

The output from your original shader was not very different from the processing thing and didn't look as bad as what you posted.
added on the 2011-05-16 00:25:43 by las las
Thanks for taking the time to look into this las, much appreciated!
I tried with your changes, and the left of boxes/spheres are no longer white, but instead they are constant grey, so still not working properly.

Could it be something in my WebGL setup code (stolen straight from mr doob) that is wrong? Or maybe that I have an ATI card?

Could you please try and run this in your WebGL-compatible browser and see how it looks:

http://ag1976.com/tmp/raymarching.html

(same scene but with a bit of movement added).
added on the 2011-05-16 00:43:36 by Sdw Sdw
Works here, shading looks correct, and I'm on ATI (although on mac - it doesn't tend to make much difference). Speedy too.
added on the 2011-05-16 01:02:24 by psonice psonice
On my NV card that one almost looks perfect (I see some artifacts when the camera comes too close).
You might want to try to replace
Code: float normlight=0.25*dot(light,n);

with
Code: float normlight=0.25*max(0.,dot(light,n));

+ ATI sucks.
added on the 2011-05-16 08:24:06 by las las
(And I don't think this can be caused by the WebGL Code)
added on the 2011-05-16 08:25:14 by las las
A graphics-card driver update helped me in a similar case.
added on the 2011-05-16 10:25:41 by chock chock
@Sdw: don't know if it helps, but i get the same error as you.
Windows 7 x64, GeForce 285 GTX, Firefox 4
added on the 2011-05-16 11:01:17 by hcdlt hcdlt
Works on my work box too (also ati + mac, but different card + chrome instead of firefox).
added on the 2011-05-16 11:17:42 by psonice psonice
@Sdw: Doesn't work here either.
Windows XP, GeForce Quadro FX 580 + recent driver, Firefox 4
added on the 2011-05-16 12:39:51 by raer raer
BB Image Radeon HD 6950, Catalyst 11.5
added on the 2011-05-16 12:53:18 by kusma kusma
Same look as kusma's here on gtx460, 270.61...
added on the 2011-05-16 13:02:10 by Psycho Psycho
Yeah, I get the same result as kusma's screenshot (which appears to have disappeared now btw).
Can someone who has it working post a screenshot? I'd love to see how it looks when it runs properly! :D

I must say that I'm very confused to as to why it isn't working, I think what I have done is pretty straightforward, but I'm a toooootal noob on GLSL so I might have totally missed something.
added on the 2011-05-16 13:25:12 by Sdw Sdw
This is what I see:

BB Image
added on the 2011-05-16 13:34:58 by psonice psonice
(white borders are my crap screen grabbing skills, and I get the same "closest face of the bottom cube glitches when camera gets close" thing too)
added on the 2011-05-16 13:36:08 by psonice psonice
psonice: Yeah, that's pretty much the expected outcome, the glitching is probably due to me having to settle for max 25 iterations instead of 50 as I want to. With 50 the shader compile takes so long that the browser gives up on the Javascript.

Really strange, so it works for you and some others, but for most people, including me, it doesn't work and that applies to both ATI and Nvidia?

Confusion...

added on the 2011-05-16 13:43:24 by Sdw Sdw
what i'm learning right now is that nothing changed.
web-something and platform-independent-bullshit hypes still suffer from the same problems as they did 10 years ago.
added on the 2011-05-16 13:48:10 by hcdlt hcdlt
sdw: what's the compilation time with 25 iterations like it is now? Because for me, it's like 0 seconds, and unless it's trying to do some kind of crazy optimisation, that should be the same at 50 (I mean, I've used 300+ iterations before now, and not noticed any compiling delay at all!)
added on the 2011-05-16 13:51:33 by psonice psonice
psonice: Well, I don't know if it is compile time, I just assumed it was, I mean the time that elapses from when I load the page in the browser until the first frame is rendered.
I just tried here at work (somewhat slower computer than at home) and it took just about 30 seconds with 25 iterations enabled.
added on the 2011-05-16 13:54:59 by Sdw Sdw
Here's a link to a page with the screenshot. Sorry for the annoyance, seems awesomescreenshot tries really hard not to have people link directly.
added on the 2011-05-16 13:57:14 by kusma kusma

login