🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Texture transparency doesn't work correctly in DirectX 11

Started by
5 comments, last by Juliean 3 years, 8 months ago

Hello, i am trying to render a model with a texture that is transparent, i got transparency to work, however when i look through the part of the model that is transparent, i can't see what is behind it, it just cuts off everything except skybox that is behind it, an example shown here:

This is a flashlight model and where it is empty it supposed to have glass and light behind it

I am not sure what is causing it, perhaps blend state? Here is my blend state description:

D3D11_BLEND_DESC blendStateDesc;
ZeroMemory(&blendStateDescription, sizeof(D3D11_BLEND_DESC));
blendStateDesc.RenderTarget[0].BlendEnable = TRUE;
blendStateDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
blendStateDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
blendStateDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
blendStateDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
blendStateDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
blendStateDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
blendStateDesc.RenderTarget[0].RenderTargetWriteMask = 0x0f;
m_Device11->CreateBlendState(&blendStateDesc, &m_BlendStateEnable11);
float blendColor[4];
blendColor[0] = 0.0f;
blendColor[1] = 0.0f;
blendColor[2] = 0.0f;
blendColor[3] = 0.0f;
m_DeviceContext11->OMSetBlendState(m_BlendStateEnable11, blendColor, 0xffffffff);

Here is the full code of draw calls:

float bgColor[4] = { (0.0f, 0.0f, 0.0f, 0.0f) };
	m_DeviceContext11->ClearRenderTargetView(m_FrameBuffer11.renderTargetView11, bgColor);
	m_DeviceContext11->ClearDepthStencilView(m_FrameBuffer11.depthStencilView11, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);

...

m_Interface->m_Tier0->m_DirectX11->m_DeviceContext11->OMSetRenderTargets(1, &m_Interface->m_Tier0->m_DirectX11->m_FrameBuffer11.renderTargetView11, m_Interface->m_Tier0->m_DirectX11->m_FrameBuffer11.depthStencilView11);

m_Interface->m_Tier0->m_DirectX11->m_DeviceContext11->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

float blendColor[4];
blendColor[0] = 0.0f;
blendColor[1] = 0.0f;
blendColor[2] = 0.0f;
blendColor[3] = 0.0f;
m_Interface->m_Tier0->m_DirectX11->m_DeviceContext11->OMSetBlendState(m_Interface->m_Tier0->m_DirectX11->m_BlendStateEnable11, blendColor, 0xffffffff);

m_Interface->m_Tier0->m_DirectX11->m_DeviceContext11->RSSetState(m_Interface->m_Tier0->m_DirectX11->m_RasterizerStateClockwise11);
m_Interface->m_Tier0->m_DirectX11->m_DeviceContext11->VSSetConstantBuffers(0, 1, &m_Interface->m_Tier0->m_DirectX11->m_TransformBuffer11);

m_GlfwLoader->DrawModel();
m_Interface->m_Tier0->m_DirectX11->m_DeviceContext11->IASetVertexBuffers(0, 1, &m_VertexBuffer, &stride, &offset);
m_Interface->m_Tier0->m_DirectX11->m_DeviceContext11->IASetIndexBuffer(m_IndexBuffer, DXGI_FORMAT_R32_UINT, 0);

...

m_Interface->m_Tier0->m_DirectX11->m_DeviceContext11->VSSetShader(m_Interface->m_Tier0->m_DirectX11->m_Shader11->m_DefaultShader11->m_VertexShader11, nullptr, 0);
m_Interface->m_Tier0->m_DirectX11->m_DeviceContext11->PSSetShader(m_Interface->m_Tier0->m_DirectX11->m_Shader11->m_DefaultShader11->m_PixelShader11, nullptr, 0);

m_Interface->m_Tier0->m_DirectX11->m_DeviceContext11->PSSetShaderResources(0, 7, shaderResourceViews);

m_Interface->m_Tier0->m_DirectX11->m_DeviceContext11->DrawIndexed(static_cast<UINT>(m_Indices.size()), 0, 0);

And in case if there's something wrong in the shader code, there it is:

Texture2D albedoTexture : register(t0);

float4 main_ps(PixelShaderInput pin) : SV_Target
{
	float3 albedo = albedoTexture.Sample(defaultSampler, pin.texcoord).rgb;
	
	...
	
	return float4(directLighting + ambientLighting, albedoTexture.Sample(defaultSampler, pin.texcoord).a);
}
Advertisement

Are you disabling depthbuffer-writes for your transparent object, and actually making sure that transparent objects are rendered after the opagues?

Juliean said:

Are you disabling depthbuffer-writes for your transparent object, and actually making sure that transparent objects are rendered after the opagues?

No, i am not, good point as when i set depth stencil state to disable depth this problem disappears, however, obviously i don't want to render everything without depth so i need to identify when part of the model has transparency and disable depth for that while keeping it enabled for part of the models that are solid? Wouldn't that cause problems if let's say model uses just one texture and some parts of that are transparent while others are not?

CAMINOonPC said:
No, i am not, good point as when i set depth stencil state to disable depth this problem disappears, however, obviously i don't want to render everything without depth so i need to identify when part of the model has transparency and disable depth for that while keeping it enabled for part of the models that are solid? Wouldn't that cause problems if let's say model uses just one texture and some parts of that are transparent while others are not?

Yeah, thats basically what you have to do though. At some point in your pipeline you need to split opague and transparent (sub)meshes, and render opague with depth first, and transparent with back-to-front-sorting separately. There should be nothing apparently wrong happening when you have a model with some parts opague and some transparent, though how complicated this can be in terms of code/organisation might vary. I use a system where draw-commands are stored in “passes” and then sorted based on an integer-key, so this sort of stuff kind of works out-of-the box, but in a more simple scenario you might want to simply traverse everything twice and draw opague parts, then transparent.

This worked out perfectly, basically, i just made a check that checks if glTF material alpha mode is set to blend then disable depth, if otherwise, enable, thanks.

if (alphaBlend)
{
	m_Interface->m_Tier0->m_DirectX11->m_DeviceContext11->OMSetDepthStencilState(m_Interface->m_Tier0->m_DirectX11->m_DepthDisabledStencilState11, 1);
}
else
{
	m_Interface->m_Tier0->m_DirectX11->m_DeviceContext11->OMSetDepthStencilState(m_Interface->m_Tier0->m_DirectX11->m_DepthStencilState11, 1);
}

CAMINOonPC said:
This worked out perfectly, basically, i just made a check that checks if glTF material alpha mode is set to blend then disable depth, if otherwise, enable, thanks.

You must still ensure a correct draw other, if you want to get stable results though (just in case you aren't already). If you just draw models in any order, the depending on the order transparent objects might disappear (if the transparent is drawn before the opague object), or they might look wrong when multiple transparent objects are drawn on top of each other (which must happen back-to-front to look right.

This topic is closed to new replies.

Advertisement