From 1f0feed255217cd1bd1df7cb45d72f5604daf865 Mon Sep 17 00:00:00 2001 From: Jack Chen Date: Sat, 18 Nov 2023 21:26:29 +0800 Subject: [PATCH] remove usages of xbox view matrix in fixed mode vertex shader state and light state setup. unpatch D3DDevice_SetTransform() --- src/core/hle/D3D8/Direct3D9/Direct3D9.cpp | 60 ++++++++++----------- src/core/hle/D3D8/XbPushBuffer.cpp | 64 ++++++++++++----------- src/core/hle/Patches.cpp | 4 +- 3 files changed, 62 insertions(+), 66 deletions(-) diff --git a/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp b/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp index 06d02d351..3799e0330 100644 --- a/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp +++ b/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp @@ -7822,8 +7822,9 @@ extern xbox::X_D3DLIGHT8* CxbxrGetLight8Ptr(int lightNum); D3DMATRIX g_xbox_transform_ModelView; D3DMATRIX g_xbox_transform_InverseModelView; D3DMATRIX g_xbox_transform_Composite; -D3DMATRIX g_xbox_DirectModelView_View; -D3DMATRIX g_xbox_DirectModelView_InverseView; +//view matrix and inverse view matrix are no longer needed in fixed mode vertex shader +//D3DMATRIX g_xbox_DirectModelView_View; +//D3DMATRIX g_xbox_DirectModelView_InverseView; D3DMATRIX g_xbox_DirectModelView_World; D3DMATRIX g_xbox_DirectModelView_Projection; D3DMATRIX g_xbox_DirectModelView_InverseWorldViewTransposed; @@ -7842,40 +7843,39 @@ void UpdateFixedFunctionShaderLight(int d3dLightIndex, Light* pShaderLight, D3DX auto d3dLight = &d3d8LightState.Lights[d3dLightIndex]; D3DXMATRIX viewTransform; + bool SpecularEnable; // use lights composed from kelvin. if (is_pgraph_using_NV2A_Kelvin()) { d3dLight=CxbxrGetLight8Ptr(d3dLightIndex); // g_xbox_DirectModelView_View was set to )d3d8TransformState.Transforms[xbox::X_D3DTS_VIEW] - viewTransform = g_xbox_DirectModelView_View; + //viewTransform = g_xbox_DirectModelView_View; + //Light position and direction in NV2A are already in view space. No need to transform them with view matrix here. //viewTransform = (D3DXMATRIX)d3d8TransformState.Transforms[xbox::X_D3DTS_VIEW]; + pShaderLight->PositionV = d3dLight->Position; + pShaderLight->DirectionVN = d3dLight->Direction; + SpecularEnable = NV2ARenderStates.GetXboxRenderState(xbox::X_D3DRS_SPECULARENABLE) != FALSE; }else { //d3dLight = &d3d8LightState.Lights[d3dLightIndex]; viewTransform = (D3DXMATRIX)d3d8TransformState.Transforms[xbox::X_D3DTS_VIEW]; - } - // TODO remove D3DX usage + // TODO remove D3DX usage // Pre-transform light position to viewspace - D3DXVECTOR4 positionV; - D3DXVec3Transform(&positionV, (D3DXVECTOR3*)&d3dLight->Position, &viewTransform); - pShaderLight->PositionV = (D3DXVECTOR3)positionV; + D3DXVECTOR4 positionV; + D3DXVec3Transform(&positionV, (D3DXVECTOR3*)&d3dLight->Position, &viewTransform); + pShaderLight->PositionV = (D3DXVECTOR3)positionV; - // Pre-transform light direction to viewspace and normalize - D3DXVECTOR4 directionV; - D3DXMATRIX viewTransform3x3; - D3DXMatrixIdentity(&viewTransform3x3); - for (int y = 0; y < 3; y++) { - for (int x = 0; x < 3; x++) { - viewTransform3x3.m[x][y] = viewTransform.m[x][y]; + // Pre-transform light direction to viewspace and normalize + D3DXVECTOR4 directionV; + D3DXMATRIX viewTransform3x3; + D3DXMatrixIdentity(&viewTransform3x3); + for (int y = 0; y < 3; y++) { + for (int x = 0; x < 3; x++) { + viewTransform3x3.m[x][y] = viewTransform.m[x][y]; + } } - } - D3DXVec3Transform(&directionV, (D3DXVECTOR3*)&d3dLight->Direction, &viewTransform3x3); - D3DXVec3Normalize((D3DXVECTOR3*)&pShaderLight->DirectionVN, (D3DXVECTOR3*)&directionV); + D3DXVec3Transform(&directionV, (D3DXVECTOR3*)&d3dLight->Direction, &viewTransform3x3); + D3DXVec3Normalize((D3DXVECTOR3*)&pShaderLight->DirectionVN, (D3DXVECTOR3*)&directionV); - bool SpecularEnable; - if (is_pgraph_using_NV2A_Kelvin()) { - SpecularEnable = NV2ARenderStates.GetXboxRenderState(xbox::X_D3DRS_SPECULARENABLE) != FALSE; - } - else { SpecularEnable = XboxRenderStates.GetXboxRenderState(xbox::X_D3DRS_SPECULARENABLE) != FALSE; } // Map D3D light to state struct @@ -8197,14 +8197,7 @@ void UpdateFixedFunctionVertexShaderState()//(NV2ASTATE *d) if (is_pgraph_using_NV2A_Kelvin()) { //todo: check if accumulate active light ambient and add it to scene ambient is necessary or not. for (size_t i = 0; i < 8; i++) { - if (CxbxrNV2ALight8EnableMask(i) != 0) { - //accumulate LightAmbient with each active light - UpdateFixedFunctionShaderLight(i, &ffShaderState.Lights[i], &LightAmbient); - } - else { - //this simply set the light.type to 0 in order to disable it in shader. - UpdateFixedFunctionShaderLight(-1, &ffShaderState.Lights[i], &LightAmbient); - } + UpdateFixedFunctionShaderLight(CxbxrNV2ALight8EnableMask(i) != 0?i:-1, &ffShaderState.Lights[i], &LightAmbient); } // X_D3DRS_AMBIENT and X_D3DRS_BACKAMBIENT renderstates are updated by pgraph in CxbxrLazySetLights() already. but here we directly use the D3DCOLORVAL NV2A_SceneAmbient[] preventing conversion loss. Ambient = D3DXVECTOR4(NV2A_SceneAmbient[0].r, NV2A_SceneAmbient[0].g, NV2A_SceneAmbient[0].b, NV2A_SceneAmbient[0].a);//toVector(NV2ARenderStates.GetXboxRenderState(X_D3DRS_AMBIENT)); @@ -13681,15 +13674,16 @@ void CxbxrImpl_SetModelView_Calc if (pComposite != nullptr)g_xbox_transform_Composite = *pComposite; if(pInverseModelView!=nullptr)g_xbox_transform_InverseModelView = *pInverseModelView; // matModelView=matWorld*matView, we have no idea of these two Matrix. so we use unit matrix for view matrix, and matModelView matrix for matWorld + D3DMATRIX matUnit = {}; matUnit._11 = 1.0f; matUnit._22 = 1.0f; matUnit._33 = 1.0f; matUnit._44 = 1.0f; - + //CxbxrImpl_SetTransform(xbox::X_D3DTS_WORLD, pModelView); //CxbxrImpl_SetTransform(xbox::X_D3DTS_VIEW, &matUnit); - g_xbox_DirectModelView_View= matUnit; + //g_xbox_DirectModelView_View= matUnit; g_xbox_DirectModelView_World= *pModelView; // use g_xbox_transform_ViewportTransform //D3DXMATRIX matViewportTransform; diff --git a/src/core/hle/D3D8/XbPushBuffer.cpp b/src/core/hle/D3D8/XbPushBuffer.cpp index 021c625d0..aaa6caa5a 100644 --- a/src/core/hle/D3D8/XbPushBuffer.cpp +++ b/src/core/hle/D3D8/XbPushBuffer.cpp @@ -1401,15 +1401,17 @@ void CxbxrImpl_LazySetTransform(NV2AState* d) // handle DirectModelView() // todo: figure out how to compose View matrix via NV2A content. here is hack using View matrix from xbox d3d. extern D3D8TransformState d3d8TransformState; - g_xbox_DirectModelView_View= (D3DXMATRIX)d3d8TransformState.Transforms[xbox::X_D3DTS_VIEW]; - D3DXMatrixInverse((D3DXMATRIX*)&g_xbox_DirectModelView_InverseView, NULL, (D3DXMATRIX*)&g_xbox_DirectModelView_View); + //g_xbox_DirectModelView_View= (D3DXMATRIX)d3d8TransformState.Transforms[xbox::X_D3DTS_VIEW]; + //D3DXMatrixInverse((D3DXMATRIX*)&g_xbox_DirectModelView_InverseView, NULL, (D3DXMATRIX*)&g_xbox_DirectModelView_View); + /* D3DMATRIX matUnit = {}; matUnit._11 = 1.0f; matUnit._22 = 1.0f; matUnit._33 = 1.0f; matUnit._44 = 1.0f; - // TODO: this is a hack, we set cached View Matrix to unit matrix and leave all variables in the cached projection matrix. - g_NV2A_DirectModelView_View = matUnit; + g_xbox_DirectModelView_View = matUnit; + g_xbox_DirectModelView_InverseView = matUnit; + */ // use X_D3DTS_VIEW matrix from xbox side instead of unit matrix. //CxbxrImpl_GetTransform(xbox::X_D3DTRANSFORMSTATETYPE::X_D3DTS_VIEW, &g_NV2A_DirectModelView_View); //calculate inverse matrix of X_D3DTS_VIEW @@ -3104,7 +3106,6 @@ void CxbxrImpl_LazySetLights(NV2AState* d) //D3DVECTOR hv; D3DVECTOR EyeDirection = { 0.0,0.0,-1.0 }; D3DVECTOR NV2ALightdir = {}; - D3DVECTOR tmpDir; D3DVECTOR NV2ALightPosition = {}; D3DVECTOR tmpPosition; for (lightNum = 0; lightNum < 8; lightNum++) { @@ -3113,7 +3114,7 @@ void CxbxrImpl_LazySetLights(NV2AState* d) //default: NV2A_Light8[lightNum].Type = (D3DLIGHTTYPE)0; bEnable = false; - + D3DVECTOR dirNormal; switch (lightType) { case NV097_SET_LIGHT_ENABLE_MASK_LIGHT0_OFF: //light disable @@ -3124,15 +3125,15 @@ void CxbxrImpl_LazySetLights(NV2AState* d) case NV097_SET_LIGHT_ENABLE_MASK_LIGHT0_INFINITE://D3DLIGHT_DIRECTIONAL NV2A_Light8[lightNum].Type= D3DLIGHT_DIRECTIONAL; NV2A_Light8[lightNum].Range = pg->KelvinPrimitive.SetLight[lightNum].LocalRange; - NV2ALightdir.x = pg->KelvinPrimitive.SetLight[lightNum].InfiniteDirection[0]; - NV2ALightdir.y = pg->KelvinPrimitive.SetLight[lightNum].InfiniteDirection[1]; - NV2ALightdir.z = pg->KelvinPrimitive.SetLight[lightNum].InfiniteDirection[2]; + NV2ALightdir.x = -pg->KelvinPrimitive.SetLight[lightNum].InfiniteDirection[0]; + NV2ALightdir.y = -pg->KelvinPrimitive.SetLight[lightNum].InfiniteDirection[1]; + NV2ALightdir.z = -pg->KelvinPrimitive.SetLight[lightNum].InfiniteDirection[2]; - XformBy4x3(&tmpDir, &NV2ALightdir,0.0f, &g_xbox_DirectModelView_InverseView); + //XformBy4x3(&tmpDir, &NV2ALightdir,0.0f, &g_xbox_DirectModelView_InverseView); + + NormalizeVector3(&NV2ALightdir); - NV2A_Light8[lightNum].Direction.x =-tmpDir.x; - NV2A_Light8[lightNum].Direction.y =-tmpDir.y; - NV2A_Light8[lightNum].Direction.z =-tmpDir.z; + NV2A_Light8[lightNum].Direction = NV2ALightdir; bEnable = true; break; case NV097_SET_LIGHT_ENABLE_MASK_LIGHT0_LOCAL: //D3DLIGHT_POINT @@ -3143,11 +3144,11 @@ void CxbxrImpl_LazySetLights(NV2AState* d) NV2ALightPosition.y = pg->KelvinPrimitive.SetLight[lightNum].LocalPosition[1]; NV2ALightPosition.z = pg->KelvinPrimitive.SetLight[lightNum].LocalPosition[2]; - XformBy4x3(&tmpPosition, &NV2ALightPosition, 1.0f, &g_xbox_DirectModelView_InverseView); + //XformBy4x3(&tmpPosition, &NV2ALightPosition, 1.0f, &g_xbox_DirectModelView_InverseView); - NV2A_Light8[lightNum].Position.x = tmpPosition.x; - NV2A_Light8[lightNum].Position.y = tmpPosition.y; - NV2A_Light8[lightNum].Position.z = tmpPosition.z; + NV2A_Light8[lightNum].Position.x = NV2ALightPosition.x; + NV2A_Light8[lightNum].Position.y = NV2ALightPosition.y; + NV2A_Light8[lightNum].Position.z = NV2ALightPosition.z; NV2A_Light8[lightNum].Attenuation0 = pg->KelvinPrimitive.SetLight[lightNum].LocalAttenuation[0]; NV2A_Light8[lightNum].Attenuation1 = pg->KelvinPrimitive.SetLight[lightNum].LocalAttenuation[1]; NV2A_Light8[lightNum].Attenuation2 = pg->KelvinPrimitive.SetLight[lightNum].LocalAttenuation[2]; @@ -3160,32 +3161,33 @@ void CxbxrImpl_LazySetLights(NV2AState* d) NV2ALightPosition.y = pg->KelvinPrimitive.SetLight[lightNum].LocalPosition[1]; NV2ALightPosition.z = pg->KelvinPrimitive.SetLight[lightNum].LocalPosition[2]; - XformBy4x3(&tmpPosition, &NV2ALightPosition, 1.0f, &g_xbox_DirectModelView_InverseView); + //XformBy4x3(&tmpPosition, &NV2ALightPosition, 1.0f, &g_xbox_DirectModelView_InverseView); - NV2A_Light8[lightNum].Position.x = tmpPosition.x; - NV2A_Light8[lightNum].Position.y = tmpPosition.y; - NV2A_Light8[lightNum].Position.z = tmpPosition.z; + NV2A_Light8[lightNum].Position.x = NV2ALightPosition.x; + NV2A_Light8[lightNum].Position.y = NV2ALightPosition.y; + NV2A_Light8[lightNum].Position.z = NV2ALightPosition.z; NV2A_Light8[lightNum].Attenuation0 = pg->KelvinPrimitive.SetLight[lightNum].LocalAttenuation[0]; NV2A_Light8[lightNum].Attenuation1 = pg->KelvinPrimitive.SetLight[lightNum].LocalAttenuation[1]; NV2A_Light8[lightNum].Attenuation2 = pg->KelvinPrimitive.SetLight[lightNum].LocalAttenuation[2]; float Falloff_L = pg->KelvinPrimitive.SetLight[lightNum].SpotFalloff[0]; //todo: Falloff_L/Falloff_M/Falloff_N there should be 3 components but not found in Light8/Light9 float Falloff_M = pg->KelvinPrimitive.SetLight[lightNum].SpotFalloff[1]; float Falloff_N = pg->KelvinPrimitive.SetLight[lightNum].SpotFalloff[2]; - NV2ALightdir.x = pg->KelvinPrimitive.SetLight[lightNum].SpotDirection[0]; - NV2ALightdir.y = pg->KelvinPrimitive.SetLight[lightNum].SpotDirection[1]; - NV2ALightdir.z = pg->KelvinPrimitive.SetLight[lightNum].SpotDirection[2]; + NV2ALightdir.x = -pg->KelvinPrimitive.SetLight[lightNum].SpotDirection[0]; + NV2ALightdir.y = -pg->KelvinPrimitive.SetLight[lightNum].SpotDirection[1]; + NV2ALightdir.z = -pg->KelvinPrimitive.SetLight[lightNum].SpotDirection[2]; - XformBy4x3(&tmpDir, &NV2ALightdir, 0.0f, &g_xbox_DirectModelView_InverseView); + //XformBy4x3(&tmpDir, &NV2ALightdir, 0.0f, &g_xbox_DirectModelView_InverseView); - NV2A_Light8[lightNum].Direction.x = -tmpDir.x; - NV2A_Light8[lightNum].Direction.y = -tmpDir.y; - NV2A_Light8[lightNum].Direction.z = -tmpDir.z; + NV2A_Light8[lightNum].Direction.x = NV2ALightdir.x; + NV2A_Light8[lightNum].Direction.y = NV2ALightdir.y; + NV2A_Light8[lightNum].Direction.z = NV2ALightdir.z; float W = pg->KelvinPrimitive.SetLight[lightNum].SpotDirection[3]; // there is no W member of Light8 // Fixme!!! there is no eazy way to reverse Falloff from Falloff_L/Falloff_M, so I put the default value 1.0f here. NV2A_Light8[lightNum].Falloff = 1.0f; - D3DVECTOR dirNormal = NV2A_Light8[lightNum].Direction; - NormalizeVector3(&dirNormal); - float Scale = NV2A_Light8[lightNum].Direction.x / dirNormal.x; // there is no Scale member of Light8 + dirNormal = NV2A_Light8[lightNum].Direction; + NormalizeVector3(&NV2ALightdir); + float Scale = NV2A_Light8[lightNum].Direction.x / NV2ALightdir.x; // there is no Scale member of Light8 + NV2A_Light8[lightNum].Direction = NV2ALightdir; float phi2 = -1.0f*W / Scale; float theta2 = phi2 + 1.0f / Scale; NV2A_Light8[lightNum].Theta = 2.0f*acos(theta2); diff --git a/src/core/hle/Patches.cpp b/src/core/hle/Patches.cpp index 0399a4e3f..abfad54cc 100644 --- a/src/core/hle/Patches.cpp +++ b/src/core/hle/Patches.cpp @@ -169,8 +169,8 @@ std::map g_PatchTable = { PATCH_ENTRY("D3DDevice_SetTexture_4__LTCG_eax_pTexture", xbox::EMUPATCH(D3DDevice_SetTexture_4__LTCG_eax_pTexture), PATCH_HLE_D3D), PATCH_ENTRY("D3DDevice_SetTexture_4__LTCG_eax_Stage", xbox::EMUPATCH(D3DDevice_SetTexture_4__LTCG_eax_Stage), PATCH_HLE_D3D), PATCH_ENTRY("D3DDevice_SetTile", xbox::EMUPATCH(D3DDevice_SetTile), PATCH_HLE_D3D), - PATCH_ENTRY("D3DDevice_SetTransform", xbox::EMUPATCH(D3DDevice_SetTransform), PATCH_HLE_D3D), - PATCH_ENTRY("D3DDevice_SetTransform_0__LTCG_eax1_edx2", xbox::EMUPATCH(D3DDevice_SetTransform_0__LTCG_eax1_edx2), PATCH_HLE_D3D), + //PATCH_ENTRY("D3DDevice_SetTransform", xbox::EMUPATCH(D3DDevice_SetTransform), PATCH_HLE_D3D), + //PATCH_ENTRY("D3DDevice_SetTransform_0__LTCG_eax1_edx2", xbox::EMUPATCH(D3DDevice_SetTransform_0__LTCG_eax1_edx2), PATCH_HLE_D3D), //PATCH_ENTRY("D3DDevice_SetVertexData2f", xbox::EMUPATCH(D3DDevice_SetVertexData2f), PATCH_HLE_D3D), //PATCH_ENTRY("D3DDevice_SetVertexData2s", xbox::EMUPATCH(D3DDevice_SetVertexData2s), PATCH_HLE_D3D), //PATCH_ENTRY("D3DDevice_SetVertexData4f", xbox::EMUPATCH(D3DDevice_SetVertexData4f), PATCH_HLE_D3D),