Evgenii Golubev 8 年前
当前提交
478a2e31
共有 48 个文件被更改,包括 1961 次插入267 次删除
  1. 8
      Assets/ScriptableRenderLoop/HDRenderPipeline/Editor/HDRenderPipelineInspector.cs
  2. 18
      Assets/ScriptableRenderLoop/HDRenderPipeline/Editor/HDRenderPipelineMenuItems.cs
  3. 52
      Assets/ScriptableRenderLoop/HDRenderPipeline/HDRenderPipeline.cs
  4. 27
      Assets/ScriptableRenderLoop/HDRenderPipeline/Lighting/TilePass/TilePass.cs
  5. 32
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/LayeredLit/Editor/LayeredLitUI.cs
  6. 17
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/LayeredLit/LayeredLit.shader
  7. 2
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Editor/BaseLitUI.cs
  8. 2
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Editor/LitUI.cs
  9. 13
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Lit.shader
  10. 68
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitData.hlsl
  11. 3
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitProperties.hlsl
  12. 2
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitSharePass.hlsl
  13. 31
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitSurfaceData.hlsl
  14. 2
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Unlit/Editor/BaseUnlitUI.cs
  15. 2
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Unlit/Editor/UnlitUI.cs
  16. 10
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Unlit/Unlit.shader
  17. 2
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Unlit/UnlitSharePass.hlsl
  18. 207
      Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Resources/FinalPass.shader
  19. 15
      Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderVariables.hlsl
  20. 15
      Assets/ScriptableRenderLoop/ShaderLibrary/CommonMaterial.hlsl
  21. 2
      Assets/TestScenes/HDTest/LayeredLitTest.unity
  22. 35
      Assets/TestScenes/HDTest/LayeredLitTest/Material/Layered_HeightBased.mat
  23. 11
      Assets/TestScenes/HDTest/LayeredLitTest/Material/Lit_White.mat
  24. 9
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Tesselation.meta
  25. 9
      Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Editor.meta
  26. 257
      Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/PostProcessing.cs
  27. 12
      Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/PostProcessing.cs.meta
  28. 77
      Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Resources/ColorGrading.hlsl
  29. 9
      Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Resources/ColorGrading.hlsl.meta
  30. 22
      Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Resources/EyeAdaptation.hlsl
  31. 9
      Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Resources/EyeAdaptation.hlsl.meta
  32. 236
      Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Resources/EyeAdaptation.shader
  33. 9
      Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Resources/EyeAdaptation.shader.meta
  34. 59
      Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Resources/EyeHistogram.compute
  35. 9
      Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Resources/EyeHistogram.compute.meta
  36. 68
      Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Resources/LutGen.shader
  37. 9
      Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Resources/LutGen.shader.meta
  38. 0
      Assets/ScriptableRenderLoop/ShaderLibrary/Tesselation.hlsl
  39. 9
      Assets/ScriptableRenderLoop/ShaderLibrary/Tesselation.hlsl.meta
  40. 9
      Assets/TestScenes/HDTest/HDRI.meta
  41. 422
      Assets/Textures/CoolingFilterLUT.exr
  42. 108
      Assets/Textures/CoolingFilterLUT.exr.meta
  43. 0
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Tesselation/ShareTesselation.hlsl
  44. 9
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Tesselation/ShareTesselation.hlsl.meta
  45. 289
      Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Editor/PostProcessingEditor.cs
  46. 12
      Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Editor/PostProcessingEditor.cs.meta

8
Assets/ScriptableRenderLoop/HDRenderPipeline/Editor/HDRenderPipelineInspector.cs


public readonly GUIContent displayOpaqueObjects = new GUIContent("Display Opaque Objects", "Toggle opaque objects rendering on and off.");
public readonly GUIContent displayTransparentObjects = new GUIContent("Display Transparent Objects", "Toggle transparent objects rendering on and off.");
public readonly GUIContent enableTonemap = new GUIContent("Enable Tonemap");
public readonly GUIContent exposure = new GUIContent("Exposure");
public readonly GUIContent useForwardRenderingOnly = new GUIContent("Use Forward Rendering Only");
public readonly GUIContent useDepthPrepass = new GUIContent("Use Depth Prepass");

debugParameters.debugViewMaterial = EditorGUILayout.IntPopup(styles.debugViewMaterial, (int)debugParameters.debugViewMaterial, styles.debugViewMaterialStrings, styles.debugViewMaterialValues);
EditorGUILayout.Space();
debugParameters.enableTonemap = EditorGUILayout.Toggle(styles.enableTonemap, debugParameters.enableTonemap);
debugParameters.exposure = Mathf.Max(Mathf.Min(EditorGUILayout.FloatField(styles.exposure, debugParameters.exposure), k_MaxExposure), -k_MaxExposure);
EditorGUILayout.Space();
if (EditorGUI.EndChangeCheck())
{
EditorUtility.SetDirty(renderContext); // Repaint

18
Assets/ScriptableRenderLoop/HDRenderPipeline/Editor/HDRenderPipelineMenuItems.cs


using System.Collections;
using System.Collections.Generic;
using UnityEditor;
namespace UnityEditor.Experimental.ScriptableRenderLoop
namespace UnityEditor.Experimental.Rendering.HDPipeline
[UnityEditor.MenuItem("HDRenderPipeline/Create Scene Settings")]
[MenuItem("HDRenderPipeline/Create Scene Settings")]
CommonSettings[] settings = Object.FindObjectsOfType(typeof(CommonSettings)) as CommonSettings[];
CommonSettings[] settings = Object.FindObjectsOfType<CommonSettings>();
GameObject go = new GameObject();
go.name = "SceneSettings";
go.AddComponent(typeof(CommonSettings));
GameObject go = new GameObject { name = "SceneSettings" };
go.AddComponent<CommonSettings>();
go.AddComponent<PostProcessing>();
}
else
{

[UnityEditor.MenuItem("HDRenderPipeline/Synchronize all Layered materials")]
[MenuItem("HDRenderPipeline/Synchronize all Layered materials")]
static void SynchronizeAllLayeredMaterial()
{
Object[] materials = Resources.FindObjectsOfTypeAll<Material>();

52
Assets/ScriptableRenderLoop/HDRenderPipeline/HDRenderPipeline.cs


public bool useForwardRenderingOnly = false; // TODO: Currently there is no way to strip the extra forward shaders generated by the shaders compiler, so we can switch dynamically.
public bool useDepthPrepass = false;
public bool useDistortion = true;
public bool enableTonemap = true;
public float exposure = 0;
}
DebugParameters m_DebugParameters = new DebugParameters();

}
// Various set of material use in render loop
Material m_FinalPassMaterial;
Material m_DebugViewMaterialGBuffer;
// Various buffer

m_SkyManager.Build();
m_FinalPassMaterial = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/FinalPass");
m_DebugViewMaterialGBuffer = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/DebugViewMaterialGBuffer");
m_ShadowPass = new ShadowRenderPass(m_ShadowSettings);

m_lightLoop.Cleanup();
m_LitRenderLoop.Cleanup();
Utilities.Destroy(m_FinalPassMaterial);
Utilities.Destroy(m_DebugViewMaterialGBuffer);
m_SkyManager.Cleanup();

}
}
void FinalPass(ScriptableRenderContext renderContext)
void FinalPass(Camera camera, ScriptableRenderContext renderContext)
// Those could be tweakable for the neutral tonemapper, but in the case of the LookDev we don't need that
const float blackIn = 0.02f;
const float whiteIn = 10.0f;
const float blackOut = 0.0f;
const float whiteOut = 10.0f;
const float whiteLevel = 5.3f;
const float whiteClip = 10.0f;
const float dialUnits = 20.0f;
const float halfDialUnits = dialUnits * 0.5f;
// converting from artist dial units to easy shader-lerps (0-1)
var tonemapCoeff1 = new Vector4((blackIn * dialUnits) + 1.0f, (blackOut * halfDialUnits) + 1.0f, (whiteIn / dialUnits), (1.0f - (whiteOut / dialUnits)));
var tonemapCoeff2 = new Vector4(0.0f, 0.0f, whiteLevel, whiteClip / halfDialUnits);
// All of this is temporary, sub-optimal and quickly hacked together but is necessary
// for artists to do lighting work until the fully-featured framework is ready
m_FinalPassMaterial.SetVector("_ToneMapCoeffs1", tonemapCoeff1);
m_FinalPassMaterial.SetVector("_ToneMapCoeffs2", tonemapCoeff2);
var localPostProcess = camera.GetComponent<PostProcessing>();
var globalPostProcess = commonSettings == null
? null
: commonSettings.GetComponent<PostProcessing>();
m_FinalPassMaterial.SetFloat("_EnableToneMap", debugParameters.enableTonemap ? 1.0f : 0.0f);
m_FinalPassMaterial.SetFloat("_Exposure", debugParameters.exposure);
bool localActive = localPostProcess != null && localPostProcess.enabled;
bool globalActive = globalPostProcess != null && globalPostProcess.enabled;
var cmd = new CommandBuffer { name = "" };
if (!localActive && !globalActive)
{
var cmd = new CommandBuffer { name = "" };
cmd.Blit(m_CameraColorBufferRT, BuiltinRenderTextureType.CameraTarget);
renderContext.ExecuteCommandBuffer(cmd);
cmd.Dispose();
return;
}
// Resolve our HDR texture to CameraTarget.
cmd.Blit(m_CameraColorBufferRT, BuiltinRenderTextureType.CameraTarget, m_FinalPassMaterial, 0);
renderContext.ExecuteCommandBuffer(cmd);
cmd.Dispose();
var target = localActive ? localPostProcess : globalPostProcess;
target.Render(camera, renderContext, m_CameraColorBufferRT, BuiltinRenderTextureType.CameraTarget);
}
}

// Instead we chose to apply distortion at the end after we cumulate distortion vector and desired blurriness. This
RenderDistortion(cullResults, camera, renderContext);
FinalPass(renderContext);
FinalPass(camera, renderContext);
}
// bind depth surface for editor grid/gizmo/selection rendering

renderContext.Submit();
}
// Post effects
}
}
}

27
Assets/ScriptableRenderLoop/HDRenderPipeline/Lighting/TilePass/TilePass.cs


{
m_lightList.Clear();
if (cullResults.visibleLights.Length == 0)
if (cullResults.visibleLights.Length == 0 && cullResults.visibleReflectionProbes.Length == 0)
return;
// 1. Count the number of lights and sort all light by category, type and volume

cmd.SetComputeTextureParam(shadeOpaqueShader, kernel, "uavOutput", cameraColorBufferRT);
cmd.DispatchCompute(shadeOpaqueShader, kernel, numTilesX, numTilesY, 1);
}
else
{
// Pixel shader evaluation
if (enableSplitLightEvaluation)
}
else
// Pixel shader evaluation
if (enableSplitLightEvaluation)
{
Utilities.SetupMaterialHDCamera(hdCamera, m_DeferredDirectMaterial);
m_DeferredDirectMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
m_DeferredDirectMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);

m_DeferredIndirectMaterial.EnableKeyword(bUseClusteredForDeferred ? "USE_CLUSTERED_LIGHTLIST" : "USE_FPTL_LIGHTLIST");
m_DeferredIndirectMaterial.DisableKeyword(!bUseClusteredForDeferred ? "USE_CLUSTERED_LIGHTLIST" : "USE_FPTL_LIGHTLIST");
cmd.Blit(null, cameraColorBufferRT, m_DeferredDirectMaterial, 0);
cmd.Blit(null, cameraColorBufferRT, m_DeferredIndirectMaterial, 0);
}
else
{
cmd.Blit(null, cameraColorBufferRT, m_DeferredDirectMaterial, 0);
cmd.Blit(null, cameraColorBufferRT, m_DeferredIndirectMaterial, 0);
}
else
{
Utilities.SetupMaterialHDCamera(hdCamera, m_DeferredAllMaterial);
m_DeferredAllMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
m_DeferredAllMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);

cmd.Blit(null, cameraColorBufferRT, m_DeferredAllMaterial, 0);
}
cmd.Blit(null, cameraColorBufferRT, m_DeferredAllMaterial, 0);
}
}
// Draw tile debugging

}
SetGlobalPropertyRedirect(null, 0, null);
//}
renderContext.ExecuteCommandBuffer(cmd);
cmd.Dispose();

32
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/LayeredLit/Editor/LayeredLitUI.cs


