Skip to content

Commit 2317af5

Browse files
author
Paul Demeulenaere
committed
Merge remote-tracking branch 'origin/master' into scriptablerenderloop-materialgraph
2 parents cb08abd + 156afc2 commit 2317af5

58 files changed

Lines changed: 8925 additions & 172 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.asset.meta

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,8 @@ void UpdateReflectionProbes(VisibleReflectionProbe[] activeReflectionProbes)
529529
continue;
530530

531531
var l = new EnvLightData();
532-
532+
533+
// CAUTION: localToWorld is the transform for the widget of the reflection probe. i.e the world position of the point use to do the cubemap capture (mean it include the local offset)
533534
l.positionWS = probe.localToWorld.GetColumn(3);
534535
l.shapeType = EnvShapeType.None;
535536

@@ -538,18 +539,20 @@ void UpdateReflectionProbes(VisibleReflectionProbe[] activeReflectionProbes)
538539
l.shapeType = EnvShapeType.Box;
539540
}
540541

542+
// remove scale from the matrix (Scale in this matrix is use to scale the widget)
541543
l.right = probe.localToWorld.GetColumn(0);
544+
l.right.Normalize();
542545
l.up = probe.localToWorld.GetColumn(1);
546+
l.up.Normalize();
543547
l.forward = probe.localToWorld.GetColumn(2);
548+
l.forward.Normalize();
544549

545550
l.innerDistance = probe.bounds.extents;
546551

547552
l.sliceIndex = m_cubeReflTexArray.FetchSlice(probe.texture);
548553

549-
// center is local capture point. By multiply by localToWorld we get world position
550-
l.capturePointWS = probe.localToWorld.MultiplyPoint(probe.center);
554+
l.offsetLS = probe.center; // center is misnamed, it is the offset (in local space) from center of the bounding box to the cubemap capture point
551555
l.blendDistance = probe.blendDistance;
552-
553556
lights.Add(l);
554557
}
555558

Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/LightDefinition.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public struct EnvLightData
9090
public Vector3 innerDistance;
9191
public float unused1;
9292

93-
public Vector3 capturePointWS;
93+
public Vector3 offsetLS;
9494
public float unused2;
9595
};
9696

Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/LightDefinition.cs.hlsl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ struct EnvLightData
7171
float unused0;
7272
float3 innerDistance;
7373
float unused1;
74-
float3 capturePointWS;
74+
float3 offsetLS;
7575
float unused2;
7676
};
7777

