首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >阴影贴图(DirectX12):阴影贴图不能正确渲染

阴影贴图(DirectX12):阴影贴图不能正确渲染
EN

Stack Overflow用户
提问于 2021-08-26 13:15:57
回答 2查看 153关注 0票数 0

对于自动翻译,很抱歉。

现在卡住的部分是阴影贴图。

播放器的位置正好是2000,0,2000;有一个光源,它是天空正上方阴影贴图摄影机的原点(它是一个目录光)。

问题1

你需要一个阴影贴图来应用阴影贴图,不是吗?

阴影贴图现在不起作用,但让我们继续。

只要阴影贴图摄影机的视口位于覆盖空间本身,渲染就不会在阴影贴图上正常工作。

即使它被初始化为1.0f,它也应该都在阴影之外。

虽然当前的阴影贴图相机位置是2000,100,2000,并且焦点位置是0,0,0。

这不是一个红色的正方形区域,应该被确定为在阴影之外。

绿色正方形区域被确定为走出阴影。

仅供参考,视口中没有任何遮挡灯光的对象。你在屏幕截图中看到的阴影就在视口之外,所以它是一个来自阴影贴图上0.0f判断的阴影。

问题2

这是最根本的问题。在阴影过程中没有在阴影贴图上渲染。

一旦这个完成,我会找到第一个问题,但渲染本身不工作,所以没有阴影的对象->原因是未知的

Source表示ShadowShader类正在渲染阴影贴图(ShadowPassRender)

影响这一点的是在光源时创建的视图项目矩阵(阴影着色器类的更新ShaderVariables部分)。

我对这个最怀疑,但它的制作过程与示例没有什么不同,所以我不知道它错在哪里。

我正在使用灯光本身作为一个闪光乒乓球,我将以此为例,并为项目修复它。

生成阴影映射视图-投影矩阵的代码

代码语言:javascript
运行
复制
void CShadowShader::UpdateShaderVariables(ID3D12GraphicsCommandList* pd3dCommandList, XMFLOAT3 xmf3TargetPos)
{
    XMFLOAT3 TargetPos = {950, 0, 950};
    XMMATRIX lightView = XMMatrixLookAtLH(XMLoadFloat3(&m_pLight->GetPosition()), XMLoadFloat3(&TargetPos), XMLoadFloat3(&m_pLight->GetUp()));

    // Transform bounding sphere to light space.
    XMFLOAT3 xmf3CenterLS;
    XMStoreFloat3(&xmf3CenterLS, XMVector3TransformCoord(XMLoadFloat3(&TargetPos), lightView));

    // Ortho frustum in light space encloses scene.

    float l = xmf3CenterLS.x - 3000;
    float b = xmf3CenterLS.y - 3000;
    float n = xmf3CenterLS.z - 3000;
    float r = xmf3CenterLS.x + 3000;
    float t = xmf3CenterLS.y + 3000;
    float f = xmf3CenterLS.z + 3000;

    XMMATRIX lightProj = XMMatrixOrthographicOffCenterLH(l, r, b, t, n, f);

    // Transform NDC space [-1,+1]^2 to texture space [0,1]^2
    XMMATRIX T(
        0.5f, 0.0f, 0.0f, 0.0f,
        0.0f, -0.5f, 0.0f, 0.0f,
        0.0f, 0.0f, 1.0f, 0.0f,
        0.5f, 0.5f, 0.0f, 1.0f);

    XMMATRIX S = lightView * lightProj * T;

    XMFLOAT4X4 m_xmf4x4ShadowTransform;

    XMStoreFloat4x4(&m_xmf4x4ShadowTransform, S);

    CB_SHADOW cbShadow{ m_xmf4x4ShadowTransform, m_pLight->GetPosition() };

    m_ubShadowCB->CopyData(0, cbShadow); 
    pd3dCommandList->SetGraphicsRootConstantBufferView(3, m_ubShadowCB->Resource()->GetGPUVirtualAddress());
}

使PSO用于阴影过程

