diff --git a/src/core/hle/D3D8/Direct3D9/FixedFunctionPixelShader.hlsl b/src/core/hle/D3D8/Direct3D9/FixedFunctionPixelShader.hlsl index bae54ed1b..6bcb9908b 100644 --- a/src/core/hle/D3D8/Direct3D9/FixedFunctionPixelShader.hlsl +++ b/src/core/hle/D3D8/Direct3D9/FixedFunctionPixelShader.hlsl @@ -174,6 +174,14 @@ TextureArgs ExecuteTextureStage( // Sample the texture float4 t; int type = TextureSampleType[i]; + // Divide texcoords by w when sampling + // Which corresponds to D3DTTFF_PROJECTED behaviour + // The w component can be set by titles in vertex shaders + // without using texture transform flags + // Test case: DoA 3 reflections on 'Ice Stage' + //float4 coords;// = TexCoords[i].xyzw / TexCoords[i].w; + if (TexCoords[i].w > 1.0) + TexCoords[i].xyzw = TexCoords[i].xyzw / TexCoords[i].w; if (type == SAMPLE_NONE) t = 1; // Test case JSRF else if (type == SAMPLE_2D) @@ -237,8 +245,22 @@ TextureArgs ExecuteTextureStage( float4 main(const PS_INPUT input) : COLOR { +// Calculate the fog factor + // Some of this might be better done in the pixel shader? + float fogFactor; + if (state.FogTableMode == FOG_TABLE_NONE) + fogFactor = input.iFog; + if (state.FogTableMode == FOG_TABLE_EXP) + fogFactor = 1 / exp(input.iFog * state.FogDensity); // 1 / e^(d * density) + if (state.FogTableMode == FOG_TABLE_EXP2) + fogFactor = 1 / exp(pow(input.iFog * state.FogDensity, 2)); // 1 / e^((d * density)^2) + if (state.FogTableMode == FOG_TABLE_LINEAR) + fogFactor = (state.FogEnd - input.iFog) / (state.FogEnd - state.FogStart); // (end - d) / (end - start) + if (state.FogEnable == 0) + fogFactor = 1; + TexCoords = input.iT; - + // Each stage is passed and returns // a set of texture arguments // And will usually update the CURRENT value @@ -284,7 +306,7 @@ float4 main(const PS_INPUT input) : COLOR { // Add fog if enabled if (state.FogEnable) { - ctx.CURRENT.rgb = lerp(state.FogColor.rgb, ctx.CURRENT.rgb, clamp(input.iFog, 0, 1)); + ctx.CURRENT.rgb = lerp(state.FogColor.rgb, ctx.CURRENT.rgb, clamp(fogFactor, 0, 1)); } // Add specular if enabled diff --git a/src/core/hle/D3D8/Direct3D9/FixedFunctionPixelShader.hlsli b/src/core/hle/D3D8/Direct3D9/FixedFunctionPixelShader.hlsli index f2458947c..4c8d2ccbe 100644 --- a/src/core/hle/D3D8/Direct3D9/FixedFunctionPixelShader.hlsli +++ b/src/core/hle/D3D8/Direct3D9/FixedFunctionPixelShader.hlsli @@ -63,10 +63,16 @@ namespace FixedFunctionPixelShader { const float X_D3DTA_COMPLEMENT = 0x00000010; // take 1.0 - x (read modifier) const float X_D3DTA_ALPHAREPLICATE = 0x00000020; // replicate alpha to color components (read modifier) - const int SAMPLE_NONE = 0; - const int SAMPLE_2D = 1; - const int SAMPLE_3D = 2; - const int SAMPLE_CUBE = 3; + const int SAMPLE_NONE = 0; + const int SAMPLE_2D = 1; + const int SAMPLE_3D = 2; + const int SAMPLE_CUBE = 3; + + // https://docs.microsoft.com/en-us/windows/win32/direct3d9/fog-formulas + const float FOG_TABLE_NONE = 0; + const float FOG_TABLE_EXP = 1; + const float FOG_TABLE_EXP2 = 2; + const float FOG_TABLE_LINEAR = 3; // This state is passed to the shader struct PsTextureStageState { @@ -121,11 +127,15 @@ namespace FixedFunctionPixelShader { struct FixedFunctionPixelShaderState { alignas(16) arr(stages, PsTextureStageState, 4); - alignas(16) float4 TextureFactor; - alignas(16) float SpecularEnable; - alignas(16) float FogEnable; - alignas(16) float3 FogColor; - }; + alignas(16) float4 TextureFactor; + alignas(16) float SpecularEnable; + alignas(16) float FogEnable; + alignas(16) float3 FogColor; + alignas(16) float FogTableMode; + alignas(16) float FogDensity; + alignas(16) float FogStart; + alignas(16) float FogEnd; + }; #ifdef __cplusplus } // FixedFunctionPixelShader namespace #endif diff --git a/src/core/hle/D3D8/Direct3D9/FixedFunctionVertexShader.hlsl b/src/core/hle/D3D8/Direct3D9/FixedFunctionVertexShader.hlsl index 68d9aa7cb..87a7ecc52 100644 --- a/src/core/hle/D3D8/Direct3D9/FixedFunctionVertexShader.hlsl +++ b/src/core/hle/D3D8/Direct3D9/FixedFunctionVertexShader.hlsl @@ -339,9 +339,9 @@ float4 DoTexCoord(const uint stage, const VS_INPUT xIn) // TODO move alongside the texture transformation when it stops angering the HLSL compiler const float componentCount = state.TexCoordComponentCount[texCoordIndex]; if (componentCount == 1) - texCoord.yzw = float3(1, 0, 0); + texCoord.yzw = float3(0, 0, 1); if (componentCount == 2) - texCoord.zw = float2(1, 0); + texCoord.zw = float2(0, 1); if (componentCount == 3) texCoord.w = 1; } // Generate texture coordinates @@ -378,14 +378,15 @@ float4 DoTexCoord(const uint stage, const VS_INPUT xIn) // Test case: ProjectedTexture sample, which uses 3 coordinates // We'll need to implement the divide when D3D stops handling it for us? // https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dtexturetransformflags + // padding makes no differences in LLE. LLE works with ProjectedTexture sample without padding, but to be devided by w is necessary. + if (projected) { - if (countFlag == 1) - texCoord.yzw = texCoord.x; - if (countFlag == 2) - texCoord.zw = texCoord.y; - if (countFlag == 3) - texCoord.w = texCoord.z; + //if (countFlag == 1) + //texCoord.yz = texCoord.x; + //if (countFlag == 2) + //texCoord.z = texCoord.y; + //texCoord.xyzw = texCoord.xyzw / texCoord.w; } return texCoord; diff --git a/src/core/hle/D3D8/XbPixelShader.cpp b/src/core/hle/D3D8/XbPixelShader.cpp index 655a17618..86cd83f9a 100644 --- a/src/core/hle/D3D8/XbPixelShader.cpp +++ b/src/core/hle/D3D8/XbPixelShader.cpp @@ -973,7 +973,10 @@ void UpdateFixedFunctionPixelShaderState() ffPsState.SpecularEnable = XboxRenderStates.GetXboxRenderState(xbox::X_D3DRS_SPECULARENABLE); ffPsState.FogEnable = XboxRenderStates.GetXboxRenderState(xbox::X_D3DRS_FOGENABLE); ffPsState.FogColor = (D3DXVECTOR3)((D3DXCOLOR)XboxRenderStates.GetXboxRenderState(xbox::X_D3DRS_FOGCOLOR)); - + ffPsState.FogTableMode = XboxRenderStates.GetXboxRenderState(xbox::_X_D3DRENDERSTATETYPE::X_D3DRS_FOGTABLEMODE); + ffPsState.FogDensity = XboxRenderStates.GetXboxRenderStateAsFloat(xbox::_X_D3DRENDERSTATETYPE::X_D3DRS_FOGDENSITY); + ffPsState.FogStart = XboxRenderStates.GetXboxRenderStateAsFloat(xbox::_X_D3DRENDERSTATETYPE::X_D3DRS_FOGSTART); + ffPsState.FogEnd = XboxRenderStates.GetXboxRenderStateAsFloat(xbox::_X_D3DRENDERSTATETYPE::X_D3DRS_FOGEND); // Texture state for (int i = 0; i < xbox::X_D3DTS_STAGECOUNT; i++) {