问题描述
我有一个DirectX 11 C ++应用程序,显示两个矩形与纹理和一些文本。
这两个纹理都是从TGA资源(添加了alpha通道)中获取的。
I have an DirectX 11 C++ application that displays two rectangles with textures and some text.Both textures are taken from TGA resources (with alpha channel added).
当我运行程序时,我得到结果:
When I run the program, I get the result:
有什么问题?仔细观察一下:
What's wrong? Take a closer look:
矩形的角是透明的(它们应该是)。
The corners of the rectangles are transparent (and they should be). The rest of textures are set to be 30% opacity (and it works well too).
但是,当一个纹理(让我们称之为 )时,纹理的其他部分设置为30%不透明度>)超过另一个( texture2 ):
But, when one texture (let's call it texture1) is over another (texture2):
换句话说,透明度纹理与窗口背景相互作用,而不是背后的纹理。
我做错了什么?
What have I done wrong? What part of my program can be responsible for it? Blending options, render states, shader code...?
在我的着色器中,我设置: / p>
In my shader, I set:
technique10 RENDER{
pass P0{
SetVertexShader(CompileShader( vs_4_0, VS()));
SetPixelShader(CompileShader( ps_4_0, PS()));
SetBlendState(SrcAlphaBlendingAdd, float4(0.0f, 0.0f, 0.0f, 0.0f),
0xFFFFFFFF);
}
}
当然,当我将窗口的背景从蓝色改为另一种颜色时,元素仍然具有透明度(边角不是蓝色)。
P.s.Of course, when I change the background of window from blue to another colour, the elements still have the transparency (the corners aren't blue).
编辑:
根据 @ComicSansMS
无论如何,p),我试图改变渲染元素的顺序(我也移动了较小的纹理,以检查错误是否仍然存在):
According to @ComicSansMS
(+ for nick, anyway ;p ), I've tried to change to order of render elements (I've also moved the smaller texture a bit, to check if the error remains):
较小的纹理现在在更大的后面。但是角落的问题仍然存在(现在它出现在第二个纹理上)。 我几乎可以肯定,在我渲染上面的矩形之前我绘制矩形(我看到代码的行顺序)。
The smaller texture is now behind the bigger one. But the problem with corners remains (now it appears on the second texture). I am almost sure that I draw the rectangle behind BEFORE I render the rectangle above (I see the code's lines order).
我的深度模板:
//initialize the description of the stencil state
ZeroMemory(depthStencilsDescs, sizeof(*depthStencilsDescs));
//set up the description of the stencil state
depthStencilsDescs->DepthEnable = true;
depthStencilsDescs->DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
depthStencilsDescs->DepthFunc = D3D11_COMPARISON_LESS;
depthStencilsDescs->StencilEnable = true;
depthStencilsDescs->StencilReadMask = 0xFF;
depthStencilsDescs->StencilWriteMask = 0xFF;
//stencil operations if pixel is front-facing
depthStencilsDescs->FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilsDescs->FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
depthStencilsDescs->FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilsDescs->FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
//stencil operations if pixel is back-facing
depthStencilsDescs->BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilsDescs->BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
depthStencilsDescs->BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilsDescs->BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
//create the depth stencil state
result = device->CreateDepthStencilState(depthStencilsDescs, depthStencilState2D);
渲染函数:
...
//clear the back buffer
context->ClearRenderTargetView(myRenderTargetView, backgroundColor); //backgroundColor
//clear the depth buffer to 1.0 (max depth)
context->ClearDepthStencilView(depthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);
context->OMSetDepthStencilState(depthStencilState2D, 1);
context->VSSetShader(getVertexShader(), NULL, 0);
context->PSSetShader(getPixelShader(), NULL, 0);
for(...){
rectangles[i]->render();
}
混合状态:
D3D11_BLEND_DESC blendDesc;
ZeroMemory(&blendDesc, sizeof(D3D11_BLEND_DESC) );
blendDesc.AlphaToCoverageEnable = false;
blendDesc.IndependentBlendEnable = false;
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_ONE;
blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE;
blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL ;
ID3D11BlendState * blendState;
if (FAILED(device->CreateBlendState(&blendDesc, &blendState))){
}
context->OMSetBlendState(blendState,NULL,0xffffffff);
推荐答案
您的绘图顺序可能是错误的。
Your draw order is probably wrong.
混合不与其后面的对象的像素交互,它与当前帧缓冲区中的像素交互。
Blending does not interact with the pixels of the object behind it, it interacts with the pixels that are currently in the frame buffer.
所以如果你在前面的矩形前面绘制矩形,它的混合操作将会与帧缓冲区中的那一点(即背景)进行交互。
So if you draw the rectangle in front before the rectangle in the back, its blending operation will interact with what is in the frame buffer at that point (that is, the background).
解决方案显然是通过它们在视图空间中的深度来对对象进行排序,并从后向前绘制,尽管这有时说起来容易做起来(特别是允许任意重叠时)。
The solution is obviously to sort your objects by their depth in view space and draw from back-to-front, although that is sometimes easier said than done (especially when allowing arbitrary overlaps).
另一个问题似乎是你绘制两个矩形在相同的深度值。您的深度测试设置为 D3D11_COMPARISON_LESS
,因此在像素上绘制三角形后,另一个三角形将无法对该像素进行深度测试,并且不会绘制在所有。这将解释在交换绘图顺序时获得的结果。
The other problem seems to be that you draw both rectangles at the same depth value. Your depth test is set to D3D11_COMPARISON_LESS
, so as soon as a triangle is drawn on a pixel, the other triangle will fail the depth test for that pixel and won't get drawn at all. This is explains the results you get when swapping the drawing order.
请注意,如果您将对象从后向前绘制,则不需要执行深度测试,所以你可能只是想在这种情况下关闭它。或者,您可以尝试通过给它们不同的Z值来沿深度轴排列对象,或者只是切换到 D3D11_COMPARISON_LESS_EQUAL
进行深度测试。
Note that if you draw objects back-to-front there is no need to perform a depth test at all, so you might just want to switch it off in this case. Alternatively, you can try to arrange the objects along the depth axis by giving them different Z values, or just switch to D3D11_COMPARISON_LESS_EQUAL
for the depth test.
这篇关于在DirectX中的两个矩形上的透明度,一个在另一个之后 - 我看到窗口的背景而不是第二个纹理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!