Jump to content

  • Log In with Google      Sign In   
  • Create Account


Sprites, primitives and depth testing


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
5 replies to this topic

#1 benp444   Members   -  Reputation: 177

Like
0Likes
Like

Posted 04 July 2012 - 08:08 AM

Hi,
I am trying to draw both sprites and 2d primitives on the screen at the same time and am having problems with the depth. The primitives are created using D3D10_PRIMITIVE_TOPOLOGY_LINESTRIP.

There are two situations that I can have. Note that the rectangles have a depth of 0.5, the left hand ball of 0.2 and the two balls on the right 0.6:

1) Depth Enabled: the sprites render correctly based on the assigned depth. However the alpha channels of the sprite show up.

DepthEnabled.png



2) Depth Disabled: the primitives and sprites do not render correctly on depth. If the sprites are the last group to be drawn the they will be on top and visa versa

DepthDisabled.png

During initialisation have created two depth stencils:

[source lang="cpp"]//Create a disabled depth state SAFE_RELEASE(m_pDepthDisabledState); D3D10_DEPTH_STENCIL_DESC depthStencilDesc; ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc)); depthStencilDesc.DepthEnable = false; depthStencilDesc.DepthWriteMask = D3D10_DEPTH_WRITE_MASK_ALL; depthStencilDesc.DepthFunc = D3D10_COMPARISON_LESS; depthStencilDesc.StencilEnable = false; depthStencilDesc.StencilReadMask = 0xFF; depthStencilDesc.StencilWriteMask = 0xFF; depthStencilDesc.FrontFace.StencilFailOp = D3D10_STENCIL_OP_KEEP; depthStencilDesc.FrontFace.StencilDepthFailOp = D3D10_STENCIL_OP_INCR; depthStencilDesc.FrontFace.StencilPassOp = D3D10_STENCIL_OP_KEEP; depthStencilDesc.FrontFace.StencilFunc = D3D10_COMPARISON_ALWAYS; depthStencilDesc.BackFace.StencilFailOp = D3D10_STENCIL_OP_KEEP; depthStencilDesc.BackFace.StencilDepthFailOp = D3D10_STENCIL_OP_DECR; depthStencilDesc.BackFace.StencilPassOp = D3D10_STENCIL_OP_KEEP; depthStencilDesc.BackFace.StencilFunc = D3D10_COMPARISON_ALWAYS; hr = DXUTGetD3D10Device()->CreateDepthStencilState(&depthStencilDesc, &m_pDepthDisabledState); //Create an enabled depth state SAFE_RELEASE(m_pDepthEnabledState); depthStencilDesc.DepthEnable = true; //the only difference hr = DXUTGetD3D10Device()->CreateDepthStencilState(&depthStencilDesc, &m_pDepthEnabledState); //set to disabled by default. DXUTGetD3D10Device()->OMSetDepthStencilState(m_pDepthDisabledState, 0); //DXUTGetD3D10Device()->OMSetDepthStencilState(m_pDepthEnabledState, 0);[/source]
I have tried switching between depth enabled/disabled during the rendering of either the primitives or the sprites but it seems and cannot mix and match the two. Has anyone any ideas what approach I should take to solve this?

Thanks,

Ben.

Sponsor:

#2 NightCreature83   Crossbones+   -  Reputation: 2689

Like
1Likes
Like

Posted 04 July 2012 - 10:29 AM

If you turn depth testing off rendering is done in the order you submit the draw calls in, so say you have two objects that overlap and one is at 0.1 and the other is at 0.2 depth. With depth testing on and rendering the 0.1 object first that would be the object you see, when it is off however the one with 0.2 is rendered last and will overlap the other one.

Are you sure you aren't changing the alpha blend equations as well? If you render something thats changing the Alpha blend state before or after this draw call when you next come to this drawcall the alpha state will not have reset itself.
Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, Mad Max

#3 benp444   Members   -  Reputation: 177

Like
0Likes
Like

Posted 04 July 2012 - 11:30 AM

Thanks for your response.

If you turn depth testing off rendering is done in the order you submit the draw calls in, so say you have two objects that overlap and one is at 0.1 and the other is at 0.2 depth. With depth testing on and rendering the 0.1 object first that would be the object you see, when it is off however the one with 0.2 is rendered last and will overlap the other one.


My calls to draw may not come in an order based on depth so I really want to keep depth testing on. However this approach results in image 1) shown in my original post.

Are you sure you aren't changing the alpha blend equations as well? If you render something thats changing the Alpha blend state before or after this draw call when you next come to this drawcall the alpha state will not have reset itself.


I don't know much about the alpha blending. I have posted my code below that handles the alpha channel. Again looking at image 1); are you suggesting that this problem may have nothing to do with depth testing and that I should be looking at my alpha code? Apart from the initialisation code below and the rendering code that follows I don't touch the alpha set up. Perhaps my Alpha setup is wrong?

