From e8c63066e37ff9e820fcd865a3a7fc1fcb6e3c92 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 3 Aug 2026 07:04:49 +0200 Subject: [PATCH] Fix LOD Dither Factor regression from bc361683180bae67b3d469b023dbd87fde3bb681 on negative values --- Source/Engine/Core/Types/BaseTypes.h | 4 ++-- Source/Engine/Graphics/Materials/MaterialShader.h | 2 +- Source/Engine/Graphics/Models/Mesh.cpp | 4 ++-- Source/Engine/Graphics/Models/SkinnedMesh.cpp | 4 ++-- Source/Engine/Renderer/DrawCall.h | 2 +- Source/Engine/Renderer/RenderList.cpp | 12 ++++++------ Source/Engine/Renderer/RenderList.h | 4 ++-- Source/Shaders/MaterialCommon.hlsl | 2 +- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Source/Engine/Core/Types/BaseTypes.h b/Source/Engine/Core/Types/BaseTypes.h index 8a6c8d70b..abee1b5ba 100644 --- a/Source/Engine/Core/Types/BaseTypes.h +++ b/Source/Engine/Core/Types/BaseTypes.h @@ -8,13 +8,13 @@ typedef unsigned char byte; // Unsigned 8 bits // Unsigned base types -typedef unsigned char uint8; // 8-bit unsigned +typedef unsigned char uint8; // 8-bit unsigned typedef unsigned short uint16; // 16-bit unsigned typedef unsigned int uint32; // 32-bit unsigned typedef unsigned long long uint64; // 64-bit unsigned // Signed base types -typedef signed char int8; // 8-bit signed +typedef signed char int8; // 8-bit signed typedef signed short int16; // 16-bit signed typedef signed int int32; // 32-bit signed typedef long long int64; // 64-bit signed diff --git a/Source/Engine/Graphics/Materials/MaterialShader.h b/Source/Engine/Graphics/Materials/MaterialShader.h index c14c54851..fa3d47629 100644 --- a/Source/Engine/Graphics/Materials/MaterialShader.h +++ b/Source/Engine/Graphics/Materials/MaterialShader.h @@ -10,7 +10,7 @@ /// /// Current materials shader version. /// -#define MATERIAL_GRAPH_VERSION 185 +#define MATERIAL_GRAPH_VERSION 186 class Material; class GPUShader; diff --git a/Source/Engine/Graphics/Models/Mesh.cpp b/Source/Engine/Graphics/Models/Mesh.cpp index 44057902f..7f461b8c2 100644 --- a/Source/Engine/Graphics/Models/Mesh.cpp +++ b/Source/Engine/Graphics/Models/Mesh.cpp @@ -305,7 +305,7 @@ void Mesh::Draw(const RenderContext& renderContext, const DrawInfo& info, float drawCall.Surface.PrevWorld = info.DrawState->PrevWorld; drawCall.Surface.Lightmap = (info.Flags & StaticFlags::Lightmap) != StaticFlags::None ? info.Lightmap : nullptr; drawCall.Surface.LightmapUVsArea = info.LightmapUVs ? *info.LightmapUVs : Half4::Zero; - drawCall.Surface.LODDitherFactor = (byte)(lodDitherFactor * 255); + drawCall.Surface.LODDitherFactor = (int8)(lodDitherFactor * 127); drawCall.PerInstanceRandom = info.PerInstanceRandom; drawCall.StencilValue = info.StencilValue; #if GPU_ENABLE_DEVELOPMENT @@ -368,7 +368,7 @@ void Mesh::Draw(const RenderContextBatch& renderContextBatch, const DrawInfo& in drawCall.Surface.PrevWorld = info.DrawState->PrevWorld; drawCall.Surface.Lightmap = (info.Flags & StaticFlags::Lightmap) != StaticFlags::None ? info.Lightmap : nullptr; drawCall.Surface.LightmapUVsArea = info.LightmapUVs ? *info.LightmapUVs : Half4::Zero; - drawCall.Surface.LODDitherFactor = (byte)(lodDitherFactor * 255); + drawCall.Surface.LODDitherFactor = (int8)(lodDitherFactor * 127); drawCall.PerInstanceRandom = info.PerInstanceRandom; drawCall.StencilValue = info.StencilValue; #if GPU_ENABLE_DEVELOPMENT diff --git a/Source/Engine/Graphics/Models/SkinnedMesh.cpp b/Source/Engine/Graphics/Models/SkinnedMesh.cpp index 395f4655b..e953c0ac1 100644 --- a/Source/Engine/Graphics/Models/SkinnedMesh.cpp +++ b/Source/Engine/Graphics/Models/SkinnedMesh.cpp @@ -382,7 +382,7 @@ void SkinnedMesh::Draw(const RenderContext& renderContext, const DrawInfo& info, drawCall.Surface.SkinningBones = info.SkinningBones; drawCall.Surface.SkinningBonesOffset = info.SkinningBonesOffset; drawCall.Surface.PrevBonesOffset = info.PrevBonesOffset; - drawCall.Surface.LODDitherFactor = (byte)(lodDitherFactor * 255); + drawCall.Surface.LODDitherFactor = (int8)(lodDitherFactor * 127); drawCall.PerInstanceRandom = info.PerInstanceRandom; drawCall.StencilValue = info.StencilValue; @@ -427,7 +427,7 @@ void SkinnedMesh::Draw(const RenderContextBatch& renderContextBatch, const DrawI drawCall.Surface.SkinningBones = info.SkinningBones; drawCall.Surface.SkinningBonesOffset = info.SkinningBonesOffset; drawCall.Surface.PrevBonesOffset = info.PrevBonesOffset; - drawCall.Surface.LODDitherFactor = (byte)(lodDitherFactor * 255); + drawCall.Surface.LODDitherFactor = (int8)(lodDitherFactor * 127); drawCall.PerInstanceRandom = info.PerInstanceRandom; drawCall.StencilValue = info.StencilValue; diff --git a/Source/Engine/Renderer/DrawCall.h b/Source/Engine/Renderer/DrawCall.h index 420f2c613..8881715ef 100644 --- a/Source/Engine/Renderer/DrawCall.h +++ b/Source/Engine/Renderer/DrawCall.h @@ -199,7 +199,7 @@ struct DrawCall Half4 LightmapUVsArea; SkinningMode Skinning; int16 PrevBonesOffset; // In Matrix3x4s, can be negative - byte LODDitherFactor; // The model LOD transition dither progress. + int8 LODDitherFactor; // The model LOD transition dither progress. [-127; 127] that maps into [-1;1] inside shader GPUBuffer* SkinningBones; Float3 GeometrySize; // Object geometry size in the world (unscaled). uint32 SkinningBonesOffset; // In Matrix3x4s diff --git a/Source/Engine/Renderer/RenderList.cpp b/Source/Engine/Renderer/RenderList.cpp index b426fdea3..626af23b6 100644 --- a/Source/Engine/Renderer/RenderList.cpp +++ b/Source/Engine/Renderer/RenderList.cpp @@ -47,7 +47,7 @@ namespace } } -void ShaderObjectData::Store(const Matrix& worldMatrix, const Matrix& prevWorldMatrix, const Half4& lightmapUVsArea, const Float3& geometrySize, float perInstanceRandom, float worldDeterminantSign, byte lodDitherFactor, uint32 skinningOffset, int16 skinningPrevOffset) +void ShaderObjectData::Store(const Matrix& worldMatrix, const Matrix& prevWorldMatrix, const Half4& lightmapUVsArea, const Float3& geometrySize, float perInstanceRandom, float worldDeterminantSign, int8 lodDitherFactor, uint32 skinningOffset, int16 skinningPrevOffset) { Float2 lightmapUVsAreaPackedAliased = *(Float2*)&lightmapUVsArea; Raw[0] = Float4(worldMatrix.M11, worldMatrix.M12, worldMatrix.M13, worldMatrix.M41); @@ -57,15 +57,15 @@ void ShaderObjectData::Store(const Matrix& worldMatrix, const Matrix& prevWorldM Raw[4] = Float4(prevWorldMatrix.M21, prevWorldMatrix.M22, prevWorldMatrix.M23, prevWorldMatrix.M42); Raw[5] = Float4(prevWorldMatrix.M31, prevWorldMatrix.M32, prevWorldMatrix.M33, prevWorldMatrix.M43); Raw[6] = Float4(geometrySize, perInstanceRandom); - // 0-3 bits: LOD Dither Factor (0-1 range mapped to 0-255) - // 4 bit: World Determinant Sign (0 for normal or 1 for inversed) - // 5-15 bits: unused + // 0-7 bits: LOD Dither Factor (0-1 range mapped to 0-255) with separate sign at 7th bit + // 8 bit: World Determinant Sign (0 for normal or 1 for inversed) + // 9-15 bits: unused // 16-31 bits: Offset in Skinning Bones buffer for previous frame bones (can be negative) - uint32 packed7x = (uint32)lodDitherFactor + (worldDeterminantSign < 0 ? 256 : 0) + ((skinningPrevOffset + 32760) << 16); + uint32 packed7x = (uint32)Math::Abs(lodDitherFactor) + (lodDitherFactor < 0 ? 128 : 0) + (worldDeterminantSign < 0 ? 256 : 0) + ((skinningPrevOffset + 32760) << 16); Raw[7] = Float4(*(float*)&packed7x, *(float*)&skinningOffset, lightmapUVsAreaPackedAliased.X, lightmapUVsAreaPackedAliased.Y); } -void ShaderObjectData::Load(Matrix& worldMatrix, Matrix& prevWorldMatrix, Half4& lightmapUVsArea, Float3& geometrySize, float& perInstanceRandom, float& worldDeterminantSign, byte& lodDitherFactor, uint32& skinningOffset, int16& skinningPrevOffset) const +void ShaderObjectData::Load(Matrix& worldMatrix, Matrix& prevWorldMatrix, Half4& lightmapUVsArea, Float3& geometrySize, float& perInstanceRandom, float& worldDeterminantSign, int8& lodDitherFactor, uint32& skinningOffset, int16& skinningPrevOffset) const { worldMatrix.SetRow1(Float4(Float3(Raw[0]), 0.0f)); worldMatrix.SetRow2(Float4(Float3(Raw[1]), 0.0f)); diff --git a/Source/Engine/Renderer/RenderList.h b/Source/Engine/Renderer/RenderList.h index 7895cabda..957778e18 100644 --- a/Source/Engine/Renderer/RenderList.h +++ b/Source/Engine/Renderer/RenderList.h @@ -693,8 +693,8 @@ GPU_CB_STRUCT(ShaderObjectData { Float4 Raw[8]; - void FLAXENGINE_API Store(const Matrix& worldMatrix, const Matrix& prevWorldMatrix, const Half4& lightmapUVsAreaPacked, const Float3& geometrySize, float perInstanceRandom = 0.0f, float worldDeterminantSign = 1.0f, byte lodDitherFactor = 0, uint32 skinningOffset = 0, int16 skinningPrevOffset = 0); - void FLAXENGINE_API Load(Matrix& worldMatrix, Matrix& prevWorldMatrix, Half4& lightmapUVsArea, Float3& geometrySize, float& perInstanceRandom, float& worldDeterminantSign, byte& lodDitherFactor, uint32& skinningOffset, int16& prevBonesOffset) const; + void FLAXENGINE_API Store(const Matrix& worldMatrix, const Matrix& prevWorldMatrix, const Half4& lightmapUVsAreaPacked, const Float3& geometrySize, float perInstanceRandom = 0.0f, float worldDeterminantSign = 1.0f, int8 lodDitherFactor = 0, uint32 skinningOffset = 0, int16 skinningPrevOffset = 0); + void FLAXENGINE_API Load(Matrix& worldMatrix, Matrix& prevWorldMatrix, Half4& lightmapUVsArea, Float3& geometrySize, float& perInstanceRandom, float& worldDeterminantSign, int8& lodDitherFactor, uint32& skinningOffset, int16& prevBonesOffset) const; FORCE_INLINE void Store(const DrawCall& drawCall) { diff --git a/Source/Shaders/MaterialCommon.hlsl b/Source/Shaders/MaterialCommon.hlsl index 6ca9d8216..09530eb16 100644 --- a/Source/Shaders/MaterialCommon.hlsl +++ b/Source/Shaders/MaterialCommon.hlsl @@ -119,7 +119,7 @@ ObjectData LoadObject(Buffer objectsBuffer, uint objectIndex) object.PerInstanceRandom = vector6.w; uint packed7x = asuint(vector7.x); object.WorldDeterminantSign = (packed7x & 256) == 256 ? -1.0f : 1.0f; - object.LODDitherFactor = (packed7x & 255) / 255.0f; + object.LODDitherFactor = (packed7x & 127) / 127.0f * ((packed7x & 128) == 128 ? -1.0f : 1.0f); object.SkinningOffset = asuint(vector7.y); object.PrevBonesOffset = (int)(packed7x >> 16) - 32760; object.LightmapArea.xy = UnpackHalf2(asuint(vector7.z));