6
$\begingroup$

I'm implementing volumetric fog in my OpenGL renderer. First I inject color into 3D texture using compute shader, atomic operations and shadow map visibility check. The information I use to compute cell index and position in world space are uniforms: camera pos, cellsize and texture dimensions. Next, when volume filled with data is ready, I need to align it with view frustum to raymarch through texture and apply effect as postprocess (deffered stage) and I'm quite stuck with it. I think there are two options (red is texture volume): 3d texture aligned with frustum

So, while applying effect I raymarch from camera pos to frag pos (from G-Buffer texture). I dont know if it is correct, but I think I need to somewhat transform frag pos to NDC, scale it to [0,1] and then using this sample from volume.

Tried some magic like:

vec4 texcoords = vpMatrix * vec4(fragPos, 1.0); //to clip space
texcoords.xyz /= texcoords.w; //to NDC
texcoords.xyz = texcoords.xyz *0.5 +0.5; //[-1,1] to [0,1]

Eventually:

vec3 texcoords;
texcoords.x = texcoord0.x; //texcoord0 - texcoords of screen quad
texcoords.y = texcoord0.y;
texcoords.z = depth; //depth from vector: worldpos-camerapos

But its just guessing. In addition I dont know which option from picture is used in such cases (pro game engines) and how to apply only on some length of frustum because its quite big. Will be really grateful for any hint for this.

To check if this works for now its implemented like this: camera aligned in center of volume so rotating it not really matters some much. So i probably will need to modify injections stage too to get correct cell indexes which are statically computed like:

vec3 index = vec3(gl_GlobalInvocationID); //cell number of texture;
vec3 pos = camerapos+index*cellSize;
$\endgroup$

1 Answer 1

3
$\begingroup$

In techniques I've seen that use a frustum-aligned voxel grid (so-called "froxels"), it looks like option 2 in your diagram. The voxels are cuboids in post-projective screen space, so when transformed back to world space they look like mini-frusta, automatically expanding as they get farther from the camera.

Marching along eye rays is then very easy: you just step along the grid's Z axis. Summing optical density or in-scattered light along an eye ray is just a matter of iterating over the Z dimension of the texture. (Or you could try to apply methods like parallel prefix sum as well, but it may not be worthwhile, depending on the texture size.)

If you're rendering some geometry and you want to know which voxel it's in, you don't have to do any matrix transformations. Just use gl_FragCoord​, which represents the screen-space position (including depth) of the current fragment. It comes in window units (i.e. pixels) so you'll have to remap it to [0,1] for texture sampling, or to voxel units if you're doing an image store.

Otherwise, for mapping world-space positions into the voxel grid, use the usual sequence of transformations. It looks to me like you got it right in your code snippet, assuming fragPos is in world space. For getting from the voxel grid back to world space, you'll need to invert that sequence of transformations.

$\endgroup$
2
  • $\begingroup$ Thanks. Just managed to get it working (option 2). Transformation while raymarching to sample and inverse transformation while injecting. But I'm still raymarching to worldpos as usual, maybe i can be done simpler - iterating like you said but it would still require a loop. $\endgroup$
    – mdkdy
    Commented Aug 21, 2016 at 11:45
  • $\begingroup$ I mean not using transformations but iterate through z. $\endgroup$
    – mdkdy
    Commented Aug 21, 2016 at 11:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.