PSSetSamplers не работает (модуль Pixel Shader ожидает Sampler)

Я очень новичок в DirectX11, и я хотел добавить текстуру в шейдер, который я использую. (до сих пор я не использовал никакой текстуры в DirectX11)

Но выборка, похоже, не работает (это всегда float4(0,0,0,0)), и я получаю предупреждение: "D3D11 ПРЕДУПРЕЖДЕНИЕ: ID3D11DeviceContext::DrawIndexed: модуль Pixel Shader ожидает, что Sampler будет установлен в слот 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);

1 ответ

Решение

Проблема в том, что вы используете ComPtr. operator& перегрузка для Microsoft::WRL::ComPtr звонки 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 CComPtr имел operator& карта перегрузки вGetAddressOf но утверждал, что это был nullptr, который часто приводил к непреднамеренным утечкам памяти. operator& предполагается, что эти умные указатели будут использоваться при инициализации, но это не то, что вы здесь делаете. Вы действительно хотите адрес инициализированного необработанного указателя.

Помните, что оба эти метода на самом деле принимают массив указателей COM. В C вы, конечно, можете обращаться с указателем как с массивом размера один, но вам может показаться более понятным сделать что-то вроде:

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

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

Также обратите внимание, что вы определяете некоторые элементы устаревшей системы эффектов в исходном коде HLSL, которые игнорируются при стандартном использовании DirectX API. Вы можете просто удалить его.

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

Поскольку вы новичок в DirectX 11, вы должны взглянуть на DirectX Tool Kit.

Другие вопросы по тегам