Changed the ReflectionProbe component to use an OBB
Signed-off-by: dmcdiar <dmcdiar@amazon.com>
This commit is contained in:
@@ -40,11 +40,10 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject
|
||||
//! Reflection Probe (smallest probe volume that overlaps the object position)
|
||||
struct ReflectionProbeData
|
||||
{
|
||||
float3 m_aabbPos;
|
||||
float3 m_outerAabbMin;
|
||||
float3 m_outerAabbMax;
|
||||
float3 m_innerAabbMin;
|
||||
float3 m_innerAabbMax;
|
||||
row_major float3x4 m_modelToWorld;
|
||||
row_major float3x4 m_modelToWorldInverse; // does not include extents
|
||||
float3 m_outerObbHalfLengths;
|
||||
float3 m_innerObbHalfLengths;
|
||||
float m_padding;
|
||||
bool m_useReflectionProbe;
|
||||
bool m_useParallaxCorrection;
|
||||
@@ -52,4 +51,32 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject
|
||||
|
||||
ReflectionProbeData m_reflectionProbeData;
|
||||
TextureCube m_reflectionProbeCubeMap;
|
||||
|
||||
float4x4 GetReflectionProbeWorldMatrix()
|
||||
{
|
||||
float4x4 modelToWorld = float4x4(
|
||||
float4(1, 0, 0, 0),
|
||||
float4(0, 1, 0, 0),
|
||||
float4(0, 0, 1, 0),
|
||||
float4(0, 0, 0, 1));
|
||||
|
||||
modelToWorld[0] = m_reflectionProbeData.m_modelToWorld[0];
|
||||
modelToWorld[1] = m_reflectionProbeData.m_modelToWorld[1];
|
||||
modelToWorld[2] = m_reflectionProbeData.m_modelToWorld[2];
|
||||
return modelToWorld;
|
||||
}
|
||||
|
||||
float4x4 GetReflectionProbeWorldMatrixInverse()
|
||||
{
|
||||
float4x4 modelToWorldInverse = float4x4(
|
||||
float4(1, 0, 0, 0),
|
||||
float4(0, 1, 0, 0),
|
||||
float4(0, 0, 1, 0),
|
||||
float4(0, 0, 0, 1));
|
||||
|
||||
modelToWorldInverse[0] = m_reflectionProbeData.m_modelToWorldInverse[0];
|
||||
modelToWorldInverse[1] = m_reflectionProbeData.m_modelToWorldInverse[1];
|
||||
modelToWorldInverse[2] = m_reflectionProbeData.m_modelToWorldInverse[2];
|
||||
return modelToWorldInverse;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,10 +50,10 @@ float GetRoughnessMip(float roughness)
|
||||
return roughness * maxRoughnessMip;
|
||||
}
|
||||
|
||||
// compute parallax corrected reflection vector
|
||||
// compute parallax corrected reflection vector, AABB version
|
||||
// we do this by finding the intersection with the volume and adjusting the reflection vector for the surface position
|
||||
// https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
|
||||
float3 ApplyParallaxCorrection(float3 aabbMin, float3 aabbMax, float3 aabbPos, float3 positionWS, float3 reflectDir)
|
||||
float3 ApplyParallaxCorrectionAABB(float3 aabbMin, float3 aabbMax, float3 aabbPos, float3 positionWS, float3 reflectDir)
|
||||
{
|
||||
float3 rcpReflectDir = 1.0f / reflectDir;
|
||||
float3 intersectA = (aabbMax - positionWS) * rcpReflectDir;
|
||||
@@ -63,3 +63,10 @@ float3 ApplyParallaxCorrection(float3 aabbMin, float3 aabbMax, float3 aabbPos, f
|
||||
float3 intersectPos = reflectDir * distance + positionWS;
|
||||
return (intersectPos - aabbPos);
|
||||
}
|
||||
|
||||
// compute parallax corrected reflection vector, OBB version
|
||||
float3 ApplyParallaxCorrectionOBB(float4x4 obbTransformInverse, float3 obbHalfExtents, float3 positionWS, float3 reflectDir)
|
||||
{
|
||||
float4 p = mul(obbTransformInverse, float4(positionWS, 1.0f));
|
||||
return ApplyParallaxCorrectionAABB(-obbHalfExtents, obbHalfExtents, float3(0.0f, 0.0f, 0.0f), p, reflectDir);
|
||||
}
|
||||
|
||||
@@ -48,10 +48,9 @@ float3 GetIblSpecular(
|
||||
{
|
||||
if (ObjectSrg::m_reflectionProbeData.m_useParallaxCorrection)
|
||||
{
|
||||
reflectDir = ApplyParallaxCorrection(
|
||||
ObjectSrg::m_reflectionProbeData.m_outerAabbMin,
|
||||
ObjectSrg::m_reflectionProbeData.m_outerAabbMax,
|
||||
ObjectSrg::m_reflectionProbeData.m_aabbPos,
|
||||
reflectDir = ApplyParallaxCorrectionOBB(
|
||||
ObjectSrg::GetReflectionProbeWorldMatrixInverse(),
|
||||
ObjectSrg::m_reflectionProbeData.m_outerObbHalfLengths,
|
||||
position,
|
||||
reflectDir);
|
||||
}
|
||||
@@ -60,11 +59,10 @@ float3 GetIblSpecular(
|
||||
probeSpecular *= (specularF0 * brdf.x + brdf.y);
|
||||
|
||||
// compute blend amount based on world position in the reflection probe volume
|
||||
float blendAmount = ComputeLerpBetweenInnerOuterAABBs(
|
||||
ObjectSrg::m_reflectionProbeData.m_innerAabbMin,
|
||||
ObjectSrg::m_reflectionProbeData.m_innerAabbMax,
|
||||
ObjectSrg::m_reflectionProbeData.m_outerAabbMax,
|
||||
ObjectSrg::m_reflectionProbeData.m_aabbPos,
|
||||
float blendAmount = ComputeLerpBetweenInnerOuterOBBs(
|
||||
ObjectSrg::m_reflectionProbeData.m_modelToWorldInverse,
|
||||
ObjectSrg::m_reflectionProbeData.m_innerObbHalfLengths,
|
||||
ObjectSrg::m_reflectionProbeData.m_outerObbHalfLengths,
|
||||
position);
|
||||
|
||||
outSpecular = lerp(outSpecular, probeSpecular, blendAmount);
|
||||
|
||||
@@ -63,7 +63,7 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex)
|
||||
// make sure the pixel belongs to this probe volume
|
||||
// this is necessary since it could have the correct stencil value but actually reside
|
||||
// in another volume that's in between the camera and the volume we're rendering
|
||||
if (!AabbContainsPoint(ObjectSrg::m_outerAabbMin, ObjectSrg::m_outerAabbMax, positionWS))
|
||||
if (!ObbContainsPoint(ObjectSrg::GetWorldMatrixInverse(), ObjectSrg::m_outerObbHalfLengths, positionWS))
|
||||
{
|
||||
discard;
|
||||
}
|
||||
@@ -71,11 +71,15 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex)
|
||||
// determine blend based on position with respect to the inner and outer AABBs
|
||||
// if it's inside the inner AABB it blends at 100%, otherwise it's the percentage of the distance between the inner/outer AABB
|
||||
float blendWeight = 1.0f;
|
||||
if (!AabbContainsPoint(ObjectSrg::m_innerAabbMin, ObjectSrg::m_innerAabbMax, positionWS))
|
||||
if (!ObbContainsPoint(ObjectSrg::GetWorldMatrixInverse(), ObjectSrg::m_innerObbHalfLengths, positionWS))
|
||||
{
|
||||
// not inside the inner AABB, so it's in between the inner and outer AABBs
|
||||
// compute blend amount based on the distance to the outer AABB
|
||||
blendWeight = ComputeLerpBetweenInnerOuterAABBs(ObjectSrg::m_innerAabbMin, ObjectSrg::m_innerAabbMax, ObjectSrg::m_outerAabbMax, ObjectSrg::m_aabbPos, positionWS);
|
||||
blendWeight = ComputeLerpBetweenInnerOuterOBBs(
|
||||
ObjectSrg::GetWorldMatrixInverse(),
|
||||
ObjectSrg::m_innerObbHalfLengths,
|
||||
ObjectSrg::m_outerObbHalfLengths,
|
||||
positionWS);
|
||||
}
|
||||
|
||||
// write the blend weight (additive) at this position for the probe volume
|
||||
|
||||
+7
-3
@@ -12,12 +12,12 @@
|
||||
#include <Atom/Features/PBR/Microfacet/Fresnel.azsli>
|
||||
|
||||
// compute final probe specular using the probe cubemap and the roughness, normals, and specularF0 for the surface
|
||||
bool ComputeProbeSpecular(float2 screenCoords, float3 positionWS, float3 aabbMin, float3 aabbMax, uint sampleIndex, out float3 specular)
|
||||
bool ComputeProbeSpecular(float2 screenCoords, float3 positionWS, float4x4 obbTransformInverse, float3 outerObbHalfLengths, uint sampleIndex, out float3 specular)
|
||||
{
|
||||
// make sure the pixel belongs to this probe volume
|
||||
// this is necessary since it could have the correct stencil value but actually reside
|
||||
// in another volume that's in between the camera and the volume we're rendering
|
||||
if (!AabbContainsPoint(aabbMin, aabbMax, positionWS))
|
||||
if (!ObbContainsPoint(obbTransformInverse, outerObbHalfLengths, positionWS))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -47,7 +47,11 @@ bool ComputeProbeSpecular(float2 screenCoords, float3 positionWS, float3 aabbMin
|
||||
float3 localReflectDir = reflectDir;
|
||||
if (ObjectSrg::m_useParallaxCorrection)
|
||||
{
|
||||
localReflectDir = ApplyParallaxCorrection(ObjectSrg::m_outerAabbMin, ObjectSrg::m_outerAabbMax, ObjectSrg::m_aabbPos, positionWS, reflectDir);
|
||||
localReflectDir = ApplyParallaxCorrectionOBB(
|
||||
ObjectSrg::GetWorldMatrixInverse(),
|
||||
ObjectSrg::m_outerObbHalfLengths,
|
||||
positionWS,
|
||||
reflectDir);
|
||||
}
|
||||
|
||||
// sample reflection cubemap with the appropriate roughness mip
|
||||
|
||||
@@ -75,7 +75,7 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex)
|
||||
|
||||
// compute specular using the probe cubemap and the roughness, normals, and specularF0 for the surface
|
||||
float3 specular = float3(0.0f, 0.0f, 0.0f);
|
||||
if (!ComputeProbeSpecular(IN.m_position.xy, positionWS, ObjectSrg::m_innerAabbMin, ObjectSrg::m_innerAabbMax, sampleIndex, specular))
|
||||
if (!ComputeProbeSpecular(IN.m_position.xy, positionWS, ObjectSrg::GetWorldMatrixInverse(), ObjectSrg::m_innerObbHalfLengths, sampleIndex, specular))
|
||||
{
|
||||
discard;
|
||||
}
|
||||
|
||||
+17
-6
@@ -13,12 +13,9 @@
|
||||
ShaderResourceGroup ObjectSrg : SRG_PerObject
|
||||
{
|
||||
row_major float3x4 m_modelToWorld;
|
||||
|
||||
float3 m_aabbPos;
|
||||
float3 m_outerAabbMin;
|
||||
float3 m_outerAabbMax;
|
||||
float3 m_innerAabbMin;
|
||||
float3 m_innerAabbMax;
|
||||
row_major float3x4 m_modelToWorldInverse; // does not include extents
|
||||
float3 m_outerObbHalfLengths;
|
||||
float3 m_innerObbHalfLengths;
|
||||
bool m_useParallaxCorrection;
|
||||
TextureCube m_reflectionCubeMap;
|
||||
|
||||
@@ -35,4 +32,18 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject
|
||||
modelToWorld[2] = ObjectSrg::m_modelToWorld[2];
|
||||
return modelToWorld;
|
||||
}
|
||||
|
||||
float4x4 GetWorldMatrixInverse()
|
||||
{
|
||||
float4x4 modelToWorldInverse = float4x4(
|
||||
float4(1, 0, 0, 0),
|
||||
float4(0, 1, 0, 0),
|
||||
float4(0, 0, 1, 0),
|
||||
float4(0, 0, 0, 1));
|
||||
|
||||
modelToWorldInverse[0] = ObjectSrg::m_modelToWorldInverse[0];
|
||||
modelToWorldInverse[1] = ObjectSrg::m_modelToWorldInverse[1];
|
||||
modelToWorldInverse[2] = ObjectSrg::m_modelToWorldInverse[2];
|
||||
return modelToWorldInverse;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex)
|
||||
|
||||
// compute specular using the probe cubemap and the roughness, normals, and specularF0 for the surface
|
||||
float3 specular = float3(0.0f, 0.0f, 0.0f);
|
||||
if (!ComputeProbeSpecular(IN.m_position.xy, positionWS, ObjectSrg::m_outerAabbMin, ObjectSrg::m_outerAabbMax, sampleIndex, specular))
|
||||
if (!ComputeProbeSpecular(IN.m_position.xy, positionWS, ObjectSrg::GetWorldMatrixInverse(), ObjectSrg::m_outerObbHalfLengths, sampleIndex, specular))
|
||||
{
|
||||
discard;
|
||||
}
|
||||
@@ -85,13 +85,17 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex)
|
||||
// determine blend based on position with respect to the inner and outer AABBs
|
||||
// if it's inside the inner AABB it blends at 100%, otherwise it's the percentage of the distance between the inner/outer AABB
|
||||
float blendWeight = 1.0f;
|
||||
if (!AabbContainsPoint(ObjectSrg::m_innerAabbMin, ObjectSrg::m_innerAabbMax, positionWS))
|
||||
if (!ObbContainsPoint(ObjectSrg::GetWorldMatrixInverse(), ObjectSrg::m_innerObbHalfLengths, positionWS))
|
||||
{
|
||||
// not inside the inner AABB, so it's in between the inner and outer AABBs
|
||||
// compute blend amount based on the distance to the outer AABB
|
||||
blendWeight = ComputeLerpBetweenInnerOuterAABBs(ObjectSrg::m_innerAabbMin, ObjectSrg::m_innerAabbMax, ObjectSrg::m_outerAabbMax, ObjectSrg::m_aabbPos, positionWS);
|
||||
blendWeight = ComputeLerpBetweenInnerOuterOBBs(
|
||||
ObjectSrg::GetWorldMatrixInverse(),
|
||||
ObjectSrg::m_innerObbHalfLengths,
|
||||
ObjectSrg::m_outerObbHalfLengths,
|
||||
positionWS);
|
||||
}
|
||||
|
||||
|
||||
// retrieve the blend weight of all probes at this location
|
||||
float blendWeightAllProbes = PassSrg::m_blendWeight.Load(IN.m_position.xy, sampleIndex).r;
|
||||
|
||||
|
||||
@@ -1119,20 +1119,17 @@ namespace AZ
|
||||
if (reflectionProbeFeatureProcessor && (m_descriptor.m_useForwardPassIblSpecular || m_hasForwardPassIblSpecularMaterial))
|
||||
{
|
||||
// retrieve probe constant indices
|
||||
AZ::RHI::ShaderInputConstantIndex posConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_aabbPos"));
|
||||
AZ_Error("MeshDataInstance", posConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
|
||||
AZ::RHI::ShaderInputConstantIndex modelToWorldConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_modelToWorld"));
|
||||
AZ_Error("MeshDataInstance", modelToWorldConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
|
||||
|
||||
AZ::RHI::ShaderInputConstantIndex outerAabbMinConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_outerAabbMin"));
|
||||
AZ_Error("MeshDataInstance", outerAabbMinConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
|
||||
AZ::RHI::ShaderInputConstantIndex modelToWorldInverseConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_modelToWorldInverse"));
|
||||
AZ_Error("MeshDataInstance", modelToWorldInverseConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
|
||||
|
||||
AZ::RHI::ShaderInputConstantIndex outerAabbMaxConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_outerAabbMax"));
|
||||
AZ_Error("MeshDataInstance", outerAabbMaxConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
|
||||
AZ::RHI::ShaderInputConstantIndex outerObbHalfLengthsConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_outerObbHalfLengths"));
|
||||
AZ_Error("MeshDataInstance", outerObbHalfLengthsConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
|
||||
|
||||
AZ::RHI::ShaderInputConstantIndex innerAabbMinConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_innerAabbMin"));
|
||||
AZ_Error("MeshDataInstance", innerAabbMinConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
|
||||
|
||||
AZ::RHI::ShaderInputConstantIndex innerAabbMaxConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_innerAabbMax"));
|
||||
AZ_Error("MeshDataInstance", innerAabbMaxConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
|
||||
AZ::RHI::ShaderInputConstantIndex innerObbHalfLengthsConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_innerObbHalfLengths"));
|
||||
AZ_Error("MeshDataInstance", innerObbHalfLengthsConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
|
||||
|
||||
AZ::RHI::ShaderInputConstantIndex useReflectionProbeConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_useReflectionProbe"));
|
||||
AZ_Error("MeshDataInstance", useReflectionProbeConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
|
||||
@@ -1154,11 +1151,10 @@ namespace AZ
|
||||
|
||||
if (!reflectionProbes.empty() && reflectionProbes[0])
|
||||
{
|
||||
m_shaderResourceGroup->SetConstant(posConstantIndex, reflectionProbes[0]->GetPosition());
|
||||
m_shaderResourceGroup->SetConstant(outerAabbMinConstantIndex, reflectionProbes[0]->GetOuterAabbWs().GetMin());
|
||||
m_shaderResourceGroup->SetConstant(outerAabbMaxConstantIndex, reflectionProbes[0]->GetOuterAabbWs().GetMax());
|
||||
m_shaderResourceGroup->SetConstant(innerAabbMinConstantIndex, reflectionProbes[0]->GetInnerAabbWs().GetMin());
|
||||
m_shaderResourceGroup->SetConstant(innerAabbMaxConstantIndex, reflectionProbes[0]->GetInnerAabbWs().GetMax());
|
||||
m_shaderResourceGroup->SetConstant(modelToWorldConstantIndex, reflectionProbes[0]->GetTransform());
|
||||
m_shaderResourceGroup->SetConstant(modelToWorldInverseConstantIndex, reflectionProbes[0]->GetTransform().GetInverse());
|
||||
m_shaderResourceGroup->SetConstant(outerObbHalfLengthsConstantIndex, reflectionProbes[0]->GetOuterObbWs().GetHalfLengths());
|
||||
m_shaderResourceGroup->SetConstant(innerObbHalfLengthsConstantIndex, reflectionProbes[0]->GetInnerObbWs().GetHalfLengths());
|
||||
m_shaderResourceGroup->SetConstant(useReflectionProbeConstantIndex, true);
|
||||
m_shaderResourceGroup->SetConstant(useParallaxCorrectionConstantIndex, reflectionProbes[0]->GetUseParallaxCorrection());
|
||||
|
||||
|
||||
@@ -138,43 +138,40 @@ namespace AZ
|
||||
if (m_updateSrg)
|
||||
{
|
||||
// stencil Srg
|
||||
// Note: the stencil pass uses a slightly reduced inner AABB to avoid seams
|
||||
// Note: the stencil pass uses a slightly reduced inner OBB to avoid seams
|
||||
Vector3 innerExtentsReduced = m_innerExtents - Vector3(0.1f, 0.1f, 0.1f);
|
||||
Matrix3x4 modelToWorldStencil = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(innerExtentsReduced);
|
||||
Matrix3x4 modelToWorldStencil = Matrix3x4::CreateFromQuaternionAndTranslation(m_transform.GetRotation(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(innerExtentsReduced);
|
||||
m_stencilSrg->SetConstant(m_reflectionRenderData->m_modelToWorldStencilConstantIndex, modelToWorldStencil);
|
||||
m_stencilSrg->SetConstant(m_reflectionRenderData->m_modelToWorldInverseStencilConstantIndex, modelToWorldStencil.GetInverseFull());
|
||||
m_stencilSrg->Compile();
|
||||
|
||||
Matrix3x4 modelToWorldInverse = Matrix3x4::CreateFromTransform(m_transform).GetInverseFull();
|
||||
|
||||
// blend weight Srg
|
||||
Matrix3x4 modelToWorldOuter = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(m_outerExtents);
|
||||
Matrix3x4 modelToWorldOuter = Matrix3x4::CreateFromQuaternionAndTranslation(m_transform.GetRotation(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(m_outerExtents);
|
||||
m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_modelToWorldRenderConstantIndex, modelToWorldOuter);
|
||||
m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_aabbPosRenderConstantIndex, m_outerAabbWs.GetCenter());
|
||||
m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_outerAabbMinRenderConstantIndex, m_outerAabbWs.GetMin());
|
||||
m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_outerAabbMaxRenderConstantIndex, m_outerAabbWs.GetMax());
|
||||
m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_innerAabbMinRenderConstantIndex, m_innerAabbWs.GetMin());
|
||||
m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_innerAabbMaxRenderConstantIndex, m_innerAabbWs.GetMax());
|
||||
m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_modelToWorldInverseRenderConstantIndex, modelToWorldInverse);
|
||||
m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_outerObbHalfLengthsRenderConstantIndex, m_outerObbWs.GetHalfLengths());
|
||||
m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_innerObbHalfLengthsRenderConstantIndex, m_innerObbWs.GetHalfLengths());
|
||||
m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_useParallaxCorrectionRenderConstantIndex, m_useParallaxCorrection);
|
||||
m_blendWeightSrg->SetImage(m_reflectionRenderData->m_reflectionCubeMapRenderImageIndex, m_cubeMapImage);
|
||||
m_blendWeightSrg->Compile();
|
||||
|
||||
// render outer Srg
|
||||
m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_modelToWorldRenderConstantIndex, modelToWorldOuter);
|
||||
m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_aabbPosRenderConstantIndex, m_outerAabbWs.GetCenter());
|
||||
m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_outerAabbMinRenderConstantIndex, m_outerAabbWs.GetMin());
|
||||
m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_outerAabbMaxRenderConstantIndex, m_outerAabbWs.GetMax());
|
||||
m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_innerAabbMinRenderConstantIndex, m_innerAabbWs.GetMin());
|
||||
m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_innerAabbMaxRenderConstantIndex, m_innerAabbWs.GetMax());
|
||||
m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_modelToWorldInverseRenderConstantIndex, modelToWorldInverse);
|
||||
m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_outerObbHalfLengthsRenderConstantIndex, m_outerObbWs.GetHalfLengths());
|
||||
m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_innerObbHalfLengthsRenderConstantIndex, m_innerObbWs.GetHalfLengths());
|
||||
m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_useParallaxCorrectionRenderConstantIndex, m_useParallaxCorrection);
|
||||
m_renderOuterSrg->SetImage(m_reflectionRenderData->m_reflectionCubeMapRenderImageIndex, m_cubeMapImage);
|
||||
m_renderOuterSrg->Compile();
|
||||
|
||||
// render inner Srg
|
||||
Matrix3x4 modelToWorldInner = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(m_innerExtents);
|
||||
Matrix3x4 modelToWorldInner = Matrix3x4::CreateFromQuaternionAndTranslation(m_transform.GetRotation(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(m_innerExtents);
|
||||
m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_modelToWorldRenderConstantIndex, modelToWorldInner);
|
||||
m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_aabbPosRenderConstantIndex, m_outerAabbWs.GetCenter());
|
||||
m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_outerAabbMinRenderConstantIndex, m_outerAabbWs.GetMin());
|
||||
m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_outerAabbMaxRenderConstantIndex, m_outerAabbWs.GetMax());
|
||||
m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_innerAabbMinRenderConstantIndex, m_innerAabbWs.GetMin());
|
||||
m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_innerAabbMaxRenderConstantIndex, m_innerAabbWs.GetMax());
|
||||
m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_modelToWorldInverseRenderConstantIndex, modelToWorldInverse);
|
||||
m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_outerObbHalfLengthsRenderConstantIndex, m_outerObbWs.GetHalfLengths());
|
||||
m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_innerObbHalfLengthsRenderConstantIndex, m_innerObbWs.GetHalfLengths());
|
||||
m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_useParallaxCorrectionRenderConstantIndex, m_useParallaxCorrection);
|
||||
m_renderInnerSrg->SetImage(m_reflectionRenderData->m_reflectionCubeMapRenderImageIndex, m_cubeMapImage);
|
||||
m_renderInnerSrg->Compile();
|
||||
@@ -244,22 +241,22 @@ namespace AZ
|
||||
m_outerExtents *= m_transform.GetUniformScale();
|
||||
m_innerExtents *= m_transform.GetUniformScale();
|
||||
|
||||
m_outerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_outerExtents / 2.0f);
|
||||
m_innerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_innerExtents / 2.0f);
|
||||
m_outerObbWs = Obb::CreateFromPositionRotationAndHalfLengths(m_transform.GetTranslation(), m_transform.GetRotation(), m_outerExtents / 2.0f);
|
||||
m_innerObbWs = Obb::CreateFromPositionRotationAndHalfLengths(m_transform.GetTranslation(), m_transform.GetRotation(), m_innerExtents / 2.0f);
|
||||
m_updateSrg = true;
|
||||
}
|
||||
|
||||
void ReflectionProbe::SetOuterExtents(const AZ::Vector3& outerExtents)
|
||||
{
|
||||
m_outerExtents = outerExtents * m_transform.GetUniformScale();
|
||||
m_outerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_outerExtents / 2.0f);
|
||||
m_outerObbWs = Obb::CreateFromPositionRotationAndHalfLengths(m_transform.GetTranslation(), m_transform.GetRotation(), m_outerExtents / 2.0f);
|
||||
m_updateSrg = true;
|
||||
}
|
||||
|
||||
void ReflectionProbe::SetInnerExtents(const AZ::Vector3& innerExtents)
|
||||
{
|
||||
m_innerExtents = innerExtents * m_transform.GetUniformScale();
|
||||
m_innerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_innerExtents / 2.0f);
|
||||
m_innerObbWs = Obb::CreateFromPositionRotationAndHalfLengths(m_transform.GetTranslation(), m_transform.GetRotation(), m_innerExtents / 2.0f);
|
||||
m_updateSrg = true;
|
||||
}
|
||||
|
||||
@@ -394,13 +391,14 @@ namespace AZ
|
||||
lod.m_screenCoverageMax = 1.0f;
|
||||
|
||||
// update cullable bounds
|
||||
Aabb outerAabb = Aabb::CreateFromObb(m_outerObbWs);
|
||||
Vector3 center;
|
||||
float radius;
|
||||
m_outerAabbWs.GetAsSphere(center, radius);
|
||||
outerAabb.GetAsSphere(center, radius);
|
||||
|
||||
m_cullable.m_cullData.m_boundingSphere = Sphere(center, radius);
|
||||
m_cullable.m_cullData.m_boundingObb = m_outerAabbWs.GetTransformedObb(AZ::Transform::CreateIdentity());
|
||||
m_cullable.m_cullData.m_visibilityEntry.m_boundingVolume = m_outerAabbWs;
|
||||
m_cullable.m_cullData.m_boundingObb = m_outerObbWs;
|
||||
m_cullable.m_cullData.m_visibilityEntry.m_boundingVolume = outerAabb;
|
||||
m_cullable.m_cullData.m_visibilityEntry.m_userData = &m_cullable;
|
||||
m_cullable.m_cullData.m_visibilityEntry.m_typeFlags = AzFramework::VisibilityEntry::TYPE_RPI_Cullable;
|
||||
|
||||
|
||||
@@ -56,12 +56,11 @@ namespace AZ
|
||||
RHI::DrawListTag m_renderInnerDrawListTag;
|
||||
|
||||
RHI::ShaderInputConstantIndex m_modelToWorldStencilConstantIndex;
|
||||
RHI::ShaderInputConstantIndex m_modelToWorldInverseStencilConstantIndex;
|
||||
RHI::ShaderInputConstantIndex m_modelToWorldRenderConstantIndex;
|
||||
RHI::ShaderInputConstantIndex m_aabbPosRenderConstantIndex;
|
||||
RHI::ShaderInputConstantIndex m_outerAabbMinRenderConstantIndex;
|
||||
RHI::ShaderInputConstantIndex m_outerAabbMaxRenderConstantIndex;
|
||||
RHI::ShaderInputConstantIndex m_innerAabbMinRenderConstantIndex;
|
||||
RHI::ShaderInputConstantIndex m_innerAabbMaxRenderConstantIndex;
|
||||
RHI::ShaderInputConstantIndex m_modelToWorldInverseRenderConstantIndex;
|
||||
RHI::ShaderInputConstantIndex m_outerObbHalfLengthsRenderConstantIndex;
|
||||
RHI::ShaderInputConstantIndex m_innerObbHalfLengthsRenderConstantIndex;
|
||||
RHI::ShaderInputConstantIndex m_useParallaxCorrectionRenderConstantIndex;
|
||||
RHI::ShaderInputImageIndex m_reflectionCubeMapRenderImageIndex;
|
||||
};
|
||||
@@ -78,6 +77,7 @@ namespace AZ
|
||||
void Simulate(uint32_t probeIndex);
|
||||
|
||||
const Vector3& GetPosition() const { return m_transform.GetTranslation(); }
|
||||
const AZ::Transform& GetTransform() const { return m_transform; }
|
||||
void SetTransform(const AZ::Transform& transform);
|
||||
|
||||
const AZ::Vector3& GetOuterExtents() const { return m_outerExtents; }
|
||||
@@ -86,8 +86,8 @@ namespace AZ
|
||||
const AZ::Vector3& GetInnerExtents() const { return m_innerExtents; }
|
||||
void SetInnerExtents(const AZ::Vector3& innerExtents);
|
||||
|
||||
const Aabb& GetOuterAabbWs() const { return m_outerAabbWs; }
|
||||
const Aabb& GetInnerAabbWs() const { return m_innerAabbWs; }
|
||||
const Obb& GetOuterObbWs() const { return m_outerObbWs; }
|
||||
const Obb& GetInnerObbWs() const { return m_innerObbWs; }
|
||||
|
||||
const Data::Instance<RPI::Image>& GetCubeMapImage() const { return m_cubeMapImage; }
|
||||
void SetCubeMapImage(const Data::Instance<RPI::Image>& cubeMapImage, const AZStd::string& relativePath);
|
||||
@@ -133,9 +133,9 @@ namespace AZ
|
||||
AZ::Vector3 m_outerExtents = AZ::Vector3(0.0f, 0.0f, 0.0f);
|
||||
AZ::Vector3 m_innerExtents = AZ::Vector3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
// probe volume AABBs (world space), built from position and extents
|
||||
Aabb m_outerAabbWs;
|
||||
Aabb m_innerAabbWs;
|
||||
// probe volume OBBs (world space), built from position and extents
|
||||
Obb m_outerObbWs;
|
||||
Obb m_innerObbWs;
|
||||
|
||||
// cubemap
|
||||
Data::Instance<RPI::Image> m_cubeMapImage;
|
||||
|
||||
+18
-22
@@ -92,6 +92,10 @@ namespace AZ
|
||||
m_reflectionRenderData.m_modelToWorldStencilConstantIndex = stencilSrgLayout->FindShaderInputConstantIndex(modelToWorldConstantName);
|
||||
AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_modelToWorldStencilConstantIndex.IsValid(), "Failed to find stencil shader input constant [%s]", modelToWorldConstantName.GetCStr());
|
||||
|
||||
Name modelToWorldInverseConstantName = Name("m_modelToWorldInverse");
|
||||
m_reflectionRenderData.m_modelToWorldInverseStencilConstantIndex = stencilSrgLayout->FindShaderInputConstantIndex(modelToWorldInverseConstantName);
|
||||
AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_modelToWorldInverseStencilConstantIndex.IsValid(), "Failed to find stencil shader input constant [%s]", modelToWorldInverseConstantName.GetCStr());
|
||||
|
||||
// cache probe render shader indices
|
||||
// Note: the outer and inner render shaders use the same Srg
|
||||
Data::Instance<RPI::ShaderResourceGroup> renderReflectionSrg = RPI::ShaderResourceGroup::Create(
|
||||
@@ -104,25 +108,16 @@ namespace AZ
|
||||
m_reflectionRenderData.m_modelToWorldRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(modelToWorldConstantName);
|
||||
AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_modelToWorldRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", modelToWorldConstantName.GetCStr());
|
||||
|
||||
Name aabbPosConstantName = Name("m_aabbPos");
|
||||
m_reflectionRenderData.m_aabbPosRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(aabbPosConstantName);
|
||||
AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_aabbPosRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", aabbPosConstantName.GetCStr());
|
||||
m_reflectionRenderData.m_modelToWorldInverseRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(modelToWorldInverseConstantName);
|
||||
AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_modelToWorldRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", modelToWorldInverseConstantName.GetCStr());
|
||||
|
||||
Name outerAabbMinConstantName = Name("m_outerAabbMin");
|
||||
m_reflectionRenderData.m_outerAabbMinRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(outerAabbMinConstantName);
|
||||
AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_outerAabbMinRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", outerAabbMinConstantName.GetCStr());
|
||||
Name outerObbHalfLengthsConstantName = Name("m_outerObbHalfLengths");
|
||||
m_reflectionRenderData.m_outerObbHalfLengthsRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(outerObbHalfLengthsConstantName);
|
||||
AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_outerObbHalfLengthsRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", outerObbHalfLengthsConstantName.GetCStr());
|
||||
|
||||
Name outerAabbMaxConstantName = Name("m_outerAabbMax");
|
||||
m_reflectionRenderData.m_outerAabbMaxRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(outerAabbMaxConstantName);
|
||||
AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_outerAabbMaxRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", outerAabbMaxConstantName.GetCStr());
|
||||
|
||||
Name innerAabbMinConstantName = Name("m_innerAabbMin");
|
||||
m_reflectionRenderData.m_innerAabbMinRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(innerAabbMinConstantName);
|
||||
AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_innerAabbMinRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", innerAabbMinConstantName.GetCStr());
|
||||
|
||||
Name innerAabbMaxConstantName = Name("m_innerAabbMax");
|
||||
m_reflectionRenderData.m_innerAabbMaxRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(innerAabbMaxConstantName);
|
||||
AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_innerAabbMaxRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", innerAabbMaxConstantName.GetCStr());
|
||||
Name innerObbHalfLengthsConstantName = Name("m_innerObbHalfLengths");
|
||||
m_reflectionRenderData.m_innerObbHalfLengthsRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(innerObbHalfLengthsConstantName);
|
||||
AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_innerObbHalfLengthsRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", innerObbHalfLengthsConstantName.GetCStr());
|
||||
|
||||
Name useParallaxCorrectionConstantName = Name("m_useParallaxCorrection");
|
||||
m_reflectionRenderData.m_useParallaxCorrectionRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(useParallaxCorrectionConstantName);
|
||||
@@ -199,10 +194,11 @@ namespace AZ
|
||||
// sort the probes by descending inner volume size, so the smallest volumes are rendered last
|
||||
auto sortFn = [](AZStd::shared_ptr<ReflectionProbe> const& probe1, AZStd::shared_ptr<ReflectionProbe> const& probe2) -> bool
|
||||
{
|
||||
const Aabb& aabb1 = probe1->GetInnerAabbWs();
|
||||
const Aabb& aabb2 = probe2->GetInnerAabbWs();
|
||||
float size1 = aabb1.GetXExtent() * aabb1.GetZExtent() * aabb1.GetYExtent();
|
||||
float size2 = aabb2.GetXExtent() * aabb2.GetZExtent() * aabb2.GetYExtent();
|
||||
const Obb& obb1 = probe1->GetInnerObbWs();
|
||||
const Obb& obb2 = probe2->GetInnerObbWs();
|
||||
float size1 = obb1.GetHalfLengthX() * obb1.GetHalfLengthZ() * obb1.GetHalfLengthY();
|
||||
float size2 = obb2.GetHalfLengthX() * obb2.GetHalfLengthZ() * obb2.GetHalfLengthY();
|
||||
|
||||
return (size1 > size2);
|
||||
};
|
||||
|
||||
@@ -347,7 +343,7 @@ namespace AZ
|
||||
// simple AABB check to find the reflection probes that contain the position
|
||||
for (auto& reflectionProbe : m_reflectionProbes)
|
||||
{
|
||||
if (reflectionProbe->GetOuterAabbWs().Contains(position)
|
||||
if (reflectionProbe->GetOuterObbWs().Contains(position)
|
||||
&& reflectionProbe->GetCubeMapImage()
|
||||
&& reflectionProbe->GetCubeMapImage()->IsInitialized())
|
||||
{
|
||||
|
||||
@@ -116,6 +116,22 @@ float ComputeLerpBetweenInnerOuterAABBs(float3 innerAabbMin, float3 innerAabbMax
|
||||
return totalDistance > 0.0f ? saturate(shortestDistance / totalDistance) : 1.0f;
|
||||
}
|
||||
|
||||
// returns true if the Obb contains the specified point
|
||||
bool ObbContainsPoint(float4x4 obbTransformInverse, float3 obbHalfExtents, float3 testPoint)
|
||||
{
|
||||
// get the position in Obb local space, force to positive quadrant with abs()
|
||||
float4 p = abs(mul(obbTransformInverse, float4(testPoint, 1.0f)));
|
||||
return AabbContainsPoint(-obbHalfExtents, obbHalfExtents, p);
|
||||
}
|
||||
|
||||
// computes [0..1] percentage of a point that's in between the inner and outer OBBs
|
||||
float ComputeLerpBetweenInnerOuterOBBs(float3x4 obbTransformInverse, float3 innerObbHalfExtents, float3 outerObbHalfExtents, float3 position)
|
||||
{
|
||||
// get the position in Obb local space, force to positive quadrant with abs()
|
||||
float3 p = abs(mul(obbTransformInverse, float4(position, 1.0f)));
|
||||
return ComputeLerpBetweenInnerOuterAABBs(-innerObbHalfExtents, innerObbHalfExtents, outerObbHalfExtents, float3(0.0f, 0.0f, 0.0f), p);
|
||||
}
|
||||
|
||||
// ---------- Normal Encoding -----------
|
||||
|
||||
// Encode/Decode functions for Signed Octahedron normals
|
||||
|
||||
+4
-3
@@ -212,6 +212,9 @@ namespace AZ
|
||||
|
||||
AZ::Vector3 position = AZ::Vector3::CreateZero();
|
||||
AZ::TransformBus::EventResult(position, GetEntityId(), &AZ::TransformBus::Events::GetWorldTranslation);
|
||||
AZ::Quaternion rotationQuaternion = AZ::Quaternion::CreateIdentity();
|
||||
AZ::TransformBus::EventResult(rotationQuaternion, GetEntityId(), &AZ::TransformBus::Events::GetWorldRotationQuaternion);
|
||||
AZ::Matrix3x3 rotationMatrix = AZ::Matrix3x3::CreateFromQuaternion(rotationQuaternion);
|
||||
|
||||
float scale = 1.0f;
|
||||
AZ::TransformBus::EventResult(scale, GetEntityId(), &AZ::TransformBus::Events::GetLocalUniformScale);
|
||||
@@ -224,9 +227,7 @@ namespace AZ
|
||||
AZ::Vector3 innerExtents(configuration.m_innerWidth, configuration.m_innerLength, configuration.m_innerHeight);
|
||||
innerExtents *= scale;
|
||||
|
||||
AZ::Vector3 innerMin(position.GetX() - innerExtents.GetX() / 2, position.GetY() - innerExtents.GetY() / 2, position.GetZ() - innerExtents.GetZ() / 2);
|
||||
AZ::Vector3 innerMax(position.GetX() + innerExtents.GetX() / 2, position.GetY() + innerExtents.GetY() / 2, position.GetZ() + innerExtents.GetZ() / 2);
|
||||
debugDisplay.DrawWireBox(innerMin, innerMax);
|
||||
debugDisplay.DrawWireOBB(position, rotationMatrix.GetBasisX(), rotationMatrix.GetBasisY(), rotationMatrix.GetBasisZ(), innerExtents / 2.0f);
|
||||
}
|
||||
|
||||
AZ::Aabb EditorReflectionProbeComponent::GetEditorSelectionBoundsViewport([[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo)
|
||||
|
||||
Reference in New Issue
Block a user