我有一个应用程序,它在一个基本上是2D的上下文中渲染多个纹理四边形(图像),这个工作正常。然而,在修改它以使某些纹理的某些部分是透明的之后,我已经停下来试图让它以看似标准的,理论上简单化的方式运行:我只是想让它按顺序绘制纹理(就像它一直在做的那样) ),当纹理具有透明像素时,显示先前在这些斑点中绘制的内容。
但它正在做的是在透明部分后面显示每个先前绘制的纹理的缩放版本,而不是渲染目标的先前渲染部分。因此,例如,如果我尝试绘制不透明的背景纹理,然后绘制一个较小的完全透明的纹理,那么背景将绘制得很好,但透明图像将显示整个背景缩放到新透明图像的大小/位置。
后续渲染的纹理以这种方式继续,显示以前渲染的纹理结束的任何内容(包括 it 之前的纹理中的元素)。
我显然缺少关于DirectX中的纹理/像素着色器如何工作的基本原理(这并不奇怪,因为我对它相对较新),但在网上阅读完所有内容之后,我可以进行搜索,并以无数种方式进行实验,我仍然无法弄清楚我需要做什么。
我在像素着色器中使用了一个纹理,这可能是也可能不是问题的一部分。每次渲染场景时,我遍历我要渲染的所有纹理,调用PSSetShaderResources()将不同的纹理绑定到该像素着色器纹理,每个循环,并在每次更改后调用DrawIndexed()。看起来这是一种有效的方法,因为当像素着色器似乎无法使用任意一个时,拥有大量着色器纹理似乎没有意义(它需要预先编译,没有?)。
无论如何,我希望这些症状足以让一个比我更有知识的人立即意识到我正在犯的错误。代码在这些方面非常简单,但我可能还包括几个部分:
每个shaderRV场景:
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;
如果任何其他代码段有用,请告诉我们。