Volumetric Fog Producing Weird 'Bands'

Hey guys, I've been working on my first proper 3D engine, and recently I decided to implement a volumetric fog algorithm (from GPU Pro 6, though you do not need own a copy to help me :) ), and it has been causing me a great deal of stress, so any help will be much appreciated.

Anyway, to the problem at hand...

My volumetric fog is held in a 3D texture, which is view-aligned, so the Z of the texture extends forwards (much like a depth buffer) and the X and Y are fit with the screen. Anyway, I have a function which transforms any one texel of that texture from texture space to world space:

1
2
3
4
5
6
7
8
9
10
11
12
float3 CalculateWorldPos(uint3 texel)
{
    //Texture space to NDC coordinates
    float3 pos = (float3)texel * float3(1.0f / 190.0f, 1.0f / 90.0f, 1.0f / (float)(g_Depth));
    pos.xy = 2.0f * pos.xy - float2(1.0f, 1.0f);
    //NDC coordinates to world coordinates
    //The constant g_InverseFogTransform is basically the inverse view projection. I will show how it is defined further down.
    float4 worldPos = mul(float4(pos, 1.0f), g_InverseFogTransform);
    //Complete transformation
    worldPos.xyz /= worldPos.w;
    return worldPos.xyz;
}


The matrix g_InverseFogTransform is defined as:

 
XMMATRIX FogTransform = CameraViewMatrix * XMMatrixPerspectiveFovLH(pCamera->GetFOVY(), pCamera->GetAspectRatio(), 1.0f, m_WorldDepth);


CameraViewMatrix is unsurprisingly the camera's view matrix,
m_WorldDepth is the depth in world space I wish this texture to extend,
pCamera is a pointer to a camera object.
Note that once that matrix is determined, THEN I take the inverse (and then the transpose and send it over to my HLSL shaders via a constant buffer)

However, this code does not work completely. The X and Z coordinates of the world position seem to be correct, but the Y coordinates seem to be incorrect (for the texels). I have no clue why and have been pondering this all of Christmas Eve and today.

Referring to the title, by 'bands' I mean weird strips of sorts, where the fog is denser, then becomes less dense, then becomes even denser, creating a wave-ripple-band effect, whatever you want to call it :). This is due to my function to calculate fog density which is solely based on the world Y coordinate.

While writing this question it has occurred to me that maybe my problem is that I'm using a perspective matrix, because after the 3D fog texture is created, I then create a second one and it loops through every X and Y coordinate and accumulates fog; don't worry, I'll show you...

1
2
3
4
5
6
7
8
9
10
11
12
void main(int3 dispatchThreadID : SV_DispatchThreadID)
{
    float4 currentSliceValue = g_Input[uint3(dispatchThreadID.xy, 0)];
    WriteOutput(uint3(dispatchThreadID.xy, 0), currentSliceValue);
    for (uint z = 1; z < g_Depth; z++)
    {
        uint3 volumePos = uint3(dispatchThreadID.xy, z);
        float4 nextValue = g_Input[volumePos];
        currentSliceValue = AccumulateScattering(currentSliceValue, nextValue);
        WriteOutput(volumePos, nextValue);
    }
}


So if you picture that function running in your head, all of the Z values are parallel; one behind the other. Maybe (I'm not sure though) that means I should be using an orthographic projection matrix.

So yeah, hard question. I know I'm not supposed to use the word "help", but honestly, I'm so stuck and this has eaten up a lot of my spare time. Including the majority of Christmas Eve.

Thanks so much in advance :)
Last edited on
Topic archived. No new replies allowed.