More initialisation code wrt alpha:

[source lang="cpp"] D3D10_BLEND_DESC StateDesc; ZeroMemory(&StateDesc, sizeof(D3D10_BLEND_DESC)); StateDesc.AlphaToCoverageEnable = TRUE; //changed from FALSE 040712 StateDesc.BlendEnable[0] = TRUE; StateDesc.SrcBlend = D3D10_BLEND_SRC_ALPHA; StateDesc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA; StateDesc.BlendOp = D3D10_BLEND_OP_ADD; StateDesc.SrcBlendAlpha = D3D10_BLEND_ZERO; StateDesc.DestBlendAlpha = D3D10_BLEND_ZERO; StateDesc.BlendOpAlpha = D3D10_BLEND_OP_ADD; StateDesc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL; hr=pD3DDevice->CreateBlendState(&StateDesc, &m_pBlendState10);[/source]
And the code that renders the sprites:

[source lang="cpp"]hr = m_pSpriteObject->SetProjectionTransform(&(g_pGameManager->m_pMatProjection));// start drawing the spriteshr=m_pSpriteObject->Begin(D3DX10_SPRITE_SORT_DEPTH_BACK_TO_FRONT); //D3DX10_SPRITE_SORT_DEPTH_FRONT_TO_BACK,D3DX10_SPRITE_SORT_DEPTH_BACK_TO_FRONT//Save the current blend stateID3D10BlendState* pOrigBlendState;DXUTGetD3D10Device()->OMGetBlendState(&pOrigBlendState, OriginalBlendFactor, &OriginalSampleMask);// Draw all the sprites in the poolhr=m_pSpriteObject->DrawSpritesBuffered(&(m_spritePool[0]), m_spritePoolIdx);// Set the blend state for alpha drawingif(m_pBlendState10){ FLOAT NewBlendFactor[4] = {1,1,1,1}; DXUTGetD3D10Device()->OMSetBlendState(m_pBlendState10, NewBlendFactor, 0xffffffff);}// Finish up and send the sprites to the hardwarehr=m_pSpriteObject->Flush();hr=m_pSpriteObject->End();DXUTGetD3D10Device()->OMSetBlendState(m_pBlendState10, OriginalBlendFactor, OriginalSampleMask);[/source]
Note: I am checking all my Direct X calls. I have just removed them for clarity.

#4 Dancin_Fool   Members   -  Reputation: 581

Like
1Likes
Like

Posted 04 July 2012 - 11:55 AM

With depth testing enabled, the drawing order for alpha objects matter. The problem you're seeing is caused by the first object filling the depth buffer with a quad so when the second object which is behind draws it's tested against the depth buffer which contains a quad so that area is clipped out rather than alpha blended with the object in front of it.

This is a common problem with alpha blending. What you want to do is sort your objects from back to front before you render them. Even if you are submitting these objects out of order, if you queue them up in a buffer you can sort that buffer before you actually submit them to be rendered.

#5 benp444   Members   -  Reputation: 177

Like
0Likes
Like

Posted 04 July 2012 - 02:05 PM

With depth testing enabled, the drawing order for alpha objects matter. The problem you're seeing is caused by the first object filling the depth buffer with a quad so when the second object which is behind draws it's tested against the depth buffer which contains a quad so that area is clipped out rather than alpha blended with the object in front of it.

This is a common problem with alpha blending. What you want to do is sort your objects from back to front before you render them. Even if you are submitting these objects out of order, if you queue them up in a buffer you can sort that buffer before you actually submit them to be rendered.


OK. So for sprites the following line sorts the buffer:

m_pSpriteObject->Begin(D3DX10_SPRITE_SORT_DEPTH_BACK_TO_FRONT);

I will however have to ensure that no two sprites have the same depth; in image 1) both sprites were 0.6. Thats fine I can write a trivial bit of code that takes the user defined depth and adds 0.0001 to it so that it is highly unlikely two sprites will have the same depth.

I was going to say that I still had a problem with the primitives (which are drawn at a depth of 0.5). However I found that if I draw the primitives before the sprites (which may be shallower or deeper than sprites) then there is no clipping and all the depth is correct. I can't quite understand why this works as the ordering is not as discussed but it does.

Successful depth enabled sprites and primitives below:
DepthEnabledWorks.png

Thanks both for you help.

Ben.

#6 Dancin_Fool   Members   -  Reputation: 581

Like
0Likes
Like

Posted 04 July 2012 - 03:33 PM

The reason for why the primitives need to be drawn before the alpha objects is the same as for why you have to sort the alpha objects. If you draw the primitives after the alpha objects and you had depth writes on for the alpha objects, then you're still going to have the problem of the alpha object writing a quad to the depth buffer and the primitives testing against that quad when it's rendered and essentially clipping out the primitive.

Glad to see you have it working though!




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS