【发布时间】:2015-02-15 19:18:08
【问题描述】:
我目前正在研究 Directx 11 阴影映射示例。
这是我的步骤
- 创建 2 个顶点 hlsl 文件和 2 个像素 hlsl 文件。一个用于标准绘制,另一个用于将阴影渲染到深度缓冲区。
- 创建阴影着色器 depthStencilView。
- 创建纹理并绑定:D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE
- 对于每一帧:
- 设置新的渲染目标来渲染阴影:OMSetRenderTargets(0, nullptr, m_shadowDepthStencilView.Get());
- 清除深度缓冲区:ClearDepthStencilView(m_depthStencilView.Get(), D3D11_CLEAR_DEPTH, 1.0f, 0);
- 渲染所有对象。
- 将渲染目标重置为标准渲染目标视图:OMSetRenderTargets(1, renderTarget.GetAddressOf(), m_standarDepthStencilView.Get());
- 将深度纹理(在上次绘制中更改)设置为像素着色器资源:PSSetShaderResources(1, 1, m_directLightShadowResourceView.GetAddressOf());
- 再次渲染所有对象。
除了我在像素着色器中使用以下方法获取 z 值之外,一切似乎都有效:
float depthValue = depthTexture.Sample(samplerClamp, projectTexCoord).r;
depthValue 总是返回 0,不管怎样。 我已经使用 Visual Studio 图形诊断检查了我的 depthTexture 并且没问题。
但是当我对其纹理进行采样时,结果始终为 0。
不知道为什么,我卡在这个问题上很久了,请大家帮帮我。
注意:
- 深度纹理格式:DXGI_FORMAT_R24G8_TYPELESS
- shaderResourceView 格式:DXGI_FORMAT_R24_UNORM_X8_TYPELESS
这是我的 hlsl 文件
标准顶点着色器
/////////////////////
// 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;
}
标准像素着色器
/////////////////////
// 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);
}
}
阴影顶点着色器
/////////////////////
// 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;
}
它是像素着色器,什么都不做
////////////////////////
// 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);
}
【问题讨论】:
-
您使用的是什么硬件功能级别/着色器配置文件?
-
我正在使用 D3D_FEATURE_LEVEL_11_0。
-
我尝试了一个 sn-p: float4 main(PIn pixel) : SV_TARGET { return depthTexture.Sample(samplerWrap, pixel.texcoord); } 结果是纯黑色。我的纹理一定有问题,但我不知道为什么。
-
我已经弄清楚了。我现在觉得自己好傻。 - 我不能进行深度缓冲的原因是因为我在释放它的深度缓冲区(在 OSState 中绑定)之前使用 PSSetShaderResource 设置了着色器资源。 - 我唯一需要做的就是将代码 PSSetShaderResource 移到代码 OSSetRenderTarget 之后,然后它就可以工作了。
-
确保您尝试使用
D3D11_CREATE_DEVICE_DEBUG开关并检查错误或警告。调试层会提到管道危险。
标签: c++ graphics 3d directx directx-11