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 :)