浏览代码

HDRenderLoop; start support of reflection probe

- Add texture abstration in API
- Add imagebasedlighting.hlsl
- Add divide pi version of BSDF
- Change resolution of cubemap as 128
- Misc stuff
/main
sebastienlagarde 8 年前
当前提交
b2a49403
共有 24 个文件被更改,包括 755 次插入267 次删除
  1. 255
      Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.cs
  2. 5
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Debug/DebugViewMaterial.hlsl
  3. 2
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Debug/DebugViewMaterialGBuffer.shader
  4. 2
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/LightingDeferred.shader
  5. 23
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/LightingForward.hlsl
  6. 46
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/LitTemplate.hlsl
  7. 6
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Lit.hlsl
  8. 23
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Material.hlsl
  9. 4
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/PostProcess/FinalPass.shader
  10. 10
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Unlit.shader
  11. 49
      Assets/ScriptableRenderLoop/ShaderLibrary/API/D3D11.hlsl
  12. 32
      Assets/ScriptableRenderLoop/ShaderLibrary/BSDF.hlsl
  13. 5
      Assets/ScriptableRenderLoop/ShaderLibrary/Common.hlsl
  14. 24
      Assets/ScriptableRenderLoop/ShaderLibrary/CommonLighting.hlsl
  15. 4
      Assets/ScriptableRenderLoop/common/TextureSettings.cs
  16. 460
      Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl
  17. 9
      Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl.meta
  18. 9
      Assets/ScriptableRenderLoop/fptl/LightingTemplate.hlsl.meta
  19. 9
      Assets/ScriptableRenderLoop/fptl/ReflectionTemplate.hlsl.meta
  20. 9
      Assets/ScriptableRenderLoop/fptl/StandardTest.shader.meta
  21. 9
      Assets/ScriptableRenderLoop/fptl/TiledLightingTemplate.hlsl.meta
  22. 9
      Assets/ScriptableRenderLoop/fptl/TiledLightingUtils.hlsl.meta
  23. 9
      Assets/ScriptableRenderLoop/fptl/TiledReflectionTemplate.hlsl.meta
  24. 9
      Assets/ScriptableRenderLoop/fptl/UnityStandardForwardNew.cginc.meta

255
Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.cs


VertexNormalWS = 3,
VertexTangentWS = 4,
VertexBitangentWS = 5,
VertexColor = 6,
Depth = 6,
BakeDiffuseLighting = 7,
Depth = 7,
BakeDiffuseLighting = 8,
}
public class DebugParameters

}
public const int MaxLights = 32;
public const int MaxProbes = 32;
[SerializeField]
TextureSettings m_TextureSettings = TextureSettings.Default;
Material m_DeferredMaterial;
Material m_FinalPassMaterial;

static private int s_CameraDepthBuffer;
static private ComputeBuffer s_punctualLightList;
static private ComputeBuffer s_envLightList;
private TextureCacheCubemap m_cubeReflTexArray;
void OnEnable()
{

{
if (s_punctualLightList != null)
s_punctualLightList.Release();
if (s_envLightList != null)
s_envLightList.Release();
}
Material CreateEngineMaterial(string shaderPath)

s_CameraDepthBuffer = Shader.PropertyToID("_CameraDepthTexture");
s_punctualLightList = new ComputeBuffer(MaxLights, System.Runtime.InteropServices.Marshal.SizeOf(typeof(PunctualLightData)));
s_envLightList = new ComputeBuffer(MaxLights, System.Runtime.InteropServices.Marshal.SizeOf(typeof(EnvLightData)));
m_DeferredMaterial = CreateEngineMaterial("Hidden/Unity/LightingDeferred");
m_FinalPassMaterial = CreateEngineMaterial("Hidden/Unity/FinalPass");

// m_ShadowPass = new ShadowRenderPass (m_ShadowSettings);
m_cubeReflTexArray = new TextureCacheCubemap();
m_cubeReflTexArray.AllocTextureArray(32, (int)m_TextureSettings.reflectionCubemapSize, TextureFormat.BC6H, true);
s_envLightList.Release();
m_cubeReflTexArray.Release();
}
void InitAndClearBuffer(Camera camera, RenderLoop renderLoop)

Vector4 screenSize = ComputeScreenSize(camera);
m_DeferredMaterial.SetVector("_ScreenSize", screenSize);
m_DeferredMaterial.SetTexture("_reflCubeTextures", m_cubeReflTexArray.GetTexCache());
// gbufferManager.BindBuffers(m_DeferredMaterial);
// TODO: Bind depth textures
var cmd = new CommandBuffer();

cmd.Blit(s_CameraColorBuffer, BuiltinRenderTextureType.CameraTarget, m_FinalPassMaterial, 0);
renderLoop.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}
void NewFrame()
{
// update texture caches
m_cubeReflTexArray.NewFrame();
}
//---------------------------------------------------------------------------------------------------------------------------------------------------

}
s_punctualLightList.SetData(lights.ToArray());
Shader.SetGlobalBuffer("g_punctualLightList", s_punctualLightList);
Shader.SetGlobalInt("g_punctualLightCount", punctualLightCount);
Shader.SetGlobalBuffer("_PunctualLightList", s_punctualLightList);
Shader.SetGlobalInt("_PunctualLightCount", punctualLightCount);
void UpdateLightConstants(ActiveLight[] activeLights /*, ref ShadowOutput shadow */)
void UpdateReflectionProbes(VisibleReflectionProbe[] activeReflectionProbes)
/*
int nNumLightsIncludingTooMany = 0;
int g_nNumLights = 0;
Vector4[] g_vLightColor = new Vector4[ MAX_LIGHTS ];
Vector4[] g_vLightPosition_flInvRadius = new Vector4[ MAX_LIGHTS ];
Vector4[] g_vLightDirection = new Vector4[ MAX_LIGHTS ];
Vector4[] g_vLightShadowIndex_vLightParams = new Vector4[ MAX_LIGHTS ];
Vector4[] g_vLightFalloffParams = new Vector4[ MAX_LIGHTS ];
Vector4[] g_vSpotLightInnersuterConeCosines = new Vector4[ MAX_LIGHTS ];
Matrix4x4[] g_matWorldToShadow = new Matrix4x4[ MAX_LIGHTS * MAX_SHADOWMAP_PER_LIGHTS ];
Vector4[] g_vDirShadowSplitSpheres = new Vector4[ MAX_DIRECTIONAL_SPLIT ];
int envLightCount = 0;
List<EnvLightData> lights = new List<EnvLightData>();
for ( int nLight = 0; nLight < activeLights.Length; nLight++ )
for (int lightIndex = 0; lightIndex < Math.Min(activeReflectionProbes.Length, MaxProbes); lightIndex++)
nNumLightsIncludingTooMany++;
if ( nNumLightsIncludingTooMany > MAX_LIGHTS )
continue;
ActiveLight light = activeLights [nLight];
LightType lightType = light.lightType;
Vector3 position = light.light.transform.position;
Vector3 lightDir = light.light.transform.forward.normalized;
AdditionalLightData additionalLightData = light.light.GetComponent<AdditionalLightData> ();
// Setup shadow data arrays
bool hasShadows = shadow.GetShadowSliceCountLightIndex (nLight) != 0;
VisibleReflectionProbe probe = activeReflectionProbes[lightIndex];
EnvLightData l = new EnvLightData();
if ( lightType == LightType.Directional )
{
g_vLightColor[ g_nNumLights ] = light.finalColor;
g_vLightPosition_flInvRadius[ g_nNumLights ] = new Vector4(
position.x - ( lightDir.x * DIRECTIONAL_LIGHT_PULLBACK_DISTANCE ),
position.y - ( lightDir.y * DIRECTIONAL_LIGHT_PULLBACK_DISTANCE ),
position.z - ( lightDir.z * DIRECTIONAL_LIGHT_PULLBACK_DISTANCE ),
-1.0f );
g_vLightDirection[ g_nNumLights ] = new Vector4( lightDir.x, lightDir.y, lightDir.z );
g_vLightShadowIndex_vLightParams[ g_nNumLights ] = new Vector4( 0, 0, 1, 1 );
g_vLightFalloffParams[ g_nNumLights ] = new Vector4( 0.0f, 0.0f, float.MaxValue, (float)lightType );
g_vSpotLightInnerOuterConeCosines[ g_nNumLights ] = new Vector4( 0.0f, -1.0f, 1.0f );
/*
Vector3 boxOffset = rl.center; // reflection volume offset relative to cube map capture point
float blendDistance = rl.blendDistance;
if (hasShadows)
{
for (int s = 0; s < MAX_DIRECTIONAL_SPLIT; ++s)
{
g_vDirShadowSplitSpheres[s] = shadow.directionalShadowSplitSphereSqr[s];
}
}
}
else if ( lightType == LightType.Point )
{
g_vLightColor[ g_nNumLights ] = light.finalColor;
Matrix4x4 mat = rl.localToWorld;
//Matrix4x4 mat = rl.transform.localToWorldMatrix;
Vector3 cubeCapturePos = mat.GetColumn(3); // cube map capture position in world space
Vector3 combinedExtent = e + new Vector3(blendDistance, blendDistance, blendDistance);
g_vLightPosition_flInvRadius[ g_nNumLights ] = new Vector4( position.x, position.y, position.z, 1.0f / light.range );
g_vLightDirection[ g_nNumLights ] = new Vector4( 0.0f, 0.0f, 0.0f );
g_vLightShadowIndex_vLightParams[ g_nNumLights ] = new Vector4( 0, 0, 1, 1 );
g_vLightFalloffParams[ g_nNumLights ] = new Vector4( 1.0f, 0.0f, light.range * light.range, (float)lightType );
g_vSpotLightInnerOuterConeCosines[ g_nNumLights ] = new Vector4( 0.0f, -1.0f, 1.0f );
}
else if ( lightType == LightType.Spot )
{
g_vLightColor[ g_nNumLights ] = light.finalColor;
g_vLightPosition_flInvRadius[ g_nNumLights ] = new Vector4( position.x, position.y, position.z, 1.0f / light.range );
g_vLightDirection[ g_nNumLights ] = new Vector4( lightDir.x, lightDir.y, lightDir.z );
g_vLightShadowIndex_vLightParams[ g_nNumLights ] = new Vector4( 0, 0, 1, 1 );
g_vLightFalloffParams[ g_nNumLights ] = new Vector4( 1.0f, 0.0f, light.range * light.range, (float)lightType );
lightData[i].uLightType = (uint)LightDefinitions.BOX_LIGHT;
float flInnerConePercent = AdditionalLightData.GetInnerSpotPercent01(additionalLightData);
float spotAngle = light.light.spotAngle;
float flPhiDot = Mathf.Clamp( Mathf.Cos( spotAngle * 0.5f * Mathf.Deg2Rad ), 0.0f, 1.0f ); // outer cone
float flThetaDot = Mathf.Clamp( Mathf.Cos( spotAngle * 0.5f * flInnerConePercent * Mathf.Deg2Rad ), 0.0f, 1.0f ); // inner cone
g_vSpotLightInnerOuterConeCosines[ g_nNumLights ] = new Vector4( flThetaDot, flPhiDot, 1.0f / Mathf.Max( 0.01f, flThetaDot - flPhiDot ) );
m_cubeReflTexArray.FetchSlice(cubemap);
}
if (boxProj) lightData[i].flags |= LightDefinitions.IS_BOX_PROJECTED;
*/
if ( hasShadows )
{
// Enable shadows
g_vLightShadowIndex_vLightParams[ g_nNumLights ].x = 1;
for(int s=0; s < shadow.GetShadowSliceCountLightIndex (nLight); ++s)
{
int shadowSliceIndex = shadow.GetShadowSliceIndex (nLight, s);
g_matWorldToShadow [g_nNumLights * MAX_SHADOWMAP_PER_LIGHTS + s] = shadow.shadowSlices[shadowSliceIndex].shadowTransform.transpose;
}
}
g_nNumLights++;
lights.Add(l);
envLightCount++;
// Warn if too many lights found
if ( nNumLightsIncludingTooMany > MAX_LIGHTS )
{
if ( nNumLightsIncludingTooMany > m_nWarnedTooManyLights )
{
Debug.LogError( "ERROR! Found " + nNumLightsIncludingTooMany + " runtime lights! Valve renderer supports up to " + MAX_LIGHTS +
" active runtime lights at a time!\nDisabling " + ( nNumLightsIncludingTooMany - MAX_LIGHTS ) + " runtime light" +
( ( nNumLightsIncludingTooMany - MAX_LIGHTS ) > 1 ? "s" : "" ) + "!\n" );
}
m_nWarnedTooManyLights = nNumLightsIncludingTooMany;
}
else
{
if ( m_nWarnedTooManyLights > 0 )
{
m_nWarnedTooManyLights = 0;
Debug.Log( "SUCCESS! Found " + nNumLightsIncludingTooMany + " runtime lights which is within the supported number of lights, " + MAX_LIGHTS + ".\n\n" );
}
}
// Send constants to shaders
Shader.SetGlobalInt( "g_nNumLights", g_nNumLights );
// New method for Unity 5.4 to set arrays of constants
Shader.SetGlobalVectorArray( "g_vLightPosition_flInvRadius", g_vLightPosition_flInvRadius );
Shader.SetGlobalVectorArray( "g_vLightColor", g_vLightColor );
Shader.SetGlobalVectorArray( "g_vLightDirection", g_vLightDirection );
Shader.SetGlobalVectorArray( "g_vLightShadowIndex_vLightParams", g_vLightShadowIndex_vLightParams );
Shader.SetGlobalVectorArray( "g_vLightFalloffParams", g_vLightFalloffParams );
Shader.SetGlobalVectorArray( "g_vSpotLightInnerOuterConeCosines", g_vSpotLightInnerOuterConeCosines );
Shader.SetGlobalMatrixArray( "g_matWorldToShadow", g_matWorldToShadow );
Shader.SetGlobalVectorArray( "g_vDirShadowSplitSpheres", g_vDirShadowSplitSpheres );
// Time
#if ( UNITY_EDITOR )
{
Shader.SetGlobalFloat( "g_flTime", Time.realtimeSinceStartup );
//Debug.Log( "Time " + Time.realtimeSinceStartup );
}
#else
{
Shader.SetGlobalFloat( "g_flTime", Time.timeSinceLevelLoad );
//Debug.Log( "Time " + Time.timeSinceLevelLoad );
}
#endif
// PCF 3x3 Shadows
float flTexelEpsilonX = 1.0f / m_ShadowSettings.shadowAtlasWidth;
float flTexelEpsilonY = 1.0f / m_ShadowSettings.shadowAtlasHeight;
Vector4 g_vShadow3x3PCFTerms0 = new Vector4( 20.0f / 267.0f, 33.0f / 267.0f, 55.0f / 267.0f, 0.0f );
Vector4 g_vShadow3x3PCFTerms1 = new Vector4( flTexelEpsilonX, flTexelEpsilonY, -flTexelEpsilonX, -flTexelEpsilonY );
Vector4 g_vShadow3x3PCFTerms2 = new Vector4( flTexelEpsilonX, flTexelEpsilonY, 0.0f, 0.0f );
Vector4 g_vShadow3x3PCFTerms3 = new Vector4( -flTexelEpsilonX, -flTexelEpsilonY, 0.0f, 0.0f );
s_envLightList.SetData(lights.ToArray());
Shader.SetGlobalVector( "g_vShadow3x3PCFTerms0", g_vShadow3x3PCFTerms0 );
Shader.SetGlobalVector( "g_vShadow3x3PCFTerms1", g_vShadow3x3PCFTerms1 );
Shader.SetGlobalVector( "g_vShadow3x3PCFTerms2", g_vShadow3x3PCFTerms2 );
Shader.SetGlobalVector( "g_vShadow3x3PCFTerms3", g_vShadow3x3PCFTerms3 );
*/
Shader.SetGlobalBuffer("_EnvLightList", s_envLightList);
Shader.SetGlobalInt("_EnvLightCount", envLightCount);
/*
void RenderDeferredLighting(Camera camera, CullingInputs inputs, RenderLoop loop)
public override void Render(Camera[] cameras, RenderLoop renderLoop)
var props = new MaterialPropertyBlock();
var cmd = new CommandBuffer();
cmd.SetRenderTarget(new RenderTargetIdentifier(kGBufferEmission), new RenderTargetIdentifier(kGBufferZ));
foreach (var cl in inputs.culledLights)
{
bool renderAsQuad = (cl.flags & VisibleLightFlags.IntersectsNearPlane) != 0 || (cl.flags & VisibleLightFlags.IntersectsFarPlane) != 0 || (cl.lightType == LightType.Directional);
// Do anything we need to do upon a new frame.
NewFrame();
Vector3 lightPos = cl.localToWorld.GetColumn(3);
float range = cl.range;
cmd.DisableShaderKeyword("POINT");
cmd.DisableShaderKeyword("POINT_COOKIE");
cmd.DisableShaderKeyword("SPOT");
cmd.DisableShaderKeyword("DIRECTIONAL");
cmd.DisableShaderKeyword("DIRECTIONAL_COOKIE");
//cmd.EnableShaderKeyword ("UNITY_HDR_ON");
switch (cl.lightType)
{
case LightType.Point:
cmd.EnableShaderKeyword("POINT");
break;
case LightType.Spot:
cmd.EnableShaderKeyword("SPOT");
break;
case LightType.Directional:
cmd.EnableShaderKeyword("DIRECTIONAL");
break;
}
props.SetFloat("_LightAsQuad", renderAsQuad ? 1 : 0);
props.SetVector("_LightPos", new Vector4(lightPos.x, lightPos.y, lightPos.z, 1.0f / (range * range)));
props.SetVector("_LightColor", cl.finalColor);
Debug.Log("Light color : " + cl.finalColor.ToString());
props.SetMatrix("_WorldToLight", cl.worldToLocal);
///@TODO: cleanup, remove this from Internal-PrePassLighting shader
//DeferredPrivate::s_LightMaterial->SetTexture (ShaderLab::Property ("_LightTextureB0"), builtintex::GetAttenuationTexture ());
if (renderAsQuad)
{
cmd.DrawMesh(m_QuadMesh, Matrix4x4.identity, m_DeferredMaterial, 0, 0, props);
}
else
{
var matrix = Matrix4x4.TRS(lightPos, Quaternion.identity, new Vector3(range, range, range));
cmd.DrawMesh(m_PointLightMesh, matrix, m_DeferredMaterial, 0, 0, props);
}
}
loop.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}
*/
public override void Render(Camera[] cameras, RenderLoop renderLoop)
{
// Set Frame constant buffer
// TODO...

//UpdateLightConstants(cullResults.culledLights /*, ref shadows */);
UpdatePunctualLights(cullResults.culledLights);
UpdateReflectionProbes(cullResults.culledReflectionProbes);
InitAndClearBuffer(camera, renderLoop);

5
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Debug/DebugViewMaterial.hlsl


// CAUTION: 0 is a reserved numbers meaning there is no debug view mode
// All number below folow each others!
// Must be in sync with DebugViewVaryingMode
#define DEBUGVIEW_VARYING_DEPTH 1

#define DEBUGVIEW_VARYING_VERTEXCOLOR 6
// These define are sepcific to GBuffer
#define DEBUGVIEW_GBUFFER_DEPTH 6
#define DEBUGVIEW_GBUFFER_BAKEDIFFUSELIGHTING 7
#define DEBUGVIEW_GBUFFER_DEPTH 7
#define DEBUGVIEW_GBUFFER_BAKEDIFFUSELIGHTING 8

2
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Debug/DebugViewMaterialGBuffer.shader


DECLARE_GBUFFER_TEXTURE(_CameraGBufferTexture);
DECLARE_GBUFFER_BAKE_LIGHTING(_CameraGBufferTexture);
Texture2D _CameraDepthTexture;
UNITY_DECLARE_TEX2D(_CameraDepthTexture);
float4 _ScreenSize;
int _DebugViewMaterial;

2
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/LightingDeferred.shader


DECLARE_GBUFFER_TEXTURE(_CameraGBufferTexture);
DECLARE_GBUFFER_BAKE_LIGHTING(_CameraGBufferTexture);
Texture2D _CameraDepthTexture;
UNITY_DECLARE_TEX2D(_CameraDepthTexture);
float4 _ScreenSize;
float4x4 _InvViewProjMatrix;

23
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/LightingForward.hlsl


// Simple forward loop architecture
//-----------------------------------------------------------------------------
StructuredBuffer<PunctualLightData> g_punctualLightList;
int g_punctualLightCount;
StructuredBuffer<PunctualLightData> _PunctualLightList;
int _PunctualLightCount;
UNITY_DECLARE_TEXCUBEARRAY(_reflCubeTextures);
StructuredBuffer<PunctualLightData> _EnvLightList;
int _EnvLightCount;
// TODO: Think about how to apply Disney diffuse preconvolve on indirect diffuse => must be done during GBuffer layout! Else emissive will be fucked...
// That's mean we need to read DFG texture during Gbuffer...

diffuseLighting = float4(0.0, 0.0, 0.0, 0.0);
specularLighting = float4(0.0, 0.0, 0.0, 0.0);
for (int i = 0; i < g_punctualLightCount; ++i)
for (int i = 0; i < _PunctualLightCount; ++i)
EvaluateBSDF_Punctual(V, positionWS, g_punctualLightList[i], bsdfData, localDiffuseLighting, localSpecularLighting);
EvaluateBSDF_Punctual(V, positionWS, _PunctualLightList[i], bsdfData, localDiffuseLighting, localSpecularLighting);
diffuseLighting += localDiffuseLighting;
specularLighting += localSpecularLighting;
}

EvaluateBSDF_Area(V, positionWS, areaLightData[i], bsdfData, localDiffuseLighting, localSpecularLighting);
diffuseLighting += localDiffuseLighting;
specularLighting += localSpecularLighting;
}
*/
/*
for (int i = 0; i < _EnvLightCount; ++i)
{
float4 localDiffuseLighting;
float4 localSpecularLighting;
EvaluateBSDF_Env(V, positionWS, _EnvLightList[i], bsdfData, UNITY_PASS_TEXCUBEARRAY(_reflCubeTextures), localDiffuseLighting, localSpecularLighting);
diffuseLighting += localDiffuseLighting;
specularLighting += localSpecularLighting;
}
*/
}

46
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/LitTemplate.hlsl


// Set of users variables
float4 _BaseColor;
sampler2D _BaseColorMap;
UNITY_DECLARE_TEX2D(_BaseColorMap);
sampler2D _MaskMap;
sampler2D _SpecularOcclusionMap;
UNITY_DECLARE_TEX2D(_MaskMap);
UNITY_DECLARE_TEX2D(_SpecularOcclusionMap);
sampler2D _NormalMap;
sampler2D _Heightmap;
UNITY_DECLARE_TEX2D(_NormalMap);
UNITY_DECLARE_TEX2D(_Heightmap);
sampler2D _DiffuseLightingMap;
UNITY_DECLARE_TEX2D(_DiffuseLightingMap);
sampler2D _EmissiveColorMap;
UNITY_DECLARE_TEX2D(_EmissiveColorMap);
sampler2D _SubSurfaceRadiusMap;
UNITY_DECLARE_TEX2D(_SubSurfaceRadiusMap);
// sampler2D _ThicknessMap;
// UNITY_DECLARE_TEX2D(_ThicknessMap);
// sampler2D _CoatCoverageMap;
// UNITY_DECLARE_TEX2D(_CoatCoverageMap);
// sampler2D _CoatRoughnessMap;
// UNITY_DECLARE_TEX2D(_CoatRoughnessMap);
float _AlphaCutoff;

void GetSurfaceAndBuiltinData(Varyings input, out SurfaceData surfaceData, out BuiltinData builtinData)
{
surfaceData.baseColor = tex2D(_BaseColorMap, input.texCoord0).rgb * _BaseColor.rgb;
surfaceData.baseColor = UNITY_SAMPLE_TEX2D(_BaseColorMap, input.texCoord0).rgb * _BaseColor.rgb;
float alpha = tex2D(_BaseColorMap, input.texCoord0).a * _BaseColor.a;
float alpha = UNITY_SAMPLE_TEX2D(_BaseColorMap, input.texCoord0).a * _BaseColor.a;
#endif
#ifdef _ALPHATEST_ON

#ifdef _SPECULAROCCLUSIONMAP
// TODO: Do something. For now just take alpha channel
surfaceData.specularOcclusion = tex2D(_SpecularOcclusionMap, input.texCoord0).a;
surfaceData.specularOcclusion = UNITY_SAMPLE_TEX2D(_SpecularOcclusionMap, input.texCoord0).a;
#else
// Horizon Occlusion for Normal Mapped Reflections: http://marmosetco.tumblr.com/post/81245981087
//surfaceData.specularOcclusion = saturate(1.0 + horizonFade * dot(r, input.tangentToWorld[2].xyz);

#ifdef _NORMALMAP
#ifdef _NORMALMAP_TANGENT_SPACE
float3 normalTS = UnpackNormalDXT5nm(tex2D(_NormalMap, input.texCoord0));
float3 normalTS = UnpackNormalDXT5nm(UNITY_SAMPLE_TEX2D(_NormalMap, input.texCoord0));
surfaceData.normalWS = tex2D(_NormalMap, input.texCoord0).rgb;
surfaceData.normalWS = UNITY_SAMPLE_TEX2D(_NormalMap, input.texCoord0).rgb;
#endif
#else
surfaceData.normalWS = vertexNormalWS;

#endif
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
surfaceData.perceptualSmoothness = tex2D(_BaseColorMap, input.texCoord0).a;
surfaceData.perceptualSmoothness = UNITY_SAMPLE_TEX2D(_BaseColorMap, input.texCoord0).a;
surfaceData.perceptualSmoothness = tex2D(_MaskMap, input.texCoord0).a;
surfaceData.perceptualSmoothness = UNITY_SAMPLE_TEX2D(_MaskMap, input.texCoord0).a;
#else
surfaceData.perceptualSmoothness = 1.0;
#endif

// MaskMap is Metalic, Ambient Occlusion, (Optional) - emissive Mask, Optional - Smoothness (in alpha)
#ifdef _MASKMAP
surfaceData.metalic = tex2D(_MaskMap, input.texCoord0).r;
surfaceData.ambientOcclusion = tex2D(_MaskMap, input.texCoord0).g;
surfaceData.metalic = UNITY_SAMPLE_TEX2D(_MaskMap, input.texCoord0).r;
surfaceData.ambientOcclusion = UNITY_SAMPLE_TEX2D(_MaskMap, input.texCoord0).g;
#else
surfaceData.metalic = 1.0;
surfaceData.ambientOcclusion = 1.0;

// TODO: Sample lightmap/lightprobe/volume proxy
// This should also handle projective lightmap
// Note that data input above can be use to sample into lightmap (like normal)
builtinData.bakeDiffuseLighting = tex2D(_DiffuseLightingMap, input.texCoord0).rgb;
builtinData.bakeDiffuseLighting = UNITY_SAMPLE_TEX2D(_DiffuseLightingMap, input.texCoord0).rgb;
builtinData.emissiveColor = tex2D(_EmissiveColorMap, input.texCoord0).rgb * _EmissiveColor;
builtinData.emissiveColor = UNITY_SAMPLE_TEX2D(_EmissiveColorMap, input.texCoord0).rgb * _EmissiveColor;
builtinData.emissiveColor = surfaceData.baseColor * tex2D(_MaskMap, input.texCoord0).bbb;
builtinData.emissiveColor = surfaceData.baseColor * UNITY_SAMPLE_TEX2D(_MaskMap, input.texCoord0).bbb;
#else
builtinData.emissiveColor = float3(0.0, 0.0, 0.0);
#endif

6
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Lit.hlsl


float NdotL = saturate(dot(bsdfData.normalWS, L));
float3 F = F_Schlick(bsdfData.fresnel0, LdotH);
float Vis = V_SmithJointGGX(NdotL, NdotV, bsdfData.roughness);
float D = D_GGX(NdotH, bsdfData.roughness);
float D = D_GGXDividePI(NdotH, bsdfData.roughness);
float diffuseTerm = Lambert();
float diffuseTerm = LambertDividePI();
float diffuseTerm = DisneyDiffuse(NdotV, NdotL, LdotH, bsdfData.perceptualRoughness);
float diffuseTerm = DisneyDiffuseDividePI(NdotV, NdotL, LdotH, bsdfData.perceptualRoughness);
#endif
diffuseLighting.rgb = bsdfData.diffuseColor * diffuseTerm;

23
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Material.hlsl


#include "Assets/ScriptableRenderLoop/ShaderLibrary/Packing.hlsl"
#include "Assets/ScriptableRenderLoop/ShaderLibrary/BSDF.hlsl"
#include "Assets/ScriptableRenderLoop/ShaderLibrary/CommonLighting.hlsl"
#include "Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl"
#include "Assets/ScriptableRenderLoop/ShaderLibrary/Debug.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/ShaderConfig.cs"

// Parametrization function helpers
// common Encode/Decode functions
float PerceptualRoughnessToRoughness(float perceptualRoughness)
{
return perceptualRoughness * perceptualRoughness;
}
float RoughnessToPerceptualRoughness(float roughness)
{
return sqrt(roughness);
}
float PerceptualSmoothnessToRoughness(float perceptualSmoothness)
{
return (1 - perceptualSmoothness) * (1 - perceptualSmoothness);
}
float PerceptualSmoothnessToPerceptualRoughness(float perceptualSmoothness)
{
return (1 - perceptualSmoothness);
}
// Encode/Decode velocity in a buffer (either forward of deferred)
// Design note: We assume that VelocityVector fit into a single buffer (i.e not spread on several buffer)

4
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/PostProcess/FinalPass.shader


#include "Assets/ScriptableRenderLoop/ShaderLibrary/Color.hlsl"
#include "../ShaderVariables.hlsl"
sampler2D _MainTex;
UNITY_DECLARE_TEX2D(_MainTex);
float4 _ToneMapCoeffs1;
float4 _ToneMapCoeffs2;

float4 Frag(Varyings input) : SV_Target
{
float4 c = tex2D(_MainTex, input.texcoord);
float4 c = UNITY_SAMPLE_TEX2D(_MainTex, input.texcoord);
// Gamma correction
// TODO: Currenlt in the editor there a an additional pass were the result is copyed in a render target RGBA8_sRGB.

10
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Unlit.shader


#include "ShaderVariables.hlsl"
float4 _Color;
sampler2D _ColorMap;
UNITY_DECLARE_TEX2D(_ColorMap);
sampler2D _EmissiveColorMap;
UNITY_DECLARE_TEX2D(_EmissiveColorMap);
float _EmissiveIntensity;
ENDHLSL

void GetSurfaceAndBuiltinData(Varyings input, out SurfaceData surfaceData, out BuiltinData builtinData)
{
surfaceData.color = tex2D(_ColorMap, input.texCoord0).rgb * _Color.rgb;
float alpha = tex2D(_ColorMap, input.texCoord0).a * _Color.a;
surfaceData.color = UNITY_SAMPLE_TEX2D(_ColorMap, input.texCoord0).rgb * _Color.rgb;
float alpha = UNITY_SAMPLE_TEX2D(_ColorMap, input.texCoord0).a * _Color.a;
#ifdef _ALPHATEST_ON
clip(alpha - _AlphaCutoff);

builtinData.bakeDiffuseLighting = float3(0.0, 0.0, 0.0);
#ifdef _EMISSIVE_COLOR_MAP
builtinData.emissiveColor = tex2D(_EmissiveColorMap, input.texCoord0).rgb * _EmissiveColor;
builtinData.emissiveColor = UNITY_SAMPLE_TEX2D(_EmissiveColorMap, input.texCoord0).rgb * _EmissiveColor;
#else
builtinData.emissiveColor = _EmissiveColor;
#endif

49
Assets/ScriptableRenderLoop/ShaderLibrary/API/D3D11.hlsl


#define CBUFFER_START(name) cbuffer name {
#define CBUFFER_END };
// Macros to declare textures and samplers, possibly separately. For platforms
// that have separate samplers & textures (like DX11), and we'd want to conserve
// the samplers.
// - UNITY_DECLARE_TEX*_NOSAMPLER declares a texture, without a sampler.
// - UNITY_SAMPLE_TEX*_SAMPLER samples a texture, using sampler from another texture.
// That another texture must also be actually used in the current shader, otherwise
// the correct sampler will not be set.
// 2D textures
#define UNITY_DECLARE_TEX2D(tex) Texture2D tex; SamplerState sampler##tex
#define UNITY_DECLARE_TEX2D_NOSAMPLER(tex) Texture2D tex
#define UNITY_SAMPLE_TEX2D(tex,coord) tex.Sample (sampler##tex,coord)
#define UNITY_SAMPLE_TEX2D_SAMPLER(tex,samplertex,coord) tex.Sample (sampler##samplertex,coord)
// Cubemaps
#define UNITY_DECLARE_TEXCUBE(tex) TextureCube tex; SamplerState sampler##tex
#define UNITY_ARGS_TEXCUBE(tex) TextureCube tex, SamplerState sampler##tex
#define UNITY_PASS_TEXCUBE(tex) tex, sampler##tex
#define UNITY_PASS_TEXCUBE_SAMPLER(tex,samplertex) tex, sampler##samplertex
#define UNITY_DECLARE_TEXCUBE_NOSAMPLER(tex) TextureCube tex
#define UNITY_SAMPLE_TEXCUBE(tex,coord) tex.Sample (sampler##tex,coord)
#define UNITY_SAMPLE_TEXCUBE_LOD(tex,coord,lod) tex.SampleLevel (sampler##tex,coord, lod)
#define UNITY_SAMPLE_TEXCUBE_SAMPLER(tex,samplertex,coord) tex.Sample (sampler##samplertex,coord)
// 3D textures
#define UNITY_DECLARE_TEX3D(tex) Texture3D tex; SamplerState sampler##tex
#define UNITY_DECLARE_TEX3D_NOSAMPLER(tex) Texture3D tex
#define UNITY_SAMPLE_TEX3D(tex,coord) tex.Sample (sampler##tex,coord)
#define UNITY_SAMPLE_TEX3D_LOD(tex,coord,lod) tex.SampleLevel (sampler##tex,coord, lod)
#define UNITY_SAMPLE_TEX3D_SAMPLER(tex,samplertex,coord) tex.Sample (sampler##samplertex,coord)
// 2D arrays
#define UNITY_DECLARE_TEX2DARRAY(tex) Texture2DArray tex; SamplerState sampler##tex
#define UNITY_DECLARE_TEX2DARRAY_NOSAMPLER(tex) Texture2DArray tex
#define UNITY_ARGS_TEX2DARRAY(tex) Texture2DArray tex, SamplerState sampler##tex
#define UNITY_PASS_TEX2DARRAY(tex) tex, sampler##tex
#define UNITY_SAMPLE_TEX2DARRAY(tex,coord) tex.Sample (sampler##tex,coord)
#define UNITY_SAMPLE_TEX2DARRAY_LOD(tex,coord,lod) tex.SampleLevel (sampler##tex,coord, lod)
#define UNITY_SAMPLE_TEX2DARRAY_SAMPLER(tex,samplertex,coord) tex.Sample (sampler##samplertex,coord)
// Cube arrays
#define UNITY_DECLARE_TEXCUBEARRAY(tex) TextureCubeArray tex; SamplerState sampler##tex
#define UNITY_DECLARE_TEXCUBEARRAY_NOSAMPLER(tex) TextureCubeArray tex
#define UNITY_ARGS_TEXCUBEARRAY(tex) TextureCubeArray tex, SamplerState sampler##tex
#define UNITY_PASS_TEXCUBEARRAY(tex) tex, sampler##tex
#define UNITY_SAMPLE_TEXCUBEARRAY(tex,coord) tex.Sample (sampler##tex,coord)
#define UNITY_SAMPLE_TEXCUBEARRAY_LOD(tex,coord,lod) tex.SampleLevel (sampler##tex,coord, lod)
#define UNITY_SAMPLE_TEXCUBEARRAY_SAMPLER(tex,samplertex,coord) tex.Sample (sampler##samplertex,coord)

32
Assets/ScriptableRenderLoop/ShaderLibrary/BSDF.hlsl


#include "Common.hlsl"
// Note: All NDF and diffuse term have a version with and without divide by PI.
// Version with divide by PI are use for direct lighting.
// Version without divide by PI are use for image based lighting where often the PI cancel during importance sampling
//-----------------------------------------------------------------------------
// Fresnel term
//-----------------------------------------------------------------------------

float a2 = roughness * roughness;
float f = (NdotH * a2 - NdotH) * NdotH + 1.0;
return INV_PI * a2 / (f * f);
return a2 / (f * f);
float D_GGXDividePI(float NdotH, float roughness)
{
return INV_PI * D_GGX(NdotH, roughness);
}
// Ref: http://jcgt.org/published/0003/02/03/paper.pdf
float V_SmithJointGGX(float NdotL, float NdotV, float roughness)
{

roughnessB = max(roughnessB, UNITY_MIN_ROUGHNESS);
float f = TdotH * TdotH / (roughnessT * roughnessT) + BdotH * BdotH / (roughnessB * roughnessB) + NdotH * NdotH;
return INV_PI / (roughnessT * roughnessB * f * f);
return 1.0 / (roughnessT * roughnessB * f * f);
}
float D_GGXAnisoDividePI(float TdotH, float BdotH, float NdotH, float roughnessT, float roughnessB)
{
return INV_PI * D_GGXAniso(TdotH, BdotH, NdotH, roughnessT, roughnessB);
}
// Ref: https://cedec.cesa.or.jp/2015/session/ENG/14698.html The Rendering Materials of Far Cry 4

//-----------------------------------------------------------------------------
float Lambert()
{
return 1.0;
}
float LambertDividePI()
{
return INV_PI;
}

float lightScatter = F_Schlick(1.0, fd90, NdotL);
float viewScatter = F_Schlick(1.0, fd90, NdotV);
return INV_PI * lightScatter * viewScatter;
return lightScatter * viewScatter;
float DisneyDiffuseDividePI(float NdotV, float NdotL, float LdotH, float perceptualRoughness)
{
return INV_PI * DisneyDiffuse(NdotV, NdotL, LdotH, perceptualRoughness);
}
#endif // UNITY_BSDF_INCLUDED

5
Assets/ScriptableRenderLoop/ShaderLibrary/Common.hlsl


#define UNITY_COMMON_INCLUDED
// Convention:
// Unity is Y up - left handed
// space at the end of the variable name
// WS: world space
// VS: view space

// constant floating number written as 1.0 (not 1, not 1.0f, not 1.0h)
// uniform have g_ as prefix (still lowercaseThenCamelCase)
// uniform have _ as prefix (still lowercaseThenCamelCase) // TODO: define upper or lower case as a start
// Structure definition that are share between C# and hlsl.
// These structures need to be align on float4 to respectect various packing rules from sahder language.

24
Assets/ScriptableRenderLoop/ShaderLibrary/CommonLighting.hlsl


return normalize(lerp(normalWS, anisoNormalWS, anisotropy));
}
//-----------------------------------------------------------------------------
// Helper function for perceptual roughness
//-----------------------------------------------------------------------------
float PerceptualRoughnessToRoughness(float perceptualRoughness)
{
return perceptualRoughness * perceptualRoughness;
}
float RoughnessToPerceptualRoughness(float roughness)
{
return sqrt(roughness);
}
float PerceptualSmoothnessToRoughness(float perceptualSmoothness)
{
return (1 - perceptualSmoothness) * (1 - perceptualSmoothness);
}
float PerceptualSmoothnessToPerceptualRoughness(float perceptualSmoothness)
{
return (1 - perceptualSmoothness);
}
#endif // UNITY_COMMON_LIGHTING_INCLUDED

4
Assets/ScriptableRenderLoop/common/TextureSettings.cs


using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

TextureSettings settings;
settings.spotCookieSize = 128;
settings.pointCookieSize = 512;
settings.reflectionCubemapSize = 64;
settings.reflectionCubemapSize = 128;
return settings;
}
}

