浏览代码

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.cs

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

#	Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/LightingForward.hlsl
#	Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Lit.hlsl
#	Assets/ScriptableRenderLoop/ShaderLibrary/Common.hlsl
/main
sebastienlagarde 8 年前
当前提交
feca166f
共有 70 个文件被更改,包括 6058 次插入6037 次删除
  1. 29
      Assets/Editor/Tests/RenderloopTests/CullResultsTest.cs
  2. 47
      Assets/Editor/Tests/RenderloopTests/RenderloopTestFixture.cs
  3. 239
      Assets/Editor/Tests/ShaderGeneratorTests/ShaderGeneratorTests.cs
  4. 52
      Assets/ScriptableRenderLoop/AdditionalLightData.cs
  5. 388
      Assets/ScriptableRenderLoop/ForwardRenderLoop/ForwardRenderLoop.cs
  6. 878
      Assets/ScriptableRenderLoop/ForwardRenderLoop/Shaders/vr_lighting.cginc
  7. 1001
      Assets/ScriptableRenderLoop/ForwardRenderLoop/Shaders/vr_standard.shader
  8. 332
      Assets/ScriptableRenderLoop/ForwardRenderLoop/Shaders/vr_utils.cginc
  9. 995
      Assets/ScriptableRenderLoop/ForwardRenderLoop/ValveMenuTools.cs
  10. 987
      Assets/ScriptableRenderLoop/ForwardRenderLoop/ValveShaderGUI.cs
  11. 37
      Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.cs
  12. 16
      Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoopInspector.cs
  13. 2
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Debug/DebugViewMaterial.hlsl
  14. 4
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Debug/DebugViewMaterialGBuffer.shader
  15. 16
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/LayeredLit.shader
  16. 14
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/LayeredLitTemplate.hlsl
  17. 598
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/LayeredLitUI.cs
  18. 66
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/LightDefinition.cs.hlsl
  19. 2
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/Lighting.hlsl
  20. 4
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/LightingDeferred.shader
  21. 2
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/LightingForward.hlsl
  22. 34
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lit.shader
  23. 10
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/LitTemplate.hlsl
  24. 723
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/LitUI.cs
  25. 4
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/BuiltinData.cs
  26. 16
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/BuiltinData.cs.hlsl
  27. 66
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Lit.cs.hlsl
  28. 138
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Lit.hlsl
  29. 72
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Material.hlsl
  30. 30
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/PostProcess/FinalPass.shader
  31. 1
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/ShaderConfig.cs
  32. 16
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/ShaderVariables.hlsl
  33. 16
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Unlit.shader
  34. 689
      Assets/ScriptableRenderLoop/RenderPasses/ShadowRenderPass.cs
  35. 20
      Assets/ScriptableRenderLoop/ScriptableRenderLoop.cs
  36. 98
      Assets/ScriptableRenderLoop/ScriptableRenderLoopPicker.cs
  37. 8
      Assets/ScriptableRenderLoop/ShaderLibrary/API/D3D11.hlsl
  38. 18
      Assets/ScriptableRenderLoop/ShaderLibrary/BSDF.hlsl
  39. 16
      Assets/ScriptableRenderLoop/ShaderLibrary/Color.hlsl
  40. 46
      Assets/ScriptableRenderLoop/ShaderLibrary/Common.hlsl
  41. 6
      Assets/ScriptableRenderLoop/ShaderLibrary/CommonLighting.hlsl
  42. 2
      Assets/ScriptableRenderLoop/ShaderLibrary/Debug.hlsl
  43. 2
      Assets/ScriptableRenderLoop/ShaderLibrary/Filtering.hlsl
  44. 600
      Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl
  45. 8
      Assets/ScriptableRenderLoop/ShaderLibrary/Packing.hlsl
  46. 4
      Assets/ScriptableRenderLoop/ShaderLibrary/QuaternionMath.hlsl
  47. 16
      Assets/ScriptableRenderLoop/common/ShaderBase.h
  48. 445
      Assets/ScriptableRenderLoop/common/SkyboxHelper.cs
  49. 513
      Assets/ScriptableRenderLoop/common/TextureCache.cs
  50. 28
      Assets/ScriptableRenderLoop/common/TextureSettings.cs
  51. 71
      Assets/ScriptableRenderLoop/fptl/ClusteredUtils.h
  52. 74
      Assets/ScriptableRenderLoop/fptl/FinalPass.shader
  53. 992
      Assets/ScriptableRenderLoop/fptl/FptlLighting.cs
  54. 108
      Assets/ScriptableRenderLoop/fptl/Internal-DeferredReflections.shader
  55. 106
      Assets/ScriptableRenderLoop/fptl/Internal-DeferredShading.shader
  56. 44
      Assets/ScriptableRenderLoop/fptl/LightDefinitions.cs
  57. 138
      Assets/ScriptableRenderLoop/fptl/LightDefinitions.cs.hlsl
  58. 347
      Assets/ScriptableRenderLoop/fptl/LightingTemplate.hlsl
  59. 170
      Assets/ScriptableRenderLoop/fptl/ReflectionTemplate.hlsl
  60. 190
      Assets/ScriptableRenderLoop/fptl/StandardTest.shader
  61. 14
      Assets/ScriptableRenderLoop/fptl/TiledLightingTemplate.hlsl
  62. 136
      Assets/ScriptableRenderLoop/fptl/TiledLightingUtils.hlsl
  63. 14
      Assets/ScriptableRenderLoop/fptl/TiledReflectionTemplate.hlsl
  64. 130
      Assets/ScriptableRenderLoop/fptl/UnityStandardForwardNew.cginc
  65. 2
      Assets/ScriptableRenderLoop/fptl/lightlistbuild-clustered.compute
  66. 97
      Assets/ScriptableRenderLoop/fptl/lightlistbuild.compute
  67. 17
      Assets/ShaderGenerator/CSharpToHLSL.cs
  68. 2
      Assets/ShaderGenerator/ShaderGeneratorMenu.cs
  69. 1
      Assets/ShaderGenerator/ShaderTypeGeneration.cs
  70. 88
      Assets/ScriptableRenderLoop/fptl/LightingUtils.hlsl

29
Assets/Editor/Tests/RenderloopTests/CullResultsTest.cs


[TestFixture]
public class CullResultsTest
{
void InspectCullResults(Camera camera, CullResults cullResults, RenderLoop renderLoop)
{
VisibleReflectionProbe[] probes = cullResults.visibleReflectionProbes;
void InspectCullResults(Camera camera, CullResults cullResults, RenderLoop renderLoop)
{
VisibleReflectionProbe[] probes = cullResults.visibleReflectionProbes;
Assert.AreEqual(1, probes.Length, "Incorrect reflection probe count");
Assert.AreEqual(1, probes.Length, "Incorrect reflection probe count");
VisibleReflectionProbe probeA = probes[0];
Assert.NotNull(probeA.texture, "probe texture");
VisibleReflectionProbe probeA = probes[0];
Assert.NotNull(probeA.texture, "probe texture");
VisibleLight[] lights = cullResults.visibleLights;
Assert.AreEqual(3, lights.Length, "Incorrect light count");

{
Assert.AreEqual(expectedTypes[i], lights[i].lightType,
Assert.AreEqual(expectedTypes[i], lights[i].lightType,
// @TODO..
}
// @TODO..
}
[Test]
public void TestReflectionProbes()
{
UnityEditor.SceneManagement.EditorSceneManager.OpenScene("Assets/Editor/Tests/TestScene.unity");
[Test]
public void TestReflectionProbes()
{
UnityEditor.SceneManagement.EditorSceneManager.OpenScene("Assets/Editor/Tests/TestScene.unity");
// Asserts.ExpectLogError("Boing");
// Asserts.ExpectLogError("Boing");
RenderLoopTestFixture.Run(InspectCullResults);
}

47
Assets/Editor/Tests/RenderloopTests/RenderloopTestFixture.cs


using System.Collections;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

[ExecuteInEditMode]
public class RenderLoopTestFixture : MonoBehaviour
{
public delegate void TestDelegate(Camera camera, CullResults cullResults, RenderLoop renderLoop);
private static TestDelegate callback;
public static void Render(RenderLoopWrapper wrapper, Camera[] cameras, RenderLoop renderLoop)
{
public delegate void TestDelegate(Camera camera, CullResults cullResults, RenderLoop renderLoop);
private static TestDelegate callback;
public static void Render(RenderLoopWrapper wrapper, Camera[] cameras, RenderLoop renderLoop)
{
{
CullingParameters cullingParams;
bool gotCullingParams = CullResults.GetCullingParameters(camera, out cullingParams);
Assert.IsTrue(gotCullingParams);
{
CullingParameters cullingParams;
bool gotCullingParams = CullResults.GetCullingParameters(camera, out cullingParams);
Assert.IsTrue(gotCullingParams);
CullResults cullResults = CullResults.Cull(ref cullingParams, renderLoop);
CullResults cullResults = CullResults.Cull(ref cullingParams, renderLoop);
}
renderLoop.Submit();
}
public static void Run(TestDelegate renderCallback)
{
}
renderLoop.Submit();
}
public static void Run(TestDelegate renderCallback)
{
var instance = camObject.AddComponent<RenderLoopWrapper>();
instance.callback = Render;
callback = renderCallback;
instance.enabled = true;
var instance = camObject.AddComponent<RenderLoopWrapper>();
instance.callback = Render;
callback = renderCallback;
instance.enabled = true;
Transform t = camObject.transform;

float camDist = size / Mathf.Tan(fov * 0.5f * Mathf.Deg2Rad);
SceneView.lastActiveSceneView.LookAtDirect(t.position + t.forward * camDist, t.rotation, size);
// Invoke renderer
try
{

}
}
}

239
Assets/Editor/Tests/ShaderGeneratorTests/ShaderGeneratorTests.cs


using System;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Reflection;

[TestFixture]
public class ShaderGeneratorTests
{
struct FailureTypes
{
// Non-primitive type in nested struct
internal struct NestedWithNonPrimitiveType
{
public struct Data
{
public string s;
}
public Data contents;
}
struct FailureTypes
{
// Non-primitive type in nested struct
internal struct NestedWithNonPrimitiveType
{
public struct Data
{
public string s;
}
public Data contents;
}
// Unsupported primitive type in nested struct
internal struct UnsupportedPrimitiveType
{
public struct Data
{
public IntPtr intPtr;
}
public Data contents;
}
// Unsupported primitive type in nested struct
internal struct UnsupportedPrimitiveType
{
public struct Data
{
public IntPtr intPtr;
}
public Data contents;
}
// Mixed types in nested struct
internal struct MixedTypesInNestedStruct
{
public struct Data
{
public float f;
public int i;
}
public Data contents;
}
// Mixed types in nested struct
internal struct MixedTypesInNestedStruct
{
public struct Data
{
public float f;
public int i;
}
public Data contents;
}
// More than 4 primitive fields in nested struct
internal struct TooManyFields
{
public struct Data
{
public float f1, f2, f3, f4, f5;
}
public Data contents;
}
// More than 4 primitive fields in nested struct
internal struct TooManyFields
{
public struct Data
{
public float f1, f2, f3, f4, f5;
}
public Data contents;
}
// Merge failure due to incompatible types
internal struct MergeIncompatibleTypes
{
public float f;
public Vector2 v;
public int i;
}
// Merge failure due to incompatible types
internal struct MergeIncompatibleTypes
{
public float f;
public Vector2 v;
public int i;
}
// Merge failure due to register boundary crossing
internal struct MergeCrossBoundary
{
public Vector2 u;
public Vector3 v;
}
}
// Merge failure due to register boundary crossing
internal struct MergeCrossBoundary
{
public Vector2 u;
public Vector3 v;
}
}
// @TODO: should probably switch to exceptions...
static bool HasErrorString(List<string> errors, string errorSubstring)
{
if (errors == null)
return false;
// @TODO: should probably switch to exceptions...
static bool HasErrorString(List<string> errors, string errorSubstring)
{
if (errors == null)
return false;
bool foundError = false;
foreach (var error in errors)
{
if (error.IndexOf(errorSubstring) >= 0)
{
foundError = true;
break;
}
}
bool foundError = false;
foreach (var error in errors)
{
if (error.IndexOf(errorSubstring) >= 0)
{
foundError = true;
break;
}
}
return foundError;
}
return foundError;
}
[Test(Description = "Disallow non-primitive types in nested structs")]
[Test(Description = "Disallow non-primitive types in nested structs")]
{
string source;
List<string> errors;
{
string source;
List<string> errors;
bool success = CSharpToHLSL.GenerateHLSL(typeof(FailureTypes.NestedWithNonPrimitiveType), new GenerateHLSL(PackingRules.Exact), out source, out errors);
Assert.IsFalse(success);
Assert.IsTrue(HasErrorString(errors, "contains a non-primitive field type"));
}
bool success = CSharpToHLSL.GenerateHLSL(typeof(FailureTypes.NestedWithNonPrimitiveType), new GenerateHLSL(PackingRules.Exact), out source, out errors);
Assert.IsFalse(success);
Assert.IsTrue(HasErrorString(errors, "contains a non-primitive field type"));
}
[Test(Description = "Check for unsupported types in primitive structs")]
[Test(Description = "Check for unsupported types in primitive structs")]
{
string source;
List<string> errors;
{
string source;
List<string> errors;
bool success = CSharpToHLSL.GenerateHLSL(typeof(FailureTypes.UnsupportedPrimitiveType), new GenerateHLSL(PackingRules.Exact), out source, out errors);
Assert.IsFalse(success);
Assert.IsTrue(HasErrorString(errors, "contains an unsupported field type"));
}
bool success = CSharpToHLSL.GenerateHLSL(typeof(FailureTypes.UnsupportedPrimitiveType), new GenerateHLSL(PackingRules.Exact), out source, out errors);
Assert.IsFalse(success);
Assert.IsTrue(HasErrorString(errors, "contains an unsupported field type"));
}
[Test(Description = "Disallow mixed types in nested structs")]
public void Fail_MixedTypesInNestedStruct()
{
string source;
List<string> errors;
[Test(Description = "Disallow mixed types in nested structs")]
public void Fail_MixedTypesInNestedStruct()
{
string source;
List<string> errors;
bool success = CSharpToHLSL.GenerateHLSL(typeof(FailureTypes.MixedTypesInNestedStruct), new GenerateHLSL(PackingRules.Exact), out source, out errors);
Assert.IsFalse(success);
Assert.IsTrue(HasErrorString(errors, "contains mixed basic types"));
}
bool success = CSharpToHLSL.GenerateHLSL(typeof(FailureTypes.MixedTypesInNestedStruct), new GenerateHLSL(PackingRules.Exact), out source, out errors);
Assert.IsFalse(success);
Assert.IsTrue(HasErrorString(errors, "contains mixed basic types"));
}
[Test(Description = "Disallow more than 16 bytes worth of fields in nested structs")]
[Test(Description = "Disallow more than 16 bytes worth of fields in nested structs")]
{
string source;
List<string> errors;
{
string source;
List<string> errors;
bool success = CSharpToHLSL.GenerateHLSL(typeof(FailureTypes.TooManyFields), new GenerateHLSL(PackingRules.Exact), out source, out errors);
Assert.IsFalse(success);
Assert.IsTrue(HasErrorString(errors, "more than 4 fields"));
}
bool success = CSharpToHLSL.GenerateHLSL(typeof(FailureTypes.TooManyFields), new GenerateHLSL(PackingRules.Exact), out source, out errors);
Assert.IsFalse(success);
Assert.IsTrue(HasErrorString(errors, "more than 4 fields"));
}
[Test(Description = "Disallow merging incompatible types when doing aggressive packing")]
[Test(Description = "Disallow merging incompatible types when doing aggressive packing")]
{
string source;
List<string> errors;
{
string source;
List<string> errors;
bool success = CSharpToHLSL.GenerateHLSL(typeof(FailureTypes.MergeIncompatibleTypes), new GenerateHLSL(PackingRules.Aggressive), out source, out errors);
Assert.IsFalse(success);
Assert.IsTrue(HasErrorString(errors, "incompatible types"));
}
bool success = CSharpToHLSL.GenerateHLSL(typeof(FailureTypes.MergeIncompatibleTypes), new GenerateHLSL(PackingRules.Aggressive), out source, out errors);
Assert.IsFalse(success);
Assert.IsTrue(HasErrorString(errors, "incompatible types"));
}
[Test(Description = "Disallow placing fields across register boundaries when merging")]
[Test(Description = "Disallow placing fields across register boundaries when merging")]
{
string source;
List<string> errors;
bool success = CSharpToHLSL.GenerateHLSL(typeof(FailureTypes.MergeCrossBoundary), new GenerateHLSL(PackingRules.Aggressive), out source, out errors);
Assert.IsFalse(success);
Assert.IsTrue(HasErrorString(errors, "cross register boundary"));
}
{
string source;
List<string> errors;
bool success = CSharpToHLSL.GenerateHLSL(typeof(FailureTypes.MergeCrossBoundary), new GenerateHLSL(PackingRules.Aggressive), out source, out errors);
Assert.IsFalse(success);
Assert.IsTrue(HasErrorString(errors, "cross register boundary"));
}
}

52
Assets/ScriptableRenderLoop/AdditionalLightData.cs


using System;
using System;
//@TODO: We should continously move these values
// into the engine when we can see them being generally useful
[RequireComponent(typeof(Light))]
public class AdditionalLightData : MonoBehaviour
{
public const int defaultShadowResolution = 512;
//@TODO: We should continously move these values
// into the engine when we can see them being generally useful
[RequireComponent(typeof(Light))]
public class AdditionalLightData : MonoBehaviour
{
public const int defaultShadowResolution = 512;
public int shadowResolution = defaultShadowResolution;
public int shadowResolution = defaultShadowResolution;
[RangeAttribute(0.0F, 100.0F)]
public float innerSpotPercent = 0.0F;
[RangeAttribute(0.0F, 100.0F)]
public float innerSpotPercent = 0.0F;
public static float GetInnerSpotPercent01(AdditionalLightData lightData)
{
if (lightData != null)
return Mathf.Clamp( lightData.innerSpotPercent, 0.0f, 100.0f ) / 100.0f;
else
return 0.0F;
}
public static float GetInnerSpotPercent01(AdditionalLightData lightData)
{
if (lightData != null)
return Mathf.Clamp(lightData.innerSpotPercent, 0.0f, 100.0f) / 100.0f;
else
return 0.0F;
}
public static int GetShadowResolution(AdditionalLightData lightData)
{
if (lightData != null)
return lightData.shadowResolution;
else
return defaultShadowResolution;
}
}
public static int GetShadowResolution(AdditionalLightData lightData)
{
if (lightData != null)
return lightData.shadowResolution;
else
return defaultShadowResolution;
}
}

388
Assets/ScriptableRenderLoop/ForwardRenderLoop/ForwardRenderLoop.cs


namespace UnityEngine.ScriptableRenderLoop
{
public class ForwardRenderLoop : ScriptableRenderLoop
{
public class ForwardRenderLoop : ScriptableRenderLoop
{
[UnityEditor.MenuItem("Renderloop/CreateForwardRenderLoop")]
static void CreateForwardRenderLoop()
{
var instance = ScriptableObject.CreateInstance<ForwardRenderLoop>();
UnityEditor.AssetDatabase.CreateAsset(instance, "Assets/forwardrenderloop.asset");
}
[UnityEditor.MenuItem("Renderloop/CreateForwardRenderLoop")]
static void CreateForwardRenderLoop()
{
var instance = ScriptableObject.CreateInstance<ForwardRenderLoop>();
UnityEditor.AssetDatabase.CreateAsset(instance, "Assets/forwardrenderloop.asset");
}
[SerializeField]
ShadowSettings m_ShadowSettings = ShadowSettings.Default;
ShadowRenderPass m_ShadowPass;
[SerializeField]
ShadowSettings m_ShadowSettings = ShadowSettings.Default;
ShadowRenderPass m_ShadowPass;
const int MAX_LIGHTS = 10;
const int MAX_SHADOWMAP_PER_LIGHTS = 6;
const int MAX_DIRECTIONAL_SPLIT = 4;
// Directional lights become spotlights at a far distance. This is the distance we pull back to set the spotlight origin.
const float DIRECTIONAL_LIGHT_PULLBACK_DISTANCE = 10000.0f;
const int MAX_LIGHTS = 10;
const int MAX_SHADOWMAP_PER_LIGHTS = 6;
const int MAX_DIRECTIONAL_SPLIT = 4;
// Directional lights become spotlights at a far distance. This is the distance we pull back to set the spotlight origin.
const float DIRECTIONAL_LIGHT_PULLBACK_DISTANCE = 10000.0f;
[NonSerialized] private int m_nWarnedTooManyLights = 0;
[NonSerialized] private int m_nWarnedTooManyLights = 0;
void OnEnable()
{
Rebuild ();
}
void OnEnable()
{
Rebuild();
}
void OnValidate()
{
Rebuild ();
}
void OnValidate()
{
Rebuild();
}
public override void Rebuild()
{
m_ShadowPass = new ShadowRenderPass (m_ShadowSettings);
}
public override void Rebuild()
{
m_ShadowPass = new ShadowRenderPass(m_ShadowSettings);
}
//---------------------------------------------------------------------------------------------------------------------------------------------------
void UpdateLightConstants(VisibleLight[] visibleLights, ref ShadowOutput shadow)
{
int nNumLightsIncludingTooMany = 0;
//---------------------------------------------------------------------------------------------------------------------------------------------------
void UpdateLightConstants(VisibleLight[] visibleLights, ref ShadowOutput shadow)
{
int nNumLightsIncludingTooMany = 0;
int g_nNumLights = 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_vSpotLightInnerOuterConeCosines = new Vector4[ MAX_LIGHTS ];
Matrix4x4[] g_matWorldToShadow = new Matrix4x4[ MAX_LIGHTS * MAX_SHADOWMAP_PER_LIGHTS ];
Vector4[] g_vDirShadowSplitSpheres = new Vector4[ MAX_DIRECTIONAL_SPLIT ];
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_vSpotLightInnerOuterConeCosines = new Vector4[MAX_LIGHTS];
Matrix4x4[] g_matWorldToShadow = new Matrix4x4[MAX_LIGHTS * MAX_SHADOWMAP_PER_LIGHTS];
Vector4[] g_vDirShadowSplitSpheres = new Vector4[MAX_DIRECTIONAL_SPLIT];
for ( int nLight = 0; nLight < visibleLights.Length; nLight++ )
{
for (int nLight = 0; nLight < visibleLights.Length; nLight++)
{
nNumLightsIncludingTooMany++;
if (nNumLightsIncludingTooMany > MAX_LIGHTS)
continue;
nNumLightsIncludingTooMany++;
if ( nNumLightsIncludingTooMany > MAX_LIGHTS )
continue;
VisibleLight light = visibleLights[nLight];
LightType lightType = light.lightType;
Vector3 position = light.light.transform.position;
Vector3 lightDir = light.light.transform.forward.normalized;
AdditionalLightData additionalLightData = light.light.GetComponent<AdditionalLightData>();
VisibleLight light = visibleLights[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;
// Setup shadow data arrays
bool hasShadows = shadow.GetShadowSliceCountLightIndex (nLight) != 0;
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);
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 );
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;
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;
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);
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 );
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));
}
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 ) );
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++;
}
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;
}
}
// 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");
}
}
g_nNumLights++;
}
// Send constants to shaders
Shader.SetGlobalInt("g_nNumLights", g_nNumLights);
// 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" );
}
}
// 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);
// Send constants to shaders
Shader.SetGlobalInt( "g_nNumLights", g_nNumLights );
// 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
// 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 );
// 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);
// 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
Shader.SetGlobalVector("g_vShadow3x3PCFTerms0", g_vShadow3x3PCFTerms0);
Shader.SetGlobalVector("g_vShadow3x3PCFTerms1", g_vShadow3x3PCFTerms1);
Shader.SetGlobalVector("g_vShadow3x3PCFTerms2", g_vShadow3x3PCFTerms2);
Shader.SetGlobalVector("g_vShadow3x3PCFTerms3", g_vShadow3x3PCFTerms3);
}
// 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 );
public override void Render(Camera[] cameras, RenderLoop renderLoop)
{
foreach (var camera in cameras)
{
CullResults cullResults;
CullingParameters cullingParams;
if (!CullResults.GetCullingParameters(camera, out cullingParams))
continue;
Shader.SetGlobalVector( "g_vShadow3x3PCFTerms0", g_vShadow3x3PCFTerms0 );
Shader.SetGlobalVector( "g_vShadow3x3PCFTerms1", g_vShadow3x3PCFTerms1 );
Shader.SetGlobalVector( "g_vShadow3x3PCFTerms2", g_vShadow3x3PCFTerms2 );
Shader.SetGlobalVector( "g_vShadow3x3PCFTerms3", g_vShadow3x3PCFTerms3 );
}
m_ShadowPass.UpdateCullingParameters(ref cullingParams);
public override void Render(Camera[] cameras, RenderLoop renderLoop)
{
foreach (var camera in cameras)
{
CullResults cullResults;
CullingParameters cullingParams;
if (!CullResults.GetCullingParameters (camera, out cullingParams))
continue;
cullResults = CullResults.Cull(ref cullingParams, renderLoop);
m_ShadowPass.UpdateCullingParameters (ref cullingParams);
ShadowOutput shadows;
m_ShadowPass.Render(renderLoop, cullResults, out shadows);
cullResults = CullResults.Cull (ref cullingParams, renderLoop);
ShadowOutput shadows;
m_ShadowPass.Render (renderLoop, cullResults, out shadows);
renderLoop.SetupCameraProperties(camera);
renderLoop.SetupCameraProperties (camera);
UpdateLightConstants(cullResults.visibleLights, ref shadows);
UpdateLightConstants(cullResults.visibleLights, ref shadows);
DrawRendererSettings settings = new DrawRendererSettings(cullResults, camera, new ShaderPassName("ForwardBase"));
settings.rendererConfiguration = RendererConfiguration.ConfigureOneLightProbePerRenderer | RendererConfiguration.ConfigureReflectionProbesProbePerRenderer;
settings.sorting.sortOptions = SortOptions.SortByMaterialThenMesh;
DrawRendererSettings settings = new DrawRendererSettings (cullResults, camera, new ShaderPassName("ForwardBase"));
settings.rendererConfiguration = RendererConfiguration.ConfigureOneLightProbePerRenderer | RendererConfiguration.ConfigureReflectionProbesProbePerRenderer;
settings.sorting.sortOptions = SortOptions.SortByMaterialThenMesh;
renderLoop.DrawRenderers(ref settings);
renderLoop.Submit();
}
renderLoop.DrawRenderers (ref settings);
renderLoop.Submit ();
}
// Post effects
}
// Post effects
}
#if UNITY_EDITOR
public override UnityEditor.SupportedRenderingFeatures GetSupportedRenderingFeatures()
{
var features = new UnityEditor.SupportedRenderingFeatures();
#if UNITY_EDITOR
public override UnityEditor.SupportedRenderingFeatures GetSupportedRenderingFeatures()
{
var features = new UnityEditor.SupportedRenderingFeatures();
features.reflectionProbe = UnityEditor.SupportedRenderingFeatures.ReflectionProbe.Rotation;
features.reflectionProbe = UnityEditor.SupportedRenderingFeatures.ReflectionProbe.Rotation;
return features;
}
return features;
}
#endif
}
#endif
}
}

878
Assets/ScriptableRenderLoop/ForwardRenderLoop/Shaders/vr_lighting.cginc


//-------------------------------------------------------------------------------------------------------------------------------------------------------------
struct LightingTerms_t
{
float3 vDiffuse;
float3 vSpecular;
float3 vIndirectDiffuse;
float3 vIndirectSpecular;
float3 vTransmissiveSunlight;
float3 vDiffuse;
float3 vSpecular;
float3 vIndirectDiffuse;
float3 vIndirectSpecular;
float3 vTransmissiveSunlight;
float3 vNormalWsDdx = ddx(vGeometricNormalWs.xyz);
float3 vNormalWsDdy = ddy(vGeometricNormalWs.xyz);
float flGeometricRoughnessFactor = pow(saturate(max(dot(vNormalWsDdx.xyz, vNormalWsDdx.xyz), dot(vNormalWsDdy.xyz, vNormalWsDdy.xyz))), 0.333);
return flGeometricRoughnessFactor;
float3 vNormalWsDdx = ddx(vGeometricNormalWs.xyz);
float3 vNormalWsDdy = ddy(vGeometricNormalWs.xyz);
float flGeometricRoughnessFactor = pow(saturate(max(dot(vNormalWsDdx.xyz, vNormalWsDdx.xyz), dot(vNormalWsDdy.xyz, vNormalWsDdy.xyz))), 0.333);
return flGeometricRoughnessFactor;
float flGeometricRoughnessFactor = CalculateGeometricRoughnessFactor(vGeometricNormalWs.xyz);
float flGeometricRoughnessFactor = CalculateGeometricRoughnessFactor(vGeometricNormalWs.xyz);
//if ( Blink( 1.0 ) )
//vRoughness.xy = min( vRoughness.xy + flGeometricRoughnessFactor.xx, float2( 1.0, 1.0 ) );
//else
vRoughness.xy = max(vRoughness.xy, flGeometricRoughnessFactor.xx);
return vRoughness.xy;
//if ( Blink( 1.0 ) )
//vRoughness.xy = min( vRoughness.xy + flGeometricRoughnessFactor.xx, float2( 1.0, 1.0 ) );
//else
vRoughness.xy = max(vRoughness.xy, flGeometricRoughnessFactor.xx);
return vRoughness.xy;
o_vDiffuseExponentOut.xy = ((1.0 - vRoughness.xy) * 0.8) + 0.6; // 0.8 and 0.6 are magic numbers
o_vSpecularExponentOut.xy = exp2(pow(float2(1.0, 1.0) - vRoughness.xy, float2(1.5, 1.5)) * float2(14.0, 14.0)); // Outputs 1-16384
o_vSpecularScaleOut.xy = 1.0 - saturate(vRoughness.xy * 0.5); // This is an energy conserving scalar for the roughness exponent.
o_vDiffuseExponentOut.xy = ((1.0 - vRoughness.xy) * 0.8) + 0.6; // 0.8 and 0.6 are magic numbers
o_vSpecularExponentOut.xy = exp2(pow(float2(1.0, 1.0) - vRoughness.xy, float2(1.5, 1.5)) * float2(14.0, 14.0)); // Outputs 1-16384
o_vSpecularScaleOut.xy = 1.0 - saturate(vRoughness.xy * 0.5); // This is an energy conserving scalar for the roughness exponent.
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------

{
float flNumer = (k + 2.0) * (k + 4.0);
float flDenom = 8 * (exp2(-k * 0.5) + k);
return flNumer / flDenom;
float flNumer = (k + 2.0) * (k + 4.0);
float flDenom = 8 * (exp2(-k * 0.5) + k);
return flNumer / flDenom;
// AV - My approximation to Unity's falloff function (I'll experiment with putting this into a texture later)
return lerp(1.0, (1.0 - pow(flDistToLightSq * flLightInvRadius * flLightInvRadius, 0.175)), vFalloffParams.x);
// AV - My approximation to Unity's falloff function (I'll experiment with putting this into a texture later)
return lerp(1.0, (1.0 - pow(flDistToLightSq * flLightInvRadius * flLightInvRadius, 0.175)), vFalloffParams.x);
// AV - This is the VR Aperture Demo falloff function
//flDistToLightSq = max( flDistToLightSq, 8.0f ); // Can't be inside the light source (assuming radius^2 == 8.0f)
//
//float2 vInvRadiusAndInvRadiusSq = float2( flLightInvRadius, flLightInvRadius * flLightInvRadius );
//float2 vLightDistAndLightDistSq = float2( sqrt( flDistToLightSq ), flDistToLightSq );
//
//float flTruncation = dot( vFalloffParams.xy, vInvRadiusAndInvRadiusSq.xy ); // Constant amount to subtract to ensure that the light is zero past the light radius
//float flFalloff = dot( vFalloffParams.xy, vLightDistAndLightDistSq.xy );
//
//return saturate( ( 1.0f / flFalloff ) - flTruncation );
// AV - This is the VR Aperture Demo falloff function
//flDistToLightSq = max( flDistToLightSq, 8.0f ); // Can't be inside the light source (assuming radius^2 == 8.0f)
//
//float2 vInvRadiusAndInvRadiusSq = float2( flLightInvRadius, flLightInvRadius * flLightInvRadius );
//float2 vLightDistAndLightDistSq = float2( sqrt( flDistToLightSq ), flDistToLightSq );
//
//float flTruncation = dot( vFalloffParams.xy, vInvRadiusAndInvRadiusSq.xy ); // Constant amount to subtract to ensure that the light is zero past the light radius
//float flFalloff = dot( vFalloffParams.xy, vLightDistAndLightDistSq.xy );
//
//return saturate( ( 1.0f / flFalloff ) - flTruncation );
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------

float3 vNormalWs, float3 vEllipseUWs, float3 vEllipseVWs, float3 vPositionToLightDirWs, float3 vPositionToCameraDirWs,
float2 vDiffuseExponent, float2 vSpecularExponent, float2 vSpecularScale, float3 vReflectance, float flFresnelExponent)
float3 vNormalWs, float3 vEllipseUWs, float3 vEllipseVWs, float3 vPositionToLightDirWs, float3 vPositionToCameraDirWs,
float2 vDiffuseExponent, float2 vSpecularExponent, float2 vSpecularScale, float3 vReflectance, float flFresnelExponent)
float flNDotL = ClampToPositive(dot(vNormalWs.xyz, vPositionToLightDirWs.xyz));
float flNDotL = ClampToPositive(dot(vNormalWs.xyz, vPositionToLightDirWs.xyz));
// Diffuse
float flDiffuseTerm = 0.0;
if (bDiffuse)
{
/* Disabling anisotropic diffuse until we have a need for it. Isotropic diffuse should be enough.
// Project light vector onto each tangent plane
float3 vDiffuseNormalX = vPositionToLightDirWs.xyz - ( vEllipseUWs.xyz * dot( vPositionToLightDirWs.xyz, vEllipseUWs.xyz ) ); // Not normalized on purpose
float3 vDiffuseNormalY = vPositionToLightDirWs.xyz - ( vEllipseVWs.xyz * dot( vPositionToLightDirWs.xyz, vEllipseVWs.xyz ) ); // Not normalized on purpose
// Diffuse
float flDiffuseTerm = 0.0;
if (bDiffuse)
{
/* Disabling anisotropic diffuse until we have a need for it. Isotropic diffuse should be enough.
// Project light vector onto each tangent plane
float3 vDiffuseNormalX = vPositionToLightDirWs.xyz - ( vEllipseUWs.xyz * dot( vPositionToLightDirWs.xyz, vEllipseUWs.xyz ) ); // Not normalized on purpose
float3 vDiffuseNormalY = vPositionToLightDirWs.xyz - ( vEllipseVWs.xyz * dot( vPositionToLightDirWs.xyz, vEllipseVWs.xyz ) ); // Not normalized on purpose
float flNDotLX = ClampToPositive( dot( vDiffuseNormalX.xyz, vPositionToLightDirWs.xyz ) );
flNDotLX = pow( flNDotLX, vDiffuseExponent.x * 0.5 );
float flNDotLX = ClampToPositive( dot( vDiffuseNormalX.xyz, vPositionToLightDirWs.xyz ) );
flNDotLX = pow( flNDotLX, vDiffuseExponent.x * 0.5 );
float flNDotLY = ClampToPositive( dot( vDiffuseNormalY.xyz, vPositionToLightDirWs.xyz ) );
flNDotLY = pow( flNDotLY, vDiffuseExponent.y * 0.5 );
float flNDotLY = ClampToPositive( dot( vDiffuseNormalY.xyz, vPositionToLightDirWs.xyz ) );
flNDotLY = pow( flNDotLY, vDiffuseExponent.y * 0.5 );
flDiffuseTerm = flNDotLX * flNDotLY;
flDiffuseTerm *= ( ( vDiffuseExponent.x * 0.5 + vDiffuseExponent.y * 0.5 ) + 1.0 ) * 0.5;
flDiffuseTerm *= flNDotL;
//*/
flDiffuseTerm = flNDotLX * flNDotLY;
flDiffuseTerm *= ( ( vDiffuseExponent.x * 0.5 + vDiffuseExponent.y * 0.5 ) + 1.0 ) * 0.5;
flDiffuseTerm *= flNDotL;
//*/
float flDiffuseExponent = (vDiffuseExponent.x + vDiffuseExponent.y) * 0.5;
flDiffuseTerm = pow(flNDotL, flDiffuseExponent) * ((flDiffuseExponent + 1.0) * 0.5);
}
float flDiffuseExponent = (vDiffuseExponent.x + vDiffuseExponent.y) * 0.5;
flDiffuseTerm = pow(flNDotL, flDiffuseExponent) * ((flDiffuseExponent + 1.0) * 0.5);
}
// Specular
float3 vSpecularTerm = float3(0.0, 0.0, 0.0);
[branch] if (bSpecular)
{
float3 vHalfAngleDirWs = normalize(vPositionToLightDirWs.xyz + vPositionToCameraDirWs.xyz);
// Specular
float3 vSpecularTerm = float3(0.0, 0.0, 0.0);
[branch] if (bSpecular)
{
float3 vHalfAngleDirWs = normalize(vPositionToLightDirWs.xyz + vPositionToCameraDirWs.xyz);
float flSpecularTerm = 0.0;
float flSpecularTerm = 0.0;
{
float3 vSpecularNormalX = vHalfAngleDirWs.xyz - (vEllipseUWs.xyz * dot(vHalfAngleDirWs.xyz, vEllipseUWs.xyz)); // Not normalized on purpose
float3 vSpecularNormalY = vHalfAngleDirWs.xyz - (vEllipseVWs.xyz * dot(vHalfAngleDirWs.xyz, vEllipseVWs.xyz)); // Not normalized on purpose
{
float3 vSpecularNormalX = vHalfAngleDirWs.xyz - (vEllipseUWs.xyz * dot(vHalfAngleDirWs.xyz, vEllipseUWs.xyz)); // Not normalized on purpose
float3 vSpecularNormalY = vHalfAngleDirWs.xyz - (vEllipseVWs.xyz * dot(vHalfAngleDirWs.xyz, vEllipseVWs.xyz)); // Not normalized on purpose
float flNDotHX = ClampToPositive(dot(vSpecularNormalX.xyz, vHalfAngleDirWs.xyz));
float flNDotHkX = pow(flNDotHX, vSpecularExponent.x * 0.5);
flNDotHkX *= vSpecularScale.x;
float flNDotHX = ClampToPositive(dot(vSpecularNormalX.xyz, vHalfAngleDirWs.xyz));
float flNDotHkX = pow(flNDotHX, vSpecularExponent.x * 0.5);
flNDotHkX *= vSpecularScale.x;
float flNDotHY = ClampToPositive(dot(vSpecularNormalY.xyz, vHalfAngleDirWs.xyz));
float flNDotHkY = pow(flNDotHY, vSpecularExponent.y * 0.5);
flNDotHkY *= vSpecularScale.y;
float flNDotHY = ClampToPositive(dot(vSpecularNormalY.xyz, vHalfAngleDirWs.xyz));
float flNDotHkY = pow(flNDotHY, vSpecularExponent.y * 0.5);
flNDotHkY *= vSpecularScale.y;
flSpecularTerm = flNDotHkX * flNDotHkY;
}
flSpecularTerm = flNDotHkX * flNDotHkY;
}
{
float flNDotH = saturate(dot(vNormalWs.xyz, vHalfAngleDirWs.xyz));
float flNDotHk = pow(flNDotH, dot(vSpecularExponent.xy, float2(0.5, 0.5)));
flNDotHk *= dot(vSpecularScale.xy, float2(0.33333, 0.33333)); // The 0.33333 is to match the spec of the aniso algorithm above with isotropic roughness values
flSpecularTerm = flNDotHk;
}
{
float flNDotH = saturate(dot(vNormalWs.xyz, vHalfAngleDirWs.xyz));
float flNDotHk = pow(flNDotH, dot(vSpecularExponent.xy, float2(0.5, 0.5)));
flNDotHk *= dot(vSpecularScale.xy, float2(0.33333, 0.33333)); // The 0.33333 is to match the spec of the aniso algorithm above with isotropic roughness values
flSpecularTerm = flNDotHk;
}
flSpecularTerm *= flNDotL; // This makes it modified Blinn-Phong
flSpecularTerm *= BlinnPhongModifiedNormalizationFactor(vSpecularExponent.x * 0.5 + vSpecularExponent.y * 0.5);
flSpecularTerm *= flNDotL; // This makes it modified Blinn-Phong
flSpecularTerm *= BlinnPhongModifiedNormalizationFactor(vSpecularExponent.x * 0.5 + vSpecularExponent.y * 0.5);
float flLDotH = ClampToPositive(dot(vPositionToLightDirWs.xyz, vHalfAngleDirWs.xyz));
float3 vMaxReflectance = vReflectance.rgb / (Luminance(vReflectance.rgb) + 0.0001);
float3 vFresnel = lerp(vReflectance.rgb, vMaxReflectance.rgb, pow(1.0 - flLDotH, flFresnelExponent));
vSpecularTerm.rgb = flSpecularTerm * vFresnel.rgb;
}
float flLDotH = ClampToPositive(dot(vPositionToLightDirWs.xyz, vHalfAngleDirWs.xyz));
float3 vMaxReflectance = vReflectance.rgb / (Luminance(vReflectance.rgb) + 0.0001);
float3 vFresnel = lerp(vReflectance.rgb, vMaxReflectance.rgb, pow(1.0 - flLDotH, flFresnelExponent));
vSpecularTerm.rgb = flSpecularTerm * vFresnel.rgb;
}
return float4(flDiffuseTerm, vSpecularTerm.rgb);
return float4(flDiffuseTerm, vSpecularTerm.rgb);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

float ComputeShadow_PCF_3x3_Gaussian(float3 vPositionWs, float4x4 matWorldToShadow)
{
float4 vPositionTextureSpace = mul(float4(vPositionWs.xyz, 1.0), matWorldToShadow);
vPositionTextureSpace.xyz /= vPositionTextureSpace.w;
float4 vPositionTextureSpace = mul(float4(vPositionWs.xyz, 1.0), matWorldToShadow);
vPositionTextureSpace.xyz /= vPositionTextureSpace.w;
float2 shadowMapCenter = vPositionTextureSpace.xy;
float2 shadowMapCenter = vPositionTextureSpace.xy;
//if ( ( frac( shadowMapCenter.x ) != shadowMapCenter.x ) || ( frac( shadowMapCenter.y ) != shadowMapCenter.y ) )
if ((shadowMapCenter.x < 0.0f) || (shadowMapCenter.x > 1.0f) || (shadowMapCenter.y < 0.0f) || (shadowMapCenter.y > 1.0f))
return 1.0f;
//if ( ( frac( shadowMapCenter.x ) != shadowMapCenter.x ) || ( frac( shadowMapCenter.y ) != shadowMapCenter.y ) )
if ((shadowMapCenter.x < 0.0f) || (shadowMapCenter.x > 1.0f) || (shadowMapCenter.y < 0.0f) || (shadowMapCenter.y > 1.0f))
return 1.0f;
//float objDepth = saturate( vPositionTextureSpace.z - 0.000001 );
float objDepth = 1 - vPositionTextureSpace.z;
//float objDepth = saturate( vPositionTextureSpace.z - 0.000001 );
float objDepth = 1 - vPositionTextureSpace.z;
/* // Depth texture visualization
if ( 1 )
{
#define NUM_SAMPLES 128.0
float flSum = 0.0;
for ( int j = 0; j < NUM_SAMPLES; j++ )
{
flSum += ( 1.0 / NUM_SAMPLES ) * ( VALVE_SAMPLE_SHADOW( g_tShadowBuffer, float3( shadowMapCenter.xy, j / NUM_SAMPLES ) ).r );
}
return flSum;
}
//*/
/* // Depth texture visualization
if ( 1 )
{
#define NUM_SAMPLES 128.0
float flSum = 0.0;
for ( int j = 0; j < NUM_SAMPLES; j++ )
{
flSum += ( 1.0 / NUM_SAMPLES ) * ( VALVE_SAMPLE_SHADOW( g_tShadowBuffer, float3( shadowMapCenter.xy, j / NUM_SAMPLES ) ).r );
}
return flSum;
}
//*/
//float flTexelEpsilonX = 1.0 / 4096.0;
//float flTexelEpsilonY = 1.0 / 4096.0;
//g_vShadow3x3PCFTerms0 = float4( 20.0 / 267.0, 33.0 / 267.0, 55.0 / 267.0, 0.0 );
//g_vShadow3x3PCFTerms1 = float4( flTexelEpsilonX, flTexelEpsilonY, -flTexelEpsilonX, -flTexelEpsilonY );
//g_vShadow3x3PCFTerms2 = float4( flTexelEpsilonX, flTexelEpsilonY, 0.0, 0.0 );
//g_vShadow3x3PCFTerms3 = float4( -flTexelEpsilonX, -flTexelEpsilonY, 0.0, 0.0 );
//float flTexelEpsilonX = 1.0 / 4096.0;
//float flTexelEpsilonY = 1.0 / 4096.0;
//g_vShadow3x3PCFTerms0 = float4( 20.0 / 267.0, 33.0 / 267.0, 55.0 / 267.0, 0.0 );
//g_vShadow3x3PCFTerms1 = float4( flTexelEpsilonX, flTexelEpsilonY, -flTexelEpsilonX, -flTexelEpsilonY );
//g_vShadow3x3PCFTerms2 = float4( flTexelEpsilonX, flTexelEpsilonY, 0.0, 0.0 );
//g_vShadow3x3PCFTerms3 = float4( -flTexelEpsilonX, -flTexelEpsilonY, 0.0, 0.0 );
float4 v20Taps;
v20Taps.x = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms1.xy, objDepth)).x; // 1 1
v20Taps.y = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms1.zy, objDepth)).x; // -1 1
v20Taps.z = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms1.xw, objDepth)).x; // 1 -1
v20Taps.w = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms1.zw, objDepth)).x; // -1 -1
float flSum = dot(v20Taps.xyzw, float4(0.25, 0.25, 0.25, 0.25));
if ((flSum == 0.0) || (flSum == 1.0))
return flSum;
flSum *= g_vShadow3x3PCFTerms0.x * 4.0;
float4 v20Taps;
v20Taps.x = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms1.xy, objDepth)).x; // 1 1
v20Taps.y = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms1.zy, objDepth)).x; // -1 1
v20Taps.z = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms1.xw, objDepth)).x; // 1 -1
v20Taps.w = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms1.zw, objDepth)).x; // -1 -1
float flSum = dot(v20Taps.xyzw, float4(0.25, 0.25, 0.25, 0.25));
if ((flSum == 0.0) || (flSum == 1.0))
return flSum;
flSum *= g_vShadow3x3PCFTerms0.x * 4.0;
float4 v33Taps;
v33Taps.x = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms2.xz, objDepth)).x; // 1 0
v33Taps.y = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms3.xz, objDepth)).x; // -1 0
v33Taps.z = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms3.zy, objDepth)).x; // 0 -1
v33Taps.w = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms2.zy, objDepth)).x; // 0 1
flSum += dot(v33Taps.xyzw, g_vShadow3x3PCFTerms0.yyyy);
float4 v33Taps;
v33Taps.x = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms2.xz, objDepth)).x; // 1 0
v33Taps.y = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms3.xz, objDepth)).x; // -1 0
v33Taps.z = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms3.zy, objDepth)).x; // 0 -1
v33Taps.w = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms2.zy, objDepth)).x; // 0 1
flSum += dot(v33Taps.xyzw, g_vShadow3x3PCFTerms0.yyyy);
flSum += VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy, objDepth)).x * g_vShadow3x3PCFTerms0.z;
flSum += VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy, objDepth)).x * g_vShadow3x3PCFTerms0.z;
return flSum;
return flSum;
float4 vLightmapTexel = tex2D(g_tOverrideLightmap, vLightmapUV.xy);
float4 vLightmapTexel = tex2D(g_tOverrideLightmap, vLightmapUV.xy);
// This path looks over-saturated
//return g_vOverrideLightmapScale * ( unity_Lightmap_HDR.x * pow( vLightmapTexel.a, unity_Lightmap_HDR.y ) ) * vLightmapTexel.rgb;
// This path looks over-saturated
//return g_vOverrideLightmapScale * ( unity_Lightmap_HDR.x * pow( vLightmapTexel.a, unity_Lightmap_HDR.y ) ) * vLightmapTexel.rgb;
// This path looks less broken
return g_vOverrideLightmapScale * (unity_Lightmap_HDR.x * vLightmapTexel.a) * sqrt(vLightmapTexel.rgb);
// This path looks less broken
return g_vOverrideLightmapScale * (unity_Lightmap_HDR.x * vLightmapTexel.a) * sqrt(vLightmapTexel.rgb);
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------

*/
float GetSplitSphereIndexForDirshadows(float3 wpos)
{
float3 fromCenter0 = wpos.xyz - g_vDirShadowSplitSpheres[0].xyz;
float3 fromCenter1 = wpos.xyz - g_vDirShadowSplitSpheres[1].xyz;
float3 fromCenter2 = wpos.xyz - g_vDirShadowSplitSpheres[2].xyz;
float3 fromCenter3 = wpos.xyz - g_vDirShadowSplitSpheres[3].xyz;
float4 distances2 = float4(dot(fromCenter0, fromCenter0), dot(fromCenter1, fromCenter1), dot(fromCenter2, fromCenter2), dot(fromCenter3, fromCenter3));
float4 vDirShadowSplitSphereSqRadii;
vDirShadowSplitSphereSqRadii.x = g_vDirShadowSplitSpheres[0].w;
vDirShadowSplitSphereSqRadii.y = g_vDirShadowSplitSpheres[1].w;
vDirShadowSplitSphereSqRadii.z = g_vDirShadowSplitSpheres[2].w;
vDirShadowSplitSphereSqRadii.w = g_vDirShadowSplitSpheres[3].w;
fixed4 weights = float4(distances2 < vDirShadowSplitSphereSqRadii);
weights.yzw = saturate(weights.yzw - weights.xyz);
return 4 - dot(weights, float4(4, 3, 2, 1));
float3 fromCenter0 = wpos.xyz - g_vDirShadowSplitSpheres[0].xyz;
float3 fromCenter1 = wpos.xyz - g_vDirShadowSplitSpheres[1].xyz;
float3 fromCenter2 = wpos.xyz - g_vDirShadowSplitSpheres[2].xyz;
float3 fromCenter3 = wpos.xyz - g_vDirShadowSplitSpheres[3].xyz;
float4 distances2 = float4(dot(fromCenter0, fromCenter0), dot(fromCenter1, fromCenter1), dot(fromCenter2, fromCenter2), dot(fromCenter3, fromCenter3));
float4 vDirShadowSplitSphereSqRadii;
vDirShadowSplitSphereSqRadii.x = g_vDirShadowSplitSpheres[0].w;
vDirShadowSplitSphereSqRadii.y = g_vDirShadowSplitSpheres[1].w;
vDirShadowSplitSphereSqRadii.z = g_vDirShadowSplitSpheres[2].w;
vDirShadowSplitSphereSqRadii.w = g_vDirShadowSplitSpheres[3].w;
fixed4 weights = float4(distances2 < vDirShadowSplitSphereSqRadii);
weights.yzw = saturate(weights.yzw - weights.xyz);
return 4 - dot(weights, float4(4, 3, 2, 1));
#if DEBUG_SHADOWS_SPLIT
// Slightly intensified colors of ShadowCascadeSplitGUI + 2 new for point light (ie splitIndex 4 and 5)
const fixed3 kSplitColors[6] =
{
fixed3(0.5, 0.5, 0.7),
fixed3(0.5, 0.7, 0.5),
fixed3(0.7, 0.7, 0.5),
fixed3(0.7, 0.5, 0.5),
#if DEBUG_SHADOWS_SPLIT
// Slightly intensified colors of ShadowCascadeSplitGUI + 2 new for point light (ie splitIndex 4 and 5)
const fixed3 kSplitColors[6] =
{
fixed3(0.5, 0.5, 0.7),
fixed3(0.5, 0.7, 0.5),
fixed3(0.7, 0.7, 0.5),
fixed3(0.7, 0.5, 0.5),
fixed3(0.7, 0.5, 0.7),
fixed3(0.5, 0.7, 0.7),
};
lightColor = kSplitColors[shadowSplitIndex];
#endif
fixed3(0.7, 0.5, 0.7),
fixed3(0.5, 0.7, 0.7),
};
lightColor = kSplitColors[shadowSplitIndex];
#endif
float3 vReflectance, float flFresnelExponent, float4 vLightmapUV)
float3 vReflectance, float flFresnelExponent, float4 vLightmapUV)
LightingTerms_t o;
o.vDiffuse = float3(0.0, 0.0, 0.0);
o.vSpecular = float3(0.0, 0.0, 0.0);
o.vIndirectDiffuse = float3(0.0, 0.0, 0.0);
o.vIndirectSpecular = float3(0.0, 0.0, 0.0);
o.vTransmissiveSunlight = float3(0.0, 0.0, 0.0);
LightingTerms_t o;
o.vDiffuse = float3(0.0, 0.0, 0.0);
o.vSpecular = float3(0.0, 0.0, 0.0);
o.vIndirectDiffuse = float3(0.0, 0.0, 0.0);
o.vIndirectSpecular = float3(0.0, 0.0, 0.0);
o.vTransmissiveSunlight = float3(0.0, 0.0, 0.0);
// Convert roughness to scale and exp
float2 vDiffuseExponent;
float2 vSpecularExponent;
float2 vSpecularScale;
RoughnessEllipseToScaleAndExp(vRoughness.xy, vDiffuseExponent.xy, vSpecularExponent.xy, vSpecularScale.xy);
// Convert roughness to scale and exp
float2 vDiffuseExponent;
float2 vSpecularExponent;
float2 vSpecularScale;
RoughnessEllipseToScaleAndExp(vRoughness.xy, vDiffuseExponent.xy, vSpecularExponent.xy, vSpecularScale.xy);
// Get positions between the clip planes of the frustum in 0..1 coordinates
//float3 vPositionCs = float3( vPosition4Cs.xy / vPosition4Cs.w, vPosition4Cs.z );
//vPositionCs.xy = ( vPositionCs.xy * 0.5 ) + 0.5;
// Get positions between the clip planes of the frustum in 0..1 coordinates
//float3 vPositionCs = float3( vPosition4Cs.xy / vPosition4Cs.w, vPosition4Cs.z );
//vPositionCs.xy = ( vPositionCs.xy * 0.5 ) + 0.5;
float3 vPositionToCameraDirWs = CalculatePositionToCameraDirWs(vPositionWs.xyz);
float3 vPositionToCameraDirWs = CalculatePositionToCameraDirWs(vPositionWs.xyz);
// Compute tangent frame relative to per-pixel normal
float3 vEllipseUWs = normalize(cross(vTangentVWs.xyz, vNormalWs.xyz));
float3 vEllipseVWs = normalize(cross(vNormalWs.xyz, vTangentUWs.xyz));
// Compute tangent frame relative to per-pixel normal
float3 vEllipseUWs = normalize(cross(vTangentVWs.xyz, vNormalWs.xyz));
float3 vEllipseVWs = normalize(cross(vNormalWs.xyz, vTangentUWs.xyz));
//-------------------------------------//
// Point, spot, and directional lights //
//-------------------------------------//
int nNumLightsUsed = 0;
[loop] for (int i = 0; i < g_nNumLights; i++)
{
float3 vPositionToLightRayWs = g_vLightPosition_flInvRadius[i].xyz - vPositionWs.xyz;
float flDistToLightSq = dot(vPositionToLightRayWs.xyz, vPositionToLightRayWs.xyz);
if (flDistToLightSq > g_vLightFalloffParams[i].z) // .z stores radius squared of light
{
// Outside light range
continue;
}
//-------------------------------------//
// Point, spot, and directional lights //
//-------------------------------------//
int nNumLightsUsed = 0;
[loop] for (int i = 0; i < g_nNumLights; i++)
{
float3 vPositionToLightRayWs = g_vLightPosition_flInvRadius[i].xyz - vPositionWs.xyz;
float flDistToLightSq = dot(vPositionToLightRayWs.xyz, vPositionToLightRayWs.xyz);
if (flDistToLightSq > g_vLightFalloffParams[i].z) // .z stores radius squared of light
{
// Outside light range
continue;
}
if (dot(vNormalWs.xyz, vPositionToLightRayWs.xyz) <= 0.0)
{
// Backface cull pixel to this light
continue;
}
if (dot(vNormalWs.xyz, vPositionToLightRayWs.xyz) <= 0.0)
{
// Backface cull pixel to this light
continue;
}
float3 vPositionToLightDirWs = normalize(vPositionToLightRayWs.xyz);
float flOuterConeCos = g_vSpotLightInnerOuterConeCosines[i].y;
float flTemp = dot(vPositionToLightDirWs.xyz, -g_vLightDirection[i].xyz) - flOuterConeCos;
if (flTemp <= 0.0)
{
// Outside spotlight cone
continue;
}
float3 vSpotAtten = saturate(flTemp * g_vSpotLightInnerOuterConeCosines[i].z).xxx;
float3 vPositionToLightDirWs = normalize(vPositionToLightRayWs.xyz);
float flOuterConeCos = g_vSpotLightInnerOuterConeCosines[i].y;
float flTemp = dot(vPositionToLightDirWs.xyz, -g_vLightDirection[i].xyz) - flOuterConeCos;
if (flTemp <= 0.0)
{
// Outside spotlight cone
continue;
}
float3 vSpotAtten = saturate(flTemp * g_vSpotLightInnerOuterConeCosines[i].z).xxx;
nNumLightsUsed++;
nNumLightsUsed++;
//[branch] if ( g_vLightShadowIndex_vLightParams[ i ].y != 0 ) // If has light cookie
//{
// // Light cookie
// float4 vPositionTextureSpace = mul( float4( vPositionWs.xyz, 1.0 ), g_matWorldToLightCookie[ i ] );
// vPositionTextureSpace.xyz /= vPositionTextureSpace.w;
// vSpotAtten.rgb = Tex3DLevel( g_tVrLightCookieTexture, vPositionTextureSpace.xyz, 0.0 ).rgb;
//}
//[branch] if ( g_vLightShadowIndex_vLightParams[ i ].y != 0 ) // If has light cookie
//{
// // Light cookie
// float4 vPositionTextureSpace = mul( float4( vPositionWs.xyz, 1.0 ), g_matWorldToLightCookie[ i ] );
// vPositionTextureSpace.xyz /= vPositionTextureSpace.w;
// vSpotAtten.rgb = Tex3DLevel( g_tVrLightCookieTexture, vPositionTextureSpace.xyz, 0.0 ).rgb;
//}
float flLightFalloff = DistanceFalloff(flDistToLightSq, g_vLightPosition_flInvRadius[i].w, g_vLightFalloffParams[i].xy);
float flLightFalloff = DistanceFalloff(flDistToLightSq, g_vLightPosition_flInvRadius[i].w, g_vLightFalloffParams[i].xy);
float flShadowScalar = 1.0;
int shadowSplitIndex = 0;
if (g_vLightShadowIndex_vLightParams[i].x != 0.0)
{
if (g_vLightFalloffParams[i].w == LIGHT_TYPE_DIRECTIONAL)
{
shadowSplitIndex = GetSplitSphereIndexForDirshadows(vPositionWs);
}
float flShadowScalar = 1.0;
int shadowSplitIndex = 0;
if (g_vLightShadowIndex_vLightParams[i].x != 0.0)
{
if (g_vLightFalloffParams[i].w == LIGHT_TYPE_DIRECTIONAL)
{
shadowSplitIndex = GetSplitSphereIndexForDirshadows(vPositionWs);
}
if (g_vLightFalloffParams[i].w == LIGHT_TYPE_POINT)
{
float3 absPos = abs(vPositionToLightDirWs);
shadowSplitIndex = (vPositionToLightDirWs.z > 0) ? CUBEMAPFACE_NEGATIVE_Z : CUBEMAPFACE_POSITIVE_Z;
if (absPos.x > absPos.y)
{
if (absPos.x > absPos.z)
{
shadowSplitIndex = (vPositionToLightDirWs.x > 0) ? CUBEMAPFACE_NEGATIVE_X : CUBEMAPFACE_POSITIVE_X;
}
}
else
{
if (absPos.y > absPos.z)
{
shadowSplitIndex = (vPositionToLightDirWs.y > 0) ? CUBEMAPFACE_NEGATIVE_Y : CUBEMAPFACE_POSITIVE_Y;
}
}
}
if (g_vLightFalloffParams[i].w == LIGHT_TYPE_POINT)
{
float3 absPos = abs(vPositionToLightDirWs);
shadowSplitIndex = (vPositionToLightDirWs.z > 0) ? CUBEMAPFACE_NEGATIVE_Z : CUBEMAPFACE_POSITIVE_Z;
if (absPos.x > absPos.y)
{
if (absPos.x > absPos.z)
{
shadowSplitIndex = (vPositionToLightDirWs.x > 0) ? CUBEMAPFACE_NEGATIVE_X : CUBEMAPFACE_POSITIVE_X;
}
}
else
{
if (absPos.y > absPos.z)
{
shadowSplitIndex = (vPositionToLightDirWs.y > 0) ? CUBEMAPFACE_NEGATIVE_Y : CUBEMAPFACE_POSITIVE_Y;
}
}
}
flShadowScalar = ComputeShadow_PCF_3x3_Gaussian(vPositionWs.xyz, g_matWorldToShadow[i * MAX_SHADOWMAP_PER_LIGHTS + shadowSplitIndex]);
flShadowScalar = ComputeShadow_PCF_3x3_Gaussian(vPositionWs.xyz, g_matWorldToShadow[i * MAX_SHADOWMAP_PER_LIGHTS + shadowSplitIndex]);
if (flShadowScalar <= 0.0)
continue;
}
if (flShadowScalar <= 0.0)
continue;
}
float4 vLightingTerms = ComputeDiffuseAndSpecularTerms(g_vLightShadowIndex_vLightParams[i].z != 0.0, g_vLightShadowIndex_vLightParams[i].w != 0.0,
vNormalWs.xyz, vEllipseUWs.xyz, vEllipseVWs.xyz,
vPositionToLightDirWs.xyz, vPositionToCameraDirWs.xyz,
vDiffuseExponent.xy, vSpecularExponent.xy, vSpecularScale.xy, vReflectance.rgb, flFresnelExponent);
float4 vLightingTerms = ComputeDiffuseAndSpecularTerms(g_vLightShadowIndex_vLightParams[i].z != 0.0, g_vLightShadowIndex_vLightParams[i].w != 0.0,
vNormalWs.xyz, vEllipseUWs.xyz, vEllipseVWs.xyz,
vPositionToLightDirWs.xyz, vPositionToCameraDirWs.xyz,
vDiffuseExponent.xy, vSpecularExponent.xy, vSpecularScale.xy, vReflectance.rgb, flFresnelExponent);
float3 vLightColor = g_vLightColor[i].rgb;
OverrideLightColorWithSplitDebugInfo(vLightColor, shadowSplitIndex);
float3 vLightColor = g_vLightColor[i].rgb;
OverrideLightColorWithSplitDebugInfo(vLightColor, shadowSplitIndex);
float3 vLightMask = vLightColor.rgb * flShadowScalar * flLightFalloff * vSpotAtten.rgb;
o.vDiffuse.rgb += vLightingTerms.xxx * vLightMask.rgb;
o.vSpecular.rgb += vLightingTerms.yzw * vLightMask.rgb;
}
float3 vLightMask = vLightColor.rgb * flShadowScalar * flLightFalloff * vSpotAtten.rgb;
o.vDiffuse.rgb += vLightingTerms.xxx * vLightMask.rgb;
o.vSpecular.rgb += vLightingTerms.yzw * vLightMask.rgb;
}
/* // Visualize number of lights for the first 7 as RGBCMYW
if ( nNumLightsUsed == 0 )
o.vDiffuse.rgb = float3( 0.0, 0.0, 0.0 );
else if ( nNumLightsUsed == 1 )
o.vDiffuse.rgb = float3( 1.0, 0.0, 0.0 );
else if ( nNumLightsUsed == 2 )
o.vDiffuse.rgb = float3( 0.0, 1.0, 0.0 );
else if ( nNumLightsUsed == 3 )
o.vDiffuse.rgb = float3( 0.0, 0.0, 1.0 );
else if ( nNumLightsUsed == 4 )
o.vDiffuse.rgb = float3( 0.0, 1.0, 1.0 );
else if ( nNumLightsUsed == 5 )
o.vDiffuse.rgb = float3( 1.0, 0.0, 1.0 );
else if ( nNumLightsUsed == 6 )
o.vDiffuse.rgb = float3( 1.0, 1.0, 0.0 );
else
o.vDiffuse.rgb = float3( 1.0, 1.0, 1.0 );
o.vDiffuse.rgb *= float3( 2.0, 2.0, 2.0 );
o.vSpecular.rgb = float3( 0.0, 0.0, 0.0 );
return o;
//*/
/* // Visualize number of lights for the first 7 as RGBCMYW
if ( nNumLightsUsed == 0 )
o.vDiffuse.rgb = float3( 0.0, 0.0, 0.0 );
else if ( nNumLightsUsed == 1 )
o.vDiffuse.rgb = float3( 1.0, 0.0, 0.0 );
else if ( nNumLightsUsed == 2 )
o.vDiffuse.rgb = float3( 0.0, 1.0, 0.0 );
else if ( nNumLightsUsed == 3 )
o.vDiffuse.rgb = float3( 0.0, 0.0, 1.0 );
else if ( nNumLightsUsed == 4 )
o.vDiffuse.rgb = float3( 0.0, 1.0, 1.0 );
else if ( nNumLightsUsed == 5 )
o.vDiffuse.rgb = float3( 1.0, 0.0, 1.0 );
else if ( nNumLightsUsed == 6 )
o.vDiffuse.rgb = float3( 1.0, 1.0, 0.0 );
else
o.vDiffuse.rgb = float3( 1.0, 1.0, 1.0 );
o.vDiffuse.rgb *= float3( 2.0, 2.0, 2.0 );
o.vSpecular.rgb = float3( 0.0, 0.0, 0.0 );
return o;
//*/
// Apply specular reflectance to diffuse term (specular term already accounts for this in the fresnel equation)
o.vDiffuse.rgb *= (float3(1.0, 1.0, 1.0) - vReflectance.rgb);
// Apply specular reflectance to diffuse term (specular term already accounts for this in the fresnel equation)
o.vDiffuse.rgb *= (float3(1.0, 1.0, 1.0) - vReflectance.rgb);
//------------------//
// Indirect diffuse //
//------------------//
//------------------//
// Indirect diffuse //
//------------------//
{
o.vIndirectDiffuse.rgb += ComputeOverrideLightmap(vLightmapUV.xy);
}
{
o.vIndirectDiffuse.rgb += ComputeOverrideLightmap(vLightmapUV.xy);
}
{
// Baked lightmaps
float4 bakedColorTex = Tex2DLevel(unity_Lightmap, vLightmapUV.xy, 0.0);
float3 bakedColor = DecodeLightmap(bakedColorTex);
{
// Baked lightmaps
float4 bakedColorTex = Tex2DLevel(unity_Lightmap, vLightmapUV.xy, 0.0);
float3 bakedColor = DecodeLightmap(bakedColorTex);
{
o.vIndirectDiffuse.rgb += bakedColor.rgb;
{
o.vIndirectDiffuse.rgb += bakedColor.rgb;
//o_gi.indirect.diffuse = bakedColor;
//
//#ifdef SHADOWS_SCREEN
// o_gi.indirect.diffuse = MixLightmapWithRealtimeAttenuation (o_gi.indirect.diffuse, data.atten, bakedColorTex);
//#endif // SHADOWS_SCREEN
}
//o_gi.indirect.diffuse = bakedColor;
//
//#ifdef SHADOWS_SCREEN
// o_gi.indirect.diffuse = MixLightmapWithRealtimeAttenuation (o_gi.indirect.diffuse, data.atten, bakedColorTex);
//#endif // SHADOWS_SCREEN
}
{
//o.vIndirectDiffuse.rgb = float3( 0.0, 1.0, 0.0 );
{
//o.vIndirectDiffuse.rgb = float3( 0.0, 1.0, 0.0 );
float4 bakedDirTex = Tex2DLevelFromSampler(unity_LightmapInd, unity_Lightmap, vLightmapUV.xy, 0.0);
//float flHalfLambert = dot( vNormalWs.xyz, bakedDirTex.xyz - 0.5 ) + 0.5;
//o.vIndirectDiffuse.rgb += bakedColor.rgb * flHalfLambert / bakedDirTex.w;
float4 bakedDirTex = Tex2DLevelFromSampler(unity_LightmapInd, unity_Lightmap, vLightmapUV.xy, 0.0);
//float flHalfLambert = dot( vNormalWs.xyz, bakedDirTex.xyz - 0.5 ) + 0.5;
//o.vIndirectDiffuse.rgb += bakedColor.rgb * flHalfLambert / bakedDirTex.w;
float flHalfLambert = dot(vNormalWs.xyz, normalize(bakedDirTex.xyz - 0.5));// + ( 1.0 - length( bakedDirTex.xyz - 0.5 ) );
o.vIndirectDiffuse.rgb += bakedColor.rgb * flHalfLambert / (bakedDirTex.w);
float flHalfLambert = dot(vNormalWs.xyz, normalize(bakedDirTex.xyz - 0.5));// + ( 1.0 - length( bakedDirTex.xyz - 0.5 ) );
o.vIndirectDiffuse.rgb += bakedColor.rgb * flHalfLambert / (bakedDirTex.w);
//#ifdef SHADOWS_SCREEN
// o_gi.indirect.diffuse = MixLightmapWithRealtimeAttenuation (o_gi.indirect.diffuse, data.atten, bakedColorTex);
//#endif // SHADOWS_SCREEN
}
//#ifdef SHADOWS_SCREEN
// o_gi.indirect.diffuse = MixLightmapWithRealtimeAttenuation (o_gi.indirect.diffuse, data.atten, bakedColorTex);
//#endif // SHADOWS_SCREEN
}
{
// Left halves of both intensity and direction lightmaps store direct light; right halves store indirect.
float2 vUvDirect = vLightmapUV.xy;
float2 vUvIndirect = vLightmapUV.xy + float2(0.5, 0.0);
{
// Left halves of both intensity and direction lightmaps store direct light; right halves store indirect.
float2 vUvDirect = vLightmapUV.xy;
float2 vUvIndirect = vLightmapUV.xy + float2(0.5, 0.0);
// Direct Diffuse
float4 bakedDirTex = float4(0.0, 0.0, 0.0, 0.0);
if (!g_bIndirectLightmaps)
{
bakedDirTex = Tex2DLevelFromSampler(unity_LightmapInd, unity_Lightmap, vUvDirect.xy, 0.0);
//float flHalfLambert = dot( vNormalWs.xyz, bakedDirTex.xyz - 0.5 ) + 0.5;
//o.vDiffuse.rgb += bakedColor.rgb * flHalfLambert / bakedDirTex.w;
// Direct Diffuse
float4 bakedDirTex = float4(0.0, 0.0, 0.0, 0.0);
if (!g_bIndirectLightmaps)
{
bakedDirTex = Tex2DLevelFromSampler(unity_LightmapInd, unity_Lightmap, vUvDirect.xy, 0.0);
//float flHalfLambert = dot( vNormalWs.xyz, bakedDirTex.xyz - 0.5 ) + 0.5;
//o.vDiffuse.rgb += bakedColor.rgb * flHalfLambert / bakedDirTex.w;
float flHalfLambert = ClampToPositive(dot(vNormalWs.xyz, normalize(bakedDirTex.xyz - 0.5)));// + ( 1.0 - length( bakedDirTex.xyz - 0.5 ) );
o.vDiffuse.rgb += bakedColor.rgb * flHalfLambert / (bakedDirTex.w);
}
float flHalfLambert = ClampToPositive(dot(vNormalWs.xyz, normalize(bakedDirTex.xyz - 0.5)));// + ( 1.0 - length( bakedDirTex.xyz - 0.5 ) );
o.vDiffuse.rgb += bakedColor.rgb * flHalfLambert / (bakedDirTex.w);
}
// Indirect Diffuse
float4 bakedIndirTex = float4(0.0, 0.0, 0.0, 0.0);
float3 vBakedIndirectColor = float3(0.0, 0.0, 0.0);
if (1)
{
vBakedIndirectColor.rgb = DecodeLightmap(Tex2DLevel(unity_Lightmap, vUvIndirect.xy, 0.0));
bakedIndirTex = Tex2DLevelFromSampler(unity_LightmapInd, unity_Lightmap, vUvIndirect.xy, 0.0);
// Indirect Diffuse
float4 bakedIndirTex = float4(0.0, 0.0, 0.0, 0.0);
float3 vBakedIndirectColor = float3(0.0, 0.0, 0.0);
if (1)
{
vBakedIndirectColor.rgb = DecodeLightmap(Tex2DLevel(unity_Lightmap, vUvIndirect.xy, 0.0));
bakedIndirTex = Tex2DLevelFromSampler(unity_LightmapInd, unity_Lightmap, vUvIndirect.xy, 0.0);
//float flHalfLambert = dot( vNormalWs.xyz, bakedIndirTex.xyz - 0.5 ) + 0.5;
//o.vIndirectDiffuse.rgb += vBakedIndirectColor.rgb * flHalfLambert / bakedIndirTex.w;
//float flHalfLambert = dot( vNormalWs.xyz, bakedIndirTex.xyz - 0.5 ) + 0.5;
//o.vIndirectDiffuse.rgb += vBakedIndirectColor.rgb * flHalfLambert / bakedIndirTex.w;
float flHalfLambert = dot(vNormalWs.xyz, normalize(bakedIndirTex.xyz - 0.5));// + ( 1.0 - length( bakedIndirTex.xyz - 0.5 ) );
o.vIndirectDiffuse.rgb += vBakedIndirectColor.rgb * flHalfLambert / (bakedIndirTex.w);
}
float flHalfLambert = dot(vNormalWs.xyz, normalize(bakedIndirTex.xyz - 0.5));// + ( 1.0 - length( bakedIndirTex.xyz - 0.5 ) );
o.vIndirectDiffuse.rgb += vBakedIndirectColor.rgb * flHalfLambert / (bakedIndirTex.w);
}
// Direct Specular
if (!g_bIndirectLightmaps)
{
UnityLight o_light;
o.vIndirectDiffuse.rgb += DecodeDirectionalSpecularLightmap(bakedColor, bakedDirTex, vNormalWs, false, 0, o_light);
// Direct Specular
if (!g_bIndirectLightmaps)
{
UnityLight o_light;
o.vIndirectDiffuse.rgb += DecodeDirectionalSpecularLightmap(bakedColor, bakedDirTex, vNormalWs, false, 0, o_light);
float4 vLightingTerms = ComputeDiffuseAndSpecularTerms(false, true,
vNormalWs.xyz, vEllipseUWs.xyz, vEllipseVWs.xyz,
o_light.dir.xyz, vPositionToCameraDirWs.xyz,
vDiffuseExponent.xy, vSpecularExponent.xy, vSpecularScale.xy, vReflectance.rgb, flFresnelExponent);
float4 vLightingTerms = ComputeDiffuseAndSpecularTerms(false, true,
vNormalWs.xyz, vEllipseUWs.xyz, vEllipseVWs.xyz,
o_light.dir.xyz, vPositionToCameraDirWs.xyz,
vDiffuseExponent.xy, vSpecularExponent.xy, vSpecularScale.xy, vReflectance.rgb, flFresnelExponent);
float3 vLightColor = o_light.color;
float3 vLightMask = vLightColor.rgb;
o.vSpecular.rgb += vLightingTerms.yzw * vLightMask.rgb;
}
float3 vLightColor = o_light.color;
float3 vLightMask = vLightColor.rgb;
o.vSpecular.rgb += vLightingTerms.yzw * vLightMask.rgb;
}
// Indirect Specular
//if ( 1 )
//{
// UnityLight o_light;
// o.vIndirectSpecular.rgb += DecodeDirectionalSpecularLightmap( vBakedIndirectColor, bakedIndirTex, vNormalWs, false, 0, o_light );
//}
}
// Indirect Specular
//if ( 1 )
//{
// UnityLight o_light;
// o.vIndirectSpecular.rgb += DecodeDirectionalSpecularLightmap( vBakedIndirectColor, bakedIndirTex, vNormalWs, false, 0, o_light );
//}
}
}
}
{
// Light probe
o.vIndirectDiffuse.rgb += ShadeSH9(float4(vNormalWs.xyz, 1.0));
}
{
// Light probe
o.vIndirectDiffuse.rgb += ShadeSH9(float4(vNormalWs.xyz, 1.0));
}
{
float4 realtimeColorTex = Tex2DLevel(unity_DynamicLightmap, vLightmapUV.zw, 0.0);
float3 realtimeColor = DecodeRealtimeLightmap(realtimeColorTex);
{
float4 realtimeColorTex = Tex2DLevel(unity_DynamicLightmap, vLightmapUV.zw, 0.0);
float3 realtimeColor = DecodeRealtimeLightmap(realtimeColorTex);
{
o.vIndirectDiffuse.rgb += realtimeColor.rgb;
}
{
o.vIndirectDiffuse.rgb += realtimeColor.rgb;
}
{
float4 realtimeDirTex = Tex2DLevelFromSampler(unity_DynamicDirectionality, unity_DynamicLightmap, vLightmapUV.zw, 0.0);
o.vIndirectDiffuse.rgb += DecodeDirectionalLightmap(realtimeColor, realtimeDirTex, vNormalWs);
}
{
float4 realtimeDirTex = Tex2DLevelFromSampler(unity_DynamicDirectionality, unity_DynamicLightmap, vLightmapUV.zw, 0.0);
o.vIndirectDiffuse.rgb += DecodeDirectionalLightmap(realtimeColor, realtimeDirTex, vNormalWs);
}
{
float4 realtimeDirTex = Tex2DLevelFromSampler(unity_DynamicDirectionality, unity_DynamicLightmap, vLightmapUV.zw, 0.0);
o.vIndirectDiffuse.rgb += DecodeDirectionalLightmap(realtimeColor, realtimeDirTex, vNormalWs);
{
float4 realtimeDirTex = Tex2DLevelFromSampler(unity_DynamicDirectionality, unity_DynamicLightmap, vLightmapUV.zw, 0.0);
o.vIndirectDiffuse.rgb += DecodeDirectionalLightmap(realtimeColor, realtimeDirTex, vNormalWs);
UnityLight o_light;
float4 realtimeNormalTex = Tex2DLevelFromSampler(unity_DynamicNormal, unity_DynamicLightmap, vLightmapUV.zw, 0.0);
o.vIndirectSpecular.rgb += DecodeDirectionalSpecularLightmap(realtimeColor, realtimeDirTex, vNormalWs, true, realtimeNormalTex, o_light);
UnityLight o_light;
float4 realtimeNormalTex = Tex2DLevelFromSampler(unity_DynamicNormal, unity_DynamicLightmap, vLightmapUV.zw, 0.0);
o.vIndirectSpecular.rgb += DecodeDirectionalSpecularLightmap(realtimeColor, realtimeDirTex, vNormalWs, true, realtimeNormalTex, o_light);
float4 vLightingTerms = ComputeDiffuseAndSpecularTerms(false, true,
vNormalWs.xyz, vEllipseUWs.xyz, vEllipseVWs.xyz,
o_light.dir.xyz, vPositionToCameraDirWs.xyz,
vDiffuseExponent.xy, vSpecularExponent.xy, vSpecularScale.xy, vReflectance.rgb, flFresnelExponent);
float4 vLightingTerms = ComputeDiffuseAndSpecularTerms(false, true,
vNormalWs.xyz, vEllipseUWs.xyz, vEllipseVWs.xyz,
o_light.dir.xyz, vPositionToCameraDirWs.xyz,
vDiffuseExponent.xy, vSpecularExponent.xy, vSpecularScale.xy, vReflectance.rgb, flFresnelExponent);
float3 vLightColor = o_light.color;
float3 vLightMask = vLightColor.rgb;
o.vSpecular.rgb += vLightingTerms.yzw * vLightMask.rgb;
}
float3 vLightColor = o_light.color;
float3 vLightMask = vLightColor.rgb;
o.vSpecular.rgb += vLightingTerms.yzw * vLightMask.rgb;
}
}
}
//-------------------//
// Indirect specular //
//-------------------//
//-------------------//
// Indirect specular //
//-------------------//
{
float flRoughness = dot(vRoughness.xy, float2(0.5, 0.5));
{
float flRoughness = dot(vRoughness.xy, float2(0.5, 0.5));
float3 vReflectionDirWs = CalculateCameraReflectionDirWs(vPositionWs.xyz, vNormalWs.xyz);
float3 vReflectionDirWs0 = vReflectionDirWs.xyz;
float3 vReflectionDirWs = CalculateCameraReflectionDirWs(vPositionWs.xyz, vNormalWs.xyz);
float3 vReflectionDirWs0 = vReflectionDirWs.xyz;
{
vReflectionDirWs0.xyz = BoxProjectedCubemapDirection(vReflectionDirWs.xyz, vPositionWs.xyz, unity_SpecCube0_ProbePosition, unity_SpecCube0_BoxMin, unity_SpecCube0_BoxMax);
}
{
vReflectionDirWs0.xyz = BoxProjectedCubemapDirection(vReflectionDirWs.xyz, vPositionWs.xyz, unity_SpecCube0_ProbePosition, unity_SpecCube0_BoxMin, unity_SpecCube0_BoxMax);
}
float3 vEnvMap0 = max(0.0, Unity_GlossyEnvironment(UNITY_PASS_TEXCUBE(unity_SpecCube0), unity_SpecCube0_HDR, vReflectionDirWs0, flRoughness));
float3 vEnvMap0 = max(0.0, Unity_GlossyEnvironment(UNITY_PASS_TEXCUBE(unity_SpecCube0), unity_SpecCube0_HDR, vReflectionDirWs0, flRoughness));
{
const float flBlendFactor = 0.99999;
float flBlendLerp = saturate(unity_SpecCube0_BoxMin.w);
UNITY_BRANCH
if (flBlendLerp < flBlendFactor)
{
float3 vReflectionDirWs1 = vReflectionDirWs.xyz;
{
const float flBlendFactor = 0.99999;
float flBlendLerp = saturate(unity_SpecCube0_BoxMin.w);
UNITY_BRANCH
if (flBlendLerp < flBlendFactor)
{
float3 vReflectionDirWs1 = vReflectionDirWs.xyz;
{
vReflectionDirWs1.xyz = BoxProjectedCubemapDirection(vReflectionDirWs.xyz, vPositionWs.xyz, unity_SpecCube1_ProbePosition, unity_SpecCube1_BoxMin, unity_SpecCube1_BoxMax);
}
{
vReflectionDirWs1.xyz = BoxProjectedCubemapDirection(vReflectionDirWs.xyz, vPositionWs.xyz, unity_SpecCube1_ProbePosition, unity_SpecCube1_BoxMin, unity_SpecCube1_BoxMax);
}
float3 vEnvMap1 = max(0.0, Unity_GlossyEnvironment(UNITY_PASS_TEXCUBE(unity_SpecCube1), unity_SpecCube1_HDR, vReflectionDirWs1, flRoughness));
o.vIndirectSpecular.rgb += lerp(vEnvMap1.rgb, vEnvMap0.rgb, flBlendLerp);
}
else
{
o.vIndirectSpecular.rgb += vEnvMap0.rgb;
}
}
float3 vEnvMap1 = max(0.0, Unity_GlossyEnvironment(UNITY_PASS_TEXCUBE(unity_SpecCube1), unity_SpecCube1_HDR, vReflectionDirWs1, flRoughness));
o.vIndirectSpecular.rgb += lerp(vEnvMap1.rgb, vEnvMap0.rgb, flBlendLerp);
}
else
{
o.vIndirectSpecular.rgb += vEnvMap0.rgb;
}
}
{
o.vIndirectSpecular.rgb += vEnvMap0.rgb;
}
{
o.vIndirectSpecular.rgb += vEnvMap0.rgb;
}
}
}
// Apply fresnel to indirect specular
float flVDotN = saturate(dot(vPositionToCameraDirWs.xyz, vNormalWs.xyz));
float3 vMaxReflectance = vReflectance.rgb / (Luminance(vReflectance.rgb) + 0.0001);
float3 vFresnel = lerp(vReflectance.rgb, vMaxReflectance.rgb, pow(1.0 - flVDotN, flFresnelExponent));
// Apply fresnel to indirect specular
float flVDotN = saturate(dot(vPositionToCameraDirWs.xyz, vNormalWs.xyz));
float3 vMaxReflectance = vReflectance.rgb / (Luminance(vReflectance.rgb) + 0.0001);
float3 vFresnel = lerp(vReflectance.rgb, vMaxReflectance.rgb, pow(1.0 - flVDotN, flFresnelExponent));
o.vIndirectSpecular.rgb *= vFresnel.rgb;
o.vIndirectSpecular.rgb *= g_flCubeMapScalar; // !!! FIXME: This also contains lightmap spec
o.vIndirectSpecular.rgb *= vFresnel.rgb;
o.vIndirectSpecular.rgb *= g_flCubeMapScalar; // !!! FIXME: This also contains lightmap spec
// Since we have indirect specular, apply reflectance to indirect diffuse
o.vIndirectDiffuse.rgb *= (float3(1.0, 1.0, 1.0) - vReflectance.rgb);
// Since we have indirect specular, apply reflectance to indirect diffuse
o.vIndirectDiffuse.rgb *= (float3(1.0, 1.0, 1.0) - vReflectance.rgb);
return o;
return o;
LightingTerms_t lightingTerms = ComputeLighting(vPositionWs, vNormalWs, vTangentUWs, vTangentVWs, vRoughness, 0.0, 1.0, vLightmapUV.xyzw);
LightingTerms_t lightingTerms = ComputeLighting(vPositionWs, vNormalWs, vTangentUWs, vTangentVWs, vRoughness, 0.0, 1.0, vLightmapUV.xyzw);
lightingTerms.vSpecular = float3(0.0, 0.0, 0.0);
lightingTerms.vIndirectSpecular = float3(0.0, 0.0, 0.0);
lightingTerms.vSpecular = float3(0.0, 0.0, 0.0);
lightingTerms.vIndirectSpecular = float3(0.0, 0.0, 0.0);
return lightingTerms;
return lightingTerms;
float3 vCameraToPositionRayCubemapLocal = vPositionCubemapLocal.xyz - vCameraPositionCubemapLocal.xyz;
float3 vCameraToPositionRayReflectedCubemapLocal = reflect(vCameraToPositionRayCubemapLocal.xyz, vNormalCubemapLocal.xyz);
float3 vCameraToPositionRayCubemapLocal = vPositionCubemapLocal.xyz - vCameraPositionCubemapLocal.xyz;
float3 vCameraToPositionRayReflectedCubemapLocal = reflect(vCameraToPositionRayCubemapLocal.xyz, vNormalCubemapLocal.xyz);
float3 vIntersectA = (vBoxMaxs.xyz - vPositionCubemapLocal.xyz) / vCameraToPositionRayReflectedCubemapLocal.xyz;
float3 vIntersectB = (vBoxMins.xyz - vPositionCubemapLocal.xyz) / vCameraToPositionRayReflectedCubemapLocal.xyz;
float3 vIntersectA = (vBoxMaxs.xyz - vPositionCubemapLocal.xyz) / vCameraToPositionRayReflectedCubemapLocal.xyz;
float3 vIntersectB = (vBoxMins.xyz - vPositionCubemapLocal.xyz) / vCameraToPositionRayReflectedCubemapLocal.xyz;
float3 vIntersect = max(vIntersectA.xyz, vIntersectB.xyz);
float flDistance = min(vIntersect.x, min(vIntersect.y, vIntersect.z));
float3 vIntersect = max(vIntersectA.xyz, vIntersectB.xyz);
float flDistance = min(vIntersect.x, min(vIntersect.y, vIntersect.z));
float3 vReflectDirectionWs = vPositionCubemapLocal.xyz + vCameraToPositionRayReflectedCubemapLocal.xyz * flDistance;
float3 vReflectDirectionWs = vPositionCubemapLocal.xyz + vCameraToPositionRayReflectedCubemapLocal.xyz * flDistance;
return vReflectDirectionWs;
return vReflectDirectionWs;
}
#endif

1001
Assets/ScriptableRenderLoop/ForwardRenderLoop/Shaders/vr_standard.shader
文件差异内容过多而无法显示
查看文件

332
Assets/ScriptableRenderLoop/ForwardRenderLoop/Shaders/vr_utils.cginc


//---------------------------------------------------------------------------------------------------------------------------------------------------------
float3 ScreenSpaceDither( float2 vScreenPos )
{
//if ( Blink( 1.5 ) )
// return 0.0;
//if ( Blink( 1.5 ) )
// return 0.0;
//if ( ( int )vScreenPos.y == 840 )
// return 0.3;
//if ( vScreenPos.y < 840 )
// return 0.0;
//if ( ( int )vScreenPos.y == 840 )
// return 0.3;
//if ( vScreenPos.y < 840 )
// return 0.0;
float3 vDither = dot( float2( 171.0, 231.0 ), vScreenPos.xy + g_flTime.xx ).xxx;
vDither.rgb = frac( vDither.rgb / float3( 103.0, 71.0, 97.0 ) ) - float3( 0.5, 0.5, 0.5 );
return ( vDither.rgb / 255.0 ) * 0.375;
float3 vDither = dot( float2( 171.0, 231.0 ), vScreenPos.xy + g_flTime.xx ).xxx;
vDither.rgb = frac( vDither.rgb / float3( 103.0, 71.0, 97.0 ) ) - float3( 0.5, 0.5, 0.5 );
return ( vDither.rgb / 255.0 ) * 0.375;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

{
return step( 0.5, frac( g_flTime * 0.5 / flNumSeconds ) );
return step( 0.5, frac( g_flTime * 0.5 / flNumSeconds ) );
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

{
float3 vVectorTs;
vVectorTs.x = dot( vVectorWs.xyz, vTangentUWs.xyz );
vVectorTs.y = dot( vVectorWs.xyz, vTangentVWs.xyz );
vVectorTs.z = dot( vVectorWs.xyz, vNormalWs.xyz );
return vVectorTs.xyz; // Return without normalizing
float3 vVectorTs;
vVectorTs.x = dot( vVectorWs.xyz, vTangentUWs.xyz );
vVectorTs.y = dot( vVectorWs.xyz, vTangentVWs.xyz );
vVectorTs.z = dot( vVectorWs.xyz, vNormalWs.xyz );
return vVectorTs.xyz; // Return without normalizing
return normalize( Vec3WsToTs( vVectorWs.xyz, vNormalWs.xyz, vTangentUWs.xyz, vTangentVWs.xyz ) );
return normalize( Vec3WsToTs( vVectorWs.xyz, vNormalWs.xyz, vTangentUWs.xyz, vTangentVWs.xyz ) );
float3 vVectorWs;
vVectorWs.xyz = vVectorTs.x * vTangentUWs.xyz;
vVectorWs.xyz += vVectorTs.y * vTangentVWs.xyz;
vVectorWs.xyz += vVectorTs.z * vNormalWs.xyz;
return vVectorWs.xyz; // Return without normalizing
float3 vVectorWs;
vVectorWs.xyz = vVectorTs.x * vTangentUWs.xyz;
vVectorWs.xyz += vVectorTs.y * vTangentVWs.xyz;
vVectorWs.xyz += vVectorTs.z * vNormalWs.xyz;
return vVectorWs.xyz; // Return without normalizing
return normalize( Vec3TsToWs( vVectorTs.xyz, vNormalWs.xyz, vTangentUWs.xyz, vTangentVWs.xyz ) );
return normalize( Vec3TsToWs( vVectorTs.xyz, vNormalWs.xyz, vTangentUWs.xyz, vTangentVWs.xyz ) );
return normalize( cross( vTangentUWs.xyz, vNormalWs.xyz ) ) * flTangentFlip;
return normalize( cross( vTangentUWs.xyz, vNormalWs.xyz ) ) * flTangentFlip;
// Rotate and scale the unit square back to the center diamond
vHemiOct.xy = ( vHemiOct.xy * 2.0 ) - 1.0;
float2 temp = float2( vHemiOct.x + vHemiOct.y, vHemiOct.x - vHemiOct.y ) * 0.5;
float3 v = float3( temp.xy, 1.0 - abs( temp.x ) - abs( temp.y ) );
return normalize( v );
// Rotate and scale the unit square back to the center diamond
vHemiOct.xy = ( vHemiOct.xy * 2.0 ) - 1.0;
float2 temp = float2( vHemiOct.x + vHemiOct.y, vHemiOct.x - vHemiOct.y ) * 0.5;
float3 v = float3( temp.xy, 1.0 - abs( temp.x ) - abs( temp.y ) );
return normalize( v );
}
// Defines ----------------------------------------------------------------------------------------------------------------------------------------------------

//-------------------------------------------------------------------------------------------------------------------------------------------------------------
float MAX( float flA, float flB )
{
return max( flA, flB );
return max( flA, flB );
return min( flA, flB );
return min( flA, flB );
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

{
float3 vResult;
float3 vResult;
//[flatten]
if ( length( vVec.xyz ) == 0.0 )
{
vResult.xyz = float3( 0.0, 0.0, 0.0 );
}
else
{
vResult.xyz = normalize( vVec.xyz );
}
//[flatten]
if ( length( vVec.xyz ) == 0.0 )
{
vResult.xyz = float3( 0.0, 0.0, 0.0 );
}
else
{
vResult.xyz = normalize( vVec.xyz );
}
return vResult.xyz;
return vResult.xyz;
float2 vResult;
float2 vResult;
//[flatten]
if ( length( vVec.xy ) == 0.0 )
{
vResult.xy = float2( 0.0, 0.0 );
}
else
{
vResult.xy = normalize( vVec.xy );
}
//[flatten]
if ( length( vVec.xy ) == 0.0 )
{
vResult.xy = float2( 0.0, 0.0 );
}
else
{
vResult.xy = normalize( vVec.xy );
}
return vResult.xy;
return vResult.xy;
return max( 0.0, flValue );
return max( 0.0, flValue );
return max( float2( 0.0, 0.0 ), vValue.xy );
return max( float2( 0.0, 0.0 ), vValue.xy );
return max( float3( 0.0, 0.0, 0.0 ), vValue.xyz );
return max( float3( 0.0, 0.0, 0.0 ), vValue.xyz );
return max( float4( 0.0, 0.0, 0.0, 0.0 ), vValue.xyzw );
return max( float4( 0.0, 0.0, 0.0, 0.0 ), vValue.xyzw );
return saturate( ( flInput - flMin ) / ( flMax - flMin ) );
return saturate( ( flInput - flMin ) / ( flMax - flMin ) );
return ( flComparand >= 0.0 ) ? flValGE : flLT;
return ( flComparand >= 0.0 ) ? flValGE : flLT;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

{
// Put the old val into 0-1 range based on the old min/max
float flValNormalized = ( flOldVal - flOldMin ) / ( flOldMax - flOldMin );
// Put the old val into 0-1 range based on the old min/max
float flValNormalized = ( flOldVal - flOldMin ) / ( flOldMax - flOldMin );
// Map 0-1 range into new min/max
return ( flValNormalized * ( flNewMax - flNewMin ) ) + flNewMin;
// Map 0-1 range into new min/max
return ( flValNormalized * ( flNewMax - flNewMin ) ) + flNewMin;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

{
// Put the old val into 0-1 range based on the old min/max
float flValNormalized = saturate( ( flOldVal - flOldMin ) / ( flOldMax - flOldMin ) );
// Put the old val into 0-1 range based on the old min/max
float flValNormalized = saturate( ( flOldVal - flOldMin ) / ( flOldMax - flOldMin ) );
// Map 0-1 range into new min/max
return ( flValNormalized * ( flNewMax - flNewMin ) ) + flNewMin;
// Map 0-1 range into new min/max
return ( flValNormalized * ( flNewMax - flNewMin ) ) + flNewMin;
return ( ( vValue.xyzw * 0.5 ) + 0.5 );
return ( ( vValue.xyzw * 0.5 ) + 0.5 );
return ( ( vValue.xyz * 0.5 ) + 0.5 );
return ( ( vValue.xyz * 0.5 ) + 0.5 );
return ( ( vValue.xy * 0.5 ) + 0.5 );
return ( ( vValue.xy * 0.5 ) + 0.5 );
return ( ( flValue * 0.5 ) + 0.5 );
return ( ( flValue * 0.5 ) + 0.5 );
return ( ( cColor.xyzw * 2.0 ) - 1.0 );
return ( ( cColor.xyzw * 2.0 ) - 1.0 );
return ( ( cColor.xyz * 2.0 ) - 1.0 );
return ( ( cColor.xyz * 2.0 ) - 1.0 );
return ( ( cColor.xy * 2.0 ) - 1.0 );
return ( ( cColor.xy * 2.0 ) - 1.0 );
return ( ( flColor * 2.0 ) - 1.0 );
return ( ( flColor * 2.0 ) - 1.0 );
// Formula for calculating luminance based on NTSC standard
float3 tmpv = float3( 0.2125, 0.7154, 0.0721 );
float flLuminance = dot( cColor.rgb, tmpv.rgb );
// Formula for calculating luminance based on NTSC standard
float3 tmpv = float3( 0.2125, 0.7154, 0.0721 );
float flLuminance = dot( cColor.rgb, tmpv.rgb );
// Alternate formula for calculating luminance for linear RGB space (Widely used in color hue and saturation computations)
//float3 tmpv = float3( 0.3086, 0.6094, 0.0820 );;
//float flLuminance = dot( cColor.rgb, tmpv.rgb );
// Alternate formula for calculating luminance for linear RGB space (Widely used in color hue and saturation computations)
//float3 tmpv = float3( 0.3086, 0.6094, 0.0820 );;
//float flLuminance = dot( cColor.rgb, tmpv.rgb );
// Simple average
//float3 tmpv = float3( 0.333, 0.333, 0.333 );
//float flLuminance = dot( cColor.rgb, tmpv.rgb );
// Simple average
//float3 tmpv = float3( 0.333, 0.333, 0.333 );
//float flLuminance = dot( cColor.rgb, tmpv.rgb );
return flLuminance;
return flLuminance;
float lum = Luminance( cColor.rgb );
return lerp( float3( lum, lum, lum ), cColor.rgb, flTargetSaturation.xxx );
float lum = Luminance( cColor.rgb );
return lerp( float3( lum, lum, lum ), cColor.rgb, flTargetSaturation.xxx );
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

{
return pow( vLinear, 0.5 );
return pow( vLinear, 0.5 );
return pow( vLinear.rgb, float3( 0.5, 0.5, 0.5 ) );
return pow( vLinear.rgb, float3( 0.5, 0.5, 0.5 ) );
return float4( pow( vLinear.rgb, float3( 0.5, 0.5, 0.5 ) ), vLinear.a );
return float4( pow( vLinear.rgb, float3( 0.5, 0.5, 0.5 ) ), vLinear.a );
return vGamma * vGamma;
return vGamma * vGamma;
return vGamma.rgb * vGamma.rgb;
return vGamma.rgb * vGamma.rgb;
return float4( vGamma.rgb * vGamma.rgb, vGamma.a );
return float4( vGamma.rgb * vGamma.rgb, vGamma.a );
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

{
return pow( vLinear, 0.454545454545455 );
return pow( vLinear, 0.454545454545455 );
return pow( vLinear.rgb, float3( 0.454545454545455, 0.454545454545455, 0.454545454545455 ) );
return pow( vLinear.rgb, float3( 0.454545454545455, 0.454545454545455, 0.454545454545455 ) );
return float4( pow( vLinear.rgb, float3( 0.454545454545455, 0.454545454545455, 0.454545454545455 ) ), vLinear.a );
return float4( pow( vLinear.rgb, float3( 0.454545454545455, 0.454545454545455, 0.454545454545455 ) ), vLinear.a );
return pow( vGamma, 2.2 );
return pow( vGamma, 2.2 );
return pow( vGamma.rgb, float3( 2.2, 2.2, 2.2 ) );
return pow( vGamma.rgb, float3( 2.2, 2.2, 2.2 ) );
return float4( pow( vGamma.rgb, float3( 2.2, 2.2, 2.2 ) ), vGamma.a );
return float4( pow( vGamma.rgb, float3( 2.2, 2.2, 2.2 ) ), vGamma.a );
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

{
// 15 asm instructions
float3 vLinearSegment = vSrgbGammaColor.rgb / 12.92;
float3 vExpSegment = pow( ( ( vSrgbGammaColor.rgb / 1.055 ) + ( 0.055 / 1.055 ) ), float3( 2.4, 2.4, 2.4 ) );
// 15 asm instructions
float3 vLinearSegment = vSrgbGammaColor.rgb / 12.92;
float3 vExpSegment = pow( ( ( vSrgbGammaColor.rgb / 1.055 ) + ( 0.055 / 1.055 ) ), float3( 2.4, 2.4, 2.4 ) );
float3 vLinearColor = float3( ( vSrgbGammaColor.r <= 0.04045 ) ? vLinearSegment.r : vExpSegment.r,
( vSrgbGammaColor.g <= 0.04045 ) ? vLinearSegment.g : vExpSegment.g,
( vSrgbGammaColor.b <= 0.04045 ) ? vLinearSegment.b : vExpSegment.b );
float3 vLinearColor = float3( ( vSrgbGammaColor.r <= 0.04045 ) ? vLinearSegment.r : vExpSegment.r,
( vSrgbGammaColor.g <= 0.04045 ) ? vLinearSegment.g : vExpSegment.g,
( vSrgbGammaColor.b <= 0.04045 ) ? vLinearSegment.b : vExpSegment.b );
return vLinearColor.rgb;
return vLinearColor.rgb;
// 15 asm instructions
float3 vLinearSegment = vLinearColor.rgb * 12.92;
float3 vExpSegment = ( 1.055 * pow( vLinearColor.rgb, float3 ( 1.0 / 2.4, 1.0 / 2.4, 1.0 / 2.4 ) ) ) - 0.055;
// 15 asm instructions
float3 vLinearSegment = vLinearColor.rgb * 12.92;
float3 vExpSegment = ( 1.055 * pow( vLinearColor.rgb, float3 ( 1.0 / 2.4, 1.0 / 2.4, 1.0 / 2.4 ) ) ) - 0.055;
float3 vGammaColor = float3( ( vLinearColor.r <= 0.0031308 ) ? vLinearSegment.r : vExpSegment.r,
( vLinearColor.g <= 0.0031308 ) ? vLinearSegment.g : vExpSegment.g,
( vLinearColor.b <= 0.0031308 ) ? vLinearSegment.b : vExpSegment.b );
float3 vGammaColor = float3( ( vLinearColor.r <= 0.0031308 ) ? vLinearSegment.r : vExpSegment.r,
( vLinearColor.g <= 0.0031308 ) ? vLinearSegment.g : vExpSegment.g,
( vLinearColor.b <= 0.0031308 ) ? vLinearSegment.b : vExpSegment.b );
return vGammaColor.rgb;
return vGammaColor.rgb;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

{
vLinearColor.rgb = sqrt( vLinearColor.rgb );
vLinearColor.rgb = saturate( vLinearColor.rgb * ( 1.0 / 6.0 ) );
vLinearColor.rgb = sqrt( vLinearColor.rgb );
vLinearColor.rgb = saturate( vLinearColor.rgb * ( 1.0 / 6.0 ) );
float4 vRGBM;
float4 vRGBM;
vRGBM.a = max( max( vLinearColor.r, vLinearColor.g ), max( vLinearColor.b, 1.0 / 6.0 ) );
vRGBM.a = ceil( vRGBM.a * 255.0 ) / 255.0;
vRGBM.rgb = vLinearColor.rgb / vRGBM.a;
vRGBM.a = max( max( vLinearColor.r, vLinearColor.g ), max( vLinearColor.b, 1.0 / 6.0 ) );
vRGBM.a = ceil( vRGBM.a * 255.0 ) / 255.0;
vRGBM.rgb = vLinearColor.rgb / vRGBM.a;
return vRGBM;
return vRGBM;
float3 vLinearColor = vRGBM.rgb * 6.0 * vRGBM.a;
float3 vLinearColor = vRGBM.rgb * 6.0 * vRGBM.a;
vLinearColor.rgb *= vLinearColor.rgb;
vLinearColor.rgb *= vLinearColor.rgb;
return vLinearColor.rgb;
return vLinearColor.rgb;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

{
return ( ( vNormal.xy * 2.0 ) - 1.0 );
return ( ( vNormal.xy * 2.0 ) - 1.0 );
return ( ( vNormal.xy * 0.5 ) + 0.5 );
return ( ( vNormal.xy * 0.5 ) + 0.5 );
return ( ( vNormal.xyz * 2.0 ) - 1.0 );
return ( ( vNormal.xyz * 2.0 ) - 1.0 );
return ( ( vNormal.xyz * 0.5 ) + 0.5 );
return ( ( vNormal.xyz * 0.5 ) + 0.5 );
float3 vNormalTs;
float3 vNormalTs;
vNormalTs.xy = vXY.xy;
vNormalTs.z = sqrt( saturate( 1.0 - dot( vNormalTs.xy, vNormalTs.xy ) ) );
vNormalTs.xy = vXY.xy;
vNormalTs.z = sqrt( saturate( 1.0 - dot( vNormalTs.xy, vNormalTs.xy ) ) );
return vNormalTs.xyz;
return vNormalTs.xyz;
float3 vNormalTs;
float3 vNormalTs;
vNormalTs.xy = UnpackNormal2D( vRGPixel.rg );
vNormalTs.z = sqrt( saturate( 1.0 - dot( vNormalTs.xy, vNormalTs.xy ) ) );
vNormalTs.xy = UnpackNormal2D( vRGPixel.rg );
vNormalTs.z = sqrt( saturate( 1.0 - dot( vNormalTs.xy, vNormalTs.xy ) ) );
return vNormalTs.xyz;
return vNormalTs.xyz;
return ComputeNormalFromRGTexture( vDXT5Pixel.ag );
return ComputeNormalFromRGTexture( vDXT5Pixel.ag );
float2 sincosTheta;
sincos( vSpherical.x * M_PI, sincosTheta.x, sincosTheta.y );
float2 sincosPhi = float2( sqrt( 1.0 - ( vSpherical.y * vSpherical.y ) ), vSpherical.y );
float2 sincosTheta;
sincos( vSpherical.x * M_PI, sincosTheta.x, sincosTheta.y );
float2 sincosPhi = float2( sqrt( 1.0 - ( vSpherical.y * vSpherical.y ) ), vSpherical.y );
return float3( sincosTheta.y * sincosPhi.x, sincosTheta.x * sincosPhi.x, sincosPhi.y );
return float3( sincosTheta.y * sincosPhi.x, sincosTheta.x * sincosPhi.x, sincosPhi.y );
// TODO: atan2 isn't defined at 0,0. Is this a problem?
float flAtanYX = atan2( vNormal.y, vNormal.x ) / M_PI;
// TODO: atan2 isn't defined at 0,0. Is this a problem?
float flAtanYX = atan2( vNormal.y, vNormal.x ) / M_PI;
return PackToColor( float2( flAtanYX, vNormal.z ) );
return PackToColor( float2( flAtanYX, vNormal.z ) );
float2 vUnpackedSpherical = UnpackNormal2D( vRGPixel.rg );
float2 vUnpackedSpherical = UnpackNormal2D( vRGPixel.rg );
return ConvertSphericalToNormal( vUnpackedSpherical.xy );
return ConvertSphericalToNormal( vUnpackedSpherical.xy );
return ( vPositionWs.xyz - g_vCameraPositionWs.xyz );
return ( vPositionWs.xyz - g_vCameraPositionWs.xyz );
return normalize( CalculateCameraToPositionRayWs( vPositionWs.xyz ) );
return normalize( CalculateCameraToPositionRayWs( vPositionWs.xyz ) );
float3 vViewVectorWs = CalculateCameraToPositionRayWs( vPositionWs.xyz ); // Not normalized
return Vec3WsToTs( vViewVectorWs.xyz, vTangentUWs.xyz, vTangentVWs.xyz, vNormalWs.xyz ); // Not Normalized
float3 vViewVectorWs = CalculateCameraToPositionRayWs( vPositionWs.xyz ); // Not normalized
return Vec3WsToTs( vViewVectorWs.xyz, vTangentUWs.xyz, vTangentVWs.xyz, vNormalWs.xyz ); // Not Normalized
return normalize( CalculateCameraToPositionRayTs( vPositionWs.xyz, vTangentUWs.xyz, vTangentVWs.xyz, vNormalWs.xyz ) );
return normalize( CalculateCameraToPositionRayTs( vPositionWs.xyz, vTangentUWs.xyz, vTangentVWs.xyz, vNormalWs.xyz ) );
// TODO!
return CalculateCameraToPositionRayWs( vPositionWs.xyz );
//return ( vPositionWs.xyz - g_vCameraPositionWsMultiview[ nView ].xyz );
// TODO!
return CalculateCameraToPositionRayWs( vPositionWs.xyz );
//return ( vPositionWs.xyz - g_vCameraPositionWsMultiview[ nView ].xyz );
return normalize( CalculateCameraToPositionRayWsMultiview( nView, vPositionWs.xyz ) );
return normalize( CalculateCameraToPositionRayWsMultiview( nView, vPositionWs.xyz ) );
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------

{
return -CalculateCameraToPositionRayWs( vPositionWs.xyz );
return -CalculateCameraToPositionRayWs( vPositionWs.xyz );
return -CalculateCameraToPositionDirWs( vPositionWs.xyz );
return -CalculateCameraToPositionDirWs( vPositionWs.xyz );
return -CalculateCameraToPositionRayTs( vPositionWs.xyz, vTangentUWs.xyz, vTangentVWs.xyz, vNormalWs.xyz );
return -CalculateCameraToPositionRayTs( vPositionWs.xyz, vTangentUWs.xyz, vTangentVWs.xyz, vNormalWs.xyz );
return -CalculateCameraToPositionDirTs( vPositionWs.xyz, vTangentUWs.xyz, vTangentVWs.xyz, vNormalWs.xyz );
return -CalculateCameraToPositionDirTs( vPositionWs.xyz, vTangentUWs.xyz, vTangentVWs.xyz, vNormalWs.xyz );
return -CalculateCameraToPositionRayWsMultiview( nView, vPositionWs.xyz );
return -CalculateCameraToPositionRayWsMultiview( nView, vPositionWs.xyz );
return -CalculateCameraToPositionDirWsMultiview( nView, vPositionWs.xyz );
return -CalculateCameraToPositionDirWsMultiview( nView, vPositionWs.xyz );
float3 vViewVectorWs = CalculateCameraToPositionDirWs( vPositionWs.xyz );
float3 vReflectionVectorWs = reflect( vViewVectorWs.xyz, vNormalWs.xyz );
return vReflectionVectorWs.xyz;
float3 vViewVectorWs = CalculateCameraToPositionDirWs( vPositionWs.xyz );
float3 vReflectionVectorWs = reflect( vViewVectorWs.xyz, vNormalWs.xyz );
return vReflectionVectorWs.xyz;
float3 vViewVectorWs = CalculateCameraToPositionDirWsMultiview( nView, vPositionWs.xyz );
float3 vReflectionVectorWs = reflect( vViewVectorWs.xyz, vNormalWs.xyz );
return vReflectionVectorWs.xyz;
float3 vViewVectorWs = CalculateCameraToPositionDirWsMultiview( nView, vPositionWs.xyz );
float3 vReflectionVectorWs = reflect( vViewVectorWs.xyz, vNormalWs.xyz );
return vReflectionVectorWs.xyz;
return length( g_vCameraPositionWs.xyz - vPositionWs.xyz );
return length( g_vCameraPositionWs.xyz - vPositionWs.xyz );
}
#endif

995
Assets/ScriptableRenderLoop/ForwardRenderLoop/ValveMenuTools.cs
文件差异内容过多而无法显示
查看文件

987
Assets/ScriptableRenderLoop/ForwardRenderLoop/ValveShaderGUI.cs


// Copyright (c) Valve Corporation, All rights reserved. ======================================================================================================
#if ( UNITY_EDITOR )
#if (UNITY_EDITOR)
using System;
using System.Collections.Generic;

{
internal class ValveShaderGUI : ShaderGUI
{
public enum BlendMode
{
Opaque,
AlphaTest,
AlphaBlend,
Glass,
Additive
// TODO: MaskedGlass that will require an additional grayscale texture to act as a standard alpha blend mask
}
internal class ValveShaderGUI : ShaderGUI
{
public enum BlendMode
{
Opaque,
AlphaTest,
AlphaBlend,
Glass,
Additive
// TODO: MaskedGlass that will require an additional grayscale texture to act as a standard alpha blend mask
}
public enum SpecularMode
{
None,
BlinnPhong,
Metallic
//Anisotropic
}
public enum SpecularMode
{
None,
BlinnPhong,
Metallic
//Anisotropic
}
private static class Styles
{
public static GUIStyle optionsButton = "PaneOptions";
public static GUIContent uvSetLabel = new GUIContent("UV Set");
public static GUIContent[] uvSetOptions = new GUIContent[] { new GUIContent("UV channel 0"), new GUIContent("UV channel 1") };
private static class Styles
{
public static GUIStyle optionsButton = "PaneOptions";
public static GUIContent uvSetLabel = new GUIContent("UV Set");
public static GUIContent[] uvSetOptions = new GUIContent[] { new GUIContent("UV channel 0"), new GUIContent("UV channel 1") };
public static GUIContent unlitText = new GUIContent( "Unlit", "" );
public static GUIContent unlitText = new GUIContent("Unlit", "");
public static string emptyTootip = "";
public static GUIContent albedoText = new GUIContent("Albedo", "Albedo (RGB) and Transparency (A)");
public static GUIContent alphaCutoffText = new GUIContent("Alpha Cutoff", "Threshold for alpha cutoff");
public static GUIContent specularMapText = new GUIContent("Specular", "Reflectance (RGB) and Gloss (A)");
public static GUIContent reflectanceMinText = new GUIContent( "Reflectance Min", "" );
public static GUIContent reflectanceMaxText = new GUIContent( "Reflectance Max", "" );
public static GUIContent metallicMapText = new GUIContent( "Metallic", "Metallic (R) and Gloss (A)" );
public static GUIContent smoothnessText = new GUIContent("Gloss", "");
public static GUIContent normalMapText = new GUIContent("Normal", "Normal Map");
//public static GUIContent heightMapText = new GUIContent("Height Map", "Height Map (G)");
public static GUIContent cubeMapScalarText = new GUIContent( "Cube Map Scalar", "" );
public static GUIContent occlusionText = new GUIContent("Occlusion", "Occlusion (G)");
public static GUIContent occlusionStrengthDirectDiffuseText = new GUIContent( "Occlusion Direct Diffuse", "" );
public static GUIContent occlusionStrengthDirectSpecularText = new GUIContent( "Occlusion Direct Specular", "" );
public static GUIContent occlusionStrengthIndirectDiffuseText = new GUIContent( "Occlusion Indirect Diffuse", "" );
public static GUIContent occlusionStrengthIndirectSpecularText = new GUIContent( "Occlusion Indirect Specular", "" );
public static GUIContent emissionText = new GUIContent( "Emission", "Emission (RGB)" );
public static GUIContent detailMaskText = new GUIContent("Detail Mask", "Mask for Secondary Maps (A)");
public static GUIContent detailAlbedoText = new GUIContent("Detail Albedo", "Detail Albedo (RGB) multiplied by 2");
public static GUIContent detailNormalMapText = new GUIContent("Detail Normal", "Detail Normal Map");
public static GUIContent overrideLightmapText = new GUIContent( "Override Lightmap", "Requires ValveOverrideLightmap.cs scrip on object" );
public static GUIContent worldAlignedTextureText = new GUIContent( "World Aligned Texture", "" );
public static GUIContent worldAlignedTextureSizeText = new GUIContent( "Size", "" );
public static GUIContent worldAlignedTextureNormalText = new GUIContent( "Normal", "" );
public static GUIContent worldAlignedTexturePositionText = new GUIContent( "World Position", "" );
public static string emptyTootip = "";
public static GUIContent albedoText = new GUIContent("Albedo", "Albedo (RGB) and Transparency (A)");
public static GUIContent alphaCutoffText = new GUIContent("Alpha Cutoff", "Threshold for alpha cutoff");
public static GUIContent specularMapText = new GUIContent("Specular", "Reflectance (RGB) and Gloss (A)");
public static GUIContent reflectanceMinText = new GUIContent("Reflectance Min", "");
public static GUIContent reflectanceMaxText = new GUIContent("Reflectance Max", "");
public static GUIContent metallicMapText = new GUIContent("Metallic", "Metallic (R) and Gloss (A)");
public static GUIContent smoothnessText = new GUIContent("Gloss", "");
public static GUIContent normalMapText = new GUIContent("Normal", "Normal Map");
//public static GUIContent heightMapText = new GUIContent("Height Map", "Height Map (G)");
public static GUIContent cubeMapScalarText = new GUIContent("Cube Map Scalar", "");
public static GUIContent occlusionText = new GUIContent("Occlusion", "Occlusion (G)");
public static GUIContent occlusionStrengthDirectDiffuseText = new GUIContent("Occlusion Direct Diffuse", "");
public static GUIContent occlusionStrengthDirectSpecularText = new GUIContent("Occlusion Direct Specular", "");
public static GUIContent occlusionStrengthIndirectDiffuseText = new GUIContent("Occlusion Indirect Diffuse", "");
public static GUIContent occlusionStrengthIndirectSpecularText = new GUIContent("Occlusion Indirect Specular", "");
public static GUIContent emissionText = new GUIContent("Emission", "Emission (RGB)");
public static GUIContent detailMaskText = new GUIContent("Detail Mask", "Mask for Secondary Maps (A)");
public static GUIContent detailAlbedoText = new GUIContent("Detail Albedo", "Detail Albedo (RGB) multiplied by 2");
public static GUIContent detailNormalMapText = new GUIContent("Detail Normal", "Detail Normal Map");
public static GUIContent overrideLightmapText = new GUIContent("Override Lightmap", "Requires ValveOverrideLightmap.cs scrip on object");
public static GUIContent worldAlignedTextureText = new GUIContent("World Aligned Texture", "");
public static GUIContent worldAlignedTextureSizeText = new GUIContent("Size", "");
public static GUIContent worldAlignedTextureNormalText = new GUIContent("Normal", "");
public static GUIContent worldAlignedTexturePositionText = new GUIContent("World Position", "");
public static string whiteSpaceString = " ";
public static string primaryMapsText = "Main Maps";
public static string secondaryMapsText = "Secondary Maps";
public static string renderingMode = "Rendering Mode";
public static string specularModeText = "Specular Mode";
public static GUIContent emissiveWarning = new GUIContent( "Emissive value is animated but the material has not been configured to support emissive. Please make sure the material itself has some amount of emissive." );
public static GUIContent emissiveColorWarning = new GUIContent ("Ensure emissive color is non-black for emission to have effect.");
public static readonly string[] blendNames = Enum.GetNames (typeof (BlendMode));
public static readonly string[] specularNames = Enum.GetNames( typeof( SpecularMode ) );
}
public static string whiteSpaceString = " ";
public static string primaryMapsText = "Main Maps";
public static string secondaryMapsText = "Secondary Maps";
public static string renderingMode = "Rendering Mode";
public static string specularModeText = "Specular Mode";
public static GUIContent emissiveWarning = new GUIContent("Emissive value is animated but the material has not been configured to support emissive. Please make sure the material itself has some amount of emissive.");
public static GUIContent emissiveColorWarning = new GUIContent("Ensure emissive color is non-black for emission to have effect.");
public static readonly string[] blendNames = Enum.GetNames(typeof(BlendMode));
public static readonly string[] specularNames = Enum.GetNames(typeof(SpecularMode));
}
MaterialProperty unlit = null;
MaterialProperty blendMode = null;
MaterialProperty specularMode = null;
MaterialProperty albedoMap = null;
MaterialProperty albedoColor = null;
MaterialProperty alphaCutoff = null;
MaterialProperty specularMap = null;
MaterialProperty specularColor = null;
MaterialProperty reflectanceMin = null;
MaterialProperty reflectanceMax = null;
MaterialProperty metallicMap = null;
MaterialProperty metallic = null;
MaterialProperty smoothness = null;
MaterialProperty bumpScale = null;
MaterialProperty bumpMap = null;
MaterialProperty cubeMapScalar = null;
MaterialProperty occlusionStrength = null;
MaterialProperty occlusionMap = null;
MaterialProperty occlusionStrengthDirectDiffuse = null;
MaterialProperty occlusionStrengthDirectSpecular = null;
MaterialProperty occlusionStrengthIndirectDiffuse = null;
MaterialProperty occlusionStrengthIndirectSpecular = null;
//MaterialProperty heigtMapScale = null;
//MaterialProperty heightMap = null;
MaterialProperty emissionColorForRendering = null;
MaterialProperty emissionMap = null;
MaterialProperty detailMask = null;
MaterialProperty detailAlbedoMap = null;
MaterialProperty detailNormalMapScale = null;
MaterialProperty detailNormalMap = null;
MaterialProperty uvSetSecondary = null;
MaterialProperty overrideLightmap = null;
MaterialProperty worldAlignedTexture = null;
MaterialProperty worldAlignedTextureSize = null;
MaterialProperty worldAlignedTextureNormal = null;
MaterialProperty worldAlignedTexturePosition = null;
MaterialProperty unlit = null;
MaterialProperty blendMode = null;
MaterialProperty specularMode = null;
MaterialProperty albedoMap = null;
MaterialProperty albedoColor = null;
MaterialProperty alphaCutoff = null;
MaterialProperty specularMap = null;
MaterialProperty specularColor = null;
MaterialProperty reflectanceMin = null;
MaterialProperty reflectanceMax = null;
MaterialProperty metallicMap = null;
MaterialProperty metallic = null;
MaterialProperty smoothness = null;
MaterialProperty bumpScale = null;
MaterialProperty bumpMap = null;
MaterialProperty cubeMapScalar = null;
MaterialProperty occlusionStrength = null;
MaterialProperty occlusionMap = null;
MaterialProperty occlusionStrengthDirectDiffuse = null;
MaterialProperty occlusionStrengthDirectSpecular = null;
MaterialProperty occlusionStrengthIndirectDiffuse = null;
MaterialProperty occlusionStrengthIndirectSpecular = null;
//MaterialProperty heigtMapScale = null;
//MaterialProperty heightMap = null;
MaterialProperty emissionColorForRendering = null;
MaterialProperty emissionMap = null;
MaterialProperty detailMask = null;
MaterialProperty detailAlbedoMap = null;
MaterialProperty detailNormalMapScale = null;
MaterialProperty detailNormalMap = null;
MaterialProperty uvSetSecondary = null;
MaterialProperty overrideLightmap = null;
MaterialProperty worldAlignedTexture = null;
MaterialProperty worldAlignedTextureSize = null;
MaterialProperty worldAlignedTextureNormal = null;
MaterialProperty worldAlignedTexturePosition = null;
MaterialEditor m_MaterialEditor;
ColorPickerHDRConfig m_ColorPickerHDRConfig = new ColorPickerHDRConfig(0f, 99f, 1/99f, 3f);
MaterialEditor m_MaterialEditor;
ColorPickerHDRConfig m_ColorPickerHDRConfig = new ColorPickerHDRConfig(0f, 99f, 1 / 99f, 3f);
bool m_FirstTimeApply = true;
bool m_FirstTimeApply = true;
public void FindProperties (MaterialProperty[] props)
{
unlit = FindProperty( "g_bUnlit", props );
blendMode = FindProperty( "_Mode", props );
specularMode = FindProperty( "_SpecularMode", props );
albedoMap = FindProperty( "_MainTex", props );
albedoColor = FindProperty ("_Color", props);
alphaCutoff = FindProperty ("_Cutoff", props);
specularMap = FindProperty ("_SpecGlossMap", props, false);
specularColor = FindProperty ("_SpecColor", props, false);
reflectanceMin = FindProperty( "g_flReflectanceMin", props );
reflectanceMax = FindProperty( "g_flReflectanceMax", props );
metallicMap = FindProperty ("_MetallicGlossMap", props, false);
metallic = FindProperty ("_Metallic", props, false);
smoothness = FindProperty ("_Glossiness", props);
bumpScale = FindProperty ("_BumpScale", props);
bumpMap = FindProperty ("_BumpMap", props);
//heigtMapScale = FindProperty ("_Parallax", props);
//heightMap = FindProperty("_ParallaxMap", props);
cubeMapScalar = FindProperty( "g_flCubeMapScalar", props );
occlusionStrength = FindProperty ("_OcclusionStrength", props);
occlusionStrengthDirectDiffuse = FindProperty( "_OcclusionStrengthDirectDiffuse", props );
occlusionStrengthDirectSpecular = FindProperty( "_OcclusionStrengthDirectSpecular", props );
occlusionStrengthIndirectDiffuse = FindProperty( "_OcclusionStrengthIndirectDiffuse", props );
occlusionStrengthIndirectSpecular = FindProperty( "_OcclusionStrengthIndirectSpecular", props );
occlusionMap = FindProperty ("_OcclusionMap", props);
emissionColorForRendering = FindProperty ("_EmissionColor", props);
emissionMap = FindProperty ("_EmissionMap", props);
detailMask = FindProperty ("_DetailMask", props);
detailAlbedoMap = FindProperty ("_DetailAlbedoMap", props);
detailNormalMapScale = FindProperty ("_DetailNormalMapScale", props);
detailNormalMap = FindProperty ("_DetailNormalMap", props);
uvSetSecondary = FindProperty ("_UVSec", props);
overrideLightmap = FindProperty( "g_tOverrideLightmap", props );
worldAlignedTexture = FindProperty( "g_bWorldAlignedTexture", props, false );
worldAlignedTextureSize = FindProperty( "g_vWorldAlignedTextureSize", props, worldAlignedTexture != null );
worldAlignedTextureNormal = FindProperty( "g_vWorldAlignedTextureNormal", props, worldAlignedTexture != null );
worldAlignedTexturePosition = FindProperty( "g_vWorldAlignedTexturePosition", props, worldAlignedTexture != null );
}
public void FindProperties(MaterialProperty[] props)
{
unlit = FindProperty("g_bUnlit", props);
blendMode = FindProperty("_Mode", props);
specularMode = FindProperty("_SpecularMode", props);
albedoMap = FindProperty("_MainTex", props);
albedoColor = FindProperty("_Color", props);
alphaCutoff = FindProperty("_Cutoff", props);
specularMap = FindProperty("_SpecGlossMap", props, false);
specularColor = FindProperty("_SpecColor", props, false);
reflectanceMin = FindProperty("g_flReflectanceMin", props);
reflectanceMax = FindProperty("g_flReflectanceMax", props);
metallicMap = FindProperty("_MetallicGlossMap", props, false);
metallic = FindProperty("_Metallic", props, false);
smoothness = FindProperty("_Glossiness", props);
bumpScale = FindProperty("_BumpScale", props);
bumpMap = FindProperty("_BumpMap", props);
//heigtMapScale = FindProperty ("_Parallax", props);
//heightMap = FindProperty("_ParallaxMap", props);
cubeMapScalar = FindProperty("g_flCubeMapScalar", props);
occlusionStrength = FindProperty("_OcclusionStrength", props);
occlusionStrengthDirectDiffuse = FindProperty("_OcclusionStrengthDirectDiffuse", props);
occlusionStrengthDirectSpecular = FindProperty("_OcclusionStrengthDirectSpecular", props);
occlusionStrengthIndirectDiffuse = FindProperty("_OcclusionStrengthIndirectDiffuse", props);
occlusionStrengthIndirectSpecular = FindProperty("_OcclusionStrengthIndirectSpecular", props);
occlusionMap = FindProperty("_OcclusionMap", props);
emissionColorForRendering = FindProperty("_EmissionColor", props);
emissionMap = FindProperty("_EmissionMap", props);
detailMask = FindProperty("_DetailMask", props);
detailAlbedoMap = FindProperty("_DetailAlbedoMap", props);
detailNormalMapScale = FindProperty("_DetailNormalMapScale", props);
detailNormalMap = FindProperty("_DetailNormalMap", props);
uvSetSecondary = FindProperty("_UVSec", props);
overrideLightmap = FindProperty("g_tOverrideLightmap", props);
worldAlignedTexture = FindProperty("g_bWorldAlignedTexture", props, false);
worldAlignedTextureSize = FindProperty("g_vWorldAlignedTextureSize", props, worldAlignedTexture != null);
worldAlignedTextureNormal = FindProperty("g_vWorldAlignedTextureNormal", props, worldAlignedTexture != null);
worldAlignedTexturePosition = FindProperty("g_vWorldAlignedTexturePosition", props, worldAlignedTexture != null);
}
public override void OnGUI (MaterialEditor materialEditor, MaterialProperty[] props)
{
FindProperties (props); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly
m_MaterialEditor = materialEditor;
Material material = materialEditor.target as Material;
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
{
FindProperties(props); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly
m_MaterialEditor = materialEditor;
Material material = materialEditor.target as Material;
ShaderPropertiesGUI (material);
ShaderPropertiesGUI(material);
// Make sure that needed keywords are set up if we're switching some existing
// material to a standard shader.
if (m_FirstTimeApply)
{
SetMaterialKeywords (material);
m_FirstTimeApply = false;
}
}
// Make sure that needed keywords are set up if we're switching some existing
// material to a standard shader.
if (m_FirstTimeApply)
{
SetMaterialKeywords(material);
m_FirstTimeApply = false;
}
}
public void Vector3GUI( GUIContent label, MaterialProperty materialProperty )
{
Vector4 v4 = materialProperty.vectorValue;
Vector3 v3 = EditorGUILayout.Vector3Field( label, new Vector3( v4.x, v4.y, v4.z ) );
materialProperty.vectorValue = new Vector4( v3.x, v3.y, v3.z, 0.0f );
}
public void Vector3GUI(GUIContent label, MaterialProperty materialProperty)
{
Vector4 v4 = materialProperty.vectorValue;
Vector3 v3 = EditorGUILayout.Vector3Field(label, new Vector3(v4.x, v4.y, v4.z));
materialProperty.vectorValue = new Vector4(v3.x, v3.y, v3.z, 0.0f);
}
public void ShaderPropertiesGUI (Material material)
{
// Use default labelWidth
EditorGUIUtility.labelWidth = 0f;
public void ShaderPropertiesGUI(Material material)
{
// Use default labelWidth
EditorGUIUtility.labelWidth = 0f;
// Detect any changes to the material
EditorGUI.BeginChangeCheck();
{
m_MaterialEditor.ShaderProperty( unlit, Styles.unlitText.text );
bool bUnlit = ( unlit.floatValue != 0.0f );
// Detect any changes to the material
EditorGUI.BeginChangeCheck();
{
m_MaterialEditor.ShaderProperty(unlit, Styles.unlitText.text);
bool bUnlit = (unlit.floatValue != 0.0f);
BlendModePopup();
BlendModePopup();
if ( !bUnlit )
{
SpecularModePopup();
}
if (!bUnlit)
{
SpecularModePopup();
}
EditorGUILayout.Space();
EditorGUILayout.Space();
//GUILayout.Label( Styles.primaryMapsText, EditorStyles.boldLabel );
DoAlbedoArea(material);
if (!bUnlit)
{
m_MaterialEditor.TexturePropertySingleLine(Styles.normalMapText, bumpMap, bumpMap.textureValue != null ? bumpScale : null);
DoSpecularMetallicArea(material);
m_MaterialEditor.TexturePropertySingleLine(Styles.occlusionText, occlusionMap, occlusionMap.textureValue != null ? occlusionStrength : null);
if (occlusionMap.textureValue != null)
{
m_MaterialEditor.ShaderProperty(occlusionStrengthDirectDiffuse, Styles.occlusionStrengthDirectDiffuseText.text, 2);
m_MaterialEditor.ShaderProperty(occlusionStrengthDirectSpecular, Styles.occlusionStrengthDirectSpecularText.text, 2);
m_MaterialEditor.ShaderProperty(occlusionStrengthIndirectDiffuse, Styles.occlusionStrengthIndirectDiffuseText.text, 2);
m_MaterialEditor.ShaderProperty(occlusionStrengthIndirectSpecular, Styles.occlusionStrengthIndirectSpecularText.text, 2);
}
m_MaterialEditor.ShaderProperty(cubeMapScalar, Styles.cubeMapScalarText.text, 0);
}
//m_MaterialEditor.TexturePropertySingleLine(Styles.heightMapText, heightMap, heightMap.textureValue != null ? heigtMapScale : null);
DoEmissionArea(material);
m_MaterialEditor.TexturePropertySingleLine(Styles.detailMaskText, detailMask);
if (!bUnlit)
{
m_MaterialEditor.TexturePropertySingleLine(Styles.overrideLightmapText, overrideLightmap);
}
EditorGUI.BeginChangeCheck(); // !!! AV - This is from Unity's script. Can these Begin/End calls be nested like this?
m_MaterialEditor.TextureScaleOffsetProperty(albedoMap);
if (EditorGUI.EndChangeCheck())
{
emissionMap.textureScaleAndOffset = albedoMap.textureScaleAndOffset; // Apply the main texture scale and offset to the emission texture as well, for Enlighten's sake
}
//GUILayout.Label( Styles.primaryMapsText, EditorStyles.boldLabel );
DoAlbedoArea( material );
if ( !bUnlit )
{
m_MaterialEditor.TexturePropertySingleLine( Styles.normalMapText, bumpMap, bumpMap.textureValue != null ? bumpScale : null );
DoSpecularMetallicArea( material );
m_MaterialEditor.TexturePropertySingleLine( Styles.occlusionText, occlusionMap, occlusionMap.textureValue != null ? occlusionStrength : null );
if ( occlusionMap.textureValue != null )
{
m_MaterialEditor.ShaderProperty( occlusionStrengthDirectDiffuse, Styles.occlusionStrengthDirectDiffuseText.text, 2 );
m_MaterialEditor.ShaderProperty( occlusionStrengthDirectSpecular, Styles.occlusionStrengthDirectSpecularText.text, 2 );
m_MaterialEditor.ShaderProperty( occlusionStrengthIndirectDiffuse, Styles.occlusionStrengthIndirectDiffuseText.text, 2 );
m_MaterialEditor.ShaderProperty( occlusionStrengthIndirectSpecular, Styles.occlusionStrengthIndirectSpecularText.text, 2 );
}
m_MaterialEditor.ShaderProperty( cubeMapScalar, Styles.cubeMapScalarText.text, 0 );
}
//m_MaterialEditor.TexturePropertySingleLine(Styles.heightMapText, heightMap, heightMap.textureValue != null ? heigtMapScale : null);
DoEmissionArea( material );
m_MaterialEditor.TexturePropertySingleLine( Styles.detailMaskText, detailMask );
if ( !bUnlit )
{
m_MaterialEditor.TexturePropertySingleLine( Styles.overrideLightmapText, overrideLightmap );
}
if (worldAlignedTexture != null)
{
m_MaterialEditor.ShaderProperty(worldAlignedTexture, Styles.worldAlignedTextureText.text);
EditorGUI.BeginChangeCheck(); // !!! AV - This is from Unity's script. Can these Begin/End calls be nested like this?
m_MaterialEditor.TextureScaleOffsetProperty( albedoMap );
if ( EditorGUI.EndChangeCheck() )
{
emissionMap.textureScaleAndOffset = albedoMap.textureScaleAndOffset; // Apply the main texture scale and offset to the emission texture as well, for Enlighten's sake
}
if (worldAlignedTexture.floatValue != 0.0f)
{
EditorGUI.indentLevel = 2;
Vector3GUI(Styles.worldAlignedTextureSizeText, worldAlignedTextureSize);
Vector3GUI(Styles.worldAlignedTextureNormalText, worldAlignedTextureNormal);
Vector3GUI(Styles.worldAlignedTexturePositionText, worldAlignedTexturePosition);
EditorGUI.indentLevel = 0;
}
}
if ( worldAlignedTexture != null )
{
m_MaterialEditor.ShaderProperty( worldAlignedTexture, Styles.worldAlignedTextureText.text );
EditorGUILayout.Space();
if ( worldAlignedTexture.floatValue != 0.0f )
{
EditorGUI.indentLevel = 2;
Vector3GUI( Styles.worldAlignedTextureSizeText, worldAlignedTextureSize );
Vector3GUI( Styles.worldAlignedTextureNormalText, worldAlignedTextureNormal );
Vector3GUI( Styles.worldAlignedTexturePositionText, worldAlignedTexturePosition );
EditorGUI.indentLevel = 0;
}
}
// Secondary properties
GUILayout.Label(Styles.secondaryMapsText, EditorStyles.boldLabel);
m_MaterialEditor.TexturePropertySingleLine(Styles.detailAlbedoText, detailAlbedoMap);
if (!bUnlit)
{
m_MaterialEditor.TexturePropertySingleLine(Styles.detailNormalMapText, detailNormalMap, detailNormalMapScale);
}
m_MaterialEditor.TextureScaleOffsetProperty(detailAlbedoMap);
m_MaterialEditor.ShaderProperty(uvSetSecondary, Styles.uvSetLabel.text);
}
if (EditorGUI.EndChangeCheck())
{
foreach (var obj in blendMode.targets)
{
MaterialChanged((Material)obj);
}
EditorGUILayout.Space();
foreach (var obj in specularMode.targets)
{
MaterialChanged((Material)obj);
}
}
}
// Secondary properties
GUILayout.Label( Styles.secondaryMapsText, EditorStyles.boldLabel );
m_MaterialEditor.TexturePropertySingleLine( Styles.detailAlbedoText, detailAlbedoMap );
if ( !bUnlit )
{
m_MaterialEditor.TexturePropertySingleLine( Styles.detailNormalMapText, detailNormalMap, detailNormalMapScale );
}
m_MaterialEditor.TextureScaleOffsetProperty( detailAlbedoMap );
m_MaterialEditor.ShaderProperty( uvSetSecondary, Styles.uvSetLabel.text );
}
if ( EditorGUI.EndChangeCheck() )
{
foreach ( var obj in blendMode.targets )
{
MaterialChanged( ( Material )obj );
}
public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)
{
base.AssignNewShaderToMaterial(material, oldShader, newShader);
foreach ( var obj in specularMode.targets )
{
MaterialChanged( ( Material )obj );
}
}
}
if (oldShader == null)
return;
public override void AssignNewShaderToMaterial (Material material, Shader oldShader, Shader newShader)
{
base.AssignNewShaderToMaterial( material, oldShader, newShader );
// Convert to vr_standard
if (newShader.name.Equals("Valve/vr_standard"))
{
List<string> unknownShaders = new List<string>();
ValveRefreshStandardShader.StandardToValveSingleMaterial(material, oldShader, newShader, false, unknownShaders);
}
if ( oldShader == null )
return;
// Legacy shaders
if (!oldShader.name.Contains("Legacy Shaders/"))
return;
// Convert to vr_standard
if ( newShader.name.Equals( "Valve/vr_standard" ) )
{
List<string> unknownShaders = new List<string>();
ValveRefreshStandardShader.StandardToValveSingleMaterial( material, oldShader, newShader, false, unknownShaders );
}
BlendMode blendMode = BlendMode.Opaque;
if (oldShader.name.Contains("/Transparent/Cutout/"))
{
blendMode = BlendMode.AlphaTest;
}
else if (oldShader.name.Contains("/Transparent/"))
{
// NOTE: legacy shaders did not provide physically based transparency
// therefore Fade mode
blendMode = BlendMode.AlphaBlend;
}
material.SetFloat("_Mode", (float)blendMode);
// Legacy shaders
if ( !oldShader.name.Contains( "Legacy Shaders/" ) )
return;
MaterialChanged(material);
}
BlendMode blendMode = BlendMode.Opaque;
if (oldShader.name.Contains("/Transparent/Cutout/"))
{
blendMode = BlendMode.AlphaTest;
}
else if (oldShader.name.Contains("/Transparent/"))
{
// NOTE: legacy shaders did not provide physically based transparency
// therefore Fade mode
blendMode = BlendMode.AlphaBlend;
}
material.SetFloat("_Mode", (float)blendMode);
void BlendModePopup()
{
EditorGUI.showMixedValue = blendMode.hasMixedValue;
var mode = (BlendMode)blendMode.floatValue;
MaterialChanged(material);
}
EditorGUI.BeginChangeCheck();
mode = (BlendMode)EditorGUILayout.Popup(Styles.renderingMode, (int)mode, Styles.blendNames);
if (EditorGUI.EndChangeCheck())
{
m_MaterialEditor.RegisterPropertyChangeUndo("Rendering Mode");
blendMode.floatValue = (float)mode;
}
void BlendModePopup()
{
EditorGUI.showMixedValue = blendMode.hasMixedValue;
var mode = (BlendMode)blendMode.floatValue;
EditorGUI.showMixedValue = false;
}
EditorGUI.BeginChangeCheck();
mode = (BlendMode)EditorGUILayout.Popup(Styles.renderingMode, (int)mode, Styles.blendNames);
if (EditorGUI.EndChangeCheck())
{
m_MaterialEditor.RegisterPropertyChangeUndo("Rendering Mode");
blendMode.floatValue = (float)mode;
}
void SpecularModePopup()
{
EditorGUI.showMixedValue = specularMode.hasMixedValue;
var mode = (SpecularMode)specularMode.floatValue;
EditorGUI.showMixedValue = false;
}
EditorGUI.BeginChangeCheck();
mode = (SpecularMode)EditorGUILayout.Popup(Styles.specularModeText, (int)mode, Styles.specularNames);
if (EditorGUI.EndChangeCheck())
{
m_MaterialEditor.RegisterPropertyChangeUndo("Specular Mode");
specularMode.floatValue = (float)mode;
}
void SpecularModePopup()
{
EditorGUI.showMixedValue = specularMode.hasMixedValue;
var mode = ( SpecularMode )specularMode.floatValue;
EditorGUI.showMixedValue = false;
}
EditorGUI.BeginChangeCheck();
mode = ( SpecularMode )EditorGUILayout.Popup( Styles.specularModeText, ( int )mode, Styles.specularNames );
if ( EditorGUI.EndChangeCheck() )
{
m_MaterialEditor.RegisterPropertyChangeUndo( "Specular Mode" );
specularMode.floatValue = ( float )mode;
}
void DoAlbedoArea(Material material)
{
m_MaterialEditor.TexturePropertySingleLine(Styles.albedoText, albedoMap, albedoColor);
if (((BlendMode)material.GetFloat("_Mode") == BlendMode.AlphaTest))
{
m_MaterialEditor.ShaderProperty(alphaCutoff, Styles.alphaCutoffText.text, MaterialEditor.kMiniTextureFieldLabelIndentLevel + 1);
}
}
EditorGUI.showMixedValue = false;
}
void DoEmissionArea(Material material)
{
float brightness = emissionColorForRendering.colorValue.maxColorComponent;
bool showHelpBox = !HasValidEmissiveKeyword(material);
bool showEmissionColorAndGIControls = brightness > 0.0f;
void DoAlbedoArea(Material material)
{
m_MaterialEditor.TexturePropertySingleLine(Styles.albedoText, albedoMap, albedoColor);
if (((BlendMode)material.GetFloat("_Mode") == BlendMode.AlphaTest))
{
m_MaterialEditor.ShaderProperty(alphaCutoff, Styles.alphaCutoffText.text, MaterialEditor.kMiniTextureFieldLabelIndentLevel+1);
}
}
bool hadEmissionTexture = emissionMap.textureValue != null;
void DoEmissionArea(Material material)
{
float brightness = emissionColorForRendering.colorValue.maxColorComponent;
bool showHelpBox = !HasValidEmissiveKeyword(material);
bool showEmissionColorAndGIControls = brightness > 0.0f;
bool hadEmissionTexture = emissionMap.textureValue != null;
// Texture and HDR color controls
m_MaterialEditor.TexturePropertyWithHDRColor(Styles.emissionText, emissionMap, emissionColorForRendering, m_ColorPickerHDRConfig, false);
// Texture and HDR color controls
m_MaterialEditor.TexturePropertyWithHDRColor(Styles.emissionText, emissionMap, emissionColorForRendering, m_ColorPickerHDRConfig, false);
// If texture was assigned and color was black set color to white
if (emissionMap.textureValue != null && !hadEmissionTexture && brightness <= 0f)
emissionColorForRendering.colorValue = Color.white;
// If texture was assigned and color was black set color to white
if (emissionMap.textureValue != null && !hadEmissionTexture && brightness <= 0f)
emissionColorForRendering.colorValue = Color.white;
// Dynamic Lightmapping mode
if (showEmissionColorAndGIControls)
{
bool shouldEmissionBeEnabled = ShouldEmissionBeEnabled(emissionColorForRendering.colorValue);
using (new EditorGUI.DisabledScope(!shouldEmissionBeEnabled))
{
m_MaterialEditor.LightmapEmissionProperty(MaterialEditor.kMiniTextureFieldLabelIndentLevel + 1);
}
}
// Dynamic Lightmapping mode
if (showEmissionColorAndGIControls)
{
bool shouldEmissionBeEnabled = ShouldEmissionBeEnabled(emissionColorForRendering.colorValue);
using ( new EditorGUI.DisabledScope( !shouldEmissionBeEnabled ) )
{
m_MaterialEditor.LightmapEmissionProperty( MaterialEditor.kMiniTextureFieldLabelIndentLevel + 1 );
}
}
if (showHelpBox)
{
EditorGUILayout.HelpBox(Styles.emissiveWarning.text, MessageType.Warning);
}
}
if (showHelpBox)
{
EditorGUILayout.HelpBox(Styles.emissiveWarning.text, MessageType.Warning);
}
}
void DoSpecularMetallicArea(Material material)
{
SpecularMode specularMode = (SpecularMode)material.GetInt("_SpecularMode");
if (specularMode == SpecularMode.BlinnPhong)
{
if (specularMap.textureValue == null)
{
m_MaterialEditor.TexturePropertyTwoLines(Styles.specularMapText, specularMap, specularColor, Styles.smoothnessText, smoothness);
}
else
{
m_MaterialEditor.TexturePropertySingleLine(Styles.specularMapText, specularMap);
m_MaterialEditor.ShaderProperty(reflectanceMin, Styles.reflectanceMinText.text, 2);
m_MaterialEditor.ShaderProperty(reflectanceMax, Styles.reflectanceMaxText.text, 2);
}
}
else if (specularMode == SpecularMode.Metallic)
{
if (metallicMap.textureValue == null)
m_MaterialEditor.TexturePropertyTwoLines(Styles.metallicMapText, metallicMap, metallic, Styles.smoothnessText, smoothness);
else
m_MaterialEditor.TexturePropertySingleLine(Styles.metallicMapText, metallicMap);
}
}
void DoSpecularMetallicArea( Material material )
{
SpecularMode specularMode = ( SpecularMode )material.GetInt( "_SpecularMode" );
if ( specularMode == SpecularMode.BlinnPhong )
{
if (specularMap.textureValue == null)
{
m_MaterialEditor.TexturePropertyTwoLines( Styles.specularMapText, specularMap, specularColor, Styles.smoothnessText, smoothness );
}
else
{
m_MaterialEditor.TexturePropertySingleLine( Styles.specularMapText, specularMap );
m_MaterialEditor.ShaderProperty( reflectanceMin, Styles.reflectanceMinText.text, 2 );
m_MaterialEditor.ShaderProperty( reflectanceMax, Styles.reflectanceMaxText.text, 2 );
}
}
else if ( specularMode == SpecularMode.Metallic )
{
if (metallicMap.textureValue == null)
m_MaterialEditor.TexturePropertyTwoLines(Styles.metallicMapText, metallicMap, metallic, Styles.smoothnessText, smoothness);
else
m_MaterialEditor.TexturePropertySingleLine(Styles.metallicMapText, metallicMap);
}
}
public static void SetupMaterialWithBlendMode(Material material, BlendMode blendMode)
{
switch (blendMode)
{
case BlendMode.Opaque:
material.SetOverrideTag("RenderType", "");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.DisableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = -1;
break;
case BlendMode.AlphaTest:
material.SetOverrideTag("RenderType", "TransparentCutout");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.EnableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = 2450;
break;
case BlendMode.AlphaBlend:
material.SetOverrideTag("RenderType", "Transparent");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
material.SetInt("_ZWrite", 0);
material.DisableKeyword("_ALPHATEST_ON");
material.EnableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = 3000;
break;
case BlendMode.Glass:
material.SetOverrideTag("RenderType", "Transparent");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
material.SetInt("_ZWrite", 0);
material.DisableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = 3000;
break;
case BlendMode.Additive:
material.SetOverrideTag("RenderType", "Transparent");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_ZWrite", 0);
material.DisableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = 3000;
break;
}
}
public static void SetupMaterialWithBlendMode(Material material, BlendMode blendMode)
{
switch (blendMode)
{
case BlendMode.Opaque:
material.SetOverrideTag("RenderType", "");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.DisableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = -1;
break;
case BlendMode.AlphaTest:
material.SetOverrideTag("RenderType", "TransparentCutout");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.EnableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = 2450;
break;
case BlendMode.AlphaBlend:
material.SetOverrideTag("RenderType", "Transparent");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
material.SetInt("_ZWrite", 0);
material.DisableKeyword("_ALPHATEST_ON");
material.EnableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = 3000;
break;
case BlendMode.Glass:
material.SetOverrideTag("RenderType", "Transparent");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
material.SetInt("_ZWrite", 0);
material.DisableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = 3000;
break;
case BlendMode.Additive:
material.SetOverrideTag( "RenderType", "Transparent" );
material.SetInt( "_SrcBlend", ( int )UnityEngine.Rendering.BlendMode.One );
material.SetInt( "_DstBlend", ( int )UnityEngine.Rendering.BlendMode.One );
material.SetInt( "_ZWrite", 0 );
material.DisableKeyword( "_ALPHATEST_ON" );
material.DisableKeyword( "_ALPHABLEND_ON" );
material.DisableKeyword( "_ALPHAPREMULTIPLY_ON" );
material.renderQueue = 3000;
break;
}
}
static bool ShouldEmissionBeEnabled(Color color)
{
return color.maxColorComponent > (0.1f / 255.0f);
}
static bool ShouldEmissionBeEnabled (Color color)
{
return color.maxColorComponent > (0.1f / 255.0f);
}
static void SetMaterialKeywords(Material material)
{
// Note: keywords must be based on Material value not on MaterialProperty due to multi-edit & material animation
// (MaterialProperty value might come from renderer material property block)
SetKeyword(material, "_NORMALMAP", material.GetTexture("_BumpMap") || material.GetTexture("_DetailNormalMap"));
static void SetMaterialKeywords(Material material)
{
// Note: keywords must be based on Material value not on MaterialProperty due to multi-edit & material animation
// (MaterialProperty value might come from renderer material property block)
SetKeyword (material, "_NORMALMAP", material.GetTexture ("_BumpMap") || material.GetTexture ("_DetailNormalMap"));
SpecularMode specularMode = (SpecularMode)material.GetInt("_SpecularMode");
if (specularMode == SpecularMode.BlinnPhong)
{
SetKeyword(material, "_SPECGLOSSMAP", material.GetTexture("_SpecGlossMap"));
}
else if (specularMode == SpecularMode.Metallic)
{
SetKeyword(material, "_METALLICGLOSSMAP", material.GetTexture("_MetallicGlossMap"));
}
SetKeyword(material, "S_SPECULAR_NONE", specularMode == SpecularMode.None);
SetKeyword(material, "S_SPECULAR_BLINNPHONG", specularMode == SpecularMode.BlinnPhong);
SetKeyword(material, "S_SPECULAR_METALLIC", specularMode == SpecularMode.Metallic);
SetKeyword(material, "S_OCCLUSION", material.GetTexture("_OcclusionMap"));
SpecularMode specularMode = ( SpecularMode )material.GetInt( "_SpecularMode" );
if ( specularMode == SpecularMode.BlinnPhong )
{
SetKeyword( material, "_SPECGLOSSMAP", material.GetTexture( "_SpecGlossMap" ) );
}
else if ( specularMode == SpecularMode.Metallic )
{
SetKeyword( material, "_METALLICGLOSSMAP", material.GetTexture( "_MetallicGlossMap" ) );
}
SetKeyword( material, "S_SPECULAR_NONE", specularMode == SpecularMode.None );
SetKeyword( material, "S_SPECULAR_BLINNPHONG", specularMode == SpecularMode.BlinnPhong );
SetKeyword( material, "S_SPECULAR_METALLIC", specularMode == SpecularMode.Metallic );
SetKeyword( material, "S_OCCLUSION", material.GetTexture("_OcclusionMap") );
SetKeyword(material, "_PARALLAXMAP", material.GetTexture("_ParallaxMap"));
SetKeyword(material, "_DETAIL_MULX2", material.GetTexture("_DetailAlbedoMap") || material.GetTexture("_DetailNormalMap"));
SetKeyword(material, "S_OVERRIDE_LIGHTMAP", material.GetTexture("g_tOverrideLightmap"));
SetKeyword( material, "_PARALLAXMAP", material.GetTexture("_ParallaxMap"));
SetKeyword( material, "_DETAIL_MULX2", material.GetTexture("_DetailAlbedoMap") || material.GetTexture("_DetailNormalMap"));
SetKeyword( material, "S_OVERRIDE_LIGHTMAP", material.GetTexture( "g_tOverrideLightmap" ) );
SetKeyword( material, "S_UNLIT", material.GetInt( "g_bUnlit" ) == 1 );
SetKeyword( material, "S_WORLD_ALIGNED_TEXTURE", material.GetInt( "g_bWorldAlignedTexture" ) == 1 );
SetKeyword(material, "S_UNLIT", material.GetInt("g_bUnlit") == 1);
SetKeyword(material, "S_WORLD_ALIGNED_TEXTURE", material.GetInt("g_bWorldAlignedTexture") == 1);
bool shouldEmissionBeEnabled = ShouldEmissionBeEnabled (material.GetColor("_EmissionColor"));
SetKeyword (material, "_EMISSION", shouldEmissionBeEnabled);
bool shouldEmissionBeEnabled = ShouldEmissionBeEnabled(material.GetColor("_EmissionColor"));
SetKeyword(material, "_EMISSION", shouldEmissionBeEnabled);
// Setup lightmap emissive flags
MaterialGlobalIlluminationFlags flags = material.globalIlluminationFlags;
if ((flags & (MaterialGlobalIlluminationFlags.BakedEmissive | MaterialGlobalIlluminationFlags.RealtimeEmissive)) != 0)
{
flags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;
if (!shouldEmissionBeEnabled)
flags |= MaterialGlobalIlluminationFlags.EmissiveIsBlack;
// Setup lightmap emissive flags
MaterialGlobalIlluminationFlags flags = material.globalIlluminationFlags;
if ((flags & (MaterialGlobalIlluminationFlags.BakedEmissive | MaterialGlobalIlluminationFlags.RealtimeEmissive)) != 0)
{
flags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;
if (!shouldEmissionBeEnabled)
flags |= MaterialGlobalIlluminationFlags.EmissiveIsBlack;
material.globalIlluminationFlags = flags;
}
material.globalIlluminationFlags = flags;
}
// Reflectance constants
float flReflectanceMin = material.GetFloat( "g_flReflectanceMin" );
float flReflectanceMax = material.GetFloat( "g_flReflectanceMax" );
material.SetFloat( "g_flReflectanceScale", Mathf.Max( flReflectanceMin, flReflectanceMax ) - flReflectanceMin );
material.SetFloat( "g_flReflectanceBias", flReflectanceMin );
// World aligned texture constants
Vector4 worldAlignedTextureNormal = material.GetVector( "g_vWorldAlignedTextureNormal" );
Vector3 normal = new Vector3( worldAlignedTextureNormal.x, worldAlignedTextureNormal.y, worldAlignedTextureNormal.z );
normal = ( normal.sqrMagnitude > 0.0f ) ? normal : Vector3.up;
Vector3 tangentU = Vector3.zero, tangentV = Vector3.zero;
Vector3.OrthoNormalize( ref normal, ref tangentU, ref tangentV );
material.SetVector( "g_vWorldAlignedNormalTangentU", new Vector4( tangentU.x, tangentU.y, tangentU.z, 0.0f ) );
material.SetVector( "g_vWorldAlignedNormalTangentV", new Vector4( tangentV.x, tangentV.y, tangentV.z, 0.0f ) );
// Reflectance constants
float flReflectanceMin = material.GetFloat("g_flReflectanceMin");
float flReflectanceMax = material.GetFloat("g_flReflectanceMax");
material.SetFloat("g_flReflectanceScale", Mathf.Max(flReflectanceMin, flReflectanceMax) - flReflectanceMin);
material.SetFloat("g_flReflectanceBias", flReflectanceMin);
// Static combo skips
if ( material.GetInt( "g_bUnlit" ) == 1 )
{
material.DisableKeyword( "_NORMALMAP" );
material.EnableKeyword( "S_SPECULAR_NONE" );
material.DisableKeyword( "S_SPECULAR_BLINNPHONG" );
material.DisableKeyword( "S_SPECULAR_METALLIC" );
material.DisableKeyword( "_METALLICGLOSSMAP" );
material.DisableKeyword( "_SPECGLOSSMAP" );
material.DisableKeyword( "S_OVERRIDE_LIGHTMAP" );
}
}
// World aligned texture constants
Vector4 worldAlignedTextureNormal = material.GetVector("g_vWorldAlignedTextureNormal");
Vector3 normal = new Vector3(worldAlignedTextureNormal.x, worldAlignedTextureNormal.y, worldAlignedTextureNormal.z);
normal = (normal.sqrMagnitude > 0.0f) ? normal : Vector3.up;
Vector3 tangentU = Vector3.zero, tangentV = Vector3.zero;
Vector3.OrthoNormalize(ref normal, ref tangentU, ref tangentV);
material.SetVector("g_vWorldAlignedNormalTangentU", new Vector4(tangentU.x, tangentU.y, tangentU.z, 0.0f));
material.SetVector("g_vWorldAlignedNormalTangentV", new Vector4(tangentV.x, tangentV.y, tangentV.z, 0.0f));
bool HasValidEmissiveKeyword (Material material)
{
// Material animation might be out of sync with the material keyword.
// So if the emission support is disabled on the material, but the property blocks have a value that requires it, then we need to show a warning.
// (note: (Renderer MaterialPropertyBlock applies its values to emissionColorForRendering))
bool hasEmissionKeyword = material.IsKeywordEnabled ("_EMISSION");
if (!hasEmissionKeyword && ShouldEmissionBeEnabled (emissionColorForRendering.colorValue))
return false;
else
return true;
}
// Static combo skips
if (material.GetInt("g_bUnlit") == 1)
{
material.DisableKeyword("_NORMALMAP");
material.EnableKeyword("S_SPECULAR_NONE");
material.DisableKeyword("S_SPECULAR_BLINNPHONG");
material.DisableKeyword("S_SPECULAR_METALLIC");
material.DisableKeyword("_METALLICGLOSSMAP");
material.DisableKeyword("_SPECGLOSSMAP");
material.DisableKeyword("S_OVERRIDE_LIGHTMAP");
}
}
static void MaterialChanged(Material material)
{
SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat("_Mode"));
bool HasValidEmissiveKeyword(Material material)
{
// Material animation might be out of sync with the material keyword.
// So if the emission support is disabled on the material, but the property blocks have a value that requires it, then we need to show a warning.
// (note: (Renderer MaterialPropertyBlock applies its values to emissionColorForRendering))
bool hasEmissionKeyword = material.IsKeywordEnabled("_EMISSION");
if (!hasEmissionKeyword && ShouldEmissionBeEnabled(emissionColorForRendering.colorValue))
return false;
else
return true;
}
SetMaterialKeywords(material);
}
static void MaterialChanged(Material material)
{
SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat("_Mode"));
static void SetKeyword(Material m, string keyword, bool state)
{
if (state)
m.EnableKeyword (keyword);
else
m.DisableKeyword (keyword);
}
}
SetMaterialKeywords(material);
}
static void SetKeyword(Material m, string keyword, bool state)
{
if (state)
m.EnableKeyword(keyword);
else
m.DisableKeyword(keyword);
}
}
} // namespace UnityEditor
#endif

37
Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.cs


var instance = ScriptableObject.CreateInstance<HDRenderLoop>();
UnityEditor.AssetDatabase.CreateAsset(instance, m_HDRenderLoopPath);
}
#endif
public class GBufferManager

}
*/
public int gbufferCount { get; set; }
int[] IDs = new int[MaxGbuffer];
RenderTargetIdentifier[] RTIDs = new RenderTargetIdentifier[MaxGbuffer];

void OnEnable()
{
Rebuild ();
Rebuild();
Rebuild ();
Rebuild();
}
void ClearComputeBuffers()

void InitAndClearBuffer(Camera camera, RenderLoop renderLoop)
{
// We clear only the depth buffer, no need to clear the various color buffer as we overwrite them.
// We clear only the depth buffer, no need to clear the various color buffer as we overwrite them.
// Clear depth/stencil and init buffers
{
var cmd = new CommandBuffer();

cmd.Blit(null, new RenderTargetIdentifier(s_CameraColorBuffer), m_DebugViewMaterialGBuffer, 0);
renderLoop.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}
}
// Render forward transparent
{

// gbufferManager.BindBuffers(m_DeferredMaterial);
// TODO: Bind depth textures
var cmd = new CommandBuffer();
cmd.name = "Deferred Lighting Pass";
cmd.name = "Deferred Ligthing Pass";
cmd.Blit(null, new RenderTargetIdentifier(s_CameraColorBuffer), m_DeferredMaterial, 0);
renderLoop.ExecuteCommandBuffer(cmd);
cmd.Dispose();

// CAUTION: For IES as we inverse forward maybe this will need rotation.
l.up = light.light.transform.up;
l.right = light.light.transform.right;
l.diffuseScale = 1.0f;
l.specularScale = 1.0f;
l.shadowDimmer = 1.0f;

float cosSpotInnerHalfAngle = Mathf.Clamp(Mathf.Cos(spotAngle * 0.5f * innerConePercent * Mathf.Deg2Rad), 0.0f, 1.0f); // inner cone
float val = Mathf.Max(0.001f, (cosSpotInnerHalfAngle - cosSpotOuterHalfAngle));
l.angleScale = 1.0f / val;
l.angleOffset = -cosSpotOuterHalfAngle * l.angleScale;
l.angleScale = 1.0f / val;
l.angleOffset = -cosSpotOuterHalfAngle * l.angleScale;
}
else
{

// TODO...
foreach (var camera in cameras)
{
{
if (!CullResults.GetCullingParameters (camera, out cullingParams))
if (!CullResults.GetCullingParameters(camera, out cullingParams))
cullResults = CullResults.Cull (ref cullingParams, renderLoop);
cullResults = CullResults.Cull(ref cullingParams, renderLoop);
renderLoop.SetupCameraProperties (camera);
renderLoop.SetupCameraProperties(camera);
//UpdateLightConstants(cullResults.visibleLights /*, ref shadows */);
//UpdateLightConstants(cullResults.visibleLights /*, ref shadows */);
UpdatePunctualLights (cullResults.visibleLights);
UpdatePunctualLights(cullResults.visibleLights);
UpdateReflectionProbes(cullResults.visibleReflectionProbes);
InitAndClearBuffer(camera, renderLoop);

FinalPass(renderLoop);
}
renderLoop.Submit ();
renderLoop.Submit();
}
// Post effects

return features;
}
#endif
}
}

16
Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoopInspector.cs


public override void OnInspectorGUI()
{
HDRenderLoop renderLoop = target as HDRenderLoop;
if(renderLoop)
if (renderLoop)
{
HDRenderLoop.DebugParameters debugParameters = renderLoop.debugParameters;

{
String[] varyingNames = Enum.GetNames(typeof(HDRenderLoop.DebugViewVaryingMode));
String[] GBufferNames = Enum.GetNames(typeof(HDRenderLoop.DebugViewGbufferMode));
int num = 1 + varyingNames.Length
+ GBufferNames.Length
+ typeof(Builtin.BuiltinData).GetFields().Length
+ typeof(Lit.SurfaceData).GetFields().Length
+ typeof(Lit.BSDFData).GetFields().Length;
int num = 1 + varyingNames.Length
+ GBufferNames.Length
+ typeof(Builtin.BuiltinData).GetFields().Length
+ typeof(Lit.SurfaceData).GetFields().Length
+ typeof(Lit.BSDFData).GetFields().Length;
styles.debugViewMaterialStrings = new GUIContent[num];
styles.debugViewMaterialValues = new int[num];

debugParameters.displayOpaqueObjects = EditorGUILayout.Toggle(styles.displayOpaqueObjects, debugParameters.displayOpaqueObjects);
debugParameters.displayTransparentObjects = EditorGUILayout.Toggle(styles.displayTransparentObjects, debugParameters.displayTransparentObjects);
if(EditorGUI.EndChangeCheck())
if (EditorGUI.EndChangeCheck())
{
EditorUtility.SetDirty(renderLoop); // Repaint
}

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


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

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


Shader "Hidden/Unity/DebugViewMaterialGBuffer"
Shader "Hidden/Unity/DebugViewMaterialGBuffer"
{
SubShader
{

DECLARE_GBUFFER_BAKE_LIGHTING(_CameraGBufferTexture);
UNITY_DECLARE_TEX2D(_CameraDepthTexture);
float4 _ScreenSize;
int _DebugViewMaterial;
struct Attributes

16
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/LayeredLit.shader


// They are use to fill a SurfaceData. With a MaterialGraph this should not exist.
// Reminder. Color here are in linear but the UI (color picker) do the conversion sRGB to linear
_BaseColor0("BaseColor0", Color) = (1,1,1,1)
_BaseColor0("BaseColor0", Color) = (1,1,1,1)
_BaseColor1("BaseColor1", Color) = (1, 1, 1, 1)
_BaseColor2("BaseColor2", Color) = (1, 1, 1, 1)
_BaseColor3("BaseColor3", Color) = (1, 1, 1, 1)

_NormalMap3("NormalMap3", 2D) = "bump" {}
[Enum(TangentSpace, 0, ObjectSpace, 1)] _NormalMapSpace("NormalMap space", Float) = 0
_HeightMap0("HeightMap0", 2D) = "black" {}
_HeightMap1("HeightMap1", 2D) = "black" {}
_HeightMap2("HeightMap2", 2D) = "black" {}

_HeightBias2("Height Bias2", Float) = 0
_HeightBias3("Height Bias3", Float) = 0
[Enum(Parallax, 0, Displacement, 1)] _HeightMapMode("Heightmap usage", Float) = 0
[Enum(Parallax, 0, Displacement, 1)] _HeightMapMode("Heightmap usage", Float) = 0
_EmissiveColor0("EmissiveColor0", Color) = (0, 0, 0)
_EmissiveColor1("EmissiveColor1", Color) = (0, 0, 0)

_LayerMaskMap("LayerMaskMap", 2D) = "white" {}
[ToggleOff] _DistortionOnly("Distortion Only", Float) = 0.0
[ToggleOff] _DistortionDepthTest("Distortion Only", Float) = 0.0
[ToggleOff] _DistortionOnly("Distortion Only", Float) = 0.0
[ToggleOff] _DistortionDepthTest("Distortion Only", Float) = 0.0
[ToggleOff] _AlphaCutoffEnable("Alpha Cutoff Enable", Float) = 0.0

Cull [_CullMode]
HLSLPROGRAM
HLSLPROGRAM
#pragma vertex VertDefault
#pragma fragment FragDeferred

void FragDeferred( PackedVaryings packedInput,
void FragDeferred( PackedVaryings packedInput,
OUTPUT_GBUFFER(outGBuffer)
#ifdef VELOCITY_IN_GBUFFER
, OUTPUT_GBUFFER_VELOCITY(outGBuffer)

HLSLPROGRAM
#pragma vertex VertDefault
#pragma fragment FragForward
#pragma fragment FragForward
#if SHADER_STAGE_FRAGMENT

14
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/LayeredLitTemplate.hlsl


// Forward
struct Attributes
{
float3 positionOS : POSITION;
float3 normalOS : NORMAL;
float2 uv0 : TEXCOORD0;
float4 tangentOS : TANGENT;
float3 positionOS : POSITION;
float3 normalOS : NORMAL;
float2 uv0 : TEXCOORD0;
float4 tangentOS : TANGENT;
float4 color : TANGENT;
};

ComputeMaskWeights(maskValues, weights);
PROP_DECL(float3, baseColor);
PROP_SAMPLE(baseColor, _BaseColorMap, input.texCoord0, rgb);
PROP_SAMPLE(baseColor, _BaseColorMap, input.texCoord0, rgb);
PROP_MUL(baseColor, _BaseColor, rgb);
PROP_BLEND_COLOR(baseColor, weights);

#endif
#if defined(_DOUBLESIDED_LIGHTING_FLIP) || defined(_DOUBLESIDED_LIGHTING_MIRROR)
#ifdef _DOUBLESIDED_LIGHTING_FLIP
#ifdef _DOUBLESIDED_LIGHTING_FLIP
float3 oppositeNormalWS = -surfaceData.normalWS;
#else
// Mirror the normal with the plane define by vertex normal

PROP_ASSIGN_VALUE(ambientOcclusion, 1.0);
#endif
PROP_MUL(metalic, _Metalic, r);
PROP_BLEND_SCALAR(metalic, weights);
PROP_BLEND_SCALAR(ambientOcclusion, weights);

598
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/LayeredLitUI.cs


namespace UnityEditor
{
internal class LayeredLitGUI : LitGUI
{
private class Styles
internal class LayeredLitGUI : LitGUI
public readonly GUIContent[] materialLayerLabels =
private class Styles
public readonly GUIContent[] materialLayerLabels =
{
};
public readonly GUIContent syncButton = new GUIContent("Re-Synchronize Layers", "Re-synchronize all layers's properties with the referenced Material");
public readonly GUIContent layers = new GUIContent("Layers");
public readonly GUIContent layerMapMask = new GUIContent("Layer Mask", "Layer mask (multiplied by vertex color)");
public readonly GUIContent layerCount = new GUIContent("Layer Count", "Number of layers.");
}
};
public readonly GUIContent syncButton = new GUIContent("Re-Synchronize Layers", "Re-synchronize all layers's properties with the referenced Material");
public readonly GUIContent layers = new GUIContent("Layers");
public readonly GUIContent layerMapMask = new GUIContent("Layer Mask", "Layer mask (multiplied by vertex color)");
public readonly GUIContent layerCount = new GUIContent("Layer Count", "Number of layers.");
}
static Styles s_Styles = null;
private static Styles styles { get { if (s_Styles == null) s_Styles = new Styles(); return s_Styles; } }
static Styles s_Styles = null;
private static Styles styles { get { if (s_Styles == null) s_Styles = new Styles(); return s_Styles; } }
// Needed for json serialization to work
[Serializable]
internal struct SerializeableGUIDs
{
public string[] GUIDArray;
}
// Needed for json serialization to work
[Serializable]
internal struct SerializeableGUIDs
{
public string[] GUIDArray;
}
private const int kMaxLayerCount = 4;
private const int kSyncButtonWidth = 58;
private string kLayerMaskMap = "_LayerMaskMap";
private string kLayerCount = "_LayerCount";
private const int kMaxLayerCount = 4;
private const int kSyncButtonWidth = 58;
private string kLayerMaskMap = "_LayerMaskMap";
private string kLayerCount = "_LayerCount";
private Material[] m_MaterialLayers = new Material[kMaxLayerCount];
private Material[] m_MaterialLayers = new Material[kMaxLayerCount];
MaterialProperty layerCountProperty = null;
MaterialProperty layerMaskMapProperty = null;
MaterialProperty layerCountProperty = null;
MaterialProperty layerMaskMapProperty = null;
int layerCount
{
set { layerCountProperty.floatValue = (float)value; }
get { return (int)layerCountProperty.floatValue; }
}
int layerCount
{
set { layerCountProperty.floatValue = (float)value; }
get { return (int)layerCountProperty.floatValue; }
}
void SynchronizeAllLayersProperties()
{
for(int i = 0 ; i < layerCount; ++i)
void SynchronizeAllLayersProperties()
SynchronizeLayerProperties(i);
for (int i = 0; i < layerCount; ++i)
{
SynchronizeLayerProperties(i);
}
}
void SynchronizeLayerProperties(int layerIndex)
{
Material material = m_MaterialEditor.target as Material;
Material layerMaterial = m_MaterialLayers[layerIndex];
if(layerMaterial != null)
void SynchronizeLayerProperties(int layerIndex)
Shader layerShader = layerMaterial.shader;
int propertyCount = ShaderUtil.GetPropertyCount(layerShader);
for(int i = 0 ; i < propertyCount ; ++i)
Material material = m_MaterialEditor.target as Material;
Material layerMaterial = m_MaterialLayers[layerIndex];
if (layerMaterial != null)
string propertyName = ShaderUtil.GetPropertyName(layerShader, i);
string layerPropertyName = propertyName + layerIndex;
if(material.HasProperty(layerPropertyName))
Shader layerShader = layerMaterial.shader;
int propertyCount = ShaderUtil.GetPropertyCount(layerShader);
for (int i = 0; i < propertyCount; ++i)
ShaderUtil.ShaderPropertyType type = ShaderUtil.GetPropertyType(layerShader, i);
switch (type)
string propertyName = ShaderUtil.GetPropertyName(layerShader, i);
string layerPropertyName = propertyName + layerIndex;
if (material.HasProperty(layerPropertyName))
case ShaderUtil.ShaderPropertyType.Color:
ShaderUtil.ShaderPropertyType type = ShaderUtil.GetPropertyType(layerShader, i);
switch (type)
{
case ShaderUtil.ShaderPropertyType.Color:
case ShaderUtil.ShaderPropertyType.Float:
case ShaderUtil.ShaderPropertyType.Range:
case ShaderUtil.ShaderPropertyType.Float:
case ShaderUtil.ShaderPropertyType.Range:
case ShaderUtil.ShaderPropertyType.Vector:
case ShaderUtil.ShaderPropertyType.Vector:
case ShaderUtil.ShaderPropertyType.TexEnv:
case ShaderUtil.ShaderPropertyType.TexEnv:
}
}
void InitializeMaterialLayers(AssetImporter materialImporter)
{
if (materialImporter.userData != string.Empty)
void InitializeMaterialLayers(AssetImporter materialImporter)
SerializeableGUIDs layersGUID = JsonUtility.FromJson<SerializeableGUIDs>(materialImporter.userData);
if (layersGUID.GUIDArray.Length > 0)
if (materialImporter.userData != string.Empty)
m_MaterialLayers = new Material[layersGUID.GUIDArray.Length];
for (int i = 0; i < layersGUID.GUIDArray.Length; ++i)
SerializeableGUIDs layersGUID = JsonUtility.FromJson<SerializeableGUIDs>(materialImporter.userData);
if (layersGUID.GUIDArray.Length > 0)
m_MaterialLayers[i] = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(layersGUID.GUIDArray[i]), typeof(Material)) as Material;
m_MaterialLayers = new Material[layersGUID.GUIDArray.Length];
for (int i = 0; i < layersGUID.GUIDArray.Length; ++i)
{
m_MaterialLayers[i] = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(layersGUID.GUIDArray[i]), typeof(Material)) as Material;
}
}
void SaveMaterialLayers(AssetImporter materialImporter)
{
SerializeableGUIDs layersGUID;
layersGUID.GUIDArray = new string[m_MaterialLayers.Length];
for(int i = 0 ; i < m_MaterialLayers.Length; ++i)
void SaveMaterialLayers(AssetImporter materialImporter)
if (m_MaterialLayers[i] != null)
layersGUID.GUIDArray[i] = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(m_MaterialLayers[i].GetInstanceID()));
SerializeableGUIDs layersGUID;
layersGUID.GUIDArray = new string[m_MaterialLayers.Length];
for (int i = 0; i < m_MaterialLayers.Length; ++i)
{
if (m_MaterialLayers[i] != null)
layersGUID.GUIDArray[i] = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(m_MaterialLayers[i].GetInstanceID()));
}
materialImporter.userData = JsonUtility.ToJson(layersGUID);
materialImporter.userData = JsonUtility.ToJson(layersGUID);
}
bool CheckInputOptionConsistency(string optionName, string[] shortNames, ref string outValueNames)
{
bool result = true;
outValueNames = "";
for(int i = 0 ; i < layerCount ; ++i)
bool CheckInputOptionConsistency(string optionName, string[] shortNames, ref string outValueNames)
Material layer = m_MaterialLayers[i];
if (layer != null)
bool result = true;
outValueNames = "";
for (int i = 0; i < layerCount; ++i)
int currentValue = (int)layer.GetFloat(optionName); // All options are in fact enums
Debug.Assert(currentValue < shortNames.Length);
outValueNames += shortNames[currentValue] + " ";
for (int j = i + 1; j < layerCount; ++j)
Material layer = m_MaterialLayers[i];
if (layer != null)
Material otherLayer = m_MaterialLayers[j];
if(otherLayer != null)
int currentValue = (int)layer.GetFloat(optionName); // All options are in fact enums
Debug.Assert(currentValue < shortNames.Length);
outValueNames += shortNames[currentValue] + " ";
for (int j = i + 1; j < layerCount; ++j)
if(currentValue != (int)otherLayer.GetFloat(optionName))
Material otherLayer = m_MaterialLayers[j];
if (otherLayer != null)
result = false;
if (currentValue != (int)otherLayer.GetFloat(optionName))
{
result = false;
}
else
{
outValueNames += "X ";
}
else
{
outValueNames += "X ";
}
return result;
return result;
}
bool CheckInputMapConsistency(string mapName, ref string outValueNames)
{
bool result = true;
outValueNames = "";
for (int i = 0; i < layerCount; ++i)
bool CheckInputMapConsistency(string mapName, ref string outValueNames)
Material layer = m_MaterialLayers[i];
if (layer != null)
bool result = true;
outValueNames = "";
for (int i = 0; i < layerCount; ++i)
bool currentValue = layer.GetTexture(mapName) != null;
outValueNames += (currentValue ? "Y" : "N") + " ";
Material layer = m_MaterialLayers[i];
if (layer != null)
{
bool currentValue = layer.GetTexture(mapName) != null;
outValueNames += (currentValue ? "Y" : "N") + " ";
for (int j = i + 1; j < layerCount; ++j)
{
Material otherLayer = m_MaterialLayers[j];
if (otherLayer != null)
for (int j = i + 1; j < layerCount; ++j)
bool otherValue = otherLayer.GetTexture(mapName) != null;
if (currentValue != otherValue)
Material otherLayer = m_MaterialLayers[j];
if (otherLayer != null)
result = false;
bool otherValue = otherLayer.GetTexture(mapName) != null;
if (currentValue != otherValue)
{
result = false;
}
}
else
{
outValueNames += "N ";
else
{
outValueNames += "N ";
}
}
return result;
}
void CheckLayerConsistency()
{
string optionValueNames = "";
// We need to check consistency between all layers.
// Each input options and each input maps might can result in different #defines in the shader so all of them need to be consistent
// otherwise the result will be undetermined
// Input options consistency
string[] smoothnessSourceShortNames = { "Mask", "Albedo" };
string[] emissiveModeShortNames = { "Color", "Mask" };
string[] normalMapShortNames = { "Tan", "Obj" };
string[] heightMapShortNames = { "Parallax", "Disp" };
string warningInputOptions = "";
if (!CheckInputOptionConsistency(kSmoothnessTextureChannelProp, smoothnessSourceShortNames, ref optionValueNames))
{
warningInputOptions += "Smoothness Source: " + optionValueNames + "\n";
}
if (!CheckInputOptionConsistency(kEmissiveColorMode, emissiveModeShortNames, ref optionValueNames))
{
warningInputOptions += "Emissive Mode: " + optionValueNames + "\n";
}
if (!CheckInputOptionConsistency(kNormalMapSpace, normalMapShortNames, ref optionValueNames))
{
warningInputOptions += "Normal Map Space: " + optionValueNames + "\n";
}
if (!CheckInputOptionConsistency(kHeightMapMode, heightMapShortNames, ref optionValueNames))
{
warningInputOptions += "Height Map Mode: " + optionValueNames + "\n";
return result;
if (warningInputOptions != string.Empty)
void CheckLayerConsistency()
warningInputOptions = "Input Option Consistency Error:\n" + warningInputOptions;
}
string optionValueNames = "";
// We need to check consistency between all layers.
// Each input options and each input maps might can result in different #defines in the shader so all of them need to be consistent
// otherwise the result will be undetermined
// Check input maps consistency
string warningInputMaps = "";
// Input options consistency
string[] smoothnessSourceShortNames = { "Mask", "Albedo" };
string[] emissiveModeShortNames = { "Color", "Mask" };
string[] normalMapShortNames = { "Tan", "Obj" };
string[] heightMapShortNames = { "Parallax", "Disp" };
if (!CheckInputMapConsistency(kNormalMap, ref optionValueNames))
{
warningInputMaps += "Normal Map: " + optionValueNames + "\n";
}
if (!CheckInputMapConsistency(kMaskMap, ref optionValueNames))
{
warningInputMaps += "Mask Map: " + optionValueNames + "\n";
}
if (!CheckInputMapConsistency(kspecularOcclusionMap, ref optionValueNames))
{
warningInputMaps += "Specular Occlusion Map: " + optionValueNames + "\n";
}
if (!CheckInputMapConsistency(kEmissiveColorMap, ref optionValueNames))
{
warningInputMaps += "Emissive Color Map: " + optionValueNames + "\n";
}
if (!CheckInputMapConsistency(kHeightMap, ref optionValueNames))
{
warningInputMaps += "Height Map: " + optionValueNames + "\n";
}
string warningInputOptions = "";
if (!CheckInputOptionConsistency(kSmoothnessTextureChannelProp, smoothnessSourceShortNames, ref optionValueNames))
{
warningInputOptions += "Smoothness Source: " + optionValueNames + "\n";
}
if (!CheckInputOptionConsistency(kEmissiveColorMode, emissiveModeShortNames, ref optionValueNames))
{
warningInputOptions += "Emissive Mode: " + optionValueNames + "\n";
}
if (!CheckInputOptionConsistency(kNormalMapSpace, normalMapShortNames, ref optionValueNames))
{
warningInputOptions += "Normal Map Space: " + optionValueNames + "\n";
}
if (!CheckInputOptionConsistency(kHeightMapMode, heightMapShortNames, ref optionValueNames))
{
warningInputOptions += "Height Map Mode: " + optionValueNames + "\n";
}
if (warningInputMaps != string.Empty)
{
warningInputMaps = "Input Maps Consistency Error:\n" + warningInputMaps;
warningInputMaps = "\n" + warningInputMaps;
}
{
warningInputOptions = "Input Option Consistency Error:\n" + warningInputOptions;
}
string warning = warningInputOptions + warningInputMaps;
if (warning != string.Empty)
{
EditorGUILayout.HelpBox(warning, MessageType.Error);
}
}
// Check input maps consistency
string warningInputMaps = "";
void SynchronizeInputOptions()
{
Material material = m_MaterialEditor.target as Material;
if (!CheckInputMapConsistency(kNormalMap, ref optionValueNames))
{
warningInputMaps += "Normal Map: " + optionValueNames + "\n";
}
if (!CheckInputMapConsistency(kMaskMap, ref optionValueNames))
{
warningInputMaps += "Mask Map: " + optionValueNames + "\n";
}
if (!CheckInputMapConsistency(kspecularOcclusionMap, ref optionValueNames))
{
warningInputMaps += "Specular Occlusion Map: " + optionValueNames + "\n";
}
if (!CheckInputMapConsistency(kEmissiveColorMap, ref optionValueNames))
{
warningInputMaps += "Emissive Color Map: " + optionValueNames + "\n";
}
if (!CheckInputMapConsistency(kHeightMap, ref optionValueNames))
{
warningInputMaps += "Height Map: " + optionValueNames + "\n";
}
// We synchronize input options with the firsts non null Layer (all layers should have consistent options)
Material firstLayer = null;
int i = 0;
while (i < layerCount && !(firstLayer = m_MaterialLayers[i])) ++i;
if (warningInputMaps != string.Empty)
{
warningInputMaps = "Input Maps Consistency Error:\n" + warningInputMaps;
if (warningInputOptions != string.Empty)
warningInputMaps = "\n" + warningInputMaps;
}
if(firstLayer != null)
{
material.SetFloat(kSmoothnessTextureChannelProp, firstLayer.GetFloat(kSmoothnessTextureChannelProp));
material.SetFloat(kEmissiveColorMode, firstLayer.GetFloat(kEmissiveColorMode));
material.SetFloat(kNormalMapSpace, firstLayer.GetFloat(kNormalMapSpace));
material.SetFloat(kHeightMapMode, firstLayer.GetFloat(kHeightMapMode));
string warning = warningInputOptions + warningInputMaps;
if (warning != string.Empty)
{
EditorGUILayout.HelpBox(warning, MessageType.Error);
}
}
bool LayersGUI(AssetImporter materialImporter)
{
Material material = m_MaterialEditor.target as Material;
void SynchronizeInputOptions()
{
Material material = m_MaterialEditor.target as Material;
bool layerChanged = false;
// We synchronize input options with the firsts non null Layer (all layers should have consistent options)
Material firstLayer = null;
int i = 0;
while (i < layerCount && !(firstLayer = m_MaterialLayers[i])) ++i;
EditorGUI.indentLevel++;
GUILayout.Label(styles.layers, EditorStyles.boldLabel);
if (firstLayer != null)
{
material.SetFloat(kSmoothnessTextureChannelProp, firstLayer.GetFloat(kSmoothnessTextureChannelProp));
material.SetFloat(kEmissiveColorMode, firstLayer.GetFloat(kEmissiveColorMode));
material.SetFloat(kNormalMapSpace, firstLayer.GetFloat(kNormalMapSpace));
material.SetFloat(kHeightMapMode, firstLayer.GetFloat(kHeightMapMode));
}
}
EditorGUI.BeginChangeCheck();
int newLayerCount = EditorGUILayout.IntSlider(styles.layerCount, (int)layerCountProperty.floatValue, 2, 4 );
if (EditorGUI.EndChangeCheck())
bool LayersGUI(AssetImporter materialImporter)
Undo.RecordObject(material, "Change layer count");
layerCountProperty.floatValue = (float)newLayerCount;
SynchronizeAllLayersProperties();
layerChanged = true;
}
Material material = m_MaterialEditor.target as Material;
bool layerChanged = false;
m_MaterialEditor.TexturePropertySingleLine(styles.layerMapMask, layerMaskMapProperty);
EditorGUI.indentLevel++;
GUILayout.Label(styles.layers, EditorStyles.boldLabel);
for (int i = 0; i < layerCount; i++)
{
m_MaterialLayers[i] = EditorGUILayout.ObjectField(styles.materialLayerLabels[i], m_MaterialLayers[i], typeof(Material), true) as Material;
int newLayerCount = EditorGUILayout.IntSlider(styles.layerCount, (int)layerCountProperty.floatValue, 2, 4);
Undo.RecordObject(materialImporter, "Change layer material");
SynchronizeLayerProperties(i);
Undo.RecordObject(material, "Change layer count");
layerCountProperty.floatValue = (float)newLayerCount;
SynchronizeAllLayersProperties();
}
m_MaterialEditor.TexturePropertySingleLine(styles.layerMapMask, layerMaskMapProperty);
for (int i = 0; i < layerCount; i++)
{
EditorGUI.BeginChangeCheck();
m_MaterialLayers[i] = EditorGUILayout.ObjectField(styles.materialLayerLabels[i], m_MaterialLayers[i], typeof(Material), true) as Material;
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(materialImporter, "Change layer material");
SynchronizeLayerProperties(i);
layerChanged = true;
}
}
EditorGUILayout.Space();
GUILayout.BeginHorizontal();
{
GUILayout.FlexibleSpace();
if (GUILayout.Button(styles.syncButton))
EditorGUILayout.Space();
GUILayout.BeginHorizontal();
SynchronizeAllLayersProperties();
layerChanged = true;
GUILayout.FlexibleSpace();
if (GUILayout.Button(styles.syncButton))
{
SynchronizeAllLayersProperties();
layerChanged = true;
}
}
GUILayout.EndHorizontal();
GUILayout.EndHorizontal();
EditorGUI.indentLevel--;
EditorGUI.indentLevel--;
return layerChanged;
}
protected override void SetupKeywordsForInputMaps(Material material)
{
// Find first non null layer
int i = 0;
while (i < layerCount && (m_MaterialLayers[i] == null)) ++i;
return layerChanged;
}
if (i < layerCount)
protected override void SetupKeywordsForInputMaps(Material material)
SetKeyword(material, "_NORMALMAP", material.GetTexture(kNormalMap + i));
SetKeyword(material, "_MASKMAP", material.GetTexture(kMaskMap + i));
SetKeyword(material, "_SPECULAROCCLUSIONMAP", material.GetTexture(kspecularOcclusionMap + i));
SetKeyword(material, "_EMISSIVE_COLOR_MAP", material.GetTexture(kEmissiveColorMap + i));
SetKeyword(material, "_HEIGHTMAP", material.GetTexture(kHeightMap + i));
}
// Find first non null layer
int i = 0;
while (i < layerCount && (m_MaterialLayers[i] == null)) ++i;
SetKeyword(material, "_LAYERMASKMAP", material.GetTexture(kLayerMaskMap));
}
if (i < layerCount)
{
SetKeyword(material, "_NORMALMAP", material.GetTexture(kNormalMap + i));
SetKeyword(material, "_MASKMAP", material.GetTexture(kMaskMap + i));
SetKeyword(material, "_SPECULAROCCLUSIONMAP", material.GetTexture(kspecularOcclusionMap + i));
SetKeyword(material, "_EMISSIVE_COLOR_MAP", material.GetTexture(kEmissiveColorMap + i));
SetKeyword(material, "_HEIGHTMAP", material.GetTexture(kHeightMap + i));
}
void SetupMaterialForLayers(Material material)
{
if(layerCount == 4)
{
SetKeyword(material, "_LAYEREDLIT_4_LAYERS", true);
SetKeyword(material, "_LAYEREDLIT_3_LAYERS", false);
SetKeyword(material, "_LAYERMASKMAP", material.GetTexture(kLayerMaskMap));
else if (layerCount == 3)
void SetupMaterialForLayers(Material material)
SetKeyword(material, "_LAYEREDLIT_4_LAYERS", false);
SetKeyword(material, "_LAYEREDLIT_3_LAYERS", true);
if (layerCount == 4)
{
SetKeyword(material, "_LAYEREDLIT_4_LAYERS", true);
SetKeyword(material, "_LAYEREDLIT_3_LAYERS", false);
}
else if (layerCount == 3)
{
SetKeyword(material, "_LAYEREDLIT_4_LAYERS", false);
SetKeyword(material, "_LAYEREDLIT_3_LAYERS", true);
}
else
{
SetKeyword(material, "_LAYEREDLIT_4_LAYERS", false);
SetKeyword(material, "_LAYEREDLIT_3_LAYERS", false);
}
else
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
SetKeyword(material, "_LAYEREDLIT_4_LAYERS", false);
SetKeyword(material, "_LAYEREDLIT_3_LAYERS", false);
}
}
FindOptionProperties(props);
layerMaskMapProperty = FindProperty(kLayerMaskMap, props);
layerCountProperty = FindProperty(kLayerCount, props);
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
{
FindOptionProperties(props);
layerMaskMapProperty = FindProperty(kLayerMaskMap, props);
layerCountProperty = FindProperty(kLayerCount, props);
m_MaterialEditor = materialEditor;
m_MaterialEditor = materialEditor;
m_MaterialEditor.serializedObject.Update();
m_MaterialEditor.serializedObject.Update();
Material material = m_MaterialEditor.target as Material;
AssetImporter materialImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(material.GetInstanceID()));
Material material = m_MaterialEditor.target as Material;
AssetImporter materialImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(material.GetInstanceID()));
InitializeMaterialLayers(materialImporter);
InitializeMaterialLayers(materialImporter);
bool optionsChanged = false;
EditorGUI.BeginChangeCheck();
{
ShaderOptionsGUI();
EditorGUILayout.Space();
}
if (EditorGUI.EndChangeCheck())
{
optionsChanged = true;
}
bool optionsChanged = false;
EditorGUI.BeginChangeCheck();
{
ShaderOptionsGUI();
EditorGUILayout.Space();
}
if (EditorGUI.EndChangeCheck())
{
optionsChanged = true;
}
bool layerChanged = LayersGUI(materialImporter);
bool layerChanged = LayersGUI(materialImporter);
CheckLayerConsistency();
CheckLayerConsistency();
if (layerChanged || optionsChanged)
{
SynchronizeInputOptions();
if (layerChanged || optionsChanged)
{
SynchronizeInputOptions();
foreach (var obj in m_MaterialEditor.targets)
{
SetupMaterial((Material)obj);
SetupMaterialForLayers((Material)obj);
}
foreach (var obj in m_MaterialEditor.targets)
{
SetupMaterial((Material)obj);
SetupMaterialForLayers((Material)obj);
SaveMaterialLayers(materialImporter);
SaveMaterialLayers(materialImporter);
}
m_MaterialEditor.serializedObject.ApplyModifiedProperties();
m_MaterialEditor.serializedObject.ApplyModifiedProperties();
if (layerChanged)
{
materialImporter.SaveAndReimport();
if (layerChanged)
{
materialImporter.SaveAndReimport();
}
}
} // namespace UnityEditor

66
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/LightDefinition.cs.hlsl


// PackingRules = Exact
struct PunctualLightData
{
float3 positionWS;
float invSqrAttenuationRadius;
float3 color;
float useDistanceAttenuation;
float3 forward;
float diffuseScale;
float3 up;
float specularScale;
float3 right;
float shadowDimmer;
float angleScale;
float angleOffset;
float2 unused2;
float3 positionWS;
float invSqrAttenuationRadius;
float3 color;
float useDistanceAttenuation;
float3 forward;
float diffuseScale;
float3 up;
float specularScale;
float3 right;
float shadowDimmer;
float angleScale;
float angleOffset;
float2 unused2;
};
// Generated from UnityEngine.ScriptableRenderLoop.AreaLightData

float3 positionWS;
float3 positionWS;
};
// Generated from UnityEngine.ScriptableRenderLoop.EnvLightData

float3 positionWS;
float3 positionWS;
};
// Generated from UnityEngine.ScriptableRenderLoop.PlanarLightData

float3 positionWS;
float3 positionWS;
};
//

{
return value.positionWS;
return value.positionWS;
return value.invSqrAttenuationRadius;
return value.invSqrAttenuationRadius;
return value.color;
return value.color;
return value.useDistanceAttenuation;
return value.useDistanceAttenuation;
return value.forward;
return value.forward;
return value.diffuseScale;
return value.diffuseScale;
return value.up;
return value.up;
return value.specularScale;
return value.specularScale;
return value.right;
return value.right;
return value.shadowDimmer;
return value.shadowDimmer;
return value.angleScale;
return value.angleScale;
return value.angleOffset;
return value.angleOffset;
return value.unused2;
return value.unused2;
}
//

{
return value.positionWS;
return value.positionWS;
}
//

{
return value.positionWS;
return value.positionWS;
}
//

{
return value.positionWS;
return value.positionWS;

2
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/Lighting.hlsl


#ifndef UNITY_LIGHTING_INCLUDED
#ifndef UNITY_LIGHTING_INCLUDED
#define UNITY_LIGHTING_INCLUDED
// We need to define the macro used for env map evaluation based on the different architecture.

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


Shader "Hidden/Unity/LightingDeferred"
Shader "Hidden/Unity/LightingDeferred"
{
Properties
{

SubShader
{

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


#ifndef UNITY_LIGHTING_FORWARD_INCLUDED
#ifndef UNITY_LIGHTING_FORWARD_INCLUDED
#define UNITY_LIGHTING_FORWARD_INCLUDED
//-----------------------------------------------------------------------------

34
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lit.shader


// They are use to fill a SurfaceData. With a MaterialGraph this should not exist.
// Reminder. Color here are in linear but the UI (color picker) do the conversion sRGB to linear
_BaseColor("BaseColor", Color) = (1,1,1,1)
_BaseColor("BaseColor", Color) = (1,1,1,1)
_Smoothness("Smoothness", Range(0.0, 1.0)) = 0.5
_Smoothness("Smoothness", Range(0.0, 1.0)) = 0.5
_MaskMap("MaskMap", 2D) = "white" {}
_SpecularOcclusionMap("SpecularOcclusion", 2D) = "white" {}

[Enum(Parallax, 0, Displacement, 1)] _HeightMapMode("Heightmap usage", Float) = 0
[Enum(Parallax, 0, Displacement, 1)] _HeightMapMode("Heightmap usage", Float) = 0
_SubSurfaceRadius("SubSurfaceRadius", Range(0.0, 1.0)) = 0
_SubSurfaceRadiusMap("SubSurfaceRadiusMap", 2D) = "white" {}

// These option below will cause different compilation flag.
// These option below will cause different compilation flag.
_DiffuseLightingMap("DiffuseLightingMap", 2D) = "black" {}
_EmissiveColor("EmissiveColor", Color) = (0, 0, 0)

[ToggleOff] _DistortionOnly("Distortion Only", Float) = 0.0
[ToggleOff] _DistortionDepthTest("Distortion Only", Float) = 0.0
[ToggleOff] _DistortionOnly("Distortion Only", Float) = 0.0
[ToggleOff] _DistortionDepthTest("Distortion Only", Float) = 0.0
[ToggleOff] _AlphaCutoffEnable("Alpha Cutoff Enable", Float) = 0.0
_AlphaCutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5

Cull [_CullMode]
HLSLPROGRAM
HLSLPROGRAM
#pragma vertex VertDefault
#pragma fragment FragDeferred

void FragDeferred( PackedVaryings packedInput,
void FragDeferred( PackedVaryings packedInput,
OUTPUT_GBUFFER(outGBuffer)
#ifdef VELOCITY_IN_GBUFFER
, OUTPUT_GBUFFER_VELOCITY(outGBuffer)

Cull[_CullMode]
HLSLPROGRAM
#include "Assets/ScriptableRenderLoop/ShaderLibrary/Color.hlsl"
#include "Assets/ScriptableRenderLoop/ShaderLibrary/Color.hlsl"
int _DebugViewMaterial;

float3 result = float3(1.0, 1.0, 0.0);
bool needLinearToSRGB = false;
GetVaryingsDataDebug(_DebugViewMaterial, input, result, needLinearToSRGB);
GetVaryingsDataDebug(_DebugViewMaterial, input, result, needLinearToSRGB);
// TEMP!
// TEMP!
// For now, the final blit in the backbuffer performs an sRGB write
// So in the meantime we apply the inverse transform to linear data to compensate.
if (!needLinearToSRGB)

Cull [_CullMode]
HLSLPROGRAM
#pragma fragment FragForward
#pragma fragment FragForward
#if SHADER_STAGE_FRAGMENT

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


// Forward
struct Attributes
{
float3 positionOS : POSITION;
float3 normalOS : NORMAL;
float2 uv0 : TEXCOORD0;
float4 tangentOS : TANGENT;
float3 positionOS : POSITION;
float3 normalOS : NORMAL;
float2 uv0 : TEXCOORD0;
float4 tangentOS : TANGENT;
};
struct Varyings

#endif
#if defined(_DOUBLESIDED_LIGHTING_FLIP) || defined(_DOUBLESIDED_LIGHTING_MIRROR)
#ifdef _DOUBLESIDED_LIGHTING_FLIP
#ifdef _DOUBLESIDED_LIGHTING_FLIP
float3 oppositeNormalWS = -surfaceData.normalWS;
#else
// Mirror the normal with the plane define by vertex normal

723
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/LitUI.cs


namespace UnityEditor
{
internal class LitGUI : ShaderGUI
{
public enum SurfaceType
internal class LitGUI : ShaderGUI
Opaque,
Transparent
}
public enum BlendMode
{
Lerp,
Add,
SoftAdd,
Multiply,
Premultiply
}
public enum SurfaceType
{
Opaque,
Transparent
}
public enum BlendMode
{
Lerp,
Add,
SoftAdd,
Multiply,
Premultiply
}
public enum SmoothnessMapChannel
{
MaskAlpha,
AlbedoAlpha,
}
public enum EmissiveColorMode
{
UseEmissiveColor,
UseEmissiveMask,
}
public enum DoubleSidedMode
{
None,
DoubleSided,
DoubleSidedLightingFlip,
DoubleSidedLightingMirror,
}
public enum SmoothnessMapChannel
{
MaskAlpha,
AlbedoAlpha,
}
public enum EmissiveColorMode
{
UseEmissiveColor,
UseEmissiveMask,
}
public enum DoubleSidedMode
{
None,
DoubleSided,
DoubleSidedLightingFlip,
DoubleSidedLightingMirror,
}
public enum NormalMapSpace
{
TangentSpace,
ObjectSpace,
}
public enum NormalMapSpace
{
TangentSpace,
ObjectSpace,
}
public enum HeightmapMode
{
Parallax,
Displacement,
}
public enum HeightmapMode
{
Parallax,
Displacement,
}
private static class Styles
{
public static string OptionText = "Options";
public static string SurfaceTypeText = "Surface Type";
public static string BlendModeText = "Blend Mode";
private static class Styles
{
public static string OptionText = "Options";
public static string SurfaceTypeText = "Surface Type";
public static string BlendModeText = "Blend Mode";
public static GUIContent alphaCutoffEnableText = new GUIContent("Alpha Cutoff Enable", "Threshold for alpha cutoff");
public static GUIContent alphaCutoffText = new GUIContent("Alpha Cutoff", "Threshold for alpha cutoff");
public static GUIContent doubleSidedModeText = new GUIContent("Double Sided", "This will render the two face of the objects (disable backface culling)");
public static GUIContent alphaCutoffEnableText = new GUIContent("Alpha Cutoff Enable", "Threshold for alpha cutoff");
public static GUIContent alphaCutoffText = new GUIContent("Alpha Cutoff", "Threshold for alpha cutoff");
public static GUIContent doubleSidedModeText = new GUIContent("Double Sided", "This will render the two face of the objects (disable backface culling)");
public static readonly string[] surfaceTypeNames = Enum.GetNames(typeof(SurfaceType));
public static readonly string[] blendModeNames = Enum.GetNames(typeof(BlendMode));
public static readonly string[] surfaceTypeNames = Enum.GetNames(typeof(SurfaceType));
public static readonly string[] blendModeNames = Enum.GetNames(typeof(BlendMode));
public static string InputsOptionsText = "Inputs options";
public static string InputsOptionsText = "Inputs options";
public static GUIContent smoothnessMapChannelText = new GUIContent("Smoothness Source", "Smoothness texture and channel");
public static GUIContent emissiveColorModeText = new GUIContent("Emissive Color Usage", "Use emissive color or emissive mask");
public static GUIContent smoothnessMapChannelText = new GUIContent("Smoothness Source", "Smoothness texture and channel");
public static GUIContent emissiveColorModeText = new GUIContent("Emissive Color Usage", "Use emissive color or emissive mask");
public static string InputsText = "Inputs";
public static string InputsText = "Inputs";
public static string InputsMapText = "";
public static string InputsMapText = "";
public static GUIContent baseColorText = new GUIContent("Base Color + Opacity", "Albedo (RGB) and Opacity (A)");
public static GUIContent baseColorSmoothnessText = new GUIContent("Base Color + Smoothness", "Albedo (RGB) and Smoothness (A)");
public static GUIContent baseColorText = new GUIContent("Base Color + Opacity", "Albedo (RGB) and Opacity (A)");
public static GUIContent baseColorSmoothnessText = new GUIContent("Base Color + Smoothness", "Albedo (RGB) and Smoothness (A)");
public static GUIContent metalicText = new GUIContent("Metalic", "Metalic scale factor");
public static GUIContent smoothnessText = new GUIContent("Smoothness", "Smoothness scale factor");
public static GUIContent maskMapESText = new GUIContent("Mask Map - M(R), AO(G), E(B), S(A)", "Mask map");
public static GUIContent maskMapEText = new GUIContent("Mask Map - M(R), AO(G), E(B)", "Mask map");
public static GUIContent maskMapText = new GUIContent("Mask Map - M(R), AO(G)", "Mask map");
public static GUIContent maskMapSText = new GUIContent("Mask Map - M(R), AO(G), S(A)", "Mask map");
public static GUIContent metalicText = new GUIContent("Metalic", "Metalic scale factor");
public static GUIContent smoothnessText = new GUIContent("Smoothness", "Smoothness scale factor");
public static GUIContent maskMapESText = new GUIContent("Mask Map - M(R), AO(G), E(B), S(A)", "Mask map");
public static GUIContent maskMapEText = new GUIContent("Mask Map - M(R), AO(G), E(B)", "Mask map");
public static GUIContent maskMapText = new GUIContent("Mask Map - M(R), AO(G)", "Mask map");
public static GUIContent maskMapSText = new GUIContent("Mask Map - M(R), AO(G), S(A)", "Mask map");
public static GUIContent specularOcclusionMapText = new GUIContent("Specular Occlusion Map (RGBA)", "Specular Occlusion Map");
public static GUIContent specularOcclusionMapText = new GUIContent("Specular Occlusion Map (RGBA)", "Specular Occlusion Map");
public static GUIContent normalMapText = new GUIContent("Normal Map", "Normal Map (BC5) - DXT5 for test");
public static GUIContent normalMapSpaceText = new GUIContent("Normal Map space", "");
public static GUIContent normalMapText = new GUIContent("Normal Map", "Normal Map (BC5) - DXT5 for test");
public static GUIContent normalMapSpaceText = new GUIContent("Normal Map space", "");
public static GUIContent heightMapText = new GUIContent("Height Map", "Height Map");
public static GUIContent heightMapModeText = new GUIContent("Height Map Mode", "");
public static GUIContent heightMapText = new GUIContent("Height Map", "Height Map");
public static GUIContent heightMapModeText = new GUIContent("Height Map Mode", "");
// public static GUIContent diffuseLightingMapText = new GUIContent("DiffuseLightingMap", "Lightmap/Lightprobe data (fill by system is not done");
// public static GUIContent diffuseLightingMapText = new GUIContent("DiffuseLightingMap", "Lightmap/Lightprobe data (fill by system is not done");
public static GUIContent emissiveText = new GUIContent("Emissive Color", "Emissive");
public static GUIContent emissiveIntensityText = new GUIContent("Emissive Intensity", "Emissive");
}
public static GUIContent emissiveText = new GUIContent("Emissive Color", "Emissive");
public static GUIContent emissiveIntensityText = new GUIContent("Emissive Intensity", "Emissive");
}
MaterialProperty surfaceType = null;
MaterialProperty blendMode = null;
MaterialProperty alphaCutoff = null;
MaterialProperty alphaCutoffEnable = null;
MaterialProperty doubleSidedMode = null;
MaterialProperty smoothnessMapChannel = null;
MaterialProperty emissiveColorMode = null;
MaterialProperty surfaceType = null;
MaterialProperty blendMode = null;
MaterialProperty alphaCutoff = null;
MaterialProperty alphaCutoffEnable = null;
MaterialProperty doubleSidedMode = null;
MaterialProperty smoothnessMapChannel = null;
MaterialProperty emissiveColorMode = null;
MaterialProperty baseColor = null;
MaterialProperty baseColorMap = null;
MaterialProperty metalic = null;
MaterialProperty smoothness = null;
MaterialProperty maskMap = null;
MaterialProperty specularOcclusionMap = null;
MaterialProperty normalMap = null;
MaterialProperty normalMapSpace = null;
MaterialProperty heightMap = null;
MaterialProperty heightScale = null;
MaterialProperty heightBias = null;
MaterialProperty heightMapMode = null;
MaterialProperty baseColor = null;
MaterialProperty baseColorMap = null;
MaterialProperty metalic = null;
MaterialProperty smoothness = null;
MaterialProperty maskMap = null;
MaterialProperty specularOcclusionMap = null;
MaterialProperty normalMap = null;
MaterialProperty normalMapSpace = null;
MaterialProperty heightMap = null;
MaterialProperty heightScale = null;
MaterialProperty heightBias = null;
MaterialProperty heightMapMode = null;
MaterialProperty emissiveColor = null;
MaterialProperty emissiveColorMap = null;
MaterialProperty emissiveIntensity = null;
MaterialProperty emissiveColor = null;
MaterialProperty emissiveColorMap = null;
MaterialProperty emissiveIntensity = null;
protected MaterialEditor m_MaterialEditor;
protected MaterialEditor m_MaterialEditor;
protected const string kSurfaceType = "_SurfaceType";
protected const string kBlendMode = "_BlendMode";
protected const string kAlphaCutoff = "_AlphaCutoff";
protected const string kAlphaCutoffEnabled = "_AlphaCutoffEnable";
protected const string kDoubleSidedMode = "_DoubleSidedMode";
protected const string kSmoothnessTextureChannelProp = "_SmoothnessTextureChannel";
protected const string kEmissiveColorMode = "_EmissiveColorMode";
protected const string kNormalMapSpace = "_NormalMapSpace";
protected const string kHeightMapMode = "_HeightMapMode";
protected const string kSurfaceType = "_SurfaceType";
protected const string kBlendMode = "_BlendMode";
protected const string kAlphaCutoff = "_AlphaCutoff";
protected const string kAlphaCutoffEnabled = "_AlphaCutoffEnable";
protected const string kDoubleSidedMode = "_DoubleSidedMode";
protected const string kSmoothnessTextureChannelProp = "_SmoothnessTextureChannel";
protected const string kEmissiveColorMode = "_EmissiveColorMode";
protected const string kNormalMapSpace = "_NormalMapSpace";
protected const string kHeightMapMode = "_HeightMapMode";
protected const string kNormalMap = "_NormalMap";
protected const string kMaskMap = "_MaskMap";
protected const string kspecularOcclusionMap = "_SpecularOcclusionMap";
protected const string kEmissiveColorMap = "_EmissiveColorMap";
protected const string kHeightMap = "_HeightMap";
protected const string kNormalMap = "_NormalMap";
protected const string kMaskMap = "_MaskMap";
protected const string kspecularOcclusionMap = "_SpecularOcclusionMap";
protected const string kEmissiveColorMap = "_EmissiveColorMap";
protected const string kHeightMap = "_HeightMap";
public void FindOptionProperties(MaterialProperty[] props)
{
surfaceType = FindProperty(kSurfaceType, props);
blendMode = FindProperty(kBlendMode, props);
alphaCutoff = FindProperty(kAlphaCutoff, props);
alphaCutoffEnable = FindProperty(kAlphaCutoffEnabled, props);
doubleSidedMode = FindProperty(kDoubleSidedMode, props);
smoothnessMapChannel = FindProperty(kSmoothnessTextureChannelProp, props);
emissiveColorMode = FindProperty(kEmissiveColorMode, props);
normalMapSpace = FindProperty(kNormalMapSpace, props);
heightMapMode = FindProperty(kHeightMapMode, props);
}
public void FindOptionProperties (MaterialProperty[] props)
{
surfaceType = FindProperty(kSurfaceType, props);
blendMode = FindProperty(kBlendMode, props);
alphaCutoff = FindProperty(kAlphaCutoff, props);
alphaCutoffEnable = FindProperty(kAlphaCutoffEnabled, props);
doubleSidedMode = FindProperty(kDoubleSidedMode, props);
smoothnessMapChannel = FindProperty(kSmoothnessTextureChannelProp, props);
emissiveColorMode = FindProperty(kEmissiveColorMode, props);
normalMapSpace = FindProperty(kNormalMapSpace, props);
heightMapMode = FindProperty(kHeightMapMode, props);
}
public void FindInputProperties(MaterialProperty[] props)
{
baseColor = FindProperty("_BaseColor", props);
baseColorMap = FindProperty("_BaseColorMap", props);
metalic = FindProperty("_Metalic", props);
smoothness = FindProperty("_Smoothness", props);
maskMap = FindProperty(kMaskMap, props);
specularOcclusionMap = FindProperty(kspecularOcclusionMap, props);
normalMap = FindProperty(kNormalMap, props);
heightMap = FindProperty(kHeightMap, props);
heightScale = FindProperty("_HeightScale", props);
heightBias = FindProperty("_HeightBias", props);
// diffuseLightingMap = FindProperty("_DiffuseLightingMap", props);
emissiveColor = FindProperty("_EmissiveColor", props);
emissiveColorMap = FindProperty(kEmissiveColorMap, props);
emissiveIntensity = FindProperty("_EmissiveIntensity", props);
}
public void FindInputProperties(MaterialProperty[] props)
{
baseColor = FindProperty("_BaseColor", props);
baseColorMap = FindProperty("_BaseColorMap", props);
metalic = FindProperty("_Metalic", props);
smoothness = FindProperty("_Smoothness", props);
maskMap = FindProperty(kMaskMap, props);
specularOcclusionMap = FindProperty(kspecularOcclusionMap, props);
normalMap = FindProperty(kNormalMap, props);
heightMap = FindProperty(kHeightMap, props);
heightScale = FindProperty("_HeightScale", props);
heightBias = FindProperty("_HeightBias", props);
// diffuseLightingMap = FindProperty("_DiffuseLightingMap", props);
emissiveColor = FindProperty("_EmissiveColor", props);
emissiveColorMap = FindProperty(kEmissiveColorMap, props);
emissiveIntensity = FindProperty("_EmissiveIntensity", props);
}
public override void OnGUI (MaterialEditor materialEditor, MaterialProperty[] props)
{
FindOptionProperties(props); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly
FindInputProperties(props);
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
{
FindOptionProperties(props); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly
FindInputProperties(props);
m_MaterialEditor = materialEditor;
Material material = materialEditor.target as Material;
ShaderPropertiesGUI (material);
}
m_MaterialEditor = materialEditor;
Material material = materialEditor.target as Material;
ShaderPropertiesGUI(material);
}
protected void ShaderOptionsGUI()
{
EditorGUI.indentLevel++;
GUILayout.Label(Styles.OptionText, EditorStyles.boldLabel);
SurfaceTypePopup();
if ((SurfaceType)surfaceType.floatValue == SurfaceType.Transparent)
protected void ShaderOptionsGUI()
BlendModePopup();
EditorGUI.indentLevel++;
GUILayout.Label(Styles.OptionText, EditorStyles.boldLabel);
SurfaceTypePopup();
if ((SurfaceType)surfaceType.floatValue == SurfaceType.Transparent)
{
BlendModePopup();
}
m_MaterialEditor.ShaderProperty(alphaCutoffEnable, Styles.alphaCutoffEnableText.text);
if (alphaCutoffEnable.floatValue == 1.0)
{
m_MaterialEditor.ShaderProperty(alphaCutoff, Styles.alphaCutoffText.text);
}
m_MaterialEditor.ShaderProperty(doubleSidedMode, Styles.doubleSidedModeText.text);
EditorGUI.indentLevel--;
m_MaterialEditor.ShaderProperty(alphaCutoffEnable, Styles.alphaCutoffEnableText.text);
if (alphaCutoffEnable.floatValue == 1.0)
protected void ShaderInputOptionsGUI()
m_MaterialEditor.ShaderProperty(alphaCutoff, Styles.alphaCutoffText.text);
EditorGUI.indentLevel++;
GUILayout.Label(Styles.InputsOptionsText, EditorStyles.boldLabel);
m_MaterialEditor.ShaderProperty(smoothnessMapChannel, Styles.smoothnessMapChannelText.text);
m_MaterialEditor.ShaderProperty(emissiveColorMode, Styles.emissiveColorModeText.text);
m_MaterialEditor.ShaderProperty(normalMapSpace, Styles.normalMapSpaceText.text);
m_MaterialEditor.ShaderProperty(heightMapMode, Styles.heightMapModeText.text);
EditorGUI.indentLevel--;
m_MaterialEditor.ShaderProperty(doubleSidedMode, Styles.doubleSidedModeText.text);
EditorGUI.indentLevel--;
}
protected void ShaderInputGUI()
{
EditorGUI.indentLevel++;
bool smoothnessInAlbedoAlpha = (SmoothnessMapChannel)smoothnessMapChannel.floatValue == SmoothnessMapChannel.AlbedoAlpha;
bool useEmissiveMask = (EmissiveColorMode)emissiveColorMode.floatValue == EmissiveColorMode.UseEmissiveMask;
protected void ShaderInputOptionsGUI()
{
EditorGUI.indentLevel++;
GUILayout.Label(Styles.InputsOptionsText, EditorStyles.boldLabel);
m_MaterialEditor.ShaderProperty(smoothnessMapChannel, Styles.smoothnessMapChannelText.text);
m_MaterialEditor.ShaderProperty(emissiveColorMode, Styles.emissiveColorModeText.text);
m_MaterialEditor.ShaderProperty(normalMapSpace, Styles.normalMapSpaceText.text);
m_MaterialEditor.ShaderProperty(heightMapMode, Styles.heightMapModeText.text);
EditorGUI.indentLevel--;
}
GUILayout.Label(Styles.InputsText, EditorStyles.boldLabel);
m_MaterialEditor.TexturePropertySingleLine(smoothnessInAlbedoAlpha ? Styles.baseColorSmoothnessText : Styles.baseColorText, baseColorMap, baseColor);
m_MaterialEditor.ShaderProperty(metalic, Styles.metalicText);
m_MaterialEditor.ShaderProperty(smoothness, Styles.smoothnessText);
if (smoothnessInAlbedoAlpha && useEmissiveMask)
m_MaterialEditor.TexturePropertySingleLine(Styles.maskMapEText, maskMap);
else if (smoothnessInAlbedoAlpha && !useEmissiveMask)
m_MaterialEditor.TexturePropertySingleLine(Styles.maskMapText, maskMap);
else if (!smoothnessInAlbedoAlpha && useEmissiveMask)
m_MaterialEditor.TexturePropertySingleLine(Styles.maskMapESText, maskMap);
else if (!smoothnessInAlbedoAlpha && !useEmissiveMask)
m_MaterialEditor.TexturePropertySingleLine(Styles.maskMapSText, maskMap);
protected void ShaderInputGUI()
{
EditorGUI.indentLevel++;
bool smoothnessInAlbedoAlpha = (SmoothnessMapChannel)smoothnessMapChannel.floatValue == SmoothnessMapChannel.AlbedoAlpha;
bool useEmissiveMask = (EmissiveColorMode)emissiveColorMode.floatValue == EmissiveColorMode.UseEmissiveMask;
m_MaterialEditor.TexturePropertySingleLine(Styles.specularOcclusionMapText, specularOcclusionMap);
GUILayout.Label(Styles.InputsText, EditorStyles.boldLabel);
m_MaterialEditor.TexturePropertySingleLine(smoothnessInAlbedoAlpha ? Styles.baseColorSmoothnessText : Styles.baseColorText, baseColorMap, baseColor);
m_MaterialEditor.ShaderProperty(metalic, Styles.metalicText);
m_MaterialEditor.ShaderProperty(smoothness, Styles.smoothnessText);
if (smoothnessInAlbedoAlpha && useEmissiveMask)
m_MaterialEditor.TexturePropertySingleLine(Styles.maskMapEText, maskMap);
else if (smoothnessInAlbedoAlpha && !useEmissiveMask)
m_MaterialEditor.TexturePropertySingleLine(Styles.maskMapText, maskMap);
else if (!smoothnessInAlbedoAlpha && useEmissiveMask)
m_MaterialEditor.TexturePropertySingleLine(Styles.maskMapESText, maskMap);
else if (!smoothnessInAlbedoAlpha && !useEmissiveMask)
m_MaterialEditor.TexturePropertySingleLine(Styles.maskMapSText, maskMap);
m_MaterialEditor.TexturePropertySingleLine(Styles.specularOcclusionMapText, specularOcclusionMap);
m_MaterialEditor.TexturePropertySingleLine(Styles.normalMapText, normalMap);
m_MaterialEditor.TexturePropertySingleLine(Styles.normalMapText, normalMap);
m_MaterialEditor.TexturePropertySingleLine(Styles.heightMapText, heightMap, heightScale, heightBias);
m_MaterialEditor.TexturePropertySingleLine(Styles.heightMapText, heightMap, heightScale, heightBias);
if (!useEmissiveMask)
{
m_MaterialEditor.TexturePropertySingleLine(Styles.emissiveText, emissiveColorMap, emissiveColor);
}
m_MaterialEditor.ShaderProperty(emissiveIntensity, Styles.emissiveIntensityText);
EditorGUI.indentLevel--;
}
if (!useEmissiveMask)
public void ShaderPropertiesGUI(Material material)
m_MaterialEditor.TexturePropertySingleLine(Styles.emissiveText, emissiveColorMap, emissiveColor);
}
m_MaterialEditor.ShaderProperty(emissiveIntensity, Styles.emissiveIntensityText);
EditorGUI.indentLevel--;
}
// Use default labelWidth
EditorGUIUtility.labelWidth = 0f;
public void ShaderPropertiesGUI (Material material)
{
// Use default labelWidth
EditorGUIUtility.labelWidth = 0f;
// Detect any changes to the material
EditorGUI.BeginChangeCheck();
{
ShaderOptionsGUI();
EditorGUILayout.Space();
// Detect any changes to the material
EditorGUI.BeginChangeCheck();
{
ShaderOptionsGUI();
EditorGUILayout.Space();
ShaderInputOptionsGUI();
ShaderInputOptionsGUI();
EditorGUILayout.Space();
ShaderInputGUI();
}
EditorGUILayout.Space();
ShaderInputGUI();
if (EditorGUI.EndChangeCheck())
{
foreach (var obj in m_MaterialEditor.targets)
SetupMaterial((Material)obj);
}
if (EditorGUI.EndChangeCheck())
// TODO: try to setup minimun value to fall back to standard shaders and reverse
public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)
foreach (var obj in m_MaterialEditor.targets)
SetupMaterial((Material)obj);
base.AssignNewShaderToMaterial(material, oldShader, newShader);
}
// TODO: try to setup minimun value to fall back to standard shaders and reverse
public override void AssignNewShaderToMaterial (Material material, Shader oldShader, Shader newShader)
{
base.AssignNewShaderToMaterial(material, oldShader, newShader);
}
void SurfaceTypePopup()
{
EditorGUI.showMixedValue = surfaceType.hasMixedValue;
var mode = (SurfaceType)surfaceType.floatValue;
void SurfaceTypePopup()
{
EditorGUI.showMixedValue = surfaceType.hasMixedValue;
var mode = (SurfaceType)surfaceType.floatValue;
EditorGUI.BeginChangeCheck();
mode = (SurfaceType)EditorGUILayout.Popup(Styles.SurfaceTypeText, (int)mode, Styles.surfaceTypeNames);
if (EditorGUI.EndChangeCheck())
{
m_MaterialEditor.RegisterPropertyChangeUndo("Surface Type");
surfaceType.floatValue = (float)mode;
}
EditorGUI.BeginChangeCheck();
mode = (SurfaceType)EditorGUILayout.Popup(Styles.SurfaceTypeText, (int)mode, Styles.surfaceTypeNames);
if (EditorGUI.EndChangeCheck())
{
m_MaterialEditor.RegisterPropertyChangeUndo("Surface Type");
surfaceType.floatValue = (float)mode;
EditorGUI.showMixedValue = false;
EditorGUI.showMixedValue = false;
}
void BlendModePopup()
{
EditorGUI.showMixedValue = blendMode.hasMixedValue;
var mode = (BlendMode)blendMode.floatValue;
EditorGUI.BeginChangeCheck();
mode = (BlendMode)EditorGUILayout.Popup(Styles.BlendModeText, (int)mode, Styles.blendModeNames);
if (EditorGUI.EndChangeCheck())
void BlendModePopup()
m_MaterialEditor.RegisterPropertyChangeUndo("Blend Mode");
blendMode.floatValue = (float)mode;
}
EditorGUI.showMixedValue = false;
}
protected virtual void SetupKeywordsForInputMaps(Material material)
{
SetKeyword(material, "_NORMALMAP", material.GetTexture(kNormalMap));
SetKeyword(material, "_MASKMAP", material.GetTexture(kMaskMap));
SetKeyword(material, "_SPECULAROCCLUSIONMAP", material.GetTexture(kspecularOcclusionMap));
SetKeyword(material, "_EMISSIVE_COLOR_MAP", material.GetTexture(kEmissiveColorMap));
SetKeyword(material, "_HEIGHTMAP", material.GetTexture(kHeightMap));
}
EditorGUI.showMixedValue = blendMode.hasMixedValue;
var mode = (BlendMode)blendMode.floatValue;
protected void SetupMaterial(Material material)
{
// Note: keywords must be based on Material value not on MaterialProperty due to multi-edit & material animation
// (MaterialProperty value might come from renderer material property block)
EditorGUI.BeginChangeCheck();
mode = (BlendMode)EditorGUILayout.Popup(Styles.BlendModeText, (int)mode, Styles.blendModeNames);
if (EditorGUI.EndChangeCheck())
{
m_MaterialEditor.RegisterPropertyChangeUndo("Blend Mode");
blendMode.floatValue = (float)mode;
}
bool alphaTestEnable = material.GetFloat(kAlphaCutoffEnabled) == 1.0;
SurfaceType surfaceType = (SurfaceType)material.GetFloat(kSurfaceType);
BlendMode blendMode = (BlendMode)material.GetFloat(kBlendMode);
DoubleSidedMode doubleSidedMode = (DoubleSidedMode)material.GetFloat(kDoubleSidedMode);
EditorGUI.showMixedValue = false;
}
if (surfaceType == SurfaceType.Opaque)
protected virtual void SetupKeywordsForInputMaps(Material material)
material.SetOverrideTag("RenderType", alphaTestEnable ? "TransparentCutout" : "");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.renderQueue = alphaTestEnable ? (int)UnityEngine.Rendering.RenderQueue.AlphaTest : -1;
SetKeyword(material, "_NORMALMAP", material.GetTexture(kNormalMap));
SetKeyword(material, "_MASKMAP", material.GetTexture(kMaskMap));
SetKeyword(material, "_SPECULAROCCLUSIONMAP", material.GetTexture(kspecularOcclusionMap));
SetKeyword(material, "_EMISSIVE_COLOR_MAP", material.GetTexture(kEmissiveColorMap));
SetKeyword(material, "_HEIGHTMAP", material.GetTexture(kHeightMap));
else
protected void SetupMaterial(Material material)
material.SetOverrideTag("RenderType", "Transparent");
material.SetInt("_ZWrite", 0);
material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
// Note: keywords must be based on Material value not on MaterialProperty due to multi-edit & material animation
// (MaterialProperty value might come from renderer material property block)
switch (blendMode)
bool alphaTestEnable = material.GetFloat(kAlphaCutoffEnabled) == 1.0;
SurfaceType surfaceType = (SurfaceType)material.GetFloat(kSurfaceType);
BlendMode blendMode = (BlendMode)material.GetFloat(kBlendMode);
DoubleSidedMode doubleSidedMode = (DoubleSidedMode)material.GetFloat(kDoubleSidedMode);
if (surfaceType == SurfaceType.Opaque)
{
material.SetOverrideTag("RenderType", alphaTestEnable ? "TransparentCutout" : "");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.renderQueue = alphaTestEnable ? (int)UnityEngine.Rendering.RenderQueue.AlphaTest : -1;
}
else
case BlendMode.Lerp:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
break;
material.SetOverrideTag("RenderType", "Transparent");
material.SetInt("_ZWrite", 0);
material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
switch (blendMode)
{
case BlendMode.Lerp:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
break;
case BlendMode.Add:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.One);
break;
case BlendMode.Add:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.One);
break;
case BlendMode.SoftAdd:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusDstColor);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.One);
break;
case BlendMode.SoftAdd:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusDstColor);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.One);
break;
case BlendMode.Multiply:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.DstColor);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
break;
case BlendMode.Multiply:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.DstColor);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
break;
case BlendMode.Premultiply:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
break;
case BlendMode.Premultiply:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
break;
}
}
if (doubleSidedMode == DoubleSidedMode.None)
{
material.SetInt("_CullMode", (int)UnityEngine.Rendering.CullMode.Back);
}
else
{
material.SetInt("_CullMode", (int)UnityEngine.Rendering.CullMode.Off);
}
if (doubleSidedMode == DoubleSidedMode.None)
{
material.SetInt("_CullMode", (int)UnityEngine.Rendering.CullMode.Back);
}
else
{
material.SetInt("_CullMode", (int)UnityEngine.Rendering.CullMode.Off);
}
if (doubleSidedMode == DoubleSidedMode.DoubleSidedLightingFlip)
{
material.EnableKeyword("_DOUBLESIDED_LIGHTING_FLIP");
material.DisableKeyword("_DOUBLESIDED_LIGHTING_MIRROR");
}
else if (doubleSidedMode == DoubleSidedMode.DoubleSidedLightingMirror)
{
material.DisableKeyword("_DOUBLESIDED_LIGHTING_FLIP");
material.EnableKeyword("_DOUBLESIDED_LIGHTING_MIRROR");
}
else
{
material.DisableKeyword("_DOUBLESIDED_LIGHTING_FLIP");
material.DisableKeyword("_DOUBLESIDED_LIGHTING_MIRROR");
}
if (doubleSidedMode == DoubleSidedMode.DoubleSidedLightingFlip)
{
material.EnableKeyword("_DOUBLESIDED_LIGHTING_FLIP");
material.DisableKeyword("_DOUBLESIDED_LIGHTING_MIRROR");
}
else if (doubleSidedMode == DoubleSidedMode.DoubleSidedLightingMirror)
{
material.DisableKeyword("_DOUBLESIDED_LIGHTING_FLIP");
material.EnableKeyword("_DOUBLESIDED_LIGHTING_MIRROR");
}
else
{
material.DisableKeyword("_DOUBLESIDED_LIGHTING_FLIP");
material.DisableKeyword("_DOUBLESIDED_LIGHTING_MIRROR");
}
SetKeyword(material, "_ALPHATEST_ON", alphaTestEnable);
SetKeyword(material, "_NORMALMAP_TANGENT_SPACE", (NormalMapSpace)material.GetFloat(kNormalMapSpace) == NormalMapSpace.TangentSpace);
SetKeyword(material, "_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A", ((SmoothnessMapChannel)material.GetFloat(kSmoothnessTextureChannelProp)) == SmoothnessMapChannel.AlbedoAlpha);
SetKeyword(material, "_EMISSIVE_COLOR", ((EmissiveColorMode)material.GetFloat(kEmissiveColorMode)) == EmissiveColorMode.UseEmissiveColor);
SetKeyword(material, "_HEIGHTMAP_AS_DISPLACEMENT", (HeightmapMode)material.GetFloat(kHeightMapMode) == HeightmapMode.Displacement);
SetKeyword(material, "_ALPHATEST_ON", alphaTestEnable);
SetKeyword(material, "_NORMALMAP_TANGENT_SPACE", (NormalMapSpace)material.GetFloat(kNormalMapSpace) == NormalMapSpace.TangentSpace);
SetKeyword(material, "_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A", ((SmoothnessMapChannel)material.GetFloat(kSmoothnessTextureChannelProp)) == SmoothnessMapChannel.AlbedoAlpha);
SetKeyword(material, "_EMISSIVE_COLOR", ((EmissiveColorMode)material.GetFloat(kEmissiveColorMode)) == EmissiveColorMode.UseEmissiveColor);
SetKeyword(material, "_HEIGHTMAP_AS_DISPLACEMENT", (HeightmapMode)material.GetFloat(kHeightMapMode) == HeightmapMode.Displacement);
SetupKeywordsForInputMaps(material);
SetupKeywordsForInputMaps(material);
/*
// Setup lightmap emissive flags
MaterialGlobalIlluminationFlags flags = material.globalIlluminationFlags;
if ((flags & (MaterialGlobalIlluminationFlags.BakedEmissive | MaterialGlobalIlluminationFlags.RealtimeEmissive)) != 0)
{
flags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;
if (!shouldEmissionBeEnabled)
flags |= MaterialGlobalIlluminationFlags.EmissiveIsBlack;
/*
// Setup lightmap emissive flags
MaterialGlobalIlluminationFlags flags = material.globalIlluminationFlags;
if ((flags & (MaterialGlobalIlluminationFlags.BakedEmissive | MaterialGlobalIlluminationFlags.RealtimeEmissive)) != 0)
{
flags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;
if (!shouldEmissionBeEnabled)
flags |= MaterialGlobalIlluminationFlags.EmissiveIsBlack;
material.globalIlluminationFlags = flags;
material.globalIlluminationFlags = flags;
}
*/
*/
}
static bool ShouldEmissionBeEnabled(Material mat, Color color)
{
static bool ShouldEmissionBeEnabled(Material mat, Color color)
{
}
}
bool HasValidEmissiveKeyword(Material material)
{
/*
// Material animation might be out of sync with the material keyword.
// So if the emission support is disabled on the material, but the property blocks have a value that requires it, then we need to show a warning.
// (note: (Renderer MaterialPropertyBlock applies its values to emissionColorForRendering))
bool hasEmissionKeyword = material.IsKeywordEnabled ("_EMISSION");
if (!hasEmissionKeyword && ShouldEmissionBeEnabled (material, emissionColorForRendering.colorValue))
return false;
else
return true;
*/
bool HasValidEmissiveKeyword (Material material)
{
/*
// Material animation might be out of sync with the material keyword.
// So if the emission support is disabled on the material, but the property blocks have a value that requires it, then we need to show a warning.
// (note: (Renderer MaterialPropertyBlock applies its values to emissionColorForRendering))
bool hasEmissionKeyword = material.IsKeywordEnabled ("_EMISSION");
if (!hasEmissionKeyword && ShouldEmissionBeEnabled (material, emissionColorForRendering.colorValue))
return false;
else
*/
}
return true;
}
protected void SetKeyword(Material m, string keyword, bool state)
{
if (state)
m.EnableKeyword (keyword);
else
m.DisableKeyword (keyword);
protected void SetKeyword(Material m, string keyword, bool state)
{
if (state)
m.EnableKeyword(keyword);
else
m.DisableKeyword(keyword);
}
}
} // namespace UnityEditor

4
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/BuiltinData.cs


public float opacity;
// These are lighting data.
// We would prefer to split lighting and material information but for performance reasons,
// those lighting information are fill
// We would prefer to split lighting and material information but for performance reasons,
// those lighting information are fill
// at the same time than material information.
[SurfaceDataAttributes("Bake Diffuse Lighting")]
public Vector3 bakeDiffuseLighting; // This is the result of sampling lightmap/lightprobe/proxyvolume

16
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/BuiltinData.cs.hlsl


// PackingRules = Exact
struct BuiltinData
{
float opacity;
float3 bakeDiffuseLighting;
float3 emissiveColor;
float emissiveIntensity;
float2 velocity;
float2 distortion;
float distortionBlur;
float opacity;
float3 bakeDiffuseLighting;
float3 emissiveColor;
float emissiveIntensity;
float2 velocity;
float2 distortion;
float distortionBlur;

66
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Lit.cs.hlsl


// PackingRules = Exact
struct SurfaceData
{
float3 baseColor;
float specularOcclusion;
float3 normalWS;
float perceptualSmoothness;
int materialId;
float ambientOcclusion;
float3 tangentWS;
float anisotropy;
float metalic;
float specular;
float subSurfaceRadius;
float thickness;
int subSurfaceProfile;
float3 coatNormalWS;
float coatPerceptualSmoothness;
float3 specularColor;
float3 baseColor;
float specularOcclusion;
float3 normalWS;
float perceptualSmoothness;
int materialId;
float ambientOcclusion;
float3 tangentWS;
float anisotropy;
float metalic;
float specular;
float subSurfaceRadius;
float thickness;
int subSurfaceProfile;
float3 coatNormalWS;
float coatPerceptualSmoothness;
float3 specularColor;
};
// Generated from UnityEngine.ScriptableRenderLoop.Lit.BSDFData

float3 diffuseColor;
float3 fresnel0;
float specularOcclusion;
float3 normalWS;
float perceptualRoughness;
float roughness;
float materialId;
float3 tangentWS;
float3 bitangentWS;
float roughnessT;
float roughnessB;
float subSurfaceRadius;
float thickness;
int subSurfaceProfile;
float3 coatNormalWS;
float coatRoughness;
float3 diffuseColor;
float3 fresnel0;
float specularOcclusion;
float3 normalWS;
float perceptualRoughness;
float roughness;
float materialId;
float3 tangentWS;
float3 bitangentWS;
float roughnessT;
float roughnessB;
float subSurfaceRadius;
float thickness;
int subSurfaceProfile;
float3 coatNormalWS;
float coatRoughness;

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


bsdfData.materialId = surfaceData.materialId;
if (bsdfData.materialId == MATERIALID_LIT_STANDARD)
{
{
bsdfData.diffuseColor = surfaceData.baseColor * (1.0 - surfaceData.metalic);
bsdfData.fresnel0 = lerp(float3(surfaceData.specular, surfaceData.specular, surfaceData.specular), surfaceData.baseColor, surfaceData.metalic);

// Encode SurfaceData (BSDF parameters) into GBuffer
// Must be in sync with RT declared in HDRenderLoop.cs ::Rebuild
void EncodeIntoGBuffer( SurfaceData surfaceData,
out float4 outGBuffer0,
out float4 outGBuffer1,
void EncodeIntoGBuffer( SurfaceData surfaceData,
out float4 outGBuffer0,
out float4 outGBuffer1,
out float4 outGBuffer2)
{
// RT0 - 8:8:8:8 sRGB

}
}
BSDFData DecodeFromGBuffer( float4 inGBuffer0,
float4 inGBuffer1,
BSDFData DecodeFromGBuffer( float4 inGBuffer0,
float4 inGBuffer1,
bsdfData.perceptualRoughness = inGBuffer1.b;
bsdfData.perceptualRoughness = inGBuffer1.b;
bsdfData.roughness = PerceptualRoughnessToRoughness(bsdfData.perceptualRoughness);
bsdfData.materialId = UnpackMaterialId(inGBuffer1.a);

{
switch (paramId)
{
case DEBUGVIEW_LIT_SURFACEDATA_BASE_COLOR:
result = surfaceData.baseColor; needLinearToSRGB = true;
case DEBUGVIEW_LIT_SURFACEDATA_BASE_COLOR:
result = surfaceData.baseColor; needLinearToSRGB = true;
case DEBUGVIEW_LIT_SURFACEDATA_SPECULAR_OCCLUSION:
result = surfaceData.specularOcclusion.xxx;
case DEBUGVIEW_LIT_SURFACEDATA_SPECULAR_OCCLUSION:
result = surfaceData.specularOcclusion.xxx;
case DEBUGVIEW_LIT_SURFACEDATA_NORMAL_WS:
result = surfaceData.normalWS * 0.5 + 0.5;
case DEBUGVIEW_LIT_SURFACEDATA_NORMAL_WS:
result = surfaceData.normalWS * 0.5 + 0.5;
case DEBUGVIEW_LIT_SURFACEDATA_PERCEPTUAL_SMOOTHNESS:
result = surfaceData.perceptualSmoothness.xxx;
case DEBUGVIEW_LIT_SURFACEDATA_PERCEPTUAL_SMOOTHNESS:
result = surfaceData.perceptualSmoothness.xxx;
case DEBUGVIEW_LIT_SURFACEDATA_MATERIAL_ID:
result = GetIndexColor(surfaceData.materialId);
case DEBUGVIEW_LIT_SURFACEDATA_MATERIAL_ID:
result = GetIndexColor(surfaceData.materialId);
case DEBUGVIEW_LIT_SURFACEDATA_AMBIENT_OCCLUSION:
result = surfaceData.ambientOcclusion.xxx;
case DEBUGVIEW_LIT_SURFACEDATA_AMBIENT_OCCLUSION:
result = surfaceData.ambientOcclusion.xxx;
case DEBUGVIEW_LIT_SURFACEDATA_TANGENT_WS:
result = surfaceData.tangentWS * 0.5 + 0.5;
case DEBUGVIEW_LIT_SURFACEDATA_TANGENT_WS:
result = surfaceData.tangentWS * 0.5 + 0.5;
case DEBUGVIEW_LIT_SURFACEDATA_ANISOTROPY:
result = surfaceData.anisotropy.xxx;
case DEBUGVIEW_LIT_SURFACEDATA_ANISOTROPY:
result = surfaceData.anisotropy.xxx;
case DEBUGVIEW_LIT_SURFACEDATA_METALIC:
result = surfaceData.metalic.xxx;
case DEBUGVIEW_LIT_SURFACEDATA_METALIC:
result = surfaceData.metalic.xxx;
case DEBUGVIEW_LIT_SURFACEDATA_SPECULAR:
result = surfaceData.specular.xxx;
case DEBUGVIEW_LIT_SURFACEDATA_SPECULAR:
result = surfaceData.specular.xxx;
case DEBUGVIEW_LIT_SURFACEDATA_SUB_SURFACE_RADIUS:
result = surfaceData.subSurfaceRadius.xxx;
case DEBUGVIEW_LIT_SURFACEDATA_SUB_SURFACE_RADIUS:
result = surfaceData.subSurfaceRadius.xxx;
case DEBUGVIEW_LIT_SURFACEDATA_THICKNESS:
result = surfaceData.thickness.xxx;
case DEBUGVIEW_LIT_SURFACEDATA_THICKNESS:
result = surfaceData.thickness.xxx;
case DEBUGVIEW_LIT_SURFACEDATA_SUB_SURFACE_PROFILE:
result = GetIndexColor(surfaceData.subSurfaceProfile);
case DEBUGVIEW_LIT_SURFACEDATA_SUB_SURFACE_PROFILE:
result = GetIndexColor(surfaceData.subSurfaceProfile);
case DEBUGVIEW_LIT_SURFACEDATA_COAT_NORMAL_WS:
result = surfaceData.coatNormalWS * 0.5 + 0.5;
case DEBUGVIEW_LIT_SURFACEDATA_COAT_NORMAL_WS:
result = surfaceData.coatNormalWS * 0.5 + 0.5;
case DEBUGVIEW_LIT_SURFACEDATA_COAT_PERCEPTUAL_SMOOTHNESS:
result = surfaceData.coatPerceptualSmoothness.xxx;
case DEBUGVIEW_LIT_SURFACEDATA_COAT_PERCEPTUAL_SMOOTHNESS:
result = surfaceData.coatPerceptualSmoothness.xxx;
case DEBUGVIEW_LIT_SURFACEDATA_SPECULAR_COLOR:
result = surfaceData.specularColor; needLinearToSRGB = true;
case DEBUGVIEW_LIT_SURFACEDATA_SPECULAR_COLOR:
result = surfaceData.specularColor; needLinearToSRGB = true;
break;
}
}

result = bsdfData.diffuseColor; needLinearToSRGB = true;
break;
case DEBUGVIEW_LIT_BSDFDATA_FRESNEL0:
result = bsdfData.fresnel0;
result = bsdfData.fresnel0;
case DEBUGVIEW_LIT_BSDFDATA_SPECULAR_OCCLUSION:
result = bsdfData.specularOcclusion.xxx;
case DEBUGVIEW_LIT_BSDFDATA_SPECULAR_OCCLUSION:
result = bsdfData.specularOcclusion.xxx;
case DEBUGVIEW_LIT_BSDFDATA_NORMAL_WS:
result = bsdfData.normalWS * 0.5 + 0.5;
case DEBUGVIEW_LIT_BSDFDATA_NORMAL_WS:
result = bsdfData.normalWS * 0.5 + 0.5;
case DEBUGVIEW_LIT_BSDFDATA_PERCEPTUAL_ROUGHNESS:
result = bsdfData.perceptualRoughness.xxx;
case DEBUGVIEW_LIT_BSDFDATA_PERCEPTUAL_ROUGHNESS:
result = bsdfData.perceptualRoughness.xxx;
case DEBUGVIEW_LIT_BSDFDATA_ROUGHNESS:
result = bsdfData.roughness.xxx;
case DEBUGVIEW_LIT_BSDFDATA_ROUGHNESS:
result = bsdfData.roughness.xxx;
case DEBUGVIEW_LIT_BSDFDATA_MATERIAL_ID:
result = GetIndexColor(bsdfData.materialId);
case DEBUGVIEW_LIT_BSDFDATA_MATERIAL_ID:
result = GetIndexColor(bsdfData.materialId);
case DEBUGVIEW_LIT_BSDFDATA_TANGENT_WS:
result = bsdfData.tangentWS * 0.5 + 0.5;
case DEBUGVIEW_LIT_BSDFDATA_TANGENT_WS:
result = bsdfData.tangentWS * 0.5 + 0.5;
case DEBUGVIEW_LIT_BSDFDATA_BITANGENT_WS:
result = bsdfData.bitangentWS * 0.5 + 0.5;
case DEBUGVIEW_LIT_BSDFDATA_BITANGENT_WS:
result = bsdfData.bitangentWS * 0.5 + 0.5;
case DEBUGVIEW_LIT_BSDFDATA_ROUGHNESS_T:
result = bsdfData.roughnessT.xxx;
case DEBUGVIEW_LIT_BSDFDATA_ROUGHNESS_T:
result = bsdfData.roughnessT.xxx;
case DEBUGVIEW_LIT_BSDFDATA_ROUGHNESS_B:
result = bsdfData.roughnessB.xxx;
case DEBUGVIEW_LIT_BSDFDATA_ROUGHNESS_B:
result = bsdfData.roughnessB.xxx;
case DEBUGVIEW_LIT_BSDFDATA_SUB_SURFACE_RADIUS:
result = bsdfData.subSurfaceRadius.xxx;
case DEBUGVIEW_LIT_BSDFDATA_SUB_SURFACE_RADIUS:
result = bsdfData.subSurfaceRadius.xxx;
case DEBUGVIEW_LIT_BSDFDATA_THICKNESS:
result = bsdfData.thickness.xxx;
case DEBUGVIEW_LIT_BSDFDATA_THICKNESS:
result = bsdfData.thickness.xxx;
case DEBUGVIEW_LIT_BSDFDATA_SUB_SURFACE_PROFILE:
result = GetIndexColor(bsdfData.subSurfaceProfile);
case DEBUGVIEW_LIT_BSDFDATA_SUB_SURFACE_PROFILE:
result = GetIndexColor(bsdfData.subSurfaceProfile);
case DEBUGVIEW_LIT_BSDFDATA_COAT_NORMAL_WS:
result = bsdfData.coatNormalWS * 0.5 + 0.5;
case DEBUGVIEW_LIT_BSDFDATA_COAT_NORMAL_WS:
result = bsdfData.coatNormalWS * 0.5 + 0.5;
case DEBUGVIEW_LIT_BSDFDATA_COAT_ROUGHNESS:
result = bsdfData.coatRoughness.xxx;
case DEBUGVIEW_LIT_BSDFDATA_COAT_ROUGHNESS:
result = bsdfData.coatRoughness.xxx;
break;
}
}

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


#if GBUFFER_MATERIAL_COUNT == 3
#define OUTPUT_GBUFFER(NAME) \
out float4 MERGE_NAME(NAME, 0) : SV_Target0, \
out float4 MERGE_NAME(NAME, 1) : SV_Target1, \
#define OUTPUT_GBUFFER(NAME) \
out float4 MERGE_NAME(NAME, 0) : SV_Target0, \
out float4 MERGE_NAME(NAME, 1) : SV_Target1, \
#define DECLARE_GBUFFER_TEXTURE(NAME) \
Texture2D MERGE_NAME(NAME, 0); \
Texture2D MERGE_NAME(NAME, 1); \
#define DECLARE_GBUFFER_TEXTURE(NAME) \
Texture2D MERGE_NAME(NAME, 0); \
Texture2D MERGE_NAME(NAME, 1); \
#define FETCH_GBUFFER(NAME, TEX, UV) \
float4 MERGE_NAME(NAME, 0) = MERGE_NAME(TEX, 0).Load(uint3(UV, 0)); \
float4 MERGE_NAME(NAME, 1) = MERGE_NAME(TEX, 1).Load(uint3(UV, 0)); \
#define FETCH_GBUFFER(NAME, TEX, UV) \
float4 MERGE_NAME(NAME, 0) = MERGE_NAME(TEX, 0).Load(uint3(UV, 0)); \
float4 MERGE_NAME(NAME, 1) = MERGE_NAME(TEX, 1).Load(uint3(UV, 0)); \
float4 MERGE_NAME(NAME, 2) = MERGE_NAME(TEX, 2).Load(uint3(UV, 0));
#define ENCODE_INTO_GBUFFER(SURFACE_DATA, NAME) EncodeIntoGBuffer(SURFACE_DATA, MERGE_NAME(NAME,0), MERGE_NAME(NAME,1), MERGE_NAME(NAME,2))

#elif GBUFFER_MATERIAL_COUNT == 4
#define OUTPUT_GBUFFER(NAME) \
out float4 MERGE_NAME(NAME, 0) : SV_Target0, \
out float4 MERGE_NAME(NAME, 1) : SV_Target1, \
out float4 MERGE_NAME(NAME, 2) : SV_Target2, \
#define OUTPUT_GBUFFER(NAME) \
out float4 MERGE_NAME(NAME, 0) : SV_Target0, \
out float4 MERGE_NAME(NAME, 1) : SV_Target1, \
out float4 MERGE_NAME(NAME, 2) : SV_Target2, \
#define DECLARE_GBUFFER_TEXTURE(NAME) \
Texture2D MERGE_NAME(NAME, 0); \
Texture2D MERGE_NAME(NAME, 1); \
Texture2D MERGE_NAME(NAME, 2); \
#define DECLARE_GBUFFER_TEXTURE(NAME) \
Texture2D MERGE_NAME(NAME, 0); \
Texture2D MERGE_NAME(NAME, 1); \
Texture2D MERGE_NAME(NAME, 2); \
#define FETCH_GBUFFER(NAME, TEX, UV) \
float4 MERGE_NAME(NAME, 0) = MERGE_NAME(TEX, 0).Load(uint3(UV, 0)); \
float4 MERGE_NAME(NAME, 1) = MERGE_NAME(TEX, 1).Load(uint3(UV, 0)); \
float4 MERGE_NAME(NAME, 2) = MERGE_NAME(TEX, 2).Load(uint3(UV, 0)); \
#define FETCH_GBUFFER(NAME, TEX, UV) \
float4 MERGE_NAME(NAME, 0) = MERGE_NAME(TEX, 0).Load(uint3(UV, 0)); \
float4 MERGE_NAME(NAME, 1) = MERGE_NAME(TEX, 1).Load(uint3(UV, 0)); \
float4 MERGE_NAME(NAME, 2) = MERGE_NAME(TEX, 2).Load(uint3(UV, 0)); \
float4 MERGE_NAME(NAME, 3) = MERGE_NAME(TEX, 3).Load(uint3(UV, 0));
#define ENCODE_INTO_GBUFFER(SURFACE_DATA, NAME) EncodeIntoGBuffer(SURFACE_DATA, MERGE_NAME(NAME, 0), MERGE_NAME(NAME, 1), MERGE_NAME(NAME, 2), MERGE_NAME(NAME, 3))

#elif GBUFFER_MATERIAL_COUNT == 5
#define OUTPUT_GBUFFER(NAME) \
out float4 MERGE_NAME(NAME, 0) : SV_Target0, \
out float4 MERGE_NAME(NAME, 1) : SV_Target1, \
out float4 MERGE_NAME(NAME, 2) : SV_Target2, \
out float4 MERGE_NAME(NAME, 3) : SV_Target3, \
#define OUTPUT_GBUFFER(NAME) \
out float4 MERGE_NAME(NAME, 0) : SV_Target0, \
out float4 MERGE_NAME(NAME, 1) : SV_Target1, \
out float4 MERGE_NAME(NAME, 2) : SV_Target2, \
out float4 MERGE_NAME(NAME, 3) : SV_Target3, \
#define DECLARE_GBUFFER_TEXTURE(NAME) \
Texture2D MERGE_NAME(NAME, 0); \
Texture2D MERGE_NAME(NAME, 1); \
Texture2D MERGE_NAME(NAME, 2); \
Texture2D MERGE_NAME(NAME, 3); \
#define DECLARE_GBUFFER_TEXTURE(NAME) \
Texture2D MERGE_NAME(NAME, 0); \
Texture2D MERGE_NAME(NAME, 1); \
Texture2D MERGE_NAME(NAME, 2); \
Texture2D MERGE_NAME(NAME, 3); \
#define FETCH_GBUFFER(NAME, TEX, UV) \
float4 MERGE_NAME(NAME, 0) = MERGE_NAME(TEX, 0).Load(uint3(UV, 0)); \
float4 MERGE_NAME(NAME, 1) = MERGE_NAME(TEX, 1).Load(uint3(UV, 0)); \
float4 MERGE_NAME(NAME, 2) = MERGE_NAME(TEX, 2).Load(uint3(UV, 0)); \
float4 MERGE_NAME(NAME, 3) = MERGE_NAME(TEX, 3).Load(uint3(UV, 0)); \
#define FETCH_GBUFFER(NAME, TEX, UV) \
float4 MERGE_NAME(NAME, 0) = MERGE_NAME(TEX, 0).Load(uint3(UV, 0)); \
float4 MERGE_NAME(NAME, 1) = MERGE_NAME(TEX, 1).Load(uint3(UV, 0)); \
float4 MERGE_NAME(NAME, 2) = MERGE_NAME(TEX, 2).Load(uint3(UV, 0)); \
float4 MERGE_NAME(NAME, 3) = MERGE_NAME(TEX, 3).Load(uint3(UV, 0)); \
float4 MERGE_NAME(NAME, 4) = MERGE_NAME(TEX, 4).Load(uint3(UV, 0));
#define ENCODE_INTO_GBUFFER(SURFACE_DATA, NAME) EncodeIntoGBuffer(SURFACE_DATA, MERGE_NAME(NAME, 0), MERGE_NAME(NAME, 1), MERGE_NAME(NAME, 2), MERGE_NAME(NAME, 3), MERGE_NAME(NAME, 4))

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


// Final compositing pass, just does gamma correction for now.
Shader "Hidden/Unity/FinalPass"
Shader "Hidden/Unity/FinalPass"
Properties
{
_MainTex ("Texture", any) = "" {}
Properties
{
_MainTex ("Texture", any) = "" {}
_ToneMapCoeffs1("Parameters for neutral tonemap", Vector) = (0.0, 0.0, 0.0, 0.0)
_ToneMapCoeffs2("Parameters for neutral tonemap", Vector) = (0.0, 0.0, 0.0, 0.0)

SubShader {
SubShader {
Pass {
ZTest Always Cull Off ZWrite Off

#include "../ShaderVariables.hlsl"
UNITY_DECLARE_TEX2D(_MainTex);
float4 _ToneMapCoeffs1;
float4 _ToneMapCoeffs2;
float4 _ToneMapCoeffs1;
float4 _ToneMapCoeffs2;
#define InBlack _ToneMapCoeffs1.x
#define OutBlack _ToneMapCoeffs1.y
#define InWhite _ToneMapCoeffs1.z
#define OutWhite _ToneMapCoeffs1.w
#define WhiteLevel _ToneMapCoeffs2.z
#define WhiteClip _ToneMapCoeffs2.w
#define InBlack _ToneMapCoeffs1.x
#define OutBlack _ToneMapCoeffs1.y
#define InWhite _ToneMapCoeffs1.z
#define OutWhite _ToneMapCoeffs1.w
#define WhiteLevel _ToneMapCoeffs2.z
#define WhiteClip _ToneMapCoeffs2.w
float _Exposure;
float _EnableToneMap;

// return LinearToSRGB(c);
return c;
Fallback Off
Fallback Off
}

1
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/ShaderConfig.cs


// #define DIFFUSE_LAMBERT_BRDF
// #define USE_BSDF_PRE_LAMBDAV
// #define VELOCITY_IN_GBUFFER

16
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/ShaderVariables.hlsl


float4 _SinTime; // sin(t/8), sin(t/4), sin(t/2), sin(t)
float4 _CosTime; // cos(t/8), cos(t/4), cos(t/2), cos(t)
float4 unity_DeltaTime; // dt, 1/dt, smoothdt, 1/smoothdt
// Values used to linearize the Z buffer (http://www.humus.name/temp/Linearize%20depth.txt)
// x = 1-far/near
// y = far/near

#ifndef UNITY_SINGLE_PASS_STEREO
float4x4 glstate_matrix_mvp;
#endif
// Use center position for stereo rendering
float4x4 glstate_matrix_modelview0;
float4x4 glstate_matrix_invtrans_modelview0;

CBUFFER_START(UnityPerEye)
float3 _WorldSpaceCameraPos;
float4x4 glstate_matrix_projection;
float4x4 unity_MatrixV;
float4x4 unity_MatrixVP;

float4x4 unity_MatrixV;
float4x4 unity_MatrixVP;
#endif
float4 glstate_lightmodel_ambient;
float4 unity_AmbientSky;
float4 unity_AmbientEquator;

// For odd-negative scale transforms we need to flip the sign
float sign = tangentSign * GetOdddNegativeScale();
float3 bitangent = cross(normal, tangent) * sign;
return float3x3(tangent, bitangent, normal);
}

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


{
Properties
{
_Color("Color", Color) = (1,1,1,1)
_Color("Color", Color) = (1,1,1,1)
_ColorMap("ColorMap", 2D) = "white" {}
_EmissiveColor("EmissiveColor", Color) = (0, 0, 0)

[ToggleOff] _DistortionOnly("Distortion Only", Float) = 0.0
[ToggleOff] _DistortionDepthTest("Distortion Only", Float) = 0.0
[ToggleOff] _DistortionOnly("Distortion Only", Float) = 0.0
[ToggleOff] _DistortionDepthTest("Distortion Only", Float) = 0.0
[ToggleOff] _AlphaCutoffEnable("Alpha Cutoff Enable", Float) = 0.0
_AlphaCutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5

#include "Material/Material.hlsl"
#include "ShaderVariables.hlsl"
float4 _Color;
float4 _Color;
UNITY_DECLARE_TEX2D(_ColorMap);
float3 _EmissiveColor;
UNITY_DECLARE_TEX2D(_EmissiveColorMap);

Cull [_CullMode]
HLSLPROGRAM
#pragma vertex VertDefault
#pragma fragment FragForward

float3 positionOS : POSITION;
float2 uv0 : TEXCOORD0;
float3 positionOS : POSITION;
float2 uv0 : TEXCOORD0;
};
struct Varyings

builtinData.emissiveColor = UNITY_SAMPLE_TEX2D(_EmissiveColorMap, input.texCoord0).rgb * _EmissiveColor;
#else
builtinData.emissiveColor = _EmissiveColor;
#endif
#endif
builtinData.emissiveIntensity = _EmissiveIntensity;

689
Assets/ScriptableRenderLoop/RenderPasses/ShadowRenderPass.cs


namespace UnityEngine.ScriptableRenderLoop
{
[System.Serializable]
public struct ShadowSettings
{
public bool enabled;
public int shadowAtlasWidth;
public int shadowAtlasHeight;
[System.Serializable]
public struct ShadowSettings
{
public bool enabled;
public int shadowAtlasWidth;
public int shadowAtlasHeight;
public float maxShadowDistance;
public int directionalLightCascadeCount;
public Vector3 directionalLightCascades;
public float maxShadowDistance;
public int directionalLightCascadeCount;
public Vector3 directionalLightCascades;
public static ShadowSettings Default
{
get
{
ShadowSettings settings;
settings.enabled = true;
settings.shadowAtlasHeight = settings.shadowAtlasWidth = 4096;
settings.directionalLightCascadeCount = 1;
settings.directionalLightCascades = new Vector3 (0.05F, 0.2F, 0.3F);
settings.directionalLightCascadeCount = 4;
settings.maxShadowDistance = 1000.0F;
return settings;
}
}
}
public static ShadowSettings Default
{
get
{
ShadowSettings settings;
settings.enabled = true;
settings.shadowAtlasHeight = settings.shadowAtlasWidth = 4096;
settings.directionalLightCascadeCount = 1;
settings.directionalLightCascades = new Vector3(0.05F, 0.2F, 0.3F);
settings.directionalLightCascadeCount = 4;
settings.maxShadowDistance = 1000.0F;
return settings;
}
}
}
public struct InputShadowLightData
{
public int lightIndex;
public int shadowResolution;
}
public struct ShadowLight
{
public int shadowSliceIndex;
public int shadowSliceCount;
}
public struct ShadowSliceData
{
public Matrix4x4 shadowTransform;
public int atlasX;
public int atlasY;
public int shadowResolution;
}
public struct InputShadowLightData
{
public int lightIndex;
public int shadowResolution;
}
public struct ShadowOutput
{
public ShadowSliceData[] shadowSlices;
public ShadowLight[] shadowLights;
public Vector4[] directionalShadowSplitSphereSqr;
public struct ShadowLight
{
public int shadowSliceIndex;
public int shadowSliceCount;
}
public int GetShadowSliceCountLightIndex(int lightIndex)
{
return shadowLights[lightIndex].shadowSliceCount;
}
public struct ShadowSliceData
{
public Matrix4x4 shadowTransform;
public int atlasX;
public int atlasY;
public int shadowResolution;
}
public int GetShadowSliceIndex(int lightIndex, int sliceIndex)
{
if (sliceIndex >= shadowLights[lightIndex].shadowSliceCount)
throw new System.IndexOutOfRangeException();
public struct ShadowOutput
{
public ShadowSliceData[] shadowSlices;
public ShadowLight[] shadowLights;
public Vector4[] directionalShadowSplitSphereSqr;
return shadowLights[lightIndex].shadowSliceIndex + sliceIndex;
}
}
public int GetShadowSliceCountLightIndex(int lightIndex)
{
return shadowLights[lightIndex].shadowSliceCount;
}
public struct ShadowRenderPass : IDisposable
{
ShadowSettings m_Settings;
public int GetShadowSliceIndex(int lightIndex, int sliceIndex)
{
if (sliceIndex >= shadowLights[lightIndex].shadowSliceCount)
throw new System.IndexOutOfRangeException ();
return shadowLights[lightIndex].shadowSliceIndex + sliceIndex;
}
}
public struct ShadowRenderPass : IDisposable
{
ShadowSettings m_Settings;
[NonSerialized]
bool m_bFailedToPackLastTime;
int m_ShadowTexName;
const int kDepthBuffer = 24;
[NonSerialized]
bool m_bFailedToPackLastTime;
int m_ShadowTexName;
const int kDepthBuffer = 24;
public ShadowRenderPass(ShadowSettings settings)
{
m_Settings = settings;
m_bFailedToPackLastTime = false;
m_ShadowTexName = Shader.PropertyToID("g_tShadowBuffer");
}
public ShadowRenderPass(ShadowSettings settings)
{
m_Settings = settings;
m_bFailedToPackLastTime = false;
m_ShadowTexName = Shader.PropertyToID("g_tShadowBuffer");
}
public void Dispose()
{
}
public void Dispose()
{
}
struct AtlasEntry
{
public AtlasEntry(int splitIndex, int lightIndex)
{
this.splitIndex = splitIndex;
this.lightIndex = lightIndex;
}
struct AtlasEntry
{
public AtlasEntry(int splitIndex, int lightIndex)
{
this.splitIndex = splitIndex;
this.lightIndex = lightIndex;
}
public int splitIndex;
public int lightIndex;
}
public int splitIndex;
public int lightIndex;
}
int CalculateNumShadowSplits(int index, VisibleLight[] lights)
{
LightType lightType = lights[index].lightType;
if (lightType == LightType.Spot)
return 1;
int CalculateNumShadowSplits(int index, VisibleLight[] lights)
{
LightType lightType = lights [index].lightType;
if (lightType == LightType.Spot)
return 1;
if (lightType == LightType.Directional)
return m_Settings.directionalLightCascadeCount;
if (lightType == LightType.Directional)
return m_Settings.directionalLightCascadeCount;
return 6;
}
return 6;
}
static public void ClearPackedShadows(VisibleLight[] lights, out ShadowOutput packedShadows)
{
packedShadows.directionalShadowSplitSphereSqr = null;
packedShadows.shadowSlices = null;
packedShadows.shadowLights = new ShadowLight[lights.Length];
}
static public void ClearPackedShadows(VisibleLight[] lights, out ShadowOutput packedShadows)
{
packedShadows.directionalShadowSplitSphereSqr = null;
packedShadows.shadowSlices = null;
packedShadows.shadowLights = new ShadowLight[lights.Length];
}
//---------------------------------------------------------------------------------------------------------------------------------------------------
bool AutoPackLightsIntoShadowTexture(List<InputShadowLightData> shadowLights, VisibleLight[] lights, out ShadowOutput packedShadows)
{
Dictionary<int, InputShadowLightData> activeShadowLights = new Dictionary<int, InputShadowLightData>();
List<int> shadowIndices = new List<int>();
//---------------------------------------------------------------------------------------------------------------------------------------------------
bool AutoPackLightsIntoShadowTexture(List<InputShadowLightData> shadowLights, VisibleLight[] lights, out ShadowOutput packedShadows)
{
Dictionary<int, InputShadowLightData> activeShadowLights = new Dictionary<int, InputShadowLightData>();
List<int> shadowIndices = new List<int>();
//@TODO: Disallow multiple directional lights
//@TODO: Disallow multiple directional lights
for (int i = 0; i < shadowLights.Count; i++)
{
shadowIndices.Add(shadowLights[i].lightIndex);
activeShadowLights[shadowLights[i].lightIndex] = shadowLights[i];
}
for (int i = 0; i < shadowLights.Count; i++)
{
shadowIndices.Add (shadowLights[i].lightIndex);
activeShadowLights[shadowLights[i].lightIndex] = shadowLights[i];
}
// World's stupidest sheet packer:
// 1. Sort all lights from largest to smallest
// 2. In a left->right, top->bottom pattern, fill quads until you reach the edge of the texture
// 3. Move position to x=0, y=bottomOfFirstTextureInThisRow
// 4. Goto 2.
// Yes, this will produce holes as the quads shrink, but it's good enough for now. I'll work on this more later to fill the gaps.
// World's stupidest sheet packer:
// 1. Sort all lights from largest to smallest
// 2. In a left->right, top->bottom pattern, fill quads until you reach the edge of the texture
// 3. Move position to x=0, y=bottomOfFirstTextureInThisRow
// 4. Goto 2.
// Yes, this will produce holes as the quads shrink, but it's good enough for now. I'll work on this more later to fill the gaps.
// Sort all lights from largest to smallest
shadowIndices.Sort(
delegate(int l1, int l2)
{
int nCompare = 0;
// Sort shadow-casting lights by shadow resolution
nCompare = activeShadowLights[l1].shadowResolution.CompareTo(activeShadowLights[l2].shadowResolution); // Sort by shadow size
// Sort all lights from largest to smallest
shadowIndices.Sort(
delegate( int l1, int l2 )
{
int nCompare = 0;
// Sort shadow-casting lights by shadow resolution
nCompare = activeShadowLights[l1].shadowResolution.CompareTo(activeShadowLights[l2].shadowResolution); // Sort by shadow size
if (nCompare == 0) // Same, so sort by range to stabilize sort results
nCompare = lights[l1].range.CompareTo(lights[l2].range); // Sort by shadow size
if ( nCompare == 0 ) // Same, so sort by range to stabilize sort results
nCompare = lights[l1].range.CompareTo( lights[l2].range ); // Sort by shadow size
if (nCompare == 0) // Still same, so sort by instance ID to stabilize sort results
nCompare = lights[l1].light.GetInstanceID().CompareTo(lights[l2].light.GetInstanceID());
if ( nCompare == 0 ) // Still same, so sort by instance ID to stabilize sort results
nCompare = lights[l1].light.GetInstanceID().CompareTo( lights[l2].light.GetInstanceID() );
return nCompare;
}
);
return nCompare;
}
);
// Start filling lights into texture
List<AtlasEntry> requestedPages = new List<AtlasEntry>();
packedShadows.shadowLights = new ShadowLight[lights.Length];
for (int i = 0; i != shadowIndices.Count;i++)
{
int numShadowSplits = CalculateNumShadowSplits(shadowIndices[i], lights);
// Start filling lights into texture
List<AtlasEntry> requestedPages = new List<AtlasEntry>();
packedShadows.shadowLights = new ShadowLight[lights.Length];
for (int i = 0; i != shadowIndices.Count; i++)
{
int numShadowSplits = CalculateNumShadowSplits(shadowIndices[i], lights);
packedShadows.shadowLights[shadowIndices [i]].shadowSliceCount = numShadowSplits;
packedShadows.shadowLights[shadowIndices [i]].shadowSliceIndex = requestedPages.Count;
packedShadows.shadowLights[shadowIndices[i]].shadowSliceCount = numShadowSplits;
packedShadows.shadowLights[shadowIndices[i]].shadowSliceIndex = requestedPages.Count;
for (int s = 0; s < numShadowSplits; s++)
requestedPages.Add (new AtlasEntry (requestedPages.Count, shadowIndices[i]));
}
for (int s = 0; s < numShadowSplits; s++)
requestedPages.Add(new AtlasEntry(requestedPages.Count, shadowIndices[i]));
}
int nCurrentX = 0;
int nCurrentY = -1;
int nNextY = 0;
int nCurrentX = 0;
int nCurrentY = -1;
int nNextY = 0;
packedShadows.shadowSlices = new ShadowSliceData[requestedPages.Count];
packedShadows.directionalShadowSplitSphereSqr = new Vector4[4];
packedShadows.shadowSlices = new ShadowSliceData[requestedPages.Count];
packedShadows.directionalShadowSplitSphereSqr = new Vector4[4];
foreach (AtlasEntry entry in requestedPages)
{
int shadowResolution = activeShadowLights[entry.lightIndex].shadowResolution;
foreach (AtlasEntry entry in requestedPages)
{
int shadowResolution = activeShadowLights[entry.lightIndex].shadowResolution;
// Check if first texture is too wide
if ( nCurrentY == -1 )
{
if ( ( shadowResolution > m_Settings.shadowAtlasWidth ) || ( shadowResolution > m_Settings.shadowAtlasHeight ) )
{
Debug.LogError( "ERROR! Shadow packer ran out of space in the " + m_Settings.shadowAtlasWidth + "x" + m_Settings.shadowAtlasHeight + " texture!\n\n" );
m_bFailedToPackLastTime = true;
ClearPackedShadows (lights, out packedShadows);
return false;
}
}
// Check if first texture is too wide
if (nCurrentY == -1)
{
if ((shadowResolution > m_Settings.shadowAtlasWidth) || (shadowResolution > m_Settings.shadowAtlasHeight))
{
Debug.LogError("ERROR! Shadow packer ran out of space in the " + m_Settings.shadowAtlasWidth + "x" + m_Settings.shadowAtlasHeight + " texture!\n\n");
m_bFailedToPackLastTime = true;
ClearPackedShadows(lights, out packedShadows);
return false;
}
}
// Goto next scanline
if ( ( nCurrentY == -1 ) || ( ( nCurrentX + shadowResolution ) > m_Settings.shadowAtlasWidth ) )
{
nCurrentX = 0;
nCurrentY = nNextY;
nNextY += shadowResolution;
}
// Goto next scanline
if ((nCurrentY == -1) || ((nCurrentX + shadowResolution) > m_Settings.shadowAtlasWidth))
{
nCurrentX = 0;
nCurrentY = nNextY;
nNextY += shadowResolution;
}
// Check if we've run out of space
if ( ( nCurrentY + shadowResolution ) > m_Settings.shadowAtlasHeight )
{
Debug.LogError( "ERROR! Shadow packer ran out of space in the " + m_Settings.shadowAtlasWidth + "x" + m_Settings.shadowAtlasHeight + " texture!\n\n" );
m_bFailedToPackLastTime = true;
ClearPackedShadows (lights, out packedShadows);
return false;
}
// Check if we've run out of space
if ((nCurrentY + shadowResolution) > m_Settings.shadowAtlasHeight)
{
Debug.LogError("ERROR! Shadow packer ran out of space in the " + m_Settings.shadowAtlasWidth + "x" + m_Settings.shadowAtlasHeight + " texture!\n\n");
m_bFailedToPackLastTime = true;
ClearPackedShadows(lights, out packedShadows);
return false;
}
// Save location to light
packedShadows.shadowSlices[entry.splitIndex].atlasX = nCurrentX;
packedShadows.shadowSlices[entry.splitIndex].atlasY = nCurrentY;
packedShadows.shadowSlices[entry.splitIndex].shadowResolution = shadowResolution;
// Save location to light
packedShadows.shadowSlices[entry.splitIndex].atlasX = nCurrentX;
packedShadows.shadowSlices[entry.splitIndex].atlasY = nCurrentY;
packedShadows.shadowSlices[entry.splitIndex].shadowResolution = shadowResolution;
// Move ahead
nCurrentX += shadowResolution;
// Move ahead
nCurrentX += shadowResolution;
//Debug.Log( "Sheet packer: " + vl.m_cachedLight.name + " ( " + vl.m_shadowX + ", " + vl.m_shadowY + " ) " + vl.m_shadowResolution + "\n\n" );
}
//Debug.Log( "Sheet packer: " + vl.m_cachedLight.name + " ( " + vl.m_shadowX + ", " + vl.m_shadowY + " ) " + vl.m_shadowResolution + "\n\n" );
}
if ( m_bFailedToPackLastTime )
{
m_bFailedToPackLastTime = false;
Debug.Log( "SUCCESS! Shadow packer can now fit all lights into the " + m_Settings.shadowAtlasWidth + "x" + m_Settings.shadowAtlasHeight + " texture!\n\n" );
}
if (m_bFailedToPackLastTime)
{
m_bFailedToPackLastTime = false;
Debug.Log("SUCCESS! Shadow packer can now fit all lights into the " + m_Settings.shadowAtlasWidth + "x" + m_Settings.shadowAtlasHeight + " texture!\n\n");
}
return requestedPages.Count != 0;
}
return requestedPages.Count != 0;
}
static List<InputShadowLightData> GetInputShadowLightData(CullResults cullResults)
{
var shadowCasters = new List<InputShadowLightData> ();
VisibleLight[] lights = cullResults.visibleLights;
int directionalLightCount = 0;
for (int i = 0; i < lights.Length; i++)
{
//@TODO: ignore baked. move this logic to c++...
if (lights[i].light.shadows != LightShadows.None)
{
static List<InputShadowLightData> GetInputShadowLightData(CullResults cullResults)
{
var shadowCasters = new List<InputShadowLightData>();
VisibleLight[] lights = cullResults.visibleLights;
int directionalLightCount = 0;
for (int i = 0; i < lights.Length; i++)
{
//@TODO: ignore baked. move this logic to c++...
if (lights[i].light.shadows != LightShadows.None)
{
// Only a single directional shadow casting light is supported
if (lights[i].lightType == LightType.Directional)
{
directionalLightCount++;
if (directionalLightCount != 1)
continue;
}
// Only a single directional shadow casting light is supported
if (lights [i].lightType == LightType.Directional)
{
directionalLightCount++;
if (directionalLightCount != 1)
continue;
}
AdditionalLightData additionalLight = lights[i].light.GetComponent<AdditionalLightData>();
AdditionalLightData additionalLight = lights [i].light.GetComponent<AdditionalLightData> ();
InputShadowLightData light;
light.lightIndex = i;
light.shadowResolution = AdditionalLightData.GetShadowResolution(additionalLight);
InputShadowLightData light;
light.lightIndex = i;
light.shadowResolution = AdditionalLightData.GetShadowResolution(additionalLight);
shadowCasters.Add(light);
}
}
return shadowCasters;
}
shadowCasters.Add (light);
}
}
return shadowCasters;
}
public void UpdateCullingParameters(ref CullingParameters parameters)
{
parameters.shadowDistance = Mathf.Min(m_Settings.maxShadowDistance, parameters.shadowDistance);
}
public void UpdateCullingParameters(ref CullingParameters parameters)
{
parameters.shadowDistance = Mathf.Min (m_Settings.maxShadowDistance, parameters.shadowDistance);
}
public void Render(RenderLoop loop, CullResults cullResults, out ShadowOutput packedShadows)
{
if (!m_Settings.enabled)
{
ClearPackedShadows(cullResults.visibleLights, out packedShadows);
}
public void Render(RenderLoop loop, CullResults cullResults, out ShadowOutput packedShadows)
{
if (!m_Settings.enabled)
{
ClearPackedShadows(cullResults.visibleLights, out packedShadows);
}
// Pack all shadow quads into the texture
if (!AutoPackLightsIntoShadowTexture(GetInputShadowLightData(cullResults), cullResults.visibleLights, out packedShadows))
{
// No shadowing lights found, so skip all rendering
return;
}
// Pack all shadow quads into the texture
if ( !AutoPackLightsIntoShadowTexture(GetInputShadowLightData(cullResults), cullResults.visibleLights, out packedShadows) )
{
// No shadowing lights found, so skip all rendering
return;
}
RenderPackedShadows(loop, cullResults, ref packedShadows);
}
RenderPackedShadows (loop, cullResults, ref packedShadows);
}
//---------------------------------------------------------------------------------------------------------------------------------------------------
// Render shadows
//---------------------------------------------------------------------------------------------------------------------------------------------------
void RenderPackedShadows(RenderLoop loop, CullResults cullResults, ref ShadowOutput packedShadows)
{
var setRenderTargetCommandBuffer = new CommandBuffer();
//---------------------------------------------------------------------------------------------------------------------------------------------------
// Render shadows
//---------------------------------------------------------------------------------------------------------------------------------------------------
void RenderPackedShadows(RenderLoop loop, CullResults cullResults, ref ShadowOutput packedShadows)
{
var setRenderTargetCommandBuffer = new CommandBuffer ();
setRenderTargetCommandBuffer.name = "Render packed shadows";
setRenderTargetCommandBuffer.GetTemporaryRT(m_ShadowTexName, m_Settings.shadowAtlasWidth, m_Settings.shadowAtlasHeight, kDepthBuffer, FilterMode.Bilinear, RenderTextureFormat.Shadowmap, RenderTextureReadWrite.Linear);
setRenderTargetCommandBuffer.SetRenderTarget(new RenderTargetIdentifier(m_ShadowTexName));
setRenderTargetCommandBuffer.name = "Render packed shadows";
setRenderTargetCommandBuffer.GetTemporaryRT (m_ShadowTexName, m_Settings.shadowAtlasWidth, m_Settings.shadowAtlasHeight, kDepthBuffer, FilterMode.Bilinear, RenderTextureFormat.Shadowmap, RenderTextureReadWrite.Linear);
setRenderTargetCommandBuffer.SetRenderTarget (new RenderTargetIdentifier (m_ShadowTexName));
setRenderTargetCommandBuffer.ClearRenderTarget(true, true, Color.green);
loop.ExecuteCommandBuffer(setRenderTargetCommandBuffer);
setRenderTargetCommandBuffer.Dispose();
setRenderTargetCommandBuffer.ClearRenderTarget (true, true, Color.green);
loop.ExecuteCommandBuffer (setRenderTargetCommandBuffer);
setRenderTargetCommandBuffer.Dispose ();
VisibleLight[] visibleLights = cullResults.visibleLights;
var shadowSlices = packedShadows.shadowSlices;
VisibleLight[] visibleLights = cullResults.visibleLights;
var shadowSlices = packedShadows.shadowSlices;
// Render each light's shadow buffer into a subrect of the shared depth texture
for (int lightIndex = 0; lightIndex < packedShadows.shadowLights.Length; lightIndex++)
{
int shadowSliceCount = packedShadows.shadowLights[lightIndex].shadowSliceCount;
if (shadowSliceCount == 0)
continue;
// Render each light's shadow buffer into a subrect of the shared depth texture
for ( int lightIndex = 0; lightIndex < packedShadows.shadowLights.Length; lightIndex++ )
{
int shadowSliceCount = packedShadows.shadowLights[lightIndex].shadowSliceCount;
if (shadowSliceCount == 0)
continue;
Profiler.BeginSample ("Shadows.GetShadowCasterBounds");
Bounds bounds;
if (!cullResults.GetShadowCasterBounds (lightIndex, out bounds))
{
Profiler.EndSample ();
return;
}
Profiler.EndSample ();
Profiler.BeginSample("Shadows.GetShadowCasterBounds");
Bounds bounds;
if (!cullResults.GetShadowCasterBounds(lightIndex, out bounds))
{
Profiler.EndSample();
return;
}
Profiler.EndSample();
Profiler.BeginSample ("Shadows.DrawShadows");
Profiler.BeginSample("Shadows.DrawShadows");
Matrix4x4 proj;
Matrix4x4 view;
Matrix4x4 proj;
Matrix4x4 view;
LightType lightType = visibleLights[lightIndex].lightType;
Vector3 lightDirection = visibleLights[lightIndex].light.transform.forward;
var shadowNearClip = visibleLights[lightIndex].light.shadowNearPlane;
LightType lightType = visibleLights[lightIndex].lightType;
Vector3 lightDirection = visibleLights[lightIndex].light.transform.forward;
var shadowNearClip = visibleLights[lightIndex].light.shadowNearPlane;
int shadowSliceIndex = packedShadows.GetShadowSliceIndex (lightIndex, 0);
if (lightType == LightType.Spot)
{
DrawShadowsSettings settings = new DrawShadowsSettings(cullResults, lightIndex);
bool needRendering = cullResults.ComputeSpotShadowsMatricesAndCullingPrimitives(lightIndex, out view, out proj, out settings.splitData);
SetupShadowSplitMatrices(ref packedShadows.shadowSlices[shadowSliceIndex], proj, view);
if (needRendering)
RenderShadowSplit(ref shadowSlices[shadowSliceIndex], lightDirection, proj, view, ref loop, settings);
}
else if (lightType == LightType.Directional)
{
Vector3 splitRatio = m_Settings.directionalLightCascades;
int shadowSliceIndex = packedShadows.GetShadowSliceIndex(lightIndex, 0);
for (int s = 0; s < 4; ++s)
packedShadows.directionalShadowSplitSphereSqr[s] = new Vector4 (0, 0, 0, float.NegativeInfinity);
if (lightType == LightType.Spot)
{
DrawShadowsSettings settings = new DrawShadowsSettings(cullResults, lightIndex);
bool needRendering = cullResults.ComputeSpotShadowsMatricesAndCullingPrimitives(lightIndex, out view, out proj, out settings.splitData);
SetupShadowSplitMatrices(ref packedShadows.shadowSlices[shadowSliceIndex], proj, view);
if (needRendering)
RenderShadowSplit(ref shadowSlices[shadowSliceIndex], lightDirection, proj, view, ref loop, settings);
}
else if (lightType == LightType.Directional)
{
Vector3 splitRatio = m_Settings.directionalLightCascades;
for (int s = 0; s < shadowSliceCount; ++s, shadowSliceIndex++)
{
var settings = new DrawShadowsSettings(cullResults, lightIndex);
var shadowResolution = shadowSlices [shadowSliceIndex].shadowResolution;
bool needRendering = cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(lightIndex, s, shadowSliceCount, splitRatio, shadowResolution, shadowNearClip, out view, out proj, out settings.splitData);
for (int s = 0; s < 4; ++s)
packedShadows.directionalShadowSplitSphereSqr[s] = new Vector4(0, 0, 0, float.NegativeInfinity);
packedShadows.directionalShadowSplitSphereSqr[s] = settings.splitData.cullingSphere;
packedShadows.directionalShadowSplitSphereSqr[s].w *= packedShadows.directionalShadowSplitSphereSqr[s].w;
for (int s = 0; s < shadowSliceCount; ++s, shadowSliceIndex++)
{
var settings = new DrawShadowsSettings(cullResults, lightIndex);
var shadowResolution = shadowSlices[shadowSliceIndex].shadowResolution;
bool needRendering = cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(lightIndex, s, shadowSliceCount, splitRatio, shadowResolution, shadowNearClip, out view, out proj, out settings.splitData);
SetupShadowSplitMatrices(ref shadowSlices[shadowSliceIndex], proj, view);
if (needRendering)
RenderShadowSplit(ref shadowSlices[shadowSliceIndex], lightDirection, proj, view, ref loop, settings);
}
}
else if (lightType == LightType.Point)
{
for(int s = 0; s < shadowSliceCount; ++s, shadowSliceIndex++)
{
DrawShadowsSettings settings = new DrawShadowsSettings(cullResults, lightIndex);
bool needRendering = cullResults.ComputePointShadowsMatricesAndCullingPrimitives(lightIndex, (CubemapFace)s, 2.0f, out view, out proj, out settings.splitData);
packedShadows.directionalShadowSplitSphereSqr[s] = settings.splitData.cullingSphere;
packedShadows.directionalShadowSplitSphereSqr[s].w *= packedShadows.directionalShadowSplitSphereSqr[s].w;
SetupShadowSplitMatrices(ref shadowSlices[shadowSliceIndex], proj, view);
if (needRendering)
RenderShadowSplit(ref shadowSlices[shadowSliceIndex], lightDirection, proj, view, ref loop, settings);
}
}
Profiler.EndSample ();
}
}
SetupShadowSplitMatrices(ref shadowSlices[shadowSliceIndex], proj, view);
if (needRendering)
RenderShadowSplit(ref shadowSlices[shadowSliceIndex], lightDirection, proj, view, ref loop, settings);
}
}
else if (lightType == LightType.Point)
{
for (int s = 0; s < shadowSliceCount; ++s, shadowSliceIndex++)
{
DrawShadowsSettings settings = new DrawShadowsSettings(cullResults, lightIndex);
bool needRendering = cullResults.ComputePointShadowsMatricesAndCullingPrimitives(lightIndex, (CubemapFace)s, 2.0f, out view, out proj, out settings.splitData);
SetupShadowSplitMatrices(ref shadowSlices[shadowSliceIndex], proj, view);
if (needRendering)
RenderShadowSplit(ref shadowSlices[shadowSliceIndex], lightDirection, proj, view, ref loop, settings);
}
}
Profiler.EndSample();
}
}
private void SetupShadowSplitMatrices(ref ShadowSliceData lightData, Matrix4x4 proj, Matrix4x4 view)
{
Matrix4x4 matScaleBias = Matrix4x4.identity;
matScaleBias.m00 = 0.5f;
matScaleBias.m11 = 0.5f;
matScaleBias.m22 = 0.5f;
matScaleBias.m03 = 0.5f;
matScaleBias.m13 = 0.5f;
matScaleBias.m23 = 0.5f;
private void SetupShadowSplitMatrices(ref ShadowSliceData lightData, Matrix4x4 proj, Matrix4x4 view)
{
Matrix4x4 matScaleBias = Matrix4x4.identity;
matScaleBias.m00 = 0.5f;
matScaleBias.m11 = 0.5f;
matScaleBias.m22 = 0.5f;
matScaleBias.m03 = 0.5f;
matScaleBias.m13 = 0.5f;
matScaleBias.m23 = 0.5f;
Matrix4x4 matTile = Matrix4x4.identity;
matTile.m00 = (float)lightData.shadowResolution / (float)m_Settings.shadowAtlasWidth;
matTile.m11 = (float)lightData.shadowResolution / (float)m_Settings.shadowAtlasHeight;
matTile.m03 = (float)lightData.atlasX / (float)m_Settings.shadowAtlasWidth;
matTile.m13 = (float)lightData.atlasY / (float)m_Settings.shadowAtlasHeight;
lightData.shadowTransform = matTile * matScaleBias * proj * view;
}
Matrix4x4 matTile = Matrix4x4.identity;
matTile.m00 = (float)lightData.shadowResolution / (float)m_Settings.shadowAtlasWidth;
matTile.m11 = (float)lightData.shadowResolution / (float)m_Settings.shadowAtlasHeight;
matTile.m03 = (float)lightData.atlasX / (float)m_Settings.shadowAtlasWidth;
matTile.m13 = (float)lightData.atlasY / (float)m_Settings.shadowAtlasHeight;
lightData.shadowTransform = matTile * matScaleBias * proj * view;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------
private void RenderShadowSplit(ref ShadowSliceData slice, Vector3 lightDirection, Matrix4x4 proj, Matrix4x4 view, ref RenderLoop loop, DrawShadowsSettings settings)
{
var commandBuffer = new CommandBuffer();
commandBuffer.name = "ShadowSetup";
//---------------------------------------------------------------------------------------------------------------------------------------------------
private void RenderShadowSplit(ref ShadowSliceData slice, Vector3 lightDirection, Matrix4x4 proj, Matrix4x4 view, ref RenderLoop loop, DrawShadowsSettings settings)
{
var commandBuffer = new CommandBuffer();
commandBuffer.name = "ShadowSetup";
// Set viewport / matrices etc
commandBuffer.SetViewport(new Rect(slice.atlasX, slice.atlasY, slice.shadowResolution, slice.shadowResolution));
//commandBuffer.ClearRenderTarget (true, true, Color.green);
commandBuffer.SetGlobalVector("g_vLightDirWs", new Vector4(lightDirection.x, lightDirection.y, lightDirection.z));
commandBuffer.SetProjectionAndViewMatrices(proj, view);
// commandBuffer.SetGlobalDepthBias (1.0F, 1.0F);
loop.ExecuteCommandBuffer(commandBuffer);
commandBuffer.Dispose();
// Set viewport / matrices etc
commandBuffer.SetViewport(new Rect(slice.atlasX, slice.atlasY, slice.shadowResolution, slice.shadowResolution));
//commandBuffer.ClearRenderTarget (true, true, Color.green);
commandBuffer.SetGlobalVector("g_vLightDirWs", new Vector4(lightDirection.x, lightDirection.y, lightDirection.z));
commandBuffer.SetProjectionAndViewMatrices(proj, view);
// commandBuffer.SetGlobalDepthBias (1.0F, 1.0F);
loop.ExecuteCommandBuffer(commandBuffer);
commandBuffer.Dispose();
// Render
loop.DrawShadows(ref settings);
}
}
// Render
loop.DrawShadows(ref settings);
}
}
}

20
Assets/ScriptableRenderLoop/ScriptableRenderLoop.cs


using UnityEngine;
using UnityEngine;
public abstract class ScriptableRenderLoop : ScriptableObject
{
public abstract void Render(Camera[] cameras, RenderLoop renderLoop);
public virtual void Rebuild() { }
public abstract class ScriptableRenderLoop : ScriptableObject
{
public abstract void Render(Camera[] cameras, RenderLoop renderLoop);
public virtual void Rebuild() {}
#if UNITY_EDITOR
public virtual UnityEditor.SupportedRenderingFeatures GetSupportedRenderingFeatures() { return new UnityEditor.SupportedRenderingFeatures(); }
#endif
}
}
#if UNITY_EDITOR
public virtual UnityEditor.SupportedRenderingFeatures GetSupportedRenderingFeatures() { return new UnityEditor.SupportedRenderingFeatures(); }
#endif
}
}

98
Assets/ScriptableRenderLoop/ScriptableRenderLoopPicker.cs


using UnityEngine;
using UnityEngine;
using System.Collections;
using UnityEngine.Rendering;
using System.Collections.Generic;

{
//@TODO: This should be moved into GraphicsSettings
[ExecuteInEditMode]
public class ScriptableRenderLoopPicker : MonoBehaviour
{
public ScriptableRenderLoop renderloop
{
get { return m_RenderLoop; }
set { m_RenderLoop = value; }
}
//@TODO: This should be moved into GraphicsSettings
[ExecuteInEditMode]
public class ScriptableRenderLoopPicker : MonoBehaviour
{
public ScriptableRenderLoop renderloop
{
get { return m_RenderLoop; }
set { m_RenderLoop = value; }
}
[SerializeField]
private ScriptableRenderLoop m_RenderLoop;
[SerializeField]
private ScriptableRenderLoop m_RenderLoop;
void OnEnable ()
{
RenderLoop.renderLoopDelegate += Render;
void OnEnable()
{
RenderLoop.renderLoopDelegate += Render;
SyncRenderingFeatures();
}
SyncRenderingFeatures();
}
void OnValidate()
{
SyncRenderingFeatures();
}
void OnValidate()
{
SyncRenderingFeatures();
}
void SyncRenderingFeatures ()
{
void SyncRenderingFeatures()
{
if (m_RenderLoop != null && isActiveAndEnabled)
UnityEditor.SupportedRenderingFeatures.active = m_RenderLoop.GetSupportedRenderingFeatures();
else
UnityEditor.SupportedRenderingFeatures.active = UnityEditor.SupportedRenderingFeatures.Default;
if (m_RenderLoop != null && isActiveAndEnabled)
UnityEditor.SupportedRenderingFeatures.active = m_RenderLoop.GetSupportedRenderingFeatures();
else
UnityEditor.SupportedRenderingFeatures.active = UnityEditor.SupportedRenderingFeatures.Default;
}
}
void OnDisable ()
{
RenderLoop.renderLoopDelegate -= Render;
void OnDisable()
{
RenderLoop.renderLoopDelegate -= Render;
#if UNITY_EDITOR
UnityEditor.SupportedRenderingFeatures.active = UnityEditor.SupportedRenderingFeatures.Default;
#endif
}
#if UNITY_EDITOR
UnityEditor.SupportedRenderingFeatures.active = UnityEditor.SupportedRenderingFeatures.Default;
#endif
}
bool Render(Camera[] cameras, RenderLoop loop)
{
if (m_RenderLoop == null)
return false;
bool Render(Camera[] cameras, RenderLoop loop)
{
if (m_RenderLoop == null)
return false;
if (m_AssetVersion != ms_GlobalAssetVersion)
{
m_AssetVersion = ms_GlobalAssetVersion;
m_RenderLoop.Rebuild();
}
if (m_AssetVersion != ms_GlobalAssetVersion)
{
m_AssetVersion = ms_GlobalAssetVersion;
m_RenderLoop.Rebuild();
}
m_RenderLoop.Render (cameras, loop);
return true;
}
m_RenderLoop.Render(cameras, loop);
return true;
}
// Temporary hack to allow compute shader reloading
internal class AssetReloader : UnityEditor.AssetPostprocessor
// Temporary hack to allow compute shader reloading
internal class AssetReloader : UnityEditor.AssetPostprocessor
{
static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
{

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


// 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.
// - 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

18
Assets/ScriptableRenderLoop/ShaderLibrary/BSDF.hlsl


float F_Schlick(float f0, float f90, float u)
{
float x = 1.0 - u;
float x5 = x * x;
x5 = x5 * x5 * x;
float x = 1.0 - u;
float x5 = x * x;
x5 = x5 * x5 * x;
return (f90 - f0) * x5 + f0; // sub mul mul mul sub mad
}

float3 F_Schlick(float3 f0, float f90, float u)
{
float x = 1.0 - u;
float x5 = x * x;
x5 = x5 * x5 * x;
float x = 1.0 - u;
float x5 = x * x;
x5 = x5 * x5 * x;
return (float3(f90, f90, f90) - f0) * x5 + f0; // sub mul mul mul sub mad
}

float V_SmithJointGGX(float NdotL, float NdotV, float roughness)
{
// Original formulation:
// lambda_v = (-1 + sqrt(a2 * (1 - NdotL2) / NdotL2 + 1)) * 0.5f;
// lambda_l = (-1 + sqrt(a2 * (1 - NdotV2) / NdotV2 + 1)) * 0.5f;
// G = 1 / (1 + lambda_v + lambda_l);
// lambda_v = (-1 + sqrt(a2 * (1 - NdotL2) / NdotL2 + 1)) * 0.5f;
// lambda_l = (-1 + sqrt(a2 * (1 - NdotV2) / NdotV2 + 1)) * 0.5f;
// G = 1 / (1 + lambda_v + lambda_l);
float a = roughness;
float a2 = a * a;

16
Assets/ScriptableRenderLoop/ShaderLibrary/Color.hlsl


// sRGB
float3 SRGBToLinear(float3 c)
{
float3 linearRGBLo = c / 12.92;
float3 linearRGBHi = pow((c + 0.055) / 1.055, float3(2.4, 2.4, 2.4));
float3 linearRGB = (c <= 0.04045) ? linearRGBLo : linearRGBHi;
float3 linearRGBLo = c / 12.92;
float3 linearRGBHi = pow((c + 0.055) / 1.055, float3(2.4, 2.4, 2.4));
float3 linearRGB = (c <= 0.04045) ? linearRGBLo : linearRGBHi;
return linearRGB;
}

// Convert rgb to luminance
// with rgb in linear space with sRGB primaries and D65 white point
float Luminance(float3 linearRgb)
{
{
return dot(linearRgb, float3(0.2126729f, 0.7151522f, 0.0721750f));
}

float4 rgbm = float4(rgb * kOneOverRGBMMaxRange, 1.0);
rgbm.a = max(max(rgbm.r, rgbm.g), max(rgbm.b, kMinMultiplier));
rgbm.a = ceil(rgbm.a * 255.0) / 255.0;
rgbm.rgb /= rgbm.a;
return rgbm;
}

float4 packRGBM(float3 color)
float4 packRGBM(float3 color)
{
float4 rgbm;
color *= (1.0 / RGBMRANGE);

return rgbm;
}
float3 unpackRGBM(float4 rgbm)
float3 unpackRGBM(float4 rgbm)
{
return RGBMRANGE * rgbm.rgb * rgbm.a;
}

46
Assets/ScriptableRenderLoop/ShaderLibrary/Common.hlsl


// Common math definition and fastmath function
// ----------------------------------------------------------------------------
#define PI 3.14159265359f
#define TWO_PI 6.28318530718f
#define FOUR_PI 12.56637061436f
#define INV_PI 0.31830988618f
#define INV_TWO_PI 0.15915494309f
#define INV_FOUR_PI 0.07957747155f
#define HALF_PI 1.57079632679f
#define INV_HALF_PI 0.636619772367f
#define PI 3.14159265359f
#define TWO_PI 6.28318530718f
#define FOUR_PI 12.56637061436f
#define INV_PI 0.31830988618f
#define INV_TWO_PI 0.15915494309f
#define INV_FOUR_PI 0.07957747155f
#define HALF_PI 1.57079632679f
#define INV_HALF_PI 0.636619772367f
float FastACos(float inX)
{
float x = abs(inX);
float res = -0.156583 * x + HALF_PI;
res *= sqrt(1.0 - x);
return (inX >= 0) ? res : PI - res;
float FastACos(float inX)
{
float x = abs(inX);
float res = -0.156583 * x + HALF_PI;
res *= sqrt(1.0 - x);
return (inX >= 0) ? res : PI - res;
}
// Same cost as Acos + 1 FR

// Eberly's odd polynomial degree 5 - respect bounds
// 4 VGPR, 14 FR (10 FR, 1 QR), 2 scalar
// input [0, infinity] and output [0, PI/2]
float FastATanPos(float x)
{
float FastATanPos(float x)
{
float t0 = (x < 1.0) ? x : 1.0 / x;
float t1 = t0 * t0;
float poly = 0.0872929;

// 4 VGPR, 16 FR (12 FR, 1 QR), 2 scalar
// input [-infinity, infinity] and output [-PI/2, PI/2]
float FastATan(float x)
{
float t0 = FastATanPos(abs(x));
return (x < 0.0) ? -t0 : t0;
{
float t0 = FastATanPos(abs(x));
return (x < 0.0) ? -t0 : t0;
}
// ----------------------------------------------------------------------------

struct Coordinate
{
// Normalize coordinates
float2 positionSS;
float2 positionSS;
int2 unPositionSS;
int2 unPositionSS;
};
// This function is use to provide an easy way to sample into a screen texture, either from a pixel or a compute shaders.

// For information. In Unity Depth is always in range 0..1 (even on OpenGL) but can be reversed.
float3 UnprojectToWorld(float depth, float2 screenPos, float4x4 invViewProjectionMatrix)
{
float4 positionHS = float4(screenPos.xy * 2.0 - 1.0, depth, 1.0);
float4 hpositionWS = mul(invViewProjectionMatrix, positionHS);
float4 positionHS = float4(screenPos.xy * 2.0 - 1.0, depth, 1.0);
float4 hpositionWS = mul(invViewProjectionMatrix, positionHS);
return hpositionWS.xyz / hpositionWS.w;
}

6
Assets/ScriptableRenderLoop/ShaderLibrary/CommonLighting.hlsl


{
float sqrDist = dot(unL, unL);
float attenuation = 1.0f / (max(PUNCTUAL_LIGHT_THRESHOLD * PUNCTUAL_LIGHT_THRESHOLD, sqrDist));
// Non physically based hack to limit light influence to attenuationRadius.
// Non physically based hack to limit light influence to attenuationRadius.
attenuation *= SmoothDistanceAttenuation(sqrDist, invSqrAttenuationRadius);
return attenuation;

// Ref: http://blog.selfshadow.com/publications/s2012-shading-course/burley/s2012_pbs_disney_brdf_notes_v3.pdf (in addenda)
// Convert anisotropic ratio (0->no isotropic; 1->full anisotropy in tangent direction) to roughness
void ConvertAnisotropyToRoughness(float roughness, float anisotropy, out float roughnessT, out float roughnessB)
{
float anisoAspect = sqrt(1.0 - 0.9 * anisotropy);
{
float anisoAspect = sqrt(1.0 - 0.9 * anisotropy);
roughnessT = roughness * anisoAspect;
roughnessB = roughness / anisoAspect;
}

2
Assets/ScriptableRenderLoop/ShaderLibrary/Debug.hlsl


return outColor;
}
#endif // UNITY_DEBUG_INCLUDED
#endif // UNITY_DEBUG_INCLUDED

2
Assets/ScriptableRenderLoop/ShaderLibrary/Filtering.hlsl


float2 w2 = (1.0f / 6.0) * (-9.0 * f3 + 12.0 * f2 + 3.0 * f);
float2 w3 = (1.0f / 6.0) * (3.0 * f3 - 3.0 * f2);
// Otim by Vlad, to test
// Otim by Vlad, to test
// float2 w0 = (1.0 / 2.0) * f * (-1.0 + f * (2.0 - f));
// float2 w1 = (1.0 / 6.0) * f2 * (-15.0 + 9.0 * f)) + 1.0;
// float2 w2 = (1.0 / 6.0) * f * (3.0 + f * (12.0 - f * 9.0));

600
Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl


uint ReverseBits32(uint bits)
{
#if 0 // Shader model 5
return reversebits(bits);
return reversebits(bits);
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;
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;
float RadicalInverse_VdC(uint bits)
float RadicalInverse_VdC(uint bits)
return float(ReverseBits32(bits)) * 2.3283064365386963e-10; // 0x100000000
return float(ReverseBits32(bits)) * 2.3283064365386963e-10; // 0x100000000
return float2(float(i) / float(maxSampleCount), RadicalInverse_VdC(i));
return float2(float(i) / float(maxSampleCount), RadicalInverse_VdC(i));
}
float Hash(uint s)

float2 InitRandom(float2 input)
{
float2 r;
r.x = Hash(uint(input.x * 4294967295.0));
r.y = Hash(uint(input.y * 4294967295.0));
float2 r;
r.x = Hash(uint(input.x * 4294967295.0));
r.y = Hash(uint(input.y * 4294967295.0));
return r;
return r;
}
//-----------------------------------------------------------------------------

// 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);
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

{
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 ;
}
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);
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);
}
*/

void ImportanceSampleCosDir(float2 u,
float3 N,
float3 tangentX,
float3 tangentY,
out float3 L)
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;
// 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;
// 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)
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;
// 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;
// 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;
// Convert sample from half angle to incident angle
L = 2.0 * dot(V, H) * H - V;
float2 u,
float3 N,
float3 tangentX,
float3 tangentY,
out float3 L,
out float NdotL,
out float weightOverPdf)
float2 u,
float3 N,
float3 tangentX,
float3 tangentY,
out float3 L,
out float NdotL,
out float weightOverPdf)
ImportanceSampleCosDir(u, N, tangentX, tangentY, L);
ImportanceSampleCosDir(u, N, tangentX, tangentY, L);
NdotL = saturate(dot(N, 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
// 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 = 1.0;
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)
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));
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))
// 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))
// F is apply outside the function
// F is apply outside the function
weightOverPdf = 4.0 * Vis * NdotL * VdotH / NdotH;
weightOverPdf = 4.0 * Vis * NdotL * VdotH / NdotH;
// Reference
// ----------------------------------------------------------------------------
// Reference
// ----------------------------------------------------------------------------
void IntegrateLambertDiffuseIBLRef( out float3 diffuseLighting,
UNITY_ARGS_TEXCUBE(tex),
float3 N,
float3 diffuseAlbedo,
uint sampleCount = 2048)
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 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);
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);
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);
float3 L;
float NdotL;
float weightOverPdf;
ImportanceSampleLambert(u, N, tangentX, tangentY, L, NdotL, weightOverPdf);
if (NdotL > 0.0)
{
if (NdotL > 0.0)
{
// diffuse Albedo is apply here as describe in ImportanceSampleLambert function
// diffuse Albedo is apply here as describe in ImportanceSampleLambert function
}
}
}
}
diffuseLighting = acc / sampleCount;
diffuseLighting = acc / sampleCount;
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
void IntegrateDisneyDiffuseIBLRef( out float3 diffuseLighting,
UNITY_ARGS_TEXCUBE(tex),
float3 N,
float3 V,
float roughness,
float3 diffuseAlbedo,
uint sampleCount = 2048)
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);
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);
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);
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);
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)
{
if (NdotL > 0.0)
{
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.
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.
// diffuse Albedo is apply here as describe in ImportanceSampleLambert function
acc += diffuseAlbedo * disneyDiffuse * weightOverPdf * val;
}
}
// diffuse Albedo is apply here as describe in ImportanceSampleLambert function
acc += diffuseAlbedo * disneyDiffuse * weightOverPdf * val;
}
}
diffuseLighting = acc / sampleCount;
diffuseLighting = acc / sampleCount;
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
UNITY_ARGS_TEXCUBE(tex),
float3 N,
float3 V,
float roughness,
float3 f0,
float f90,
uint sampleCount = 2048)
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);
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);
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;
for (uint i = 0; i < sampleCount; ++i)
{
float2 u = Hammersley2d(i, sampleCount);
u = frac(u + randNum + 0.5);
// GGX BRDF
ImportanceSampleGGX(u, V, N, tangentX, tangentY, roughness, NdotV,
L, VdotH, NdotL, weightOverPdf);
float VdotH;
float NdotL;
float3 L;
float weightOverPdf;
if (NdotL > 0.0)
{
// Fresnel component is apply here as describe in ImportanceSampleGGX function
// 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
acc += FweightOverPdf * val;
}
}
acc += FweightOverPdf * val;
}
}
specularLighting = acc / sampleCount;
specularLighting = acc / 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);
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);
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;
for (uint i = 0; i < sampleCount; ++i)
{
float2 u = Hammersley2d(i, sampleCount);
u = frac(u + randNum + 0.5);
float3 L; // Unused
ImportanceSampleGGX(u, V, N, tangentX, tangentY, roughness, NdotV,
L, VdotH, NdotL, weightOverPdf);
float VdotH;
float NdotL;
float 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 ]
float3 L; // Unused
ImportanceSampleGGX(u, V, N, tangentX, tangentY, roughness, NdotV,
L, VdotH, NdotL, 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;
}
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 ]
// 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);
// 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;
}
if (NdotL > 0.0)
{
float3 H = normalize(L + V);
float LdotH = dot(L, H);
float disneyDiffuse = DisneyDiffuse(NdotV, NdotL, LdotH, RoughnessToPerceptualRoughness(roughness));
// 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);
acc.z += disneyDiffuse * weightOverPdf;
}
}
if (NdotL > 0.0)
{
float3 H = normalize(L + V);
float LdotH = dot(L, H);
float disneyDiffuse = DisneyDiffuse(NdotV, NdotL, LdotH, RoughnessToPerceptualRoughness(roughness));
return acc / sampleCount;
acc.z += disneyDiffuse * weightOverPdf;
}
}
return acc / sampleCount;
float4 IntegrateLD( UNITY_ARGS_TEXCUBE(tex),
float3 V,
float3 N,
float roughness,
float mipmapcount,
float invOmegaP,
uint sampleCount,
bool prefilter = true) // static bool
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 acc = float3(0.0, 0.0, 0.0);
float accWeight = 0;
float3 tangentX, tangentY;
GetLocalFrame(N, tangentX, tangentY);
float2 randNum = InitRandom(V.xy * 0.5 + 0.5);
for (uint i = 0; i < sampleCount; ++i)
{
float2 u = Hammersley2d(i, sampleCount);
u = frac(u + randNum + 0.5);
float3 tangentX, tangentY;
GetLocalFrame(N, tangentX, tangentY);
float3 H;
float3 L;
ImportanceSampleGGXDir(u, V, N, tangentX, tangentY, roughness, H, L);
for (uint i = 0; i < sampleCount; ++i)
{
float2 u = Hammersley2d(i, sampleCount);
u = frac(u + randNum + 0.5);
float NdotL = saturate(dot(N,L));
float3 H;
float3 L;
ImportanceSampleGGXDir(u, V, N, tangentX, tangentY, roughness, H, L);
float mipLevel;
float NdotL = saturate(dot(N,L));
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));
float mipLevel;
// 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
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.
}
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;
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;
}
}
// 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);
return float4(acc * (1.0 / accWeight), 1.0);
}
#endif // UNITY_IMAGE_BASED_LIGHTING_INCLUDED

8
Assets/ScriptableRenderLoop/ShaderLibrary/Packing.hlsl


// return float between [-1, 1]
float2 PackNormalOctEncode(float3 n)
{
float l1norm = abs(n.x) + abs(n.y) + abs(n.z);
float2 res0 = n.xy * (1.0 / l1norm);
float l1norm = abs(n.x) + abs(n.y) + abs(n.z);
float2 res0 = n.xy * (1.0 / l1norm);
float2 val = 1.0 - abs(res0.yx);
float2 val = 1.0 - abs(res0.yx);
return (n.zz < float2(0.0, 0.0) ? (res0 >= 0.0 ? val : -val) : res0);
}

}
// Pack a quaternion into a 10:10:10:2
float4 PackQuat(float4 quat)
float4 PackQuat(float4 quat)
{
uint index = FindBiggestComponent(quat);

4
Assets/ScriptableRenderLoop/ShaderLibrary/QuaternionMath.hlsl


void QuatToTangentSpace(float4 quaterion, out float3 tangent, out float3 bitangent, out float3 normal)
{
tangent = float3(1.0, 0.0, 0.0)
tangent = float3(1.0, 0.0, 0.0)
+ float3(-2.0, 2.0, 2.0) * quat.y * quat.yxw
+ float3(-2.0, -2.0, 2.0) * quat.z * quaternion.zwx;

normal = float3(0.0, 0.0, 1.0)
normal = float3(0.0, 0.0, 1.0)
+ float3(2.0, 2.0, -2.0) * quat.x * quat.zwx
+ float3(-2.0, 2.0, -2.0) * quat.y * quaternion.wzy;
}

16
Assets/ScriptableRenderLoop/common/ShaderBase.h


#define __SHADERBASE_H__
#define __HLSL 1
#define __HLSL 1
#define unistruct cbuffer
#define hbool bool
#define unistruct cbuffer
#define hbool bool
#define _CB_REGSLOT(x) : register(x)
#define _QALIGN(x) : packoffset(c0);
#define _CB_REGSLOT(x) : register(x)
#define _QALIGN(x) : packoffset(c0);
return 1 - depthTexture.Load(uint3(pixCoord.xy, 0)).x;
return 1 - depthTexture.Load(uint3(pixCoord.xy, 0)).x;
return 1 - depthTexture.Load(uint3(pixCoord.xy, 0), sampleIdx).x;
return 1 - depthTexture.Load(uint3(pixCoord.xy, 0), sampleIdx).x;
#endif
#endif

445
Assets/ScriptableRenderLoop/common/SkyboxHelper.cs


using System.Collections;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Rendering;
using UnityEngine;

public SkyboxHelper()
{
}
public SkyboxHelper()
{
}
const int NumFullSubdivisions = 3; // 3 subdivs == 2048 triangles
const int NumHorizonSubdivisions = 2;
const int NumFullSubdivisions = 3; // 3 subdivs == 2048 triangles
const int NumHorizonSubdivisions = 2;
public void CreateMesh()
{
Vector3[] vertData = new Vector3[8 * 3];
for (int i = 0; i < 8 * 3; i++)
{
vertData[i] = octaVerts[i];
}
public void CreateMesh()
{
Vector3[] vertData = new Vector3[8 * 3];
for (int i = 0; i < 8 * 3; i++)
{
vertData[i] = octaVerts[i];
}
// Regular subdivisions
for (int i = 0; i < NumFullSubdivisions; i++)
{
Vector3[] srcData = vertData.Clone() as Vector3[];
List<Vector3> verts = new List<Vector3>();
// Regular subdivisions
for (int i = 0; i < NumFullSubdivisions; i++)
{
Vector3[] srcData = vertData.Clone() as Vector3[];
List<Vector3> verts = new List<Vector3>();
for (int k = 0; k < srcData.Length; k += 3)
{
Subdivide(verts, srcData[k], srcData[k + 1], srcData[k + 2]);
}
vertData = verts.ToArray();
}
for (int k = 0; k < srcData.Length; k += 3)
{
Subdivide(verts, srcData[k], srcData[k + 1], srcData[k + 2]);
}
vertData = verts.ToArray();
}
// Horizon subdivisions
float horizonLimit = 1.0f;
for (int i = 0; i < NumHorizonSubdivisions; i++)
{
Vector3[] srcData = vertData.Clone() as Vector3[];
List<Vector3> verts = new List<Vector3>();
// Horizon subdivisions
float horizonLimit = 1.0f;
for (int i = 0; i < NumHorizonSubdivisions; i++)
{
Vector3[] srcData = vertData.Clone() as Vector3[];
List<Vector3> verts = new List<Vector3>();
horizonLimit *= 0.5f; // First iteration limit to y < +-0.5, next one 0.25 etc.
for (int k = 0; k < srcData.Length; k += 3)
{
float maxAbsY = Mathf.Max(Mathf.Abs(srcData[k].y), Mathf.Abs(srcData[k + 1].y), Mathf.Abs(srcData[k + 2].y));
if (maxAbsY > horizonLimit)
{
// Pass through existing triangle
verts.Add(srcData[k]);
verts.Add(srcData[k + 1]);
verts.Add(srcData[k + 2]);
}
else
{
SubdivideYOnly(verts, srcData[k], srcData[k + 1], srcData[k + 2]);
}
}
vertData = verts.ToArray();
}
horizonLimit *= 0.5f; // First iteration limit to y < +-0.5, next one 0.25 etc.
for (int k = 0; k < srcData.Length; k += 3)
{
float maxAbsY = Mathf.Max(Mathf.Abs(srcData[k].y), Mathf.Abs(srcData[k + 1].y), Mathf.Abs(srcData[k + 2].y));
if (maxAbsY > horizonLimit)
{
// Pass through existing triangle
verts.Add(srcData[k]);
verts.Add(srcData[k + 1]);
verts.Add(srcData[k + 2]);
}
else
{
SubdivideYOnly(verts, srcData[k], srcData[k + 1], srcData[k + 2]);
}
}
vertData = verts.ToArray();
}
// Write out the mesh
int vertexCount = vertData.Length;
var triangles = new int[vertexCount];
for (int i = 0; i < vertexCount; i++)
{
triangles[i] = i;
}
// Write out the mesh
int vertexCount = vertData.Length;
var triangles = new int[vertexCount];
for (int i = 0; i < vertexCount; i++)
{
triangles[i] = i;
}
_mesh = new Mesh();
_mesh.vertices = vertData;
_mesh.triangles = triangles;
}
_mesh = new Mesh();
_mesh.vertices = vertData;
_mesh.triangles = triangles;
}
public UnityEngine.Mesh mesh
{
get { return _mesh; }
}
public UnityEngine.Mesh mesh
{
get { return _mesh; }
}
public void Draw(RenderLoop loop, Camera camera)
{
if (camera.clearFlags != CameraClearFlags.Skybox)
{
return;
}
public void Draw(RenderLoop loop, Camera camera)
{
if (camera.clearFlags != CameraClearFlags.Skybox)
{
return;
}
Material mat = RenderSettings.skybox;
Material mat = RenderSettings.skybox;
if (mat == null)
{
return;
}
if (mat == null)
{
return;
}
CommandBuffer cmd = new CommandBuffer();
cmd.name = "Skybox";
CommandBuffer cmd = new CommandBuffer();
cmd.name = "Skybox";
bool looksLikeSixSidedShader = true;
looksLikeSixSidedShader &= (mat.passCount == 6); // should have six passes
//looksLikeSixSidedShader &= !mat.GetShader()->GetShaderLabShader()->HasLightingPasses();
bool looksLikeSixSidedShader = true;
looksLikeSixSidedShader &= (mat.passCount == 6); // should have six passes
//looksLikeSixSidedShader &= !mat.GetShader()->GetShaderLabShader()->HasLightingPasses();
if (looksLikeSixSidedShader)
{
Debug.LogWarning("Six sided skybox not yet supported.");
}
else
{
if (mesh == null)
{
CreateMesh();
}
float dist = camera.farClipPlane * 10.0f;
if (looksLikeSixSidedShader)
{
Debug.LogWarning("Six sided skybox not yet supported.");
}
else
{
if (mesh == null)
{
CreateMesh();
}
Matrix4x4 world = Matrix4x4.TRS(camera.transform.position, Quaternion.identity, new Vector3(dist, dist, dist));
float dist = camera.farClipPlane * 10.0f;
Matrix4x4 skyboxProj = SkyboxHelper.GetProjectionMatrix(camera);
cmd.SetProjectionAndViewMatrices(skyboxProj, camera.worldToCameraMatrix);
cmd.DrawMesh(mesh, world, mat);
Matrix4x4 world = Matrix4x4.TRS(camera.transform.position, Quaternion.identity, new Vector3(dist, dist, dist));
cmd.SetProjectionAndViewMatrices(camera.projectionMatrix, camera.worldToCameraMatrix);
}
Matrix4x4 skyboxProj = SkyboxHelper.GetProjectionMatrix(camera);
cmd.SetProjectionAndViewMatrices(skyboxProj, camera.worldToCameraMatrix);
cmd.DrawMesh(mesh, world, mat);
loop.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}
cmd.SetProjectionAndViewMatrices(camera.projectionMatrix, camera.worldToCameraMatrix);
}
static public Matrix4x4 GetProjectionMatrix(Camera camera)
{
Matrix4x4 skyboxProj = Matrix4x4.Perspective(camera.fieldOfView, camera.aspect, camera.nearClipPlane, camera.farClipPlane);
loop.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}
float nearPlane = camera.nearClipPlane * 0.01f;
skyboxProj = AdjustDepthRange(skyboxProj, camera.nearClipPlane, nearPlane, camera.farClipPlane);
return MakeProjectionInfinite(skyboxProj, nearPlane);
}
static public Matrix4x4 GetProjectionMatrix(Camera camera)
{
Matrix4x4 skyboxProj = Matrix4x4.Perspective(camera.fieldOfView, camera.aspect, camera.nearClipPlane, camera.farClipPlane);
static Matrix4x4 MakeProjectionInfinite(Matrix4x4 m, float nearPlane)
{
const float epsilon = 1e-6f;
float nearPlane = camera.nearClipPlane * 0.01f;
skyboxProj = AdjustDepthRange(skyboxProj, camera.nearClipPlane, nearPlane, camera.farClipPlane);
return MakeProjectionInfinite(skyboxProj, nearPlane);
}
Matrix4x4 r = m;
r[2, 2] = -1.0f + epsilon;
r[2, 3] = (-2.0f + epsilon) * nearPlane;
r[3, 2] = -1.0f;
return r;
}
static Matrix4x4 MakeProjectionInfinite(Matrix4x4 m, float nearPlane)
{
const float epsilon = 1e-6f;
static Matrix4x4 AdjustDepthRange(Matrix4x4 mat, float origNear, float newNear, float newFar)
{
float x = mat[0, 0];
float y = mat[1, 1];
float w = mat[0, 2];
float z = mat[1, 2];
Matrix4x4 r = m;
r[2, 2] = -1.0f + epsilon;
r[2, 3] = (-2.0f + epsilon) * nearPlane;
r[3, 2] = -1.0f;
return r;
}
float r = ((2.0f * origNear) / x) * ((w + 1) * 0.5f);
float t = ((2.0f * origNear) / y) * ((z + 1) * 0.5f);
float l = ((2.0f * origNear) / x) * (((w + 1) * 0.5f) - 1);
float b = ((2.0f * origNear) / y) * (((z + 1) * 0.5f) - 1);
static Matrix4x4 AdjustDepthRange(Matrix4x4 mat, float origNear, float newNear, float newFar)
{
float x = mat[0, 0];
float y = mat[1, 1];
float w = mat[0, 2];
float z = mat[1, 2];
float ratio = (newNear / origNear);
float r = ((2.0f * origNear) / x) * ((w + 1) * 0.5f);
float t = ((2.0f * origNear) / y) * ((z + 1) * 0.5f);
float l = ((2.0f * origNear) / x) * (((w + 1) * 0.5f) - 1);
float b = ((2.0f * origNear) / y) * (((z + 1) * 0.5f) - 1);
r *= ratio;
t *= ratio;
l *= ratio;
b *= ratio;
float ratio = (newNear / origNear);
Matrix4x4 ret = new Matrix4x4();
r *= ratio;
t *= ratio;
l *= ratio;
b *= ratio;
ret[0, 0] = (2.0f * newNear) / (r - l); ret[0, 1] = 0; ret[0, 2] = (r + l) / (r - l); ret[0, 3] = 0;
ret[1, 0] = 0; ret[1, 1] = (2.0f * newNear) / (t - b); ret[1, 2] = (t + b) / (t - b); ret[1, 3] = 0;
ret[2, 0] = 0; ret[2, 1] = 0; ret[2, 2] = -(newFar + newNear) / (newFar - newNear); ret[2, 3] = -(2.0f * newFar * newNear) / (newFar - newNear);
ret[3, 0] = 0; ret[3, 1] = 0; ret[3, 2] = -1.0f; ret[3, 3] = 0;
Matrix4x4 ret = new Matrix4x4();
return ret;
}
ret[0, 0] = (2.0f * newNear) / (r - l); ret[0, 1] = 0; ret[0, 2] = (r + l) / (r - l); ret[0, 3] = 0;
ret[1, 0] = 0; ret[1, 1] = (2.0f * newNear) / (t - b); ret[1, 2] = (t + b) / (t - b); ret[1, 3] = 0;
ret[2, 0] = 0; ret[2, 1] = 0; ret[2, 2] = -(newFar + newNear) / (newFar - newNear); ret[2, 3] = -(2.0f * newFar * newNear) / (newFar - newNear);
ret[3, 0] = 0; ret[3, 1] = 0; ret[3, 2] = -1.0f; ret[3, 3] = 0;
// Octahedron vertices
Vector3[] octaVerts =
{
new Vector3(0.0f, 1.0f, 0.0f), new Vector3(0.0f, 0.0f, -1.0f), new Vector3(1.0f, 0.0f, 0.0f),
new Vector3(0.0f, 1.0f, 0.0f), new Vector3(1.0f, 0.0f, 0.0f), new Vector3(0.0f, 0.0f, 1.0f),
new Vector3(0.0f, 1.0f, 0.0f), new Vector3(0.0f, 0.0f, 1.0f), new Vector3(-1.0f, 0.0f, 0.0f),
new Vector3(0.0f, 1.0f, 0.0f), new Vector3(-1.0f, 0.0f, 0.0f), new Vector3(0.0f, 0.0f, -1.0f),
new Vector3(0.0f, -1.0f, 0.0f), new Vector3(1.0f, 0.0f, 0.0f), new Vector3(0.0f, 0.0f, -1.0f),
new Vector3(0.0f, -1.0f, 0.0f), new Vector3(0.0f, 0.0f, 1.0f), new Vector3(1.0f, 0.0f, 0.0f),
new Vector3(0.0f, -1.0f, 0.0f), new Vector3(-1.0f, 0.0f, 0.0f), new Vector3(0.0f, 0.0f, 1.0f),
new Vector3(0.0f, -1.0f, 0.0f), new Vector3(0.0f, 0.0f, -1.0f), new Vector3(-1.0f, 0.0f, 0.0f),
};
return ret;
}
Vector3 SubDivVert(Vector3 v1, Vector3 v2)
{
return Vector3.Normalize(v1 + v2);
}
// Octahedron vertices
Vector3[] octaVerts =
{
new Vector3(0.0f, 1.0f, 0.0f), new Vector3(0.0f, 0.0f, -1.0f), new Vector3(1.0f, 0.0f, 0.0f),
new Vector3(0.0f, 1.0f, 0.0f), new Vector3(1.0f, 0.0f, 0.0f), new Vector3(0.0f, 0.0f, 1.0f),
new Vector3(0.0f, 1.0f, 0.0f), new Vector3(0.0f, 0.0f, 1.0f), new Vector3(-1.0f, 0.0f, 0.0f),
new Vector3(0.0f, 1.0f, 0.0f), new Vector3(-1.0f, 0.0f, 0.0f), new Vector3(0.0f, 0.0f, -1.0f),
new Vector3(0.0f, -1.0f, 0.0f), new Vector3(1.0f, 0.0f, 0.0f), new Vector3(0.0f, 0.0f, -1.0f),
new Vector3(0.0f, -1.0f, 0.0f), new Vector3(0.0f, 0.0f, 1.0f), new Vector3(1.0f, 0.0f, 0.0f),
new Vector3(0.0f, -1.0f, 0.0f), new Vector3(-1.0f, 0.0f, 0.0f), new Vector3(0.0f, 0.0f, 1.0f),
new Vector3(0.0f, -1.0f, 0.0f), new Vector3(0.0f, 0.0f, -1.0f), new Vector3(-1.0f, 0.0f, 0.0f),
};
void Subdivide(List<Vector3> dest, Vector3 v1, Vector3 v2, Vector3 v3)
{
Vector3 v12 = SubDivVert(v1, v2);
Vector3 v23 = SubDivVert(v2, v3);
Vector3 v13 = SubDivVert(v1, v3);
Vector3 SubDivVert(Vector3 v1, Vector3 v2)
{
return Vector3.Normalize(v1 + v2);
}
dest.Add(v1);
dest.Add(v12);
dest.Add(v13);
dest.Add(v12);
dest.Add(v2);
dest.Add(v23);
dest.Add(v23);
dest.Add(v13);
dest.Add(v12);
dest.Add(v3);
dest.Add(v13);
dest.Add(v23);
}
void Subdivide(List<Vector3> dest, Vector3 v1, Vector3 v2, Vector3 v3)
{
Vector3 v12 = SubDivVert(v1, v2);
Vector3 v23 = SubDivVert(v2, v3);
Vector3 v13 = SubDivVert(v1, v3);
void SubdivideYOnly(List<Vector3> dest, Vector3 v1, Vector3 v2, Vector3 v3)
{
// Find out which vertex is furthest out from the others on the y axis
dest.Add(v1);
dest.Add(v12);
dest.Add(v13);
dest.Add(v12);
dest.Add(v2);
dest.Add(v23);
dest.Add(v23);
dest.Add(v13);
dest.Add(v12);
dest.Add(v3);
dest.Add(v13);
dest.Add(v23);
}
float d12 = Mathf.Abs(v2.y - v1.y);
float d23 = Mathf.Abs(v2.y - v3.y);
float d31 = Mathf.Abs(v3.y - v1.y);
void SubdivideYOnly(List<Vector3> dest, Vector3 v1, Vector3 v2, Vector3 v3)
{
// Find out which vertex is furthest out from the others on the y axis
Vector3 top, va, vb;
float d12 = Mathf.Abs(v2.y - v1.y);
float d23 = Mathf.Abs(v2.y - v3.y);
float d31 = Mathf.Abs(v3.y - v1.y);
if (d12 < d23 && d12 < d31)
{
top = v3;
va = v1;
vb = v2;
}
else if (d23 < d12 && d23 < d31)
{
top = v1;
va = v2;
vb = v3;
}
else
{
top = v2;
va = v3;
vb = v1;
}
Vector3 top, va, vb;
Vector3 v12 = SubDivVert(top, va);
Vector3 v13 = SubDivVert(top, vb);
if (d12 < d23 && d12 < d31)
{
top = v3;
va = v1;
vb = v2;
}
else if (d23 < d12 && d23 < d31)
{
top = v1;
va = v2;
vb = v3;
}
else
{
top = v2;
va = v3;
vb = v1;
}
dest.Add(top);
dest.Add(v12);
dest.Add(v13);
Vector3 v12 = SubDivVert(top, va);
Vector3 v13 = SubDivVert(top, vb);
// A bit of extra logic to prevent triangle slivers: choose the shorter of (13->va), (12->vb) as triangle base
if ((v13 - va).sqrMagnitude > (v12 - vb).sqrMagnitude)
{
dest.Add(v12);
dest.Add(va);
dest.Add(vb);
dest.Add(v13);
dest.Add(v12);
dest.Add(vb);
}
else
{
dest.Add(v13);
dest.Add(v12);
dest.Add(va);
dest.Add(v13);
dest.Add(va);
dest.Add(vb);
}
dest.Add(top);
dest.Add(v12);
dest.Add(v13);
}
// A bit of extra logic to prevent triangle slivers: choose the shorter of (13->va), (12->vb) as triangle base
if ((v13 - va).sqrMagnitude > (v12 - vb).sqrMagnitude)
{
dest.Add(v12);
dest.Add(va);
dest.Add(vb);
dest.Add(v13);
dest.Add(v12);
dest.Add(vb);
}
else
{
dest.Add(v13);
dest.Add(v12);
dest.Add(va);
dest.Add(v13);
dest.Add(va);
dest.Add(vb);
}
}
Mesh _mesh;
Mesh _mesh;
}

513
Assets/ScriptableRenderLoop/common/TextureCache.cs


public class TextureCache2D : TextureCache
{
private Texture2DArray cache;
private Texture2DArray cache;
public override void TransferToSlice(int sliceIndex, Texture texture)
{
bool mismatch = (cache.width != texture.width) || (cache.height != texture.height);
public override void TransferToSlice(int sliceIndex, Texture texture)
{
bool mismatch = (cache.width != texture.width) || (cache.height != texture.height);
if (texture is Texture2D)
{
mismatch |= (cache.format != (texture as Texture2D).format);
}
if (texture is Texture2D)
{
mismatch |= (cache.format != (texture as Texture2D).format);
}
if (mismatch)
{
Debug.LogErrorFormat(texture, "Texture size or format of \"{0}\" doesn't match renderloop settings (should be {1}x{2} {3})",
texture.name, cache.width, cache.height, cache.format);
return;
}
if (mismatch)
{
Debug.LogErrorFormat(texture, "Texture size or format of \"{0}\" doesn't match renderloop settings (should be {1}x{2} {3})",
texture.name, cache.width, cache.height, cache.format);
return;
}
Graphics.CopyTexture(texture, 0, cache, sliceIndex);
}
Graphics.CopyTexture(texture, 0, cache, sliceIndex);
}
public override Texture GetTexCache()
{
return cache;
}
public override Texture GetTexCache()
{
return cache;
}
public bool AllocTextureArray(int numTextures, int width, int height, TextureFormat format, bool isMipMapped)
{
bool res = AllocTextureArray(numTextures);
m_numMipLevels = GetNumMips(width, height);
public bool AllocTextureArray(int numTextures, int width, int height, TextureFormat format, bool isMipMapped)
{
bool res = AllocTextureArray(numTextures);
m_numMipLevels = GetNumMips(width, height);
cache = new Texture2DArray(width, height, numTextures, format, isMipMapped);
cache.hideFlags = HideFlags.HideAndDontSave;
cache.wrapMode = TextureWrapMode.Clamp;
cache = new Texture2DArray(width, height, numTextures, format, isMipMapped);
cache.hideFlags = HideFlags.HideAndDontSave;
cache.wrapMode = TextureWrapMode.Clamp;
return res;
}
return res;
}
public void Release()
{
Texture.DestroyImmediate(cache); // do I need this?
}
public void Release()
{
Texture.DestroyImmediate(cache); // do I need this?
}
private CubemapArray cache;
private CubemapArray cache;
public override void TransferToSlice(int sliceIndex, Texture texture)
{
bool mismatch = (cache.width != texture.width) || (cache.height != texture.height);
public override void TransferToSlice(int sliceIndex, Texture texture)
{
bool mismatch = (cache.width != texture.width) || (cache.height != texture.height);
if (texture is Cubemap)
{
mismatch |= (cache.format != (texture as Cubemap).format);
}
if (texture is Cubemap)
{
mismatch |= (cache.format != (texture as Cubemap).format);
}
if (mismatch)
{
Debug.LogErrorFormat(texture, "Texture size or format of \"{0}\" doesn't match renderloop settings (should be {1}x{2} {3})",
texture.name, cache.width, cache.height, cache.format);
return;
}
if (mismatch)
{
Debug.LogErrorFormat(texture, "Texture size or format of \"{0}\" doesn't match renderloop settings (should be {1}x{2} {3})",
texture.name, cache.width, cache.height, cache.format);
return;
}
for (int f = 0; f < 6; f++)
Graphics.CopyTexture(texture, f, cache, 6 * sliceIndex + f);
}
for (int f = 0; f < 6; f++)
Graphics.CopyTexture(texture, f, cache, 6 * sliceIndex + f);
}
public override Texture GetTexCache()
{
return cache;
}
public override Texture GetTexCache()
{
return cache;
}
public bool AllocTextureArray(int numCubeMaps, int width, TextureFormat format, bool isMipMapped)
{
bool res = AllocTextureArray(6 * numCubeMaps);
m_numMipLevels = GetNumMips(width, width);
public bool AllocTextureArray(int numCubeMaps, int width, TextureFormat format, bool isMipMapped)
{
bool res = AllocTextureArray(6 * numCubeMaps);
m_numMipLevels = GetNumMips(width, width);
cache = new CubemapArray(width, numCubeMaps, format, isMipMapped);
cache.hideFlags = HideFlags.HideAndDontSave;
cache.wrapMode = TextureWrapMode.Clamp;
cache = new CubemapArray(width, numCubeMaps, format, isMipMapped);
cache.hideFlags = HideFlags.HideAndDontSave;
cache.wrapMode = TextureWrapMode.Clamp;
return res;
}
return res;
}
public void Release()
{
Texture.DestroyImmediate(cache); // do I need this?
}
public void Release()
{
Texture.DestroyImmediate(cache); // do I need this?
}
protected int m_numMipLevels;
protected int m_numMipLevels;
public static int ms_GlobalTextureCacheVersion = 0;
public int m_TextureCacheVersion = 0;
public static int ms_GlobalTextureCacheVersion = 0;
public int m_TextureCacheVersion = 0;
internal class AssetReloader : UnityEditor.AssetPostprocessor
{
void OnPostprocessTexture(Texture texture)
{
ms_GlobalTextureCacheVersion++;
}
}
private AssetReloader m_assetReloader;
internal class AssetReloader : UnityEditor.AssetPostprocessor
{
void OnPostprocessTexture(Texture texture)
{
ms_GlobalTextureCacheVersion++;
}
}
private AssetReloader m_assetReloader;
private struct SSliceEntry
{
public uint TexID;
public uint CountLRU;
};
private struct SSliceEntry
{
public uint TexID;
public uint CountLRU;
};
private int m_numTextures;
private int[] m_SortedIdxArray;
private SSliceEntry[] m_SliceArray;
Dictionary<uint, int> m_locatorInSliceArray;
private int m_numTextures;
private int[] m_SortedIdxArray;
private SSliceEntry[] m_SliceArray;
private static uint g_MaxFrameCount = unchecked((uint)(-1));
private static uint g_InvalidTexID = (uint)0;
Dictionary<uint, int> m_locatorInSliceArray;
public int FetchSlice(Texture texture)
{
uint TexID = (uint)texture.GetInstanceID();
private static uint g_MaxFrameCount = unchecked((uint)(-1));
private static uint g_InvalidTexID = (uint)0;
//assert(TexID!=g_InvalidTexID);
if (TexID == g_InvalidTexID) return 0;
public int FetchSlice(Texture texture)
{
uint TexID = (uint)texture.GetInstanceID();
bool bSwapSlice = false;
bool bFoundAvailOrExistingSlice = false;
int sliceIndex = -1;
//assert(TexID!=g_InvalidTexID);
if (TexID == g_InvalidTexID) return 0;
// search for existing copy
if (m_locatorInSliceArray.ContainsKey(TexID))
{
if (m_TextureCacheVersion != ms_GlobalTextureCacheVersion)
{
m_locatorInSliceArray.Remove(TexID);
m_TextureCacheVersion++;
Debug.Assert(m_TextureCacheVersion <= ms_GlobalTextureCacheVersion);
}
else
{
sliceIndex = m_locatorInSliceArray[TexID];
bFoundAvailOrExistingSlice = true;
}
//assert(m_SliceArray[sliceIndex].TexID==TexID);
}
bool bSwapSlice = false;
bool bFoundAvailOrExistingSlice = false;
int sliceIndex = -1;
// If no existing copy found in the array
if (!bFoundAvailOrExistingSlice)
{
// look for first non zero entry. Will by the least recently used entry
// since the array was pre-sorted (in linear time) in NewFrame()
bool bFound = false;
int j = 0, idx = 0;
while ((!bFound) && j < m_numTextures)
{
idx = m_SortedIdxArray[j];
if (m_SliceArray[idx].CountLRU == 0) ++j; // if entry already snagged by a new texture in this frame then ++j
else bFound = true;
}
// search for existing copy
if (m_locatorInSliceArray.ContainsKey(TexID))
{
if (m_TextureCacheVersion != ms_GlobalTextureCacheVersion)
{
m_locatorInSliceArray.Remove(TexID);
m_TextureCacheVersion++;
Debug.Assert(m_TextureCacheVersion <= ms_GlobalTextureCacheVersion);
}
else
{
sliceIndex = m_locatorInSliceArray[TexID];
bFoundAvailOrExistingSlice = true;
}
//assert(m_SliceArray[sliceIndex].TexID==TexID);
}
if (bFound)
{
// if we are replacing an existing entry delete it from m_locatorInSliceArray.
if (m_SliceArray[idx].TexID != g_InvalidTexID)
{
m_locatorInSliceArray.Remove(m_SliceArray[idx].TexID);
}
// If no existing copy found in the array
if (!bFoundAvailOrExistingSlice)
{
// look for first non zero entry. Will by the least recently used entry
// since the array was pre-sorted (in linear time) in NewFrame()
bool bFound = false;
int j = 0, idx = 0;
while ((!bFound) && j < m_numTextures)
{
idx = m_SortedIdxArray[j];
if (m_SliceArray[idx].CountLRU == 0) ++j; // if entry already snagged by a new texture in this frame then ++j
else bFound = true;
}
m_locatorInSliceArray.Add(TexID, idx);
m_SliceArray[idx].TexID = TexID;
if (bFound)
{
// if we are replacing an existing entry delete it from m_locatorInSliceArray.
if (m_SliceArray[idx].TexID != g_InvalidTexID)
{
m_locatorInSliceArray.Remove(m_SliceArray[idx].TexID);
}
sliceIndex = idx;
bFoundAvailOrExistingSlice = true;
bSwapSlice = true;
}
}
m_locatorInSliceArray.Add(TexID, idx);
m_SliceArray[idx].TexID = TexID;
sliceIndex = idx;
bFoundAvailOrExistingSlice = true;
bSwapSlice = true;
}
}
// wrap up
//assert(bFoundAvailOrExistingSlice);
if (bFoundAvailOrExistingSlice)
{
m_SliceArray[sliceIndex].CountLRU = 0; // mark slice as in use this frame
if (bSwapSlice) // if this was a miss
{
// transfer new slice to sliceIndex from source texture
TransferToSlice(sliceIndex, texture);
}
}
// wrap up
//assert(bFoundAvailOrExistingSlice);
if (bFoundAvailOrExistingSlice)
{
m_SliceArray[sliceIndex].CountLRU = 0; // mark slice as in use this frame
return sliceIndex;
}
if (bSwapSlice) // if this was a miss
{
// transfer new slice to sliceIndex from source texture
TransferToSlice(sliceIndex, texture);
}
}
public void NewFrame()
{
int numNonZeros = 0;
int[] tmpBuffer = new int[m_numTextures];
for (int i = 0; i < m_numTextures; i++)
{
tmpBuffer[i] = m_SortedIdxArray[i]; // copy buffer
if (m_SliceArray[m_SortedIdxArray[i]].CountLRU != 0) ++numNonZeros;
}
int nonZerosBase = 0, zerosBase = 0;
for (int i = 0; i < m_numTextures; i++)
{
if (m_SliceArray[tmpBuffer[i]].CountLRU == 0)
{
m_SortedIdxArray[zerosBase + numNonZeros] = tmpBuffer[i];
++zerosBase;
}
else
{
m_SortedIdxArray[nonZerosBase] = tmpBuffer[i];
++nonZerosBase;
}
}
return sliceIndex;
}
for (int i = 0; i < m_numTextures; i++)
{
if (m_SliceArray[i].CountLRU < g_MaxFrameCount) ++m_SliceArray[i].CountLRU; // next frame
}
public void NewFrame()
{
int numNonZeros = 0;
int[] tmpBuffer = new int[m_numTextures];
for (int i = 0; i < m_numTextures; i++)
{
tmpBuffer[i] = m_SortedIdxArray[i]; // copy buffer
if (m_SliceArray[m_SortedIdxArray[i]].CountLRU != 0) ++numNonZeros;
}
int nonZerosBase = 0, zerosBase = 0;
for (int i = 0; i < m_numTextures; i++)
{
if (m_SliceArray[tmpBuffer[i]].CountLRU == 0)
{
m_SortedIdxArray[zerosBase + numNonZeros] = tmpBuffer[i];
++zerosBase;
}
else
{
m_SortedIdxArray[nonZerosBase] = tmpBuffer[i];
++nonZerosBase;
}
}
//for(int q=1; q<m_numTextures; q++)
// assert(m_SliceArray[m_SortedIdxArray[q-1]].CountLRU>=m_SliceArray[m_SortedIdxArray[q]].CountLRU);
}
for (int i = 0; i < m_numTextures; i++)
{
if (m_SliceArray[i].CountLRU < g_MaxFrameCount) ++m_SliceArray[i].CountLRU; // next frame
}
public TextureCache()
{
m_numTextures = 0;
m_numMipLevels = 0;
}
//for(int q=1; q<m_numTextures; q++)
// assert(m_SliceArray[m_SortedIdxArray[q-1]].CountLRU>=m_SliceArray[m_SortedIdxArray[q]].CountLRU);
}
public virtual void TransferToSlice(int sliceIndex, Texture texture)
{
}
public TextureCache()
{
m_numTextures = 0;
m_numMipLevels = 0;
}
public virtual Texture GetTexCache()
{
return null;
}
public virtual void TransferToSlice(int sliceIndex, Texture texture)
{
}
protected bool AllocTextureArray(int numTextures)
{
if (numTextures > 0)
{
m_SliceArray = new SSliceEntry[numTextures];
m_SortedIdxArray = new int[numTextures];
m_locatorInSliceArray = new Dictionary<uint, int>();
public virtual Texture GetTexCache()
{
return null;
}
m_numTextures = numTextures;
for (int i = 0; i < m_numTextures; i++)
{
m_SliceArray[i].CountLRU = g_MaxFrameCount; // never used before
m_SliceArray[i].TexID = g_InvalidTexID;
m_SortedIdxArray[i] = i;
}
}
protected bool AllocTextureArray(int numTextures)
{
if (numTextures > 0)
{
m_SliceArray = new SSliceEntry[numTextures];
m_SortedIdxArray = new int[numTextures];
m_locatorInSliceArray = new Dictionary<uint, int>();
//return m_SliceArray != NULL && m_SortedIdxArray != NULL && numTextures > 0;
return numTextures > 0;
}
m_numTextures = numTextures;
for (int i = 0; i < m_numTextures; i++)
{
m_SliceArray[i].CountLRU = g_MaxFrameCount; // never used before
m_SliceArray[i].TexID = g_InvalidTexID;
m_SortedIdxArray[i] = i;
}
}
// should not really be used in general. Assuming lights are culled properly entries will automatically be replaced efficiently.
public void RemoveEntryFromSlice(Texture texture)
{
uint TexID = (uint)texture.GetInstanceID();
//return m_SliceArray != NULL && m_SortedIdxArray != NULL && numTextures > 0;
return numTextures > 0;
}
//assert(TexID!=g_InvalidTexID);
if (TexID == g_InvalidTexID) return;
// should not really be used in general. Assuming lights are culled properly entries will automatically be replaced efficiently.
public void RemoveEntryFromSlice(Texture texture)
{
uint TexID = (uint)texture.GetInstanceID();
// search for existing copy
if (m_locatorInSliceArray.ContainsKey(TexID))
{
int sliceIndex = m_locatorInSliceArray[TexID];
//assert(TexID!=g_InvalidTexID);
if (TexID == g_InvalidTexID) return;
//assert(m_SliceArray[sliceIndex].TexID==TexID);
// search for existing copy
if (m_locatorInSliceArray.ContainsKey(TexID))
{
int sliceIndex = m_locatorInSliceArray[TexID];
// locate entry sorted by uCountLRU in m_pSortedIdxArray
bool bFoundIdxSortLRU = false;
int i = 0;
while ((!bFoundIdxSortLRU) && i < m_numTextures)
{
if (m_SortedIdxArray[i] == sliceIndex) bFoundIdxSortLRU = true;
else ++i;
}
//assert(m_SliceArray[sliceIndex].TexID==TexID);
if (bFoundIdxSortLRU)
{
// relocate sliceIndex to front of m_pSortedIdxArray since uCountLRU will be set to maximum.
for (int j = 0; j < i; j++) { m_SortedIdxArray[j + 1] = m_SortedIdxArray[j]; }
m_SortedIdxArray[0] = sliceIndex;
// locate entry sorted by uCountLRU in m_pSortedIdxArray
bool bFoundIdxSortLRU = false;
int i = 0;
while ((!bFoundIdxSortLRU) && i < m_numTextures)
{
if (m_SortedIdxArray[i] == sliceIndex) bFoundIdxSortLRU = true;
else ++i;
}
// delete from m_locatorInSliceArray and m_pSliceArray.
m_locatorInSliceArray.Remove(TexID);
m_SliceArray[sliceIndex].CountLRU = g_MaxFrameCount; // never used before
m_SliceArray[sliceIndex].TexID = g_InvalidTexID;
}
}
if (bFoundIdxSortLRU)
{
// relocate sliceIndex to front of m_pSortedIdxArray since uCountLRU will be set to maximum.
for (int j = 0; j < i; j++) { m_SortedIdxArray[j + 1] = m_SortedIdxArray[j]; }
m_SortedIdxArray[0] = sliceIndex;
}
// delete from m_locatorInSliceArray and m_pSliceArray.
m_locatorInSliceArray.Remove(TexID);
m_SliceArray[sliceIndex].CountLRU = g_MaxFrameCount; // never used before
m_SliceArray[sliceIndex].TexID = g_InvalidTexID;
}
}
}
protected int GetNumMips(int width, int height)
{
return GetNumMips(width > height ? width : height);
}
protected int GetNumMips(int width, int height)
{
return GetNumMips(width > height ? width : height);
}
protected int GetNumMips(int dim)
{
uint uDim = (uint)dim;
int iNumMips = 0;
while (uDim > 0)
{ ++iNumMips; uDim >>= 1; }
return iNumMips;
}
protected int GetNumMips(int dim)
{
uint uDim = (uint)dim;
int iNumMips = 0;
while (uDim > 0)
{ ++iNumMips; uDim >>= 1; }
return iNumMips;
}
}

28
Assets/ScriptableRenderLoop/common/TextureSettings.cs


[System.Serializable]
public struct TextureSettings
{
public uint spotCookieSize;
public uint pointCookieSize;
public uint reflectionCubemapSize;
public uint spotCookieSize;
public uint pointCookieSize;
public uint reflectionCubemapSize;
static public TextureSettings Default
{
get
{
TextureSettings settings;
settings.spotCookieSize = 128;
settings.pointCookieSize = 512;
settings.reflectionCubemapSize = 128;
return settings;
}
}
static public TextureSettings Default
{
get
{
TextureSettings settings;
settings.spotCookieSize = 128;
settings.pointCookieSize = 512;
settings.reflectionCubemapSize = 128;
return settings;
}
}
}

71
Assets/ScriptableRenderLoop/fptl/ClusteredUtils.h


#define __CLUSTEREDUTILS_H__
#ifndef FLT_EPSILON
#define FLT_EPSILON 1.192092896e-07f
#define FLT_EPSILON 1.192092896e-07f
const float C = (float) (1<<g_iLog2NumClusters);
const float geomSeries = (1.0 - pow(base, C))/(1-base); // geometric series: sum_k=0^{C-1} base^k
return geomSeries/(g_fFarPlane-g_fNearPlane);
const float C = (float)(1 << g_iLog2NumClusters);
const float geomSeries = (1.0 - pow(base, C)) / (1 - base); // geometric series: sum_k=0^{C-1} base^k
return geomSeries / (g_fFarPlane - g_fNearPlane);
float z = z_in;
float z = z_in;
float z = -z_in;
float z = -z_in;
float userscale = g_fClustScale;
if(logBasePerTile)
userscale = GetScaleFromBase(suggestedBase);
float userscale = g_fClustScale;
if (logBasePerTile)
userscale = GetScaleFromBase(suggestedBase);
// using the inverse of the geometric series
const float dist = max(0, z-g_fNearPlane);
return (int) clamp( log2(dist*userscale*(suggestedBase-1.0f) + 1) / log2(suggestedBase), 0.0, (float) ((1<<g_iLog2NumClusters)-1) );
// using the inverse of the geometric series
const float dist = max(0, z - g_fNearPlane);
return (int)clamp(log2(dist * userscale * (suggestedBase - 1.0f) + 1) / log2(suggestedBase), 0.0, (float)((1 << g_iLog2NumClusters) - 1));
bool logBasePerTile = true; // resolved compile time
bool logBasePerTile = true; // resolved compile time
bool logBasePerTile = false;
bool logBasePerTile = false;
return SnapToClusterIdxFlex(z_in, suggestedBase, logBasePerTile);
return SnapToClusterIdxFlex(z_in, suggestedBase, logBasePerTile);
float res;
float res;
float userscale = g_fClustScale;
if(logBasePerTile)
userscale = GetScaleFromBase(suggestedBase);
float userscale = g_fClustScale;
if (logBasePerTile)
userscale = GetScaleFromBase(suggestedBase);
float dist = (pow(suggestedBase,(float) k)-1.0)/(userscale*(suggestedBase-1.0f));
res = dist+g_fNearPlane;
float dist = (pow(suggestedBase, (float)k) - 1.0) / (userscale * (suggestedBase - 1.0f));
res = dist + g_fNearPlane;
return res;
return res;
return -res;
return -res;
#endif
}

bool logBasePerTile = true; // resolved compile time
bool logBasePerTile = true; // resolved compile time
bool logBasePerTile = false;
bool logBasePerTile = false;
return ClusterIdxToZFlex(k, suggestedBase, logBasePerTile);
return ClusterIdxToZFlex(k, suggestedBase, logBasePerTile);
const float C = (float) (1<<g_iLog2NumClusters);
float normDist = clamp( (tileFarPlane-g_fNearPlane) / (g_fFarPlane-g_fNearPlane), FLT_EPSILON, 1.0);
float suggested_base = pow( (1.0 + sqrt(max(0.0,1.0-4.0*normDist*(1.0-normDist))))/(2.0*normDist), 2.0/C); //
return max(g_fClustBase, suggested_base);
const float C = (float)(1 << g_iLog2NumClusters);
float normDist = clamp((tileFarPlane - g_fNearPlane) / (g_fFarPlane - g_fNearPlane), FLT_EPSILON, 1.0);
float suggested_base = pow((1.0 + sqrt(max(0.0, 1.0 - 4.0 * normDist * (1.0 - normDist)))) / (2.0 * normDist), 2.0 / C); //
return max(g_fClustBase, suggested_base);
const float C = (float) (1<<g_iLog2NumClusters);
float normDist = clamp( (tileFarPlane-g_fNearPlane) / (g_fFarPlane-g_fNearPlane), FLT_EPSILON, 1.0);
float suggested_base = pow( (1/2.3)*max(0.0, (0.8/normDist)-1), 4.0/(C*2)); // approximate inverse of d*x^4 + (-x) + (1-d) = 0 - d is normalized distance
return max(g_fClustBase,suggested_base);
const float C = (float)(1 << g_iLog2NumClusters);
float normDist = clamp((tileFarPlane - g_fNearPlane) / (g_fFarPlane - g_fNearPlane), FLT_EPSILON, 1.0);
float suggested_base = pow((1 / 2.3) * max(0.0, (0.8 / normDist) - 1), 4.0 / (C * 2)); // approximate inverse of d*x^4 + (-x) + (1-d) = 0 - d is normalized distance
return max(g_fClustBase, suggested_base);
#endif
#endif

74
Assets/ScriptableRenderLoop/fptl/FinalPass.shader


// Final compositing pass, just does gamma conversion for now.
// Final compositing pass, just does gamma conversion for now.
Shader "Hidden/FinalPass"
Shader "Hidden/FinalPass"
Properties { _MainTex ("Texture", any) = "" {} }
SubShader {
Pass {
ZTest Always Cull Off ZWrite Off
Properties { _MainTex ("Texture", any) = "" {} }
SubShader {
Pass {
ZTest Always Cull Off ZWrite Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0
#pragma multi_compile __ UNITY_COLORSPACE_GAMMA
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0
#pragma multi_compile __ UNITY_COLORSPACE_GAMMA
#include "UnityCG.cginc"
#include "UnityCG.cginc"
sampler2D _MainTex;
uniform float4 _MainTex_ST;
sampler2D _MainTex;
uniform float4 _MainTex_ST;
struct appdata_t {
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};
struct appdata_t {
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};
struct v2f {
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
};
struct v2f {
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
};
v2f vert (appdata_t v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.texcoord = TRANSFORM_TEX(v.texcoord.xy, _MainTex);
return o;
}
v2f vert (appdata_t v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.texcoord = TRANSFORM_TEX(v.texcoord.xy, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return tex2D(_MainTex, i.texcoord);
}
ENDCG
fixed4 frag (v2f i) : SV_Target
{
return tex2D(_MainTex, i.texcoord);
}
ENDCG
}
}
Fallback Off
}
}
Fallback Off
}

992
Assets/ScriptableRenderLoop/fptl/FptlLighting.cs
文件差异内容过多而无法显示
查看文件

108
Assets/ScriptableRenderLoop/fptl/Internal-DeferredReflections.shader


Shader "Hidden/Internal-TiledReflections" {
Properties {
_LightTexture0 ("", any) = "" {}
_ShadowMapTexture ("", any) = "" {}
_SrcBlend ("", Float) = 1
_DstBlend ("", Float) = 1
_LightTexture0 ("", any) = "" {}
_ShadowMapTexture ("", any) = "" {}
_SrcBlend ("", Float) = 1
_DstBlend ("", Float) = 1
}
SubShader {

Pass
Pass
ZWrite Off
ZTest Always
Cull Off
//Blend Off
Blend [_SrcBlend] [_DstBlend]
ZWrite Off
ZTest Always
Cull Off
//Blend Off
Blend [_SrcBlend] [_DstBlend]
CGPROGRAM
#pragma target 5.0

#pragma multi_compile USE_FPTL_LIGHTLIST USE_CLUSTERED_LIGHTLIST
#pragma multi_compile USE_FPTL_LIGHTLIST USE_CLUSTERED_LIGHTLIST
#include "UnityLightingCommon.cginc"

// uses the optimized single layered light list for opaques only
#ifdef USE_FPTL_LIGHTLIST
#define OPAQUES_ONLY
#define OPAQUES_ONLY
#endif
#include "TiledReflectionTemplate.hlsl"

struct v2f {
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
v2f o;
o.vertex = UnityObjectToClipPos(vertex);
o.texcoord = texcoord.xy;
return o;
v2f o;
o.vertex = UnityObjectToClipPos(vertex);
o.texcoord = texcoord.xy;
return o;
float3 specularColor;
float3 diffuseColor;
float3 normalWorld;
float smoothness;
float occlusion;
float3 specularColor;
float3 diffuseColor;
float3 normalWorld;
float smoothness;
float occlusion;
StandardData gbuf;
StandardData gbuf;
// extras
float oneMinusReflectivity;
float3 Vworld;
// extras
float oneMinusReflectivity;
float3 Vworld;
};
static LocalDataBRDF g_localParams;

StandardData data;
StandardData data;
data.normalWorld = normalize(2*gbuffer2.xyz-1);
data.smoothness = gbuffer1.a;
data.diffuseColor = gbuffer0.xyz; data.specularColor = gbuffer1.xyz;
data.occlusion = gbuffer0.a;
data.normalWorld = normalize(2*gbuffer2.xyz-1);
data.smoothness = gbuffer1.a;
data.diffuseColor = gbuffer0.xyz; data.specularColor = gbuffer1.xyz;
data.occlusion = gbuffer0.a;
return data;
return data;
StandardData data = g_localParams.gbuf;
StandardData data = g_localParams.gbuf;
return data.occlusion * UNITY_BRDF_PBS(0, data.specularColor, g_localParams.oneMinusReflectivity, data.smoothness, data.normalWorld, g_localParams.Vworld, light, ind).rgb;
return data.occlusion * UNITY_BRDF_PBS(0, data.specularColor, g_localParams.oneMinusReflectivity, data.smoothness, data.normalWorld, g_localParams.Vworld, light, ind).rgb;
uint2 pixCoord = ((uint2) i.vertex.xy);
uint2 pixCoord = ((uint2) i.vertex.xy);
float zbufDpth = FetchDepth(_CameraDepthTexture, pixCoord.xy).x;
float linDepth = GetLinearDepth(zbufDpth);
float zbufDpth = FetchDepth(_CameraDepthTexture, pixCoord.xy).x;
float linDepth = GetLinearDepth(zbufDpth);
float3 vP = GetViewPosFromLinDepth(i.vertex.xy, linDepth);
float3 vPw = mul(g_mViewToWorld, float4(vP, 1)).xyz;
float3 Vworld = normalize(mul((float3x3) g_mViewToWorld, -vP).xyz); //unity_CameraToWorld
float3 vP = GetViewPosFromLinDepth(i.vertex.xy, linDepth);
float3 vPw = mul(g_mViewToWorld, float4(vP, 1)).xyz;
float3 Vworld = normalize(mul((float3x3) g_mViewToWorld, -vP).xyz); //unity_CameraToWorld
float4 gbuffer0 = _CameraGBufferTexture0.Load( uint3(pixCoord.xy, 0) );
float4 gbuffer1 = _CameraGBufferTexture1.Load( uint3(pixCoord.xy, 0) );
float4 gbuffer2 = _CameraGBufferTexture2.Load( uint3(pixCoord.xy, 0) );
float4 gbuffer0 = _CameraGBufferTexture0.Load( uint3(pixCoord.xy, 0) );
float4 gbuffer1 = _CameraGBufferTexture1.Load( uint3(pixCoord.xy, 0) );
float4 gbuffer2 = _CameraGBufferTexture2.Load( uint3(pixCoord.xy, 0) );
StandardData data = UnityStandardDataFromGbuffer(gbuffer0, gbuffer1, gbuffer2);
StandardData data = UnityStandardDataFromGbuffer(gbuffer0, gbuffer1, gbuffer2);
g_localParams.gbuf = data;
g_localParams.oneMinusReflectivity = 1.0 - SpecularStrength(data.specularColor.rgb);
g_localParams.Vworld = Vworld;
g_localParams.gbuf = data;
g_localParams.oneMinusReflectivity = 1.0 - SpecularStrength(data.specularColor.rgb);
g_localParams.Vworld = Vworld;
uint numReflectionsProcessed = 0;
float3 c = ExecuteReflectionListTiled(numReflectionsProcessed, pixCoord, vP, data.normalWorld, Vworld, data.smoothness);
uint numReflectionsProcessed = 0;
float3 c = ExecuteReflectionListTiled(numReflectionsProcessed, pixCoord, vP, data.normalWorld, Vworld, data.smoothness);
//c = OverlayHeatMap(numLightsProcessed, c);
return float4(c,1.0);
//c = OverlayHeatMap(numLightsProcessed, c);
return float4(c,1.0);
ENDCG
ENDCG
}
}

106
Assets/ScriptableRenderLoop/fptl/Internal-DeferredShading.shader


Shader "Hidden/Internal-Obscurity" {
Properties {
_LightTexture0 ("", any) = "" {}
_ShadowMapTexture ("", any) = "" {}
_SrcBlend ("", Float) = 1
_DstBlend ("", Float) = 1
_LightTexture0 ("", any) = "" {}
_ShadowMapTexture ("", any) = "" {}
_SrcBlend ("", Float) = 1
_DstBlend ("", Float) = 1
}
SubShader {

Pass
Pass
ZWrite Off
ZTest Always
Cull Off
Blend Off
//Blend [_SrcBlend] [_DstBlend]
ZWrite Off
ZTest Always
Cull Off
Blend Off
//Blend [_SrcBlend] [_DstBlend]
CGPROGRAM
#pragma target 5.0

#pragma multi_compile USE_FPTL_LIGHTLIST USE_CLUSTERED_LIGHTLIST
#pragma multi_compile USE_FPTL_LIGHTLIST USE_CLUSTERED_LIGHTLIST
#include "UnityLightingCommon.cginc"

#ifdef USE_FPTL_LIGHTLIST
#define OPAQUES_ONLY
#define OPAQUES_ONLY
#endif
#include "TiledLightingTemplate.hlsl"

struct v2f {
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
v2f o;
o.vertex = UnityObjectToClipPos(vertex);
o.texcoord = texcoord.xy;
return o;
v2f o;
o.vertex = UnityObjectToClipPos(vertex);
o.texcoord = texcoord.xy;
return o;
float3 specularColor;
float3 diffuseColor;
float3 normalWorld;
float smoothness;
float3 specularColor;
float3 diffuseColor;
float3 normalWorld;
float smoothness;
StandardData gbuf;
StandardData gbuf;
// extras
float oneMinusReflectivity;
float3 Vworld;
// extras
float oneMinusReflectivity;
float3 Vworld;
};
static LocalDataBRDF g_localParams;

StandardData data;
StandardData data;
data.normalWorld = normalize(2*gbuffer2.xyz-1);
data.smoothness = gbuffer1.a;
data.diffuseColor = gbuffer0.xyz; data.specularColor = gbuffer1.xyz;
float ao = gbuffer0.a;
data.normalWorld = normalize(2*gbuffer2.xyz-1);
data.smoothness = gbuffer1.a;
data.diffuseColor = gbuffer0.xyz; data.specularColor = gbuffer1.xyz;
float ao = gbuffer0.a;
return data;
return data;
StandardData data = g_localParams.gbuf;
return UNITY_BRDF_PBS(data.diffuseColor, data.specularColor, g_localParams.oneMinusReflectivity, data.smoothness, data.normalWorld, g_localParams.Vworld, light, ind);
StandardData data = g_localParams.gbuf;
return UNITY_BRDF_PBS(data.diffuseColor, data.specularColor, g_localParams.oneMinusReflectivity, data.smoothness, data.normalWorld, g_localParams.Vworld, light, ind);
uint2 pixCoord = ((uint2) i.vertex.xy);
uint2 pixCoord = ((uint2) i.vertex.xy);
float zbufDpth = FetchDepth(_CameraDepthTexture, pixCoord.xy).x;
float linDepth = GetLinearDepth(zbufDpth);
float zbufDpth = FetchDepth(_CameraDepthTexture, pixCoord.xy).x;
float linDepth = GetLinearDepth(zbufDpth);
float3 vP = GetViewPosFromLinDepth(i.vertex.xy, linDepth);
float3 vPw = mul(g_mViewToWorld, float4(vP, 1)).xyz;
float3 Vworld = normalize(mul((float3x3) g_mViewToWorld, -vP).xyz); //unity_CameraToWorld
float3 vP = GetViewPosFromLinDepth(i.vertex.xy, linDepth);
float3 vPw = mul(g_mViewToWorld, float4(vP, 1)).xyz;
float3 Vworld = normalize(mul((float3x3) g_mViewToWorld, -vP).xyz); //unity_CameraToWorld
float4 gbuffer0 = _CameraGBufferTexture0.Load( uint3(pixCoord.xy, 0) );
float4 gbuffer1 = _CameraGBufferTexture1.Load( uint3(pixCoord.xy, 0) );
float4 gbuffer2 = _CameraGBufferTexture2.Load( uint3(pixCoord.xy, 0) );
float4 gbuffer0 = _CameraGBufferTexture0.Load( uint3(pixCoord.xy, 0) );
float4 gbuffer1 = _CameraGBufferTexture1.Load( uint3(pixCoord.xy, 0) );
float4 gbuffer2 = _CameraGBufferTexture2.Load( uint3(pixCoord.xy, 0) );
StandardData data = UnityStandardDataFromGbuffer(gbuffer0, gbuffer1, gbuffer2);
StandardData data = UnityStandardDataFromGbuffer(gbuffer0, gbuffer1, gbuffer2);
g_localParams.gbuf = data;
g_localParams.oneMinusReflectivity = 1.0 - SpecularStrength(data.specularColor.rgb);
g_localParams.Vworld = Vworld;
g_localParams.gbuf = data;
g_localParams.oneMinusReflectivity = 1.0 - SpecularStrength(data.specularColor.rgb);
g_localParams.Vworld = Vworld;
uint numLightsProcessed = 0;
float3 c = ExecuteLightListTiled(numLightsProcessed, pixCoord, vP, vPw, Vworld);
uint numLightsProcessed = 0;
float3 c = ExecuteLightListTiled(numLightsProcessed, pixCoord, vP, vPw, Vworld);
//c = OverlayHeatMap(numLightsProcessed, c);
return float4(c,1.0);
//c = OverlayHeatMap(numLightsProcessed, c);
return float4(c,1.0);
ENDCG
ENDCG
}
}

44
Assets/ScriptableRenderLoop/fptl/LightDefinitions.cs


[UnityEngine.ScriptableRenderLoop.GenerateHLSL]
public struct SFiniteLightData
{
// setup constant buffer
// setup constant buffer
public int flags;
public int flags;
public Vector3 vLaxisX;
public Vector3 vLaxisX;
public Vector3 vLaxisY;
public float fSphRadiusSq;
public Vector3 vLaxisY;
public float fSphRadiusSq;
public Vector3 vCol;
public int iSliceIndex;
public Vector3 vCol;
public int iSliceIndex;
public uint uShadowLightIndex;
public uint uShadowLightIndex;
public Vector3 vLocalCubeCapturePoint;
public float fProbeBlendDistance;

public Vector3 vBoxAxisX;
public Vector3 vBoxAxisY;
public Vector3 vBoxAxisZ;
public Vector3 vCen; // a center in camera space inside the bounding volume of the light source.
public Vector3 vCen; // a center in camera space inside the bounding volume of the light source.
public Vector2 vScaleXY;
public float fRadius;
};

{
public Vector3 vCol;
public float fLightIntensity;
public Vector3 vCol;
public float fLightIntensity;
public Vector3 vLaxisX;
public uint uShadowLightIndex;
public Vector3 vLaxisX;
public uint uShadowLightIndex;
public Vector3 vLaxisY;
public float fPad0;
public Vector3 vLaxisY;
public float fPad0;
public Vector3 vLaxisZ;
public float fPad1;
public Vector3 vLaxisZ;
public float fPad1;
};
[UnityEngine.ScriptableRenderLoop.GenerateHLSL]

public static int SPOT_LIGHT = 0;
public static int SPHERE_LIGHT = 1;
public static int BOX_LIGHT = 2;
public static int DIRECTIONAL_LIGHT = 3;
public static int DIRECTIONAL_LIGHT = 3;
// direct lights and reflection probes for now
public static int NR_LIGHT_MODELS = 2;
// direct lights and reflection probes for now
public static int NR_LIGHT_MODELS = 2;
public static int DIRECT_LIGHT = 0;
public static int REFLECTION_LIGHT = 1;
}

138
Assets/ScriptableRenderLoop/fptl/LightDefinitions.cs.hlsl


// PackingRules = Exact
struct SFiniteLightData
{
float fPenumbra;
int flags;
uint uLightType;
uint uLightModel;
float3 vLpos;
float fLightIntensity;
float3 vLaxisX;
float fRecipRange;
float3 vLaxisY;
float fSphRadiusSq;
float3 vLaxisZ;
float cotan;
float3 vCol;
int iSliceIndex;
float3 vBoxInnerDist;
float fDecodeExp;
float3 vBoxInvRange;
uint uShadowLightIndex;
float3 vLocalCubeCapturePoint;
float fProbeBlendDistance;
float fPenumbra;
int flags;
uint uLightType;
uint uLightModel;
float3 vLpos;
float fLightIntensity;
float3 vLaxisX;
float fRecipRange;
float3 vLaxisY;
float fSphRadiusSq;
float3 vLaxisZ;
float cotan;
float3 vCol;
int iSliceIndex;
float3 vBoxInnerDist;
float fDecodeExp;
float3 vBoxInvRange;
uint uShadowLightIndex;
float3 vLocalCubeCapturePoint;
float fProbeBlendDistance;
};
// Generated from SFiniteLightBound

float3 vBoxAxisX;
float3 vBoxAxisY;
float3 vBoxAxisZ;
float3 vCen;
float2 vScaleXY;
float fRadius;
float3 vBoxAxisX;
float3 vBoxAxisY;
float3 vBoxAxisZ;
float3 vCen;
float2 vScaleXY;
float fRadius;
};
// Generated from DirectionalLight

float3 vCol;
float fLightIntensity;
float3 vLaxisX;
uint uShadowLightIndex;
float3 vLaxisY;
float fPad0;
float3 vLaxisZ;
float fPad1;
float3 vCol;
float fLightIntensity;
float3 vLaxisX;
uint uShadowLightIndex;
float3 vLaxisY;
float fPad0;
float3 vLaxisZ;
float fPad1;
};
//

{
return value.fPenumbra;
return value.fPenumbra;
return value.flags;
return value.flags;
return value.uLightType;
return value.uLightType;
return value.uLightModel;
return value.uLightModel;
return value.vLpos;
return value.vLpos;
return value.fLightIntensity;
return value.fLightIntensity;
return value.vLaxisX;
return value.vLaxisX;
return value.fRecipRange;
return value.fRecipRange;
return value.vLaxisY;
return value.vLaxisY;
return value.fSphRadiusSq;
return value.fSphRadiusSq;
return value.vLaxisZ;
return value.vLaxisZ;
return value.cotan;
return value.cotan;
return value.vCol;
return value.vCol;
return value.iSliceIndex;
return value.iSliceIndex;
return value.vBoxInnerDist;
return value.vBoxInnerDist;
return value.fDecodeExp;
return value.fDecodeExp;
return value.vBoxInvRange;
return value.vBoxInvRange;
return value.uShadowLightIndex;
return value.uShadowLightIndex;
return value.vLocalCubeCapturePoint;
return value.vLocalCubeCapturePoint;
return value.fProbeBlendDistance;
return value.fProbeBlendDistance;
}
//

{
return value.vBoxAxisX;
return value.vBoxAxisX;
return value.vBoxAxisY;
return value.vBoxAxisY;
return value.vBoxAxisZ;
return value.vBoxAxisZ;
return value.vCen;
return value.vCen;
return value.vScaleXY;
return value.vScaleXY;
return value.fRadius;
return value.fRadius;
}
//

{
return value.vCol;
return value.vCol;
return value.fLightIntensity;
return value.fLightIntensity;
return value.vLaxisX;
return value.vLaxisX;
return value.uShadowLightIndex;
return value.uShadowLightIndex;
return value.vLaxisY;
return value.vLaxisY;
return value.fPad0;
return value.fPad0;
return value.vLaxisZ;
return value.vLaxisZ;
return value.fPad1;
return value.fPad1;

347
Assets/ScriptableRenderLoop/fptl/LightingTemplate.hlsl


sampler2D _LightTextureB0;
UNITY_DECLARE_TEX2DARRAY(_spotCookieTextures);
UNITY_DECLARE_TEXCUBEARRAY(_pointCookieTextures);
StructuredBuffer<DirectionalLight> g_dirLightData;

float ComputeShadow_PCF_3x3_Gaussian(float3 vPositionWs, float4x4 matWorldToShadow)
{
float4 vPositionTextureSpace = mul(float4(vPositionWs.xyz, 1.0), matWorldToShadow);
vPositionTextureSpace.xyz /= vPositionTextureSpace.w;
float4 vPositionTextureSpace = mul(float4(vPositionWs.xyz, 1.0), matWorldToShadow);
vPositionTextureSpace.xyz /= vPositionTextureSpace.w;
float2 shadowMapCenter = vPositionTextureSpace.xy;
float2 shadowMapCenter = vPositionTextureSpace.xy;
if ((shadowMapCenter.x < 0.0f) || (shadowMapCenter.x > 1.0f) || (shadowMapCenter.y < 0.0f) || (shadowMapCenter.y > 1.0f))
return 1.0f;
if ((shadowMapCenter.x < 0.0f) || (shadowMapCenter.x > 1.0f) || (shadowMapCenter.y < 0.0f) || (shadowMapCenter.y > 1.0f))
return 1.0f;
float objDepth = saturate(257.0 / 256.0 - vPositionTextureSpace.z);
float objDepth = saturate(257.0 / 256.0 - vPositionTextureSpace.z);
float4 v20Taps;
v20Taps.x = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms1.xy, objDepth)).x; // 1 1
v20Taps.y = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms1.zy, objDepth)).x; // -1 1
v20Taps.z = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms1.xw, objDepth)).x; // 1 -1
v20Taps.w = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms1.zw, objDepth)).x; // -1 -1
float flSum = dot(v20Taps.xyzw, float4(0.25, 0.25, 0.25, 0.25));
if ((flSum == 0.0) || (flSum == 1.0))
return flSum;
flSum *= g_vShadow3x3PCFTerms0.x * 4.0;
float4 v20Taps;
v20Taps.x = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms1.xy, objDepth)).x; // 1 1
v20Taps.y = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms1.zy, objDepth)).x; // -1 1
v20Taps.z = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms1.xw, objDepth)).x; // 1 -1
v20Taps.w = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms1.zw, objDepth)).x; // -1 -1
float flSum = dot(v20Taps.xyzw, float4(0.25, 0.25, 0.25, 0.25));
if ((flSum == 0.0) || (flSum == 1.0))
return flSum;
flSum *= g_vShadow3x3PCFTerms0.x * 4.0;
float4 v33Taps;
v33Taps.x = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms2.xz, objDepth)).x; // 1 0
v33Taps.y = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms3.xz, objDepth)).x; // -1 0
v33Taps.z = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms3.zy, objDepth)).x; // 0 -1
v33Taps.w = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms2.zy, objDepth)).x; // 0 1
flSum += dot(v33Taps.xyzw, g_vShadow3x3PCFTerms0.yyyy);
float4 v33Taps;
v33Taps.x = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms2.xz, objDepth)).x; // 1 0
v33Taps.y = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms3.xz, objDepth)).x; // -1 0
v33Taps.z = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms3.zy, objDepth)).x; // 0 -1
v33Taps.w = VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy + g_vShadow3x3PCFTerms2.zy, objDepth)).x; // 0 1
flSum += dot(v33Taps.xyzw, g_vShadow3x3PCFTerms0.yyyy);
flSum += VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy, objDepth)).x * g_vShadow3x3PCFTerms0.z;
flSum += VALVE_SAMPLE_SHADOW(g_tShadowBuffer, float3(shadowMapCenter.xy, objDepth)).x * g_vShadow3x3PCFTerms0.z;
return flSum;
return flSum;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------

*/
float GetSplitSphereIndexForDirshadows(float3 wpos)
{
float3 fromCenter0 = wpos.xyz - g_vDirShadowSplitSpheres[0].xyz;
float3 fromCenter1 = wpos.xyz - g_vDirShadowSplitSpheres[1].xyz;
float3 fromCenter2 = wpos.xyz - g_vDirShadowSplitSpheres[2].xyz;
float3 fromCenter3 = wpos.xyz - g_vDirShadowSplitSpheres[3].xyz;
float4 distances2 = float4(dot(fromCenter0, fromCenter0), dot(fromCenter1, fromCenter1), dot(fromCenter2, fromCenter2), dot(fromCenter3, fromCenter3));
float3 fromCenter0 = wpos.xyz - g_vDirShadowSplitSpheres[0].xyz;
float3 fromCenter1 = wpos.xyz - g_vDirShadowSplitSpheres[1].xyz;
float3 fromCenter2 = wpos.xyz - g_vDirShadowSplitSpheres[2].xyz;
float3 fromCenter3 = wpos.xyz - g_vDirShadowSplitSpheres[3].xyz;
float4 distances2 = float4(dot(fromCenter0, fromCenter0), dot(fromCenter1, fromCenter1), dot(fromCenter2, fromCenter2), dot(fromCenter3, fromCenter3));
float4 vDirShadowSplitSphereSqRadii;
vDirShadowSplitSphereSqRadii.x = g_vDirShadowSplitSpheres[0].w;
vDirShadowSplitSphereSqRadii.y = g_vDirShadowSplitSpheres[1].w;
vDirShadowSplitSphereSqRadii.z = g_vDirShadowSplitSpheres[2].w;
vDirShadowSplitSphereSqRadii.w = g_vDirShadowSplitSpheres[3].w;
fixed4 weights = float4(distances2 < vDirShadowSplitSphereSqRadii);
weights.yzw = saturate(weights.yzw - weights.xyz);
return 4 - dot(weights, float4(4, 3, 2, 1));
float4 vDirShadowSplitSphereSqRadii;
vDirShadowSplitSphereSqRadii.x = g_vDirShadowSplitSpheres[0].w;
vDirShadowSplitSphereSqRadii.y = g_vDirShadowSplitSpheres[1].w;
vDirShadowSplitSphereSqRadii.z = g_vDirShadowSplitSpheres[2].w;
vDirShadowSplitSphereSqRadii.w = g_vDirShadowSplitSpheres[3].w;
fixed4 weights = float4(distances2 < vDirShadowSplitSphereSqRadii);
weights.yzw = saturate(weights.yzw - weights.xyz);
return 4 - dot(weights, float4(4, 3, 2, 1));
float flShadowScalar = 1.0;
int shadowSplitIndex = 0;
float flShadowScalar = 1.0;
int shadowSplitIndex = 0;
if (type == DIRECTIONAL_LIGHT)
{
shadowSplitIndex = GetSplitSphereIndexForDirshadows(vPositionWs);
}
if (type == DIRECTIONAL_LIGHT)
{
shadowSplitIndex = GetSplitSphereIndexForDirshadows(vPositionWs);
}
else if (type == SPHERE_LIGHT)
{
float3 absPos = abs(vPositionToLightDirWs);
shadowSplitIndex = (vPositionToLightDirWs.z > 0) ? CUBEMAPFACE_NEGATIVE_Z : CUBEMAPFACE_POSITIVE_Z;
if (absPos.x > absPos.y)
{
if (absPos.x > absPos.z)
{
shadowSplitIndex = (vPositionToLightDirWs.x > 0) ? CUBEMAPFACE_NEGATIVE_X : CUBEMAPFACE_POSITIVE_X;
}
}
else
{
if (absPos.y > absPos.z)
{
shadowSplitIndex = (vPositionToLightDirWs.y > 0) ? CUBEMAPFACE_NEGATIVE_Y : CUBEMAPFACE_POSITIVE_Y;
}
}
}
else if (type == SPHERE_LIGHT)
{
float3 absPos = abs(vPositionToLightDirWs);
shadowSplitIndex = (vPositionToLightDirWs.z > 0) ? CUBEMAPFACE_NEGATIVE_Z : CUBEMAPFACE_POSITIVE_Z;
if (absPos.x > absPos.y)
{
if (absPos.x > absPos.z)
{
shadowSplitIndex = (vPositionToLightDirWs.x > 0) ? CUBEMAPFACE_NEGATIVE_X : CUBEMAPFACE_POSITIVE_X;
}
}
else
{
if (absPos.y > absPos.z)
{
shadowSplitIndex = (vPositionToLightDirWs.y > 0) ? CUBEMAPFACE_NEGATIVE_Y : CUBEMAPFACE_POSITIVE_Y;
}
}
}
flShadowScalar = ComputeShadow_PCF_3x3_Gaussian(vPositionWs.xyz, g_matWorldToShadow[lightIndex * MAX_SHADOWMAP_PER_LIGHT + shadowSplitIndex]);
return flShadowScalar;
flShadowScalar = ComputeShadow_PCF_3x3_Gaussian(vPositionWs.xyz, g_matWorldToShadow[lightIndex * MAX_SHADOWMAP_PER_LIGHT + shadowSplitIndex]);
return flShadowScalar;
UnityIndirect ind;
UNITY_INITIALIZE_OUTPUT(UnityIndirect, ind);
ind.diffuse = 0;
ind.specular = 0;
UnityIndirect ind;
UNITY_INITIALIZE_OUTPUT(UnityIndirect, ind);
ind.diffuse = 0;
ind.specular = 0;
float3 ints = 0;
for (int i = 0; i < g_nNumDirLights; i++)
{
DirectionalLight lightData = g_dirLightData[i];
float atten = 1;
[branch]
if (lightData.uShadowLightIndex != 0xffffffff)
{
float shadowScalar = SampleShadow(DIRECTIONAL_LIGHT, vPw, 0, lightData.uShadowLightIndex);
atten *= shadowScalar;
}
UnityLight light;
light.color.xyz = lightData.vCol.xyz * atten;
light.dir.xyz = mul((float3x3) g_mViewToWorld, -lightData.vLaxisZ).xyz;
ints += EvalMaterial(light, ind);
}
uint l=0;
// don't need the outer loop since the lights are sorted by volume type
//while(l<numLights)
if(numLights>0)
{
uint uIndex = l<numLights ? FetchIndex(start, l) : 0;
uint uLgtType = l<numLights ? g_vLightData[uIndex].uLightType : 0;
// specialized loop for spot lights
while(l<numLights && uLgtType==SPOT_LIGHT)
{
SFiniteLightData lgtDat = g_vLightData[uIndex];
float3 vLp = lgtDat.vLpos.xyz;
float3 ints = 0;
uint l=0;
float3 toLight = vLp - vP;
float dist = length(toLight);
float3 vL = toLight / dist;
for (int i = 0; i < g_nNumDirLights; i++)
{
DirectionalLight lightData = g_dirLightData[i];
float atten = 1;
float attLookUp = dist*lgtDat.fRecipRange; attLookUp *= attLookUp;
float atten = tex2Dlod(_LightTextureB0, float4(attLookUp.rr, 0.0, 0.0)).UNITY_ATTEN_CHANNEL;
[branch]
if (lightData.uShadowLightIndex != 0xffffffff)
{
float shadowScalar = SampleShadow(DIRECTIONAL_LIGHT, vPw, 0, lightData.uShadowLightIndex);
atten *= shadowScalar;
}
// spot attenuation
const float fProjVec = -dot(vL, lgtDat.vLaxisZ.xyz); // spotDir = lgtDat.vLaxisZ.xyz
float2 cookCoord = (-lgtDat.cotan)*float2( dot(vL, lgtDat.vLaxisX.xyz), dot(vL, lgtDat.vLaxisY.xyz) ) / fProjVec;
UnityLight light;
light.color.xyz = lightData.vCol.xyz * atten;
light.dir.xyz = mul((float3x3) g_mViewToWorld, -lightData.vLaxisZ).xyz;
const bool bHasCookie = (lgtDat.flags&IS_CIRCULAR_SPOT_SHAPE)==0; // all square spots have cookies
float d0 = 0.65;
float4 angularAtt = float4(1,1,1,smoothstep(0.0, 1.0-d0, 1.0-length(cookCoord)));
[branch]if(bHasCookie)
{
cookCoord = cookCoord*0.5 + 0.5;
angularAtt = UNITY_SAMPLE_TEX2DARRAY_LOD(_spotCookieTextures, float3(cookCoord, lgtDat.iSliceIndex), 0.0);
}
atten *= angularAtt.w*(fProjVec>0.0); // finally apply this to the dist att.
ints += EvalMaterial(light, ind);
}
const bool bHasShadow = (lgtDat.flags&HAS_SHADOW)!=0;
[branch]if(bHasShadow)
{
float shadowScalar = SampleShadow(SPOT_LIGHT, vPw, 0, lgtDat.uShadowLightIndex);
atten *= shadowScalar;
}
// we need this outer loop for when we cannot assume a wavefront is 64 wide
// since in this case we cannot assume the lights will remain sorted by type
// during processing in lightlist_cs.hlsl
#if !defined(XBONE) && !defined(PLAYSTATION4)
while(l<numLights)
#endif
{
uint uIndex = l<numLights ? FetchIndex(start, l) : 0;
uint uLgtType = l<numLights ? g_vLightData[uIndex].uLightType : 0;
UnityLight light;
light.color.xyz = lgtDat.vCol.xyz*atten*angularAtt.xyz;
light.dir.xyz = mul((float3x3) g_mViewToWorld, vL).xyz; //unity_CameraToWorld
ints += EvalMaterial(light, ind);
// specialized loop for spot lights
while(l<numLights && uLgtType==SPOT_LIGHT)
{
SFiniteLightData lgtDat = g_vLightData[uIndex];
float3 vLp = lgtDat.vLpos.xyz;
++l; uIndex = l<numLights ? FetchIndex(start, l) : 0;
uLgtType = l<numLights ? g_vLightData[uIndex].uLightType : 0;
}
float3 toLight = vLp - vP;
float dist = length(toLight);
float3 vL = toLight / dist;
float attLookUp = dist*lgtDat.fRecipRange; attLookUp *= attLookUp;
float atten = tex2Dlod(_LightTextureB0, float4(attLookUp.rr, 0.0, 0.0)).UNITY_ATTEN_CHANNEL;
// spot attenuation
const float fProjVec = -dot(vL, lgtDat.vLaxisZ.xyz); // spotDir = lgtDat.vLaxisZ.xyz
float2 cookCoord = (-lgtDat.cotan)*float2( dot(vL, lgtDat.vLaxisX.xyz), dot(vL, lgtDat.vLaxisY.xyz) ) / fProjVec;
// specialized loop for sphere lights
while(l<numLights && uLgtType==SPHERE_LIGHT)
{
SFiniteLightData lgtDat = g_vLightData[uIndex];
float3 vLp = lgtDat.vLpos.xyz;
const bool bHasCookie = (lgtDat.flags&IS_CIRCULAR_SPOT_SHAPE)==0; // all square spots have cookies
float d0 = 0.65;
float4 angularAtt = float4(1,1,1,smoothstep(0.0, 1.0-d0, 1.0-length(cookCoord)));
[branch]if(bHasCookie)
{
cookCoord = cookCoord*0.5 + 0.5;
angularAtt = UNITY_SAMPLE_TEX2DARRAY_LOD(_spotCookieTextures, float3(cookCoord, lgtDat.iSliceIndex), 0.0);
}
atten *= angularAtt.w*(fProjVec>0.0); // finally apply this to the dist att.
const bool bHasShadow = (lgtDat.flags&HAS_SHADOW)!=0;
[branch]if(bHasShadow)
{
float shadowScalar = SampleShadow(SPOT_LIGHT, vPw, 0, lgtDat.uShadowLightIndex);
atten *= shadowScalar;
}
float3 toLight = vLp - vP;
float dist = length(toLight);
float3 vL = toLight / dist;
float3 vLw = mul((float3x3) g_mViewToWorld, vL).xyz; //unity_CameraToWorld
UnityLight light;
light.color.xyz = lgtDat.vCol.xyz*atten*angularAtt.xyz;
light.dir.xyz = mul((float3x3) g_mViewToWorld, vL).xyz; //unity_CameraToWorld
float attLookUp = dist*lgtDat.fRecipRange; attLookUp *= attLookUp;
float atten = tex2Dlod(_LightTextureB0, float4(attLookUp.rr, 0.0, 0.0)).UNITY_ATTEN_CHANNEL;
ints += EvalMaterial(light, ind);
float4 cookieColor = float4(1,1,1,1);
++l; uIndex = l<numLights ? FetchIndex(start, l) : 0;
uLgtType = l<numLights ? g_vLightData[uIndex].uLightType : 0;
}
// specialized loop for sphere lights
while(l<numLights && uLgtType==SPHERE_LIGHT)
{
SFiniteLightData lgtDat = g_vLightData[uIndex];
float3 vLp = lgtDat.vLpos.xyz;
const bool bHasCookie = (lgtDat.flags&HAS_COOKIE_TEXTURE)!=0;
[branch]if(bHasCookie)
{
float3 cookieCoord = -float3(dot(vL, lgtDat.vLaxisX.xyz), dot(vL, lgtDat.vLaxisY.xyz), dot(vL, lgtDat.vLaxisZ.xyz)); // negate to make vL a fromLight vector
cookieColor = UNITY_SAMPLE_TEXCUBEARRAY_LOD(_pointCookieTextures, float4(cookieCoord, lgtDat.iSliceIndex), 0.0);
atten *= cookieColor.w;
}
float3 toLight = vLp - vP;
float dist = length(toLight);
float3 vL = toLight / dist;
float3 vLw = mul((float3x3) g_mViewToWorld, vL).xyz; //unity_CameraToWorld
const bool bHasShadow = (lgtDat.flags&HAS_SHADOW)!=0;
[branch]if(bHasShadow)
{
float shadowScalar = SampleShadow(SPHERE_LIGHT, vPw, vLw, lgtDat.uShadowLightIndex);
atten *= shadowScalar;
}
float attLookUp = dist*lgtDat.fRecipRange; attLookUp *= attLookUp;
float atten = tex2Dlod(_LightTextureB0, float4(attLookUp.rr, 0.0, 0.0)).UNITY_ATTEN_CHANNEL;
UnityLight light;
light.color.xyz = lgtDat.vCol.xyz*atten*cookieColor.xyz;
light.dir.xyz = vLw;
float4 cookieColor = float4(1,1,1,1);
const bool bHasCookie = (lgtDat.flags&HAS_COOKIE_TEXTURE)!=0;
[branch]if(bHasCookie)
{
float3 cookieCoord = -float3(dot(vL, lgtDat.vLaxisX.xyz), dot(vL, lgtDat.vLaxisY.xyz), dot(vL, lgtDat.vLaxisZ.xyz)); // negate to make vL a fromLight vector
cookieColor = UNITY_SAMPLE_TEXCUBEARRAY_LOD(_pointCookieTextures, float4(cookieCoord, lgtDat.iSliceIndex), 0.0);
atten *= cookieColor.w;
}
const bool bHasShadow = (lgtDat.flags&HAS_SHADOW)!=0;
[branch]if(bHasShadow)
{
float shadowScalar = SampleShadow(SPHERE_LIGHT, vPw, vLw, lgtDat.uShadowLightIndex);
atten *= shadowScalar;
}
ints += EvalMaterial(light, ind);
UnityLight light;
light.color.xyz = lgtDat.vCol.xyz*atten*cookieColor.xyz;
light.dir.xyz = vLw;
ints += EvalMaterial(light, ind);
++l; uIndex = l<numLights ? FetchIndex(start, l) : 0;
uLgtType = l<numLights ? g_vLightData[uIndex].uLightType : 0;
}
++l; uIndex = l<numLights ? FetchIndex(start, l) : 0;
uLgtType = l<numLights ? g_vLightData[uIndex].uLightType : 0;
}
#if !defined(XBONE) && !defined(PLAYSTATION4)
//if(uLgtType>=MAX_TYPES) ++l;
if(uLgtType!=SPOT_LIGHT && uLgtType!=SPHERE_LIGHT) ++l;
#endif
}
//if(uLgtType!=SPOT_LIGHT && uLgtType!=SPHERE_LIGHT) ++l;
}
return ints;
return ints;
}

#endif
#endif

170
Assets/ScriptableRenderLoop/fptl/ReflectionTemplate.hlsl


half3 distanceFromAABB(half3 p, half3 aabbMin, half3 aabbMax)
{
return max(max(p - aabbMax, aabbMin - p), half3(0.0, 0.0, 0.0));
return max(max(p - aabbMax, aabbMin - p), half3(0.0, 0.0, 0.0));
float3 worldNormalRefl = reflect(-Vworld, vNw);
float3 worldNormalRefl = reflect(-Vworld, vNw);
float3 vspaceRefl = mul((float3x3) g_mWorldToView, worldNormalRefl).xyz;
float3 vspaceRefl = mul((float3x3) g_mWorldToView, worldNormalRefl).xyz;
float percRoughness = SmoothnessToPerceptualRoughness(smoothness);
float percRoughness = SmoothnessToPerceptualRoughness(smoothness);
UnityLight light;
light.color = 0;
light.dir = 0;
float3 ints = 0;
UnityLight light;
light.color = 0;
light.dir = 0;
float3 ints = 0;
uint l=0;
uint l=0;
// don't need the outer loop since the probes are sorted by volume type (currently one type in fact)
//while(l<numReflProbes)
if(numReflProbes>0)
{
uint uIndex = l<numReflProbes ? FetchIndex(start, l) : 0;
uint uLgtType = l<numReflProbes ? g_vLightData[uIndex].uLightType : 0;
// we need this outer loop for when we cannot assume a wavefront is 64 wide
// since in this case we cannot assume the lights will remain sorted by type
// during processing in lightlist_cs.hlsl
#if !defined(XBONE) && !defined(PLAYSTATION4)
while(l<numReflProbes)
#endif
{
uint uIndex = l<numReflProbes ? FetchIndex(start, l) : 0;
uint uLgtType = l<numReflProbes ? g_vLightData[uIndex].uLightType : 0;
// specialized loop for sphere lights
while(l<numReflProbes && uLgtType==(uint) BOX_LIGHT)
{
SFiniteLightData lgtDat = g_vLightData[uIndex];
float3 vLp = lgtDat.vLpos.xyz;
float3 vecToSurfPos = vP - vLp; // vector from reflection volume to surface position in camera space
float3 posInReflVolumeSpace = float3( dot(vecToSurfPos, lgtDat.vLaxisX), dot(vecToSurfPos, lgtDat.vLaxisY), dot(vecToSurfPos, lgtDat.vLaxisZ) );
// specialized loop for sphere lights
while(l<numReflProbes && uLgtType==(uint) BOX_LIGHT)
{
SFiniteLightData lgtDat = g_vLightData[uIndex];
float3 vLp = lgtDat.vLpos.xyz;
float3 vecToSurfPos = vP - vLp; // vector from reflection volume to surface position in camera space
float3 posInReflVolumeSpace = float3( dot(vecToSurfPos, lgtDat.vLaxisX), dot(vecToSurfPos, lgtDat.vLaxisY), dot(vecToSurfPos, lgtDat.vLaxisZ) );
float blendDistance = lgtDat.fProbeBlendDistance;//unity_SpecCube1_ProbePosition.w; // will be set to blend distance for this probe
float blendDistance = lgtDat.fProbeBlendDistance;//unity_SpecCube1_ProbePosition.w; // will be set to blend distance for this probe
float3 sampleDir;
if((lgtDat.flags&IS_BOX_PROJECTED)!=0)
{
// For box projection, use expanded bounds as they are rendered; otherwise
// box projection artifacts when outside of the box.
//float4 boxMin = unity_SpecCube0_BoxMin - float4(blendDistance,blendDistance,blendDistance,0);
//float4 boxMax = unity_SpecCube0_BoxMax + float4(blendDistance,blendDistance,blendDistance,0);
//sampleDir = BoxProjectedCubemapDirection (worldNormalRefl, worldPos, unity_SpecCube0_ProbePosition, boxMin, boxMax);
float3 sampleDir;
if((lgtDat.flags&IS_BOX_PROJECTED)!=0)
{
// For box projection, use expanded bounds as they are rendered; otherwise
// box projection artifacts when outside of the box.
//float4 boxMin = unity_SpecCube0_BoxMin - float4(blendDistance,blendDistance,blendDistance,0);
//float4 boxMax = unity_SpecCube0_BoxMax + float4(blendDistance,blendDistance,blendDistance,0);
//sampleDir = BoxProjectedCubemapDirection (worldNormalRefl, worldPos, unity_SpecCube0_ProbePosition, boxMin, boxMax);
float4 vBoxOuterDistance = float4( lgtDat.vBoxInnerDist + float3(blendDistance, blendDistance, blendDistance), 0.0 );
float4 vBoxOuterDistance = float4( lgtDat.vBoxInnerDist + float3(blendDistance, blendDistance, blendDistance), 0.0 );
// if rotation is NOT supported
sampleDir = BoxProjectedCubemapDirection(worldNormalRefl, posInReflVolumeSpace, float4(lgtDat.vLocalCubeCapturePoint, 1.0), -vBoxOuterDistance, vBoxOuterDistance);
// if rotation is NOT supported
sampleDir = BoxProjectedCubemapDirection(worldNormalRefl, posInReflVolumeSpace, float4(lgtDat.vLocalCubeCapturePoint, 1.0), -vBoxOuterDistance, vBoxOuterDistance);
float3 volumeSpaceRefl = float3( dot(vspaceRefl, lgtDat.vLaxisX), dot(vspaceRefl, lgtDat.vLaxisY), dot(vspaceRefl, lgtDat.vLaxisZ) );
float3 vPR = BoxProjectedCubemapDirection(volumeSpaceRefl, posInReflVolumeSpace, float4(lgtDat.vLocalCubeCapturePoint, 1.0), -vBoxOuterDistance, vBoxOuterDistance); // Volume space corrected reflection vector
sampleDir = mul( (float3x3) g_mViewToWorld, vPR.x*lgtDat.vLaxisX + vPR.y*lgtDat.vLaxisY + vPR.z*lgtDat.vLaxisZ );
float3 volumeSpaceRefl = float3( dot(vspaceRefl, lgtDat.vLaxisX), dot(vspaceRefl, lgtDat.vLaxisY), dot(vspaceRefl, lgtDat.vLaxisZ) );
float3 vPR = BoxProjectedCubemapDirection(volumeSpaceRefl, posInReflVolumeSpace, float4(lgtDat.vLocalCubeCapturePoint, 1.0), -vBoxOuterDistance, vBoxOuterDistance); // Volume space corrected reflection vector
sampleDir = mul( (float3x3) g_mViewToWorld, vPR.x*lgtDat.vLaxisX + vPR.y*lgtDat.vLaxisY + vPR.z*lgtDat.vLaxisZ );
}
else
sampleDir = worldNormalRefl;
}
else
sampleDir = worldNormalRefl;
Unity_GlossyEnvironmentData g;
g.roughness = percRoughness;
g.reflUVW = sampleDir;
Unity_GlossyEnvironmentData g;
g.roughness = percRoughness;
g.reflUVW = sampleDir;
half3 env0 = Unity_GlossyEnvironment(UNITY_PASS_TEXCUBEARRAY(_reflCubeTextures), lgtDat.iSliceIndex, float4(lgtDat.fLightIntensity, lgtDat.fDecodeExp, 0.0, 0.0), g);
half3 env0 = Unity_GlossyEnvironment(UNITY_PASS_TEXCUBEARRAY(_reflCubeTextures), lgtDat.iSliceIndex, float4(lgtDat.fLightIntensity, lgtDat.fDecodeExp, 0.0, 0.0), g);
UnityIndirect ind;
ind.diffuse = 0;
ind.specular = env0;// * data.occlusion;
UnityIndirect ind;
ind.diffuse = 0;
ind.specular = env0;// * data.occlusion;
//half3 rgb = UNITY_BRDF_PBS(0, data.specularColor, oneMinusReflectivity, data.smoothness, data.normalWorld, vWSpaceVDir, light, ind).rgb;
half3 rgb = EvalIndirectSpecular(light, ind);
//half3 rgb = UNITY_BRDF_PBS(0, data.specularColor, oneMinusReflectivity, data.smoothness, data.normalWorld, vWSpaceVDir, light, ind).rgb;
half3 rgb = EvalIndirectSpecular(light, ind);
// Calculate falloff value, so reflections on the edges of the Volume would gradually blend to previous reflection.
// Also this ensures that pixels not located in the reflection Volume AABB won't
// accidentally pick up reflections from this Volume.
//half3 distance = distanceFromAABB(worldPos, unity_SpecCube0_BoxMin.xyz, unity_SpecCube0_BoxMax.xyz);
half3 distance = distanceFromAABB(posInReflVolumeSpace, -lgtDat.vBoxInnerDist, lgtDat.vBoxInnerDist);
half falloff = saturate(1.0 - length(distance)/blendDistance);
// Calculate falloff value, so reflections on the edges of the Volume would gradually blend to previous reflection.
// Also this ensures that pixels not located in the reflection Volume AABB won't
// accidentally pick up reflections from this Volume.
//half3 distance = distanceFromAABB(worldPos, unity_SpecCube0_BoxMin.xyz, unity_SpecCube0_BoxMax.xyz);
half3 distance = distanceFromAABB(posInReflVolumeSpace, -lgtDat.vBoxInnerDist, lgtDat.vBoxInnerDist);
half falloff = saturate(1.0 - length(distance)/blendDistance);
ints = lerp(ints, rgb, falloff);
ints = lerp(ints, rgb, falloff);
// next probe
++l; uIndex = l<numReflProbes ? FetchIndex(start, l) : 0;
uLgtType = l<numReflProbes ? g_vLightData[uIndex].uLightType : 0;
}
// next probe
++l; uIndex = l<numReflProbes ? FetchIndex(start, l) : 0;
uLgtType = l<numReflProbes ? g_vLightData[uIndex].uLightType : 0;
}
#if !defined(XBONE) && !defined(PLAYSTATION4)
if(uLgtType!=BOX_LIGHT) ++l;
#endif
}
//if(uLgtType!=BOX_LIGHT) ++l;
}
return ints;
return ints;
}

// TODO: remove pow, store cubemap mips differently
half perceptualRoughness = pow(glossIn.roughness, 3.0/4.0);
// TODO: remove pow, store cubemap mips differently
half perceptualRoughness = pow(glossIn.roughness, 3.0/4.0);
half perceptualRoughness = glossIn.roughness; // MM: switched to this
half perceptualRoughness = glossIn.roughness; // MM: switched to this
//perceptualRoughness = sqrt(sqrt(2/(64.0+2))); // spec power to the square root of real roughness
//perceptualRoughness = sqrt(sqrt(2/(64.0+2))); // spec power to the square root of real roughness
float m = perceptualRoughness*perceptualRoughness; // m is the real roughness parameter
const float fEps = 1.192092896e-07F; // smallest such that 1.0+FLT_EPSILON != 1.0 (+1e-4h is NOT good here. is visibly very wrong)
float n = (2.0/max(fEps, m*m))-2.0; // remap to spec power. See eq. 21 in --> https://dl.dropboxusercontent.com/u/55891920/papers/mm_brdf.pdf
float m = perceptualRoughness*perceptualRoughness; // m is the real roughness parameter
const float fEps = 1.192092896e-07F; // smallest such that 1.0+FLT_EPSILON != 1.0 (+1e-4h is NOT good here. is visibly very wrong)
float n = (2.0/max(fEps, m*m))-2.0; // remap to spec power. See eq. 21 in --> https://dl.dropboxusercontent.com/u/55891920/papers/mm_brdf.pdf
n /= 4; // remap from n_dot_h formulatino to n_dot_r. See section "Pre-convolved Cube Maps vs Path Tracers" --> https://s3.amazonaws.com/docs.knaldtech.com/knald/1.0.0/lys_power_drops.html
n /= 4; // remap from n_dot_h formulatino to n_dot_r. See section "Pre-convolved Cube Maps vs Path Tracers" --> https://s3.amazonaws.com/docs.knaldtech.com/knald/1.0.0/lys_power_drops.html
perceptualRoughness = pow( 2/(n+2), 0.25); // remap back to square root of real roughness
perceptualRoughness = pow( 2/(n+2), 0.25); // remap back to square root of real roughness
// MM: came up with a surprisingly close approximation to what the #if 0'ed out code above does.
perceptualRoughness = perceptualRoughness*(1.7 - 0.7*perceptualRoughness);
// MM: came up with a surprisingly close approximation to what the #if 0'ed out code above does.
perceptualRoughness = perceptualRoughness*(1.7 - 0.7*perceptualRoughness);
half mip = perceptualRoughness * UNITY_SPECCUBE_LOD_STEPS;
half4 rgbm = UNITY_SAMPLE_TEXCUBEARRAY_LOD(tex, float4(glossIn.reflUVW.xyz, sliceIndex), mip);
half mip = perceptualRoughness * UNITY_SPECCUBE_LOD_STEPS;
half4 rgbm = UNITY_SAMPLE_TEXCUBEARRAY_LOD(tex, float4(glossIn.reflUVW.xyz, sliceIndex), mip);
//return rgbm.xyz;
return DecodeHDR_NoLinearSupportInSM2 (rgbm, hdr);
//return rgbm.xyz;
return DecodeHDR_NoLinearSupportInSM2 (rgbm, hdr);
#endif
#endif

190
Assets/ScriptableRenderLoop/fptl/StandardTest.shader


Shader "Experim/StdShader"
{
Properties
{
_Color("Color", Color) = (1,1,1,1)
_MainTex("Albedo", 2D) = "white" {}
_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
Properties
{
_Color("Color", Color) = (1,1,1,1)
_MainTex("Albedo", 2D) = "white" {}
_Glossiness("Smoothness", Range(0.0, 1.0)) = 0.5
_GlossMapScale("Smoothness Scale", Range(0.0, 1.0)) = 1.0
[Enum(Metallic Alpha,0,Albedo Alpha,1)] _SmoothnessTextureChannel ("Smoothness texture channel", Float) = 0
_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
[Gamma] _Metallic("Metallic", Range(0.0, 1.0)) = 0.0
_MetallicGlossMap("Metallic", 2D) = "white" {}
_Glossiness("Smoothness", Range(0.0, 1.0)) = 0.5
_GlossMapScale("Smoothness Scale", Range(0.0, 1.0)) = 1.0
[Enum(Metallic Alpha,0,Albedo Alpha,1)] _SmoothnessTextureChannel ("Smoothness texture channel", Float) = 0
[ToggleOff] _SpecularHighlights("Specular Highlights", Float) = 1.0
[ToggleOff] _GlossyReflections("Glossy Reflections", Float) = 1.0
[Gamma] _Metallic("Metallic", Range(0.0, 1.0)) = 0.0
_MetallicGlossMap("Metallic", 2D) = "white" {}
_BumpScale("Scale", Float) = 1.0
_BumpMap("Normal Map", 2D) = "bump" {}
_Parallax ("Height Scale", Range (0.005, 0.08)) = 0.02
_ParallaxMap ("Height Map", 2D) = "black" {}
[ToggleOff] _SpecularHighlights("Specular Highlights", Float) = 1.0
[ToggleOff] _GlossyReflections("Glossy Reflections", Float) = 1.0
_OcclusionStrength("Strength", Range(0.0, 1.0)) = 1.0
_OcclusionMap("Occlusion", 2D) = "white" {}
_BumpScale("Scale", Float) = 1.0
_BumpMap("Normal Map", 2D) = "bump" {}
_EmissionColor("Color", Color) = (0,0,0)
_EmissionMap("Emission", 2D) = "white" {}
_DetailMask("Detail Mask", 2D) = "white" {}
_Parallax ("Height Scale", Range (0.005, 0.08)) = 0.02
_ParallaxMap ("Height Map", 2D) = "black" {}
_DetailAlbedoMap("Detail Albedo x2", 2D) = "grey" {}
_DetailNormalMapScale("Scale", Float) = 1.0
_DetailNormalMap("Normal Map", 2D) = "bump" {}
_OcclusionStrength("Strength", Range(0.0, 1.0)) = 1.0
_OcclusionMap("Occlusion", 2D) = "white" {}
[Enum(UV0,0,UV1,1)] _UVSec ("UV Set for secondary textures", Float) = 0
_EmissionColor("Color", Color) = (0,0,0)
_EmissionMap("Emission", 2D) = "white" {}
_DetailMask("Detail Mask", 2D) = "white" {}
// Blending state
[HideInInspector] _Mode ("__mode", Float) = 0.0
[HideInInspector] _SrcBlend ("__src", Float) = 1.0
[HideInInspector] _DstBlend ("__dst", Float) = 0.0
[HideInInspector] _ZWrite ("__zw", Float) = 1.0
}
_DetailAlbedoMap("Detail Albedo x2", 2D) = "grey" {}
_DetailNormalMapScale("Scale", Float) = 1.0
_DetailNormalMap("Normal Map", 2D) = "bump" {}
CGINCLUDE
#define UNITY_SETUP_BRDF_INPUT MetallicSetup
ENDCG
[Enum(UV0,0,UV1,1)] _UVSec ("UV Set for secondary textures", Float) = 0
SubShader
{
Tags { "RenderType" = "Opaque" "PerformanceChecks" = "False" }
LOD 300
// ------------------------------------------------------------------
// Forward pass
Pass
{
Name "FORWARD"
Tags { "LightMode" = "ForwardSinglePass" }
// Blending state
[HideInInspector] _Mode ("__mode", Float) = 0.0
[HideInInspector] _SrcBlend ("__src", Float) = 1.0
[HideInInspector] _DstBlend ("__dst", Float) = 0.0
[HideInInspector] _ZWrite ("__zw", Float) = 1.0
}
Blend [_SrcBlend] [_DstBlend]
ZWrite [_ZWrite]
CGINCLUDE
#define UNITY_SETUP_BRDF_INPUT MetallicSetup
ENDCG
CGPROGRAM
#pragma target 5.0
SubShader
{
Tags { "RenderType" = "Opaque" "PerformanceChecks" = "False" }
LOD 300
// -------------------------------------
#pragma shader_feature _NORMALMAP
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
#pragma shader_feature _EMISSION
#pragma shader_feature _METALLICGLOSSMAP
#pragma shader_feature ___ _DETAIL_MULX2
#pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
#pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF
#pragma shader_feature _ _GLOSSYREFLECTIONS_OFF
#pragma shader_feature _PARALLAXMAP
// ------------------------------------------------------------------
// Forward pass
Pass
{
Name "FORWARD"
Tags { "LightMode" = "ForwardSinglePass" }
#pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON
#pragma multi_compile DIRLIGHTMAP_OFF DIRLIGHTMAP_COMBINED DIRLIGHTMAP_SEPARATE
#pragma multi_compile DYNAMICLIGHTMAP_OFF DYNAMICLIGHTMAP_ON
#pragma multi_compile_fog
Blend [_SrcBlend] [_DstBlend]
ZWrite [_ZWrite]
#pragma vertex vertForward
#pragma fragment fragForward
CGPROGRAM
#pragma target 5.0
#include "UnityStandardForwardNew.cginc"
// -------------------------------------
#pragma shader_feature _NORMALMAP
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
#pragma shader_feature _EMISSION
#pragma shader_feature _METALLICGLOSSMAP
#pragma shader_feature ___ _DETAIL_MULX2
#pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
#pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF
#pragma shader_feature _ _GLOSSYREFLECTIONS_OFF
#pragma shader_feature _PARALLAXMAP
ENDCG
}
// ------------------------------------------------------------------
// Shadow rendering pass
Pass {
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
#pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON
#pragma multi_compile DIRLIGHTMAP_OFF DIRLIGHTMAP_COMBINED DIRLIGHTMAP_SEPARATE
#pragma multi_compile DYNAMICLIGHTMAP_OFF DYNAMICLIGHTMAP_ON
#pragma multi_compile_fog
#pragma vertex vertForward
#pragma fragment fragForward
#include "UnityStandardForwardNew.cginc"
ENDCG
}
// ------------------------------------------------------------------
// Shadow rendering pass
Pass {
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
ZWrite On ZTest LEqual
ZWrite On ZTest LEqual
CGPROGRAM
#pragma target 5.0
CGPROGRAM
#pragma target 5.0
// -------------------------------------
// -------------------------------------
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
#pragma shader_feature _METALLICGLOSSMAP
#pragma multi_compile_shadowcaster
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
#pragma shader_feature _METALLICGLOSSMAP
#pragma multi_compile_shadowcaster
#pragma vertex vertShadowCaster
#pragma fragment fragShadowCaster
#pragma vertex vertShadowCaster
#pragma fragment fragShadowCaster
#include "UnityStandardShadow.cginc"
#include "UnityStandardShadow.cginc"
ENDCG
}
// ------------------------------------------------------------------
// Deferred pass
ENDCG
}
// ------------------------------------------------------------------
// Deferred pass
}
}
FallBack "VertexLit"
CustomEditor "StandardShaderGUI"
FallBack "VertexLit"
CustomEditor "StandardShaderGUI"
}

14
Assets/ScriptableRenderLoop/fptl/TiledLightingTemplate.hlsl


float3 ExecuteLightListTiled(out uint numLightsProcessed, uint2 pixCoord, float3 vP, float3 vPw, float3 Vworld)
{
uint nrTilesX = (g_widthRT+15)/16; uint nrTilesY = (g_heightRT+15)/16;
uint2 tileIDX = pixCoord / 16;
uint nrTilesX = (g_widthRT+15)/16; uint nrTilesY = (g_heightRT+15)/16;
uint2 tileIDX = pixCoord / 16;
uint start = 0, numLights = 0;
GetCountAndStart(start, numLights, tileIDX, nrTilesX, nrTilesY, vP.z, DIRECT_LIGHT);
uint start = 0, numLights = 0;
GetCountAndStart(start, numLights, tileIDX, nrTilesX, nrTilesY, vP.z, DIRECT_LIGHT);
numLightsProcessed = numLights; // mainly for debugging/heat maps
return ExecuteLightList(start, numLights, vP, vPw, Vworld);
numLightsProcessed = numLights; // mainly for debugging/heat maps
return ExecuteLightList(start, numLights, vP, vPw, Vworld);
#endif
#endif

136
Assets/ScriptableRenderLoop/fptl/TiledLightingUtils.hlsl


#define __TILEDLIGHTINGUTILS_H__
#include "..\common\ShaderBase.h"
#include "LightDefinitions.cs.hlsl"
uniform float4x4 g_mViewToWorld;
uniform float4x4 g_mWorldToView; // used for reflection only
uniform float4x4 g_mScrProjection;
uniform float4x4 g_mInvScrProjection;
#include "LightingUtils.hlsl"
uniform uint g_widthRT;
uniform uint g_heightRT;
const int tileOffs = (tileIDX.y+model*nrTilesY)*nrTilesX+tileIDX.x;
const int tileOffs = (tileIDX.y+model*nrTilesY)*nrTilesX+tileIDX.x;
uNrLights = g_vLightListGlobal[ 16*tileOffs + 0]&0xffff;
uStart = tileOffs;
uNrLights = g_vLightListGlobal[ 16*tileOffs + 0]&0xffff;
uStart = tileOffs;
const uint l1 = l+1;
return (g_vLightListGlobal[ 16*tileOffs + (l1>>1)]>>((l1&1)*16))&0xffff;
const uint l1 = l+1;
return (g_vLightListGlobal[ 16*tileOffs + (l1>>1)]>>((l1&1)*16))&0xffff;
}
#ifdef OPAQUES_ONLY

GetCountAndStartOpaque(uStart, uNrLights, tileIDX, nrTilesX, nrTilesY, linDepth, model);
GetCountAndStartOpaque(uStart, uNrLights, tileIDX, nrTilesX, nrTilesY, linDepth, model);
return FetchIndexOpaque(tileOffs, l);
return FetchIndexOpaque(tileOffs, l);
}
#else

uniform float g_fNearPlane;
uniform float g_fFarPlane;
//uniform int g_iLog2NumClusters; // numClusters = (1<<g_iLog2NumClusters)
//uniform int g_iLog2NumClusters; // numClusters = (1<<g_iLog2NumClusters)
uniform int g_iLog2NumClusters;
#include "ClusteredUtils.h"

void GetCountAndStart(out uint uStart, out uint uNrLights, uint2 tileIDX, int nrTilesX, int nrTilesY, float linDepth, uint model)
{
if(g_isOpaquesOnlyEnabled)
{
GetCountAndStartOpaque(uStart, uNrLights, tileIDX, nrTilesX, nrTilesY, linDepth, model);
}
else
{
float logBase = g_fClustBase;
if(g_isLogBaseBufferEnabled)
logBase = g_logBaseBuffer[tileIDX.y*nrTilesX + tileIDX.x];
if(g_isOpaquesOnlyEnabled)
{
GetCountAndStartOpaque(uStart, uNrLights, tileIDX, nrTilesX, nrTilesY, linDepth, model);
}
else
{
float logBase = g_fClustBase;
if(g_isLogBaseBufferEnabled)
logBase = g_logBaseBuffer[tileIDX.y*nrTilesX + tileIDX.x];
int clustIdx = SnapToClusterIdxFlex(linDepth, logBase, g_isLogBaseBufferEnabled!=0);
int clustIdx = SnapToClusterIdxFlex(linDepth, logBase, g_isLogBaseBufferEnabled!=0);
int nrClusters = (1<<g_iLog2NumClusters);
const int idx = ((model*nrClusters + clustIdx)*nrTilesY + tileIDX.y)*nrTilesX + tileIDX.x;
uint dataPair = g_vLayeredOffsetsBuffer[idx];
uStart = dataPair&0x7ffffff;
uNrLights = (dataPair>>27)&31;
}
int nrClusters = (1<<g_iLog2NumClusters);
const int idx = ((model*nrClusters + clustIdx)*nrTilesY + tileIDX.y)*nrTilesX + tileIDX.x;
uint dataPair = g_vLayeredOffsetsBuffer[idx];
uStart = dataPair&0x7ffffff;
uNrLights = (dataPair>>27)&31;
}
if(g_isOpaquesOnlyEnabled)
return FetchIndexOpaque(tileOffs, l);
else
return g_vLightListGlobal[ tileOffs+l ];
if(g_isOpaquesOnlyEnabled)
return FetchIndexOpaque(tileOffs, l);
else
return g_vLightListGlobal[ tileOffs+l ];
float3 GetViewPosFromLinDepth(float2 v2ScrPos, float fLinDepth)
{
float fSx = g_mScrProjection[0].x;
//float fCx = g_mScrProjection[2].x;
float fCx = g_mScrProjection[0].z;
float fSy = g_mScrProjection[1].y;
//float fCy = g_mScrProjection[2].y;
float fCy = g_mScrProjection[1].z;
#ifdef LEFT_HAND_COORDINATES
return fLinDepth*float3( ((v2ScrPos.x-fCx)/fSx), ((v2ScrPos.y-fCy)/fSy), 1.0 );
#else
return fLinDepth*float3( -((v2ScrPos.x+fCx)/fSx), -((v2ScrPos.y+fCy)/fSy), 1.0 );
}
float GetLinearZFromSVPosW(float posW)
{
#ifdef LEFT_HAND_COORDINATES
float linZ = posW;
#else
float linZ = -posW;
#endif
return linZ;
}
float GetLinearDepth(float zDptBufSpace) // 0 is near 1 is far
{
float3 vP = float3(0.0f,0.0f,zDptBufSpace);
float4 v4Pres = mul(g_mInvScrProjection, float4(vP,1.0));
return v4Pres.z / v4Pres.w;
}
float3 OverlayHeatMap(uint numLights, float3 c)
{
/////////////////////////////////////////////////////////////////////
//
const float4 kRadarColors[12] =
{
float4(0.0,0.0,0.0,0.0), // black
float4(0.0,0.0,0.6,0.5), // dark blue
float4(0.0,0.0,0.9,0.5), // blue
float4(0.0,0.6,0.9,0.5), // light blue
float4(0.0,0.9,0.9,0.5), // cyan
float4(0.0,0.9,0.6,0.5), // blueish green
float4(0.0,0.9,0.0,0.5), // green
float4(0.6,0.9,0.0,0.5), // yellowish green
float4(0.9,0.9,0.0,0.5), // yellow
float4(0.9,0.6,0.0,0.5), // orange
float4(0.9,0.0,0.0,0.5), // red
float4(1.0,0.0,0.0,0.9) // strong red
};
float maxNrLightsPerTile = 31;
int nColorIndex = numLights==0 ? 0 : (1 + (int) floor(10 * (log2((float)numLights) / log2(maxNrLightsPerTile))) );
nColorIndex = nColorIndex<0 ? 0 : nColorIndex;
float4 col = nColorIndex>11 ? float4(1.0,1.0,1.0,1.0) : kRadarColors[nColorIndex];
return lerp(c, pow(col.xyz, 2.2), 0.3*col.w);
}
#endif

14
Assets/ScriptableRenderLoop/fptl/TiledReflectionTemplate.hlsl


float3 ExecuteReflectionListTiled(out uint numReflectionProbesProcessed, uint2 pixCoord, float3 vP, float3 vNw, float3 Vworld, float smoothness)
{
uint nrTilesX = (g_widthRT+15)/16; uint nrTilesY = (g_heightRT+15)/16;
uint2 tileIDX = pixCoord / 16;
uint nrTilesX = (g_widthRT+15)/16; uint nrTilesY = (g_heightRT+15)/16;
uint2 tileIDX = pixCoord / 16;
uint start = 0, numReflectionProbes = 0;
GetCountAndStart(start, numReflectionProbes, tileIDX, nrTilesX, nrTilesY, vP.z, REFLECTION_LIGHT);
uint start = 0, numReflectionProbes = 0;
GetCountAndStart(start, numReflectionProbes, tileIDX, nrTilesX, nrTilesY, vP.z, REFLECTION_LIGHT);
numReflectionProbesProcessed = numReflectionProbes; // mainly for debugging/heat maps
return ExecuteReflectionList(start, numReflectionProbes, vP, vNw, Vworld, smoothness);
numReflectionProbesProcessed = numReflectionProbes; // mainly for debugging/heat maps
return ExecuteReflectionList(start, numReflectionProbes, vP, vNw, Vworld, smoothness);
#endif
#endif

130
Assets/ScriptableRenderLoop/fptl/UnityStandardForwardNew.cginc


struct VertexOutputForwardNew
{
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
half4 ambientOrLightmapUV : TEXCOORD1; // SH or Lightmap UV
half4 tangentToWorldAndParallax[3] : TEXCOORD2; // [3x3:tangentToWorld | 1x3:empty]
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
half4 ambientOrLightmapUV : TEXCOORD1; // SH or Lightmap UV
half4 tangentToWorldAndParallax[3] : TEXCOORD2; // [3x3:tangentToWorld | 1x3:empty]
LIGHTING_COORDS(5,6)
UNITY_FOG_COORDS(7)
LIGHTING_COORDS(5,6)
UNITY_FOG_COORDS(7)
UNITY_VERTEX_OUTPUT_STEREO
UNITY_VERTEX_OUTPUT_STEREO
VertexOutputForwardNew vertForward(VertexInput v)
{
UNITY_SETUP_INSTANCE_ID(v);
VertexOutputForwardNew o;
UNITY_INITIALIZE_OUTPUT(VertexOutputForwardNew, o);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
VertexOutputForwardNew vertForward(VertexInput v)
{
UNITY_SETUP_INSTANCE_ID(v);
VertexOutputForwardNew o;
UNITY_INITIALIZE_OUTPUT(VertexOutputForwardNew, o);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
float4 posWorld = mul(unity_ObjectToWorld, v.vertex);
o.pos = UnityObjectToClipPos(v.vertex);
float4 posWorld = mul(unity_ObjectToWorld, v.vertex);
o.pos = UnityObjectToClipPos(v.vertex);
o.tex = TexCoords(v);
float3 normalWorld = UnityObjectToWorldNormal(v.normal);
#ifdef _TANGENT_TO_WORLD
float4 tangentWorld = float4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w);
o.tex = TexCoords(v);
float3 normalWorld = UnityObjectToWorldNormal(v.normal);
#ifdef _TANGENT_TO_WORLD
float4 tangentWorld = float4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w);
float3x3 tangentToWorld = CreateTangentToWorldPerVertex(normalWorld, tangentWorld.xyz, tangentWorld.w);
o.tangentToWorldAndParallax[0].xyz = tangentToWorld[0];
o.tangentToWorldAndParallax[1].xyz = tangentToWorld[1];
o.tangentToWorldAndParallax[2].xyz = tangentToWorld[2];
#else
o.tangentToWorldAndParallax[0].xyz = 0;
o.tangentToWorldAndParallax[1].xyz = 0;
o.tangentToWorldAndParallax[2].xyz = normalWorld;
#endif
float3x3 tangentToWorld = CreateTangentToWorldPerVertex(normalWorld, tangentWorld.xyz, tangentWorld.w);
o.tangentToWorldAndParallax[0].xyz = tangentToWorld[0];
o.tangentToWorldAndParallax[1].xyz = tangentToWorld[1];
o.tangentToWorldAndParallax[2].xyz = tangentToWorld[2];
#else
o.tangentToWorldAndParallax[0].xyz = 0;
o.tangentToWorldAndParallax[1].xyz = 0;
o.tangentToWorldAndParallax[2].xyz = normalWorld;
#endif
o.ambientOrLightmapUV = VertexGIForward(v, posWorld, normalWorld);
UNITY_TRANSFER_FOG(o,o.pos);
o.ambientOrLightmapUV = VertexGIForward(v, posWorld, normalWorld);
return o;
UNITY_TRANSFER_FOG(o,o.pos);
return o;
}

float3 EvalMaterial(UnityLight light, UnityIndirect ind)
{
return UNITY_BRDF_PBS(gdata.diffColor, gdata.specColor, gdata.oneMinusReflectivity, gdata.smoothness, gdata.normalWorld, -gdata.eyeVec, light, ind);
return UNITY_BRDF_PBS(gdata.diffColor, gdata.specColor, gdata.oneMinusReflectivity, gdata.smoothness, gdata.normalWorld, -gdata.eyeVec, light, ind);
float occlusion = 1.0; // have none for now
return occlusion * UNITY_BRDF_PBS(gdata.diffColor, gdata.specColor, gdata.oneMinusReflectivity, gdata.smoothness, gdata.normalWorld, -gdata.eyeVec, light, ind);
float occlusion = 1.0; // have none for now
return occlusion * UNITY_BRDF_PBS(gdata.diffColor, gdata.specColor, gdata.oneMinusReflectivity, gdata.smoothness, gdata.normalWorld, -gdata.eyeVec, light, ind);
}

half4 fragForward(VertexOutputForwardNew i) : SV_Target
{
float linZ = GetLinearZFromSVPosW(i.pos.w); // matching script side where camera space is right handed.
float3 vP = GetViewPosFromLinDepth(i.pos.xy, linZ);
float3 vPw = mul(g_mViewToWorld, float4(vP,1.0)).xyz;
float3 Vworld = normalize(mul((float3x3) g_mViewToWorld, -vP).xyz); // not same as unity_CameraToWorld
half4 fragForward(VertexOutputForwardNew i) : SV_Target
{
float linZ = GetLinearZFromSVPosW(i.pos.w); // matching script side where camera space is right handed.
float3 vP = GetViewPosFromLinDepth(i.pos.xy, linZ);
float3 vPw = mul(g_mViewToWorld, float4(vP,1.0)).xyz;
float3 Vworld = normalize(mul((float3x3) g_mViewToWorld, -vP).xyz); // not same as unity_CameraToWorld
half3 tangent = i.tangentToWorldAndParallax[0].xyz;
half3 bitangent = i.tangentToWorldAndParallax[1].xyz;
half3 normal = i.tangentToWorldAndParallax[2].xyz;
float3 vDirForParallax = float3( dot(tangent, Vworld), dot(bitangent, Vworld), dot(normal, Vworld));
half3 tangent = i.tangentToWorldAndParallax[0].xyz;
half3 bitangent = i.tangentToWorldAndParallax[1].xyz;
half3 normal = i.tangentToWorldAndParallax[2].xyz;
float3 vDirForParallax = float3( dot(tangent, Vworld), dot(bitangent, Vworld), dot(normal, Vworld));
float3 vDirForParallax = Vworld;
float3 vDirForParallax = Vworld;
gdata = FragmentSetup(i.tex, -Vworld, vDirForParallax, i.tangentToWorldAndParallax, vPw); // eyeVec = -Vworld
gdata = FragmentSetup(i.tex, -Vworld, vDirForParallax, i.tangentToWorldAndParallax, vPw); // eyeVec = -Vworld
uint2 pixCoord = ((uint2) i.pos.xy);
uint2 pixCoord = ((uint2) i.pos.xy);
//float atten = 0.0;
//half occlusion = Occlusion(i.tex.xy);
//UnityGI gi = FragmentGI (gdata, occlusion, i.ambientOrLightmapUV, atten, mainLight);
//float atten = 0.0;
//half occlusion = Occlusion(i.tex.xy);
//UnityGI gi = FragmentGI (gdata, occlusion, i.ambientOrLightmapUV, atten, mainLight);
uint numLightsProcessed = 0, numReflectionsProcessed = 0;
float3 res = 0;
res += ExecuteLightListTiled(numLightsProcessed, pixCoord, vP, vPw, Vworld);
res += ExecuteReflectionListTiled(numReflectionsProcessed, pixCoord, vP, gdata.normalWorld, Vworld, gdata.smoothness);
uint numLightsProcessed = 0, numReflectionsProcessed = 0;
float3 res = 0;
res += ExecuteLightListTiled(numLightsProcessed, pixCoord, vP, vPw, Vworld);
res += ExecuteReflectionListTiled(numReflectionsProcessed, pixCoord, vP, gdata.normalWorld, Vworld, gdata.smoothness);
// don't really have a handle on this yet
//UnityLight mainLight = MainLight ();
//res += UNITY_BRDF_GI (gdata.diffColor, gdata.specColor, gdata.oneMinusReflectivity, gdata.smoothness, gdata.normalWorld, -gdata.eyeVec, occlusion, gi);
res += Emission(i.tex.xy);
// don't really have a handle on this yet
//UnityLight mainLight = MainLight ();
//res += UNITY_BRDF_GI (gdata.diffColor, gdata.specColor, gdata.oneMinusReflectivity, gdata.smoothness, gdata.normalWorld, -gdata.eyeVec, occlusion, gi);
res += Emission(i.tex.xy);
//res = OverlayHeatMap(numLightsProcessed, res);
//res = OverlayHeatMap(numLightsProcessed, res);
//UNITY_APPLY_FOG(i.fogCoord, res);
return OutputForward (float4(res,1.0), gdata.alpha);
//UNITY_APPLY_FOG(i.fogCoord, res);
return OutputForward (float4(res,1.0), gdata.alpha);
}
#endif // UNITY_STANDARD_SHADOW_INCLUDED

2
Assets/ScriptableRenderLoop/fptl/lightlistbuild-clustered.compute


float c = dot(vCen,vCen) - fRad*fRad;
float fDescDivFour = CdotV*CdotV - a*c;
if(!(c<0 || (fDescDivFour>0 && CdotV>0))) // if ray hit bounding sphere
if(!(c<0 || (fDescDivFour>0 && CdotV>0))) // if ray misses bounding sphere
coarseList[l]=0xffffffff;
}

97
Assets/ScriptableRenderLoop/fptl/lightlistbuild.compute


#include "LightDefinitions.cs.hlsl"
#define FINE_PRUNING_ENABLED
#define PERFORM_SPHERICAL_INTERSECTION_TESTS
uniform int g_iNrVisibLights;

Texture2D g_depth_tex : register( t0 );
StructuredBuffer<float3> g_vBoundsBuffer : register( t1 );
StructuredBuffer<SFiniteLightData> g_vLightData : register( t2 );
StructuredBuffer<SFiniteLightBound> g_data : register( t3 );
#define NR_THREADS 64

groupshared int ldsModelListCount[NR_LIGHT_MODELS]; // since NR_LIGHT_MODELS is 2
#ifdef PERFORM_SPHERICAL_INTERSECTION_TESTS
groupshared uint lightOffsSph;
#endif
//float GetLinearDepth(float3 vP)
//{

#endif
}
float GetOnePixDiagWorldDistAtDepthOne()
{
float fSx = g_mScrProjection[0].x;
float fSy = g_mScrProjection[1].y;
return length( float2(1.0/fSx,1.0/fSy) );
}
#ifdef PERFORM_SPHERICAL_INTERSECTION_TESTS
int SphericalIntersectionTests(uint threadID, int iNrCoarseLights, float2 screenCoordinate);
#endif
[numthreads(NR_THREADS, 1, 1)]

int iNrCoarseLights = lightOffs<MAX_NR_COARSE_ENTRIES ? lightOffs : MAX_NR_COARSE_ENTRIES;
#ifdef PERFORM_SPHERICAL_INTERSECTION_TESTS
iNrCoarseLights = SphericalIntersectionTests( t, iNrCoarseLights, float2(min(viTilLL.xy+uint2(16/2,16/2), uint2(iWidth-1, iHeight-1))) );
#endif
#ifndef FINE_PRUNING_ENABLED
{

uint uLightsFlags[2] = {0,0};
int l=0;
// we need this outer loop for when we cannot assume a wavefront is 64 wide
// since in this case we cannot assume the lights will remain sorted by type
#if !defined(XBONE) && !defined(PLAYSTATION4)
// need this outer loop even on xb1 and ps4 since direct lights and
// reflection lights are kept in separate regions.
#endif
{
// fetch light
int idxCoarse = l<iNrCoarseLights ? coarseList[l] : 0;

uLgtType = l<iNrCoarseLights ? g_vLightData[idxCoarse].uLightType : 0;
}
#if !defined(XBONE) && !defined(PLAYSTATION4)
#endif
}
InterlockedOr(ldsDoesLightIntersect[0], uLightsFlags[0]);

}
}
#endif
#ifdef PERFORM_SPHERICAL_INTERSECTION_TESTS
int SphericalIntersectionTests(uint threadID, int iNrCoarseLights, float2 screenCoordinate)
{
lightOffsSph = 0;
// make a copy of coarseList in prunedList.
for(int l=threadID; l<iNrCoarseLights; l+=NR_THREADS)
prunedList[l]=coarseList[l];
#if !defined(XBONE) && !defined(PLAYSTATION4)
GroupMemoryBarrierWithGroupSync();
#endif
#ifdef LEFT_HAND_COORDINATES
float3 V = GetViewPosFromLinDepth( screenCoordinate, 1.0);
#else
float3 V = GetViewPosFromLinDepth( screenCoordinate, -1.0);
#endif
float onePixDiagDist = GetOnePixDiagWorldDistAtDepthOne();
float worldDistAtDepthOne = 8*onePixDiagDist; // scale by half a tile
int iNrVisib = 0;
for(int l=threadID; l<iNrCoarseLights; l+=NR_THREADS)
{
SFiniteLightBound lgtDat = g_data[coarseList[l]];
const float3 vCen = lgtDat.vCen.xyz;
float fRad = lgtDat.fRadius;
#if 1
float3 maxZdir = float3(-vCen.z*vCen.x, -vCen.z*vCen.y, vCen.x*vCen.x + vCen.y*vCen.y); // cross(vCen,cross(Zaxis,vCen))
float len = length(maxZdir);
float scalarProj = len>0.0001 ? (maxZdir.z/len) : len; // since len>=(maxZdir.z/len) we can use len as an approximate value when len<=epsilon
float fOffs = scalarProj*fRad;
#else
float fOffs = fRad; // more false positives due to larger radius but works too
#endif
#ifdef LEFT_HAND_COORDINATES
fRad = fRad + (vCen.z+fOffs)*worldDistAtDepthOne;
#else
fRad = fRad + (vCen.z-fOffs)*worldDistAtDepthOne;
#endif
float a = dot(V,V);
float CdotV = dot(vCen,V);
float c = dot(vCen,vCen) - fRad*fRad;
float fDescDivFour = CdotV*CdotV - a*c;
if(c<0 || (fDescDivFour>0 && CdotV>0)) // if ray hit bounding sphere
{
unsigned int uIndex;
InterlockedAdd(lightOffsSph, 1, uIndex);
coarseList[uIndex]=prunedList[l]; // read from the original copy of coarseList which is backed up in prunedList
}
}
#if !defined(XBONE) && !defined(PLAYSTATION4)
GroupMemoryBarrierWithGroupSync();
#endif
return lightOffsSph;
}
#endif

17
Assets/ShaderGenerator/CSharpToHLSL.cs


}
// Now that we have extracted all the typenames that we care about, parse all .cs files in all asset
// Now that we have extracted all the typenames that we care about, parse all .cs files in all asset
// paths and figure out in which files those types are actually declared.
m_sourceGenerators = new Dictionary<string, List<ShaderTypeGenerator>>();

// Error reporting will be done by the generator. Skip this file.
gen.PrintErrors();
skipFile = true;
break; ;
break;
}
}

// @TODO any standard preprocessor symbols we need?
/*var uniqueSymbols = new HashSet<string>(definedSymbols.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries));
foreach (var symbol in uniqueSymbols)
{
parser.Lexer.ConditionalCompilationSymbols.Add(symbol, string.Empty);
}*/
foreach (var symbol in uniqueSymbols)
{
parser.Lexer.ConditionalCompilationSymbols.Add(symbol, string.Empty);
}*/
parser.Lexer.EvaluateConditionalCompilation = true;
parser.Parse();

if (data.generators.Count > 0)
m_sourceGenerators[fileName] = data.generators;
}
catch
{

// Skip assemblies from GAC (@TODO: any reason we'd want to include them?)
var keysToRemove = assemblies.Values.Where(
o => o.GlobalAssemblyCache == true).ToList();
o => o.GlobalAssemblyCache == true).ToList();
foreach (var k in keysToRemove)
{

static Dictionary<string, Assembly> assemblies;
}
};
}

2
Assets/ShaderGenerator/ShaderGeneratorMenu.cs


using System;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;

1
Assets/ShaderGenerator/ShaderTypeGeneration.cs


packed = false;
accessor = new Accessor(type, name, rows, cols);
}
public ShaderFieldInfo(PrimitiveType type, string name, int rows, int cols, string comment)
{
this.type = type;

88
Assets/ScriptableRenderLoop/fptl/LightingUtils.hlsl


#ifndef __LIGHTINGUTILS_H__
#define __LIGHTINGUTILS_H__
#include "..\common\ShaderBase.h"
#include "LightDefinitions.cs.hlsl"
uniform float4x4 g_mViewToWorld;
uniform float4x4 g_mWorldToView; // used for reflection only
uniform float4x4 g_mScrProjection;
uniform float4x4 g_mInvScrProjection;
uniform uint g_widthRT;
uniform uint g_heightRT;
float3 GetViewPosFromLinDepth(float2 v2ScrPos, float fLinDepth)
{
float fSx = g_mScrProjection[0].x;
//float fCx = g_mScrProjection[2].x;
float fCx = g_mScrProjection[0].z;
float fSy = g_mScrProjection[1].y;
//float fCy = g_mScrProjection[2].y;
float fCy = g_mScrProjection[1].z;
#ifdef LEFT_HAND_COORDINATES
return fLinDepth*float3( ((v2ScrPos.x-fCx)/fSx), ((v2ScrPos.y-fCy)/fSy), 1.0 );
#else
return fLinDepth*float3( -((v2ScrPos.x+fCx)/fSx), -((v2ScrPos.y+fCy)/fSy), 1.0 );
#endif
}
float GetLinearZFromSVPosW(float posW)
{
#ifdef LEFT_HAND_COORDINATES
float linZ = posW;
#else
float linZ = -posW;
#endif
return linZ;
}
float GetLinearDepth(float zDptBufSpace) // 0 is near 1 is far
{
float3 vP = float3(0.0f,0.0f,zDptBufSpace);
float4 v4Pres = mul(g_mInvScrProjection, float4(vP,1.0));
return v4Pres.z / v4Pres.w;
}
float3 OverlayHeatMap(uint numLights, float3 c)
{
/////////////////////////////////////////////////////////////////////
//
const float4 kRadarColors[12] =
{
float4(0.0,0.0,0.0,0.0), // black
float4(0.0,0.0,0.6,0.5), // dark blue
float4(0.0,0.0,0.9,0.5), // blue
float4(0.0,0.6,0.9,0.5), // light blue
float4(0.0,0.9,0.9,0.5), // cyan
float4(0.0,0.9,0.6,0.5), // blueish green
float4(0.0,0.9,0.0,0.5), // green
float4(0.6,0.9,0.0,0.5), // yellowish green
float4(0.9,0.9,0.0,0.5), // yellow
float4(0.9,0.6,0.0,0.5), // orange
float4(0.9,0.0,0.0,0.5), // red
float4(1.0,0.0,0.0,0.9) // strong red
};
float maxNrLightsPerTile = 31;
int nColorIndex = numLights==0 ? 0 : (1 + (int) floor(10 * (log2((float)numLights) / log2(maxNrLightsPerTile))) );
nColorIndex = nColorIndex<0 ? 0 : nColorIndex;
float4 col = nColorIndex>11 ? float4(1.0,1.0,1.0,1.0) : kRadarColors[nColorIndex];
return lerp(c, pow(col.xyz, 2.2), 0.3*col.w);
}
#endif
正在加载...
取消
保存