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 ( 9 0.0f + fovBias , 1.0f , nearPlane , farPlane ) ;
// and the compound
return proj * view ;
}