namespace UnityEngine.Experimental.ScriptableRenderLoop
{
[Serializable]
public enum SkyResolution
{
SkyResolution128 = 1 2 8 ,
SkyResolution256 = 2 5 6 ,
SkyResolution512 = 5 1 2 ,
SkyResolution1024 = 1 0 2 4 ,
// TODO: Anything above 1024 cause a crash in Unity...
//SkyResolution2048 = 2048,
//SkyResolution4096 = 4096
}
[Serializable]
public float multiplier = 1.0f ;
public float multiplier = 1.0f ;
public SkyResolution skyResolution = SkyResolution . SkyResolution256 ;
const int kSkyCubemapSize = 2 5 6 ;
RenderTexture m_SkyboxCubemapRT = null ;
RenderTexture m_SkyboxGGXCubemapRT = null ;
SkyParameters m_bakedSkyParameters = new SkyParameters ( ) ; // This is the SkyParam used when baking and convolving the sky.
Mesh [ ] m_CubemapFaceMesh = new Mesh [ 6 ] ;
Mesh BuildSkyMesh ( Camera camera , bool forceUVBottom )
{
vertData [ 2 ] = new Vector3 ( vertData2 . x , vertData2 . y , vertData2 . z ) ;
vertData [ 3 ] = new Vector3 ( vertData3 . x , vertData3 . y , vertData3 . z ) ;
// Get view vector vased on the frustrum, i.e (invert transform frustr um get position etc...)
// Get view vector based on the frustum, i.e (invert transform frust um get position etc...)
Vector3 [ ] eyeVectorData = new Vector3 [ 4 ] ;
Matrix4x4 transformMatrix = camera . cameraToWorldMatrix * camera . projectionMatrix . inverse ;
} ;
}
void RebuildTextures ( )
void RebuildTextures ( SkyParameters skyParameters )
if ( m_SkyboxCubemapRT = = null )
if ( ( m_SkyboxCubemapRT ! = null ) & & ( m_SkyboxCubemapRT . width ! = ( int ) skyParameters . skyResolution ) )
m_SkyboxCubemapRT = new RenderTexture ( kSkyCubemapSize , kSkyCubemapSize , 1 , RenderTextureFormat . ARGBHalf ) ;
Utilities . Destroy ( m_SkyboxCubemapRT ) ;
m_SkyboxCubemapRT = null ;
Utilities . Destroy ( m_SkyboxGGXCubemapRT ) ;
m_SkyboxGGXCubemapRT = null ;
}
if ( m_SkyboxCubemapRT = = null )
{
m_SkyboxCubemapRT = new RenderTexture ( ( int ) skyParameters . skyResolution , ( int ) skyParameters . skyResolution , 1 , RenderTextureFormat . ARGBHalf ) ;
m_SkyboxCubemapRT . autoGenerateMips = true ;
m_SkyboxCubemapRT . filterMode = FilterMode . Point ;
m_SkyboxCubemapRT . autoGenerateMips = true ; // Generate regular mipmap for filtered importance sampling
m_SkyboxCubemapRT . filterMode = FilterMode . Trilinear ;
}
if ( m_SkyboxGGXCubemapRT = = null )
{
m_SkyboxGGXCubemapRT = new RenderTexture ( kSkyCubemapSize , kSkyCubemapSize , 1 , RenderTextureFormat . ARGBHalf ) ;
m_SkyboxGGXCubemapRT = new RenderTexture ( ( int ) skyParameters . skyResolution , ( int ) skyParameters . skyResolution , 1 , RenderTextureFormat . ARGBHalf ) ;
m_SkyboxGGXCubemapRT . dimension = TextureDimension . Cube ;
m_SkyboxGGXCubemapRT . useMipMap = true ;
m_SkyboxGGXCubemapRT . autoGenerateMips = false ;
Shader . SetGlobalTexture ( "_SkyTexture" , m_SkyboxGGXCubemapRT ) ;
}
public void Resize ( SkyParameters skyParameters )
{
// When loading RenderDoc, RenderTextures will go null
RebuildTextures ( skyParameters ) ;
}
public void Rebuild ( )
{
// TODO: We need to have an API to send our sky information to Enlighten. For now use a workaround through skybox/cubemap material...
m_GGXConvolveMaterial = Utilities . CreateEngineMaterial ( "Hidden/HDRenderLoop/GGXConvolve" ) ;
m_RenderSkyPropertyBlock = new MaterialPropertyBlock ( ) ;
RebuildTextures ( ) ;
m_RenderSkyPropertyBlock = new MaterialPropertyBlock ( ) ;
Matrix4x4 cubeProj = Matrix4x4 . Perspective ( 9 0.0f , 1.0f , 0.1f , 1.0f ) ;
camera . projectionMatrix = cubeProj ;
Transform transform = camera . GetComponent < Transform > ( ) ;
transform . LookAt ( lookAtList [ i ] , UpVectorList [ i ] ) ;
// When rendering into a texture the render will be flip (due to legacy unity openGL behavior), so we need to flip UV here...
m_CubemapFaceMesh [ i ] = BuildSkyMesh ( camera , true ) ;
}
}
return parameters . skyHDRI ! = null ;
}
private void RenderSky ( Camera camera , SkyParameters skyParameters , bool forceUVBottom , RenderLoop renderLoop )
private void RenderSky ( Camera camera , SkyParameters skyParameters , Mesh skyMesh , RenderLoop renderLoop )
Mesh skyMesh = BuildSkyMesh ( camera , forceUVBottom ) ;
Shader . EnableKeyword ( "PERFORM_SKY_OCCLUSION_TEST" ) ;
m_RenderSkyPropertyBlock . SetTexture ( "_Cubemap" , skyParameters . skyHDRI ) ;
{
Utilities . SetRenderTarget ( renderLoop , target , 0 , ( CubemapFace ) i ) ;
Camera faceCamera = m_CubemapFaceCamera [ i ] . GetComponent < Camera > ( ) ;
RenderSky ( faceCamera , skyParameters , true , renderLoop ) ;
RenderSky ( faceCamera , skyParameters , m_CubemapFaceMesh [ i ] , renderLoop ) ;
}
}
Utilities . SetRenderTarget ( renderLoop , target , mip , ( CubemapFace ) face ) ;
Camera faceCamera = m_CubemapFaceCamera [ face ] . GetComponent < Camera > ( ) ;
Mesh skyMesh = BuildSkyMesh ( faceCamera , true ) ;
cmd . DrawMesh ( skyMesh , Matrix4x4 . identity , m_GGXConvolveMaterial , 0 , 0 , propertyBlock ) ;
cmd . DrawMesh ( m_CubemapFaceMesh [ face ] , Matrix4x4 . identity , m_GGXConvolveMaterial , 0 , 0 , propertyBlock ) ;
renderLoop . ExecuteCommandBuffer ( cmd ) ;
cmd . Dispose ( ) ;
}
{
using ( new Utilities . ProfilingSample ( "Sky Pass" , renderLoop ) )
{
//using (new EditorGUI.DisabledScope(m_LookDevEnvLibrary.hdriList.Count <= 1))
// When loading RenderDoc, RenderTextures will go null
RebuildTextures ( ) ;
// Trigger a rebuild of cubemap / convolution
// TODO: can we have some kind of hash value here ? +> use or override GetHashCode() + include a refresh rate value in parameters
if ( skyParameters . skyResolution ! = m_bakedSkyParameters . skyResolution | |
skyParameters . exposure ! = m_bakedSkyParameters . exposure | |
skyParameters . rotation ! = m_bakedSkyParameters . rotation | |
skyParameters . multiplier ! = m_bakedSkyParameters . multiplier )
{
using ( new Utilities . ProfilingSample ( "Sky Pass: Render Cubemap" , renderLoop ) )
{
// Render sky into a cubemap - doesn't happen every frame, can be controlled
RenderSkyToCubemap ( skyParameters , m_SkyboxCubemapRT , renderLoop ) ;
// Convolve downsampled cubemap
RenderCubemapGGXConvolution ( m_SkyboxCubemapRT , m_SkyboxGGXCubemapRT , renderLoop ) ;
using ( new Utilities . ProfilingSample ( "Sky Pass: Render Cubemap" , renderLoop ) )
{
// Render sky into a cubemap - doesn't happen every frame, can be controlled
RenderSkyToCubemap ( skyParameters , m_SkyboxCubemapRT , renderLoop ) ;
// Convolve downsampled cubemap
RenderCubemapGGXConvolution ( m_SkyboxCubemapRT , m_SkyboxGGXCubemapRT , renderLoop ) ;
// TODO: Properly send the cubemap to Enlighten. Currently workaround is to set the cubemap in a Skybox/cubemap material
m_StandardSkyboxMaterial . SetTexture ( "_Tex" , m_SkyboxCubemapRT ) ;
RenderSettings . skybox = m_StandardSkyboxMaterial ; // Setup this material as the default to be use in RenderSettings
RenderSettings . ambientIntensity = 1.0f ; // fix this to 1, this parameter should not exist!
RenderSettings . ambientMode = UnityEngine . Rendering . AmbientMode . Skybox ; // Force skybox for our HDRI
RenderSettings . reflectionIntensity = 1.0f ;
RenderSettings . customReflection = null ;
//DynamicGI.UpdateEnvironment();
}
// TODO: Properly send the cubemap to Enlighten. Currently workaround is to set the cubemap in a Skybox/cubemap material
m_StandardSkyboxMaterial . SetTexture ( "_Tex" , m_SkyboxCubemapRT ) ;
RenderSettings . skybox = m_StandardSkyboxMaterial ; // Setup this material as the default to be use in RenderSettings
RenderSettings . ambientIntensity = 1.0f ; // fix this to 1, this parameter should not exist!
RenderSettings . ambientMode = UnityEngine . Rendering . AmbientMode . Skybox ; // Force skybox for our HDRI
RenderSettings . reflectionIntensity = 1.0f ;
RenderSettings . customReflection = null ;
//DynamicGI.UpdateEnvironment();
// Cleanup all this...
m_bakedSkyParameters . skyResolution = skyParameters . skyResolution ;
m_bakedSkyParameters . exposure = skyParameters . exposure ;
m_bakedSkyParameters . rotation = skyParameters . rotation ;
m_bakedSkyParameters . multiplier = skyParameters . multiplier ;
RenderSky ( camera , skyParameters , false , renderLoop ) ;
RenderSky ( camera , skyParameters , BuildSkyMesh ( camera , false ) , renderLoop ) ;
}
}
}