Optimize world matrix storage for drawable objects to use Matrix3x4 instead of full matrix

This commit is contained in:
Wojtek Figat
2024-03-26 11:29:01 +01:00
parent cdbb2cc813
commit 2dfb1058b2
15 changed files with 134 additions and 105 deletions

View File

@@ -26,7 +26,7 @@ struct RibbonInput
// Primary constant buffer (with additional material parameters) // Primary constant buffer (with additional material parameters)
META_CB_BEGIN(0, Data) META_CB_BEGIN(0, Data)
float4x4 WorldMatrix; float4x3 WorldMatrix;
uint SortedIndicesOffset; uint SortedIndicesOffset;
float PerInstanceRandom; float PerInstanceRandom;
int ParticleStride; int ParticleStride;
@@ -45,7 +45,7 @@ int RibbonWidthOffset;
int RibbonTwistOffset; int RibbonTwistOffset;
int RibbonFacingVectorOffset; int RibbonFacingVectorOffset;
uint RibbonSegmentCount; uint RibbonSegmentCount;
float4x4 WorldMatrixInverseTransposed; float4x3 WorldMatrixInverseTransposed;
@1META_CB_END @1META_CB_END
// Particles attributes buffer // Particles attributes buffer
@@ -138,7 +138,7 @@ MaterialInput GetMaterialInput(PixelInput input)
#if USE_INSTANCING #if USE_INSTANCING
#define GetInstanceTransform(input) float4x4(float4(input.InstanceTransform1.xyz, 0.0f), float4(input.InstanceTransform2.xyz, 0.0f), float4(input.InstanceTransform3.xyz, 0.0f), float4(input.InstanceOrigin.xyz, 1.0f)) #define GetInstanceTransform(input) float4x4(float4(input.InstanceTransform1.xyz, 0.0f), float4(input.InstanceTransform2.xyz, 0.0f), float4(input.InstanceTransform3.xyz, 0.0f), float4(input.InstanceOrigin.xyz, 1.0f))
#else #else
#define GetInstanceTransform(input) WorldMatrix; #define GetInstanceTransform(input) ToMatrix4x4(WorldMatrix);
#endif #endif
// Removes the scale vector from the local to world transformation matrix (supports instancing) // Removes the scale vector from the local to world transformation matrix (supports instancing)
@@ -264,12 +264,12 @@ float4 GetParticleVec4(uint particleIndex, int offset)
float3 TransformParticlePosition(float3 input) float3 TransformParticlePosition(float3 input)
{ {
return mul(float4(input, 1.0f), WorldMatrix).xyz; return mul(float4(input, 1.0f), ToMatrix4x4(WorldMatrix)).xyz;
} }
float3 TransformParticleVector(float3 input) float3 TransformParticleVector(float3 input)
{ {
return mul(float4(input, 0.0f), WorldMatrixInverseTransposed).xyz; return mul(float4(input, 0.0f), ToMatrix4x4(WorldMatrixInverseTransposed)).xyz;
} }
@8 @8
@@ -333,7 +333,7 @@ VertexOutput VS_Sprite(SpriteInput input, uint particleIndex : SV_InstanceID)
float2 spriteSize = GetParticleVec2(particleIndex, SpriteSizeOffset); float2 spriteSize = GetParticleVec2(particleIndex, SpriteSizeOffset);
int spriteFacingMode = SpriteFacingModeOffset != -1 ? GetParticleInt(particleIndex, SpriteFacingModeOffset) : -1; int spriteFacingMode = SpriteFacingModeOffset != -1 ? GetParticleInt(particleIndex, SpriteFacingModeOffset) : -1;
float4x4 world = WorldMatrix; float4x4 world = ToMatrix4x4(WorldMatrix);
float3x3 eulerMatrix = EulerMatrix(radians(particleRotation)); float3x3 eulerMatrix = EulerMatrix(radians(particleRotation));
float3x3 viewRot = transpose((float3x3)ViewMatrix); float3x3 viewRot = transpose((float3x3)ViewMatrix);
float3 position = mul(float4(particlePosition, 1), world).xyz; float3 position = mul(float4(particlePosition, 1), world).xyz;
@@ -463,11 +463,12 @@ VertexOutput VS_Model(ModelInput input, uint particleIndex : SV_InstanceID)
} }
// Read particle data // Read particle data
float4x4 worldMatrix = ToMatrix4x4(WorldMatrix);
float3 particlePosition = GetParticleVec3(particleIndex, PositionOffset); float3 particlePosition = GetParticleVec3(particleIndex, PositionOffset);
float3 particleScale = GetParticleVec3(particleIndex, ScaleOffset); float3 particleScale = GetParticleVec3(particleIndex, ScaleOffset);
float3 particleRotation = GetParticleVec3(particleIndex, RotationOffset); float3 particleRotation = GetParticleVec3(particleIndex, RotationOffset);
int modelFacingMode = ModelFacingModeOffset != -1 ? GetParticleInt(particleIndex, ModelFacingModeOffset) : -1; int modelFacingMode = ModelFacingModeOffset != -1 ? GetParticleInt(particleIndex, ModelFacingModeOffset) : -1;
float3 position = mul(float4(particlePosition, 1), WorldMatrix).xyz; float3 position = mul(float4(particlePosition, 1), worldMatrix).xyz;
// Compute final vertex position in the world // Compute final vertex position in the world
float3x3 eulerMatrix = EulerMatrix(radians(particleRotation)); float3x3 eulerMatrix = EulerMatrix(radians(particleRotation));
@@ -506,7 +507,7 @@ VertexOutput VS_Model(ModelInput input, uint particleIndex : SV_InstanceID)
world = mul(world, scaleMatrix); world = mul(world, scaleMatrix);
} }
world = transpose(world); world = transpose(world);
world = mul(world, WorldMatrix); world = mul(world, worldMatrix);
// Calculate the vertex position in world space // Calculate the vertex position in world space
output.WorldPosition = mul(float4(input.Position, 1), world).xyz; output.WorldPosition = mul(float4(input.Position, 1), world).xyz;
@@ -520,12 +521,12 @@ VertexOutput VS_Model(ModelInput input, uint particleIndex : SV_InstanceID)
#if USE_VERTEX_COLOR #if USE_VERTEX_COLOR
output.VertexColor = input.Color; output.VertexColor = input.Color;
#endif #endif
output.InstanceOrigin = WorldMatrix[3].xyz; output.InstanceOrigin = worldMatrix[3].xyz;
output.InstanceParams = PerInstanceRandom; output.InstanceParams = PerInstanceRandom;
// Calculate tanget space to world space transformation matrix for unit vectors // Calculate tanget space to world space transformation matrix for unit vectors
half3x3 tangentToLocal = CalcTangentToLocal(input); half3x3 tangentToLocal = CalcTangentToLocal(input);
half3x3 tangentToWorld = CalcTangentToWorld(WorldMatrix, tangentToLocal); half3x3 tangentToWorld = CalcTangentToWorld(worldMatrix, tangentToLocal);
output.TBN = tangentToWorld; output.TBN = tangentToWorld;
// Get material input params if need to evaluate any material property // Get material input params if need to evaluate any material property
@@ -625,12 +626,13 @@ VertexOutput VS_Ribbon(RibbonInput input, uint vertexIndex : SV_VertexID)
#if USE_VERTEX_COLOR #if USE_VERTEX_COLOR
output.VertexColor = 1; output.VertexColor = 1;
#endif #endif
output.InstanceOrigin = WorldMatrix[3].xyz; float4x4 world = ToMatrix4x4(WorldMatrix);
output.InstanceOrigin = world[3].xyz;
output.InstanceParams = PerInstanceRandom; output.InstanceParams = PerInstanceRandom;
// Calculate tanget space to world space transformation matrix for unit vectors // Calculate tanget space to world space transformation matrix for unit vectors
half3x3 tangentToLocal = float3x3(tangentRight, tangentUp, cross(tangentRight, tangentUp)); half3x3 tangentToLocal = float3x3(tangentRight, tangentUp, cross(tangentRight, tangentUp));
half3x3 tangentToWorld = CalcTangentToWorld(WorldMatrix, tangentToLocal); half3x3 tangentToWorld = CalcTangentToWorld(world, tangentToLocal);
output.TBN = tangentToWorld; output.TBN = tangentToWorld;
// Get material input params if need to evaluate any material property // Get material input params if need to evaluate any material property

