由于阴影在我的地形上工作良好,因此我想在思考实例对象上的阴影出问题的同时继续前进。
为此,我试图在阴影贴图上执行PCF以平滑边缘。我大致遵循Frank Luna的书中有关3x3 PCF的算法。但是,Texture2D.SampleCmpLevelZero函数似乎只返回了边框颜色。当我单击普通纹理采样器的一次单击时,会得到一个正确的深度深度(因此将其与objPos.z进行比较可以知道它是否在阴影中)。为了测试它并证明它按预期工作,我将其在红色通道中输出SampleCmpLevelZero的结果,然后在阴影中将绿色通道设置为1,在阴影中将蓝色通道设置为1。>
但是,结果是光中的所有内容都是品红色(R = 1 + B = 1),阴影中的所有内容都是黄色(R = 1 + G = 1),这意味着尽管普通采样器正确无误,比较采样器没有区别。边框颜色设置为纯白色,因此红色通道返回1.0f。如果将边框颜色更改为黑色,它将返回0(导致纯蓝色/绿色代表浅色/阴影)。真正的难题是,我要同时传递两个功能完全相同的参数。它是纹理坐标的相同位置值,并且是用于比较的相同深度值。我看了一堆类似的问题,我认为我的所有内容都正确,但仍然无法正常工作。任何人都可以阐明问题所在吗?预期结果是在0到1之间插值的值,用于混合阴影。让我知道您是否需要更多信息。谢谢。
着色器模型为5_0
采样器状态初始化(调用一次,永不绑定):
ZeroMemory(&sampDesc, sizeof(sampDesc));
//float shadowColor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };//Returns 1 if outside of light I guess?
float shadowColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };//Returns 0 if outside of light I guess?
sampDesc.Filter = D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT;
sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_BORDER;
sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_BORDER;
sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_BORDER;
sampDesc.ComparisonFunc = D3D11_COMPARISON_LESS;
sampDesc.BorderColor[0] = shadowColor[0];
sampDesc.BorderColor[1] = shadowColor[1];
sampDesc.BorderColor[2] = shadowColor[2];
sampDesc.BorderColor[3] = shadowColor[3];
sampDesc.MinLOD = 0;
sampDesc.MaxLOD = 0;
hr = dev->CreateSamplerState(&sampDesc, &ShadowSamplerPCF);
devcon->PSSetSamplers(1, 1, &ShadowSamplerPCF);
阴影贴图纹理创建:
lightInfo.ShadowWidth = 4096;
lightInfo.ShadowHeight = 4096;
ZeroMemory(&lightInfo.ShadowViewport, sizeof(D3D11_VIEWPORT));
lightInfo.ShadowViewport.TopLeftX = 0;
lightInfo.ShadowViewport.TopLeftY = 0;
lightInfo.ShadowViewport.Width = lightInfo.ShadowWidth;
lightInfo.ShadowViewport.Height = lightInfo.ShadowWidth;
lightInfo.ShadowViewport.MinDepth = 0.0f;
lightInfo.ShadowViewport.MaxDepth = 1.0f;
D3D11_TEXTURE2D_DESC texDesc;
ZeroMemory(&texDesc, sizeof(D3D11_TEXTURE2D_DESC));
texDesc.Width = lightInfo.ShadowWidth;
texDesc.Height = lightInfo.ShadowWidth;
texDesc.MipLevels = 1;
texDesc.ArraySize = 1;
texDesc.Format = DXGI_FORMAT_R32_TYPELESS;
texDesc.SampleDesc.Count = 1;
texDesc.SampleDesc.Quality = 0;
texDesc.Usage = D3D11_USAGE_DEFAULT;
texDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
texDesc.CPUAccessFlags = 0;
texDesc.MiscFlags = 0;
// Create the depth stencil view desc
D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
ZeroMemory(&descDSV, sizeof(D3D11_DEPTH_STENCIL_VIEW_DESC));
descDSV.Format = DXGI_FORMAT_D32_FLOAT;
descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
descDSV.Texture2D.MipSlice = 0;
//create shader resource view desc
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
ZeroMemory(&srvDesc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));
srvDesc.Format = DXGI_FORMAT_R32_FLOAT;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = texDesc.MipLevels;
srvDesc.Texture2D.MostDetailedMip = 0;
//create texture and depth/resource views
HRESULT hr;
hr = graphicsPointers.pdev->CreateTexture2D(&texDesc, NULL, &ShadowTex2D);
if (FAILED(hr))
{
MessageBox(NULL, "ERROR: Failed to create Shadow Map Texture 2D", "LightWithShadowMapClass.cpp", MB_OK);
}
hr = graphicsPointers.pdev->CreateDepthStencilView(ShadowTex2D, &descDSV, &lightInfo.ShadowDSV);
if (FAILED(hr))
{
MessageBox(NULL, "ERROR: Failed to create Shadow Map Depth Stencil View", "LightWithShadowMapClass.cpp", MB_OK);
}
hr = graphicsPointers.pdev->CreateShaderResourceView(ShadowTex2D, &srvDesc, &lightInfo.ShadowSRV);
if (FAILED(hr))
{
MessageBox(NULL, "ERROR: Failed to create Shadow Map Shader Resource View", "LightWithShadowMapClass.cpp", MB_OK);
}
以下是在着色器中声明采样器状态的方式:
SamplerState ObjSamplerState:register(s0); //Normal sampler, gets set based on what is being done. Usually is a wrap when rendering objects.
SamplerComparisonState ShadowSampler:register(s1); //Set once and never changes
这是简化的像素着色器(执行一个SampleCmp而不是9):
//re-homogenize position after interpolation
input.PosLight = mul(input.PosLight, lightVPMat); //PosLight is interpolated world Pos
input.PosLight.xyz /= input.PosLight.w;
//if position is not visible to the light, don't calculate shadows. Instead, render it normally.
if (input.PosLight.x < -1.0f || input.PosLight.x > 1.0f ||
input.PosLight.y < -1.0f || input.PosLight.y > 1.0f ||
input.PosLight.z < 0.0f || input.PosLight.z > 1.0f)
{
finalColor = texColor * light.ambient;
finalColor += saturate(dot(light.dir, input.Normal) * light.diffuse * texColor);
}
else
{
//transform clip space coords to texture space coords (-1:1 to 0:1)
input.PosLight.x = (input.PosLight.x + 1.0f) / 2.0f;
input.PosLight.y = (input.PosLight.y + 1.0f) / -2.0f;
//sample shadow map - point sampler
float percentLit = 0.0f;
float shadowMapDepth = 0.0f;
uint status = 0;
//Note that the two sample commands are receiving the same coordinates.
percentLit += ShadowMap.SampleCmpLevelZero(ShadowSampler, input.PosLight.xy, input.PosLight.z, int2(0, 0), status).r;
shadowMapDepth = ShadowMap.Sample(ObjSamplerState, input.PosLight.xy).r;
finalColor = texColor * light.ambient;
finalColor += percentLit * saturate(dot(light.dir, input.Normal) * light.diffuse * texColor);
if (shadowMapDepth < input.PosLight.z)
{
//in shadow
finalColor = float4(percentLit, 1.0f, 0.0f, 1.0f);
}
else
{
//in light
finalColor = float4(percentLit, 0.0f, 1.0f, 1.0f);
}
}
黑边颜色的图片:Not the Expected Result