I've got a deferred + forward pipeline working in my engine.
I'm drawing them "after" the GBuffer + lighting pass to the same scene target.
DepthWrite is enabled, AlphaBlend enabled and I'm drawing the backfaces first, then the front faces.
Still when I move the camera like this it's basically ignoring the depth test (or so it seems) and just blends this with the opaque object in front of it.
Blending is not enabled during GBuffer stage, only additive blending during lighting.
Here's the problem:
Cube on the left is transparent, right one opaque.
Transparent sorting itself works fine. The problem is only when they get in contact with opaque geometry in front of them.
Shouldn't the depth test tell it that this pixel should be discarded becaused the opaque geometry is in front of it ?
Transparents are being drawn "after" the opaques after all...
Here's how I draw them:
void RendererD3D11::RenderTransparents(const unsigned int* culledSceneIDs)
{
// Set BlendState
this->renderStateContext.SetBlendState(RenderStateDesc::AlphaBlend, &this->blendStates, this->deviceContext);
// Set DepthStencilState
this->renderStateContext.SetDepthStencilState(RenderStateDesc::DepthWriteEnabled, &this->depthStencilStates, this->deviceContext);
// Set BackBuffer as RenderTarget & Main DepthStencil Buffer
ID3D11DepthStencilView* main_DSV = this->mainDSV;
ID3D11RenderTargetView* backbuffer_RTV = this->backBufferRTV;
this->renderStateContext.SetRenderTargetSlot(backbuffer_RTV, main_DSV, this->deviceContext);
for(size_t i = 0; i < this->contentManager->GetTransparentInstancesSize(); ++i)
{
if(this->contentManager->GetPtrToTransparentInstances()->at(i).entityType == SceneList::Primitive)
{
// Get ScenePrimitiveDescription
unsigned int sceneID = this->contentManager->GetPtrToTransparentInstances()->at(i).sceneID;
if(culledSceneIDs[sceneID] != 0)
{
ScenePrimitiveDescription* scenePrimitive = &this->sceneManager->GetCurrentScene()->GetDesc()->primitives[sceneID];
// Set shader
GenericShader* shader = NULL;
switch(scenePrimitive->material.type)
{
case MaterialTypes::Glass:
{
shader = this->contentManager->GetShader(ShaderFile::Glass, this->device);
break;
}
case MaterialTypes::GUI_AlphaBlend:
{
shader = this->contentManager->GetShader(ShaderFile::GUI_AlphaBlend, this->device);
break;
}
case MaterialTypes::GUI_AlphaTest:
{
shader = this->contentManager->GetShader(ShaderFile::GUI_AlphaTest, this->device);
break;
}
}
if(shader)
{
this->deviceContext->VSSetShader(shader->VS, 0, 0);
this->deviceContext->PSSetShader(shader->PS, 0, 0);
}
if(scenePrimitive->material.type == MaterialTypes::GUI_AlphaBlend ||
scenePrimitive->material.type == MaterialTypes::GUI_AlphaTest)
{
// Set DiffuseMap
ID3D11ShaderResourceView* diffuseMap_SRV = this->contentManager->GetTextureFromPool(scenePrimitive->material.diffuseMap.ID)->GetResource();
this->renderStateContext.SetResourceSlot(0, RenderStateDesc::PS, diffuseMap_SRV, this->deviceContext);
// Update buffer
D3D11_MAPPED_SUBRESOURCE mappedResourcePropertiesTransforms;
// Lock the constant buffer so it can be written to
this->deviceContext->Map(this->cbTransparentTransforms, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResourcePropertiesTransforms);
// Get a pointer to the data in the constant buffer.
cbsTransparentTransforms* pDataTransform = (cbsTransparentTransforms*)mappedResourcePropertiesTransforms.pData;
// Copy the matrices into the constant buffer
XMStoreFloat4x4(&pDataTransform->ViewProjection, mainCamera->ViewProjectionMatrix());
XMMATRIX worldTransform = XMMatrixTranspose(XMLoadFloat4x4(&scenePrimitive->worldTransform));
XMStoreFloat4(&pDataTransform->world_c0, worldTransform.r[0]);
XMStoreFloat4(&pDataTransform->world_c1, worldTransform.r[1]);
XMStoreFloat4(&pDataTransform->world_c2, worldTransform.r[2]);
// Unlock the constant buffer
this->deviceContext->Unmap(this->cbTransparentTransforms, 0);
D3D11_MAPPED_SUBRESOURCE mappedResourceProperties;
// Lock the constant buffer so it can be written to
this->deviceContext->Map(this->cbGUITransforms, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResourceProperties);
// Get a pointer to the data in the constant buffer.
cbsGUITransforms* pData = (cbsGUITransforms*)mappedResourceProperties.pData;
pData->TransparencyValue = 1.0f;
// Unlock the constant buffer
this->deviceContext->Unmap(this->cbGUITransforms, 0);
// Set constant buffer
this->deviceContext->VSSetConstantBuffers(0, 1, &this->cbTransparentTransforms);
this->deviceContext->PSSetConstantBuffers(1, 1, &this->cbGUITransforms);
// Draw call
this->contentManager->GetPrimitiveFromPool(scenePrimitive->ID)->Draw(this->PosUVInputLayout, this->device,
this->deviceContext, 0,
VertexDeclaration::PosUV);
// Reset shader resource slots
ID3D11ShaderResourceView* NullSRV = NULL;
this->renderStateContext.SetResourceSlot(0, RenderStateDesc::PS, NullSRV, this->deviceContext);
}
else
{
// Set DiffuseMap
ID3D11ShaderResourceView* diffuseMap_SRV = this->contentManager->GetTextureFromPool(scenePrimitive->material.diffuseMap.ID)->GetResource();
this->renderStateContext.SetResourceSlot(0, RenderStateDesc::PS, diffuseMap_SRV, this->deviceContext);
// Set NormalMap
ID3D11ShaderResourceView* normalMap_SRV = this->contentManager->GetTextureFromPool(scenePrimitive->material.normalMap.ID)->GetResource();
this->renderStateContext.SetResourceSlot(1, RenderStateDesc::PS, normalMap_SRV, this->deviceContext);
// Set SpecularMap
ID3D11ShaderResourceView* specularMap_SRV = this->contentManager->GetTextureFromPool(scenePrimitive->material.specularMap.ID)->GetResource();
this->renderStateContext.SetResourceSlot(2, RenderStateDesc::PS, specularMap_SRV, this->deviceContext);
// Set SamplerStates
this->renderStateContext.SetSamplerState(RenderStateDesc::Anisotropic, &this->samplerstates, this->deviceContext, 0);
this->renderStateContext.SetSamplerState(RenderStateDesc::Linear, &this->samplerstates, this->deviceContext, 1);
// Update buffer
D3D11_MAPPED_SUBRESOURCE mappedResourceProperties;
// Lock the constant buffer so it can be written to
this->deviceContext->Map(this->cbTransparentTransforms, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResourceProperties);
// Get a pointer to the data in the constant buffer.
cbsTransparentTransforms* pData = (cbsTransparentTransforms*)mappedResourceProperties.pData;
// Copy the matrices into the constant buffer
XMStoreFloat4x4(&pData->ViewProjection, mainCamera->ViewProjectionMatrix());
XMMATRIX worldTransform = XMMatrixTranspose(XMLoadFloat4x4(&scenePrimitive->worldTransform));
XMStoreFloat4(&pData->world_c0, worldTransform.r[0]);
XMStoreFloat4(&pData->world_c1, worldTransform.r[1]);
XMStoreFloat4(&pData->world_c2, worldTransform.r[2]);
// Unlock the constant buffer
this->deviceContext->Unmap(this->cbTransparentTransforms, 0);
// Set Directional Light data
D3D11_MAPPED_SUBRESOURCE mappedResourcePropertiesLighting;
// Lock the constant buffer so it can be written to
this->deviceContext->Map(this->cbLightData, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResourcePropertiesLighting);
// Get a pointer to the data in the constant buffer.
cbsDirectionalLightData* pDataLighting = (cbsDirectionalLightData*)mappedResourcePropertiesLighting.pData;
pDataLighting->intensity = this->contentManager->GetDirectionalSunLight()->Intensity();
XMFLOAT3 direction = this->contentManager->GetDirectionalSunLight()->Direction();
XMFLOAT3 color = this->contentManager->GetDirectionalSunLight()->Color();
pDataLighting->lightDir = direction;
XMStoreFloat3(&pDataLighting->camPosition, this->mainCamera->Position());
pDataLighting->padding = 0.0f;
// Unlock the constant buffer
this->deviceContext->Unmap(this->cbLightData, 0);
// Set constant buffer
this->deviceContext->VSSetConstantBuffers(0, 1, &this->cbTransparentTransforms);
this->deviceContext->VSSetConstantBuffers(1, 1, &this->cbLightData);
// Set FillMode
if(this->isWireframe)
{
this->renderStateContext.SetRasterizerState(RenderStateDesc::Wireframe, &rasterizerStates, deviceContext);
}
else
{
this->renderStateContext.SetRasterizerState(RenderStateDesc::BackFaceCull, &rasterizerStates, deviceContext);
}
// Draw call
this->contentManager->GetPrimitiveFromPool(scenePrimitive->ID)->Draw(this->PosUVNormalTangentInputLayout, this->device,
this->deviceContext, 0,
VertexDeclaration::PosUVNormalTangent);
// Set FillMode
if(this->isWireframe)
{
this->renderStateContext.SetRasterizerState(RenderStateDesc::Wireframe, &rasterizerStates, deviceContext);
}
else
{
this->renderStateContext.SetRasterizerState(RenderStateDesc::FrontFaceCull, &rasterizerStates, deviceContext);
}
// Draw call
this->contentManager->GetPrimitiveFromPool(scenePrimitive->ID)->Draw(this->PosUVNormalTangentInputLayout, this->device,
this->deviceContext, 0,
VertexDeclaration::PosUVNormalTangent);
// Reset shader resource slots
ID3D11ShaderResourceView* NullSRV = NULL;
this->renderStateContext.SetResourceSlot(0, RenderStateDesc::PS, NullSRV, this->deviceContext);
this->renderStateContext.SetResourceSlot(1, RenderStateDesc::PS, NullSRV, this->deviceContext);
this->renderStateContext.SetResourceSlot(2, RenderStateDesc::PS, NullSRV, this->deviceContext);
}
}
}
else
{
// StaticMesh in here...
}
}
}