Skip to content

Fix light frustum planes #3341

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions com.unity.render-pipelines.high-definition/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

### Fixed
- Fixed an exception when opening the color picker in the material UI (case 1307143).
- Fixed lights shadow frustum near and far planes.

### Changed
- Removed the material pass probe volumes evaluation mode.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2083,8 +2083,8 @@ private void UpdateDirectionalShadowRequest(HDShadowManager manager, HDShadowSet
HDShadowUtils.ExtractDirectionalLightData(
visibleLight, viewportSize, (uint)requestIndex, shadowSettings.cascadeShadowSplitCount.value,
shadowSettings.cascadeShadowSplits, nearPlaneOffset, cullResults, lightIndex,
out shadowRequest.view, out invViewProjection, out shadowRequest.deviceProjectionYFlip,
out shadowRequest.deviceProjection, out shadowRequest.splitData
out shadowRequest.view, out invViewProjection, out shadowRequest.projection,
out shadowRequest.deviceProjection, out shadowRequest.deviceProjectionYFlip, out shadowRequest.splitData
);

cullingSphere = shadowRequest.splitData.cullingSphere;
Expand Down Expand Up @@ -2114,17 +2114,17 @@ internal void UpdateShadowRequestData(HDCamera hdCamera, HDShadowManager manager
HDShadowUtils.ExtractPointLightData(
visibleLight, viewportSize, shadowNearPlane,
normalBias, (uint)shadowIndex, filteringQuality, out shadowRequest.view,
out invViewProjection, out shadowRequest.deviceProjectionYFlip,
out shadowRequest.deviceProjection, out shadowRequest.splitData
out invViewProjection, out shadowRequest.projection,
out shadowRequest.deviceProjection, out shadowRequest.deviceProjectionYFlip, out shadowRequest.splitData
);
break;
case HDLightType.Spot:
float spotAngleForShadows = useCustomSpotLightShadowCone ? Math.Min(customSpotLightShadowCone, visibleLight.light.spotAngle) : visibleLight.light.spotAngle;
HDShadowUtils.ExtractSpotLightData(
spotLightShape, spotAngleForShadows, shadowNearPlane, aspectRatio, shapeWidth,
shapeHeight, visibleLight, viewportSize, normalBias, filteringQuality,
out shadowRequest.view, out invViewProjection, out shadowRequest.deviceProjectionYFlip,
out shadowRequest.deviceProjection, out shadowRequest.splitData
out shadowRequest.view, out invViewProjection, out shadowRequest.projection,
out shadowRequest.deviceProjection, out shadowRequest.deviceProjectionYFlip, out shadowRequest.splitData
);
break;
case HDLightType.Directional:
Expand All @@ -2138,7 +2138,7 @@ internal void UpdateShadowRequestData(HDCamera hdCamera, HDShadowManager manager
float offset = GetAreaLightOffsetForShadows(shapeSize, areaLightShadowCone);
Vector3 shadowOffset = offset * visibleLight.GetForward();
HDShadowUtils.ExtractRectangleAreaLightData(visibleLight, visibleLight.GetPosition() + shadowOffset, areaLightShadowCone, shadowNearPlane, shapeSize, viewportSize, normalBias, filteringQuality,
out shadowRequest.view, out invViewProjection, out shadowRequest.deviceProjectionYFlip, out shadowRequest.deviceProjection, out shadowRequest.splitData);
out shadowRequest.view, out invViewProjection, out shadowRequest.projection, out shadowRequest.deviceProjection, out shadowRequest.deviceProjectionYFlip, out shadowRequest.splitData);
break;
case AreaLightShape.Tube:
//Tube do not cast shadow at the moment.
Expand Down Expand Up @@ -2307,7 +2307,7 @@ void SetCommonShadowRequestSettings(HDShadowRequest shadowRequest, VisibleLight
}

// shadow clip planes (used for tessellation clipping)
GeometryUtility.CalculateFrustumPlanes(CoreMatrixUtils.MultiplyProjectionMatrix(shadowRequest.deviceProjectionYFlip, shadowRequest.view, hasOrthoMatrix), m_ShadowFrustumPlanes);
GeometryUtility.CalculateFrustumPlanes(CoreMatrixUtils.MultiplyProjectionMatrix(shadowRequest.projection, shadowRequest.view, hasOrthoMatrix), m_ShadowFrustumPlanes);
if (shadowRequest.frustumPlanes?.Length != 6)
shadowRequest.frustumPlanes = new Vector4[6];
// Left, right, top, bottom, near, far.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ class HDShadowRequest
// Use the y flipped device projection matrix as light projection matrix
public Matrix4x4 deviceProjectionYFlip;
public Matrix4x4 deviceProjection;
public Matrix4x4 projection;
public Matrix4x4 shadowToWorld;
public Vector3 position;
public Vector4 zBufferParam;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,17 @@ static float GetPunctualFilterWidthInTexels(HDShadowFilteringQuality quality)
}

public static void ExtractPointLightData(VisibleLight visibleLight, Vector2 viewportSize, float nearPlane, float normalBiasMax, uint faceIndex, HDShadowFilteringQuality filteringQuality,
out Matrix4x4 view, out Matrix4x4 invViewProjection, out Matrix4x4 projection, out Matrix4x4 deviceProjection, out ShadowSplitData splitData)
out Matrix4x4 view, out Matrix4x4 invViewProjection, out Matrix4x4 projection, out Matrix4x4 deviceProjection, out Matrix4x4 deviceProjectionYFlip, out ShadowSplitData splitData)
{
Vector4 lightDir;

float guardAngle = CalcGuardAnglePerspective(90.0f, viewportSize.x, GetPunctualFilterWidthInTexels(filteringQuality), normalBiasMax, 79.0f);
ExtractPointLightMatrix(visibleLight, faceIndex, nearPlane, guardAngle, out view, out projection, out deviceProjection, out invViewProjection, out lightDir, out splitData);
ExtractPointLightMatrix(visibleLight, faceIndex, nearPlane, guardAngle, out view, out projection, out deviceProjection, out deviceProjectionYFlip, out invViewProjection, out lightDir, out splitData);
}

