PSSetSamplers 不起作用(像素着色器单元需要一个采样器)
PSSetSamplers doens't work (The Pixel Shader unit expects a Sampler)
我是 directx11 的新手,我想为我正在使用的着色器添加纹理。
(到目前为止,我还没有在 directx11 中使用任何纹理)
但采样似乎不起作用(它始终是 float4(0,0,0,0)),我收到警告:"D3D11 WARNING: ID3D11DeviceContext::DrawIndexed: The Pixel Shader unit expects a Sampler to be set at Slot 0, but none is bound."
我搜索过这个,但所有答案都说使用
_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);
问题是您对 ComPtr 的使用。 Microsoft::WRL::ComPtr
的 operator&
重载调用 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());
The old ATL CComPtr
had the operator&
overload map toGetAddressOf
but asserted that it was a nullptr which often resulted in inadvertent memory leaks. The operator&
is assumed to be used in initialization by these smart-pointers, and that's not what you are doing here. You really want the address of the initialized raw pointer.
请记住,这两种方法实际上都采用 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;
}
As you are new to DirectX 11, you should look at DirectX Tool Kit.
我是 directx11 的新手,我想为我正在使用的着色器添加纹理。 (到目前为止,我还没有在 directx11 中使用任何纹理)
但采样似乎不起作用(它始终是 float4(0,0,0,0)),我收到警告:"D3D11 WARNING: ID3D11DeviceContext::DrawIndexed: The Pixel Shader unit expects a Sampler to be set at Slot 0, but none is bound."
我搜索过这个,但所有答案都说使用
_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);
问题是您对 ComPtr 的使用。 Microsoft::WRL::ComPtr
的 operator&
重载调用 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());
The old ATL
CComPtr
had theoperator&
overload map toGetAddressOf
but asserted that it was a nullptr which often resulted in inadvertent memory leaks. Theoperator&
is assumed to be used in initialization by these smart-pointers, and that's not what you are doing here. You really want the address of the initialized raw pointer.
请记住,这两种方法实际上都采用 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;
}
As you are new to DirectX 11, you should look at DirectX Tool Kit.