From 6aef0e913e8099a79580397a92063543fcdefbf6 Mon Sep 17 00:00:00 2001 From: ThePuzzlemaker Date: Thu, 3 Jul 2025 23:47:58 -0500 Subject: [PATCH] Don't write translucent objects to the depth buffer This fixes some issues with sun glare noticed by NASSP users, where the sun glare was hidden by the COAS (a translucent mesh). This also fixes the sun glare being hidden by the DG hud, for example. I implemented a simple heuristic for simple translucent objects (diffuse color alpha != 1.0), but others must be manually marked with the mesh group flag 0x40. Otherwise, checking translucency incurs checking every pixel of an image after considering textures, which is expensive and error-prone. These excluded objects do not write to the depth-buffer or the SSAO/glare calculation g-buffers, which I believe is probably an invalid behaviour with respect to the intended functionality. Please let me know if you find anything this breaks! I don't believe this should break anything, and it may actually fix other issues within Orbiter related to transparency. --- OVP/D3D9Client/Mesh.cpp | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/OVP/D3D9Client/Mesh.cpp b/OVP/D3D9Client/Mesh.cpp index decef7603..2d71320b5 100644 --- a/OVP/D3D9Client/Mesh.cpp +++ b/OVP/D3D9Client/Mesh.cpp @@ -1608,9 +1608,8 @@ void D3D9Mesh::Render(const LPD3DXMATRIX pW, int iTech, LPDIRECT3DCUBETEXTURE9 * bool bRefl = true; for (DWORD g=0; gDiffuse.w != 1.0f; if (mat!=old_mat) { @@ -1919,6 +1919,10 @@ void D3D9Mesh::Render(const LPD3DXMATRIX pW, int iTech, LPDIRECT3DCUBETEXTURE9 * pDev->SetRenderState(D3DRS_ZENABLE, 0); pDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); } + + if (bTransl) { + pDev->SetRenderState(D3DRS_ZWRITEENABLE, 0); + } if (Grp[g].bDualSided) { pDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); @@ -1951,6 +1955,10 @@ void D3D9Mesh::Render(const LPD3DXMATRIX pW, int iTech, LPDIRECT3DCUBETEXTURE9 * pDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); } + if (bTransl) { + pDev->SetRenderState(D3DRS_ZWRITEENABLE, 1); + } + D3D9Stats.Mesh.Vertices += Grp[g].nVert; D3D9Stats.Mesh.MeshGrps++; @@ -2067,6 +2075,7 @@ void D3D9Mesh::RenderSimplified(const LPD3DXMATRIX pW, LPDIRECT3DCUBETEXTURE9 *p // Render MeshGroups ---------------------------------------------------- // for (DWORD g = 0; gSetFloat(eMtrlAlpha, mat->Diffuse.w); else FX->SetFloat(eMtrlAlpha, 1.0f); } + bTransl = bTransl || mat->Diffuse.w != 1.0f; } // Must update FlowControl ? @@ -2208,12 +2218,20 @@ void D3D9Mesh::RenderSimplified(const LPD3DXMATRIX pW, LPDIRECT3DCUBETEXTURE9 *p pDev->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, 0); } + if (bTransl) { + pDev->SetRenderState(D3DRS_ZWRITEENABLE, 0); + } + pDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, Grp[g].VertOff, 0, Grp[g].nVert, Grp[g].IdexOff, Grp[g].nFace); Grp[g].bRendered = true; if (bOIT && dwMSAA) { pDev->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, dwMSAA); } + + if (bTransl) { + pDev->SetRenderState(D3DRS_ZWRITEENABLE, 1); + } } if (CurrentShader != 0xFFFF) HR(FX->EndPass()); @@ -2379,6 +2397,7 @@ void D3D9Mesh::RenderFast(const LPD3DXMATRIX pW, int iTech) if ((Grp[g].UsrFlag & 0x2) && (Grp[g].MFDScreenId != 0x100)) continue; bool bHUD = Grp[g].MFDScreenId == 0x100; + bool bTransl = (Grp[g].UsrFlag & 0x40) != 0; // Mesh Debugger ------------------------------------------------------------------------------------------- // @@ -2492,6 +2511,7 @@ void D3D9Mesh::RenderFast(const LPD3DXMATRIX pW, int iTech) if (bModulateMatAlpha || bTextured == false) FX->SetFloat(eMtrlAlpha, mat->Diffuse.w); else FX->SetFloat(eMtrlAlpha, 1.0f); } + bTransl = bTransl || mat->Diffuse.w != 1.0f; } @@ -2525,6 +2545,10 @@ void D3D9Mesh::RenderFast(const LPD3DXMATRIX pW, int iTech) pDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); } + if (bTransl) { + pDev->SetRenderState(D3DRS_ZWRITEENABLE, 0); + } + if (Grp[g].bDualSided) { pDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); pDev->SetRenderState(D3DRS_ZWRITEENABLE, 0); @@ -2545,6 +2569,10 @@ void D3D9Mesh::RenderFast(const LPD3DXMATRIX pW, int iTech) pDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); } + if (bTransl) { + pDev->SetRenderState(D3DRS_ZWRITEENABLE, 1); + } + D3D9Stats.Mesh.Vertices += Grp[g].nVert; D3D9Stats.Mesh.MeshGrps++; } @@ -2777,7 +2805,12 @@ void D3D9Mesh::RenderShadowMap(const LPD3DXMATRIX pW, const LPD3DXMATRIX pVP, in { if (Grp[g].UsrFlag & 0x2) continue; if (Grp[g].UsrFlag & 0x1) continue; - + + const D3D9MatExt* mat = nullptr; + if (Grp[g].MtrlIdx==SPEC_DEFAULT) mat = &defmat; + else mat = &Mtrl[Grp[g].MtrlIdx]; + if ((Grp[g].UsrFlag & 0x40 != 0) || mat->Diffuse.w != 1.0f) { continue; } // Skip recording depth and normals for translucent objects + MeshShader::ps_bools.bOIT = (Grp[g].UsrFlag & 0x20) != 0; if (MeshShader::ps_bools.bOIT) {