【问题标题】:PSSetSamplers doens't work (The Pixel Shader unit expects a Sampler)PSSetSamplers 不起作用(像素着色器单元需要一个采样器)
【发布时间】:2016-11-28 14:56:18
【问题描述】:

我是 directx11 的新手,我想为我正在使用的着色器添加纹理。 (到目前为止,我还没有在directx11中使用过任何纹理)

但是采样似乎不起作用(它总是 float4(0,0,0,0)),我收到警告:“D3D11 WARNING: ID3D11DeviceContext::DrawIndexed: The Pixel Shader unit requires a Sampler to be设置在 Slot 0,但没有绑定。"

我搜索了这个,但所有答案都说要使用

_d3dContext->PSSetSamplers(0, 1, &_sampler);

但我已经这样做了。 有谁知道可能出了什么问题?

这是我的整个着色器:

Texture2D tex;
SamplerState TexSampler : register(S0)
{
    Texture = (Slope);
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = clamp;
    AddressV = clamp;
};

struct PixelShaderInput
{
    float4 color : COLOR0;
    //.r : slope
    //.g : relative distance on road (compared the the rider)
    //.b : shadow (currently darker on lower parts)
    //.a : cameradepth
    float fogfactor : COLOR1;
};

float4 main(PixelShaderInput input) : SV_TARGET
{
    const float4 fogColor = float4(0.9, 0.9, 1, 1);

    const float halfWidth = 0.0016f;

    float4 color;

    if (input.color.g < -halfWidth * input.color.a)
    {
        color = float4(0.5, 0.85, 1, 1);
    }
    else if (input.color.g < halfWidth * input.color.a)
    {
        color = float4(1, 1, 1, 1);
    }
    else
    {
        color = tex.Sample(TexSampler, float2(input.color.r, 0.5));
    }

    if (input.color.b < 0.999)
    {
        input.color.b *= 0.94; //makes the sides a bit darker
    }
    color.rgb *= input.color.b;

    color.rgb = lerp(color.rgb, fogColor.rgb, input.fogfactor);

    return color;
}

在 c++/cx 中我这样做(不是完整的代码,只是片段):

Microsoft::WRL::ComPtr<ID3D11ShaderResourceView>    _slopeGradient;
Microsoft::WRL::ComPtr<ID3D11SamplerState>          _sampler;

D3D11_SAMPLER_DESC sampDesc;
ZeroMemory(&sampDesc, sizeof(sampDesc));
sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
sampDesc.MinLOD = 0;
sampDesc.MaxLOD = D3D11_FLOAT32_MAX;
_d3dDevice->CreateSamplerState(&sampDesc, &_sampler);

_d3dContext->PSSetShaderResources(0, 1, &_slopeGradient);
_d3dContext->PSSetSamplers(0, 1, &_sampler);

【问题讨论】:

    标签: shader directx-11 hlsl c++-cx pixel-shader


    【解决方案1】:

    问题在于您对ComPtr 的使用。 Microsoft::WRL::ComPtroperator&amp; 重载调用 ReleaseAndGetAddressOf,而不是 GetAddressOf。因此,您现在基本上正在执行此操作,始终将这些资源设置为nullptr(即清除插槽):

    _d3dContext->PSSetShaderResources(0, 1, _slopeGradient.ReleaseAndGetAddressOf());
    _d3dContext->PSSetSamplers(0, 1, _sampler.ReleaseAndGetAddressOf());
    

    你应该使用:

    _d3dContext->PSSetShaderResources(0, 1, _slopeGradient.GetAddressOf());
    _d3dContext->PSSetSamplers(0, 1, _sampler.GetAddressOf());
    

    旧的 ATL CComPtroperator&amp; 重载映射到GetAddressOf 但断言它是一个空指针,这通常会导致无意的内存泄漏。 operator&amp; 被假定用于这些智能指针的初始化,这不是您在这里所做的。你真的想要初始化的原始指针的地址。

    请记住,这两种方法实际上都是采用 COM 指针数组。在 C 中,您当然可以将指针视为大小为 1 的数组,但您可能会发现执行以下操作更清楚:

    ID3D11ShaderResourceView* srvs[] = { _slopeGradient.GetAddressOf() };
    _d3dContext->PSSetShaderResources(0, _countof(srvs), srvs);
    
    ID3D11SamplerState* samplers[] = { _sampler.GetAddressOf() };
    _d3dContext->PSSetSamplers(0, _countof(samplers), samplers);
    

    另请注意,您在 HLSL 源中定义了旧版 Effects system 的一些元素,这些元素在标准 DirectX API 使用中被忽略。你可以直接删除它。

    {
        Texture = (Slope);
        Filter = MIN_MAG_MIP_LINEAR;
        AddressU = clamp;
        AddressV = clamp;
    }
    

    由于您是 DirectX 11 的新手,您应该查看DirectX Tool Kit

    【讨论】:

    • 谢谢,我不知道。我改变了它,现在警告消失了,但我得到了相同的视觉结果。任何的想法?我必须承认,不幸的是,我是 c++/cx 和 directx11 的新手。我实际上开始使用 DirectXTK,但它似乎与我已经拥有的东西有点不同,我正在尝试将它结合起来,但我似乎无法让它发挥作用。
    • 图形调试具有挑战性,因为它有很多方法会出错并最终出现空白屏幕。请注意,DirectX 11 是一个 COM API,因此无论您使用 C++/CX 还是纯 C++ 都没有关系,因为它在所有 Direct3D 平台上都是相同的。您可能希望独立于当前项目完成 DirectX 工具包教程,然后在掌握了相关知识后返回。
    • 我认为这确实是最好的做法。感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 2013-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-15
    • 2017-08-29
    • 1970-01-01
    相关资源
    最近更新 更多