using System ;
using System.Collections.Generic ;
using UnityEngine.VR ;
namespace UnityEngine.Experimental.Rendering.Fptl
{
public class FptlLightingInstance : RenderPipeline
public bool enableReflectionProbeDebug = false ;
public bool enableComputeLightEvaluation = false ;
const bool k_UseDepthBuffer = true ; // // only has an impact when EnableClustered is true (requires a depth-prepass)
const bool k_UseAsyncCompute = true ; // should not use on mobile
//const bool k_UseAsyncCompute = true; // should not use on mobile
const bool k_UseAsyncCompute = false ; // Easier for ordering for Stereo prototype
const int k_Log2NumClusters = 6 ; // accepted range is from 0 to 6. NumClusters is 1<<g_iLog2NumClusters
const int k_Log2NumClusters = 6 ; // accepted range is from 0 to 6. NumClusters is 1<<g_iLog2NumClusters
const float k_ClustLogBase = 1.02f ; // each slice 2% bigger than the previous
float m_ClustScale ;
private static ComputeBuffer s_PerVoxelLightLists ;
private static int s_WidthOnRecord ;
private static int s_HeightOnRecord ;
private static bool s_stereoDoublewideOnRecord = false ;
Matrix4x4 [ ] m_MatWorldToShadow = new Matrix4x4 [ k_MaxLights * k_MaxShadowmapPerLights ] ;
Vector4 [ ] m_DirShadowSplitSpheres = new Vector4 [ k_MaxDirectionalSplit ] ;
private Texture2D m_LightAttentuationTexture ;
private int m_shadowBufferID ;
// VR state bits
private bool stereoActive ;
private bool stereoSinglePass ;
private bool stereoDoublewide ;
private RenderTextureDesc cachedStereoDesc ;
public void Cleanup ( )
{
if ( m_DeferredMaterial ) DestroyImmediate ( m_DeferredMaterial ) ;
m_shadowBufferID = Shader . PropertyToID ( "g_tShadowBuffer" ) ;
}
static void SetupGBuffer ( int width , int height , CommandBuffer cmd )
{
//static void SetupGBuffer(int width, int height, CommandBuffer cmd)
static void SetupGBuffer ( RenderTextureDesc baseDesc , CommandBuffer cmd )
{
var format10 = RenderTextureFormat . ARGB32 ;
if ( SystemInfo . SupportsRenderTextureFormat ( RenderTextureFormat . ARGB2101010 ) )
format10 = RenderTextureFormat . ARGB2101010 ;
// so we make it think we always render in HDR
cmd . EnableShaderKeyword ( "UNITY_HDR_ON" ) ;
//@TODO: GetGraphicsCaps().buggyMRTSRGBWriteFlag
cmd . GetTemporaryRT ( s_GBufferAlbedo , width , height , 0 , FilterMode . Point , RenderTextureFormat . ARGB32 , RenderTextureReadWrite . Default ) ;
cmd . GetTemporaryRT ( s_GBufferSpecRough , width , height , 0 , FilterMode . Point , RenderTextureFormat . ARGB32 , RenderTextureReadWrite . Default ) ;
cmd . GetTemporaryRT ( s_GBufferNormal , width , height , 0 , FilterMode . Point , format10 , RenderTextureReadWrite . Linear ) ;
cmd . GetTemporaryRT ( s_GBufferEmission , width , height , 0 , FilterMode . Point , formatHDR , RenderTextureReadWrite . Linear ) ;
cmd . GetTemporaryRT ( s_GBufferZ , width , height , 2 4 , FilterMode . Point , RenderTextureFormat . Depth ) ;
cmd . GetTemporaryRT ( s_CameraDepthTexture , width , height , 2 4 , FilterMode . Point , RenderTextureFormat . Depth ) ;
cmd . GetTemporaryRT ( s_CameraTarget , width , height , 0 , FilterMode . Point , formatHDR , RenderTextureReadWrite . Default , 1 , true ) ; // rtv/uav
var colorMRTs = new RenderTargetIdentifier [ 4 ] { s_GBufferAlbedo , s_GBufferSpecRough , s_GBufferNormal , s_GBufferEmission } ;
//@TODO: GetGraphicsCaps().buggyMRTSRGBWriteFlag
//cmd.GetTemporaryRT(s_GBufferAlbedo, width, height, 0, FilterMode.Point, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default);
//cmd.GetTemporaryRT(s_GBufferSpecRough, width, height, 0, FilterMode.Point, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default);
//cmd.GetTemporaryRT(s_GBufferNormal, width, height, 0, FilterMode.Point, format10, RenderTextureReadWrite.Linear);
//cmd.GetTemporaryRT(s_GBufferEmission, width, height, 0, FilterMode.Point, formatHDR, RenderTextureReadWrite.Linear);
//cmd.GetTemporaryRT(s_GBufferZ, width, height, 24, FilterMode.Point, RenderTextureFormat.Depth);
//cmd.GetTemporaryRT(s_CameraDepthTexture, width, height, 24, FilterMode.Point, RenderTextureFormat.Depth);
//cmd.GetTemporaryRT(s_CameraTarget, width, height, 0, FilterMode.Point, formatHDR, RenderTextureReadWrite.Default, 1, true); // rtv/uav
// finish this...
RenderTextureDesc modDesc = baseDesc ;
modDesc . depthBufferBits = 0 ;
modDesc . colorFormat = RenderTextureFormat . ARGB32 ;
modDesc . flags & = RenderTextureCreationFlags . SRGB ; // fix this...turn off the SRGB flag
cmd . GetTemporaryRT ( )
var colorMRTs = new RenderTargetIdentifier [ 4 ] { s_GBufferAlbedo , s_GBufferSpecRough , s_GBufferNormal , s_GBufferEmission } ;
cmd . SetRenderTarget ( colorMRTs , new RenderTargetIdentifier ( s_GBufferZ ) ) ;
cmd . ClearRenderTarget ( true , true , new Color ( 0 , 0 , 0 , 0 ) ) ;
static void RenderGBuffer ( CullResults cull , Camera camera , ScriptableRenderContext loop )
static void RenderGBuffer ( CullResults cull , Camera camera , ScriptableRenderContext loop , bool stereoDw , RenderTextureDesc stereoDesc )
SetupGBuffer ( camera . pixelWidth , camera . pixelHeight , cmd ) ;
if ( stereoDw )
{
//SetupGBuffer(stereoDesc.width, stereoDesc.height, cmd);
SetupGBuffer ( stereoDesc , cmd ) ;
}
else
{
//SetupGBuffer(camera.pixelWidth, camera.pixelHeight, cmd);
RenderTextureDesc baseDesc = new RenderTextureDesc ( camera . pixelWidth , camera . pixelHeight ) ;
SetupGBuffer ( baseDesc , cmd ) ;
}
loop . ExecuteCommandBuffer ( cmd ) ;
cmd . Dispose ( ) ;
cmd . Dispose ( ) ;
}
void CheckVRState ( )
{
stereoActive = VRSettings . isDeviceActive ;
if ( stereoActive )
{
cachedStereoDesc = VRDevice . GetVREyeTextureDesc ( ) ;
stereoDoublewide = ( cachedStereoDesc . dimension = = TextureDimension . Tex2D ) ;
}
else
{
stereoDoublewide = false ;
}
}
var w = camera . pixelWidth ;
var h = camera . pixelHeight ;
CheckVRState ( ) ;
int w , h ;
if ( stereoDoublewide )
{
w = cachedStereoDesc . width ;
h = cachedStereoDesc . height ;
}
else
{
w = camera . pixelWidth ;
h = camera . pixelHeight ;
}
ResizeIfNecessary ( w , h ) ;
if ( stereoDoublewide )
{
// VR - with double wide, our texture is double eye width
// That is the width we want to use for the light list generation...
ResizeIfNecessary ( w / 2 , h , true ) ;
}
else
{
ResizeIfNecessary ( w , h , false ) ;
}
// do anything we need to do upon a new frame.
NewFrame ( ) ;
#pragma warning restore 162
// generate g-buffer before shadows to leverage async compute
// forward opaques just write to depth.
loop . SetupCameraProperties ( camera ) ;
RenderGBuffer ( cullResults , camera , loop ) ;
if ( stereoActive )
{
loop . StereoSetupCameraProperties ( camera ) ;
loop . StartMultiEye ( camera ) ;
}
else
{
loop . SetupCameraProperties ( camera ) ;
}
RenderGBuffer ( cullResults , camera , loop , stereoDoublewide , cachedStereoDesc ) ;
// camera to screen matrix (and it's inverse)
var proj = CameraProjection ( camera ) ;
if ( stereoActive )
{
loop . StopMultiEye ( camera ) ;
}
// camera to screen matrix (and it's inverse)
var proj = CameraProjection ( camera ) ;
var temp = new Matrix4x4 ( ) ;
temp . SetRow ( 0 , new Vector4 ( 0.5f * w , 0.0f , 0.0f , 0.5f * w ) ) ;
temp . SetRow ( 1 , new Vector4 ( 0.0f , 0.5f * h , 0.0f , 0.5f * h ) ) ;
var numDirLights = UpdateDirectionalLights ( camera , cullResults . visibleLights ) ;
PushGlobalParams ( camera , loop , CameraToWorld ( camera ) , projscr , invProjscr , numDirLights ) ;
// do deferred lighting
DoTiledDeferredLighting ( camera , loop , numLights , numDirLights ) ;
if ( stereoActive )
{
loop . StartMultiEye ( camera ) ;
}
// do deferred lighting
DoTiledDeferredLighting ( camera , loop , numLights , numDirLights ) ;
// render opaques using tiled forward
RenderForward ( cullResults , camera , loop , true ) ; // opaques only (requires a depth pre-pass)
loop . ExecuteCommandBuffer ( cmd ) ;
cmd . Dispose ( ) ;
}
loop . Submit ( ) ;
if ( stereoActive )
{
loop . StopMultiEye ( camera ) ;
loop . StereoEndRender ( camera ) ;
}
loop . Submit ( ) ;
}
UpdateShadowConstants ( cullResults . visibleLights , ref shadows ) ;
}
void ResizeIfNecessary ( int curWidth , int curHeight )
void ResizeIfNecessary ( int curWidth , int curHeight , bool stereoDW )
if ( curWidth ! = s_WidthOnRecord | | curHeight ! = s_HeightOnRecord | | s_LightList = = null | |
if ( curWidth ! = s_WidthOnRecord | | curHeight ! = s_HeightOnRecord | | stereoDW ! = s_stereoDoublewideOnRecord | | s_LightList = = null | |
AllocResolutionDependentBuffers ( curWidth , curHeight ) ;
if ( stereoDW )
{
AllocResolutionDependentBuffers ( curWidth , curHeight , 2 ) ;
}
else
{
AllocResolutionDependentBuffers ( curWidth , curHeight , 1 ) ;
}
}
s_stereoDoublewideOnRecord = stereoDW ;
}
}
void ReleaseResolutionDependentBuffers ( )
return 8 * ( 1 < < k_Log2NumClusters ) ; // total footprint for all layers of the tile (measured in light index entries)
}
void AllocResolutionDependentBuffers ( int width , int height )
void AllocResolutionDependentBuffers ( int width , int height , int stereoMultiplier )
{
var nrTilesX = ( width + 1 5 ) / 1 6 ;
var nrTilesY = ( height + 1 5 ) / 1 6 ;
s_LightList = new ComputeBuffer ( LightDefinitions . NR_LIGHT_MODELS * dwordsPerTile * nrTiles , sizeof ( uint ) ) ; // enough list memory for a 4k x 4k display
//s_LightList = new ComputeBuffer(LightDefinitions.NR_LIGHT_MODELS * dwordsPerTile * nrTiles, sizeof(uint)); // enough list memory for a 4k x 4k display
s_LightList = new ComputeBuffer ( LightDefinitions . NR_LIGHT_MODELS * dwordsPerTile * nrTiles * stereoMultiplier , sizeof ( uint ) ) ; // enough list memory for a 4k x 4k display
if ( enableClustered )
if ( enableClustered )
// VR TODO - No stereo support yet...
var tileSizeClust = LightDefinitions . TILE_SIZE_CLUSTERED ;
var nrTilesClustX = ( width + ( tileSizeClust - 1 ) ) / tileSizeClust ;
var nrTilesClustY = ( height + ( tileSizeClust - 1 ) ) / tileSizeClust ;
var nrBigTilesX = ( width + 6 3 ) / 6 4 ;
var nrBigTilesY = ( height + 6 3 ) / 6 4 ;
var nrBigTiles = nrBigTilesX * nrBigTilesY ;
s_BigTileLightList = new ComputeBuffer ( LightDefinitions . MAX_NR_BIGTILE_LIGHTS_PLUSONE * nrBigTiles , sizeof ( uint ) ) ;
}
//s_BigTileLightList = new ComputeBuffer(LightDefinitions.MAX_NR_BIGTILE_LIGHTS_PLUSONE * nrBigTiles, sizeof(uint));
s_BigTileLightList = new ComputeBuffer ( LightDefinitions . MAX_NR_BIGTILE_LIGHTS_PLUSONE * nrBigTiles * stereoMultiplier , sizeof ( uint ) ) ;
}
}
void VoxelLightListGeneration ( CommandBuffer cmd , Camera camera , int numLights , Matrix4x4 projscr , Matrix4x4 invProjscr )