View File

@@ -10,8 +10,8 @@
@7 @7
// Primary constant buffer (with additional material parameters) // Primary constant buffer (with additional material parameters)
META_CB_BEGIN(0, Data) META_CB_BEGIN(0, Data)
float4x4 WorldMatrix; float4x3 WorldMatrix;
float4x4 PrevWorldMatrix; float4x3 PrevWorldMatrix;
float2 Dummy0; float2 Dummy0;
float LODDitherFactor; float LODDitherFactor;
float PerInstanceRandom; float PerInstanceRandom;
@@ -171,7 +171,7 @@ MaterialInput GetMaterialInput(PixelInput input)
#if USE_INSTANCING #if USE_INSTANCING
#define CalculateInstanceTransform(input) float4x4 world = GetInstanceTransform(input); output.Geometry.InstanceTransform1 = input.InstanceTransform1.xyz; output.Geometry.InstanceTransform2 = input.InstanceTransform2.xyz; output.Geometry.InstanceTransform3 = input.InstanceTransform3.xyz; #define CalculateInstanceTransform(input) float4x4 world = GetInstanceTransform(input); output.Geometry.InstanceTransform1 = input.InstanceTransform1.xyz; output.Geometry.InstanceTransform2 = input.InstanceTransform2.xyz; output.Geometry.InstanceTransform3 = input.InstanceTransform3.xyz;
#else #else
#define CalculateInstanceTransform(input) float4x4 world = WorldMatrix; output.Geometry.InstanceTransform1 = world[0].xyz; output.Geometry.InstanceTransform2 = world[1].xyz; output.Geometry.InstanceTransform3 = world[2].xyz; #define CalculateInstanceTransform(input) float4x4 world = ToMatrix4x4(WorldMatrix); output.Geometry.InstanceTransform1 = world[0].xyz; output.Geometry.InstanceTransform2 = world[1].xyz; output.Geometry.InstanceTransform3 = world[2].xyz;
#endif #endif
// Removes the scale vector from the local to world transformation matrix (supports instancing) // Removes the scale vector from the local to world transformation matrix (supports instancing)
@@ -328,7 +328,7 @@ VertexOutput VS(ModelInput input)
// Compute world space vertex position // Compute world space vertex position
CalculateInstanceTransform(input); CalculateInstanceTransform(input);
output.Geometry.WorldPosition = mul(float4(input.Position.xyz, 1), world).xyz; output.Geometry.WorldPosition = mul(float4(input.Position.xyz, 1), world).xyz;
output.Geometry.PrevWorldPosition = mul(float4(input.Position.xyz, 1), PrevWorldMatrix).xyz; output.Geometry.PrevWorldPosition = mul(float4(input.Position.xyz, 1), ToMatrix4x4(PrevWorldMatrix)).xyz;
// Compute clip space position // Compute clip space position
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix); output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
@@ -402,7 +402,7 @@ float4 VS_Depth(ModelInput_PosOnly input) : SV_Position
#if USE_INSTANCING #if USE_INSTANCING
float4x4 world = GetInstanceTransform(input); float4x4 world = GetInstanceTransform(input);
#else #else
float4x4 world = WorldMatrix; float4x4 world = ToMatrix4x4(WorldMatrix);
#endif #endif
float3 worldPosition = mul(float4(input.Position.xyz, 1), world).xyz; float3 worldPosition = mul(float4(input.Position.xyz, 1), world).xyz;
float4 position = mul(float4(worldPosition, 1), ViewProjectionMatrix); float4 position = mul(float4(worldPosition, 1), ViewProjectionMatrix);
@@ -511,9 +511,9 @@ VertexOutput VS_Skinned(ModelInput_Skinned input)
output.Geometry.WorldPosition = mul(float4(position, 1), world).xyz; output.Geometry.WorldPosition = mul(float4(position, 1), world).xyz;
#if PER_BONE_MOTION_BLUR #if PER_BONE_MOTION_BLUR
float3 prevPosition = SkinPrevPosition(input); float3 prevPosition = SkinPrevPosition(input);
output.Geometry.PrevWorldPosition = mul(float4(prevPosition, 1), PrevWorldMatrix).xyz; output.Geometry.PrevWorldPosition = mul(float4(prevPosition, 1), ToMatrix4x4(PrevWorldMatrix)).xyz;
#else #else
output.Geometry.PrevWorldPosition = mul(float4(position, 1), PrevWorldMatrix).xyz; output.Geometry.PrevWorldPosition = mul(float4(position, 1), ToMatrix4x4(PrevWorldMatrix)).xyz;
#endif #endif
// Compute clip space position // Compute clip space position

