0
votes

I am currently working on a Directx 11 shadow mapping sample.

Here are my step

  • Create 2 vertex hlsl files and 2 pixel hlsl files. One is used to standar draw and the other is used to render shadow to depth-buffer.
  • Create shadow-shader depthStencilView.
  • Create texture and bind: D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE
  • For each frame:
    • Set new render target to render shadow: OMSetRenderTargets(0, nullptr, m_shadowDepthStencilView.Get());
    • Clear depth-buffer: ClearDepthStencilView(m_depthStencilView.Get(), D3D11_CLEAR_DEPTH, 1.0f, 0);
    • Render all objects.
    • Reset render target to stander render target view: OMSetRenderTargets(1, renderTarget.GetAddressOf(), m_standarDepthStencilView.Get());
    • Set depth-texture (which is changed in last draw) to pixel shader resource: PSSetShaderResources(1, 1, m_directLightShadowResourceView.GetAddressOf());
    • Render all objects again.

Every thing seem to work except that when I get z-value in pixel shader using:

float depthValue = depthTexture.Sample(samplerClamp, projectTexCoord).r;

The depthValue always return 0, nomatter what. I have check my depthTexture using visual studio graphic diagnostic and it is ok.

But When I sampler it's texture, the result is always 0.

I don't know why, I have stuck on this for a long time, so please help me.

note:

  • depthTexture format: DXGI_FORMAT_R24G8_TYPELESS
  • shaderResourceView format: DXGI_FORMAT_R24_UNORM_X8_TYPELESS

Here are my hlsl files

Standar vertex shader

/////////////////////
// CONSTANT BUFFER
cbuffer worldMatrixBuffer : register(b0)
{
	float4x4 worldMatrix[10];
};

cbuffer cameraBuffer : register(b1)
{
	float4x4 viewProjectionMatrix;
};

cbuffer directLightBuffer : register(b2)
{
	float4x4 directLightViewProjectionMatrix;
};


////////////////////////////
// INPUT VERTEX STRUCTURE
struct VIn
{
	float4 position : POSITION;
	float4 normal : NORMAL;
	float worldMatrixIndex : TEXCOORD0;
	float2 texcoord : TEXCOORD1;
};


//////////////////////
// OUTPUT STRUCTURE
struct VOut
{
	float3 normal : NORMAL;
	float4 position : SV_POSITION;
	float2 texcoord : TEXCOORD0;
	float4 lightViewPosition : TEXCOORD1;
};


////////////////////////
// MAIN VERTEX SHADER
VOut main(VIn vertex)
{
	// Create output struct
	VOut output;

	// Change the position vector to be 4 units for proper matrix calculations.
	vertex.position.w = 1.0f;

	// Get world-view-projection matrix
	float4x4 currentWorldMatrix = worldMatrix[vertex.worldMatrixIndex];

	// vertex form object space to world-light-view space
	output.lightViewPosition = mul(currentWorldMatrix, vertex.position);
	output.lightViewPosition = mul(directLightViewProjectionMatrix, output.lightViewPosition);

	// vertex form object space to world-camera space;
	output.position = mul(currentWorldMatrix, vertex.position);
	output.position = mul(viewProjectionMatrix, output.position);

	// transform normal vector from object-space to world space
	output.normal = mul((float3x3)currentWorldMatrix,	// convert to matrix 3x3 is important because
														// we don't want to translate normal vector
		vertex.normal);

	// we need to normalize the normal vector to preform next calculation
	output.normal = normalize(output.normal);

	// Set texture coordinate
	output.texcoord = vertex.texcoord;

	// Return output values
	return output;
}

Standar pixel shader

/////////////////////
// CONSTANT BUFFER
cbuffer lightBuffer : register(b0)
{
	// Light information
	float4 lightDirection;
	float4 diffuseColor;
	float4 ambientColor;
};


//////////////////////
// INPUT STRUCTURE
struct PIn
{
	float3 normal : NORMAL;
	float4 position : SV_POSITION;
	float2 texcoord : TEXCOORD0;
	float4 lightViewPosition : TEXCOORD1;
};


//////////////////////
// TEXTURE RESOURCE
Texture2D objectTexture : register(t0);	// Register(t...) tell shader that this variable
										// retrive data from texture register 0.
Texture2D depthTexture : register(t1);


/////////////
// SAMPLER
SamplerState samplerWrap : register(s0);
SamplerState samplerClamp : register(s1);