using System.Linq;
namespace UnityEditor.Experimental.ScriptableRenderLoop
namespace UnityEditor.Experimental.Rendering.HDPipeline
{
internal class LayeredLitGUI : LitGUI
{

{
public readonly GUIContent[] layerLabels =
{
new GUIContent("Layer 0"),
new GUIContent("Base Layer"),
};
public readonly GUIStyle[] layerLabelColors =
{
new GUIStyle(EditorStyles.label),
new GUIStyle(EditorStyles.label),
new GUIStyle(EditorStyles.label),
new GUIStyle(EditorStyles.label)
};
public readonly GUIContent materialLayerText = new GUIContent("Material");

public readonly GUIContent UVBaseText = new GUIContent("Base UV Mapping", "Base UV Mapping mode of the layer.");
public readonly GUIContent UVDetailText = new GUIContent("Detail UV Mapping", "Detail UV Mapping mode of the layer.");
public readonly GUIContent useHeightBasedBlendText = new GUIContent("Use Height Based Blend", "Layer will be blended with the underlying layer based on the height.");
public readonly GUIContent heightOffsetText = new GUIContent("HeightOffset", "Height offset from the previous layer.");
public readonly GUIContent heightOffsetText = new GUIContent("Height Offset", "Height offset from the previous layer.");
public readonly GUIContent inheritBaseLayerText = new GUIContent("Inherit Base Layer Normal", "Inherit the normal from the base layer.");
public StylesLayer()
{
layerLabelColors[1].normal.textColor = Color.red;
layerLabelColors[2].normal.textColor = Color.green;
layerLabelColors[3].normal.textColor = Color.blue;
}
}
static StylesLayer s_Styles = null;

MaterialProperty useHeightBasedBlend = null;
const string kHeightOffset = "_HeightOffset";
MaterialProperty[] heightOffset = new MaterialProperty[kMaxLayerCount-1];
const string kInheritBaseLayer = "_InheritBaseLayer";
MaterialProperty[] inheritBaseLayer = new MaterialProperty[kMaxLayerCount - 1];
const string kHeightFactor = "_HeightFactor";
MaterialProperty[] heightFactor = new MaterialProperty[kMaxLayerCount-1];
const string kBlendSize = "_BlendSize";

if(i != 0)
{
inheritBaseLayer[i - 1] = FindProperty(string.Format("{0}{1}", kInheritBaseLayer, i), props);
heightOffset[i-1] = FindProperty(string.Format("{0}{1}", kHeightOffset, i), props);
heightFactor[i-1] = FindProperty(string.Format("{0}{1}", kHeightFactor, i), props);
blendSize[i-1] = FindProperty(string.Format("{0}{1}", kBlendSize, i), props);

Material material = m_MaterialEditor.target as Material;
EditorGUILayout.LabelField(styles.layerLabels[layerIndex]);
EditorGUILayout.LabelField(styles.layerLabels[layerIndex], styles.layerLabelColors[layerIndex]);
EditorGUI.indentLevel++;

{
int heightParamIndex = layerIndex - 1;
m_MaterialEditor.ShaderProperty(inheritBaseLayer[heightParamIndex], styles.inheritBaseLayerText);
m_MaterialEditor.ShaderProperty(heightOffset[heightParamIndex], styles.heightOffsetText);
m_MaterialEditor.ShaderProperty(heightFactor[heightParamIndex], styles.heightFactorText);
m_MaterialEditor.ShaderProperty(blendSize[heightParamIndex], styles.blendSizeText);

EditorGUI.indentLevel--;
if(layerIndex == 0)
EditorGUILayout.Space();
return result;
}

17
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/LayeredLit/LayeredLit.shader


_BlendSize2("_BlendSize2", Range(0, 0.05)) = 0.0
_BlendSize3("_BlendSize3", Range(0, 0.05)) = 0.0
_InheritBaseLayer1("_InheritBaseLayer1", Range(0, 1.0)) = 0.0
_InheritBaseLayer2("_InheritBaseLayer2", Range(0, 1.0)) = 0.0
_InheritBaseLayer3("_InheritBaseLayer3", Range(0, 1.0)) = 0.0
_VertexColorHeightFactor("_VertexColorHeightFactor", Float) = 1.0
_DistortionVectorMap("DistortionVectorMap", 2D) = "black" {}

#include "Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitProperties.hlsl"
// All our shaders use same name for entry point
#pragma vertex Vert
#pragma fragment Frag
ENDHLSL
SubShader

HLSLPROGRAM
#pragma vertex VertDefault
#pragma fragment Frag
#define SHADERPASS SHADERPASS_GBUFFER
#include "../../Material/Material.hlsl"

Cull[_CullMode]
HLSLPROGRAM
#pragma vertex VertDefault
#pragma fragment Frag
#define SHADERPASS SHADERPASS_DEBUG_VIEW_MATERIAL

Cull[_CullMode]
HLSLPROGRAM
#pragma vertex VertDefault
#pragma fragment Frag
#define SHADERPASS SHADERPASS_FORWARD
// TEMP until pragma work in include

2
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Editor/BaseLitUI.cs


using UnityEngine;
using UnityEngine.Rendering;
namespace UnityEditor.Experimental.ScriptableRenderLoop
namespace UnityEditor.Experimental.Rendering.HDPipeline
{
public abstract class BaseLitGUI : ShaderGUI
{

2
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Editor/LitUI.cs


using UnityEngine;
using UnityEngine.Rendering;
namespace UnityEditor.Experimental.ScriptableRenderLoop
namespace UnityEditor.Experimental.Rendering.HDPipeline
{
class LitGUI : BaseLitGUI
{

13
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Lit.shader


#include "Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitProperties.hlsl"
// All our shaders use same name for entry point
#pragma vertex Vert
#pragma fragment Frag
ENDHLSL
SubShader

HLSLPROGRAM
#pragma vertex VertDefault
#pragma fragment Frag
#define SHADERPASS SHADERPASS_GBUFFER
#include "../../Material/Material.hlsl"
#include "LitData.hlsl"

Cull[_CullMode]
HLSLPROGRAM
#pragma vertex VertDefault
#pragma fragment Frag
#define SHADERPASS SHADERPASS_DEBUG_VIEW_MATERIAL
#include "../../Material/Material.hlsl"

HLSLPROGRAM
#pragma vertex VertDefault
#pragma fragment Frag
#define SHADERPASS SHADERPASS_FORWARD
// TEMP until pragma work in include

68
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitData.hlsl


ApplyDepthOffsetAttribute(depthOffset, input);
#endif
float alpha = GetSurfaceData(input, layerTexCoord, surfaceData);
// We perform the conversion to world of the normalTS outside of the GetSurfaceData
// so it allow us to correctly deal with detail normal map and optimize the code for the layered shaders
float3 normalTS;
float alpha = GetSurfaceData(input, layerTexCoord, surfaceData, normalTS);
surfaceData.normalWS = TransformTangentToWorld(normalTS, input.tangentToWorld);
// Caution: surfaceData must be fully initialize before calling GetBuiltinData
GetBuiltinData(input, surfaceData, alpha, depthOffset, builtinData);
}

outWeights[0] = left;
}
float3 BlendLayeredColor(float3 rgb0, float3 rgb1, float3 rgb2, float3 rgb3, float weight[4])
float3 BlendLayeredFloat3(float3 x0, float3 x1, float3 x2, float3 x3, float weight[4])
result = rgb0 * weight[0] + rgb1 * weight[1];
result = x0 * weight[0] + x1 * weight[1];
result += (rgb2 * weight[2]);
result += (x2 * weight[2]);
result += rgb3 * weight[3];
result += x3 * weight[3];
float3 BlendLayeredNormal(float3 normal0, float3 normal1, float3 normal2, float3 normal3, float weight[4])
{
float3 result = float3(0.0, 0.0, 0.0);
result = normal0 * weight[0] + normal1 * weight[1];
#if _LAYER_COUNT >= 3
result += normal2 * weight[2];
#endif
#if _LAYER_COUNT >= 4
result += normal3 * weight[3];
#endif
return normalize(result);
}
float BlendLayeredScalar(float x0, float x1, float x2, float x3, float weight[4])
{
float result = 0.0;

}
#define SURFACEDATA_BLEND_COLOR(surfaceData, name, mask) BlendLayeredColor(surfaceData##0.##name, surfaceData##1.##name, surfaceData##2.##name, surfaceData##3.##name, mask);
#define SURFACEDATA_BLEND_NORMAL(surfaceData, name, mask) BlendLayeredNormal(surfaceData##0.##name, surfaceData##1.##name, surfaceData##2.##name, surfaceData##3.##name, mask);
#define SURFACEDATA_BLEND_COLOR(surfaceData, name, mask) BlendLayeredFloat3(surfaceData##0.##name, surfaceData##1.##name, surfaceData##2.##name, surfaceData##3.##name, mask);
#define SURFACEDATA_BLEND_SCALAR(surfaceData, name, mask) BlendLayeredScalar(surfaceData##0.##name, surfaceData##1.##name, surfaceData##2.##name, surfaceData##3.##name, mask);
#define PROP_BLEND_SCALAR(name, mask) BlendLayeredScalar(name##0, name##1, name##2, name##3, mask);

SurfaceData surfaceData1;
SurfaceData surfaceData2;
SurfaceData surfaceData3;
float alpha0 = GetSurfaceData0(input, layerTexCoord, surfaceData0);
float alpha1 = GetSurfaceData1(input, layerTexCoord, surfaceData1);
float alpha2 = GetSurfaceData2(input, layerTexCoord, surfaceData2);
float alpha3 = GetSurfaceData3(input, layerTexCoord, surfaceData3);
float3 normalTS0;
float3 normalTS1;
float3 normalTS2;
float3 normalTS3;
float alpha0 = GetSurfaceData0(input, layerTexCoord, surfaceData0, normalTS0);
float alpha1 = GetSurfaceData1(input, layerTexCoord, surfaceData1, normalTS1);
float alpha2 = GetSurfaceData2(input, layerTexCoord, surfaceData2, normalTS2);
float alpha3 = GetSurfaceData3(input, layerTexCoord, surfaceData3, normalTS3);
// Mask Values : Layer 1, 2, 3 are r, g, b
float3 maskValues = SAMPLE_TEXTURE2D(_LayerMaskMap, sampler_LayerMaskMap, input.texCoord0).rgb;

surfaceData.baseColor = SURFACEDATA_BLEND_COLOR(surfaceData, baseColor, weights);
surfaceData.specularOcclusion = SURFACEDATA_BLEND_SCALAR(surfaceData, specularOcclusion, weights);
// Note: for normal map (in tangent space) it is possible to have better performance
// by blending in tangent space then transform to world and apply flip.
// Sadly this require a specific path (without taking into account that there is detail normal map)
// mean it add an extra cost of maintenance. We chose to not do this optimization in favor
// of simpler code and in the future will rely on shader graph to create optimize code.
surfaceData.normalWS = SURFACEDATA_BLEND_NORMAL(surfaceData, normalWS, weights);
float3 normalTS;
#if defined(_HEIGHT_BASED_BLEND)
float _InheritBaseLayer0 = 1.0f; // Default value for lerp when all weights but base layer are zero.
// Compute the combined inheritance factor of layers 1,2 and 3
float inheritFactor = PROP_BLEND_SCALAR(_InheritBaseLayer, weights);
float3 vertexNormalTS = float3(0.0, 0.0, 1.0);
// The idea here is to lerp toward vertex normal. This way when we don't want to inherit, we will combine layer 1/2/3 normal with a vertex normal which is neutral.
float3 baseLayerNormalTS = normalize(lerp(vertexNormalTS, normalTS0, inheritFactor));
// Blend layer 1/2/3 normals before combining to the base layer. Again we need to have a neutral value for base layer (vertex normal) in case all weights are zero.
float3 layersNormalTS = BlendLayeredFloat3(vertexNormalTS, normalTS1, normalTS2, normalTS3, weights);
normalTS = BlendNormalRNM(baseLayerNormalTS, layersNormalTS);
#else
normalTS = BlendLayeredFloat3(normalTS0, normalTS1, normalTS2, normalTS3, weights);
#endif
surfaceData.normalWS = TransformTangentToWorld(normalTS, input.tangentToWorld);
// Init other unused parameter
surfaceData.materialId = 0;

3
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitProperties.hlsl


float _BlendSize2;
float _BlendSize3;
float _VertexColorHeightFactor;
float _InheritBaseLayer1;
float _InheritBaseLayer2;
float _InheritBaseLayer3;
float3 _EmissiveColor;
TEXTURE2D(_EmissiveColorMap);

2
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitSharePass.hlsl


//-------------------------------------------------------------------------------------
// TODO: Here we will also have all the vertex deformation (GPU skinning, vertex animation, morph target...) or we will need to generate a compute shaders instead (better! but require work to deal with unpacking like fp16)
PackedVaryings VertDefault(Attributes input)
PackedVaryings Vert(Attributes input)
{
Varyings output;

31
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitSurfaceData.hlsl


}
// Return opacity
float ADD_IDX(GetSurfaceData)(FragInputs input, LayerTexCoord layerTexCoord, out SurfaceData surfaceData)
float ADD_IDX(GetSurfaceData)(FragInputs input, LayerTexCoord layerTexCoord, out SurfaceData surfaceData, out float3 normalTS)
{
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
float alpha = ADD_IDX(_BaseColor).a;

//surfaceData.specularOcclusion *= surfaceData.specularOcclusion;
surfaceData.specularOcclusion = 1.0;
#endif
surfaceData.normalWS = float3(0.0, 0.0, 0.0); // Need to init this so that the compiler leaves us alone.
float3 vertexNormalWS = normalize(input.tangentToWorld[2].xyz);
float3 normalTS = SAMPLE_LAYER_NORMALMAP(ADD_IDX(_NormalMap), ADD_ZERO_IDX(sampler_NormalMap), ADD_IDX(layerTexCoord.base), ADD_ZERO_IDX(_NormalScale));
#ifdef _DETAIL_MAP
normalTS = lerp(normalTS, BlendNormal(normalTS, detailNormalTS), detailMask);
#endif
surfaceData.normalWS = TransformTangentToWorld(normalTS, input.tangentToWorld);
normalTS = SAMPLE_LAYER_NORMALMAP(ADD_IDX(_NormalMap), ADD_ZERO_IDX(sampler_NormalMap), ADD_IDX(layerTexCoord.base), ADD_ZERO_IDX(_NormalScale));
surfaceData.normalWS = TransformObjectToWorldDir(normalOS);
normalTS = TransformObjectToTangent(normalOS, input.tangentToWorld);
#endif
float3 detailNormalWS = TransformTangentToWorld(detailNormalTS, input.tangentToWorld);
surfaceData.normalWS = lerp(surfaceData.normalWS, BlendNormal(surfaceData.normalWS, detailNormalWS), detailMask);
normalTS = lerp(normalTS, BlendNormalRNM(normalTS, detailNormalTS), detailMask);
#endif
surfaceData.normalWS = vertexNormalWS;
normalTS = float3(0.0, 0.0, 1.0);
float3 oppositeNormalWS = -surfaceData.normalWS;
float3 oppositeNormalTS = -normalTS;
float3 oppositeNormalWS = reflect(surfaceData.normalWS, vertexNormalWS);
float3 oppositeNormalTS = reflect(normalTS, float3(0.0, 0.0, 1.0)); // Reflect around vertex normal (in tangent space this is z)
surfaceData.normalWS = input.isFrontFace ?
(GetOdddNegativeScale() >= 0.0 ? surfaceData.normalWS : oppositeNormalWS) :
(-GetOdddNegativeScale() >= 0.0 ? surfaceData.normalWS : oppositeNormalWS);
normalTS = input.isFrontFace ?
(GetOdddNegativeScale() >= 0.0 ? normalTS : oppositeNormalTS) :
(-GetOdddNegativeScale() >= 0.0 ? normalTS : oppositeNormalTS);
#endif
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A

2
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Unlit/Editor/BaseUnlitUI.cs


using UnityEngine;
using UnityEngine.Rendering;
namespace UnityEditor.Experimental.ScriptableRenderLoop
namespace UnityEditor.Experimental.Rendering.HDPipeline
{
public abstract class BaseUnlitGUI : ShaderGUI
{

2
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Unlit/Editor/UnlitUI.cs


using UnityEngine;
using UnityEngine.Rendering;
namespace UnityEditor.Experimental.ScriptableRenderLoop
namespace UnityEditor.Experimental.Rendering.HDPipeline
{
class UnlitGUI : BaseUnlitGUI
{

10
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Unlit/Unlit.shader


float _AlphaCutoff;
// All our shaders use same name for entry point
#pragma vertex Vert
#pragma fragment Frag
ENDHLSL
SubShader

Cull[_CullMode]
HLSLPROGRAM
#pragma vertex VertDefault
#pragma fragment Frag
#define SHADERPASS SHADERPASS_DEBUG_VIEW_MATERIAL
#include "../../Material/Material.hlsl"

Cull [_CullMode]
HLSLPROGRAM
#pragma vertex VertDefault
#pragma fragment Frag
#define SHADERPASS SHADERPASS_FORWARD_UNLIT
#include "../../Material/Material.hlsl"

2
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Unlit/UnlitSharePass.hlsl


// Vertex shader
//-------------------------------------------------------------------------------------
PackedVaryings VertDefault(Attributes input)
PackedVaryings Vert(Attributes input)
{
Varyings output;

207
Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Resources/FinalPass.shader


// Final compositing pass, just does gamma correction for now.
_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)
_Exposure("Exposure", Range(-32.0, 32.0)) = 0
[ToggleOff] _EnableToneMap("Enable Tone Map", Float) = 0
SubShader {
Pass {
ZTest Always Cull Off ZWrite Off
HLSLINCLUDE
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment Frag
#pragma target 5.0
#pragma target 5.0
#include "Common.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderVariables.hlsl"
#include "ColorGrading.hlsl"
#include "Common.hlsl"
#include "Color.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderVariables.hlsl"
TEXTURE2D(_MainTex);
SAMPLER2D(sampler_MainTex);
TEXTURE2D(_MainTex);
SAMPLER2D(sampler_MainTex);
TEXTURE2D(_AutoExposure);
SAMPLER2D(sampler_AutoExposure);
float4 _ToneMapCoeffs1;
float4 _ToneMapCoeffs2;
TEXTURE2D(_LogLut);
SAMPLER2D(sampler_LogLut);
#define InBlack _ToneMapCoeffs1.x
#define OutBlack _ToneMapCoeffs1.y
#define InWhite _ToneMapCoeffs1.z
#define OutWhite _ToneMapCoeffs1.w
#define WhiteLevel _ToneMapCoeffs2.z
#define WhiteClip _ToneMapCoeffs2.w
float4 _LogLut_Params;
float _Exposure;
float _EnableToneMap;
float _Exposure;
struct Attributes
{
float3 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};
float4 _NeutralTonemapperParams1;
float4 _NeutralTonemapperParams2;
struct Varyings
{
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
};
struct Attributes
{
float3 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};
Varyings Vert(Attributes input)
{
Varyings output;
output.vertex = TransformWorldToHClip(input.vertex);
output.texcoord = input.texcoord.xy;
return output;
}
struct Varyings
{
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
};
float3 evalCurve(float3 x, float A, float B, float C, float D, float E, float F)
{
return ((x*(A*x + C*B) + D*E) / (x*(A*x + B) + D*F)) - E / F;
}
Varyings Vert(Attributes input)
{
Varyings output;
output.vertex = TransformWorldToHClip(input.vertex);
output.texcoord = input.texcoord.xy;
return output;
}
float3 applyTonemapFilmicAD(float3 linearColor)
{
float blackRatio = InBlack / OutBlack;
float whiteRatio = InWhite / OutWhite;
// Neutral tonemapping (Hable/Hejl/Frostbite)
// Input is linear RGB
float3 NeutralCurve(float3 x, float a, float b, float c, float d, float e, float f)
{
return ((x * (a * x + c * b) + d * e) / (x * (a * x + b) + d * f)) - e / f;
}
float3 NeutralTonemap(float3 x, float4 params1, float4 params2)
{
// ACES supports negative color values and WILL output negative values when coming from ACES or ACEScg
// Make sure negative channels are clamped to 0.0 as this neutral tonemapper can't deal with them properly
x = max((0.0).xxx, x);
// Tonemap
float a = params1.x;
float b = params1.y;
float c = params1.z;
float d = params1.w;
float e = params2.x;
float f = params2.y;
float whiteLevel = params2.z;
float whiteClip = params2.w;
// blend tunable coefficients
float B = lerp(0.57, 0.37, blackRatio);
float C = lerp(0.01, 0.24, whiteRatio);
float D = lerp(0.02, 0.20, blackRatio);
float3 whiteScale = (1.0).xxx / NeutralCurve(whiteLevel, a, b, c, d, e, f);
x = NeutralCurve(x * whiteScale, a, b, c, d, e, f);
x *= whiteScale;
// constants
float A = 0.2;
float E = 0.02;
float F = 0.30;
// Post-curve white point adjustment
x /= whiteClip.xxx;
// eval and correct for white point
float3 whiteScale = 1.0f / evalCurve(WhiteLevel, A, B, C, D, E, F);
float3 curr = evalCurve(linearColor * whiteScale, A, B, C, D, E, F);
return x;
}
return curr * whiteScale;
}
float4 Frag(Varyings input) : SV_Target
{
float4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.texcoord);
float3 remapWhite(float3 inPixel, float whitePt)
#if EYE_ADAPTATION
// var breakout for readability
const float inBlack = 0;
const float outBlack = 0;
float inWhite = whitePt;
const float outWhite = 1;
// remap input range to output range
float3 outPixel = ((inPixel.rgb) - inBlack.xxx) / (inWhite.xxx - inBlack.xxx) * (outWhite.xxx - outBlack.xxx) + outBlack.xxx;
return (outPixel.rgb);
float autoExposure = SAMPLE_TEXTURE2D(_AutoExposure, sampler_AutoExposure, input.texcoord).r;
color *= autoExposure;
#endif
float3 NeutralTonemap(float3 x)
color.rgb *= _Exposure; // Exposure is in ev units (or 'stops'), precomputed CPU-side
#if NEUTRAL_GRADING
float3 finalColor = applyTonemapFilmicAD(x); // curve (dynamic coeffs differ per level)
finalColor = remapWhite(finalColor, WhiteClip); // post-curve white point adjustment
finalColor = saturate(finalColor);
return finalColor;
color.rgb = NeutralTonemap(color.rgb, _NeutralTonemapperParams1, _NeutralTonemapperParams2);
#elif CUSTOM_GRADING
{
float3 uvw = saturate(LinearToLogC(color));
float3 ApplyToneMap(float3 color)
// Strip lut format where `height = sqrt(width)`
uvw.z *= _LogLut_Params.z;
half shift = floor(uvw.z);
uvw.xy = uvw.xy * _LogLut_Params.z * _LogLut_Params.xy + _LogLut_Params.xy * 0.5;
uvw.x += shift * _LogLut_Params.y;
uvw.xyz = lerp(
SAMPLE_TEXTURE2D(_LogLut, sampler_LogLut, uvw.xy).rgb,
SAMPLE_TEXTURE2D(_LogLut, sampler_LogLut, uvw.xy + half2(_LogLut_Params.y, 0)).rgb,
uvw.z - shift
);
color.rgb = uvw;
}
#else
if (_EnableToneMap > 0.0)
{
return NeutralTonemap(color);
}
else
{
return saturate(color);
}
color = saturate(color);
#endif
float4 Frag(Varyings input) : SV_Target
{
float4 c = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.texcoord);
// Gamma correction
return color;
}
// TODO: Currenlt in the editor there a an additional pass were the result is copyed in a render target RGBA8_sRGB.
// So we must not correct the sRGB here else it will be done two time.
// To fix!
ENDHLSL
c.rgb = ApplyToneMap(c.rgb * exp2(_Exposure));
SubShader
{
Cull Off ZWrite Off ZTest Always
// return LinearToSRGB(c);
return c;
Pass
{
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment Frag
#pragma multi_compile __ NEUTRAL_GRADING CUSTOM_GRADING
#pragma multi_compile __ EYE_ADAPTATION
}
Fallback Off
}

15
Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderVariables.hlsl


return normalize(mul(float3x3(tangentToWorld[0].xyz, tangentToWorld[1].xyz, tangentToWorld[2].xyz), dirWS));
}
float3 TransformTangentToObject(float3 dirTS, float3 worldToTangent[3])
{
// TODO check: do we need to normalize ?
// worldToTangent is orthonormal so inverse <==> transpose
float3x3 mWorldToTangent = float3x3(worldToTangent[0].xyz, worldToTangent[1].xyz, worldToTangent[2].xyz);
float3 normalWS = mul(dirTS, mWorldToTangent);
return normalize(mul((float3x3)unity_WorldToObject, normalWS));
}
// Assume TBN is orthonormal.
float3 TransformObjectToTangent(float3 dirOS, float3 worldToTangent[3])
{
// TODO check: do we need to normalize ?
return normalize(mul(float3x3(worldToTangent[0].xyz, worldToTangent[1].xyz, worldToTangent[2].xyz), mul((float3x3)unity_ObjectToWorld, dirOS)));
}
#endif // UNITY_SHADER_VARIABLES_INCLUDED

15
Assets/ScriptableRenderLoop/ShaderLibrary/CommonMaterial.hlsl


return viewDirTS.xy * height;
}
// ref https://www.gamedev.net/topic/678043-how-to-blend-world-space-normals/#entry5287707
// assume compositing in world space
// Note: Using vtxNormal = float3(0, 0, 1) give the BlendNormalRNM formulation.
// TODO: Untested
float3 BlendNormalWorldspaceRNM(float3 n1, float3 n2, float3 vtxNormal)
{
// Build the shortest-arc quaternion
float4 q = float4(cross(vtxNormal, n2), dot(vtxNormal, n2) + 1.0) / sqrt(2.0 * (dot(vtxNormal, n2) + 1));
// Rotate the normal
return n1 * (q.w * q.w - dot(q.xyz, q.xyz)) + 2 * q.xyz * dot(q.xyz, n1) + 2 * q.w * cross(q.xyz, n1);
}
// assume compositing in tangent space
float3 BlendNormalRNM(float3 n1, float3 n2)
{
float3 t = n1.xyz + float3(0.0, 0.0, 1.0);

}
// assume compositing in tangent space
float3 BlendNormal(float3 n1, float3 n2)
{
return normalize(float3(n1.xy * n2.z + n2.xy * n1.z, n1.z * n2.z));

2
Assets/TestScenes/HDTest/LayeredLitTest.unity


m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 112888599}
m_LocalRotation: {x: 0.4442191, y: -0, z: -0, w: 0.8959182}
m_LocalPosition: {x: -41.74, y: -1.55, z: 8.82}
m_LocalPosition: {x: -41.31, y: -1.55, z: 13.03}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 1732353142}

35
Assets/TestScenes/HDTest/LayeredLitTest/Material/Layered_HeightBased.mat


- _HeightScale1: 0.1
- _HeightScale2: 0.05
- _HeightScale3: 0.06
- _InheritBaseLayer1: 1
- _InheritBaseLayer2: 1
- _InheritBaseLayer3: 1
- _LayerCount: 4
- _LayerMaskVertexColor: 0
- _Metallic: 0

- _SpecularHighlights: 1
- _SrcBlend: 1
- _SurfaceType: 0
- _TexWorldScale0: 1
- _TexWorldScale1: 1
- _TexWorldScale2: 1
- _TexWorldScale3: 1
- _UVBase0: 0
- _UVBase1: 0
- _UVBase2: 0
- _UVBase3: 0
- _TexWorldScale0: 0.1
- _TexWorldScale1: 0.1
- _TexWorldScale2: 0.1
- _TexWorldScale3: 0.1
- _UVBase0: 4
- _UVBase1: 4
- _UVBase2: 4
- _UVBase3: 4
- _UVMappingPlanar0: 0
- _UVMappingPlanar1: 0
- _UVMappingPlanar2: 0
- _UVMappingPlanar3: 0
- _UVMappingPlanar0: 1
- _UVMappingPlanar1: 1
- _UVMappingPlanar2: 1
- _UVMappingPlanar3: 1
- _UVSec: 0
- _UseHeightBasedBlend: 1
- _UseHeightBasedBlend1: 1

- _UVDetailsMappingMask1: {r: 1, g: 0, b: 0, a: 0}
- _UVDetailsMappingMask2: {r: 1, g: 0, b: 0, a: 0}
- _UVDetailsMappingMask3: {r: 1, g: 0, b: 0, a: 0}
- _UVMappingMask0: {r: 1, g: 0, b: 0, a: 0}
- _UVMappingMask1: {r: 1, g: 0, b: 0, a: 0}
- _UVMappingMask2: {r: 1, g: 0, b: 0, a: 0}
- _UVMappingMask3: {r: 1, g: 0, b: 0, a: 0}
- _UVMappingMask0: {r: 0, g: 0, b: 0, a: 0}
- _UVMappingMask1: {r: 0, g: 0, b: 0, a: 0}
- _UVMappingMask2: {r: 0, g: 0, b: 0, a: 0}
- _UVMappingMask3: {r: 0, g: 0, b: 0, a: 0}

11
Assets/TestScenes/HDTest/LayeredLitTest/Material/Lit_White.mat


m_LightmapFlags: 1
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
disabledShaderPasses:
- DistortionVectors
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:

m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DistortionVectorMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}

- _BumpScale: 1
- _CullMode: 2
- _Cutoff: 0.5
- _DepthOffsetEnable: 0
- _DetailAOScale: 1
- _DetailAlbedoScale: 1
- _DetailHeightScale: 1

- _DetailSmoothnessScale: 1
- _DistortionDepthTest: 0
- _DistortionEnable: 0
- _DistortionOnly: 0
- _DoubleSidedMode: 0
- _DstBlend: 0

- _TexWorldScale: 1
- _UVBase: 0
- _UVDetail: 0
- _UVMappingPlanar: 0
- _ZTestMode: 8
- _ZWrite: 1
m_Colors:
- _BaseColor: {r: 1, g: 1, b: 1, a: 1}

9
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Tesselation.meta


fileFormatVersion: 2
guid: 9582236b174d65b4391e0f9890fd2194
folderAsset: yes
timeCreated: 1483692743
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

9
Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Editor.meta


fileFormatVersion: 2
guid: 5d4f8c766010cda4b97dbd7bb0905215
folderAsset: yes
timeCreated: 1483612561
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

257
Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/PostProcessing.cs


using System;
using UnityEngine.Rendering;
// TEMPORARY, minimalist post-processing stack until the fully-featured framework is ready
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
using GradingType = PostProcessing.ColorGradingSettings.GradingType;
using EyeAdaptationType = PostProcessing.EyeAdaptationSettings.EyeAdaptationType;
[ExecuteInEditMode]
public sealed class PostProcessing : MonoBehaviour
{
[Serializable]
public sealed class ColorGradingSettings
{
public enum GradingType
{
None,
Neutral,
Custom
}
public GradingType type = GradingType.None;
public float exposure = 0f;
public Texture logLut = null;
[Range(-0.10f, 0.1f)] public float neutralBlackIn = 0.02f;
[Range( 1.00f, 20.0f)] public float neutralWhiteIn = 10f;
[Range(-0.09f, 0.1f)] public float neutralBlackOut = 0f;
[Range( 1.00f, 19.0f)] public float neutralWhiteOut = 10f;
[Range( 0.10f, 20.0f)] public float neutralWhiteLevel = 5.3f;
[Range( 1.00f, 10.0f)] public float neutralWhiteClip = 10f;
}
[Serializable]
public sealed class EyeAdaptationSettings
{
public enum EyeAdaptationType
{
Progressive,
Fixed
}
public bool enabled = false;
public bool showDebugHistogramInGameView = true;
[Range(1f, 99f)] public float lowPercent = 65f;
[Range(1f, 99f)] public float highPercent = 95f;
public float minLuminance = 0.03f;
public float maxLuminance = 2f;
public float exposureCompensation = 0.5f;
public EyeAdaptationType adaptationType = EyeAdaptationType.Progressive;
public float speedUp = 2f;
public float speedDown = 1f;
[Range(-16, -1)] public int logMin = -8;
[Range( 1, 16)] public int logMax = 4;
}
public EyeAdaptationSettings eyeAdaptation = new EyeAdaptationSettings();
public ColorGradingSettings colorGrading = new ColorGradingSettings();
Material m_EyeAdaptationMaterial;
Material m_FinalPassMaterial;
ComputeShader m_EyeCompute;
ComputeBuffer m_HistogramBuffer;
readonly RenderTexture[] m_AutoExposurePool = new RenderTexture[2];
int m_AutoExposurePingPing;
RenderTexture m_CurrentAutoExposure;
RenderTexture m_DebugHistogram = null;
static uint[] s_EmptyHistogramBuffer = new uint[k_HistogramBins];
bool m_FirstFrame = true;
// Don't forget to update 'EyeAdaptation.cginc' if you change these values !
const int k_HistogramBins = 64;
const int k_HistogramThreadX = 16;
const int k_HistogramThreadY = 16;
void OnEnable()
{
m_FinalPassMaterial = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/FinalPass");
m_EyeAdaptationMaterial = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/EyeAdaptation");
m_EyeCompute = Resources.Load<ComputeShader>("EyeHistogram");
m_HistogramBuffer = new ComputeBuffer(k_HistogramBins, sizeof(uint));
m_AutoExposurePool[0] = new RenderTexture(1, 1, 0, RenderTextureFormat.RFloat);
m_AutoExposurePool[1] = new RenderTexture(1, 1, 0, RenderTextureFormat.RFloat);
m_FirstFrame = true;
}
void OnDisable()
{
Utilities.Destroy(m_EyeAdaptationMaterial);
Utilities.Destroy(m_FinalPassMaterial);
foreach (var rt in m_AutoExposurePool)
Utilities.Destroy(rt);
Utilities.Destroy(m_DebugHistogram);
Utilities.SafeRelease(m_HistogramBuffer);
}
public void Render(Camera camera, ScriptableRenderContext context, RenderTargetIdentifier source, RenderTargetIdentifier destination)
{
m_FinalPassMaterial.shaderKeywords = null;
var cmd = new CommandBuffer { name = "Final Pass" };
if (eyeAdaptation.enabled)
{
int tempRt = Shader.PropertyToID("_Source");
// Downscale the framebuffer, we don't need an absolute precision for auto exposure
// and it helps making it more stable - should be using a previously downscaled pass
var scaleOffsetRes = GetHistogramScaleOffsetRes(camera);
cmd.GetTemporaryRT(tempRt, (int)scaleOffsetRes.z, (int)scaleOffsetRes.w, 0, FilterMode.Bilinear, RenderTextureFormat.ARGBHalf);
cmd.Blit(source, tempRt);
// Clears the buffer on every frame as we use it to accumulate luminance values on each frame
m_HistogramBuffer.SetData(s_EmptyHistogramBuffer);
// Gets a log histogram
int kernel = m_EyeCompute.FindKernel("KEyeHistogram");
cmd.SetComputeBufferParam(m_EyeCompute, kernel, "_Histogram", m_HistogramBuffer);
cmd.SetComputeTextureParam(m_EyeCompute, kernel, "_Source", tempRt);
cmd.SetComputeVectorParam(m_EyeCompute, "_ScaleOffsetRes", scaleOffsetRes);
cmd.DispatchCompute(m_EyeCompute, kernel, Mathf.CeilToInt(scaleOffsetRes.z / (float)k_HistogramThreadX), Mathf.CeilToInt(scaleOffsetRes.w / (float)k_HistogramThreadY), 1);
// Cleanup
cmd.ReleaseTemporaryRT(tempRt);
// Make sure filtering values are correct to avoid apocalyptic consequences
const float kMinDelta = 1e-2f;
eyeAdaptation.highPercent = Mathf.Clamp(eyeAdaptation.highPercent, 1f + kMinDelta, 99f);
eyeAdaptation.lowPercent = Mathf.Clamp(eyeAdaptation.lowPercent, 1f, eyeAdaptation.highPercent - kMinDelta);
// Compute auto exposure
m_EyeAdaptationMaterial.SetBuffer("_Histogram", m_HistogramBuffer);
m_EyeAdaptationMaterial.SetVector("_Params", new Vector4(eyeAdaptation.lowPercent * 0.01f, eyeAdaptation.highPercent * 0.01f, eyeAdaptation.minLuminance, eyeAdaptation.maxLuminance));
m_EyeAdaptationMaterial.SetVector("_Speed", new Vector2(eyeAdaptation.speedDown, eyeAdaptation.speedUp));
m_EyeAdaptationMaterial.SetVector("_ScaleOffsetRes", scaleOffsetRes);
m_EyeAdaptationMaterial.SetFloat("_ExposureCompensation", eyeAdaptation.exposureCompensation);
if (m_FirstFrame || !Application.isPlaying)
{
// We don't want eye adaptation when not in play mode because the GameView isn't
// animated, thus making it harder to tweak. Just use the final audo exposure value.
m_CurrentAutoExposure = m_AutoExposurePool[0];
cmd.Blit(null, m_CurrentAutoExposure, m_EyeAdaptationMaterial, (int)EyeAdaptationType.Fixed);
// Copy current exposure to the other pingpong target on first frame to avoid adapting from black
cmd.Blit(m_AutoExposurePool[0], m_AutoExposurePool[1]);
} else
{
int pp = m_AutoExposurePingPing;
var src = m_AutoExposurePool[++pp % 2];
var dst = m_AutoExposurePool[++pp % 2];
cmd.Blit(src, dst, m_EyeAdaptationMaterial, (int)eyeAdaptation.adaptationType);
m_AutoExposurePingPing = ++pp % 2;
m_CurrentAutoExposure = dst;
}
m_FinalPassMaterial.EnableKeyword("EYE_ADAPTATION");
m_FinalPassMaterial.SetTexture("_AutoExposure", m_CurrentAutoExposure);
// Debug histogram visualization
if (eyeAdaptation.showDebugHistogramInGameView)
{
if (m_DebugHistogram == null || !m_DebugHistogram.IsCreated())
{
m_DebugHistogram = new RenderTexture(256, 128, 0, RenderTextureFormat.ARGB32)
{
filterMode = FilterMode.Point,
wrapMode = TextureWrapMode.Clamp
};
}
m_EyeAdaptationMaterial.SetFloat("_DebugWidth", m_DebugHistogram.width);
cmd.Blit(null, m_DebugHistogram, m_EyeAdaptationMaterial, 2);
}
m_FirstFrame = false;
}
float ev = Mathf.Exp(colorGrading.exposure * 0.6931471805599453f);
m_FinalPassMaterial.SetFloat("_Exposure", ev);
if (colorGrading.type == GradingType.Neutral)
{
const float kScaleFactor = 20f;
const float kScaleFactorHalf = kScaleFactor * 0.5f;
float inBlack = colorGrading.neutralBlackIn * kScaleFactor + 1f;
float outBlack = colorGrading.neutralBlackOut * kScaleFactorHalf + 1f;
float inWhite = colorGrading.neutralWhiteIn / kScaleFactor;
float outWhite = 1f - colorGrading.neutralWhiteOut / kScaleFactor;
float blackRatio = inBlack / outBlack;
float whiteRatio = inWhite / outWhite;
const float a = 0.2f;
float b = Mathf.Max(0f, Mathf.LerpUnclamped(0.57f, 0.37f, blackRatio));
float c = Mathf.LerpUnclamped(0.01f, 0.24f, whiteRatio);
float d = Mathf.Max(0f, Mathf.LerpUnclamped(0.02f, 0.20f, blackRatio));
const float e = 0.02f;
const float f = 0.30f;
m_FinalPassMaterial.SetVector("_NeutralTonemapperParams1", new Vector4(a, b, c, d));
m_FinalPassMaterial.SetVector("_NeutralTonemapperParams2", new Vector4(e, f, colorGrading.neutralWhiteLevel, colorGrading.neutralWhiteClip / kScaleFactorHalf));
m_FinalPassMaterial.EnableKeyword("NEUTRAL_GRADING");
}
else if (colorGrading.type == GradingType.Custom)
{
if (colorGrading.logLut != null)
{
var lut = colorGrading.logLut;
m_FinalPassMaterial.SetTexture("_LogLut", lut);
m_FinalPassMaterial.SetVector("_LogLut_Params", new Vector3(1f / lut.width, 1f / lut.height, lut.height - 1f));
m_FinalPassMaterial.EnableKeyword("CUSTOM_GRADING");
}
}
cmd.Blit(source, destination, m_FinalPassMaterial, 0);
context.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}
Vector4 GetHistogramScaleOffsetRes(Camera camera)
{
float diff = eyeAdaptation.logMax - eyeAdaptation.logMin;
float scale = 1f / diff;
float offset = -eyeAdaptation.logMin * scale;
return new Vector4(scale, offset, Mathf.Floor(camera.pixelWidth / 2f), Mathf.Floor(camera.pixelHeight / 2f));
}
void OnGUI()
{
if (!eyeAdaptation.enabled || !eyeAdaptation.showDebugHistogramInGameView || m_DebugHistogram == null || !m_DebugHistogram.IsCreated())
return;
var rect = new Rect(8f, 8f, m_DebugHistogram.width, m_DebugHistogram.height);
GUI.DrawTexture(rect, m_DebugHistogram);
}
}
}

12
Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/PostProcessing.cs.meta


fileFormatVersion: 2
guid: aaa10d337b215d94dbc0ce5467cdc79a
timeCreated: 1483612023
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

77
Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Resources/ColorGrading.hlsl


#ifndef UNITY_COLOR_GRADING
#define UNITY_COLOR_GRADING
// Set to 1 to use more precise but more expensive log/linear conversions. I haven't found a proper
// use case for the high precision version yet so I'm leaving this to 0.
#define COLOR_GRADING_PRECISE_LOG 0
//
// Alexa LogC converters (El 1000)
// See http://www.vocas.nl/webfm_send/964
// It's a good fit to store HDR values in log as the range is pretty wide (1 maps to ~58.85666) and
// is quick enough to compute.
//
struct ParamsLogC
{
float cut;
float a, b, c, d, e, f;
};
static const ParamsLogC LogC =
{
0.011361, // cut
5.555556, // a
0.047996, // b
0.244161, // c
0.386036, // d
5.301883, // e
0.092819 // f
};
half LinearToLogC_Precise(half x)
{
float o;
if (x > LogC.cut)
o = LogC.c * log10(LogC.a * x + LogC.b) + LogC.d;
else
o = LogC.e * x + LogC.f;
return o;
}
float3 LinearToLogC(float3 x)
{
#if COLOR_GRADING_PRECISE_LOG
return float3(
LinearToLogC_Precise(x.x),
LinearToLogC_Precise(x.y),
LinearToLogC_Precise(x.z)
);
#else
return LogC.c * log10(LogC.a * x + LogC.b) + LogC.d;
#endif
}
float LogCToLinear_Precise(float x)
{
float o;
if (x > LogC.e * LogC.cut + LogC.f)
o = (pow(10.0, (x - LogC.d) / LogC.c) - LogC.b) / LogC.a;
else
o = (x - LogC.f) / LogC.e;
return o;
}
float3 LogCToLinear(float3 x)
{
#if COLOR_GRADING_PRECISE_LOG
return float3(
LogCToLinear_Precise(x.x),
LogCToLinear_Precise(x.y),
LogCToLinear_Precise(x.z)
);
#else
return (pow(10.0, (x - LogC.d) / LogC.c) - LogC.b) / LogC.a;
#endif
}
#endif // UNITY_COLOR_GRADING

9
Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Resources/ColorGrading.hlsl.meta


fileFormatVersion: 2
guid: d353f8a66edd94f4ab3f3c8e2ef7dd61
timeCreated: 1483709991
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

22
Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Resources/EyeAdaptation.hlsl


#ifndef UNITY_EYE_ADAPTATION
#define UNITY_EYE_ADAPTATION
// Optimal values for PS4/GCN
// Using a group size of 32x32 seems to be a bit faster on Kepler/Maxwell
// Don't forget to update 'EyeAdaptationController.cs' if you change these values !
#define HISTOGRAM_BINS 64
#define HISTOGRAM_TEXELS HISTOGRAM_BINS / 4
#define HISTOGRAM_THREAD_X 16
#define HISTOGRAM_THREAD_Y 16
float GetHistogramBinFromLuminance(float value, float2 scaleOffset)
{
return saturate(log2(value) * scaleOffset.x + scaleOffset.y);
}
float GetLuminanceFromHistogramBin(float bin, float2 scaleOffset)
{
return exp2((bin - scaleOffset.y) / scaleOffset.x);
}
#endif // UNITY_EYE_ADAPTATION

9
Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Resources/EyeAdaptation.hlsl.meta


fileFormatVersion: 2
guid: a34d57fb96cd85e4db20d2b70a6f0b1d
timeCreated: 1483621596
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

236
Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Resources/EyeAdaptation.shader


Shader "Hidden/HDRenderPipeline/EyeAdaptation"
{
Properties
{
_MainTex("Texture", any) = "" {}
}
HLSLINCLUDE
#pragma target 5.0
#include "Common.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderVariables.hlsl"
#include "EyeAdaptation.hlsl"
TEXTURE2D(_MainTex);
SAMPLER2D(sampler_MainTex);
float4 _Params; // x: lowPercent, y: highPercent, z: minBrightness, w: maxBrightness
float2 _Speed; // x: down, y: up
float4 _ScaleOffsetRes; // x: scale, y: offset, w: histogram pass width, h: histogram pass height
float _ExposureCompensation;
StructuredBuffer<uint> _Histogram;
float GetBinValue(uint index, float maxHistogramValue)
{
return float(_Histogram[index]) * maxHistogramValue;
}
float FindMaxHistogramValue()
{
uint maxValue = 0u;
for (uint i = 0; i < HISTOGRAM_BINS; i++)
{
uint h = _Histogram[i];
maxValue = max(maxValue, h);
}
return float(maxValue);
}
void FilterLuminance(uint i, float maxHistogramValue, inout float4 filter)
{
float binValue = GetBinValue(i, maxHistogramValue);
// Filter dark areas
float offset = min(filter.z, binValue);
binValue -= offset;
filter.zw -= offset.xx;
// Filter highlights
binValue = min(filter.w, binValue);
filter.w -= binValue;
// Luminance at the bin
float luminance = GetLuminanceFromHistogramBin(float(i) / float(HISTOGRAM_BINS), _ScaleOffsetRes.xy);
filter.xy += float2(luminance * binValue, binValue);
}
float GetAverageLuminance(float maxHistogramValue)
{
// Sum of all bins
uint i;
float totalSum = 0.0;
[loop]
for (i = 0; i < HISTOGRAM_BINS; i++)
totalSum += GetBinValue(i, maxHistogramValue);
// Skip darker and lighter parts of the histogram to stabilize the auto exposure
// x: filtered sum
// y: accumulator
// zw: fractions
float4 filter = float4(0.0, 0.0, totalSum * _Params.xy);
[loop]
for (i = 0; i < HISTOGRAM_BINS; i++)
FilterLuminance(i, maxHistogramValue, filter);
// Clamp to user brightness range
return clamp(filter.x / max(filter.y, 1.0e-4), _Params.z, _Params.w);
}
float GetExposureMultiplier(float avgLuminance)
{
avgLuminance = max(1.0e-4, avgLuminance);
//half keyValue = 1.03 - (2.0 / (2.0 + log2(avgLuminance + 1.0)));
half keyValue = _ExposureCompensation;
half exposure = keyValue / avgLuminance;
return exposure;
}
float InterpolateExposure(float newExposure, float oldExposure)
{
float delta = newExposure - oldExposure;
float speed = delta > 0.0 ? _Speed.x : _Speed.y;
float exposure = oldExposure + delta * (1.0 - exp2(-unity_DeltaTime.x * speed));
//float exposure = oldExposure + delta * (unity_DeltaTime.x * speed);
return exposure;
}
struct Attributes
{
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
};
struct Varyings
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
Varyings Vert(Attributes v)
{
Varyings o;
o.pos = TransformWorldToHClip(v.vertex.xyz);
o.uv = v.texcoord.xy;
return o;
}
float4 FragAdaptProgressive(Varyings i) : SV_Target
{
float maxValue = 1.0 / FindMaxHistogramValue();
float avgLuminance = GetAverageLuminance(maxValue);
float exposure = GetExposureMultiplier(avgLuminance);
float prevExposure = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, (0.5).xx).r;
exposure = InterpolateExposure(exposure, prevExposure);
return exposure.xxxx;
}
float4 FragAdaptFixed(Varyings i) : SV_Target
{
float maxValue = 1.0 / FindMaxHistogramValue();
float avgLuminance = GetAverageLuminance(maxValue);
float exposure = GetExposureMultiplier(avgLuminance);
return exposure.xxxx;
}
// Editor stuff (histogram debug visualization)
int _DebugWidth;
struct VaryingsEditorHisto
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float maxValue : TEXCOORD1;
float avgLuminance : TEXCOORD2;
};
VaryingsEditorHisto VertEditorHisto(Attributes v)
{
VaryingsEditorHisto o;
o.pos = TransformWorldToHClip(v.vertex.xyz);
o.uv = v.texcoord.xy;
o.maxValue = 1.0 / FindMaxHistogramValue();
o.avgLuminance = GetAverageLuminance(o.maxValue);
return o;
}
float4 FragEditorHisto(VaryingsEditorHisto i) : SV_Target
{
const float3 kRangeColor = float3(0.05, 0.4, 0.6);
const float3 kAvgColor = float3(0.8, 0.3, 0.05);
float4 color = float4(0.0, 0.0, 0.0, 0.7);
uint ix = (uint)(round(i.uv.x * HISTOGRAM_BINS));
float bin = saturate(float(_Histogram[ix]) * i.maxValue);
float fill = step(i.uv.y, bin);
// Min / max brightness markers
float luminanceMin = GetHistogramBinFromLuminance(_Params.z, _ScaleOffsetRes.xy);
float luminanceMax = GetHistogramBinFromLuminance(_Params.w, _ScaleOffsetRes.xy);
color.rgb += fill.rrr;
if (i.uv.x > luminanceMin && i.uv.x < luminanceMax)
{
color.rgb = fill.rrr * kRangeColor;
color.rgb += kRangeColor;
}
// Current average luminance marker
float luminanceAvg = GetHistogramBinFromLuminance(i.avgLuminance, _ScaleOffsetRes.xy);
float avgPx = luminanceAvg * _DebugWidth;
if (abs(i.pos.x - avgPx) < 2)
color.rgb = kAvgColor;
return color;
}
ENDHLSL
SubShader
{
Cull Off ZWrite Off ZTest Always
Pass
{
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment FragAdaptProgressive
ENDHLSL
}
Pass
{
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment FragAdaptFixed
ENDHLSL
}
Pass
{
HLSLPROGRAM
#pragma vertex VertEditorHisto
#pragma fragment FragEditorHisto
ENDHLSL
}
}
Fallback Off
}

9
Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Resources/EyeAdaptation.shader.meta


fileFormatVersion: 2
guid: aeefbc574fd1b81489d0c8f8dcd5f1b7
timeCreated: 1483625503
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

59
Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Resources/EyeHistogram.compute


// Put the following line to 0 or comment it to disable vignette weighting
#define USE_VIGNETTE_WEIGHTING 1
#include "Common.hlsl"
#include "EyeAdaptation.hlsl"
RWStructuredBuffer<uint> _Histogram;
Texture2D<float4> _Source;
CBUFFER_START(Params)
float4 _ScaleOffsetRes; // x: scale, y: offset, z: width, w: height
CBUFFER_END
groupshared uint gs_histogram[HISTOGRAM_BINS];
#pragma kernel KEyeHistogram
[numthreads(HISTOGRAM_THREAD_X,HISTOGRAM_THREAD_Y,1)]
void KEyeHistogram(uint2 dispatchThreadId : SV_DispatchThreadID, uint2 groupThreadId : SV_GroupThreadID)
{
// Pretty straightforward implementation of histogram gathering using atomic ops.
// I tried a few methods (no atomic ops / heavy LDS leveraging) but this one turned out to be
// the fastest on desktop (Nvidia - Kepler/Maxwell) and PS4. Still need to try it on GCN/desktop
// but considering it runs very fast on PS4 we can expect it to run well (?).
const uint localThreadId = groupThreadId.y * HISTOGRAM_THREAD_X + groupThreadId.x;
// Clears the shared memory
if (localThreadId < HISTOGRAM_BINS)
gs_histogram[localThreadId] = 0u;
GroupMemoryBarrierWithGroupSync();
// Gather local group histogram
if (dispatchThreadId.x < (uint)_ScaleOffsetRes.z && dispatchThreadId.y < (uint)_ScaleOffsetRes.w)
{
#if USE_VIGNETTE_WEIGHTING
// Vignette weighting to put more focus on what's in the center of the screen
float2 uv01 = float2(dispatchThreadId) / float2(_ScaleOffsetRes.z, _ScaleOffsetRes.w);
float2 d = abs(uv01 - (0.5).xx);
float vfactor = saturate(1.0 - dot(d, d));
vfactor *= vfactor;
uint weight = (uint)(64.0 * vfactor);
#else
uint weight = 1u;
#endif
float3 color = _Source[dispatchThreadId].xyz;
float luminance = max(color.r, max(color.g, color.b)); // Looks more natural than using a Rec.709 luminance
float logLuminance = GetHistogramBinFromLuminance(luminance, _ScaleOffsetRes.xy);
uint idx = (uint)(logLuminance * (HISTOGRAM_BINS - 1u));
InterlockedAdd(gs_histogram[idx], weight);
}
GroupMemoryBarrierWithGroupSync();
// Merge everything
if (localThreadId < HISTOGRAM_BINS)
InterlockedAdd(_Histogram[localThreadId], gs_histogram[localThreadId]);
}

9
Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Resources/EyeHistogram.compute.meta


fileFormatVersion: 2
guid: 6ffb363cabef3ec459559197dbeda232
timeCreated: 1483621596
licenseType: Pro
ComputeShaderImporter:
currentAPIMask: 4
userData:
assetBundleName:
assetBundleVariant:

68
Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Resources/LutGen.shader


Shader "Hidden/HDRenderPipeline/LutGen"
{
HLSLINCLUDE
#pragma target 5.0
#include "Common.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderVariables.hlsl"
#include "ColorGrading.hlsl"
float4 _LutParams;
struct Attributes
{
float3 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};
struct Varyings
{
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
};
Varyings Vert(Attributes input)
{
Varyings output;
output.vertex = TransformWorldToHClip(input.vertex);
output.texcoord = input.texcoord.xy;
return output;
}
float4 Frag(Varyings input) : SV_Target
{
// 2D strip lut
float2 uv = input.texcoord - _LutParams.yz;
float3 color;
color.r = frac(uv.x * _LutParams.x);
color.b = uv.x - color.r / _LutParams.x;
color.g = uv.y;
// Lut is in LogC
float3 colorLogC = color * _LutParams.w;
// Switch back to unity linear
float3 colorLinear = LogCToLinear(colorLogC);
return float4(colorLinear, 1.0);
}
ENDHLSL
SubShader
{
Cull Off ZWrite Off ZTest Always
Pass
{
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment Frag
ENDHLSL
}
}
Fallback Off
}

9
Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Resources/LutGen.shader.meta


fileFormatVersion: 2
guid: d5ac66d76294f88419a16132df665c37
timeCreated: 1483708495
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

0
Assets/ScriptableRenderLoop/ShaderLibrary/Tesselation.hlsl

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


fileFormatVersion: 2
guid: 1ea56bc9911bbad4191075872a46cc89
timeCreated: 1483692743
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

9
Assets/TestScenes/HDTest/HDRI.meta


fileFormatVersion: 2
guid: 373746a83365c134fa16fcc2208ff40b
folderAsset: yes
timeCreated: 1483546471
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

422
Assets/Textures/CoolingFilterLUT.exr
文件差异内容过多而无法显示
查看文件

108
Assets/Textures/CoolingFilterLUT.exr.meta


fileFormatVersion: 2
guid: 36ff124e89908864e932c5a3c7c6d366
timeCreated: 1483716363
licenseType: Pro
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
filterMode: 1
aniso: 0
mipBias: -1
wrapMode: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: iPhone
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: tvOS
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Windows Store Apps
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: WebGL
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

0
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Tesselation/ShareTesselation.hlsl

9
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Tesselation/ShareTesselation.hlsl.meta


fileFormatVersion: 2
guid: 70a7ee6a44b86494daad0acd691e1d51
timeCreated: 1483692743
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

289
Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Editor/PostProcessingEditor.cs


using System.IO;
using UnityEngine;
using UnityEngine.Experimental.Rendering.HDPipeline;
namespace UnityEditor.Experimental.Rendering.HDPipeline
{
using GradingType = PostProcessing.ColorGradingSettings.GradingType;
using EyeAdaptationType = PostProcessing.EyeAdaptationSettings.EyeAdaptationType;
[CustomEditor(typeof(PostProcessing))]
public class PostProcessingEditor : Editor
{
public class ColorGradingSettings
{
public SerializedProperty type;
public SerializedProperty exposure;
public SerializedProperty logLut;
public SerializedProperty neutralBlackIn;
public SerializedProperty neutralWhiteIn;
public SerializedProperty neutralBlackOut;
public SerializedProperty neutralWhiteOut;
public SerializedProperty neutralWhiteLevel;
public SerializedProperty neutralWhiteClip;
}
public class EyeAdaptationSettings
{
public SerializedProperty enabled;
public SerializedProperty showDebugHistogramInGameView;
public SerializedProperty lowPercent;
public SerializedProperty highPercent;
public SerializedProperty minLuminance;
public SerializedProperty maxLuminance;
public SerializedProperty exposureCompensation;
public SerializedProperty adaptationType;
public SerializedProperty speedUp;
public SerializedProperty speedDown;
public SerializedProperty logMin;
public SerializedProperty logMax;
}
public ColorGradingSettings colorGrading;
public EyeAdaptationSettings eyeAdaptation;
void OnEnable()
{
colorGrading = new ColorGradingSettings()
{
type = serializedObject.FindProperty("colorGrading.type"),
exposure = serializedObject.FindProperty("colorGrading.exposure"),
logLut = serializedObject.FindProperty("colorGrading.logLut"),
neutralBlackIn = serializedObject.FindProperty("colorGrading.neutralBlackIn"),
neutralWhiteIn = serializedObject.FindProperty("colorGrading.neutralWhiteIn"),
neutralBlackOut = serializedObject.FindProperty("colorGrading.neutralBlackOut"),
neutralWhiteOut = serializedObject.FindProperty("colorGrading.neutralWhiteOut"),
neutralWhiteLevel = serializedObject.FindProperty("colorGrading.neutralWhiteLevel"),
neutralWhiteClip = serializedObject.FindProperty("colorGrading.neutralWhiteClip")
};
eyeAdaptation = new EyeAdaptationSettings()
{
enabled = serializedObject.FindProperty("eyeAdaptation.enabled"),
showDebugHistogramInGameView = serializedObject.FindProperty("eyeAdaptation.showDebugHistogramInGameView"),
lowPercent = serializedObject.FindProperty("eyeAdaptation.lowPercent"),
highPercent = serializedObject.FindProperty("eyeAdaptation.highPercent"),
minLuminance = serializedObject.FindProperty("eyeAdaptation.minLuminance"),
maxLuminance = serializedObject.FindProperty("eyeAdaptation.maxLuminance"),
exposureCompensation = serializedObject.FindProperty("eyeAdaptation.exposureCompensation"),
adaptationType = serializedObject.FindProperty("eyeAdaptation.adaptationType"),
speedUp = serializedObject.FindProperty("eyeAdaptation.speedUp"),
speedDown = serializedObject.FindProperty("eyeAdaptation.speedDown"),
logMin = serializedObject.FindProperty("eyeAdaptation.logMin"),
logMax = serializedObject.FindProperty("eyeAdaptation.logMax")
};
}
public override void OnInspectorGUI()
{
serializedObject.Update();
var camera = (target as PostProcessing).GetComponent<Camera>();
if (camera == null)
EditorGUILayout.HelpBox("Global post-processing settings will be overriden by local camera settings. Global settings are the only one visible in the scene view.", MessageType.Info);
EditorGUILayout.LabelField("Color Grading", EditorStyles.boldLabel);
EditorGUI.indentLevel++;
if (camera != null)
{
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.Space(EditorGUI.indentLevel * 15f);
if (GUILayout.Button("Export frame to EXR", EditorStyles.miniButton))
{
string path = EditorUtility.SaveFilePanelInProject("Export frame as EXR...", "Frame.exr", "exr", "");
if (!string.IsNullOrEmpty(path))
SaveFrameToEXR(camera, path);
}
}
}
EditorGUILayout.PropertyField(colorGrading.exposure);
EditorGUILayout.PropertyField(colorGrading.type);
EditorGUI.indentLevel++;
var gradingType = (GradingType)colorGrading.type.intValue;
if (gradingType == GradingType.Custom)
{
EditorGUILayout.PropertyField(colorGrading.logLut);
if (!ValidateLutImportSettings())
{
EditorGUILayout.HelpBox("Invalid LUT import settings.", MessageType.Warning);
GUILayout.Space(-32);
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.FlexibleSpace();
if (GUILayout.Button("Fix", GUILayout.Width(60)))
{
SetLUTImportSettings();
AssetDatabase.Refresh();
}
GUILayout.Space(8);
}
GUILayout.Space(11);
}
}
else if (gradingType == GradingType.Neutral)
{
EditorGUILayout.PropertyField(colorGrading.neutralBlackIn);
EditorGUILayout.PropertyField(colorGrading.neutralWhiteIn);
EditorGUILayout.PropertyField(colorGrading.neutralBlackOut);
EditorGUILayout.PropertyField(colorGrading.neutralWhiteOut);
EditorGUILayout.PropertyField(colorGrading.neutralWhiteLevel);
EditorGUILayout.PropertyField(colorGrading.neutralWhiteClip);
}
EditorGUI.indentLevel--;
EditorGUI.indentLevel--;
EditorGUILayout.LabelField("Eye Adaptation", EditorStyles.boldLabel);
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(eyeAdaptation.enabled);
if (eyeAdaptation.enabled.boolValue)
{
EditorGUILayout.PropertyField(eyeAdaptation.showDebugHistogramInGameView);
EditorGUILayout.PropertyField(eyeAdaptation.logMin, new GUIContent("Histogram Log Min"));
EditorGUILayout.PropertyField(eyeAdaptation.logMax, new GUIContent("Histogram Log Max"));
EditorGUILayout.Space();
float low = eyeAdaptation.lowPercent.floatValue;
float high = eyeAdaptation.highPercent.floatValue;
EditorGUILayout.MinMaxSlider(new GUIContent("Filter"), ref low, ref high, 1f, 99f);
eyeAdaptation.lowPercent.floatValue = low;
eyeAdaptation.highPercent.floatValue = high;
EditorGUILayout.PropertyField(eyeAdaptation.minLuminance);
EditorGUILayout.PropertyField(eyeAdaptation.maxLuminance);
EditorGUILayout.PropertyField(eyeAdaptation.exposureCompensation);
EditorGUILayout.PropertyField(eyeAdaptation.adaptationType);
if (eyeAdaptation.adaptationType.intValue == (int)EyeAdaptationType.Progressive)
{
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(eyeAdaptation.speedUp);
EditorGUILayout.PropertyField(eyeAdaptation.speedDown);
EditorGUI.indentLevel--;
}
}
EditorGUI.indentLevel--;
serializedObject.ApplyModifiedProperties();
}
void SetLUTImportSettings()
{
var lut = (target as PostProcessing).colorGrading.logLut;
var importer = (TextureImporter)AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(lut));
importer.textureType = TextureImporterType.Default;
importer.filterMode = FilterMode.Bilinear;
importer.mipmapEnabled = false;
importer.anisoLevel = 0;
importer.sRGBTexture = false;
importer.npotScale = TextureImporterNPOTScale.None;
importer.textureCompression = TextureImporterCompression.Uncompressed;
importer.SaveAndReimport();
AssetDatabase.Refresh();
}
bool ValidateLutImportSettings()
{
var lut = (target as PostProcessing).colorGrading.logLut;
if (lut == null)
return true;
var importer = (TextureImporter)AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(lut));
return importer.anisoLevel == 0
&& importer.mipmapEnabled == false
&& importer.sRGBTexture == false
&& (importer.textureCompression == TextureImporterCompression.Uncompressed)
&& importer.filterMode == FilterMode.Bilinear;
}
void SaveFrameToEXR(Camera camera, string path)
{
// We want a 1024x32 sized render at a minimum so that we have enough space to stamp the lut
var aspect = (float)camera.pixelHeight / (float)camera.pixelWidth;
var width = camera.pixelWidth >= 1024
? camera.pixelWidth
: 1024;
var height = Mathf.RoundToInt(width * aspect);
var texture = new Texture2D(width, height, TextureFormat.RGBAHalf, false, true);
var targetRt = RenderTexture.GetTemporary(width, height, 0, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear);
// Render the current frame without post processing
var oldPPState = (target as PostProcessing).enabled;
(target as PostProcessing).enabled = false;
var oldTarget = camera.targetTexture;
var oldActive = RenderTexture.active;
camera.targetTexture = targetRt;
camera.Render();
// Stamp the log lut in the top left corner
const int k_InternalLogLutSize = 32;
var stampMaterial = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/LutGen");
stampMaterial.SetVector("_LutParams", new Vector4(
k_InternalLogLutSize,
0.5f / (k_InternalLogLutSize * k_InternalLogLutSize),
0.5f / k_InternalLogLutSize,
k_InternalLogLutSize / (k_InternalLogLutSize - 1f))
);
var stampRt = RenderTexture.GetTemporary(1024, 32, 0, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear);
Graphics.Blit(null, stampRt, stampMaterial, 0);
RenderTexture.active = targetRt;
GL.PushMatrix();
{
GL.LoadPixelMatrix(0, width, height, 0);
Graphics.DrawTexture(new Rect(0, 0, stampRt.width, stampRt.height), stampRt);
}
GL.PopMatrix();
// Read back
texture.ReadPixels(new Rect(0, 0, targetRt.width, targetRt.height), 0, 0);
camera.targetTexture = oldTarget;
RenderTexture.active = oldActive;
(target as PostProcessing).enabled = oldPPState;
// Cleanup
RenderTexture.ReleaseTemporary(stampRt);
RenderTexture.ReleaseTemporary(targetRt);
Utilities.Destroy(stampMaterial);
// Save
File.WriteAllBytes(path, texture.EncodeToEXR(Texture2D.EXRFlags.CompressPIZ));
AssetDatabase.Refresh();
}
}
}

12
Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Editor/PostProcessingEditor.cs.meta


fileFormatVersion: 2
guid: 5ddd90f68799818409996b6fd52790dc
timeCreated: 1483612569
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存