View File

@@ -17,7 +17,7 @@
@7 @7
// Primary constant buffer (with additional material parameters) // Primary constant buffer (with additional material parameters)
META_CB_BEGIN(0, Data) META_CB_BEGIN(0, Data)
float4x4 WorldMatrix; float4x3 WorldMatrix;
float3 WorldInvScale; float3 WorldInvScale;
float WorldDeterminantSign; float WorldDeterminantSign;
float PerInstanceRandom; float PerInstanceRandom;
@@ -194,7 +194,7 @@ float3 TransformViewVectorToWorld(MaterialInput input, float3 viewVector)
// Transforms a vector from local space to world space // Transforms a vector from local space to world space
float3 TransformLocalVectorToWorld(MaterialInput input, float3 localVector) float3 TransformLocalVectorToWorld(MaterialInput input, float3 localVector)
{ {
float3x3 localToWorld = (float3x3)WorldMatrix; float3x3 localToWorld = (float3x3)ToMatrix4x4(WorldMatrix);
//localToWorld = RemoveScaleFromLocalToWorld(localToWorld); //localToWorld = RemoveScaleFromLocalToWorld(localToWorld);
return mul(localVector, localToWorld); return mul(localVector, localToWorld);
} }
@@ -202,7 +202,7 @@ float3 TransformLocalVectorToWorld(MaterialInput input, float3 localVector)
// Transforms a vector from local space to world space // Transforms a vector from local space to world space
float3 TransformWorldVectorToLocal(MaterialInput input, float3 worldVector) float3 TransformWorldVectorToLocal(MaterialInput input, float3 worldVector)
{ {
float3x3 localToWorld = (float3x3)WorldMatrix; float3x3 localToWorld = (float3x3)ToMatrix4x4(WorldMatrix);
//localToWorld = RemoveScaleFromLocalToWorld(localToWorld); //localToWorld = RemoveScaleFromLocalToWorld(localToWorld);
return mul(localToWorld, worldVector); return mul(localToWorld, worldVector);
} }
@@ -210,7 +210,7 @@ float3 TransformWorldVectorToLocal(MaterialInput input, float3 worldVector)
// Gets the current object position // Gets the current object position
float3 GetObjectPosition(MaterialInput input) float3 GetObjectPosition(MaterialInput input)
{ {
return WorldMatrix[3].xyz; return ToMatrix4x4(WorldMatrix)[3].xyz;
} }
// Gets the current object size // Gets the current object size
@@ -365,7 +365,8 @@ VertexOutput VS(TerrainVertexInput input)
float3 position = float3(positionXZ.x, height, positionXZ.y); float3 position = float3(positionXZ.x, height, positionXZ.y);
// Compute world space vertex position // Compute world space vertex position
output.Geometry.WorldPosition = mul(float4(position, 1), WorldMatrix).xyz; float4x4 worldMatrix = ToMatrix4x4(WorldMatrix);
output.Geometry.WorldPosition = mul(float4(position, 1), worldMatrix).xyz;
// Compute clip space position // Compute clip space position
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix); output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
@@ -389,7 +390,7 @@ VertexOutput VS(TerrainVertexInput input)
// Compute world space normal vector // Compute world space normal vector
float3x3 tangentToLocal = CalcTangentBasisFromWorldNormal(normal); float3x3 tangentToLocal = CalcTangentBasisFromWorldNormal(normal);
float3x3 tangentToWorld = CalcTangentToWorld(WorldMatrix, tangentToLocal); float3x3 tangentToWorld = CalcTangentToWorld(worldMatrix, tangentToLocal);
output.Geometry.WorldNormal = tangentToWorld[2]; output.Geometry.WorldNormal = tangentToWorld[2];
// Get material input params if need to evaluate any material property // Get material input params if need to evaluate any material property

View File