460
Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl


#ifndef UNITY_IMAGE_BASED_LIGHTING_INCLUDED
#define UNITY_IMAGE_BASED_LIGHTING_INCLUDED
#include "CommonLighting.hlsl"
#include "BSDF.hlsl"
//-----------------------------------------------------------------------------
// Sample generator
//-----------------------------------------------------------------------------
// Ref: http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
uint ReverseBits32(uint bits)
{
#if 0 // Shader model 5
return reversebits(bits);
#else
bits = ( bits << 16) | ( bits >> 16);
bits = ((bits & 0x00ff00ff) << 8) | ((bits & 0xff00ff00) >> 8);
bits = ((bits & 0x0f0f0f0f) << 4) | ((bits & 0xf0f0f0f0) >> 4);
bits = ((bits & 0x33333333) << 2) | ((bits & 0xcccccccc) >> 2);
bits = ((bits & 0x55555555) << 1) | ((bits & 0xaaaaaaaa) >> 1);
return bits;
#endif
}
float RadicalInverse_VdC(uint bits)
{
return float(ReverseBits32(bits)) * 2.3283064365386963e-10; // 0x100000000
}
float2 Hammersley2d(uint i, uint maxSampleCount)
{
return float2(float(i) / float(maxSampleCount), RadicalInverse_VdC(i));
}
float Hash(uint s)
{
s = s ^ 2747636419u;
s = s * 2654435769u;
s = s ^ (s >> 16);
s = s * 2654435769u;
s = s ^ (s >> 16);
s = s * 2654435769u;
return float(s) / 4294967295.0;
}
float2 InitRandom(float2 input)
{
float2 r;
r.x = Hash(uint(input.x * 4294967295.0));
r.y = Hash(uint(input.y * 4294967295.0));
return r;
}
//-----------------------------------------------------------------------------
// Util
//-----------------------------------------------------------------------------
// generate an orthonormalBasis from 3d unit vector.
void GetLocalFrame(float3 N, out float3 tangentX, out float3 tangentY)
{
float3 upVector = abs(N.z) < 0.999 ? float3(0.0, 0.0, 1.0) : float3(1.0, 0.0, 0.0);
tangentX = normalize(cross(upVector, N));
tangentY = cross(N, tangentX);
}
// TODO: test
/*
// http://orbit.dtu.dk/files/57573287/onb_frisvad_jgt2012.pdf
void GetLocalFrame(float3 N, out float3 tangentX, out float3 tangentY)
{
if (N.z < -0.999) // Handle the singularity
{
tangentX = float3(0.0, -1.0, 0.0);
tangentY = float3(-1.0, 0.0, 0.0);
return ;
}
float a = 1.0 / (1.0 + N.z);
float b = -N.x * N.y * a;
tangentX = float3(1.0f - N.x * N.x * a , b, -N.x);
tangentY = float3(b, 1.0f - N.y * N.y * a, -N.y);
}
*/
// ----------------------------------------------------------------------------
// Sampling
// ----------------------------------------------------------------------------
void ImportanceSampleCosDir(float2 u,
float3 N,
float3 tangentX,
float3 tangentY,
out float3 L)
{
// Cosine sampling - ref: http://www.rorydriscoll.com/2009/01/07/better-sampling/
float cosTheta = sqrt(max(0.0, 1.0 - u.x));
float sinTheta = sqrt(u.x);
float phi = TWO_PI * u.y;
// Transform from spherical into cartesian
L = float3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta);
// Local to world
L = tangentX * L.x + tangentY * L.y + N * L.z;
}
void ImportanceSampleGGXDir(float2 u,
float3 V,
float3 N,
float3 tangentX,
float3 tangentY,
float roughness,
out float3 H,
out float3 L)
{
// GGX NDF sampling
float cosThetaH = sqrt((1.0 - u.x) / (1.0 + (roughness * roughness - 1.0) * u.x));
float sinThetaH = sqrt(max(0.0, 1.0 - cosThetaH * cosThetaH));
float phiH = TWO_PI * u.y;
// Transform from spherical into cartesian
H = float3(sinThetaH * cos(phiH), sinThetaH * sin(phiH), cosThetaH);
// Local to world
H = tangentX * H.x + tangentY * H.y + N * H.z;
// Convert sample from half angle to incident angle
L = 2.0 * dot(V, H) * H - V;
}
// weightOverPdf return the weight (without the diffuseAlbedo term) over pdf. diffuseAlbedo term must be apply by the caller.
void ImportanceSampleLambert(
float2 u,
float3 N,
float3 tangentX,
float3 tangentY,
out float3 L,
out float NdotL,
out float weightOverPdf)
{
ImportanceSampleCosDir(u, N, tangentX, tangentY, L);
NdotL = saturate(dot(N, L));
// Importance sampling weight for each sample
// pdf = N.L / PI
// weight = fr * (N.L) with fr = diffuseAlbedo / PI
// weight over pdf is:
// weightOverPdf = (diffuseAlbedo / PI) * (N.L) / (N.L / PI)
// weightOverPdf = diffuseAlbedo
// diffuseAlbedo is apply outside the function
weightOverPdf = 1.0;
}
// weightOverPdf return the weight (without the Fresnel term) over pdf. Fresnel term must be apply by the caller.
void ImportanceSampleGGX(
float2 u,
float3 V,
float3 N,
float3 tangentX,
float3 tangentY,
float roughness,
float NdotV,
out float3 L,
out float VdotH,
out float NdotL,
out float weightOverPdf)
{
float3 H;
ImportanceSampleGGXDir(u, V, N, tangentX, tangentY, roughness, H, L);
float NdotH = saturate(dot(N, H));
// Note: since L and V are symmetric around H, LdotH == VdotH
VdotH = saturate(dot(V, H));
NdotL = saturate(dot(N, L));
// Importance sampling weight for each sample
// pdf = D(H) * (N.H) / (4 * (L.H))
// weight = fr * (N.L) with fr = F(H) * G(V, L) * D(H) / (4 * (N.L) * (N.V))
// weight over pdf is:
// weightOverPdf = F(H) * G(V, L) * (L.H) / ((N.H) * (N.V))
// weightOverPdf = F(H) * 4 * (N.L) * V(V, L) * (L.H) / (N.H) with V(V, L) = G(V, L) / (4 * (N.L) * (N.V))
// Remind (L.H) == (V.H)
// F is apply outside the function
float Vis = V_SmithJointGGX(NdotL, NdotV, roughness);
weightOverPdf = 4.0 * Vis * NdotL * VdotH / NdotH;
}
//-----------------------------------------------------------------------------
// Reference
// ----------------------------------------------------------------------------
// Ref: Moving Frostbite to PBR (Appendix A)
void IntegrateLambertDiffuseIBLRef( out float3 diffuseLighting,
UNITY_ARGS_TEXCUBE(tex),
float3 N,
float3 diffuseAlbedo,
uint sampleCount = 2048)
{
float3 acc = float3(0.0, 0.0, 0.0);
// Add some jittering on Hammersley2d
float2 randNum = InitRandom(N.xy * 0.5 + 0.5);
float3 tangentX, tangentY;
GetLocalFrame(N, tangentX, tangentY);
for (uint i = 0; i < sampleCount; ++i)
{
float2 u = Hammersley2d(i, sampleCount);
u = frac(u + randNum + 0.5);
float3 L;
float NdotL;
float weightOverPdf;
ImportanceSampleLambert(u, N, tangentX, tangentY, L, NdotL, weightOverPdf);
if (NdotL > 0.0)
{
float3 val = UNITY_SAMPLE_TEXCUBE_LOD(tex, L, 0).rgb;
// diffuse Albedo is apply here as describe in ImportanceSampleLambert function
acc += diffuseAlbedo * Lambert() * weightOverPdf * val;
}
}
diffuseLighting = acc / sampleCount;
}
// ----------------------------------------------------------------------------
void IntegrateDisneyDiffuseIBLRef( out float3 diffuseLighting,
UNITY_ARGS_TEXCUBE(tex),
float3 N,
float3 V,
float roughness,
float3 diffuseAlbedo,
uint sampleCount = 2048)
{
float NdotV = dot(N, V);
float3 acc = float3(0.0, 0.0, 0.0);
// Add some jittering on Hammersley2d
float2 randNum = InitRandom(N.xy * 0.5 + 0.5);
float3 tangentX, tangentY;
GetLocalFrame(N, tangentX, tangentY);
for (uint i = 0; i < sampleCount; ++i)
{
float2 u = Hammersley2d(i, sampleCount);
u = frac(u + randNum + 0.5);
float3 L;
float NdotL;
float weightOverPdf;
// for Disney we still use a Cosine importance sampling, true Disney importance sampling imply a look up table
ImportanceSampleLambert(u, N, tangentX, tangentY, L, NdotL, weightOverPdf);
if (NdotL > 0.0)
{
float3 val = UNITY_SAMPLE_TEXCUBE_LOD(tex, L, 0).rgb;
float3 H = normalize(L + V);
float LdotH = dot(L, H);
// Note: we call DisneyDiffuse that require to multiply by Albedo / PI. Divide by PI is already taken into account
// in weightOverPdf of ImportanceSampleLambert call.
float disneyDiffuse = DisneyDiffuse(NdotV, NdotL, LdotH, RoughnessToPerceptualRoughness(roughness));
// diffuse Albedo is apply here as describe in ImportanceSampleLambert function
acc += diffuseAlbedo * disneyDiffuse * weightOverPdf * val;
}
}
diffuseLighting = acc / sampleCount;
}
// ----------------------------------------------------------------------------
// Ref: Moving Frostbite to PBR (Appendix A)
void IntegrateSpecularGGXIBLRef(out float3 specularLighting,
UNITY_ARGS_TEXCUBE(tex),
float3 N,
float3 V,
float roughness,
float3 f0,
float f90,
uint sampleCount = 2048)
{
float NdotV = saturate(dot(N, V));
float3 acc = float3(0.0, 0.0, 0.0);
// Add some jittering on Hammersley2d
float2 randNum = InitRandom(V.xy * 0.5 + 0.5);
float3 tangentX, tangentY;
GetLocalFrame(N, tangentX, tangentY);
for (uint i = 0; i < sampleCount; ++i)
{
float2 u = Hammersley2d(i, sampleCount);
u = frac(u + randNum + 0.5);
float VdotH;
float NdotL;
float3 L;
float weightOverPdf;
// GGX BRDF
ImportanceSampleGGX(u, V, N, tangentX, tangentY, roughness, NdotV,
L, VdotH, NdotL, weightOverPdf);
if (NdotL > 0.0)
{
// Fresnel component is apply here as describe in ImportanceSampleGGX function
float3 FweightOverPdf = F_Schlick(f0, f90, VdotH) * weightOverPdf;
float3 val = UNITY_SAMPLE_TEXCUBE_LOD(tex, L, 0).rgb;
acc += FweightOverPdf * val;
}
}
specularLighting = acc / sampleCount;
}
// ----------------------------------------------------------------------------
// Pre-integration
// ----------------------------------------------------------------------------
// Ref: Listing 18 in "Moving Frostbite to PBR" + https://knarkowicz.wordpress.com/2014/12/27/analytical-dfg-term-for-ibl/
float4 IntegrateDFG(float3 V, float3 N, float roughness, uint sampleCount)
{
float NdotV = saturate(dot(N, V));
float4 acc = float4(0.0, 0.0, 0.0, 0.0);
// Add some jittering on Hammersley2d
float2 randNum = InitRandom(V.xy * 0.5 + 0.5);
float3 tangentX, tangentY;
GetLocalFrame(N, tangentX, tangentY);
for (uint i = 0; i < sampleCount; ++i)
{
float2 u = Hammersley2d(i, sampleCount);
u = frac(u + randNum + 0.5);
float VdotH;
float NdotL;
float weightOverPdf;
float3 L; // Unused
ImportanceSampleGGX(u, V, N, tangentX, tangentY, roughness, NdotV,
L, VdotH, NdotL, weightOverPdf);
if (NdotL > 0.0)
{
// Integral is
// 1 / NumSample * \int[ L * fr * (N.L) / pdf ] with pdf = D(H) * (N.H) / (4 * (L.H)) and fr = F(H) * G(V, L) * D(H) / (4 * (N.L) * (N.V))
// This is split in two part:
// A) \int[ L * (N.L) ]
// B) \int[ F(H) * 4 * (N.L) * V(V, L) * (L.H) / (N.H) ] with V(V, L) = G(V, L) / (4 * (N.L) * (N.V))
// = \int[ F(H) * weightOverPdf ]
// Recombine at runtime with: ( f0 * weightOverPdf * (1 - Fc) + f90 * weightOverPdf * Fc ) with Fc =(1 - V.H)^5
float Fc = pow(1.0 - VdotH, 5.0);
acc.x += (1.0 - Fc) * weightOverPdf;
acc.y += Fc * weightOverPdf;
}
// for Disney we still use a Cosine importance sampling, true Disney importance sampling imply a look up table
ImportanceSampleLambert(u, N, tangentX, tangentY, L, NdotL, weightOverPdf);
if (NdotL > 0.0)
{
float3 H = normalize(L + V);
float LdotH = dot(L, H);
float disneyDiffuse = DisneyDiffuse(NdotV, NdotL, LdotH, RoughnessToPerceptualRoughness(roughness));
acc.z += disneyDiffuse * weightOverPdf;
}
}
return acc / sampleCount;
}
// Ref: Listing 19 in "Moving Frostbite to PBR"
float4 IntegrateLD( UNITY_ARGS_TEXCUBE(tex),
float3 V,
float3 N,
float roughness,
float mipmapcount,
float invOmegaP,
uint sampleCount,
bool prefilter = true) // static bool
{
float3 acc = float3(0.0, 0.0, 0.0);
float accWeight = 0;
float2 randNum = InitRandom(V.xy * 0.5 + 0.5);
float3 tangentX, tangentY;
GetLocalFrame(N, tangentX, tangentY);
for (uint i = 0; i < sampleCount; ++i)
{
float2 u = Hammersley2d(i, sampleCount);
u = frac(u + randNum + 0.5);
float3 H;
float3 L;
ImportanceSampleGGXDir(u, V, N, tangentX, tangentY, roughness, H, L);
float NdotL = saturate(dot(N,L));
float mipLevel;
if (!prefilter) // BRDF importance sampling
{
mipLevel = 0.0;
}
else // Prefiltered BRDF importance sampling
{
float NdotH = saturate(dot(N, H));
// Note: since L and V are symmetric around H, LdotH == VdotH
float LdotH = saturate(dot(L, H));
// Use pre - filtered importance sampling (i.e use lower mipmap
// level for fetching sample with low probability in order
// to reduce the variance ).
// ( Reference : GPU Gem3: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch20.html)
//
// Since we pre - integrate the result for normal direction ,
// N == V and then NdotH == LdotH . This is why the BRDF pdf
// can be simplifed from :
// pdf = D * NdotH /(4* LdotH ) to pdf = D / 4;
//
// - OmegaS : Solid angle associated to a sample
// - OmegaP : Solid angle associated to a pixel of the cubemap
float pdf = D_GGXDividePI(NdotH, roughness) * NdotH / (4.0 * LdotH);
float omegaS = 1.0 / (sampleCount * pdf); // Solid angle associated to a sample
// invOmegaP is precomputed on CPU and provide as a parameter of the function
// float omegaP = FOUR_PI / (6.0f * cubemapWidth * cubemapWidth); // Solid angle associated to a pixel of the cubemap
// Clamp is not necessary as the hardware will do it.
// mipLevel = clamp(0.5f * log2(omegaS * invOmegaP), 0, mipmapcount);
mipLevel = 0.5 * log2(omegaS * invOmegaP); // Clamp is not necessary as the hardware will do it.
}
if (NdotL > 0.0f)
{
float3 val = UNITY_SAMPLE_TEXCUBE_LOD(tex, L, mipLevel).rgb;
// See p63 equation (53) of moving Frostbite to PBR v2 for the extra NdotL here (both in weight and value)
acc += val * NdotL;
accWeight += NdotL;
}
}
return float4(acc * (1.0 / accWeight), 1.0);
}
#endif // UNITY_IMAGE_BASED_LIGHTING_INCLUDED