// TODO: box spot and pyramid spots with non 1 aspect ratios shadow are incorrectly culled, see when scriptable culling will be here
public static void ExtractSpotLightData(SpotLightShape shape, float spotAngle, float nearPlane, float aspectRatio, float shapeWidth, float shapeHeight, VisibleLight visibleLight, Vector2 viewportSize, float normalBiasMax, HDShadowFilteringQuality filteringQuality,
out Matrix4x4 view, out Matrix4x4 invViewProjection, out Matrix4x4 projection, out Matrix4x4 deviceProjection, out ShadowSplitData splitData)
out Matrix4x4 view, out Matrix4x4 invViewProjection, out Matrix4x4 projection, out Matrix4x4 deviceProjection, out Matrix4x4 deviceProjectionYFlip, out ShadowSplitData splitData)
{
Vector4 lightDir;

Expand All @@ -50,18 +50,19 @@ public static void ExtractSpotLightData(SpotLightShape shape, float spotAngle, f
aspectRatio = 1.0f;

float guardAngle = CalcGuardAnglePerspective(spotAngle, viewportSize.x, GetPunctualFilterWidthInTexels(filteringQuality), normalBiasMax, 180.0f - spotAngle);
ExtractSpotLightMatrix(visibleLight, spotAngle, nearPlane, guardAngle, aspectRatio, out view, out projection, out deviceProjection, out invViewProjection, out lightDir, out splitData);
ExtractSpotLightMatrix(visibleLight, spotAngle, nearPlane, guardAngle, aspectRatio, out view, out projection, out deviceProjection, out deviceProjectionYFlip, out invViewProjection, out lightDir, out splitData);

if (shape == SpotLightShape.Box)
{
projection = ExtractBoxLightProjectionMatrix(visibleLight.range, shapeWidth, shapeHeight, nearPlane);
deviceProjection = GL.GetGPUProjectionMatrix(projection, false);
projection = GL.GetGPUProjectionMatrix(projection, true);
InvertOrthographic(ref projection, ref view, out invViewProjection);
deviceProjectionYFlip = GL.GetGPUProjectionMatrix(projection, true);
InvertOrthographic(ref deviceProjectionYFlip, ref view, out invViewProjection);
}
}

public static void ExtractDirectionalLightData(VisibleLight visibleLight, Vector2 viewportSize, uint cascadeIndex, int cascadeCount, float[] cascadeRatios, float nearPlaneOffset, CullingResults cullResults, int lightIndex, out Matrix4x4 view, out Matrix4x4 invViewProjection, out Matrix4x4 projection, out Matrix4x4 deviceProjection, out ShadowSplitData splitData)
public static void ExtractDirectionalLightData(VisibleLight visibleLight, Vector2 viewportSize, uint cascadeIndex, int cascadeCount, float[] cascadeRatios, float nearPlaneOffset, CullingResults cullResults, int lightIndex,
out Matrix4x4 view, out Matrix4x4 invViewProjection, out Matrix4x4 projection, out Matrix4x4 deviceProjection, out Matrix4x4 deviceProjectionYFlip, out ShadowSplitData splitData)
{
Vector4 lightDir;

Expand All @@ -84,21 +85,21 @@ public static void ExtractDirectionalLightData(VisibleLight visibleLight, Vector
cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(lightIndex, (int)cascadeIndex, cascadeCount, ratios, (int)viewportSize.x, nearPlaneOffset, out view, out projection, out splitData);
// and the compound (deviceProjection will potentially inverse-Z)
deviceProjection = GL.GetGPUProjectionMatrix(projection, false);
projection = GL.GetGPUProjectionMatrix(projection, true);
deviceProjectionYFlip = GL.GetGPUProjectionMatrix(projection, true);
InvertOrthographic(ref deviceProjection, ref view, out invViewProjection);
}

// Currently area light shadows are not supported
public static void ExtractRectangleAreaLightData(VisibleLight visibleLight, Vector3 shadowPosition, float areaLightShadowCone, float shadowNearPlane, Vector2 shapeSize, Vector2 viewportSize, float normalBiasMax, HDShadowFilteringQuality filteringQuality,
out Matrix4x4 view, out Matrix4x4 invViewProjection, out Matrix4x4 projection, out Matrix4x4 deviceProjection, out ShadowSplitData splitData)
out Matrix4x4 view, out Matrix4x4 invViewProjection, out Matrix4x4 projection, out Matrix4x4 deviceProjection, out Matrix4x4 deviceProjectionYFlip, out ShadowSplitData splitData)
{
Vector4 lightDir;
float aspectRatio = shapeSize.x / shapeSize.y;
float spotAngle = areaLightShadowCone;
visibleLight.spotAngle = spotAngle;
float guardAngle = CalcGuardAnglePerspective(visibleLight.spotAngle, viewportSize.x, GetPunctualFilterWidthInTexels(filteringQuality), normalBiasMax, 180.0f - visibleLight.spotAngle);

ExtractSpotLightMatrix(visibleLight, visibleLight.spotAngle, shadowNearPlane, guardAngle, aspectRatio, out view, out projection, out deviceProjection, out invViewProjection, out lightDir, out splitData);
ExtractSpotLightMatrix(visibleLight, visibleLight.spotAngle, shadowNearPlane, guardAngle, aspectRatio, out view, out projection, out deviceProjection, out deviceProjectionYFlip, out invViewProjection, out lightDir, out splitData);
}

// Cubemap faces with flipped z coordinate.
Expand Down Expand Up @@ -245,7 +246,7 @@ public static Matrix4x4 ExtractBoxLightProjectionMatrix(float range, float width
return Matrix4x4.Ortho(-width / 2, width / 2, -height / 2, height / 2, nearZ, range);
}

static Matrix4x4 ExtractSpotLightMatrix(VisibleLight vl, float spotAngle, float nearPlane, float guardAngle, float aspectRatio, out Matrix4x4 view, out Matrix4x4 proj, out Matrix4x4 deviceProj, out Matrix4x4 vpinverse, out Vector4 lightDir, out ShadowSplitData splitData)
static Matrix4x4 ExtractSpotLightMatrix(VisibleLight vl, float spotAngle, float nearPlane, float guardAngle, float aspectRatio, out Matrix4x4 view, out Matrix4x4 proj, out Matrix4x4 deviceProj, out Matrix4x4 deviceProjYFlip, out Matrix4x4 vpinverse, out Vector4 lightDir, out ShadowSplitData splitData)
{
splitData = new ShadowSplitData();
splitData.cullingSphere.Set(0.0f, 0.0f, 0.0f, float.NegativeInfinity);
Expand All @@ -263,12 +264,12 @@ static Matrix4x4 ExtractSpotLightMatrix(VisibleLight vl, float spotAngle, float
proj = ExtractSpotLightProjectionMatrix(vl.range, spotAngle, nearPlane, aspectRatio, guardAngle);
// and the compound (deviceProj will potentially inverse-Z)
deviceProj = GL.GetGPUProjectionMatrix(proj, false);
proj = GL.GetGPUProjectionMatrix(proj, true);
deviceProjYFlip = GL.GetGPUProjectionMatrix(proj, true);
InvertPerspective(ref deviceProj, ref view, out vpinverse);
return CoreMatrixUtils.MultiplyPerspectiveMatrix(deviceProj, view);
}

static Matrix4x4 ExtractPointLightMatrix(VisibleLight vl, uint faceIdx, float nearPlane, float guardAngle, out Matrix4x4 view, out Matrix4x4 proj, out Matrix4x4 deviceProj, out Matrix4x4 vpinverse, out Vector4 lightDir, out ShadowSplitData splitData)
static Matrix4x4 ExtractPointLightMatrix(VisibleLight vl, uint faceIdx, float nearPlane, float guardAngle, out Matrix4x4 view, out Matrix4x4 proj, out Matrix4x4 deviceProj, out Matrix4x4 deviceProjYFlip, out Matrix4x4 vpinverse, out Vector4 lightDir, out ShadowSplitData splitData)
{
if (faceIdx > (uint)CubemapFace.NegativeZ)
Debug.LogError("Tried to extract cubemap face " + faceIdx + ".");
Expand All @@ -288,7 +289,7 @@ static Matrix4x4 ExtractPointLightMatrix(VisibleLight vl, uint faceIdx, float ne
proj = Matrix4x4.Perspective(90.0f + guardAngle, 1.0f, nearZ, vl.range);
// and the compound (deviceProj will potentially inverse-Z)
deviceProj = GL.GetGPUProjectionMatrix(proj, false);
proj = GL.GetGPUProjectionMatrix(proj, true);
deviceProjYFlip = GL.GetGPUProjectionMatrix(proj, true);
InvertPerspective(ref deviceProj, ref view, out vpinverse);

Matrix4x4 devProjView = CoreMatrixUtils.MultiplyPerspectiveMatrix(deviceProj, view);
Expand Down