Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for transforming homogenous W geometry into world geomtry #199

Open
wants to merge 32 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
917d6d6
Added support for transforming homogenous W geometry into world geome…
dkollmann May 14, 2023
e8ff88d
Fixed incorrect game camera position and orientation. Added option to…
dkollmann May 16, 2023
17ba9b6
Fix comments from pull request
elishacloud May 17, 2023
dbc8e10
Don't override matrix memory, just the pointer
elishacloud May 17, 2023
14632ef
Fix disable lighting and a couple typos
elishacloud May 17, 2023
de8fcbc
Set transform if not set by game
elishacloud May 17, 2023
a0ddc3d
Remove RenderData
elishacloud May 17, 2023
c715c61
Fix default settings
elishacloud May 17, 2023
d7dff14
Fixed that DdrawConvertHomogeneousToWorldUseGameCamera did not actual…
dkollmann May 17, 2023
575bd6f
Remove unneeded matrix assignment
elishacloud May 18, 2023
44d4338
Fix DdrawConvertHomogeneousToWorldUseGameCamera
elishacloud May 18, 2023
f823ec3
Move matrix override code to the end
elishacloud May 18, 2023
e79c204
Fix DdrawConvertHomogeneousToWorldUseGameCamera
elishacloud Jun 6, 2023
153287c
Merge branch 'master' into reverse_xyzrhw_new
elishacloud Jun 20, 2023
1a8607e
Fix merge conflict with main
elishacloud Jun 20, 2023
f82ae80
Minor update
elishacloud Jun 20, 2023
80b12b0
Merge branch 'master' into reverse_xyzrhw_new
elishacloud Jun 26, 2023
fac874b
Fix formatting
elishacloud Jun 26, 2023
8b54596
Fix defaults
elishacloud Jun 26, 2023
48bdfec
Merge remote-tracking branch 'origin/master' into pr/199
elishacloud Jul 13, 2023
3ee34d4
Fix PR to work with master branch changes
elishacloud Jul 13, 2023
5e3d5e4
Merge remote-tracking branch 'origin/master' into pr/199
elishacloud Jul 13, 2023
0d9bb50
Update to make it match master branch
elishacloud Jul 13, 2023
58812be
Merge remote-tracking branch 'origin/master' into pr/199
elishacloud Jul 15, 2023
f5b307d
Merge remote-tracking branch 'origin/master' into pr/199
elishacloud Aug 14, 2023
1ab9a42
Merge branch 'master' into reverse_xyzrhw_new
elishacloud Dec 2, 2023
80dfe72
Include DirectXMath
elishacloud Mar 2, 2024
11e1db3
Merge branch 'master' into reverse_xyzrhw_new
elishacloud Mar 2, 2024
5dec4b8
Merge branch 'master' into reverse_xyzrhw_new
elishacloud Apr 4, 2024
9b92264
Merge branch 'master' into reverse_xyzrhw_new
elishacloud Apr 7, 2024
bf79a6a
Merge branch 'master' into reverse_xyzrhw_new
elishacloud Aug 22, 2024
e84f19c
Merge branch 'master' into reverse_xyzrhw_new
elishacloud Sep 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions Settings/Settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@
visit(DdrawOverrideStencilFormat) \
visit(DdrawResolutionHack) \
visit(DdrawUseDirect3D9Ex) \
visit(DdrawConvertHomogeneousW) \
visit(DdrawConvertHomogeneousToWorld) \
visit(DdrawConvertHomogeneousToWorldUseGameCamera) \
visit(DdrawConvertHomogeneousToWorldFOV) \
visit(DdrawConvertHomogeneousToWorldNearPlane) \
visit(DdrawConvertHomogeneousToWorldFarPlane) \
visit(DdrawConvertHomogeneousToWorldDepthOffset) \
visit(DdrawUseNativeResolution) \
visit(DdrawEnableMouseHook) \
visit(DdrawHookSystem32) \
Expand Down Expand Up @@ -209,6 +216,13 @@ struct CONFIG
bool DdrawIntegerScalingClamp = false; // Scales the screen by an integer value to help preserve video quality
bool DdrawMaintainAspectRatio = false; // Keeps the current DirectDraw aspect ratio when overriding the game's resolution
bool DdrawUseDirect3D9Ex = false; // Use Direct3D9Ex extensions for Dd7to9
bool DdrawConvertHomogeneousW = false; // Convert primites using D3DFVF_XYZRHW to D3DFVF_XYZW.
bool DdrawConvertHomogeneousToWorld = false; // Convert primitives back into a world space. Needed for RTX.
bool DdrawConvertHomogeneousToWorldUseGameCamera = false; // Use the game's view matrix instead of replacing it with our own.
float DdrawConvertHomogeneousToWorldFOV = 90.0f; // The field of view of the camera used to reconstruct the original 3D world.
float DdrawConvertHomogeneousToWorldNearPlane = 1.0f; // The near plane of the camera used to reconstruct the original 3D world.
float DdrawConvertHomogeneousToWorldFarPlane = 1000.0f; // The far plane of the camera used to reconstruct the original 3D world.
float DdrawConvertHomogeneousToWorldDepthOffset = 0.0f; // The offset to add to the geometry so it does not clip into the near plane.
bool DdrawUseNativeResolution = false; // Uses the current screen resolution for Dd7to9
DWORD DdrawClippedWidth = 0; // Used to scaled Direct3d9 to use this width when using Dd7to9
DWORD DdrawClippedHeight = 0; // Used to scaled Direct3d9 to use this height when using Dd7to9
Expand Down
3 changes: 2 additions & 1 deletion ddraw/DebugOverlay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

