Raymarching Beginners' Thread

category: code [glöplog]
More distortions please ;P

But very nice.
meh, now its dead! even for ME! :p
Just to not scare the shit out of you - this is FAR from realtime. But I guess with some proper hacks... ;) At least something in that direction could be possible.
added on the 2011-07-29 21:42:41 by las las
Or do it like that and wait a couple of years and performance-issues will solve itself :D
added on the 2011-07-29 22:23:49 by Punqtured Punqtured
I think that could be OK for realtime with plenty of fakery, except maybe caustics. I can't think how you'd do caustics without some amount of bruteforcing, and then you're back to shit quality or slow as hell :(

Looks good anyway, bet you're happy with that result :)
added on the 2011-07-29 23:02:24 by psonice psonice
cool thing. that caustics. how do you do that? I'm still mega off that raymarching shit. it doesn't visualice in my head how this works. so... -.- gn
added on the 2011-07-30 00:05:29 by yumeji yumeji
I had some time again yesterday night and I finally decided to try out FBOs for being able to do postprocessing stuff etc. The shitty thing is that the depth buffer attachment of the FBO does not seem to be working right.
Crude, long code ahead, wtfs, questions at the end:

Code: #define WIDTH 512 #define HEIGHT 512 struct FBOInfo { GLuint id; GLuint color; GLuint depth; }; GLuint createTexture2D(const int w, const int h, const GLint internalFormat, const GLenum format, const GLenum type) { GLuint textureId; glGenTextures(1, &textureId); glBindTexture(GL_TEXTURE_2D, textureId); glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, w, h, 0, format, type, NULL); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); if (GL_DEPTH_COMPONENT == format) { //sample like regular texture, value is in (x,x,x,x) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY); } glBindTexture(GL_TEXTURE_2D, 0); return textureId; } bool createFBO(FBOInfo & fboInfo) { bool result = false; //generate textures for FBO usage fboInfo.color = createTexture2D(WIDTH, HEIGHT, GL_RGBA16F, GL_RGBA, GL_FLOAT); fboInfo.depth = createTexture2D(WIDTH, HEIGHT, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_FLOAT); //generate and bind FBO glGenFramebuffers(1, &fboInfo.id); glBindFramebuffer(GL_FRAMEBUFFER, fboInfo.id); //bind color and depth texture to FBO. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboInfo.color, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, fboInfo.depth, 0); if (GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER)) { printf("FBO %d set up successfully. Yay!\n", fboInfo.id); result = true; } else { printf("FBO %d NOT set up properly! Fuck.\n", fboInfo.id); } //unbind FBO for now glBindFramebuffer(GL_FRAMEBUFFER, 0); return result; }

I also tried using GLDEPTH_COMPONENT24 with GL_UNSINGED_INT or GL_UNSINGED _BYTE as texture parameter, but that made no different. Also if glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); is there or not doesn't make a difference.

When I 've set up the FBO I raymarch to the FBO:

Code: //use compiled shader glUseProgram(effectHandle); //use FBO glBindFramebuffer(GL_FRAMEBUFFER, fboInfo.id); //draw rect using raymarching shader glRectf(-1,-1,1,1); //bind regular framebuffer again glBindFramebuffer(GL_FRAMEBUFFER, 0);

The raymarchig shader writes the normalized iteration count (for testing, range 0->1) to the alpha channel of the color texture as well as to gl_FragDepth. From fragment shader main():

Code: //raymarch position, direction, max steps, max distance //returns vec4(rgb, normalized iteration count [0,1]) vec4 r = rm(p, d, 100, 100.); gl_FragColor = vec4(r.rgb, r.a); gl_FragDepth = r.a;

Postprocessing is set up like this:

Code: //set up textures for postprocessing glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, fboInfo.color); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, fboInfo.depth); // sample depth like regular texture and values are in (x,x,x,x) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY); //use compiled shader glUseProgram(postProcHandle); GLint colorSampler = glGetUniformLocation(postProcHandle, "color"); glUniform1i(colorSampler, 0); GLint depthSampler = glGetUniformLocation(postProcHandle, "depth"); glUniform1i(depthSampler, 1); //do post-processing glRectf(-1,-1,1,1);

The post-proc shader that should display the texture is:

Code: uniform sampler2D color; uniform sampler2D depth; void main() { float r = pow(texture2D(color, gl_FragCoord.xy / vec2(512, 512)).a, 128.0); float g = texture2D(depth, gl_FragCoord.xy / vec2(512, 512)).a; float b = pow(texture2D(depth, gl_FragCoord.xy / vec2(512, 512)).a, 128.0); gl_FragColor = vec4(r, g, b, 1.); }