@@ -13,8 +13,8 @@
// Primary constant buffer (with additional material parameters) // Primary constant buffer (with additional material parameters)
META_CB_BEGIN(0, Data) META_CB_BEGIN(0, Data)
float4x4 InverseViewProjectionMatrix; float4x4 InverseViewProjectionMatrix;
float4x4 WorldMatrix; float4x3 WorldMatrix;
float4x4 WorldMatrixInverseTransposed; float4x3 WorldMatrixInverseTransposed;
float3 GridSize; float3 GridSize;
float PerInstanceRandom; float PerInstanceRandom;
float Dummy0; float Dummy0;
@@ -49,7 +49,7 @@ struct MaterialInput
#endif #endif
}; };
#define GetInstanceTransform(input) WorldMatrix; #define GetInstanceTransform(input) ToMatrix4x4(WorldMatrix);
// Removes the scale vector from the local to world transformation matrix (supports instancing) // Removes the scale vector from the local to world transformation matrix (supports instancing)
float3x3 RemoveScaleFromLocalToWorld(float3x3 localToWorld) float3x3 RemoveScaleFromLocalToWorld(float3x3 localToWorld)
@@ -170,12 +170,12 @@ float4 GetParticleVec4(uint particleIndex, int offset)
float3 TransformParticlePosition(float3 input) float3 TransformParticlePosition(float3 input)
{ {
return mul(float4(input, 1.0f), WorldMatrix).xyz; return mul(float4(input, 1.0f), ToMatrix4x4(WorldMatrix)).xyz;
} }
float3 TransformParticleVector(float3 input) float3 TransformParticleVector(float3 input)
{ {
return mul(float4(input, 0.0f), WorldMatrixInverseTransposed).xyz; return mul(float4(input, 0.0f), ToMatrix4x4(WorldMatrixInverseTransposed)).xyz;
} }
@8 @8
@@ -219,7 +219,7 @@ void PS_VolumetricFog(Quad_GS2PS input, out float4 VBufferA : SV_Target0, out fl
materialInput.ParticleIndex = ParticleIndex; materialInput.ParticleIndex = ParticleIndex;
materialInput.TBN = float3x3(float3(1, 0, 0), float3(0, 1, 0), float3(0, 0, 1)); materialInput.TBN = float3x3(float3(1, 0, 0), float3(0, 1, 0), float3(0, 0, 1));
materialInput.TwoSidedSign = 1.0f; materialInput.TwoSidedSign = 1.0f;
materialInput.InstanceOrigin = WorldMatrix[3].xyz; materialInput.InstanceOrigin = ToMatrix4x4(WorldMatrix)[3].xyz;
materialInput.InstanceParams = PerInstanceRandom; materialInput.InstanceParams = PerInstanceRandom;
materialInput.SvPosition = clipPos; materialInput.SvPosition = clipPos;
Material material = GetMaterialPS(materialInput); Material material = GetMaterialPS(materialInput);

View File

@@ -2,6 +2,7 @@
#include "Matrix.h" #include "Matrix.h"
#include "Matrix3x3.h" #include "Matrix3x3.h"
#include "Matrix3x4.h"
#include "Vector2.h" #include "Vector2.h"
#include "Quaternion.h" #include "Quaternion.h"
#include "Transform.h" #include "Transform.h"
@@ -887,3 +888,39 @@ Float4 Matrix::TransformPosition(const Matrix& m, const Float4& v)
m.Values[0][3] * v.Raw[0] + m.Values[1][3] * v.Raw[1] + m.Values[2][3] * v.Raw[2] + m.Values[3][3] * v.Raw[3] m.Values[0][3] * v.Raw[0] + m.Values[1][3] * v.Raw[1] + m.Values[2][3] * v.Raw[2] + m.Values[3][3] * v.Raw[3]
); );
} }
void Matrix3x4::SetMatrix(const Matrix& m)
{
const float* src = m.Raw;
float* dst = Raw;
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = src[3];
dst[4] = src[4];
dst[5] = src[5];
dst[6] = src[6];
dst[7] = src[7];
dst[8] = src[8];
dst[9] = src[9];
dst[10] = src[10];
dst[11] = src[11];
}
void Matrix3x4::SetMatrixTranspose(const Matrix& m)
{
const float* src = m.Raw;
float* dst = Raw;
dst[0] = src[0];
dst[1] = src[4];
dst[2] = src[8];
dst[3] = src[12];
dst[4] = src[1];
dst[5] = src[5];
dst[6] = src[9];
dst[7] = src[13];
dst[8] = src[2];
dst[9] = src[6];
dst[10] = src[10];
dst[11] = src[14];
}

View File

@@ -9,43 +9,14 @@
/// </summary> /// </summary>
struct FLAXENGINE_API Matrix3x4 struct FLAXENGINE_API Matrix3x4
{ {
float M[3][4]; union
void SetMatrix(const Matrix& m)
{ {
const float* src = m.Raw; float Values[3][4];
float* dst = &M[0][0]; float Raw[12];
dst[0] = src[0]; };
dst[1] = src[1];
dst[2] = src[2];
dst[3] = src[3];
dst[4] = src[4];
dst[5] = src[5];
dst[6] = src[6];
dst[7] = src[7];
dst[8] = src[8];
dst[9] = src[9];
dst[10] = src[10];
dst[11] = src[11];
}
void SetMatrixTranspose(const Matrix& m) void SetMatrix(const Matrix& m);
{ void SetMatrixTranspose(const Matrix& m);
const float* src = m.Raw;
float* dst = &M[0][0];
dst[0] = src[0];
dst[1] = src[4];
dst[2] = src[8];
dst[3] = src[12];
dst[4] = src[1];
dst[5] = src[5];
dst[6] = src[9];
dst[7] = src[13];
dst[8] = src[2];
dst[9] = src[6];
dst[10] = src[10];
dst[11] = src[14];
}
}; };
template<> template<>

View File