#include "DebugOverlay.h"
#include "RenderData.h"
#include <sstream>

#define IMGUI_DEFINE_MATH_OPERATORS
Expand Down Expand Up @@ -98,7 +99,7 @@ void DebugOverlay::BeginScene()
ImGui::NewFrame();
}

void DebugOverlay::EndScene()
void DebugOverlay::EndScene(const RenderData &RenderData)
elishacloud marked this conversation as resolved.
Show resolved Hide resolved
{
static bool ShowDebugUI = false;
if (ImGui::IsKeyDown(ImGui::GetKeyIndex(ImGuiKey_LeftAlt)) &&
Expand Down
2 changes: 1 addition & 1 deletion ddraw/DebugOverlay.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class DebugOverlay

// Frame functions
void BeginScene();
void EndScene();
void EndScene(const class RenderData &RenderData);

// Functions
void SetTransform(D3DTRANSFORMSTATETYPE dtstTransformStateType, LPD3DMATRIX lpD3DMatrix);
Expand Down
188 changes: 182 additions & 6 deletions ddraw/IDirect3DDeviceX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@

#include "ddraw.h"
#include <d3dhal.h>
#include <DirectXMath.h>

// Enable for testing only
//#define ENABLE_DEBUGOVERLAY
#define ENABLE_DEBUGOVERLAY
elishacloud marked this conversation as resolved.
Show resolved Hide resolved

#ifdef ENABLE_DEBUGOVERLAY
#include "DebugOverlay.h"
Expand Down Expand Up @@ -338,15 +339,103 @@ HRESULT m_IDirect3DDeviceX::SetTransform(D3DTRANSFORMSTATETYPE dtstTransformStat
break;
}

HRESULT hr = (*d3d9Device)->SetTransform(dtstTransformStateType, lpD3DMatrix);

if (SUCCEEDED(hr))
if(Config.DdrawConvertHomogeneousW)
{
#ifdef ENABLE_DEBUGOVERLAY
// Set the original matrix
DOverlay.SetTransform(dtstTransformStateType, lpD3DMatrix);
#endif

if(dtstTransformStateType == D3DTS_VIEW)
{
D3DVIEWPORT9 Viewport9;
if(SUCCEEDED((*d3d9Device)->GetViewport(&Viewport9)))
{
const float width = (float)Viewport9.Width;
const float height = (float)Viewport9.Height;
const float ratio = width / height;

// Replace the matrix with one that handles D3DFVF_XYZRHW geometry
_D3DMATRIX view;
ZeroMemory(&view, sizeof(_D3DMATRIX));
view._11 = 2.0f / width;
view._22 = -2.0f / height;
view._33 = 1.0f;
view._41 = -1.0f; // translate X
view._42 = 1.0f; // translate Y
view._44 = 1.0f;

if(!Config.DdrawConvertHomogeneousToWorld)
{
// Override the original matrix
std::memcpy(lpD3DMatrix, &view, sizeof(_D3DMATRIX));
}
else
{
// Override the original matrix
std::memcpy(lpD3DMatrix, &view, sizeof(_D3DMATRIX));
elishacloud marked this conversation as resolved.
Show resolved Hide resolved

// Store the original matrix so it can be restored
std::memcpy(&RenderData.DdrawConvertHomogeneousToWorld_ViewMatrixOriginal, &view, sizeof(_D3DMATRIX));

// The Black & White matrix is an ortho camera, so create a perspective one matching the game
const float fov = Config.DdrawConvertHomogeneousToWorldFOV;
const float nearplane = Config.DdrawConvertHomogeneousToWorldNearPlane;
const float farplane = Config.DdrawConvertHomogeneousToWorldFarPlane;
DirectX::XMMATRIX proj = DirectX::XMMatrixPerspectiveFovLH(fov * (3.14159265359f / 180.0f), ratio, nearplane, farplane);
elishacloud marked this conversation as resolved.
Show resolved Hide resolved

DirectX::XMStoreFloat4x4((DirectX::XMFLOAT4X4*)&RenderData.DdrawConvertHomogeneousToWorld_ProjectionMatrix, proj);

DirectX::XMVECTOR up = DirectX::XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);

DirectX::XMMATRIX viewMatrix;
elishacloud marked this conversation as resolved.
Show resolved Hide resolved
if(Config.DdrawConvertHomogeneousToWorldUseGameCamera)
{
// To reconstruct the 3D world, we need to know where the camera is and where it is looking
DirectX::XMVECTOR position = DirectX::XMVectorSet(lpD3DMatrix->_41, lpD3DMatrix->_42, lpD3DMatrix->_43, lpD3DMatrix->_44);
DirectX::XMVECTOR direction = DirectX::XMVectorSet(lpD3DMatrix->_31, lpD3DMatrix->_32, lpD3DMatrix->_33, lpD3DMatrix->_34);

viewMatrix = DirectX::XMMatrixLookToLH(position, direction, up);
}
else
{
const float cameradir = 1.0f;

DirectX::XMVECTOR pos = DirectX::XMVectorSet(0.0f, 0.0f, -cameradir, 0.0f);
DirectX::XMVECTOR direction = DirectX::XMVectorSet(0.0f, 0.0f, cameradir, 0.0f);

viewMatrix = DirectX::XMMatrixLookToLH(pos, direction, up);
}

// Store the 3D view matrix so it can be set later
DirectX::XMStoreFloat4x4((DirectX::XMFLOAT4X4*)&RenderData.DdrawConvertHomogeneousToWorld_ViewMatrix, viewMatrix);

// Store the view inverse matrix of the game, so we can transform the geometry with it
DirectX::XMMATRIX toViewSpace = DirectX::XMLoadFloat4x4((DirectX::XMFLOAT4X4*)lpD3DMatrix);
elishacloud marked this conversation as resolved.
Show resolved Hide resolved
DirectX::XMMATRIX vp = DirectX::XMMatrixMultiply(viewMatrix, proj);
DirectX::XMMATRIX vpinv = DirectX::XMMatrixInverse(nullptr, vp);

DirectX::XMMATRIX depthoffset = DirectX::XMMatrixTranslation(0.0f, 0.0f, Config.DdrawConvertHomogeneousToWorldDepthOffset);

RenderData.DdrawConvertHomogeneousToWorld_ViewMatrixInverse = DirectX::XMMatrixMultiply(depthoffset, DirectX::XMMatrixMultiply(toViewSpace, vpinv));
}
elishacloud marked this conversation as resolved.
Show resolved Hide resolved
}
}
else
{
return D3D_OK;
elishacloud marked this conversation as resolved.
Show resolved Hide resolved
}
}

HRESULT hr = (*d3d9Device)->SetTransform(dtstTransformStateType, lpD3DMatrix);

#ifdef ENABLE_DEBUGOVERLAY
if (SUCCEEDED(hr) && !Config.DdrawConvertHomogeneousW)
{
DOverlay.SetTransform(dtstTransformStateType, lpD3DMatrix);
}
#endif

return hr;
}

