From 4dc1c70f4113721c523b29f05cd8537fa41e3564 Mon Sep 17 00:00:00 2001 From: narzoul Date: Mon, 21 Aug 2017 22:26:44 +0200 Subject: [PATCH] Fix pixel W-fog when projection matrix is not set When the 3D projection matrix is not set (transformation is performed in software), pixel (table) fog effects appear to be missing on some drivers. The matrix itself normally isn't passed to the user mode SetTransform driver function anyway due to the fixed-function shader converters being enabled by default. Instead only UpdateWInfo is called with the W-range calculated from the matrix. For the initial identity matrix, UpdateWInfo receives the range (1.0, 1.0). This seems to cause Intel (HD 4600) drivers to interpret pixel fog ranges as Z-depth values, while with any other range specified eye-relative (W) depth is used. The actual values otherwise don't seem to matter with respect to how fog is rendered. On AMD (RX 480), eye-relative depth is used irrespective of the W-range. There is currently no information on how NVIDIA drivers behave, except that with the default W-range no fog seems to be produced. This fix replaces the W-range (1.0, 1.0) with (0.0, 1.0) which causes Intel to also interpret fog range in eye-relative depth with the default identity projection matrix. Fixes missing fog on Intel HD (and hopefully NVIDIA) in Combat Mission games reported in issue #20. --- DDrawCompat/D3dDdi/DeviceFuncs.cpp | 13 +++++++++++++ DDrawCompat/D3dDdi/Log/DeviceFuncsLog.cpp | 21 +++++++++++++++++++++ DDrawCompat/D3dDdi/Log/DeviceFuncsLog.h | 3 +++ 3 files changed, 37 insertions(+) diff --git a/DDrawCompat/D3dDdi/DeviceFuncs.cpp b/DDrawCompat/D3dDdi/DeviceFuncs.cpp index 805bdb9..0834ab2 100644 --- a/DDrawCompat/D3dDdi/DeviceFuncs.cpp +++ b/DDrawCompat/D3dDdi/DeviceFuncs.cpp @@ -417,6 +417,18 @@ namespace } return getOrigVtable(hDevice).pfnUnlock(hDevice, pData); } + + HRESULT APIENTRY updateWInfo(HANDLE hDevice, const D3DDDIARG_WINFO* pData) + { + if (pData && 1.0f == pData->WNear && 1.0f == pData->WFar) + { + D3DDDIARG_WINFO wInfo = {}; + wInfo.WNear = 0.0f; + wInfo.WFar = 1.0f; + return getOrigVtable(hDevice).pfnUpdateWInfo(hDevice, &wInfo); + } + return getOrigVtable(hDevice).pfnUpdateWInfo(hDevice, pData); + } } #define RENDER_FUNC(func) renderFunc @@ -449,5 +461,6 @@ namespace D3dDdi vtable.pfnPresent1 = &present1; vtable.pfnSetRenderTarget = &setRenderTarget; vtable.pfnUnlock = &unlock; + vtable.pfnUpdateWInfo = &updateWInfo; } } diff --git a/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.cpp b/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.cpp index 0faf965..c45a69c 100644 --- a/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.cpp +++ b/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.cpp @@ -132,6 +132,13 @@ std::ostream& operator<<(std::ostream& os, const D3DDDIARG_PRESENTSURFACE& val) << val.SubResourceIndex; } +std::ostream& operator<<(std::ostream& os, const D3DDDIARG_RENDERSTATE& val) +{ + return Compat::LogStruct(os) + << val.State + << val.Value; +} + std::ostream& operator<<(std::ostream& os, const D3DDDIARG_UNLOCK& val) { return Compat::LogStruct(os) @@ -140,6 +147,20 @@ std::ostream& operator<<(std::ostream& os, const D3DDDIARG_UNLOCK& val) << Compat::hex(val.Flags.Value); } +std::ostream& operator<<(std::ostream& os, const D3DDDIARG_WINFO& val) +{ + return Compat::LogStruct(os) + << val.WNear + << val.WFar; +} + +std::ostream& operator<<(std::ostream& os, const D3DDDIARG_ZRANGE& val) +{ + return Compat::LogStruct(os) + << val.MinZ + << val.MaxZ; +} + std::ostream& operator<<(std::ostream& os, const D3DDDIBOX& box) { return Compat::LogStruct(os) diff --git a/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.h b/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.h index 80695d9..02292e9 100644 --- a/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.h +++ b/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.h @@ -18,5 +18,8 @@ std::ostream& operator<<(std::ostream& os, const D3DDDIARG_OPENRESOURCE& val); std::ostream& operator<<(std::ostream& os, const D3DDDIARG_PRESENT& val); std::ostream& operator<<(std::ostream& os, const D3DDDIARG_PRESENT1& val); std::ostream& operator<<(std::ostream& os, const D3DDDIARG_PRESENTSURFACE& val); +std::ostream& operator<<(std::ostream& os, const D3DDDIARG_RENDERSTATE& val); std::ostream& operator<<(std::ostream& os, const D3DDDIARG_UNLOCK& val); +std::ostream& operator<<(std::ostream& os, const D3DDDIARG_WINFO& val); +std::ostream& operator<<(std::ostream& os, const D3DDDIARG_ZRANGE& val); std::ostream& operator<<(std::ostream& os, const D3DDDIBOX& val);