remove usages of xbox view matrix in fixed mode vertex shader state and light state setup.

unpatch D3DDevice_SetTransform()
This commit is contained in:
Jack Chen 2023-11-18 21:26:29 +08:00
parent fa14a4ee33
commit 1f0feed255
3 changed files with 62 additions and 66 deletions

View File

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

View File

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

View File

@ -169,8 +169,8 @@ std::map<const std::string, const xbox_patch_t> 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),