Expand Down Expand Up @@ -1617,7 +1706,7 @@ HRESULT m_IDirect3DDeviceX::EndScene()
}

#ifdef ENABLE_DEBUGOVERLAY
DOverlay.EndScene();
DOverlay.EndScene(RenderData);
#endif

// The IDirect3DDevice7::EndScene method ends a scene that was begun by calling the IDirect3DDevice7::BeginScene method.
Expand Down Expand Up @@ -2453,11 +2542,98 @@ HRESULT m_IDirect3DDeviceX::DrawIndexedPrimitive(D3DPRIMITIVETYPE dptPrimitiveTy
}
else
{
const UINT stride = GetVertexStride(dwVertexTypeDesc);

// Handle PositionT
if((dwVertexTypeDesc & D3DFVF_XYZRHW) != 0 && Config.DdrawConvertHomogeneousW)
elishacloud marked this conversation as resolved.
Show resolved Hide resolved
{
if(!Config.DdrawConvertHomogeneousToWorld)
{
UINT8 *vertex = (UINT8*)lpVertices;

for (UINT x = 0; x < dwVertexCount; x++)
{
float *pos = (float*) vertex;

pos[3] = 1.0f;
elishacloud marked this conversation as resolved.
Show resolved Hide resolved
elishacloud marked this conversation as resolved.
Show resolved Hide resolved

elishacloud marked this conversation as resolved.
Show resolved Hide resolved
vertex += stride;
}

// Update the FVF
dwVertexTypeDesc = (dwVertexTypeDesc & ~D3DFVF_XYZRHW) | D3DFVF_XYZW;
}
else
{
const UINT newstride = stride - sizeof(float);
elishacloud marked this conversation as resolved.
Show resolved Hide resolved
const UINT restSize = stride - sizeof(float) * 4;

RenderData.DdrawConvertHomogeneousToWorld_IntermediateGeometry.resize(newstride * dwVertexCount);

UINT8 *sourceVertex = (UINT8*)lpVertices;
UINT8 *targetVertex = (UINT8*)RenderData.DdrawConvertHomogeneousToWorld_IntermediateGeometry.data();

lpVertices = targetVertex;

for (UINT x = 0; x < dwVertexCount; x++)
{
// Transform the vertices into world space
float *srcpos = (float*) sourceVertex;
float *trgtpos = (float*) targetVertex;

DirectX::XMVECTOR xpos = DirectX::XMVectorSet(srcpos[0], srcpos[1], srcpos[2], srcpos[3]);

DirectX::XMVECTOR xpos_global = DirectX::XMVector3TransformCoord(xpos, RenderData.DdrawConvertHomogeneousToWorld_ViewMatrixInverse);

xpos_global = DirectX::XMVectorDivide(xpos_global, DirectX::XMVectorSplatW(xpos_global));

trgtpos[0] = DirectX::XMVectorGetX(xpos_global);
trgtpos[1] = DirectX::XMVectorGetY(xpos_global);
trgtpos[2] = DirectX::XMVectorGetZ(xpos_global);

// Copy the rest
std::memcpy(targetVertex + sizeof(float) * 3, sourceVertex + sizeof(float) * 4, restSize);

// Move to next vertex
sourceVertex += stride;
targetVertex += newstride;
}

// Set transform
(*d3d9Device)->SetTransform(D3DTS_VIEW, &RenderData.DdrawConvertHomogeneousToWorld_ViewMatrix);
(*d3d9Device)->SetTransform(D3DTS_PROJECTION, &RenderData.DdrawConvertHomogeneousToWorld_ProjectionMatrix);

// Update the FVF
const DWORD newVertexTypeDesc = (dwVertexTypeDesc & ~D3DFVF_XYZRHW) | D3DFVF_XYZ;

// Set fixed function vertex type
(*d3d9Device)->SetFVF(newVertexTypeDesc);
elishacloud marked this conversation as resolved.
Show resolved Hide resolved

// Draw indexed primitive UP
hr = (*d3d9Device)->DrawIndexedPrimitiveUP(dptPrimitiveType, 0, dwVertexCount, GetNumberOfPrimitives(dptPrimitiveType, dwIndexCount), lpIndices, D3DFMT_INDEX16, lpVertices, newstride);

// Restore transform
_D3DMATRIX identityMatrix;
ZeroMemory(&identityMatrix, sizeof(_D3DMATRIX));
identityMatrix._11 = 1.0f;
identityMatrix._22 = 1.0f;
identityMatrix._33 = 1.0f;

(*d3d9Device)->SetTransform(D3DTS_VIEW, &RenderData.DdrawConvertHomogeneousToWorld_ViewMatrixOriginal);
(*d3d9Device)->SetTransform(D3DTS_PROJECTION, &identityMatrix);

// Handle dwFlags
UnSetDrawFlags(rsClipping, rsLighting, rsExtents, newVertexTypeDesc, dwFlags, DirectXVersion);

return hr;
}
}

// Set fixed function vertex type
(*d3d9Device)->SetFVF(dwVertexTypeDesc);

// Draw indexed primitive UP
hr = (*d3d9Device)->DrawIndexedPrimitiveUP(dptPrimitiveType, 0, dwVertexCount, GetNumberOfPrimitives(dptPrimitiveType, dwIndexCount), lpIndices, D3DFMT_INDEX16, lpVertices, GetVertexStride(dwVertexTypeDesc));
hr = (*d3d9Device)->DrawIndexedPrimitiveUP(dptPrimitiveType, 0, dwVertexCount, GetNumberOfPrimitives(dptPrimitiveType, dwIndexCount), lpIndices, D3DFMT_INDEX16, lpVertices, stride);
}