@@ -237,9 +237,9 @@ float GetUnused1(EnvLightData value)
237237
{
238238
return value.unused1;
239239
}
240-
float3 GetCapturePointWS(EnvLightData value)
240+
float3 GetOffsetLS(EnvLightData value)
241241
{
242-
return value.capturePointWS;
242+
return value.offsetLS;
243243
}
244244
float GetUnused2(EnvLightData value)
245245
{

Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Lit/Lit.hlsl

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -787,54 +787,68 @@ void EvaluateBSDF_Env( float3 V, float3 positionWS, PreLightData prelightData,
787787
// float shrinkedRoughness = AnisotropicStrechAtGrazingAngle(bsdfData.roughness, bsdfData.perceptualRoughness, NdotV);
788788

789789
// Note: As explain in GetPreLightData we use normalWS and not iblNormalWS here (in case of anisotropy)
790-
//float3 rayWS = GetSpecularDominantDir(bsdfData.normalWS, prelightData.iblR, bsdfData.roughness);
791-
792-
float3 rayWS = prelightData.iblR;
790+
float3 rayWS = GetSpecularDominantDir(bsdfData.normalWS, prelightData.iblR, bsdfData.roughness);
793791

794792
float3 R = rayWS;
795793
float weight = 1.0;
796794

797-
/*
795+
// In Unity the cubemaps are capture with the localToWorld transform of the component.
796+
// This mean that location and oritention matter. So after intersection of proxy volume we need to convert back to world.
798797
if (lightData.shapeType == ENVSHAPETYPE_BOX)
799798
{
799+
// CAUTION: localToWorld is the transform use to convert the cubemap capture point to world space (mean it include the offset)
800+
// the center of the bounding box is thus in locals space: positionLS - offsetLS
801+
// We use this formulation as it is the one of legacy unity that was using only AABB box.
802+
800803
// worldToLocal assume no scaling
801-
float4x4 worldToLocal = transpose(float4x4(float4(lightData.right, 0.0), float4(lightData.up, 0.0), float4(lightData.forward, 0.0), float4(light.positionWS, 1.0)));
802-
float3 positionLS = mul(lightData.worldToLocal, float4(positionWS, 1.0)).xyz;
803-
float3 rayLS = mul((float3x3)lightData.worldToLocal, rayWS);
804+
float3x3 worldToLocal = transpose(float3x3(lightData.right, lightData.up, lightData.forward));
805+
float3 positionLS = positionWS - lightData.positionWS;
806+
positionLS = mul(positionLS, worldToLocal).xyz - lightData.offsetLS; // We want to calculate the intersection from the center of the bounding box.
807+
808+
float3 rayLS = mul(rayWS, worldToLocal);
804809
float3 boxOuterDistance = lightData.innerDistance + float3(lightData.blendDistance, lightData.blendDistance, lightData.blendDistance);
805810
float dist = BoxRayIntersectSimple(positionLS, rayLS, -boxOuterDistance, boxOuterDistance);
806-
807-
// No need to normalize for fetching cubemap
808-
R = (positionWS + dist * rayWS) - lightData.capturePointWS; // TODO: check that
809811

812+
// No need to normalize for fetching cubemap
813+
// We can reuse dist calculate in LS directly in WS as there is no scaling. Also the offset is already include in lightData.positionWS
814+
R = (positionWS + dist * rayWS) - lightData.positionWS;
815+
810816
// TODO: add distance based roughness
811817

812-
// Calculate falloff value, so reflections on the edges of the Volume would gradually blend to previous reflection.
813-
// Also this ensures that pixels not located in the reflection Volume AABB won't
814-
// accidentally pick up reflections from this Volume.
818+
// Calculate falloff value, so reflections on the edges of the volume would gradually blend to previous reflection.
815819
float distFade = DistancePointBox(positionLS, -lightData.innerDistance, lightData.innerDistance);
816820
weight = saturate(1.0 - distFade / max(lightData.blendDistance, 0.0001)); // avoid divide by zero
817821

818822
// Smooth weighting
819823
weight = smoothstep01(weight);
820-
}
824+
}
821825
else if (lightData.shapeType == ENVSHAPETYPE_SPHERE)
822826
{
827+
// For now there is no specific interface for sphere proxy and it can have offset and arbitrary orientation. So we need to transform
828+
// to local space position and direction like for OBB.
829+
float3x3 worldToLocal = transpose(float3x3(lightData.right, lightData.up, lightData.forward));
830+
float3 positionLS = positionWS - lightData.positionWS;
831+
positionLS = mul(positionLS, worldToLocal).xyz - lightData.offsetLS; // We want to calculate the intersection from the center of the bounding box.
832+
833+
float3 rayLS = mul(rayWS, worldToLocal);
823834
float sphereRadius = lightData.innerDistance.x;
824-
float2 intersections;
825-
SphereRayIntersect(intersections, positionWS - lightData.positionWS, R, sphereRadius);
826-
// TODO: check if we can have simplified formula like for box
827-
// No need to normalize for fetching cubemap
828-
R = (positionWS + intersections.y * rayWS) - lightData.capturePointWS;
835+
float dist = SphereRayIntersectSimple(positionLS, rayLS, sphereRadius + lightData.blendDistance);
836+
837+
R = (positionWS + dist * rayWS) - lightData.positionWS;
829838

830839
float distFade = length(positionWS - lightData.positionWS);
831840
weight = saturate(((sphereRadius + lightData.blendDistance) - distFade) / max(lightData.blendDistance, 0.0001)); // avoid divide by zero
832841

833842
// Smooth weighting
834843
weight = smoothstep01(weight);
835844
}
836-
*/
837845

846+
// TODO: we must always perform a weight calculation as due to tiled rendering we need to smooth out cubemap at boundaries.
847+
// So goal is to split into two category and have an option to say if we parallax correct or not.
848+
849+
// TODO: compare current Morten version: offline cubemap with a particular remap + the bias in perceptualRoughnessToMipmapLevel
850+
// to classic remap like unreal/Frobiste. The function GetSpecularDominantDir can result in a better matching in this case
851+
// We let GetSpecularDominantDir currently as it still an improvement but not as good as it could be
838852
float mip = perceptualRoughnessToMipmapLevel(bsdfData.perceptualRoughness);
839853
float4 preLD = UNITY_SAMPLE_ENV_LOD(_EnvTextures, R, lightData, mip);
840854
specularLighting.rgb = preLD.rgb * prelightData.specularFGD;

Assets/ScriptableRenderLoop/ShaderLibrary/GeometricTools.hlsl

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ float2 BoxRayIntersect(float3 start, float3 dir, float3 boxMin, float3 boxMax)
2929
return intersections;
3030
}
3131

32-
// TODO: Describe difference with above
33-
// AND compare with intersections.y
32+
// This simplified version assume that we care about the result only when we are inside the box
3433
// Assume dir is normalize
3534
float BoxRayIntersectSimple(float3 start, float3 dir, float3 boxMin, float3 boxMax)
3635
{
@@ -45,15 +44,16 @@ float BoxRayIntersectSimple(float3 start, float3 dir, float3 boxMin, float3 boxM
4544
return min(min(rbminmax.x, rbminmax.y), rbminmax.z);
4645
}
4746

48-
// Sphere is at the origin
49-
bool SphereRayIntersect(out float2 intersections, float3 start, float3 dir, float radius)
47+
// Assume Sphere is at the origin (i.e start = position - spherePosition)
48+
float2 SphereRayIntersect(float3 start, float3 dir, float radius, out bool intersect)
5049
{
5150
float a = dot(dir, dir);
5251
float b = dot(dir, start) * 2.0;
5352
float c = dot(start, start) - radius * radius;
5453
float discriminant = b * b - 4.0 * a * c;
5554

56-
bool intersect = false;
55+
float2 intersections = float2(0.0, 0.0);
56+
intersect = false;
5757
if (discriminant < 0.0 || a == 0.0)
5858
{
5959
intersections.x = 0.0;
@@ -67,7 +67,19 @@ bool SphereRayIntersect(out float2 intersections, float3 start, float3 dir, floa
6767
intersect = true;
6868
}
6969

70-
return intersect;
70+
return intersections;
71+
}
72+
73+
// This simplified version assume that we care about the result only when we are inside the sphere
74+
// Assume Sphere is at the origin (i.e start = position - spherePosition) and dir is normalized
75+
// Ref: http://http.developer.nvidia.com/GPUGems/gpugems_ch19.html
76+
float SphereRayIntersectSimple(float3 start, float3 dir, float radius)
77+
{
78+
float b = dot(dir, start) * 2.0;
79+
float c = dot(start, start) - radius * radius;
80+
float discriminant = b * b - 4.0 * c;
81+
82+
return abs(sqrt(discriminant) - b) * 0.5;
7183
}
7284

7385
float3 RayPlaneIntersect(in float3 rayOrigin, in float3 rayDirection, in float3 planeOrigin, in float3 planeNormal)
@@ -80,24 +92,10 @@ float3 RayPlaneIntersect(in float3 rayOrigin, in float3 rayDirection, in float3
8092
// Distance functions
8193
//-----------------------------------------------------------------------------
8294

83-
/*
84-
// Ref: real time detection collision page 131
85-
float DistancePointBox(float3 pos, float3 boxMin, float3 boxMax)
86-
{
87-
// Clamp to find closest point then calc distance
88-
float3 distanceToMin = pos < boxMin ? (boxMin - pos) * (boxMin - pos) : 0.0;
89-
float3 distancesToMax = pos > boxMax ? (pos - boxMax) * (pos - boxMax) : 0.0;
90-
91-
float distanceSquare = dot(distanceToMin, float3(1.0, 1.0, 1.0)) + dot(distancesToMax, float3(1.0, 1.0, 1.0));
92-
return sqrt(distanceSquare);
93-
}
94-
*/
95-
96-
// TODO: check that this code is effectively equivalent to code above (it should)
9795
// Box is AABB
98-
float DistancePointBox(float3 pos, float3 boxMin, float3 boxMax)
96+
float DistancePointBox(float3 position, float3 boxMin, float3 boxMax)
9997
{
100-
return length(max(max(pos - boxMax, boxMin - pos), float3(0.0, 0.0, 0.0)));
98+
return length(max(max(position - boxMax, boxMin - position), float3(0.0, 0.0, 0.0)));
10199
}
102100

103101
#endif // UNITY_GEOMETRICTOOLS_INCLUDED

Assets/ScriptableRenderLoop/common/TextureCache.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,9 @@ public bool AllocTextureArray(int numCubeMaps, int width, TextureFormat format,
8686
m_Cache = new CubemapArray(width, numCubeMaps, format, isMipMapped)
8787
{
8888
hideFlags = HideFlags.HideAndDontSave,
89-
wrapMode = TextureWrapMode.Clamp
89+
wrapMode = TextureWrapMode.Clamp,
90+
filterMode = FilterMode.Trilinear,
91+
anisoLevel = 0 // It is important to set 0 here, else unity force anisotropy filtering
9092
};
9193

9294
return res;

Assets/ScriptableRenderLoop/fptl/ReflectionTemplate.hlsl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,7 @@ half3 Unity_GlossyEnvironment (UNITY_ARGS_TEXCUBEARRAY(tex), int sliceIndex, hal
135135
half mip = perceptualRoughness * UNITY_SPECCUBE_LOD_STEPS;
136136
half4 rgbm = UNITY_SAMPLE_TEXCUBEARRAY_LOD(tex, float4(glossIn.reflUVW.xyz, sliceIndex), mip);
137137

138-
//return rgbm.xyz;
139-
return DecodeHDR_NoLinearSupportInSM2 (rgbm, hdr);
138+
return DecodeHDR(rgbm, hdr);
140139
}
141140

142141

0 commit comments

Comments
 (0)