@@ -3,6 +3,7 @@
#include "DeferredMaterialShader.h" #include "DeferredMaterialShader.h"
#include "MaterialShaderFeatures.h" #include "MaterialShaderFeatures.h"
#include "MaterialParams.h" #include "MaterialParams.h"
#include "Engine/Core/Math/Matrix3x4.h"
#include "Engine/Graphics/RenderBuffers.h" #include "Engine/Graphics/RenderBuffers.h"
#include "Engine/Graphics/RenderView.h" #include "Engine/Graphics/RenderView.h"
#include "Engine/Renderer/DrawCall.h" #include "Engine/Renderer/DrawCall.h"
@@ -17,8 +18,8 @@
#include "Engine/Graphics/RenderTask.h" #include "Engine/Graphics/RenderTask.h"
PACK_STRUCT(struct DeferredMaterialShaderData { PACK_STRUCT(struct DeferredMaterialShaderData {
Matrix WorldMatrix; Matrix3x4 WorldMatrix;
Matrix PrevWorldMatrix; Matrix3x4 PrevWorldMatrix;
Float2 Dummy0; Float2 Dummy0;
float LODDitherFactor; float LODDitherFactor;
float PerInstanceRandom; float PerInstanceRandom;
@@ -70,8 +71,8 @@ void DeferredMaterialShader::Bind(BindParameters& params)
// Setup material constants // Setup material constants
{ {
Matrix::Transpose(drawCall.World, materialData->WorldMatrix); materialData->WorldMatrix.SetMatrixTranspose(drawCall.World);
Matrix::Transpose(drawCall.Surface.PrevWorld, materialData->PrevWorldMatrix); materialData->PrevWorldMatrix.SetMatrixTranspose(drawCall.Surface.PrevWorld);
materialData->WorldDeterminantSign = drawCall.WorldDeterminantSign; materialData->WorldDeterminantSign = drawCall.WorldDeterminantSign;
materialData->LODDitherFactor = drawCall.Surface.LODDitherFactor; materialData->LODDitherFactor = drawCall.Surface.LODDitherFactor;
materialData->PerInstanceRandom = drawCall.PerInstanceRandom; materialData->PerInstanceRandom = drawCall.PerInstanceRandom;

View File

@@ -3,6 +3,7 @@
#include "ForwardMaterialShader.h" #include "ForwardMaterialShader.h"
#include "MaterialShaderFeatures.h" #include "MaterialShaderFeatures.h"
#include "MaterialParams.h" #include "MaterialParams.h"
#include "Engine/Core/Math/Matrix3x4.h"
#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/GPUContext.h"
#include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/GPUDevice.h"
#include "Engine/Graphics/GPULimits.h" #include "Engine/Graphics/GPULimits.h"
@@ -18,8 +19,8 @@
#endif #endif
PACK_STRUCT(struct ForwardMaterialShaderData { PACK_STRUCT(struct ForwardMaterialShaderData {
Matrix WorldMatrix; Matrix3x4 WorldMatrix;
Matrix PrevWorldMatrix; Matrix3x4 PrevWorldMatrix;
Float2 Dummy0; Float2 Dummy0;
float LODDitherFactor; float LODDitherFactor;
float PerInstanceRandom; float PerInstanceRandom;
@@ -76,8 +77,8 @@ void ForwardMaterialShader::Bind(BindParameters& params)
// Setup material constants // Setup material constants
{ {
Matrix::Transpose(drawCall.World, materialData->WorldMatrix); materialData->WorldMatrix.SetMatrixTranspose(drawCall.World);
Matrix::Transpose(drawCall.Surface.PrevWorld, materialData->PrevWorldMatrix); materialData->PrevWorldMatrix.SetMatrixTranspose(drawCall.Surface.PrevWorld);
materialData->WorldDeterminantSign = drawCall.WorldDeterminantSign; materialData->WorldDeterminantSign = drawCall.WorldDeterminantSign;
materialData->LODDitherFactor = drawCall.Surface.LODDitherFactor; materialData->LODDitherFactor = drawCall.Surface.LODDitherFactor;
materialData->PerInstanceRandom = drawCall.PerInstanceRandom; materialData->PerInstanceRandom = drawCall.PerInstanceRandom;

View File

@@ -10,7 +10,7 @@
/// <summary> /// <summary>
/// Current materials shader version. /// Current materials shader version.
/// </summary> /// </summary>
#define MATERIAL_GRAPH_VERSION 161 #define MATERIAL_GRAPH_VERSION 162
class Material; class Material;
class GPUShader; class GPUShader;

View File

@@ -3,6 +3,7 @@
#include "ParticleMaterialShader.h" #include "ParticleMaterialShader.h"
#include "MaterialShaderFeatures.h" #include "MaterialShaderFeatures.h"
#include "MaterialParams.h" #include "MaterialParams.h"
#include "Engine/Core/Math/Matrix3x4.h"
#include "Engine/Renderer/DrawCall.h" #include "Engine/Renderer/DrawCall.h"
#include "Engine/Renderer/RenderList.h" #include "Engine/Renderer/RenderList.h"
#include "Engine/Graphics/RenderView.h" #include "Engine/Graphics/RenderView.h"
@@ -15,7 +16,7 @@
#include "Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.h" #include "Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.h"
PACK_STRUCT(struct ParticleMaterialShaderData { PACK_STRUCT(struct ParticleMaterialShaderData {
Matrix WorldMatrix; Matrix3x4 WorldMatrix;
uint32 SortedIndicesOffset; uint32 SortedIndicesOffset;
float PerInstanceRandom; float PerInstanceRandom;
int32 ParticleStride; int32 ParticleStride;
@@ -34,7 +35,7 @@ PACK_STRUCT(struct ParticleMaterialShaderData {
int32 RibbonTwistOffset; int32 RibbonTwistOffset;
int32 RibbonFacingVectorOffset; int32 RibbonFacingVectorOffset;
uint32 RibbonSegmentCount; uint32 RibbonSegmentCount;
Matrix WorldMatrixInverseTransposed; Matrix3x4 WorldMatrixInverseTransposed;
}); });
DrawPass ParticleMaterialShader::GetDrawModes() const DrawPass ParticleMaterialShader::GetDrawModes() const
@@ -101,7 +102,7 @@ void ParticleMaterialShader::Bind(BindParameters& params)
static StringView ParticleScaleOffset(TEXT("Scale")); static StringView ParticleScaleOffset(TEXT("Scale"));
static StringView ParticleModelFacingModeOffset(TEXT("ModelFacingMode")); static StringView ParticleModelFacingModeOffset(TEXT("ModelFacingMode"));
Matrix::Transpose(drawCall.World, materialData->WorldMatrix); materialData->WorldMatrix.SetMatrixTranspose(drawCall.World);
materialData->SortedIndicesOffset = drawCall.Particle.Particles->GPU.SortedIndices && params.RenderContext.View.Pass != DrawPass::Depth ? sortedIndicesOffset : 0xFFFFFFFF; materialData->SortedIndicesOffset = drawCall.Particle.Particles->GPU.SortedIndices && params.RenderContext.View.Pass != DrawPass::Depth ? sortedIndicesOffset : 0xFFFFFFFF;
materialData->PerInstanceRandom = drawCall.PerInstanceRandom; materialData->PerInstanceRandom = drawCall.PerInstanceRandom;
materialData->ParticleStride = drawCall.Particle.Particles->Stride; materialData->ParticleStride = drawCall.Particle.Particles->Stride;
@@ -113,7 +114,9 @@ void ParticleMaterialShader::Bind(BindParameters& params)
materialData->RotationOffset = drawCall.Particle.Particles->Layout->FindAttributeOffset(ParticleRotationOffset, ParticleAttribute::ValueTypes::Float3, -1); materialData->RotationOffset = drawCall.Particle.Particles->Layout->FindAttributeOffset(ParticleRotationOffset, ParticleAttribute::ValueTypes::Float3, -1);
materialData->ScaleOffset = drawCall.Particle.Particles->Layout->FindAttributeOffset(ParticleScaleOffset, ParticleAttribute::ValueTypes::Float3, -1); materialData->ScaleOffset = drawCall.Particle.Particles->Layout->FindAttributeOffset(ParticleScaleOffset, ParticleAttribute::ValueTypes::Float3, -1);
materialData->ModelFacingModeOffset = drawCall.Particle.Particles->Layout->FindAttributeOffset(ParticleModelFacingModeOffset, ParticleAttribute::ValueTypes::Int, -1); materialData->ModelFacingModeOffset = drawCall.Particle.Particles->Layout->FindAttributeOffset(ParticleModelFacingModeOffset, ParticleAttribute::ValueTypes::Int, -1);
Matrix::Invert(drawCall.World, materialData->WorldMatrixInverseTransposed); Matrix worldMatrixInverseTransposed;
Matrix::Invert(drawCall.World, worldMatrixInverseTransposed);
materialData->WorldMatrixInverseTransposed.SetMatrix(worldMatrixInverseTransposed);
} }
// Select pipeline state based on current pass and render mode // Select pipeline state based on current pass and render mode

View File

@@ -3,6 +3,7 @@
#include "TerrainMaterialShader.h" #include "TerrainMaterialShader.h"
#include "MaterialShaderFeatures.h" #include "MaterialShaderFeatures.h"
#include "MaterialParams.h" #include "MaterialParams.h"
#include "Engine/Core/Math/Matrix3x4.h"
#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/GPUContext.h"
#include "Engine/Graphics/GPULimits.h" #include "Engine/Graphics/GPULimits.h"
#include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/GPUDevice.h"
@@ -16,7 +17,7 @@
#include "Engine/Terrain/TerrainPatch.h" #include "Engine/Terrain/TerrainPatch.h"
PACK_STRUCT(struct TerrainMaterialShaderData { PACK_STRUCT(struct TerrainMaterialShaderData {
Matrix WorldMatrix; Matrix3x4 WorldMatrix;
Float3 WorldInvScale; Float3 WorldInvScale;
float WorldDeterminantSign; float WorldDeterminantSign;
float PerInstanceRandom; float PerInstanceRandom;
@@ -66,7 +67,7 @@ void TerrainMaterialShader::Bind(BindParameters& params)
// Setup material constants // Setup material constants
{ {
Matrix::Transpose(drawCall.World, materialData->WorldMatrix); materialData->WorldMatrix.SetMatrixTranspose(drawCall.World);
const float scaleX = Float3(drawCall.World.M11, drawCall.World.M12, drawCall.World.M13).Length(); const float scaleX = Float3(drawCall.World.M11, drawCall.World.M12, drawCall.World.M13).Length();
const float scaleY = Float3(drawCall.World.M21, drawCall.World.M22, drawCall.World.M23).Length(); const float scaleY = Float3(drawCall.World.M21, drawCall.World.M22, drawCall.World.M23).Length();
const float scaleZ = Float3(drawCall.World.M31, drawCall.World.M32, drawCall.World.M33).Length(); const float scaleZ = Float3(drawCall.World.M31, drawCall.World.M32, drawCall.World.M33).Length();

View File

@@ -3,6 +3,7 @@
#include "VolumeParticleMaterialShader.h" #include "VolumeParticleMaterialShader.h"
#include "MaterialShaderFeatures.h" #include "MaterialShaderFeatures.h"
#include "MaterialParams.h" #include "MaterialParams.h"
#include "Engine/Core/Math/Matrix3x4.h"
#include "Engine/Renderer/DrawCall.h" #include "Engine/Renderer/DrawCall.h"
#include "Engine/Renderer/VolumetricFogPass.h" #include "Engine/Renderer/VolumetricFogPass.h"
#include "Engine/Renderer/RenderList.h" #include "Engine/Renderer/RenderList.h"
@@ -16,8 +17,8 @@
PACK_STRUCT(struct VolumeParticleMaterialShaderData { PACK_STRUCT(struct VolumeParticleMaterialShaderData {
Matrix InverseViewProjectionMatrix; Matrix InverseViewProjectionMatrix;
Matrix WorldMatrix; Matrix3x4 WorldMatrix;
Matrix WorldMatrixInverseTransposed; Matrix3x4 WorldMatrixInverseTransposed;
Float3 GridSize; Float3 GridSize;
float PerInstanceRandom; float PerInstanceRandom;
float Dummy0; float Dummy0;
@@ -76,8 +77,10 @@ void VolumeParticleMaterialShader::Bind(BindParameters& params)
// Setup material constants // Setup material constants
{ {
Matrix::Transpose(view.IVP, materialData->InverseViewProjectionMatrix); Matrix::Transpose(view.IVP, materialData->InverseViewProjectionMatrix);
Matrix::Transpose(drawCall.World, materialData->WorldMatrix); materialData->WorldMatrix.SetMatrixTranspose(drawCall.World);
Matrix::Invert(drawCall.World, materialData->WorldMatrixInverseTransposed); Matrix worldMatrixInverseTransposed;
Matrix::Invert(drawCall.World, worldMatrixInverseTransposed);
materialData->WorldMatrixInverseTransposed.SetMatrix(worldMatrixInverseTransposed);
materialData->GridSize = customData->GridSize; materialData->GridSize = customData->GridSize;
materialData->PerInstanceRandom = drawCall.PerInstanceRandom; materialData->PerInstanceRandom = drawCall.PerInstanceRandom;
materialData->VolumetricFogMaxDistance = customData->VolumetricFogMaxDistance; materialData->VolumetricFogMaxDistance = customData->VolumetricFogMaxDistance;

View File

@@ -3,6 +3,7 @@
#include "GlobalSignDistanceFieldPass.h" #include "GlobalSignDistanceFieldPass.h"
#include "RenderList.h" #include "RenderList.h"
#include "Engine/Core/Math/Vector3.h" #include "Engine/Core/Math/Vector3.h"
#include "Engine/Core/Math/Matrix3x4.h"
#include "Engine/Core/Collections/HashSet.h" #include "Engine/Core/Collections/HashSet.h"
#include "Engine/Engine/Engine.h" #include "Engine/Engine/Engine.h"
#include "Engine/Content/Content.h" #include "Engine/Content/Content.h"
@@ -39,8 +40,8 @@ static_assert(GLOBAL_SDF_RASTERIZE_MODEL_MAX_COUNT % 4 == 0, "Must be multiple o
PACK_STRUCT(struct ObjectRasterizeData PACK_STRUCT(struct ObjectRasterizeData
{ {
Matrix WorldToVolume; // TODO: use 3x4 matrix Matrix3x4 WorldToVolume;
Matrix VolumeToWorld; // TODO: use 3x4 matrix Matrix3x4 VolumeToWorld;
Float3 VolumeToUVWMul; Float3 VolumeToUVWMul;
float MipOffset; float MipOffset;
Float3 VolumeToUVWAdd; Float3 VolumeToUVWAdd;
@@ -670,15 +671,15 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
// Add object data for the GPU buffer // Add object data for the GPU buffer
uint16 dataIndex = _objectsBufferCount++; uint16 dataIndex = _objectsBufferCount++;
ObjectRasterizeData objectData; ObjectRasterizeData objectData;
Matrix localToWorldM, worldToLocal, volumeToWorld; Matrix localToWorld, worldToLocal, volumeToWorld;
Matrix::Transformation(object.LocalToWorld.Scale, object.LocalToWorld.Orientation, object.LocalToWorld.Translation - _sdfData->Origin, localToWorldM); Matrix::Transformation(object.LocalToWorld.Scale, object.LocalToWorld.Orientation, object.LocalToWorld.Translation - _sdfData->Origin, localToWorld);
Matrix::Invert(localToWorldM, worldToLocal); Matrix::Invert(localToWorld, worldToLocal);
BoundingBox localVolumeBounds(object.SDF->LocalBoundsMin, object.SDF->LocalBoundsMax); BoundingBox localVolumeBounds(object.SDF->LocalBoundsMin, object.SDF->LocalBoundsMax);
Float3 volumeLocalBoundsExtent = localVolumeBounds.GetSize() * 0.5f; Float3 volumeLocalBoundsExtent = localVolumeBounds.GetSize() * 0.5f;
Matrix worldToVolume = worldToLocal * Matrix::Translation(-(localVolumeBounds.Minimum + volumeLocalBoundsExtent)); Matrix worldToVolume = worldToLocal * Matrix::Translation(-(localVolumeBounds.Minimum + volumeLocalBoundsExtent));
Matrix::Invert(worldToVolume, volumeToWorld); Matrix::Invert(worldToVolume, volumeToWorld);
Matrix::Transpose(worldToVolume, objectData.WorldToVolume); objectData.WorldToVolume.SetMatrixTranspose(worldToVolume);
Matrix::Transpose(volumeToWorld, objectData.VolumeToWorld); objectData.VolumeToWorld.SetMatrixTranspose(volumeToWorld);
objectData.VolumeLocalBoundsExtent = volumeLocalBoundsExtent; objectData.VolumeLocalBoundsExtent = volumeLocalBoundsExtent;
objectData.VolumeToUVWMul = object.SDF->LocalToUVWMul; objectData.VolumeToUVWMul = object.SDF->LocalToUVWMul;
objectData.VolumeToUVWAdd = object.SDF->LocalToUVWAdd + (localVolumeBounds.Minimum + volumeLocalBoundsExtent) * object.SDF->LocalToUVWMul; objectData.VolumeToUVWAdd = object.SDF->LocalToUVWAdd + (localVolumeBounds.Minimum + volumeLocalBoundsExtent) * object.SDF->LocalToUVWMul;
@@ -702,11 +703,11 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
// Add object data for the GPU buffer // Add object data for the GPU buffer
uint16 dataIndex = _objectsBufferCount++; uint16 dataIndex = _objectsBufferCount++;
ObjectRasterizeData objectData; ObjectRasterizeData objectData;
Matrix localToWorldM, worldToLocal; Matrix localToWorld, worldToLocal;
Matrix::Transformation(object.LocalToWorld.Scale, object.LocalToWorld.Orientation, object.LocalToWorld.Translation - _sdfData->Origin, localToWorldM); Matrix::Transformation(object.LocalToWorld.Scale, object.LocalToWorld.Orientation, object.LocalToWorld.Translation - _sdfData->Origin, localToWorld);
Matrix::Invert(localToWorldM, worldToLocal); Matrix::Invert(localToWorld, worldToLocal);
Matrix::Transpose(worldToLocal, objectData.WorldToVolume); objectData.WorldToVolume.SetMatrixTranspose(worldToLocal);
Matrix::Transpose(localToWorldM, objectData.VolumeToWorld); objectData.VolumeToWorld.SetMatrixTranspose(localToWorld);
objectData.VolumeToUVWMul = Float3(object.LocalToUV.X, 1.0f, object.LocalToUV.Y); objectData.VolumeToUVWMul = Float3(object.LocalToUV.X, 1.0f, object.LocalToUV.Y);
objectData.VolumeToUVWAdd = Float3(object.LocalToUV.Z, 0.0f, object.LocalToUV.W); objectData.VolumeToUVWAdd = Float3(object.LocalToUV.Z, 0.0f, object.LocalToUV.W);
objectData.MipOffset = (float)_cascadeIndex * 0.5f; // Use lower-quality mip for far cascades objectData.MipOffset = (float)_cascadeIndex * 0.5f; // Use lower-quality mip for far cascades

View File

@@ -230,4 +230,10 @@ float4 SampleUnwrappedTexture3D(Texture2D tex, SamplerState s, float3 uvw, float
return lerp(rg0, rg1, fracW); return lerp(rg0, rg1, fracW);
} }
// Converts compact 4x3 object transformation matrix into a full 4x4 matrix.
float4x4 ToMatrix4x4(float4x3 m)
{
return float4x4(float4(m[0].xyz, 0.0f), float4(m[1].xyz, 0.0f), float4(m[2].xyz, 0.0f), float4(m._m30, m._m31, m._m32, 1.0f));
}
#endif #endif

View File

@@ -11,8 +11,8 @@
struct ObjectRasterizeData struct ObjectRasterizeData
{ {
float4x4 WorldToVolume; // TODO: use 3x4 matrix float4x3 WorldToVolume;
float4x4 VolumeToWorld; // TODO: use 3x4 matrix float4x3 VolumeToWorld;
float3 VolumeToUVWMul; float3 VolumeToUVWMul;
float MipOffset; float MipOffset;
float3 VolumeToUVWAdd; float3 VolumeToUVWAdd;
@@ -74,14 +74,15 @@ Texture3D<float> ObjectsTextures[GLOBAL_SDF_RASTERIZE_MODEL_MAX_COUNT] : registe
float DistanceToModelSDF(float minDistance, ObjectRasterizeData modelData, Texture3D<float> modelSDFTex, float3 worldPos) float DistanceToModelSDF(float minDistance, ObjectRasterizeData modelData, Texture3D<float> modelSDFTex, float3 worldPos)
{ {
// Object scaling is the length of the rows // Object scaling is the length of the rows
float3 volumeToWorldScale = float3(length(modelData.VolumeToWorld[0]), length(modelData.VolumeToWorld[1]), length(modelData.VolumeToWorld[2])); float4x4 volumeToWorld = ToMatrix4x4(modelData.VolumeToWorld);
float3 volumeToWorldScale = float3(length(volumeToWorld[0]), length(volumeToWorld[1]), length(volumeToWorld[2]));
float volumeScale = min(volumeToWorldScale.x, min(volumeToWorldScale.y, volumeToWorldScale.z)); float volumeScale = min(volumeToWorldScale.x, min(volumeToWorldScale.y, volumeToWorldScale.z));
// Compute SDF volume UVs and distance in world-space to the volume bounds // Compute SDF volume UVs and distance in world-space to the volume bounds
float3 volumePos = mul(float4(worldPos, 1), modelData.WorldToVolume).xyz; float3 volumePos = mul(float4(worldPos, 1), ToMatrix4x4(modelData.WorldToVolume)).xyz;
float3 volumeUV = volumePos * modelData.VolumeToUVWMul + modelData.VolumeToUVWAdd; float3 volumeUV = volumePos * modelData.VolumeToUVWMul + modelData.VolumeToUVWAdd;
float3 volumePosClamped = clamp(volumePos, -modelData.VolumeLocalBoundsExtent, modelData.VolumeLocalBoundsExtent); float3 volumePosClamped = clamp(volumePos, -modelData.VolumeLocalBoundsExtent, modelData.VolumeLocalBoundsExtent);
float3 worldPosClamped = mul(float4(volumePosClamped, 1), modelData.VolumeToWorld).xyz; float3 worldPosClamped = mul(float4(volumePosClamped, 1), volumeToWorld).xyz;
float distanceToVolume = distance(worldPos, worldPosClamped); float distanceToVolume = distance(worldPos, worldPosClamped);
if (distanceToVolume < 0.01f) if (distanceToVolume < 0.01f)
distanceToVolume = length((volumePos - volumePosClamped) * volumeToWorldScale); distanceToVolume = length((volumePos - volumePosClamped) * volumeToWorldScale);
@@ -152,7 +153,7 @@ void CS_RasterizeHeightfield(uint3 DispatchThreadId : SV_DispatchThreadID)
ObjectRasterizeData objectData = ObjectsBuffer[Objects[i / 4][i % 4]]; ObjectRasterizeData objectData = ObjectsBuffer[Objects[i / 4][i % 4]];
// Convert voxel world-space position into heightfield local-space position and get heightfield UV // Convert voxel world-space position into heightfield local-space position and get heightfield UV
float3 volumePos = mul(float4(voxelWorldPos, 1), objectData.WorldToVolume).xyz; float3 volumePos = mul(float4(voxelWorldPos, 1), ToMatrix4x4(objectData.WorldToVolume)).xyz;
float3 volumeUV = volumePos * objectData.VolumeToUVWMul + objectData.VolumeToUVWAdd; float3 volumeUV = volumePos * objectData.VolumeToUVWMul + objectData.VolumeToUVWAdd;
float2 heightfieldUV = float2(volumeUV.x, volumeUV.z); float2 heightfieldUV = float2(volumeUV.x, volumeUV.z);
@@ -168,8 +169,9 @@ void CS_RasterizeHeightfield(uint3 DispatchThreadId : SV_DispatchThreadID)
float height = (float)((int)(heightmapValue.x * 255.0) + ((int)(heightmapValue.y * 255) << 8)) / 65535.0; float height = (float)((int)(heightmapValue.x * 255.0) + ((int)(heightmapValue.y * 255) << 8)) / 65535.0;
float2 positionXZ = volumePos.xz; float2 positionXZ = volumePos.xz;
float3 position = float3(positionXZ.x, height, positionXZ.y); float3 position = float3(positionXZ.x, height, positionXZ.y);
float3 heightfieldPosition = mul(float4(position, 1), objectData.VolumeToWorld).xyz; float4x4 volumeToWorld = ToMatrix4x4(objectData.VolumeToWorld);
float3 heightfieldNormal = normalize(float3(objectData.VolumeToWorld[0].y, objectData.VolumeToWorld[1].y, objectData.VolumeToWorld[2].y)); float3 heightfieldPosition = mul(float4(position, 1), volumeToWorld).xyz;
float3 heightfieldNormal = normalize(float3(volumeToWorld[0].y, volumeToWorld[1].y, volumeToWorld[2].y));
// Calculate distance from voxel center to the heightfield // Calculate distance from voxel center to the heightfield
float objectDistance = dot(heightfieldNormal, voxelWorldPos - heightfieldPosition); float objectDistance = dot(heightfieldNormal, voxelWorldPos - heightfieldPosition);