This is the result I get with and w/o post-processing:
BB Image
(Red = iteration count from the color buffer alpha channel, rest is friggin 0.0)

Everything is created/compiled/completed correctly, no OpenGL errors. The raymarching and pros-processing shaders work obviously. I don't know if writing to the depth buffer with gl_FragDepth = value is correct and what range it accepts. Also I don't know which component of the depth buffer texture to use (eg. texture2D().a). It seems with:
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY); <-- (x,x,x,x)
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE); <-- (x,x,x,1)
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_ALPHA); <-- (0,0,0,x)

Maybe the experts here can clear things up a bit as I'm obviously doing something wrong... :/
added on the 2011-07-30 17:51:53 by raer raer
i do this
rare: You probably should disable OpenGL's claming to the 0..1-range... see glClampColorARB from http://www.opengl.org/registry/specs/ARB/color_buffer_float.txt
added on the 2011-07-30 18:29:03 by kusma kusma
But I'm passing values in the [0, 1] range... ?
added on the 2011-07-30 19:00:23 by raer raer
rasmus: Your rendering depth to a RenderBufferObject. Those are not usable as textures. You need to copy them to a texture first... Other than that the code looks like mine.

kusma: Tried

before rendering to FBO, but it didn't change anything.

I know I could as well use another floating point color attachment and render depth there, but people have been doing shadow mapping with depth buffer textures like this for ages. Should be no rocket science... Fuck...
added on the 2011-07-30 19:23:30 by raer raer
Uhm... I hate to admit it, but the computer wasn't plugged in... ;)
When you have depth buffering disabled then, oh wonder, there's no depth buffer written.
Code: glEnable(GL_DEPTH_TEST); glDepthFunc(GL_ALWAYS);

Fixed it (normalized raymarching iteration count from depth buffer texture):
BB Image

\o/ DoF trickery, here I come. Slowly. If ever... ;)
added on the 2011-07-30 19:45:26 by raer raer
i haven't read through the last few posts properly, but i take it you're not going to try DOF effects based on iteration count rather than depth? (Because that will look strange as hell.. maybe cool though who knows?)
added on the 2011-07-30 20:03:18 by psonice psonice
No. Just needed to pass values through from the raymarching shader to the pos-proc shader...
added on the 2011-07-30 20:07:31 by raer raer
rär, why do you want to use the zbuffer to store info? I think it's easier if you don't use any depth buffer on your fbo, but two color buffers/render textures. or, are you planning to mix raymarching with regular zbuffered geometry?
added on the 2011-07-30 20:20:45 by iq iq
That would be an option, yes. But I also wanted to screw around with regular shadow mapping a bit.
As I wrote earlier, I know using just a bunch of float color buffers for raymarching is the way to go...
added on the 2011-07-30 20:41:17 by raer raer
iq: we are still waiting for whatever you wanted to do with our email addresses ;)
added on the 2011-07-30 21:00:16 by las las
All that spam mail... It didn't get through?! ;)
added on the 2011-07-30 21:18:25 by raer raer
rär: good stuff, nothing worse than making some schoolboy error like using the iteration count instead of depth for the DoF effect, then spending about a week debugging the DoF effect before realising :D (I know this from long, long experience...)

I'm curious about what you can do with shadow mapping with Z though. Do you mean casting shadows within the raymarched scene (in which case isn't it going to look totally wrong with only the front faces casting shadows?) Or are you going to mix it with regular geometry / something else and cast shadows from that?
added on the 2011-07-30 22:57:34 by psonice psonice
You could probably render raymarching object bounding boxes with first (maybe even with OGL) and then use that to accelerate raymarching. Or mix regular polygons and raymarching or whatnot.
I just wanted to have a buffer I could post-process with. ;) Any sugestions for an easy DoF implementation are welcome :)
added on the 2011-07-30 23:37:14 by raer raer
You could just store the depth in the alpha channel. :3
Demoscene solutions FTW \./
added on the 2011-07-31 03:41:54 by Mewler Mewler
Speaking of demoscene solutions... > 250 fps @ 1280x1024
Yes it does look ugly. Testing.
BB Image
added on the 2011-08-04 10:14:54 by las las
Getting a first try working was indeed every bit as easy as I thought. Now for some expansion with all that fancy reading material.
added on the 2011-08-05 01:24:41 by superplek superplek
I have shader compile times of around 1 minute... PAIN.
added on the 2011-08-05 02:37:45 by las las
1 minute? that's fast. lol. so... the loading bar is the actual effect?! I dunno who I should blame. I think there's something wrong with the driver devers.
added on the 2011-08-05 03:50:25 by yumeji yumeji