# Troublesome depth normal map

This topic is 2164 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi there,

I have been trying to implement SSAO and I was reading for quite a while now, so I should be quite familiar with the theory.

How ever the comparatively easy task to create the depth normal map happens to be a problem...

Here is what i am doing:

struct VS_INPUT
{
float3 position : POSITION;
float3 normal    : NORMAL;
};

struct VS_OUTPUT
{
float4 position : SV_Position;
float3 normal : TEXCOORD0;
float depth : TEXCOORD1;
};

VS_OUTPUT VSMAIN (in VS_INPUT input)
{
VS_OUTPUT output;

output.position = mul (float4 (input.position, 1.0f), WorldMatrix);
output.position = mul (output.position, ViewMatrix);
output.position = mul (output.position, ProjMatrix);

float4 norm = mul (float4 (input.normal, 0.0), WorldMatrix);
output.normal = mul (norm, ViewMatrix).xyz;
output.normal = normalize (output.normal);
output.normal = output.normal * 0.5 + 0.5;

output.depth = output.position.w;

return output;
}

float PSMAIN (in VS_OUTPUT input) : SV_Target
{
return float4 (input.normal, input.depth);
}


Unfortunately the output generated is not quite the thing you would expect, the picture is flickering with "noise":

The Question now is, what the devil could cause such behaviour? I am confused.

##### Share on other sites
float PSMAIN (in VS_OUTPUT input) : SV_Target
{
return float4 (input.normal, input.depth);
}


First problem:  the return type is declared as a float but you are actually returning a float4.  I'm surprised this is even compiling.

Second problem:  the depth value you are outputting is simply the view space depth.  Perhaps this is what you want, if so you'll need to be writing to a render target that can hold a float of arbitrary magnitude.  Also make sure all blending is switched off, weird things can happen when your pixel shaders output alpha values that are not between zero and one.

##### Share on other sites

Agree with nonoptimal!

Btw. Further in the ssao, how are you converting the depth into view space?

##### Share on other sites

Yeah that was kind of obvious, wasn't that...

Btw. Further in the ssao, how are you converting the depth into view space?

I intended to strip down the sample code from the hieroglyph3 engine, but I'm not entirely familiar with cumpute shader yet (but theres plenty of examples to go through)... I will reply again if theres an acceptaple solution for me.

##### Share on other sites

First problem:  the return type is declared as a float but you are actually returning a float4.  I'm surprised this is even compiling.

It is legal to cast any floatn to float, so no surprise here. However, there may be warning for it.

Cheers!

##### Share on other sites

Sorry to bother you again...

I think i got the depth normal pass working and went on to the actual algorithm,

but theres weired stuff happening again...

This is how i generate normals and positions:

struct VS_INPUT
{
float3 position : POSITION;
float3 normal	: NORMAL;
};

struct PS_INPUT
{
float4 position : SV_Position;
float4 viewpos : POSITION;
float3 normal : NORMAL;
};

PS_INPUT VSMAIN (in VS_INPUT input)
{
PS_INPUT Out;

Out.viewpos = mul (float4 (input.position, 1.0f), WorldMatrix);
Out.viewpos = mul (Out.viewpos, ViewMatrix);

Out.position = mul (Out.viewpos, ProjMatrix);

float3 viewSpaceNormal = mul (input.normal, (float3x3)WorldMatrix);
Out.normal = mul (viewSpaceNormal, (float3x3)ViewMatrix);

return Out;
}

struct PS_OUTPUT
{
float4 normal : SV_Target0;
float4 viewpos : SV_Target1;
};

PS_OUTPUT PSMAIN (in PS_INPUT In)
{
PS_OUTPUT Out;

Out.normal =  float4(normalize(In.normal) * 0.5f + 0.5f, 1.0f);
Out.viewpos = In.viewpos;

return Out;
}


This is what i got so far, it is pretty much like the article from here: http://www.gamedev.net/page/resources/_/technical/graphics-programming-and-theory/a-simple-and-practical-approach-to-ssao-r2753

The Ambien Occlusion shader here is applied to a full screen triangle

float3 getPosition (in float2 uv)
{
return PositionBuffer.Sample (LinearSampler, uv).xyz;
}

float3 getNormal (in float2 uv)
{
return DepthNormalBuffer.Sample (LinearSampler, uv).xyz;
}

float2 getRandom (in float2 uv)
{
return normalize (RandomTexture.Sample (LinearSampler, uv).xy * 2.0f - 1.0f);
}

float doAmbientOcclusion (in float2 tcoord, in float2 occluder, in float3 p, in float3 cnorm)
{
// vector v from the occludee to the occluder
float3 diff = getPosition (tcoord + occluder) - p;
const float3 v = normalize (diff);

// distance between occluder and occludee
const float d = length (diff);

return max (0.0, dot (cnorm,v)) * (1.0 / (1.0 + d));
}

float PSMAIN (in PS_INPUT In) : SV_Target
{
const float2 vec[4] = {
float2 (1,0), float2 (-1,0),
float2 (0,1), float2 (0,-1)
};

float3 p = getPosition (In.tex);
float3 n = getNormal (In.tex);
float2 rand = getRandom(In.tex);

float ao = 0.0f;
float rad = 0.125 / p.z;

int iterations = 4;
for (int j = 0; j < iterations; ++j)
{
float2 coord1 = reflect(vec[j], rand) * rad;
float2 coord2 = float2 (coord1.x*0.707 - coord1.y*0.707,
coord1.x*0.707 + coord1.y*0.707);

ao += doAmbientOcclusion (In.tex, coord1*0.25, p, n);
ao += doAmbientOcclusion (In.tex, coord2*0.5, p, n);
ao += doAmbientOcclusion (In.tex, coord1*0.75, p, n);
ao += doAmbientOcclusion (In.tex, coord2, p, n);
}
ao /= (float)iterations*4.0;

return ao;
}


after that I render the scene again and modulate the output by using this occlusion buffer

how ever theese are the images it produces:

I dont't know how that soapy screen effect is produced but i think it has something to do with the randomTexture.

I can't get the image look right to me (aside from the soap screen) by tweaking the parameters.

For example: If I look 45° to the left the front faces grow dark (why?).

Another thing is, that if I normalize the random normals the frame rate drops to a tenth.

• 13
• 18
• 29
• 11