// Handle dwFlags
Expand Down
4 changes: 4 additions & 0 deletions ddraw/IDirect3DDeviceX.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include "IDirectDrawX.h"
#include "RenderData.h"

class m_IDirect3DDeviceX : public IUnknown, public AddressLookupTableDdrawObject
{
Expand All @@ -27,6 +28,9 @@ class m_IDirect3DDeviceX : public IUnknown, public AddressLookupTableDdrawObject
// SetTexture array
LPDIRECTDRAWSURFACE7 AttachedTexture[8] = {};

// The data used for rendering
RenderData RenderData;

// Wrapper interface functions
inline REFIID GetWrapperType(DWORD DirectXVersion)
{
Expand Down
37 changes: 37 additions & 0 deletions ddraw/RenderData.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#pragma once

#include <d3d9types.h>
#include <DirectXMath.h>
#include <vector>

class RenderData
{
public:

// Store the projection matrix used to transform the geometry on the gpu
_D3DMATRIX DdrawConvertHomogeneousToWorld_ProjectionMatrix;

// Store the view matrix used to transform the geometry on the gpu
_D3DMATRIX DdrawConvertHomogeneousToWorld_ViewMatrix;

// Store the original view matrix, so we can restore it
_D3DMATRIX DdrawConvertHomogeneousToWorld_ViewMatrixOriginal;

// Store the inverse view matrix to transform the geometry on the cpu
DirectX::XMMATRIX DdrawConvertHomogeneousToWorld_ViewMatrixInverse;

// Intermediate buffer for the geometry conversion
std::vector<uint8_t> DdrawConvertHomogeneousToWorld_IntermediateGeometry;

RenderData()
{
ZeroMemory(&DdrawConvertHomogeneousToWorld_ViewMatrix, sizeof(_D3DMATRIX));
DdrawConvertHomogeneousToWorld_ViewMatrix._11 = 1.0f;
DdrawConvertHomogeneousToWorld_ViewMatrix._22 = 1.0f;
DdrawConvertHomogeneousToWorld_ViewMatrix._33 = 1.0f;
DdrawConvertHomogeneousToWorld_ViewMatrix._44 = 1.0f;

std::memcpy(&DdrawConvertHomogeneousToWorld_ProjectionMatrix, &DdrawConvertHomogeneousToWorld_ViewMatrix, sizeof(_D3DMATRIX));
std::memcpy(&DdrawConvertHomogeneousToWorld_ViewMatrixOriginal, &DdrawConvertHomogeneousToWorld_ViewMatrix, sizeof(_D3DMATRIX));
}
};
1 change: 1 addition & 0 deletions dxwrapper.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,7 @@ cmd /q /c "cd /D ""$(ProjectDir)d3d8\"" &amp;&amp; del build.bat"</Command>
<ClInclude Include="ddraw\IDirectDrawGammaControl.h" />
<ClInclude Include="ddraw\IDirectDrawPalette.h" />
<ClInclude Include="ddraw\IDirectDrawX.h" />
<ClInclude Include="ddraw\RenderData.h" />
<ClInclude Include="ddraw\Versions\IDirect3D.h" />
<ClInclude Include="ddraw\Versions\IDirect3D2.h" />
<ClInclude Include="ddraw\Versions\IDirect3D3.h" />
Expand Down
5 changes: 4 additions & 1 deletion dxwrapper.vcxproj.filters
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="DDrawCompat">
Expand Down Expand Up @@ -1868,6 +1868,9 @@
<ClInclude Include="ddraw\DebugOverlay.h">
<Filter>ddraw</Filter>
</ClInclude>
<ClInclude Include="ddraw\RenderData.h">
<Filter>ddraw</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Dllmain\BuildNo.rc">
Expand Down