浏览代码

Fixed winding order of objects renderered into point shadowmaps.

Pulled point light matrix and split plane calculations from C++ into C#.
Removed cullresults and index parameters from the ShadowUtils helper function for point lights.
Added new ShadowUtilsConstants class which contains constants to work with cubemaps.
/main
uygar 8 年前
当前提交
95a0d58b
共有 2 个文件被更改,包括 119 次插入6 次删除
  1. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/Shadow.cs
  2. 123
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowUtilities.cs

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/Shadow.cs


// modify
Matrix4x4 vp;
if( sr.shadowType == GPUShadowType.Point )
vp = ShadowUtils.ExtractPointLightMatrix( lights[sr.index], key.faceIdx, 2.0f, out ce.current.view, out ce.current.proj, out ce.current.lightDir, out ce.current.splitData, m_CullResults, (int) sr.index );
vp = ShadowUtils.ExtractPointLightMatrix( lights[sr.index], key.faceIdx, 2.0f, out ce.current.view, out ce.current.proj, out ce.current.lightDir, out ce.current.splitData );
else if( sr.shadowType == GPUShadowType.Spot )
vp = ShadowUtils.ExtractSpotLightMatrix( lights[sr.index], out ce.current.view, out ce.current.proj, out ce.current.lightDir, out ce.current.splitData );
else if( sr.shadowType == GPUShadowType.Directional )

123
Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowUtilities.cs


