1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

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.
This commit is contained in:
narzoul 2017-08-21 22:26:44 +02:00
parent 8ab8058ceb
commit 4dc1c70f41
3 changed files with 37 additions and 0 deletions

View File

@ -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<decltype(&D3DDDI_DEVICEFUNCS::func), &D3DDDI_DEVICEFUNCS::func>
@ -449,5 +461,6 @@ namespace D3dDdi
vtable.pfnPresent1 = &present1;
vtable.pfnSetRenderTarget = &setRenderTarget;
vtable.pfnUnlock = &unlock;
vtable.pfnUpdateWInfo = &updateWInfo;
}
}

View File

@ -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)

View File

@ -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);