代码语言:javascript
运行
复制
void CShadowShader::CreateShader(ID3D12Device* pd3dDevice, ID3D12RootSignature* pd3dGraphicsRootSignature)
{
    m_ubShadowCB = new UploadBuffer<CB_SHADOW>(pd3dDevice, 1, true);

    ID3DBlob* pd3dVertexShaderBlob = NULL, * pd3dPixelShaderBlob = NULL;

    D3D12_GRAPHICS_PIPELINE_STATE_DESC d3dPipelineStateDesc;
    ::ZeroMemory(&d3dPipelineStateDesc, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC));
    d3dPipelineStateDesc.pRootSignature = pd3dGraphicsRootSignature;
    d3dPipelineStateDesc.VS = CreateVertexShader(&pd3dVertexShaderBlob);
    d3dPipelineStateDesc.PS = CreatePixelShader(&pd3dPixelShaderBlob);
    d3dPipelineStateDesc.RasterizerState = CreateRasterizerState();

    d3dPipelineStateDesc.RasterizerState.DepthBias = 10000.0f;
    d3dPipelineStateDesc.RasterizerState.DepthBiasClamp = 0.0f;
    d3dPipelineStateDesc.RasterizerState.SlopeScaledDepthBias = 1.0f;

    d3dPipelineStateDesc.BlendState = CreateBlendState();
    d3dPipelineStateDesc.DepthStencilState = CreateDepthStencilState();
    d3dPipelineStateDesc.InputLayout = CreateInputLayout();
    d3dPipelineStateDesc.SampleMask = UINT_MAX;
    d3dPipelineStateDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
    d3dPipelineStateDesc.NumRenderTargets = 0;
    d3dPipelineStateDesc.RTVFormats[0] = DXGI_FORMAT_UNKNOWN;
    d3dPipelineStateDesc.DSVFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
    d3dPipelineStateDesc.SampleDesc.Count = 1;
    d3dPipelineStateDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
    auto tmp = pd3dDevice->CreateGraphicsPipelineState(&d3dPipelineStateDesc, __uuidof(ID3D12PipelineState), (void**)&m_pd3dPipelineState);


    if (pd3dVertexShaderBlob)
        pd3dVertexShaderBlob->Release();

    if (pd3dPixelShaderBlob)
        pd3dPixelShaderBlob->Release();

    if (d3dPipelineStateDesc.InputLayout.pInputElementDescs)
        delete[] d3dPipelineStateDesc.InputLayout.pInputElementDescs;
}

阴影过程的着色器

代码语言:javascript
运行
复制
#include "Common.hlsli"

struct VertexIn
{
    float3 PosL : POSITION;
};

struct VertexOut
{
    float4 PosH : SV_POSITION;
};

VertexOut VS(VertexIn vin)
{
    VertexOut vout = (VertexOut) 0.0f;

    MATERIAL matData = material;
    
    // Transform to world space.
    float4 posW = mul(float4(vin.PosL, 1.0f), gmtxWorld);

    // Transform to homogeneous clip space.
    vout.PosH = mul(posW, gmtxShadowTransform);
    
    return vout;
}

// This is only used for alpha cut out geometry, so that shadows 
// show up correctly.  Geometry that does not need to sample a
// texture can use a NULL pixel shader for depth pass.
void PS(VertexOut pin)
{
    // Fetch the material data.
    MATERIAL matData = material;
    float4 diffuseAlbedo = matData.DiffuseAlbedo;
}

渲染过程的Default.hlsl (韩语评论很少。不重要)

代码语言:javascript
运行
复制
#include "Common.hlsli"

//정점 셰이더의 입력을 위한 구조체를 선언한다.
struct VS_DEFAULT_INPUT
{
    float3 position : POSITION;
    float3 normal : NORMAL;
};

//정점 셰이더의 출력(픽셀 셰이더의 입력)을 위한 구조체를 선언한다.
struct VS_DEFAULT_OUTPUT
{
    float4 position : SV_POSITION;
    float4 position_shadow : POSITION0;
    float3 position_w : POSITION1;
    float3 normal : NORMAL;
};


VS_DEFAULT_OUTPUT VS_Default(VS_DEFAULT_INPUT input)
{
    VS_DEFAULT_OUTPUT output;
    output.position = mul(mul(float4(input.position, 1.0f), gmtxWorld), gmtxViewProj);
    output.position_w = mul(float4(input.position, 1.0f), gmtxWorld).xyz;
    output.normal = normalize(mul(float4(input.normal, 0.0f), gmtxWorld).xyz);
    output.position_shadow = mul(float4(output.position_w, 1.0f), gmtxShadowTransform);
    
    return (output);
}

