简体   繁体   中英

Rendering two smaller textures onto a bigger texture

When I render a two textures onto a bigger texture.

Consider:

  • ID3D10Texture2D A
    • ID3D10Texture2D B
    • ID3D10Texture2D C

If I first draw Texture B, the full width of Texture A and then draw Texture C only on half of Texture A . Why is that Texture C is erasing the area of itself from Texture B?

I then draw Texture A onto the backbuffer to see the results.

在此处输入图片说明

I did some additional testing and found out that the alpha of Texture C is also affecting the alpha of Texture B such that if the alpha of texture C is too low, you can't really see texture B. How can such an issue be resolved? In fact, how could this even be an issue? Because, I rendered C after B. ##

blendDesc.BlendEnable[0] = TRUE;
blendDesc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
blendDesc.SrcBlend = D3D10_BLEND_SRC_ALPHA;
blendDesc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
blendDesc.BlendOp = D3D10_BLEND_OP_ADD;
blendDesc.SrcBlendAlpha = D3D10_BLEND_ONE;
blendDesc.DestBlendAlpha = D3D10_BLEND_ZERO;
blendDesc.BlendOpAlpha = D3D10_BLEND_OP_ADD;

hr = aDXDevice->CreateBlendState(&blendDesc, &this->g_pBlendState);

在此处输入图片说明 NOTE: Texture B spans the full width, but texture C is only placed halfway ontop of texture B. Since Texture B is the solid red image, texture C + texture B should NOT be transparent.

Not pretend to be an answer, it's just a guess.

Possible cause of blending issue is a proliferation of states into next draw call.

All DirectX (and also GL) states are not being reset on end of frame, they persists until changed or context reset.

So, probably you have a blend state

hr = aDXDevice->CreateBlendState(&blendDesc, &this->g_pBlendState);

and you applying it after drawing B, but before drawing C:

DrawB();
aDXDevice->OMSetBlendState(&g_pBlendState, ...);
DrawC();

First frame draws as you expect, but on next frames g_pBlendState is still active. So B drawing without alpha only on a first frame.

What you need is two blend states, one for each blending mode, and apply it each frame:

aDXDevice->CreateBlendState(&blendDescForB, &blendStateForB); // no alpna
aDXDevice->CreateBlendState(&blendDescForC, &blendStateForC); // alpha enabled

aDXDevice->OMSetBlendState(blendStateForB, ...);
DrawB();
aDXDevice->OMSetBlendState(blendStateForC, ...);
DrawC();

For quick debugging of that issue you can try to apply ID3D10Device::ClearState after Present() . But just for debugging.

Note, that there are one point counter my hypothesis: blending of A not being touched.

Not sure of exact details but remember that OpenGL is a 3D library do it takes into account depth when it comes to determining which object occlude other objects. OpenGL also uses floating point numbers for vertices which means even if the numbers look equal then many well not be. The only safe way to ensure that one object is in front of the other is to draw it so. For 2D drawing generally, it is best to ensure that your objects to not overlap at all.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM