Hi guys,
I'm trying to get grass rendering to work with DirectX 11 and I'm pretty much following this GPU Gems article: http://http.developer.nvidia.com/GPUGems/gpugems_ch07.html. Basically, at the moment I have a mesh consisting of three interleaved quads that have grass textures with transparent parts on them. I'm animating these grass objects by moving the upper vertices of the quads in the vertex shader. The article says about the grass objects: "sort them back-to-front at runtime, use alpha blending, and enable z-testing/writing in the draw call". I thought I had this set up correctly but something isn't as I get some visual errors when rendering the animated grass. More precisely, when two quads of adjacent grass objects intersect, one of them gets hidden rather than being properly blended. Also when I generally render the grass objects, some parts (on the side opposite to the camera) are not visible although the occluding quad should have transparent parts. I also don't get why some transparent parts of the textures are rendered in black instead of being actually transparent, they occlude other stuff in the application (like the grid you can see in the images below, although the grid is rendered after the grass). It's a bit difficult for me to explain, so I'm attaching three pictures to this post:
[attachment=21947:Grass1.png]
This image shows how the three quads making up the mesh of my grass objects are interleaved.
[attachment=21948:Grass2.png]
This image shows a single grass object. The more distant parts are not visible, it's pretty much just showing half the object.
[attachment=21949:Grass3.png]
This image shows how some parts of one grass object are occluded by the black parts of another one.
Here is the code, in which I set up the blending state and the depth-stencil-state for rendering of the grass.
D3D11_DEPTH_STENCIL_DESC m_grassStencilDesc;
ZeroMemory( &m_grassStencilDesc, sizeof( D3D11_DEPTH_STENCIL_DESC ) );
// Set up the description of the stencil state.
m_grassStencilDesc.DepthEnable = true;
m_grassStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
m_grassStencilDesc.DepthFunc = D3D11_COMPARISON_LESS;
m_grassStencilDesc.StencilEnable = true;
m_grassStencilDesc.StencilReadMask = 0xFF;
m_grassStencilDesc.StencilWriteMask = 0xFF;
// Stencil operations if pixel is front-facing.
m_grassStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
m_grassStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
m_grassStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
m_grassStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
// Stencil operations if pixel is back-facing.
m_grassStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
m_grassStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
m_grassStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
m_grassStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
// Create the depth stencil state.
m_pD3d11Device -> CreateDepthStencilState(&m_grassStencilDesc, &m_grassStencilState);
D3D11_BLEND_DESC m_grassBlendingStateDesc;
ZeroMemory(&m_grassBlendingStateDesc, sizeof(D3D11_BLEND_DESC));
// Create an alpha enabled blend state description.
m_grassBlendingStateDesc.RenderTarget[0].BlendEnable = TRUE;
m_grassBlendingStateDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;//D3D11_BLEND_ONE;
m_grassBlendingStateDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
m_grassBlendingStateDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
m_grassBlendingStateDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
m_grassBlendingStateDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
m_grassBlendingStateDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
m_grassBlendingStateDesc.RenderTarget[0].RenderTargetWriteMask = 0x0f;
// Create the blend state using the description.
m_pD3d11Device -> CreateBlendState( &m_grassBlendingStateDesc, &m_grassBlendingState );
I am sorting the grass object back to front, as the article suggests. To do this I compare the distance from the centre of each grass object to the camera position. When the objects are animated the quad of an object that is actually farther away from the camera might be moved towards the camera in a fashion that it is now actually placed in front of a grass object that is closer to the camera. Might this actually be the problem? Should I sort the single quads instead of the grass objects? But if so, how would I determine which quad is closer to the camera, as all three have their centre at the same position. Do you generally have any idea what's going wrong, maybe an error in the code above? I hope you guys can help me, thank you very much in advance.