float4 PS_Default(VS_DEFAULT_OUTPUT input) : SV_TARGET
{
    float4 cColor = float4(0.0f, 0.0f, 0.0f, 0.0f);
    
    cColor += material.AmbientLight * material.DiffuseAlbedo;
    
    float3 toEyeW = normalize(cameraPos - input.position_w);
    
    float3 shadowFactor = float3(1.0f, 1.0f, 1.0f);
    shadowFactor[0] = CalcShadowFactor(input.position_shadow);
    
    for (int i = 0; i < nLights; i++)
    {
        cColor += ComputeLighting(light[i], input.position_w, input.normal, toEyeW, shadowFactor[0]);
    }
    // Add in specular reflections.
    
    float3 r = reflect(-toEyeW, input.normal);
    float4 reflectionColor = { 1.0f, 1.0f, 1.0f, 0.0f };
    
    float3 fresnelFactor = SchlickFresnel(material.FresnelR0, input.normal, r);
    cColor.rgb += material.Shininess * fresnelFactor * reflectionColor.rgb;
    
    // Common convention to take alpha from diffuse albedo.
    
    cColor.a = material.DiffuseAlbedo.a;
    
    
    return (cColor);
}

GitHub链接:https://github.com/kcjsend2/3DGP-BulletPhysics

子弹头物理引擎包括在内,因此子弹头引擎将需要接收并连接到项目以建立。

有关示例,请参阅弗兰克·露娜的“使用DirectX12进行3d游戏编程简介”中的第20章“阴影映射”。

框架是独立的,所以它与示例有很大的不同。

子弹头物理引擎包括在内,因此子弹头引擎将需要接收并连接到项目以建立。

EN

回答 2

Stack Overflow用户

发布于 2021-08-28 14:09:41

我修好了。因为hlsl着色器和direct x使用了不同类型的矩阵。hlsl着色器使用主要列,而直接x使用主要行矩阵。我也用矩阵乘法的顺序来计算错误。

worng是问题的第一个密码

...and这是固定代码:

代码语言:javascript
运行
复制
XMVECTOR lightPos = XMLoadFloat3(&m_pLight->GetPosition());
    XMVECTOR TargetPos = XMLoadFloat3(&xmf3TargetPos);
    XMVECTOR lightUp = XMLoadFloat3(&m_pLight->GetUp());

    XMMATRIX lightView = XMMatrixLookAtLH(lightPos, TargetPos, lightUp);

    /*XMVECTOR lightLook = Vector3::Normalize(lightPos - TargetPos);*/

    // Transform bounding sphere to light space.
    XMFLOAT3 xmf3CenterLS;
    XMStoreFloat3(&xmf3CenterLS, XMVector3TransformCoord(XMLoadFloat3(&xmf3TargetPos), lightView));

    // Ortho frustum in light space encloses scene.

    float l = xmf3CenterLS.x - 800;
    float b = xmf3CenterLS.y - 800;
    float n = xmf3CenterLS.z - 800;
    float r = xmf3CenterLS.x + 800;
    float t = xmf3CenterLS.y + 800;
    float f = xmf3CenterLS.z + 800;

    XMMATRIX lightProj = XMMatrixOrthographicOffCenterLH(l, r, b, t, n, f);

    // Transform NDC space [-1,+1]^2 to texture space [0,1]^2
    XMMATRIX T(
        0.5f, 0.0f, 0.0f, 0.0f,
        0.0f, -0.5f, 0.0f, 0.0f,
        0.0f, 0.0f, 1.0f, 0.0f,
        0.5f, 0.5f, 0.0f, 1.0f);

    XMMATRIX S = lightView * lightProj;

    XMFLOAT4X4 xmf4x4LightViewProj;
    XMStoreFloat4x4(&xmf4x4LightViewProj, XMMatrixTranspose(S));

    S = S * T;

    XMFLOAT4X4 xmf4x4ShadowTransform;
    XMStoreFloat4x4(&xmf4x4ShadowTransform, XMMatrixTranspose(S));

    CB_SHADOW cbShadow{ xmf4x4ShadowTransform, xmf4x4LightViewProj, m_pLight->GetPosition() };

    m_ubShadowCB->CopyData(0, cbShadow); 
    pd3dCommandList->SetGraphicsRootConstantBufferView(3, m_ubShadowCB->Resource()->GetGPUVirtualAddress());
票数 0
EN

Stack Overflow用户

发布于 2021-09-28 11:34:25

当我没有转置发送到着色器的矩阵时,我遇到了完全相同的问题,然后我转置了它,它工作了。:)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68939246

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档