namespace UnityEngine.Experimental.Rendering.HDPipeline
{
public class ShadowUtilsConstants
{
// Matches ScriptableShadowsUtility.cpp
public enum CubemapEdge
{
kCubeEdgePX_PY = 0,
kCubeEdgePX_NY,
kCubeEdgePX_PZ,
kCubeEdgePX_NZ,
kCubeEdgeNX_PY,
kCubeEdgeNX_NY,
kCubeEdgeNX_PZ,
kCubeEdgeNX_NZ,
kCubeEdgePY_PZ,
kCubeEdgePY_NZ,
kCubeEdgeNY_PZ,
kCubeEdgeNY_NZ,
kCubeEdge_Count
};
public static readonly CubemapEdge[,] kCubemapEdgesPerFace = new CubemapEdge[6,4]
{
{ CubemapEdge.kCubeEdgePX_PY, CubemapEdge.kCubeEdgePX_NY, CubemapEdge.kCubeEdgePX_PZ, CubemapEdge.kCubeEdgePX_NZ }, // PX
{ CubemapEdge.kCubeEdgeNX_PY, CubemapEdge.kCubeEdgeNX_NY, CubemapEdge.kCubeEdgeNX_PZ, CubemapEdge.kCubeEdgeNX_NZ }, // NX
{ CubemapEdge.kCubeEdgePX_PY, CubemapEdge.kCubeEdgeNX_PY, CubemapEdge.kCubeEdgePY_PZ, CubemapEdge.kCubeEdgePY_NZ }, // PY
{ CubemapEdge.kCubeEdgePX_NY, CubemapEdge.kCubeEdgeNX_NY, CubemapEdge.kCubeEdgeNY_PZ, CubemapEdge.kCubeEdgeNY_NZ }, // NY
{ CubemapEdge.kCubeEdgePX_PZ, CubemapEdge.kCubeEdgeNX_PZ, CubemapEdge.kCubeEdgePY_PZ, CubemapEdge.kCubeEdgeNY_PZ }, // PZ
{ CubemapEdge.kCubeEdgePX_NZ, CubemapEdge.kCubeEdgeNX_NZ, CubemapEdge.kCubeEdgePY_NZ, CubemapEdge.kCubeEdgeNY_NZ } // NZ
};
const float oneOverSqr2 = 0.70710678118654752440084436210485f;
public static readonly Vector3[] kCubemapEdgeDirections = new Vector3[(int)CubemapEdge.kCubeEdge_Count]
{
new Vector3( oneOverSqr2, oneOverSqr2, 0 ),
new Vector3( oneOverSqr2, -oneOverSqr2, 0 ),
new Vector3( oneOverSqr2, 0, oneOverSqr2 ),
new Vector3( oneOverSqr2, 0, -oneOverSqr2 ),
new Vector3( -oneOverSqr2, oneOverSqr2, 0 ),
new Vector3( -oneOverSqr2, -oneOverSqr2, 0 ),
new Vector3( -oneOverSqr2, 0, oneOverSqr2 ),
new Vector3( -oneOverSqr2, 0, -oneOverSqr2 ),
new Vector3( 0, oneOverSqr2, oneOverSqr2 ),
new Vector3( 0, oneOverSqr2, -oneOverSqr2 ),
new Vector3( 0, -oneOverSqr2, oneOverSqr2 ),
new Vector3( 0, -oneOverSqr2, -oneOverSqr2 )
};
// Cubemap faces with flipped z coordinate.
// These matrices do NOT match what we have in Skybox.cpp.
// The C++ runtime flips y as well and requires patching up
// the culling state. Using these matrices keeps the winding
// order, but may need some special treatment if rendering
// into an actual cubemap.
public static readonly Matrix4x4[] kCubemapFaces = new Matrix4x4[]
{
new Matrix4x4( // pos X
new Vector4( 0.0f, 0.0f, -1.0f, 0.0f ),
new Vector4( 0.0f, 1.0f, 0.0f, 0.0f ),
new Vector4( -1.0f, 0.0f, 0.0f, 0.0f ),
new Vector4( 0.0f, 0.0f, 0.0f, 1.0f ) ),
new Matrix4x4( // neg x
new Vector4( 0.0f, 0.0f, 1.0f, 0.0f ),
new Vector4( 0.0f, 1.0f, 0.0f, 0.0f ),
new Vector4( 1.0f, 0.0f, 0.0f, 0.0f ),
new Vector4( 0.0f, 0.0f, 0.0f, 1.0f ) ),
new Matrix4x4( // pos y
new Vector4( 1.0f, 0.0f, 0.0f, 0.0f ),
new Vector4( 0.0f, 0.0f, -1.0f, 0.0f ),
new Vector4( 0.0f, -1.0f, 0.0f, 0.0f ),
new Vector4( 0.0f, 0.0f, 0.0f, 1.0f ) ),
new Matrix4x4( // neg y
new Vector4( 1.0f, 0.0f, 0.0f, 0.0f ),
new Vector4( 0.0f, 0.0f, 1.0f, 0.0f ),
new Vector4( 0.0f, 1.0f, 0.0f, 0.0f ),
new Vector4( 0.0f, 0.0f, 0.0f, 1.0f ) ),
new Matrix4x4( // pos z
new Vector4( 1.0f, 0.0f, 0.0f, 0.0f ),
new Vector4( 0.0f, 1.0f, 0.0f, 0.0f ),
new Vector4( 0.0f, 0.0f, -1.0f, 0.0f ),
new Vector4( 0.0f, 0.0f, 0.0f, 1.0f ) ),
new Matrix4x4( // neg z
new Vector4( -1.0f, 0.0f, 0.0f, 0.0f ),
new Vector4( 0.0f, 1.0f, 0.0f, 0.0f ),
new Vector4( 0.0f, 0.0f, 1.0f, 0.0f ),
new Vector4( 0.0f, 0.0f, 0.0f, 1.0f ) )
};
}
public class ShadowUtils
{
public static Matrix4x4 ExtractSpotLightMatrix( VisibleLight vl, out Matrix4x4 view, out Matrix4x4 proj, out Vector4 lightDir, out ShadowSplitData splitData )

return proj * view;
}
public static Matrix4x4 ExtractPointLightMatrix( VisibleLight vl, uint faceIdx, float fovBias, out Matrix4x4 view, out Matrix4x4 proj, out Vector4 lightDir, out ShadowSplitData splitData, CullResults cullResults, int lightIndex )
public static Matrix4x4 ExtractPointLightMatrix( VisibleLight vl, uint faceIdx, float fovBias, out Matrix4x4 view, out Matrix4x4 proj, out Vector4 lightDir, out ShadowSplitData splitData )
splitData.cullingSphere.Set(0.0f, 0.0f, 0.0f, float.NegativeInfinity);
splitData.cullingPlaneCount = 0;
splitData.cullingSphere.Set( 0.0f, 0.0f, 0.0f, float.NegativeInfinity );
splitData.cullingPlaneCount = 4;
// TODO: At some point this logic should be moved to C#, then the parameters cullResults and lightIndex can be removed as well
cullResults.ComputePointShadowMatricesAndCullingPrimitives( lightIndex, (CubemapFace) faceIdx, fovBias, out view, out proj, out splitData );
// calculate the view matrices
Vector3 lpos = vl.light.transform.position;
view = ShadowUtilsConstants.kCubemapFaces[faceIdx];
Vector3 inverted_viewpos = ShadowUtilsConstants.kCubemapFaces[faceIdx].MultiplyPoint( -lpos );
view.SetColumn( 3, new Vector4( inverted_viewpos.x, inverted_viewpos.y, inverted_viewpos.z, 1.0f ) );
for( int i = 0; i < 4; ++i )
{
ShadowUtilsConstants.CubemapEdge cubemapEdge = ShadowUtilsConstants.kCubemapEdgesPerFace[faceIdx,i];
Vector3 cullingPlaneDirection = ShadowUtilsConstants.kCubemapEdgeDirections[(int)cubemapEdge];
splitData.SetCullingPlane( i, new Plane( cullingPlaneDirection, lpos ) );
}
// following code is from SharedLightData::GetNearPlaneMinBound
float percentageBound = 0.01f * vl.light.range;
float fixedBound = 0.1f;
float nearmin = fixedBound <= percentageBound ? fixedBound : percentageBound;
// calculate projection
float farPlane = vl.range;
float nearPlane = vl.light.shadowNearPlane >= nearmin ? vl.light.shadowNearPlane : nearmin;
proj = Matrix4x4.Perspective( 90.0f + fovBias, 1.0f, nearPlane, farPlane );
// and the compound
return proj * view;
}

正在加载...
取消
保存