public class BuiltinSkyParameters
{
public Matrix4x4 pixelCoordToViewDirMatrix ;
public Mesh skyMesh ;
public CommandBuffer commandBuffer ;
public Light sunLight ;
public RenderTargetIdentifier colorBuffer ;
IBLFilterGGX m_iblFilterGgx = null ;
Vector4 m_CubemapScreenSize ;
Matrix4x4 [ ] m_faceCameraViewProjectionMatrix = new Matrix4x4 [ 6 ] ;
Matrix4x4 [ ] m_faceWorldToViewMatrixMatrices = new Matrix4x4 [ 6 ] ;
Matrix4x4 [ ] m_facePixelCoordToViewDirMatrices = new Matrix4x4 [ 6 ] ;
Mesh [ ] m_CubemapFaceMesh = new Mesh [ 6 ] ;
BuiltinSkyParameters m_BuiltinParameters = new BuiltinSkyParameters ( ) ;
SkyRenderer m_Renderer = null ;
public Texture skyReflection { get { return m_SkyboxGGXCubemapRT ; } }
protected Mesh BuildSkyMesh ( Vector3 cameraPosition , Matrix4x4 cameraInvViewProjectionMatrix )
{
// These are clip space coords.
Vector4 vertData0 = new Vector4 ( - 1.0f , - 1.0f , 0.0f , 1.0f ) ;
Vector4 vertData1 = new Vector4 ( 1.0f , - 1.0f , 0.0f , 1.0f ) ;
Vector4 vertData2 = new Vector4 ( 1.0f , 1.0f , 0.0f , 1.0f ) ;
Vector4 vertData3 = new Vector4 ( - 1.0f , 1.0f , 0.0f , 1.0f ) ;
Vector3 [ ] vertData = new Vector3 [ 4 ] ;
vertData [ 0 ] = new Vector3 ( vertData0 . x , vertData0 . y , vertData0 . z ) ;
vertData [ 1 ] = new Vector3 ( vertData1 . x , vertData1 . y , vertData1 . z ) ;
vertData [ 2 ] = new Vector3 ( vertData2 . x , vertData2 . y , vertData2 . z ) ;
vertData [ 3 ] = new Vector3 ( vertData3 . x , vertData3 . y , vertData3 . z ) ;
// Get view vector based on the frustum, i.e (invert transform frustum get position etc...)
Vector3 [ ] eyeVectorData = new Vector3 [ 4 ] ;
Matrix4x4 transformMatrix = cameraInvViewProjectionMatrix ;
Vector4 posWorldSpace0 = transformMatrix * vertData0 ;
Vector4 posWorldSpace1 = transformMatrix * vertData1 ;
Vector4 posWorldSpace2 = transformMatrix * vertData2 ;
Vector4 posWorldSpace3 = transformMatrix * vertData3 ;
Vector4 cameraPos = new Vector4 ( cameraPosition . x , cameraPosition . y , cameraPosition . z , 0.0f ) ;
Vector4 direction0 = ( posWorldSpace0 / posWorldSpace0 . w - cameraPos ) ;
Vector4 direction1 = ( posWorldSpace1 / posWorldSpace1 . w - cameraPos ) ;
Vector4 direction2 = ( posWorldSpace2 / posWorldSpace2 . w - cameraPos ) ;
Vector4 direction3 = ( posWorldSpace3 / posWorldSpace3 . w - cameraPos ) ;
if ( SystemInfo . graphicsUVStartsAtTop )
{
eyeVectorData [ 3 ] = new Vector3 ( direction0 . x , direction0 . y , direction0 . z ) . normalized ;
eyeVectorData [ 2 ] = new Vector3 ( direction1 . x , direction1 . y , direction1 . z ) . normalized ;
eyeVectorData [ 1 ] = new Vector3 ( direction2 . x , direction2 . y , direction2 . z ) . normalized ;
eyeVectorData [ 0 ] = new Vector3 ( direction3 . x , direction3 . y , direction3 . z ) . normalized ;
}
else
{
eyeVectorData [ 0 ] = new Vector3 ( direction0 . x , direction0 . y , direction0 . z ) . normalized ;
eyeVectorData [ 1 ] = new Vector3 ( direction1 . x , direction1 . y , direction1 . z ) . normalized ;
eyeVectorData [ 2 ] = new Vector3 ( direction2 . x , direction2 . y , direction2 . z ) . normalized ;
eyeVectorData [ 3 ] = new Vector3 ( direction3 . x , direction3 . y , direction3 . z ) . normalized ;
}
// Write out the mesh
var triangles = new int [ 6 ] { 0 , 1 , 2 , 2 , 3 , 0 } ;
return new Mesh
{
vertices = vertData ,
normals = eyeVectorData ,
triangles = triangles
} ;
}
void RebuildTextures ( SkySettings skySettings )
{
int resolution = 2 5 6 ;
m_CubemapScreenSize = new Vector4 ( ( float ) resolution , ( float ) resolution , 1.0f / ( float ) resolution , 1.0f / ( float ) resolution ) ;
}
void RebuildSkyMeshes ( float nearPlane , float farPlane )
void RebuildSkyMatrices ( float nearPlane , float farPlane )
if ( m_CubemapFaceMesh [ 0 ] = = null )
if ( ! m_SkySettings ) return ;
Matrix4x4 cubeProj = Matrix4x4 . Perspective ( 9 0.0f , 1.0f , nearPlane , farPlane ) ;
// Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/bb204881(v=vs.85).aspx
Vector3 [ ] lookAtList =
Matrix4x4 cubeProj = Matrix4x4 . Perspective ( 9 0.0f , 1.0f , nearPlane , farPlane ) ;
new Vector3 ( 1.0f , 0.0f , 0.0f ) ,
new Vector3 ( - 1.0f , 0.0f , 0.0f ) ,
new Vector3 ( 0.0f , 1.0f , 0.0f ) ,
new Vector3 ( 0.0f , - 1.0f , 0.0f ) ,
new Vector3 ( 0.0f , 0.0f , 1.0f ) ,
new Vector3 ( 0.0f , 0.0f , - 1.0f ) ,
} ;
Vector3 [ ] upVectorList =
{
new Vector3 ( 0.0f , 1.0f , 0.0f ) ,
new Vector3 ( 0.0f , 1.0f , 0.0f ) ,
new Vector3 ( 0.0f , 0.0f , - 1.0f ) ,
new Vector3 ( 0.0f , 0.0f , 1.0f ) ,
new Vector3 ( 0.0f , 1.0f , 0.0f ) ,
new Vector3 ( 0.0f , 1.0f , 0.0f ) ,
} ;
Vector3 [ ] lookAtList =
{
new Vector3 ( 1.0f , 0.0f , 0.0f ) ,
new Vector3 ( - 1.0f , 0.0f , 0.0f ) ,
new Vector3 ( 0.0f , 1.0f , 0.0f ) ,
new Vector3 ( 0.0f , - 1.0f , 0.0f ) ,
new Vector3 ( 0.0f , 0.0f , 1.0f ) ,
new Vector3 ( 0.0f , 0.0f , - 1.0f ) ,
} ;
for ( int i = 0 ; i < 6 ; + + i )
{
Matrix4x4 lookAt = Matrix4x4 . LookAt ( Vector3 . zero , lookAtList [ i ] , upVectorList [ i ] ) ;
Matrix4x4 worldToView = lookAt * Matrix4x4 . Scale ( new Vector3 ( 1.0f , 1.0f , - 1.0f ) ) ; // Need to scale -1.0 on Z to match what is being done in the camera.wolrdToCameraMatrix API. ...
Vector4 screenSize = new Vector4 ( ( int ) m_SkySettings . resolution , ( int ) m_SkySettings . resolution , 1.0f / ( int ) m_SkySettings . resolution , 1.0f / ( int ) m_SkySettings . resolution ) ;
Vector3 [ ] UpVectorList =
{
new Vector3 ( 0.0f , 1.0f , 0.0f ) ,
new Vector3 ( 0.0f , 1.0f , 0.0f ) ,
new Vector3 ( 0.0f , 0.0f , - 1.0f ) ,
new Vector3 ( 0.0f , 0.0f , 1.0f ) ,
new Vector3 ( 0.0f , 1.0f , 0.0f ) ,
new Vector3 ( 0.0f , 1.0f , 0.0f ) ,
} ;
m_faceWorldToViewMatrixMatrices [ i ] = worldToView ;
m_facePixelCoordToViewDirMatrices [ i ] = ComputePixelCoordToWorldSpaceViewDirectionMatrix ( 0.5f * Mathf . PI , screenSize , worldToView , true ) ;
m_faceCameraInvViewProjectionMatrix [ i ] = Utilities . GetViewProjectionMatrix ( lookAt , cubeProj ) . inverse ;
}
}
for ( int i = 0 ; i < 6 ; + + i )
{
Matrix4x4 lookAt = Matrix4x4 . LookAt ( Vector3 . zero , lookAtList [ i ] , UpVectorList [ i ] ) ;
m_faceCameraViewProjectionMatrix [ i ] = Utilities . GetViewProjectionMatrix ( lookAt , cubeProj ) ;
m_faceCameraInvViewProjectionMatrix [ i ] = m_faceCameraViewProjectionMatrix [ i ] . inverse ;
public static Matrix4x4 ComputePixelCoordToWorldSpaceViewDirectionMatrix ( float verticalFoV , Vector4 screenSize , Matrix4x4 worldToViewMatrix , bool renderToCubemap )
{
// Compose the view space version first.
// V = -(X, Y, Z), s.t. Z = 1,
// X = (2x / resX - 1) * tan(vFoV / 2) * ar = x * [(2 / resX) * tan(vFoV / 2) * ar] + [-tan(vFoV / 2) * ar] = x * [-m00] + [-m20]
// Y = (2y / resY - 1) * tan(vFoV / 2) = y * [(2 / resY) * tan(vFoV / 2)] + [-tan(vFoV / 2)] = y * [-m11] + [-m21]
float tanHalfVertFoV = Mathf . Tan ( 0.5f * verticalFoV ) ;
float aspectRatio = screenSize . x * screenSize . w ;
m_CubemapFaceMesh [ i ] = BuildSkyMesh ( Vector3 . zero , m_faceCameraInvViewProjectionMatrix [ i ] ) ;
}
// Compose the matrix.
float m21 = tanHalfVertFoV ;
float m20 = tanHalfVertFoV * aspectRatio ;
float m00 = - 2.0f * screenSize . z * m20 ;
float m11 = - 2.0f * screenSize . w * m21 ;
float m33 = - 1.0f ;
if ( renderToCubemap )
{
// Flip Y.
m11 = - m11 ;
m21 = - m21 ;
Matrix4x4 viewSpaceRasterTransform = new Matrix4x4 ( new Vector4 ( m00 , 0.0f , 0.0f , 0.0f ) ,
new Vector4 ( 0.0f , m11 , 0.0f , 0.0f ) ,
new Vector4 ( m20 , m21 , m33 , 0.0f ) ,
new Vector4 ( 0.0f , 0.0f , 0.0f , 1.0f ) ) ;
// Remove the translation component.
Vector4 homogeneousZero = new Vector4 ( 0 , 0 , 0 , 1 ) ;
worldToViewMatrix . SetColumn ( 3 , homogeneousZero ) ;
// Flip the Z to make the coordinate system left-handed.
worldToViewMatrix . SetRow ( 2 , - worldToViewMatrix . GetRow ( 2 ) ) ;
// Transpose for HLSL.
return Matrix4x4 . Transpose ( worldToViewMatrix . transpose * viewSpaceRasterTransform ) ;
}
// Sets the global MIP-mapped cubemap '_SkyTexture' in the shader.
{
// When loading RenderDoc, RenderTextures will go null
RebuildTextures ( skySettings ) ;
RebuildSkyMesh es ( nearPlane , farPlane ) ;
RebuildSkyMatric es ( nearPlane , farPlane ) ;
}
public void Build ( RenderPipelineResources renderPipelinesResources )
{
for ( int i = 0 ; i < 6 ; + + i )
{
builtinParams . pixelCoordToViewDirMatrix = m_facePixelCoordToViewDirMatrices [ i ] ;
builtinParams . screenSize = m_CubemapScreenSize ;
builtinParams . skyMesh = m_CubemapFaceMesh [ i ] ;
builtinParams . colorBuffer = target ;
builtinParams . depthBuffer = BuiltinSkyParameters . nullRT ;
{
if ( m_useMIS & & m_iblFilterGgx . SupportMIS )
{
m_iblFilterGgx . FilterCubemapMIS ( cmd , input , target , mipCount , m_SkyboxConditionalCdfRT , m_SkyboxMarginalRowCdfRT , m_CubemapFaceMesh ) ;
m_iblFilterGgx . FilterCubemapMIS ( cmd , input , target , mipCount , m_SkyboxConditionalCdfRT , m_SkyboxMarginalRowCdfRT , m_faceWorldToViewMatrixMatrices ) ;
m_iblFilterGgx . FilterCubemap ( cmd , input , target , mipCount , m_CubemapFaceMesh ) ;
m_iblFilterGgx . FilterCubemap ( cmd , input , target , mipCount , m_faceWorldToViewMatrixMatrices ) ;
}
}
}
m_BuiltinParameters . commandBuffer = cmd ;
m_BuiltinParameters . sunLight = sunLight ;
m_BuiltinParameters . screenSize = m_CubemapScreenSize ;
m_BuiltinParameters . cameraPosWS = camera . camera . transform . position ;
if (
m_UpdatedFramesRequired > 0 | |
{
m_BuiltinParameters . commandBuffer = cmd ;
m_BuiltinParameters . sunLight = sunLight ;
m_BuiltinParameters . pixelCoordToViewDirMatrix = ComputePixelCoordToWorldSpaceViewDirectionMatrix ( camera . camera . fieldOfView * Mathf . Deg2Rad , camera . screenSize , camera . viewMatrix , false ) ;
m_BuiltinParameters . screenSize = camera . screenSize ;
m_BuiltinParameters . skyMesh = BuildSkyMesh ( camera . camera . GetComponent < Transform > ( ) . position , m_BuiltinParameters . invViewProjMatrix ) ;
m_BuiltinParameters . colorBuffer = colorBuffer ;
m_BuiltinParameters . depthBuffer = depthBuffer ;