我有一个应用程序可以在本质上是 2D 上下文中渲染多个纹理四边形(图像),效果很好。然而,在修改它以使某些纹理的部分透明之后,我停下来试图让它以一种看似标准的、理论上简单的方式表现:我只是希望它按顺序绘制纹理(就像它一直在做的那样),并且当纹理具有透明像素时,显示之前在这些点中绘制的任何内容。
但它所做的是在透明部分后面显示每个先前绘制的纹理的缩放版本,而不是渲染目标的先前渲染部分。因此,例如,如果我尝试绘制一个不透明的背景纹理,然后绘制一个较小的完全透明的纹理,那么背景会绘制得很好,但是透明图像会显示整个背景缩放到新透明图像的大小/位置。
随后的渲染纹理以这种方式继续,显示之前渲染的纹理最终结果(包括它之前的纹理中的元素)。
我显然遗漏了一些关于 DirectX 中的纹理/像素着色器如何工作的基本知识(这并不奇怪,因为我对它比较陌生),但是在阅读了所有在线内容之后,我可以搜索并以无数种方式进行实验,我仍然无法弄清楚我需要做什么。
我在像素着色器中使用了一个纹理,这可能是问题的一部分,也可能不是问题的一部分。每次渲染场景时,我都会循环遍历所有要渲染的纹理,调用 PSSetShaderResources() 将不同的纹理绑定到该像素着色器纹理,每次循环,并在每次更改后调用 DrawIndexed()。这似乎是一种有效的方法,因为当像素着色器似乎无法使用任意一个着色器时,拥有大量着色器纹理似乎没有意义(它需要预编译,不?)。
无论如何,我希望这些症状足以让比我更有知识的人立即意识到我所犯的错误。这些领域的代码非常简单,但我不妨包括几个部分:
曾经的场景,对于每个着色器RV:
m_pd3d11ImmDevContext->PSSetShaderResources(0, 1, &shaderRV);
m_pd3d11ImmDevContext->DrawIndexed( ... )
着色器:
Texture2D aTexture : register(t0);
SamplerState samLinear : register(s0);
struct VS_INPUT
{
float3 position : POSITION;
float3 texcoord0 : TEXCOORD0;
};
struct VS_OUTPUT
{
float4 hposition : SV_POSITION;
float3 texcoord0 : TEXCOORD0;
};
struct PS_OUTPUT
{
float4 color : COLOR;
};
// vertex shader
VS_OUTPUT CompositeVS( VS_INPUT IN )
{
VS_OUTPUT OUT;
float4 v = float4( IN.position.x,
IN.position.y,
0.1f,
1.0f );
OUT.hposition = v;
OUT.texcoord0 = IN.texcoord0;
OUT.texcoord0.z = IN.position.z ;
return OUT;
}
// pixel shader
PS_OUTPUT CompositePS( VS_OUTPUT IN ) : SV_Target
{
PS_OUTPUT ps;
ps.color = aTexture.Sample(samLinear, IN.texcoord0);
return ps;
}
混合描述设置(不要认为问题出在此处): blendDesc.RenderTarget[0].BlendEnable = true;
blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO;
blendDesc.RenderTarget[0].DestBlendAlpha= D3D11_BLEND_ZERO;
blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
请让我知道是否有任何其他代码段有用!