浏览代码

Merge branch 'LightweightPipeline'

/main
Felipe Lira 7 年前
当前提交
63f633bd
共有 44 个文件被更改,包括 758 次插入119 次删除
  1. 18
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Data/LightweightPipelineAsset.cs
  2. 37
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/LightweightAssetEditor.cs
  3. 120
      ScriptableRenderPipeline/LightweightPipeline/LWRP/LightweightPipeline.cs
  4. 2
      ScriptableRenderPipeline/LightweightPipeline/LWRP/LightweightPipelineUtils.cs
  5. 2
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightBlit.shader
  6. 2
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightCopyDepth.shader
  7. 18
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightStandard.shader
  8. 4
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightStandardParticles.shader
  9. 4
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightStandardParticlesUnlit.shader
  10. 8
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightStandardSimpleLighting.shader
  11. 4
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightStandardTerrain.shader
  12. 4
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightUnlit.shader
  13. 5
      Tests/GraphicsTests/RenderPipeline/LightweightPipeline/LightweightPipelineAsset.asset
  14. 6
      ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/LightweightPassLit.hlsl
  15. 4
      ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/LightweightPassMeta.hlsl
  16. 2
      ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/LightweightPassShadow.hlsl
  17. 4
      ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/InputBuiltin.hlsl
  18. 33
      ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Shadows.hlsl
  19. 8
      ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary.meta
  20. 584
      ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Lighting.hlsl
  21. 8
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightShaderLibrary.meta
  22. 0
      /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/LightweightPassLit.hlsl
  23. 0
      /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/LightweightPassMeta.hlsl
  24. 0
      /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/LightweightPassShadow.hlsl
  25. 0
      /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/LightweightPassShadow.hlsl.meta
  26. 0
      /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/LightweightPassMeta.hlsl.meta
  27. 0
      /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/LightweightPassLit.hlsl.meta
  28. 0
      /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/CoreFunctions.hlsl
  29. 0
      /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/CoreFunctions.hlsl.meta
  30. 0
      /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Input.hlsl
  31. 0
      /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/InputBuiltin.hlsl.meta
  32. 0
      /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Particles.hlsl.meta
  33. 0
      /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Shadows.hlsl.meta
  34. 0
      /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Lighting.hlsl.meta
  35. 0
      /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/InputSurface.hlsl.meta
  36. 0
      /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Input.hlsl.meta
  37. 0
      /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Core.hlsl.meta
  38. 0
      /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/InputBuiltin.hlsl
  39. 0
      /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/InputSurface.hlsl
  40. 0
      /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Shadows.hlsl
  41. 0
      /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Particles.hlsl
  42. 0
      /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Core.hlsl

18
ScriptableRenderPipeline/LightweightPipeline/LWRP/Data/LightweightPipelineAsset.cs


public static readonly string[] m_SearchPaths = {"Assets", "Packages/com.unity.render-pipelines.lightweight"};
// Default values set when a new LightweightPipeline asset is created
[SerializeField] private float kAssetVersion = 1.0f;
[SerializeField] private bool m_RequireCameraDepthTexture = false;
[SerializeField] private bool m_RequireDepthTexture = false;
[SerializeField] private bool m_RequireSoftParticles = false;
[SerializeField] private bool m_SupportsHDR = false;
[SerializeField] private MSAAQuality m_MSAA = MSAAQuality._4x;
[SerializeField] private float m_RenderScale = 1.0f;

return ShadowSetting != ShadowType.NO_SHADOW;
}
public float GetAssetVersion()
{
return kAssetVersion;
}
public int MaxPixelLights
{
get { return m_MaxPixelLights; }

get { return m_SupportsVertexLight; }
}
public bool RequireCameraDepthTexture
public bool RequireDepthTexture
get { return m_RequireCameraDepthTexture; }
get { return m_RequireDepthTexture; }
}
public bool RequireSoftParticles
{
get { return m_RequireSoftParticles; }
}
public bool SupportsHDR

37
ScriptableRenderPipeline/LightweightPipeline/LWRP/Editor/LightweightAssetEditor.cs


using UnityEditor;
using UnityEditor.AnimatedValues;
namespace UnityEngine.Experimental.Rendering.LightweightPipeline
{

public static GUIContent enableVertexLightLabel = new GUIContent("Vertex Lighting",
"If enabled shades additional lights exceeding the maximum number of pixel lights per-vertex up to the maximum of 8 lights.");
public static GUIContent requireCameraDepthTexture = new GUIContent("Camera Depth Texture", "If enabled the pipeline will generate camera's depth that can be bound in shaders as _CameraDepthTexture. This is necessary for some effect like Soft Particles.");
public static GUIContent requireDepthTexture = new GUIContent("Depth Texture", "If enabled the pipeline will generate camera's depth that can be bound in shaders as _CameraDepthTexture.");
public static GUIContent requireSoftParticles = new GUIContent("Soft Particles", "If enabled the pipeline will enable SOFT_PARTICLES keyword.");
public static GUIContent shadowType = new GUIContent("Type",
"Global shadow settings. Options are NO_SHADOW, HARD_SHADOWS and SOFT_SHADOWS.");

public static string[] shadowCascadeOptions = {"No Cascades", "Two Cascades", "Four Cascades"};
}
AnimBool m_ShowSoftParticles = new AnimBool();
private int kMaxSupportedPixelLights = 8;
private float kMinRenderScale = 0.1f;
private float kMaxRenderScale = 4.0f;

private SerializedProperty m_RequireCameraDepthTextureProp;
private SerializedProperty m_RequireDepthTextureProp;
private SerializedProperty m_RequireSoftParticlesProp;
private SerializedProperty m_ShadowTypeProp;
private SerializedProperty m_ShadowNearPlaneOffsetProp;
private SerializedProperty m_ShadowDistanceProp;

m_RenderScale = serializedObject.FindProperty("m_RenderScale");
m_MaxPixelLights = serializedObject.FindProperty("m_MaxPixelLights");
m_SupportsVertexLightProp = serializedObject.FindProperty("m_SupportsVertexLight");
m_RequireCameraDepthTextureProp = serializedObject.FindProperty("m_RequireCameraDepthTexture");
m_RequireDepthTextureProp = serializedObject.FindProperty("m_RequireDepthTexture");
m_RequireSoftParticlesProp = serializedObject.FindProperty("m_RequireSoftParticles");
m_ShadowTypeProp = serializedObject.FindProperty("m_ShadowType");
m_ShadowNearPlaneOffsetProp = serializedObject.FindProperty("m_ShadowNearPlaneOffset");
m_ShadowDistanceProp = serializedObject.FindProperty("m_ShadowDistance");

m_ShadowCascade4SplitProp = serializedObject.FindProperty("m_Cascade4Split");
m_HDR = serializedObject.FindProperty("m_SupportsHDR");
m_MSAA = serializedObject.FindProperty("m_MSAA");
m_ShowSoftParticles.valueChanged.AddListener(Repaint);
m_ShowSoftParticles.value = m_RequireSoftParticlesProp.boolValue;
}
void OnDisable()
{
m_ShowSoftParticles.valueChanged.RemoveListener(Repaint);
}
void UpdateAnimationValues()
{
m_ShowSoftParticles.target = m_RequireDepthTextureProp.boolValue;
}
void DrawAnimatedProperty(SerializedProperty prop, GUIContent content, AnimBool animation)
{
using (var group = new EditorGUILayout.FadeGroupScope(animation.faded))
if (group.visible)
EditorGUILayout.PropertyField(prop, content);
}
protected void DoPopup(GUIContent label, SerializedProperty property, string[] options)

{
serializedObject.Update();
UpdateAnimationValues();
EditorGUILayout.Space();
EditorGUILayout.LabelField(Styles.renderingLabel, EditorStyles.boldLabel);
EditorGUI.indentLevel++;

m_MaxPixelLights.intValue = EditorGUILayout.IntSlider(m_MaxPixelLights.intValue, 0, kMaxSupportedPixelLights);
EditorGUILayout.EndHorizontal();
EditorGUILayout.PropertyField(m_SupportsVertexLightProp, Styles.enableVertexLightLabel);
EditorGUILayout.PropertyField(m_RequireCameraDepthTextureProp, Styles.requireCameraDepthTexture);
EditorGUILayout.PropertyField(m_RequireDepthTextureProp, Styles.requireDepthTexture);
DrawAnimatedProperty(m_RequireSoftParticlesProp, Styles.requireSoftParticles, m_ShowSoftParticles);
EditorGUILayout.PropertyField(m_HDR, Styles.hdrContent);
EditorGUILayout.PropertyField(m_MSAA, Styles.msaaContent);

120
ScriptableRenderPipeline/LightweightPipeline/LWRP/LightweightPipeline.cs


private RenderTargetIdentifier m_Color;
private bool m_IntermediateTextureArray;
private bool m_RequiredDepth;
private bool m_RequireDepthTexture;
private bool m_RequireCopyColor;
private bool m_DepthRenderBuffer;
private MixedLightingSetup m_MixedLightingSetup;
private const int kDepthStencilBufferBits = 32;

base.Dispose();
Shader.globalRenderPipeline = "";
SupportedRenderingFeatures.active = new SupportedRenderingFeatures();
CoreUtils.Destroy(m_ErrorMaterial);
CoreUtils.Destroy(m_CopyDepthMaterial);
CoreUtils.Destroy(m_BlitMaterial);

ShadowPass(visibleLights, ref context, ref lightData);
FrameRenderingConfiguration frameRenderingConfiguration;
SetupFrameRendering(out frameRenderingConfiguration, stereoEnabled);
SetupFrameRenderingConfiguration(out frameRenderingConfiguration, stereoEnabled);
SetupIntermediateResources(frameRenderingConfiguration, ref context);
// SetupCameraProperties does the following:

// Setup global time properties (_Time, _SinTime, _CosTime)
context.SetupCameraProperties(m_CurrCamera, stereoEnabled);
if (LightweightUtils.HasFlag(frameRenderingConfiguration, FrameRenderingConfiguration.DepthPass))
if (LightweightUtils.HasFlag(frameRenderingConfiguration, FrameRenderingConfiguration.DepthPrePass))
DepthPass(ref context);
ForwardPass(visibleLights, frameRenderingConfiguration, ref context, ref lightData, stereoEnabled);

private void AfterOpaque(ref ScriptableRenderContext context, FrameRenderingConfiguration config)
{
if (!m_RequiredDepth)
if (!m_RequireDepthTexture)
// When only one opaque effect is active we need to blit to a work RT. We blit to copy color.
// TODO: We can check if there are more than one opaque postfx and avoid an extra blit.
bool setRenderTarget = false;
RenderTargetIdentifier depthRT = m_DepthRT;
RenderPostProcess(cmd, m_ColorRT, m_CopyColorRT, true);
m_CurrCameraColorRT = (m_IsOffscreenCamera) ? BuiltinRenderTextureType.CameraTarget : m_ColorRT;
// When only have one effect in the stack we blit to a work RT then blit it back to active color RT.
// This seems like an extra blit but it saves us a depth copy/blit which has some corner cases like msaa depth resolve.
if (m_RequireCopyColor)
{
RenderPostProcess(cmd, m_CurrCameraColorRT, m_CopyColorRT, true);
cmd.Blit(m_CopyColorRT, m_CurrCameraColorRT);
}
else
RenderPostProcess(cmd, m_CurrCameraColorRT, m_CurrCameraColorRT, true);
setRenderTarget = true;
SetRenderTarget(cmd, m_CurrCameraColorRT, m_DepthRT);
RenderTargetIdentifier colorRT = (m_IsOffscreenCamera) ? BuiltinRenderTextureType.CameraTarget : m_ColorRT;
SetRenderTarget(cmd, colorRT, m_CopyDepth);
depthRT = m_CopyDepth;
setRenderTarget = true;
if (setRenderTarget)
SetRenderTarget(cmd, m_CurrCameraColorRT, depthRT);
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}

return;
CommandBuffer cmd = CommandBufferPool.Get("After Transparent");
RenderPostProcess(cmd, BuiltinRenderTextureType.CurrentActive, BuiltinRenderTextureType.CameraTarget, false);
RenderPostProcess(cmd, m_CurrCameraColorRT, BuiltinRenderTextureType.CameraTarget, false);
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}

}
}
private void SetupFrameRendering(out FrameRenderingConfiguration configuration, bool stereoEnabled)
private void SetupFrameRenderingConfiguration(out FrameRenderingConfiguration configuration, bool stereoEnabled)
{
configuration = (stereoEnabled) ? FrameRenderingConfiguration.Stereo : FrameRenderingConfiguration.None;
if (stereoEnabled && XRSettings.eyeTextureDesc.dimension == TextureDimension.Tex2DArray)

m_Asset.RenderScale < 1.0f || hdrEnabled;
m_ColorFormat = hdrEnabled ? RenderTextureFormat.DefaultHDR : RenderTextureFormat.Default;
m_RequiredDepth = false;
m_RequireCopyColor = false;
m_DepthRenderBuffer = false;
m_CameraPostProcessLayer = m_CurrCamera.GetComponent<PostProcessLayer>();
bool msaaEnabled = m_CurrCamera.allowMSAA && m_Asset.MSAASampleCount > 1 && (m_CurrCamera.targetTexture == null || m_CurrCamera.targetTexture.antiAliasing > 1);

bool softParticlesEnabled = m_Asset.RequireCameraDepthTexture && !stereoEnabled;
m_RequireDepthTexture = m_Asset.RequireDepthTexture && !stereoEnabled;
m_RequiredDepth = true;
m_RequireDepthTexture = true;
{
// Resolving depth msaa requires texture2DMS. Currently if msaa is enabled we do a depth pre-pass.
if (msaaEnabled)
configuration |= FrameRenderingConfiguration.DepthPass;
}
// In case of soft particles we need depth copy. If depth copy not supported fallback to depth prepass
if (softParticlesEnabled)
{
m_RequiredDepth = true;
intermediateTexture = true;
bool supportsDepthCopy = m_CopyTextureSupport != CopyTextureSupport.None && m_Asset.CopyDepthShader.isSupported;
// currently fallback to depth prepass if msaa is enabled since. We need texture2DMS to support depth resolve.
configuration |= (msaaEnabled || !supportsDepthCopy) ? FrameRenderingConfiguration.DepthPass : FrameRenderingConfiguration.DepthCopy;
if (m_CameraPostProcessLayer.sortedBundles[PostProcessEvent.BeforeTransparent].Count == 1)
m_RequireCopyColor = true;
}
}
if (msaaEnabled)

}
if (m_RequireDepthTexture)
{
// If msaa is enabled we don't use a depth renderbuffer as we might not have support to Texture2DMS to resolve depth.
// Instead we use a depth prepass and whenever depth is needed we use the 1 sample depth from prepass.
if (!msaaEnabled)
{
bool supportsDepthCopy = m_CopyTextureSupport != CopyTextureSupport.None && m_Asset.CopyDepthShader.isSupported;
m_DepthRenderBuffer = true;
intermediateTexture = true;
// If requiring a camera depth texture we need separate depth as it reads/write to depth at same time
// Post process doesn't need the copy
if (!m_Asset.RequireDepthTexture && postProcessEnabled)
configuration |= (supportsDepthCopy) ? FrameRenderingConfiguration.DepthCopy : FrameRenderingConfiguration.DepthPrePass;
}
else
{
configuration |= FrameRenderingConfiguration.DepthPrePass;
}
else
intermediateTexture = true;
if (intermediateTexture)
configuration |= FrameRenderingConfiguration.IntermediateTexture;

int rtWidth = (int)((float)m_CurrCamera.pixelWidth * renderScale);
int rtHeight = (int)((float)m_CurrCamera.pixelHeight * renderScale);
if (m_RequiredDepth)
if (m_RequireDepthTexture)
{
RenderTextureDescriptor depthRTDesc = new RenderTextureDescriptor(rtWidth, rtHeight, RenderTextureFormat.Depth, kDepthStencilBufferBits);
cmd.GetTemporaryRT(CameraRenderTargetID.depth, depthRTDesc, FilterMode.Bilinear);

m_CurrCameraColorRT = m_ColorRT;
}
// When postprocessing is enabled we might have a before transparent effect. In that case we need to
// use the camera render target as input. We blit to an opaque RT and then after before postprocessing is done
// we blit to the final camera RT. If no postprocessing we blit to final camera RT from beginning.
if (LightweightUtils.HasFlag(renderingConfig, FrameRenderingConfiguration.BeforeTransparentPostProcess))
// When BeforeTransparent PostFX is enabled and only one effect is in the stack we need to create a temp
// color RT to blit the effect.
if (m_RequireCopyColor)
cmd.GetTemporaryRT(CameraRenderTargetID.copyColor, colorRTDesc, FilterMode.Point);
}

}
Light light = lightData.light;
// TODO: Add support to shadow mask
// TODO: Add support to shadow mask
if (m_MixedLightingSetup == MixedLightingSetup.None && lightData.light.shadows != LightShadows.None)
{
m_MixedLightingSetup = MixedLightingSetup.Subtractive;

CoreUtils.SetKeyword(cmd, "_ADDITIONAL_LIGHTS", lightData.totalAdditionalLightsCount > 0);
CoreUtils.SetKeyword(cmd, "_MIXED_LIGHTING_SUBTRACTIVE", m_MixedLightingSetup == MixedLightingSetup.Subtractive);
CoreUtils.SetKeyword(cmd, "_VERTEX_LIGHTS", vertexLightsCount > 0);
CoreUtils.SetKeyword(cmd, "SOFTPARTICLES_ON", m_Asset.RequireCameraDepthTexture);
CoreUtils.SetKeyword(cmd, "SOFTPARTICLES_ON", m_RequireDepthTexture && m_Asset.RequireSoftParticles);
bool linearFogModeEnabled = false;
bool exponentialFogModeEnabled = false;

if (!m_IsOffscreenCamera)
colorRT = m_CurrCameraColorRT;
if (m_RequiredDepth && !LightweightUtils.HasFlag(renderingConfig, FrameRenderingConfiguration.DepthPass))
if (m_RequireDepthTexture)
depthRT = m_DepthRT;
}

var cmd = CommandBufferPool.Get("Blit");
if (m_IntermediateTextureArray)
{
SetRenderTarget(cmd, BuiltinRenderTextureType.CameraTarget);
cmd.Blit(m_CurrCameraColorRT, BuiltinRenderTextureType.CurrentActive);
cmd.Blit(m_CurrCameraColorRT, BuiltinRenderTextureType.CameraTarget);
Material blitMaterial = m_BlitMaterial;
if (LightweightUtils.HasFlag(renderingConfig, FrameRenderingConfiguration.Stereo))
blitMaterial = null;
Blit(cmd, renderingConfig, BuiltinRenderTextureType.CurrentActive, BuiltinRenderTextureType.CameraTarget, m_BlitMaterial);
Blit(cmd, renderingConfig, m_CurrCameraColorRT, BuiltinRenderTextureType.CameraTarget, blitMaterial);
}
SetRenderTarget(cmd, BuiltinRenderTextureType.CameraTarget);

private void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier colorRT, RenderTargetIdentifier depthRT, ClearFlag clearFlag = ClearFlag.None)
{
if (depthRT == BuiltinRenderTextureType.None)
if (depthRT == BuiltinRenderTextureType.None || !m_DepthRenderBuffer)
{
SetRenderTarget(cmd, colorRT, clearFlag);
return;

if (opaqueOnly)
{
m_CameraPostProcessLayer.RenderOpaqueOnly(m_PostProcessRenderContext);
cmd.Blit(m_CopyColorRT, m_ColorRT);
}
else
m_CameraPostProcessLayer.Render(m_PostProcessRenderContext);

2
ScriptableRenderPipeline/LightweightPipeline/LWRP/LightweightPipelineUtils.cs


Msaa = (1 << 1),
BeforeTransparentPostProcess = (1 << 2),
PostProcess = (1 << 3),
DepthPass = (1 << 4),
DepthPrePass = (1 << 4),
DepthCopy = (1 << 5),
DefaultViewport = (1 << 6),
IntermediateTexture = (1 << 7),

2
ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightBlit.shader


#pragma vertex Vertex
#pragma fragment Fragment
#include "LightweightShaderLibrary/Core.hlsl"
#include "LWRP/ShaderLibrary/Core.hlsl"
struct VertexInput
{

2
ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightCopyDepth.shader


#pragma vertex vert
#pragma fragment frag
#include "LightweightShaderLibrary/Core.hlsl"
#include "LWRP/ShaderLibrary/Core.hlsl"
TEXTURE2D(_CameraDepthTexture);
SAMPLER(sampler_CameraDepthTexture);

18
ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightStandard.shader


SubShader
{
// Lightweight Pipeline tag is required. If Lightweight pipeline is not set in the graphics settings
// this Subshader will fail. One can add a subshader below or fallback to Standard built-in to make this
// material work with both Lightweight Pipeline and Builtin Unity Pipeline
// Base forward pass (directional light, emission, lightmaps, ...)
// Forward pass. Shades all light in a single pass. GI + emission + Fog
// Lightmode matches the ShaderPassName set in LightweightPipeline.cs. SRPDefaultUnlit and passes with
// no LightMode tag are also rendered by Lightweight Pipeline
Tags{"LightMode" = "LightweightForward"}
Blend[_SrcBlend][_DstBlend]

// Required to compile gles 2.0 with standard srp library
// Required to compile gles 2.0 with standard SRP library
// All shaders must be compiled with HLSLcc and currently only gles is not using HLSLcc by default
#pragma prefer_hlslcc gles
#pragma target 3.0

#pragma vertex LitPassVertex
#pragma fragment LitPassFragment
#include "LightweightPassLit.hlsl"
#include "LWRP/ShaderLibrary/LightweightPassLit.hlsl"
ENDHLSL
}

#pragma vertex ShadowPassVertex
#pragma fragment ShadowPassFragment
#include "LightweightPassShadow.hlsl"
#include "LWRP/ShaderLibrary/LightweightPassShadow.hlsl"
ENDHLSL
}

#pragma vertex vert
#pragma fragment frag
#include "LightweightShaderLibrary/Core.hlsl"
#include "LWRP/ShaderLibrary/Core.hlsl"
float4 vert(float4 pos : POSITION) : SV_POSITION
{

#pragma shader_feature _SPECGLOSSMAP
#include "LightweightPassMeta.hlsl"
#include "LWRP/ShaderLibrary/LightweightPassMeta.hlsl"
ENDHLSL
}

4
ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightStandardParticles.shader


#pragma shader_feature _FADING_ON
#pragma shader_feature _REQUIRE_UV2
#include "LightweightShaderLibrary/Particles.hlsl"
#include "LightweightShaderLibrary/Lighting.hlsl"
#include "LWRP/ShaderLibrary/Particles.hlsl"
#include "LWRP/ShaderLibrary/Lighting.hlsl"
VertexOutputLit ParticlesLitVertex(appdata_particles v)
{

4
ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightStandardParticlesUnlit.shader


#pragma vertex vertParticleUnlit
#pragma fragment fragParticleUnlit
#include "LightweightShaderLibrary/Particles.hlsl"
#include "LightweightShaderLibrary/Core.hlsl"
#include "LWRP/ShaderLibrary/Particles.hlsl"
#include "LWRP/ShaderLibrary/Core.hlsl"
VertexOutputLit vertParticleUnlit(appdata_particles v)
{

8
ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightStandardSimpleLighting.shader


#pragma vertex LitPassVertex
#pragma fragment LitPassFragmentSimple
#include "LightweightPassLit.hlsl"
#include "LWRP/ShaderLibrary/LightweightPassLit.hlsl"
ENDHLSL
}

#pragma vertex ShadowPassVertex
#pragma fragment ShadowPassFragment
#include "LightweightPassShadow.hlsl"
#include "LWRP/ShaderLibrary/LightweightPassShadow.hlsl"
ENDHLSL
}

#pragma vertex vert
#pragma fragment frag
#include "LightweightShaderLibrary/Core.hlsl"
#include "LWRP/ShaderLibrary/Core.hlsl"
float4 vert(float4 pos : POSITION) : SV_POSITION
{

#pragma shader_feature _EMISSION
#pragma shader_feature _SPECGLOSSMAP
#include "LightweightPassMeta.hlsl"
#include "LWRP/ShaderLibrary/LightweightPassMeta.hlsl"
ENDHLSL
}
}

4
ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightStandardTerrain.shader


#define LIGHTMAP_ON
#endif
#include "LightweightShaderLibrary/Lighting.hlsl"
#include "LWRP/ShaderLibrary/Lighting.hlsl"
CBUFFER_START(_Terrain)
half _Metallic0;

#pragma vertex vert
#pragma fragment frag
#include "LightweightShaderLibrary/Core.hlsl"
#include "LWRP/ShaderLibrary/Core.hlsl"
float4 vert(float4 pos : POSITION) : SV_POSITION
{

4
ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightUnlit.shader


#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON
// Lighting include is needed because of GI
#include "LightweightShaderLibrary/Lighting.hlsl"
#include "LightweightShaderLibrary/InputSurface.hlsl"
#include "LWRP/ShaderLibrary/Lighting.hlsl"
#include "LWRP/ShaderLibrary/InputSurface.hlsl"
struct VertexInput
{

5
Tests/GraphicsTests/RenderPipeline/LightweightPipeline/LightweightPipelineAsset.asset


m_Script: {fileID: 11500000, guid: bf2edee5c58d82540a51f03df9d42094, type: 3}
m_Name: LightweightPipelineAsset
m_EditorClassIdentifier:
kAssetVersion: 1
m_RequireCameraDepthTexture: 0
m_RequireDepthTexture: 0
m_RequireSoftParticles: 0
m_SupportsHDR: 0
m_MSAA: 4
m_RenderScale: 1
m_ShadowType: 1

6
ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/LightweightPassLit.hlsl


#ifndef LIGHTWEIGHT_PASS_LIT_INCLUDED
#define LIGHTWEIGHT_PASS_LIT_INCLUDED
#include "LightweightShaderLibrary/InputSurface.hlsl"
#include "LightweightShaderLibrary/Lighting.hlsl"
#include "LWRP/ShaderLibrary/InputSurface.hlsl"
#include "LWRP/ShaderLibrary/Lighting.hlsl"
struct LightweightVertexInput
{

float fogFactor = IN.fogFactorAndVertexLight.x;
half4 color = LightweightFragmentPBR(IN.posWS.xyz, normalWS, IN.viewDir, indirectDiffuse, IN.fogFactorAndVertexLight.yzw, surfaceData.albedo, surfaceData.metallic, surfaceData.specular, surfaceData.smoothness, surfaceData.occlusion, surfaceData.emission, surfaceData.alpha);
// Computes fog factor per-vertex
ApplyFog(color.rgb, fogFactor);
return color;
}

4
ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/LightweightPassMeta.hlsl


#ifndef LIGHTWEIGHT_PASS_META_INCLUDED
#define LIGHTWEIGHT_PASS_META_INCLUDED
#include "LightweightShaderLibrary/InputSurface.hlsl"
#include "LightweightShaderLibrary/Lighting.hlsl"
#include "LWRP/ShaderLibrary/InputSurface.hlsl"
#include "LWRP/ShaderLibrary/Lighting.hlsl"
CBUFFER_START(UnityMetaPass)
// x = use uv1 as raster position

2
ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/LightweightPassShadow.hlsl


#ifndef LIGHTWEIGHT_PASS_SHADOW_INCLUDED
#define LIGHTWEIGHT_PASS_SHADOW_INCLUDED
#include "LightweightShaderLibrary/Core.hlsl"
#include "LWRP/ShaderLibrary/Core.hlsl"
// x: global clip space bias, y: normal world space bias
float4 _ShadowBias;

4
ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/InputBuiltin.hlsl


#ifndef LIGHTWEIGHT_SHADER_VARIABLES_INCLUDED
#define LIGHTWEIGHT_SHADER_VARIABLES_INCLUDED
#if (defined(SHADER_API_D3D11) || defined(SHADER_API_PSSL)) && defined(STEREO_INSTANCING_ON)
#define UNITY_STEREO_INSTANCING_ENABLED
#endif
#if defined(UNITY_SINGLE_PASS_STEREO) || defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED)
#define USING_STEREO_MATRICES
#endif

33
ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Shadows.hlsl


return SampleShadowmap(shadowCoord);
}
half MixRealtimeAndBakedOcclusion(half realtimeAttenuation, half4 bakedOcclusion, half4 distanceAttenuation)
half MixRealtimeAndBakedOcclusion(half realtimeAttenuation, half subtractiveModeBakedOcclusion, half4 shadowMaskModeBakedOcclusion = half4(0, 0, 0, 0))
{
#if defined(LIGHTMAP_ON)
#if defined(_MIXED_LIGHTING_SHADOWMASK)

// We need to remove direct realtime contribution from mixed lights
// distanceAttenuation.w is set 0.0 if this light is mixed, 1.0 otherwise.
return realtimeAttenuation * distanceAttenuation.w;
// subtractiveModeBakedOcclusion is set 0.0 if this light occlusion was baked in the lightmap, 1.0 otherwise.
return realtimeAttenuation * subtractiveModeBakedOcclusion;
}
inline half3 SubtractDirectMainLightFromLightmap(half3 lightmap, half attenuation, half3 lambert)
{
// Let's try to make realtime shadows work on a surface, which already contains
// baked lighting and shadowing from the main sun light.
// Summary:
// 1) Calculate possible value in the shadow by subtracting estimated light contribution from the places occluded by realtime shadow:
// a) preserves other baked lights and light bounces
// b) eliminates shadows on the geometry facing away from the light
// 2) Clamp against user defined ShadowColor.
// 3) Pick original lightmap value, if it is the darkest one.
// 1) Gives good estimate of illumination as if light would've been shadowed during the bake.
// Preserves bounce and other baked lights
// No shadows on the geometry facing away from the light
half shadowStrength = _ShadowData.x;
half3 estimatedLightContributionMaskedByInverseOfShadow = lambert * (1.0 - attenuation);
half3 subtractedLightmap = lightmap - estimatedLightContributionMaskedByInverseOfShadow;
// 2) Allows user to define overall ambient of the scene and control situation when realtime shadow becomes too dark.
half3 realtimeShadow = max(subtractedLightmap, _SubtractiveShadowColor.xyz);
realtimeShadow = lerp(lightmap, realtimeShadow, shadowStrength);
// 3) Pick darkest color
return min(lightmap, realtimeShadow);
}
#endif

8
ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary.meta


fileFormatVersion: 2
guid: 2de5b472450204ae2853db2cb6a2540a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

584
ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Lighting.hlsl


#ifndef LIGHTWEIGHT_LIGHTING_INCLUDED
#define LIGHTWEIGHT_LIGHTING_INCLUDED
#include "CoreRP/ShaderLibrary/Common.hlsl"
#include "CoreRP/ShaderLibrary/EntityLighting.hlsl"
#include "CoreRP/ShaderLibrary/ImageBasedLighting.hlsl"
#include "Core.hlsl"
#include "Shadows.hlsl"
#ifdef NO_ADDITIONAL_LIGHTS
#undef _ADDITIONAL_LIGHTS
#endif
// If lightmap is not defined than we evaluate GI (ambient + probes) from SH
// We might do it fully or partially in vertex to save shader ALU
#if !defined(LIGHTMAP_ON)
#ifdef SHADER_API_GLES
// Evaluates SH fully in vertex
#define EVALUATE_SH_VERTEX
#else
// Evaluates L2 SH in vertex and L0L1 in pixel
#define EVALUATE_SH_MIXED
#endif
#endif
#ifdef LIGHTMAP_ON
#define OUTPUT_LIGHTMAP_UV(lightmapUV, lightmapScaleOffset, OUT) OUT.xy = lightmapUV.xy * lightmapScaleOffset.xy + lightmapScaleOffset.zw;
#define OUTPUT_SH(normalWS, OUT)
#else
#define OUTPUT_LIGHTMAP_UV(lightmapUV, lightmapScaleOffset, OUT)
#define OUTPUT_SH(normalWS, OUT) OUT.xyz = SampleSHVertex(normalWS)
#endif
///////////////////////////////////////////////////////////////////////////////
// Light Helpers //
///////////////////////////////////////////////////////////////////////////////
// Abstraction over Light input constants
struct LightInput
{
float4 position;
half3 color;
half4 distanceAttenuation;
half4 spotDirection;
half4 spotAttenuation;
};
// Abstraction over Light shading data.
struct Light
{
half3 direction;
half3 color;
half attenuation;
half realtimeAttenuation;
};
///////////////////////////////////////////////////////////////////////////////
// Attenuation Functions /
///////////////////////////////////////////////////////////////////////////////
half CookieAttenuation(float3 worldPos)
{
#ifdef _MAIN_LIGHT_COOKIE
#ifdef _MAIN_LIGHT_DIRECTIONAL
float2 cookieUV = mul(_WorldToLight, float4(worldPos, 1.0)).xy;
return SAMPLE_TEXTURE2D(_MainLightCookie, sampler_MainLightCookie, cookieUV).a;
#elif defined(_MAIN_LIGHT_SPOT)
float4 projPos = mul(_WorldToLight, float4(worldPos, 1.0));
float2 cookieUV = projPos.xy / projPos.w + 0.5;
return SAMPLE_TEXTURE2D(_MainLightCookie, sampler_MainLightCookie, cookieUV).a;
#endif // POINT LIGHT cookie not supported
#endif
return 1;
}
// Matches Unity Vanila attenuation
// Attenuation smoothly decreases to light range.
half DistanceAttenuation(half distanceSqr, half3 distanceAttenuation)
{
// We use a shared distance attenuation for additional directional and puctual lights
// for directional lights attenuation will be 1
half quadFalloff = distanceAttenuation.x;
half denom = distanceSqr * quadFalloff + 1.0;
half lightAtten = 1.0 / denom;
// We need to smoothly fade attenuation to light range. We start fading linearly at 80% of light range
// Therefore:
// fadeDistance = (0.8 * 0.8 * lightRangeSq)
// smoothFactor = (lightRangeSqr - distanceSqr) / (lightRangeSqr - fadeDistance)
// We can rewrite that to fit a MAD by doing
// distanceSqr * (1.0 / (fadeDistanceSqr - lightRangeSqr)) + (-lightRangeSqr / (fadeDistanceSqr - lightRangeSqr)
// distanceSqr * distanceAttenuation.y + distanceAttenuation.z
half smoothFactor = saturate(distanceSqr * distanceAttenuation.y + distanceAttenuation.z);
return lightAtten * smoothFactor;
}
half SpotAttenuation(half3 spotDirection, half3 lightDirection, half4 spotAttenuation)
{
// Spot Attenuation with a linear falloff can be defined as
// (SdotL - cosOuterAngle) / (cosInnerAngle - cosOuterAngle)
// This can be rewritten as
// invAngleRange = 1.0 / (cosInnerAngle - cosOuterAngle)
// SdotL * invAngleRange + (-cosOuterAngle * invAngleRange)
// SdotL * spotAttenuation.x + spotAttenuation.y
// If we precompute the terms in a MAD instruction
half SdotL = dot(spotDirection, lightDirection);
half atten = saturate(SdotL * spotAttenuation.x + spotAttenuation.y);
return atten * atten;
}
half4 GetLightDirectionAndRealtimeAttenuation(LightInput lightInput, float3 positionWS)
{
half4 directionAndAttenuation;
float3 posToLightVec = lightInput.position.xyz - positionWS * lightInput.position.w;
float distanceSqr = max(dot(posToLightVec, posToLightVec), FLT_MIN);
directionAndAttenuation.xyz = half3(posToLightVec * rsqrt(distanceSqr));
directionAndAttenuation.w = DistanceAttenuation(distanceSqr, lightInput.distanceAttenuation.xyz);
directionAndAttenuation.w *= SpotAttenuation(lightInput.spotDirection.xyz, directionAndAttenuation.xyz, lightInput.spotAttenuation);
return directionAndAttenuation;
}
half4 GetMainLightDirectionAndRealtimeAttenuation(LightInput lightInput, float3 positionWS)
{
half4 directionAndAttenuation;
#if defined(_MAIN_LIGHT_DIRECTIONAL)
directionAndAttenuation = half4(lightInput.position.xyz, 1.0);
#else
directionAndAttenuation = GetLightDirectionAndRealtimeAttenuation(lightInput, positionWS);
#endif
// Cookies and shadows are only computed for main light
directionAndAttenuation.w *= CookieAttenuation(positionWS);
directionAndAttenuation.w *= RealtimeShadowAttenuation(positionWS);
return directionAndAttenuation;
}
///////////////////////////////////////////////////////////////////////////////
// Light Abstraction //
///////////////////////////////////////////////////////////////////////////////
Light GetMainLight(float3 positionWS)
{
LightInput lightInput;
lightInput.position = _MainLightPosition;
lightInput.color = _MainLightColor.rgb;
lightInput.distanceAttenuation = _MainLightDistanceAttenuation;
lightInput.spotDirection = _MainLightSpotDir;
lightInput.spotAttenuation = _MainLightSpotAttenuation;
half4 directionAndRealtimeAttenuation = GetMainLightDirectionAndRealtimeAttenuation(lightInput, positionWS);
Light light;
light.direction = directionAndRealtimeAttenuation.xyz;
light.realtimeAttenuation = directionAndRealtimeAttenuation.w;
light.attenuation = MixRealtimeAndBakedOcclusion(light.realtimeAttenuation, lightInput.distanceAttenuation.w);
light.color = lightInput.color;
return light;
}
Light GetLight(int i, float3 positionWS)
{
LightInput lightInput;
half4 indices = (i < 4) ? unity_4LightIndices0 : unity_4LightIndices1;
int index = (i < 4) ? i : i - 4;
int lightIndex = indices[index];
lightInput.position = _AdditionalLightPosition[lightIndex];
lightInput.color = _AdditionalLightColor[lightIndex].rgb;
lightInput.distanceAttenuation = _AdditionalLightDistanceAttenuation[lightIndex];
lightInput.spotDirection = _AdditionalLightSpotDir[lightIndex];
lightInput.spotAttenuation = _AdditionalLightSpotAttenuation[lightIndex];
half4 directionAndRealtimeAttenuation = GetLightDirectionAndRealtimeAttenuation(lightInput, positionWS);
Light light;
light.direction = directionAndRealtimeAttenuation.xyz;
light.realtimeAttenuation = directionAndRealtimeAttenuation.w;
light.attenuation = MixRealtimeAndBakedOcclusion(light.realtimeAttenuation, lightInput.distanceAttenuation.w);
light.color = lightInput.color;
return light;
}
half GetPixelLightCount()
{
return min(_AdditionalLightCount.x, unity_LightIndicesOffsetAndCount.y);
}
///////////////////////////////////////////////////////////////////////////////
// BRDF Functions //
///////////////////////////////////////////////////////////////////////////////
#define kDieletricSpec half4(0.04, 0.04, 0.04, 1.0 - 0.04) // standard dielectric reflectivity coef at incident angle (= 4%)
struct BRDFData
{
half3 diffuse;
half3 specular;
half perceptualRoughness;
half roughness;
half roughness2;
half grazingTerm;
};
half ReflectivitySpecular(half3 specular)
{
#if (SHADER_TARGET < 30)
// SM2.0: instruction count limitation
return specular.r; // Red channel - because most metals are either monocrhome or with redish/yellowish tint
#else
return max(max(specular.r, specular.g), specular.b);
#endif
}
half OneMinusReflectivityMetallic(half metallic)
{
// We'll need oneMinusReflectivity, so
// 1-reflectivity = 1-lerp(dielectricSpec, 1, metallic) = lerp(1-dielectricSpec, 0, metallic)
// store (1-dielectricSpec) in kDieletricSpec.a, then
// 1-reflectivity = lerp(alpha, 0, metallic) = alpha + metallic*(0 - alpha) =
// = alpha - metallic * alpha
half oneMinusDielectricSpec = kDieletricSpec.a;
return oneMinusDielectricSpec - metallic * oneMinusDielectricSpec;
}
inline void InitializeBRDFData(half3 albedo, half metallic, half3 specular, half smoothness, half alpha, out BRDFData outBRDFData)
{
#ifdef _SPECULAR_SETUP
half reflectivity = ReflectivitySpecular(specular);
half oneMinusReflectivity = 1.0 - reflectivity;
outBRDFData.diffuse = albedo * (half3(1.0h, 1.0h, 1.0h) - specular);
outBRDFData.specular = specular;
#else
half oneMinusReflectivity = OneMinusReflectivityMetallic(metallic);
half reflectivity = 1.0 - oneMinusReflectivity;
outBRDFData.diffuse = albedo * oneMinusReflectivity;
outBRDFData.specular = lerp(kDieletricSpec.rgb, albedo, metallic);
#endif
outBRDFData.grazingTerm = saturate(smoothness + reflectivity);
outBRDFData.perceptualRoughness = PerceptualSmoothnessToPerceptualRoughness(smoothness);
outBRDFData.roughness = PerceptualRoughnessToRoughness(outBRDFData.perceptualRoughness);
outBRDFData.roughness2 = outBRDFData.roughness * outBRDFData.roughness;
#ifdef _ALPHAPREMULTIPLY_ON
outBRDFData.diffuse *= alpha;
alpha = alpha * oneMinusReflectivity + reflectivity;
#endif
}
half3 EnvironmentBRDF(BRDFData brdfData, half3 indirectDiffuse, half3 indirectSpecular, half fresnelTerm)
{
half3 c = indirectDiffuse * brdfData.diffuse;
float surfaceReduction = 1.0 / (brdfData.roughness2 + 1.0);
c += surfaceReduction * indirectSpecular * lerp(brdfData.specular, brdfData.grazingTerm, fresnelTerm);
return c;
}
// Based on Minimalist CookTorrance BRDF
// Implementation is slightly different from original derivation: http://www.thetenthplanet.de/archives/255
//
// * NDF [Modified] GGX
// * Modified Kelemen and Szirmay-​Kalos for Visibility term
// * Fresnel approximated with 1/LdotH
half3 DirectBDRF(BRDFData brdfData, half3 normalWS, half3 lightDirectionWS, half3 viewDirectionWS)
{
#ifndef _SPECULARHIGHLIGHTS_OFF
half3 halfDir = SafeNormalize(lightDirectionWS + viewDirectionWS);
half NoH = saturate(dot(normalWS, halfDir));
half LoH = saturate(dot(lightDirectionWS, halfDir));
// GGX Distribution multiplied by combined approximation of Visibility and Fresnel
// See "Optimizing PBR for Mobile" from Siggraph 2015 moving mobile graphics course
// https://community.arm.com/events/1155
half d = NoH * NoH * (brdfData.roughness2 - 1.h) + 1.00001h;
half LoH2 = LoH * LoH;
half specularTerm = brdfData.roughness2 / ((d * d) * max(0.1h, LoH2) * (brdfData.roughness + 0.5h) * 4);
// on mobiles (where half actually means something) denominator have risk of overflow
// clamp below was added specifically to "fix" that, but dx compiler (we convert bytecode to metal/gles)
// sees that specularTerm have only non-negative terms, so it skips max(0,..) in clamp (leaving only min(100,...))
#if defined (SHADER_API_MOBILE)
specularTerm = specularTerm - HALF_MIN;
specularTerm = clamp(specularTerm, 0.0, 100.0); // Prevent FP16 overflow on mobiles
#endif
half3 color = specularTerm * brdfData.specular + brdfData.diffuse;
return color;
#else
return brdfData.diffuse;
#endif
}
///////////////////////////////////////////////////////////////////////////////
// Global Illumination //
///////////////////////////////////////////////////////////////////////////////
// Samples SH L0, L1 and L2 terms
half3 SampleSH(half3 normalWS)
{
// LPPV is not supported in Ligthweight Pipeline
real4 SHCoefficients[7];
SHCoefficients[0] = unity_SHAr;
SHCoefficients[1] = unity_SHAg;
SHCoefficients[2] = unity_SHAb;
SHCoefficients[3] = unity_SHBr;
SHCoefficients[4] = unity_SHBg;
SHCoefficients[5] = unity_SHBb;
SHCoefficients[6] = unity_SHC;
return max(half3(0, 0, 0), SampleSH9(SHCoefficients, normalWS));
}
// SH Vertex Evaluation. Depending on target SH sampling might be
// done completely per vertex or mixed with L2 term per vertex and L0, L1
// per pixel. See SampleSHPixel
half3 SampleSHVertex(half3 normalWS)
{
#if defined(EVALUATE_SH_VERTEX)
return max(half3(0, 0, 0), SampleSH(normalWS));
#elif defined(EVALUATE_SH_MIXED)
// no max since this is only L2 contribution
return SHEvalLinearL2(normalWS, unity_SHBr, unity_SHBg, unity_SHBb, unity_SHC);
#endif
// Fully per-pixel. Nothing to compute.
return half3(0.0, 0.0, 0.0);
}
// SH Pixel Evaluation. Depending on target SH sampling might be done
// mixed or fully in pixel. See SampleSHVertex
half3 SampleSHPixel(half3 L2Term, half3 normalWS)
{
#ifdef EVALUATE_SH_MIXED
half3 L0L1Term = SHEvalLinearL0L1(normalWS, unity_SHAr, unity_SHAg, unity_SHAb);
return max(half3(0, 0, 0), L2Term + L0L1Term);
#endif
// Default: Evaluate SH fully per-pixel
return SampleSH(normalWS);
}
// Sample baked lightmap. Non-Direction and Directional if available.
// Realtime GI is not supported.
half3 SampleLightmap(float2 lightmapUV, half3 normalWS)
{
#ifdef UNITY_LIGHTMAP_FULL_HDR
bool encodedLightmap = false;
#else
bool encodedLightmap = true;
#endif
// The shader library sample lightmap functions transform the lightmap uv coords to apply bias and scale.
// However, lightweight pipeline already transformed those coords in vertex. We pass half4(1, 1, 0, 0) and
// the compiler will optimize the transform away.
half4 transformCoords = half4(1, 1, 0, 0);
#ifdef DIRLIGHTMAP_COMBINED
return SampleDirectionalLightmap(TEXTURE2D_PARAM(unity_Lightmap, samplerunity_Lightmap),
TEXTURE2D_PARAM(unity_LightmapInd, samplerunity_Lightmap),
lightmapUV, transformCoords, normalWS, encodedLightmap);
#else
return SampleSingleLightmap(TEXTURE2D_PARAM(unity_Lightmap, samplerunity_Lightmap), lightmapUV, transformCoords, encodedLightmap);
#endif
}
// We either sample GI from baked lightmap or from probes.
// If lightmap: sampleData.xy = lightmapUV
// If probe: sampleData.xyz = L2 SH terms
half3 SampleGI(float4 sampleData, half3 normalWS)
{
#ifdef LIGHTMAP_ON
return SampleLightmap(sampleData.xy, normalWS);
#endif
// If lightmap is not enabled we sample GI from SH
return SampleSHPixel(sampleData.xyz, normalWS);
}
half3 GlossyEnvironmentReflection(half3 reflectVector, half perceptualRoughness, half occlusion)
{
#if !defined(_GLOSSYREFLECTIONS_OFF)
half mip = PerceptualRoughnessToMipmapLevel(perceptualRoughness);
half4 encodedIrradiance = SAMPLE_TEXTURECUBE_LOD(unity_SpecCube0, samplerunity_SpecCube0, reflectVector, mip);
#if !defined(UNITY_USE_NATIVE_HDR)
half3 irradiance = DecodeHDREnvironment(encodedIrradiance, unity_SpecCube0_HDR);
#else
half3 irradiance = encodedIrradiance.rbg;
#endif
return irradiance * occlusion;
#endif // GLOSSY_REFLECTIONS
return _GlossyEnvironmentColor.rgb * occlusion;
}
half3 SubtractDirectMainLightFromLightmap(Light mainLight, half3 normalWS, half3 bakedGI)
{
#if defined(_MAIN_LIGHT_DIRECTIONAL) && defined(_MIXED_LIGHTING_SUBTRACTIVE) && defined(LIGHTMAP_ON) && defined(_SHADOWS_ENABLED)
// Let's try to make realtime shadows work on a surface, which already contains
// baked lighting and shadowing from the main sun light.
// Summary:
// 1) Calculate possible value in the shadow by subtracting estimated light contribution from the places occluded by realtime shadow:
// a) preserves other baked lights and light bounces
// b) eliminates shadows on the geometry facing away from the light
// 2) Clamp against user defined ShadowColor.
// 3) Pick original lightmap value, if it is the darkest one.
// 1) Gives good estimate of illumination as if light would've been shadowed during the bake.
// Preserves bounce and other baked lights
// No shadows on the geometry facing away from the light
half shadowStrength = _ShadowData.x;
half NdotL = saturate(dot(mainLight.direction, normalWS));
half3 lambert = mainLight.color * NdotL;
half3 estimatedLightContributionMaskedByInverseOfShadow = lambert * (1.0 - mainLight.realtimeAttenuation);
half3 subtractedLightmap = bakedGI - estimatedLightContributionMaskedByInverseOfShadow;
// 2) Allows user to define overall ambient of the scene and control situation when realtime shadow becomes too dark.
half3 realtimeShadow = max(subtractedLightmap, _SubtractiveShadowColor.xyz);
realtimeShadow = lerp(bakedGI, realtimeShadow, shadowStrength);
// 3) Pick darkest color
return min(bakedGI, realtimeShadow);
#endif
return bakedGI;
}
half3 GlobalIllumination(BRDFData brdfData, half3 bakedGI, half occlusion, half3 normalWS, half3 viewDirectionWS)
{
half3 reflectVector = reflect(-viewDirectionWS, normalWS);
half fresnelTerm = Pow4(1.0 - saturate(dot(normalWS, viewDirectionWS)));
half3 indirectDiffuse = bakedGI * occlusion;
half3 indirectSpecular = GlossyEnvironmentReflection(reflectVector, brdfData.perceptualRoughness, occlusion);
return EnvironmentBRDF(brdfData, indirectDiffuse, indirectSpecular, fresnelTerm);
}
///////////////////////////////////////////////////////////////////////////////
// Lighting Functions //
///////////////////////////////////////////////////////////////////////////////
half3 LightingLambert(half3 lightColor, half3 lightDir, half3 normal)
{
half NdotL = saturate(dot(normal, lightDir));
return lightColor * NdotL;
}
half3 LightingSpecular(half3 lightColor, half3 lightDir, half3 normal, half3 viewDir, half4 specularGloss, half shininess)
{
half3 halfVec = SafeNormalize(lightDir + viewDir);
half NdotH = saturate(dot(normal, halfVec));
half3 specularReflection = specularGloss.rgb * pow(NdotH, shininess) * specularGloss.a;
return lightColor * specularReflection;
}
half3 LightingPhysicallyBased(BRDFData brdfData, half3 lightColor, half3 lightDirectionWS, half lightAttenuation, half3 normalWS, half3 viewDirectionWS)
{
half NdotL = saturate(dot(normalWS, lightDirectionWS));
half3 radiance = lightColor * (lightAttenuation * NdotL);
return DirectBDRF(brdfData, normalWS, lightDirectionWS, viewDirectionWS) * radiance;
}
half3 LightingPhysicallyBased(BRDFData brdfData, Light light, half3 normalWS, half3 viewDirectionWS)
{
return LightingPhysicallyBased(brdfData, light.color, light.direction, light.attenuation, normalWS, viewDirectionWS);
}
half3 VertexLighting(float3 positionWS, half3 normalWS)
{
half3 vertexLightColor = half3(0.0, 0.0, 0.0);
#if defined(_VERTEX_LIGHTS)
int vertexLightStart = _AdditionalLightCount.x;
int vertexLightEnd = min(_AdditionalLightCount.y, unity_LightIndicesOffsetAndCount.y);
for (int lightIter = vertexLightStart; lightIter < vertexLightEnd; ++lightIter)
{
Light light = GetLight(lightIter, positionWS);
half3 lightColor = light.color * light.realtimeAttenuation;
vertexLightColor += LightingLambert(lightColor, light.direction, normalWS);
}
#endif
return vertexLightColor;
}
///////////////////////////////////////////////////////////////////////////////
// Fragment Functions //
// Used by ShaderGraph and others builtin renderers //
///////////////////////////////////////////////////////////////////////////////
half4 LightweightFragmentPBR(float3 positionWS, half3 normalWS, half3 viewDirectionWS,
half3 bakedGI, half3 vertexLighting, half3 albedo, half metallic, half3 specular,
half smoothness, half occlusion, half3 emission, half alpha)
{
BRDFData brdfData;
InitializeBRDFData(albedo, metallic, specular, smoothness, alpha, brdfData);
Light mainLight = GetMainLight(positionWS);
bakedGI = SubtractDirectMainLightFromLightmap(mainLight, normalWS, bakedGI);
half3 color = GlobalIllumination(brdfData, bakedGI, occlusion, normalWS, viewDirectionWS);
color += LightingPhysicallyBased(brdfData, mainLight, normalWS, viewDirectionWS);
#ifdef _ADDITIONAL_LIGHTS
int pixelLightCount = GetPixelLightCount();
for (int i = 0; i < pixelLightCount; ++i)
{
Light light = GetLight(i, positionWS);
color += LightingPhysicallyBased(brdfData, light, normalWS, viewDirectionWS);
}
#endif
color += vertexLighting * brdfData.diffuse;
color += emission;
return half4(color, alpha);
}
half4 LightweightFragmentLambert(float3 positionWS, half3 normalWS, half3 viewDirectionWS,
half fogFactor, half3 bakedGI, half3 diffuse, half3 emission, half alpha)
{
half3 lightDirection;
Light mainLight = GetMainLight(positionWS);
half3 indirectDiffuse = SubtractDirectMainLightFromLightmap(mainLight, normalWS, bakedGI);
half3 lambert = LightingLambert(mainLight.color, mainLight.direction, normalWS);
half3 diffuseColor = lambert * mainLight.attenuation + indirectDiffuse;
#ifdef _ADDITIONAL_LIGHTS
int pixelLightCount = GetPixelLightCount();
for (int i = 0; i < pixelLightCount; ++i)
{
Light light = GetLight(i, positionWS);
half3 attenuatedLightColor = light.color * light.attenuation;
diffuseColor += LightingLambert(attenuatedLightColor, lightDirection, normalWS);
}
#endif
half3 finalColor = diffuseColor * diffuse + emission;
ApplyFog(finalColor, fogFactor);
return half4(finalColor, alpha);
}
half4 LightweightFragmentBlinnPhong(float3 positionWS, half3 normalWS, half3 viewDirectionWS,
half fogFactor, half3 bakedGI, half3 diffuse, half4 specularGloss, half shininess, half3 emission, half alpha)
{
half3 lightDirection;
Light mainLight = GetMainLight(positionWS);
half3 indirectDiffuse = SubtractDirectMainLightFromLightmap(mainLight, normalWS, bakedGI);
half3 attenuatedLightColor = mainLight.color * mainLight.attenuation;
half3 diffuseColor = indirectDiffuse + LightingLambert(attenuatedLightColor, mainLight.direction, normalWS);
half3 specularColor = LightingSpecular(attenuatedLightColor, mainLight.direction, normalWS, viewDirectionWS, specularGloss, shininess);
#ifdef _ADDITIONAL_LIGHTS
int pixelLightCount = GetPixelLightCount();
for (int i = 0; i < pixelLightCount; ++i)
{
Light light = GetLight(i, positionWS);
half3 attenuatedLightColor = light.color * light.attenuation;
diffuseColor += LightingLambert(attenuatedLightColor, light.direction, normalWS);
specularColor += LightingSpecular(attenuatedLightColor, light.direction, normalWS, viewDirectionWS, specularGloss, shininess);
}
#endif
half3 finalColor = diffuseColor * diffuse + emission;
finalColor += specularColor;
ApplyFog(finalColor, fogFactor);
return half4(finalColor, alpha);
}
#endif

8
ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightShaderLibrary.meta


fileFormatVersion: 2
guid: 2de5b472450204ae2853db2cb6a2540a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

/ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightPassLit.hlsl → /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/LightweightPassLit.hlsl

/ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightPassMeta.hlsl → /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/LightweightPassMeta.hlsl

/ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightPassShadow.hlsl → /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/LightweightPassShadow.hlsl

/ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightPassShadow.hlsl.meta → /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/LightweightPassShadow.hlsl.meta

/ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightPassMeta.hlsl.meta → /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/LightweightPassMeta.hlsl.meta

/ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightPassLit.hlsl.meta → /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/LightweightPassLit.hlsl.meta

/ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightShaderLibrary/CoreFunctions.hlsl → /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/CoreFunctions.hlsl

/ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightShaderLibrary/CoreFunctions.hlsl.meta → /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/CoreFunctions.hlsl.meta

/ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightShaderLibrary/Input.hlsl → /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Input.hlsl

/ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightShaderLibrary/InputBuiltin.hlsl.meta → /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/InputBuiltin.hlsl.meta

/ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightShaderLibrary/Particles.hlsl.meta → /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Particles.hlsl.meta

/ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightShaderLibrary/Shadows.hlsl.meta → /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Shadows.hlsl.meta

/ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightShaderLibrary/Lighting.hlsl.meta → /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Lighting.hlsl.meta

/ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightShaderLibrary/InputSurface.hlsl.meta → /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/InputSurface.hlsl.meta

/ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightShaderLibrary/Input.hlsl.meta → /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Input.hlsl.meta

/ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightShaderLibrary/Core.hlsl.meta → /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Core.hlsl.meta

/ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightShaderLibrary/InputBuiltin.hlsl → /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/InputBuiltin.hlsl

/ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightShaderLibrary/InputSurface.hlsl → /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/InputSurface.hlsl

/ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightShaderLibrary/Shadows.hlsl → /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Shadows.hlsl

/ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightShaderLibrary/Particles.hlsl → /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Particles.hlsl

/ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightShaderLibrary/Core.hlsl → /ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Core.hlsl

正在加载...
取消
保存