9
Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl.meta


fileFormatVersion: 2
guid: ae4dc0bfd9fc0b544a109513ba841d30
timeCreated: 1476117021
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

9
Assets/ScriptableRenderLoop/fptl/LightingTemplate.hlsl.meta


fileFormatVersion: 2
guid: 055113b0dcb47d0468619612ccb7de75
timeCreated: 1476168722
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

9
Assets/ScriptableRenderLoop/fptl/ReflectionTemplate.hlsl.meta


fileFormatVersion: 2
guid: 7e1ced85dc3e259469da295c01d95ecd
timeCreated: 1476168722
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

9
Assets/ScriptableRenderLoop/fptl/StandardTest.shader.meta


fileFormatVersion: 2
guid: 8f28d6dbfdba66d4dbae80224aca5669
timeCreated: 1476168726
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

9
Assets/ScriptableRenderLoop/fptl/TiledLightingTemplate.hlsl.meta


fileFormatVersion: 2
guid: b25f3fae508f5c04f8f15d77515e4a23
timeCreated: 1476168722
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

9
Assets/ScriptableRenderLoop/fptl/TiledLightingUtils.hlsl.meta


fileFormatVersion: 2
guid: 25c458a8106d44444bea6b074b79cfdf
timeCreated: 1476168722
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

9
Assets/ScriptableRenderLoop/fptl/TiledReflectionTemplate.hlsl.meta


fileFormatVersion: 2
guid: a9b744e06937f8d4ca633dfa63e357b4
timeCreated: 1476168722
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

9
Assets/ScriptableRenderLoop/fptl/UnityStandardForwardNew.cginc.meta


fileFormatVersion: 2
guid: c185aa276c9670d4381a830ece205577
timeCreated: 1476168722
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存