///////////////////////
// MAIN PIXEL SHADER
float4 main(PIn pixel) : SV_TARGET
{
	//----------------------------------------------------------------------------------
	// Set the bias value for fixing the floating point precision issues.
	float bias = 0.001f;

	// set minimum color to ambient color
	float4 color = ambientColor;

	// Calculate the projected texture coordinates.
	float2 projectTexCoord;
	projectTexCoord.x = pixel.lightViewPosition.x / pixel.lightViewPosition.w / 2.0f + 0.5f;
	projectTexCoord.y = -pixel.lightViewPosition.y / pixel.lightViewPosition.w / 2.0f + 0.5f;
	// By divine x and y to w we convert it lightViewPosition to uv coordinate from -1 to 1
	// convert it to 0 -> 1 coordinate simply by divine it to 2 and add 0.5

	if (saturate(projectTexCoord.x) == projectTexCoord.x
		&& saturate(projectTexCoord.y) == projectTexCoord.y)
	{
		// Sample the shadow map depth value from the depth texture using the sampler at
		// the projected texture coordinate location.
		float depthValue = depthTexture.Sample(samplerClamp, projectTexCoord).r;

		// Calculate the depth of the light.
		float lightDepthValue = pixel.lightViewPosition.z / pixel.lightViewPosition.w;

		// Subtract the bias from the lightDepthValue.
		lightDepthValue = lightDepthValue - bias;

		// Compare the depth of the shadow map value and the depth of the light to determine
		// whether to shadow or to light this pixel. If the light is in front of the object
		// then light the pixel, if not then shadow this pixel since an object (occluder)
		// is casting a shadow on it.
		if (lightDepthValue > depthValue)
		{
			float4 normalLightDir = normalize(lightDirection);
				float diffuseBrigtness = saturate(			// force result to between 0 and 1
				dot(pixel.normal, normalLightDir));			// dot product of normal vector and 
			// light direction

			// add diffuse light to output color
			color += diffuseColor * diffuseBrigtness;
		}
	}

	// Multiply final color with it's texture color
	if (pixel.texcoord.x > 1)
	{
		return color * (1, 1, 1, 1);
	}
	else
	{
		return color * objectTexture.Sample(samplerWrap, pixel.texcoord);
	}
}

Shadow vertex shader

/////////////////////
// CONSTANT BUFFER
cbuffer worldMatrixBuffer : register(b0)
{
	float4x4 worldMatrix[10];
};

cbuffer directLightBuffer : register(b2)
{
	float4x4 directLightViewProjectionMatrix;
};


////////////////////////////
// INPUT VERTEX STRUCTURE
struct VIn
{
	float4 position : POSITION;
	float4 normal : NORMAL;
	float worldMatrixIndex : TEXCOORD0;
	float2 texcoord : TEXCOORD1;
};


//////////////////////
// OUTPUT STRUCTURE
struct VOut
{
	float4 position : SV_POSITION;
};


////////////////////////
// MAIN VERTEX SHADER
VOut main(VIn vertex)
{
	// Create output struct
	VOut output;

	// Get world-view-projection matrix
	float4x4 currentWorldMatrix = worldMatrix[vertex.worldMatrixIndex];

	// vertex form object space to world-camera space
	output.position = mul(currentWorldMatrix, vertex.position);
	output.position = mul(directLightViewProjectionMatrix, output.position);

	return output;
}

And it's pixel shader, which do nothing

////////////////////////
// PIXEL INPUT STRUCT
struct PIn
{
	float4 position : SV_POSITION;
};

float4 main(PIn pixel) : SV_TARGET
{
	return float4(1.0f, 1.0f, 1.0f, 1.0f);
}
1
What hardware feature level/shader profiles are you using?Chuck Walbourn
I'm using D3D_FEATURE_LEVEL_11_0.Khoi Nguyen Hoang
I have try a snippet: float4 main(PIn pixel) : SV_TARGET { return depthTexture.Sample(samplerWrap, pixel.texcoord); } and the result is pure black. There must be something wrong with my texture but I can't figure out why.Khoi Nguyen Hoang
I have figure it out. I feel so stupid now. - The reason why I can not depth-buffer is because I set shader resource using PSSetShaderResource befor I release it's depth buffer (which was bind in OSState). - The only thing I need to do is move the code PSSetShaderResource to after the code OSSetRenderTarget and suddenly it's work.Khoi Nguyen Hoang
Make sure you try the D3D11_CREATE_DEVICE_DEBUG switch and check for ERRORS or WARNINGS. The debug layer would have mentioned the pipeline hazard.Chuck Walbourn

1 Answers

0
votes

Sorry every one, I have figured it out. I feel really stupid.

  • The reason I cannot read my depth buffer is because I use PSSetShaderResource before OMSetRenderTarget. What this mean is that my depth buffer is still bind to OM state and so it cannot be binded to PS state.

  • I only need to move the code a few line down and every thing just work

I am really sorry every one who has wasted there time on my question.