浏览代码

Combined shadow and light classification keywords to reduce shader variantions by ~30%.

/feature-ReflectionProbeFit
Felipe Lira 7 年前
当前提交
bb237480
共有 8 个文件被更改,包括 147 次插入50 次删除
  1. 77
      ScriptableRenderPipeline/LightweightPipeline/LWRP/LightweightPipeline.cs
  2. 22
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightShaderLibrary/Core.hlsl
  3. 10
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightShaderLibrary/Lighting.hlsl
  4. 39
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightShaderLibrary/Shadows.hlsl
  5. 17
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightStandard.shader
  6. 7
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightStandardParticles.shader
  7. 18
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightStandardSimpleLighting.shader
  8. 7
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightStandardTerrain.shader

77
ScriptableRenderPipeline/LightweightPipeline/LWRP/LightweightPipeline.cs


using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using UnityEngine.Experimental.GlobalIllumination;
using UnityEngine.Rendering;
using UnityEngine.Rendering.PostProcessing;

public int pixelAdditionalLightsCount;
public int totalAdditionalLightsCount;
public int mainLightIndex;
public bool shadowsRendered;
public LightShadows shadowMapSampleType;
}
public enum MixedLightingSetup

// There's no way to map shadow light indices. We need to pass in the original unsorted index.
// If no additional lights then no light sorting is performed and the indices match.
int shadowOriginalIndex = (lightData.totalAdditionalLightsCount > 0) ? GetLightUnsortedIndex(lightData.mainLightIndex) : lightData.mainLightIndex;
lightData.shadowsRendered = RenderShadows(ref m_CullResults, ref mainLight,
bool shadowsRendered = RenderShadows(ref m_CullResults, ref mainLight,
if (shadowsRendered)
{
lightData.shadowMapSampleType = (m_Asset.ShadowSetting != ShadowType.SOFT_SHADOWS)
? LightShadows.Hard
: mainLight.light.shadows;
}
else
{
lightData.shadowMapSampleType = LightShadows.None;
}
}
}
}

int visibleLightsCount = Math.Min(visibleLights.Length, m_Asset.MaxPixelLights);
m_SortedLightIndexMap.Clear();
lightData.shadowsRendered = false;
lightData.shadowMapSampleType = LightShadows.None;
if (visibleLightsCount <= 1)
lightData.mainLightIndex = GetMainLight(visibleLights);

if (currLight.light == null)
break;
// Shadow lights are sorted by type (directional > puctual) and intensity
// The first shadow light we find in the list is the main light
// In case no shadow light is present we will return the brightest directional light
if (currLight.lightType == LightType.Directional && brighestDirectionalIndex == -1)
brighestDirectionalIndex = i;
}

// Main light has an optimized shader path for main light. This will benefit games that only care about a single light.
// Lightweight pipeline also supports only a single shadow light, if available it will be the main light.
SetupMainLightConstants(cmd, lights, lightData.mainLightIndex);
if (lightData.shadowsRendered)
if (lightData.shadowMapSampleType != LightShadows.None)
SetupShadowShaderConstants(cmd, ref lights[lightData.mainLightIndex], m_ShadowCasterCascadesCount);
if (lightData.totalAdditionalLightsCount > 0)

private void SetShaderKeywords(CommandBuffer cmd, ref LightData lightData, VisibleLight[] visibleLights)
{
int vertexLightsCount = lightData.totalAdditionalLightsCount - lightData.pixelAdditionalLightsCount;
CoreUtils.SetKeyword(cmd, "_VERTEX_LIGHTS", vertexLightsCount > 0);
int mainLightIndex = lightData.mainLightIndex;
int mainLightIndex = lightData.mainLightIndex;
// We have no good approach exposed to skip shader variants, e.g, ideally we would like to skip _CASCADE for all puctual lights
// We combine light and shadow classification keywords to reduce the amount of shader variants.
// Lightweight shader library declares defines based on these keywords to make avoid having to check them in the shaders
// Core.hlsl defines _MAIN_LIGHT_DIRECTIONAL and _MAIN_LIGHT_SPOT (point lights can't be main light)
// Shadow.hlsl defines _SHADOWS_ENABLED, _SHADOWS_SOFT, _SHADOWS_CASCADE, _SHADOWS_PERSPECTIVE
string[] mainLightKeywords =
{
"_MAIN_LIGHT_DIRECTIONAL_SHADOW",
"_MAIN_LIGHT_DIRECTIONAL_SHADOW_CASCADE",
"_MAIN_LIGHT_DIRECTIONAL_SHADOW_SOFT",
"_MAIN_LIGHT_DIRECTIONAL_SHADOW_CASCADE_SOFT",
CoreUtils.SetKeyword(cmd, "_MAIN_LIGHT_COOKIE", mainLightIndex != -1 && LightweightUtils.IsSupportedCookieType(visibleLights[mainLightIndex].lightType) && visibleLights[mainLightIndex].light.cookie != null);
CoreUtils.SetKeyword(cmd, "_MAIN_DIRECTIONAL_LIGHT", mainLightIndex == -1 || visibleLights[mainLightIndex].lightType == LightType.Directional);
CoreUtils.SetKeyword(cmd, "_MAIN_SPOT_LIGHT", mainLightIndex != -1 && visibleLights[mainLightIndex].lightType == LightType.Spot);
CoreUtils.SetKeyword(cmd, "_ADDITIONAL_LIGHTS", lightData.totalAdditionalLightsCount > 0);
CoreUtils.SetKeyword(cmd, "_MIXED_LIGHTING_SHADOWMASK", m_MixedLightingSetup == MixedLightingSetup.ShadowMask);
CoreUtils.SetKeyword(cmd, "_MIXED_LIGHTING_SUBTRACTIVE", m_MixedLightingSetup == MixedLightingSetup.Subtractive);
"_MAIN_LIGHT_SPOT_SHADOW",
"_MAIN_LIGHT_SPOT_SHADOW_SOFT"
};
string[] shadowKeywords = new string[] { "_HARD_SHADOWS", "_SOFT_SHADOWS", "_HARD_SHADOWS_CASCADES", "_SOFT_SHADOWS_CASCADES" };
for (int i = 0; i < shadowKeywords.Length; ++i)
cmd.DisableShaderKeyword(shadowKeywords[i]);
for (int i = 0; i < mainLightKeywords.Length; ++i)
cmd.DisableShaderKeyword(mainLightKeywords[i]);
if (m_Asset.AreShadowsEnabled() && lightData.shadowsRendered)
if (mainLightIndex != -1 && (lightData.shadowMapSampleType != LightShadows.None))
int keywordIndex = (int)m_Asset.ShadowSetting - 1;
if (m_Asset.CascadeCount > 1)
keywordIndex += 2;
cmd.EnableShaderKeyword(shadowKeywords[keywordIndex]);
StringBuilder keywordString = new StringBuilder("_MAIN_LIGHT");
LightType mainLightType = visibleLights[mainLightIndex].lightType;
if (mainLightType == LightType.Directional)
{
keywordString.Append("_DIRECTIONAL_SHADOW");
if (m_Asset.CascadeCount > 1)
keywordString.Append("_CASCADE");
}
else
{
keywordString.Append("_SPOT_SHADOW");
}
if (lightData.shadowMapSampleType == LightShadows.Soft)
keywordString.Append("_SOFT");
string keyword = keywordString.ToString();
cmd.EnableShaderKeyword(keyword);
CoreUtils.SetKeyword(cmd, "_MAIN_LIGHT_COOKIE", mainLightIndex != -1 && LightweightUtils.IsSupportedCookieType(visibleLights[mainLightIndex].lightType) && visibleLights[mainLightIndex].light.cookie != null);
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);
}

22
ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightShaderLibrary/Core.hlsl


#include "CoreRP/ShaderLibrary/Packing.hlsl"
#include "Input.hlsl"
///////////////////////////////////////////////////////////////////////////////
// Light Classification defines //
// //
// In order to reduce shader variations main light keywords were combined //
// here we define main light type keywords. //
// Main light is either a shadow casting light or the brighest directional. //
// Lightweight pipeline doesn't support point light shadows so they can't be //
// classified as main light. //
///////////////////////////////////////////////////////////////////////////////
#if defined(_MAIN_LIGHT_DIRECTIONAL_SHADOW) || defined(_MAIN_LIGHT_DIRECTIONAL_SHADOW_CASCADE) || defined(_MAIN_LIGHT_DIRECTIONAL_SHADOW_SOFT) || defined(_MAIN_LIGHT_DIRECTIONAL_SHADOW_CASCADE_SOFT)
#define _MAIN_LIGHT_DIRECTIONAL
#endif
#if defined(_MAIN_LIGHT_SPOT_SHADOW) || defined(_MAIN_LIGHT_SPOT_SHADOW_SOFT)
#define _MAIN_LIGHT_SPOT
#endif
// In case no shadow casting light we classify main light as directional
#if !defined(_MAIN_LIGHT_DIRECTIONAL) && !defined(_MAIN_LIGHT_SPOT)
#define _MAIN_LIGHT_DIRECTIONAL
#endif
#ifdef _NORMALMAP
#define OUTPUT_NORMAL(IN, OUT) OutputTangentToWorld(IN.tangent, IN.normal, OUT.tangent, OUT.binormal, OUT.normal)
#else

10
ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightShaderLibrary/Lighting.hlsl


// If shadows and mixed subtractive mode is enabled we need to remove direct
// light contribution from lightmap from occluded pixels so we can have dynamic objects
// casting shadows onto static correctly.
#if defined(_MIXED_LIGHTING_SUBTRACTIVE) && defined(LIGHTMAP_ON) && defined(_SHADOWS)
#if defined(_MIXED_LIGHTING_SUBTRACTIVE) && defined(LIGHTMAP_ON) && defined(_SHADOWS_ENABLED)
indirectDiffuse = SubtractDirectMainLightFromLightmap(indirectDiffuse, mainLightRealtimeAttenuation, lambert);
#endif

half CookieAttenuation(float3 worldPos)
{
#ifdef _MAIN_LIGHT_COOKIE
#ifdef _MAIN_DIRECTIONAL_LIGHT
#ifdef _MAIN_LIGHT_DIRECTIONAL
#elif defined(_MAIN_SPOT_LIGHT)
#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;

inline half GetMainLightDirectionAndRealtimeAttenuation(LightInput lightInput, half3 normalWS, float3 positionWS, out half3 lightDirection)
{
#ifdef _MAIN_DIRECTIONAL_LIGHT
#if defined(_MAIN_LIGHT_DIRECTIONAL)
// Light pos holds normalized light dir
lightDirection = lightInput.position.xyz;
half attenuation = 1.0;

// Cookies and shadows are only computed for main light
attenuation *= CookieAttenuation(positionWS);
attenuation *= LIGHTWEIGHT_SHADOW_ATTENUATION(positionWS, normalWS, lightDirection);
attenuation *= RealtimeShadowAttenuation(positionWS, normalWS, lightDirection);
return attenuation;
}

39
ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightShaderLibrary/Shadows.hlsl


#define MAX_SHADOW_CASCADES 4
#if defined(_HARD_SHADOWS) || defined(_SOFT_SHADOWS) || defined(_HARD_SHADOWS_CASCADES) || defined(_SOFT_SHADOWS_CASCADES)
#define _SHADOWS
///////////////////////////////////////////////////////////////////////////////
// Light Classification shadow defines //
// //
// In order to reduce shader variations main light keywords were combined //
// here we define shadow keywords. //
///////////////////////////////////////////////////////////////////////////////
#if defined(_MAIN_LIGHT_DIRECTIONAL_SHADOW) || defined(_MAIN_LIGHT_DIRECTIONAL_SHADOW_CASCADE) || defined(_MAIN_LIGHT_DIRECTIONAL_SHADOW_SOFT) || defined(_MAIN_LIGHT_DIRECTIONAL_SHADOW_CASCADE_SOFT) || defined(_MAIN_LIGHT_SPOT_SHADOW) || defined(_MAIN_LIGHT_SPOT_SHADOW_SOFT)
#define _SHADOWS_ENABLED
#if defined(_HARD_SHADOWS_CASCADES) || defined(_SOFT_SHADOWS_CASCADES)
#define _SHADOW_CASCADES
#if defined(_MAIN_LIGHT_DIRECTIONAL_SHADOW_SOFT) || defined(_MAIN_LIGHT_DIRECTIONAL_SHADOW_CASCADE_SOFT) || defined(_MAIN_LIGHT_SPOT_SHADOW_SOFT)
#define _SHADOWS_SOFT
#ifdef _SHADOWS
#define LIGHTWEIGHT_SHADOW_ATTENUATION(posWorld, vertexNormal, shadowDir) ComputeShadowAttenuation(posWorld, vertexNormal, shadowDir)
#else
#define LIGHTWEIGHT_SHADOW_ATTENUATION(posWorld, vertexNormal, shadowDir) 1.0h
#if defined(_MAIN_LIGHT_DIRECTIONAL_SHADOW_CASCADE) || defined(_MAIN_LIGHT_DIRECTIONAL_SHADOW_CASCADE_SOFT)
#define _SHADOWS_CASCADE
#endif
#if defined(_MAIN_LIGHT_SPOT_SHADOW) || defined(_MAIN_LIGHT_SPOT_SHADOW_SOFT)
#define _SHADOWS_PERSPECTIVE
#endif
TEXTURE2D_SHADOW(_ShadowMap);

inline half SampleShadowmap(float4 shadowCoord)
{
#if defined(_SHADOWS_PERSPECTIVE)
#else
float3 coord = shadowCoord.xyz;
#endif
#if defined(_SOFT_SHADOWS) || defined(_SOFT_SHADOWS_CASCADES)
#ifdef _SHADOWS_SOFT
// 4-tap hardware comparison
half4 attenuation;
attenuation.x = SAMPLE_TEXTURE2D_SHADOW(_ShadowMap, sampler_ShadowMap, coord + _ShadowOffset0.xyz);

return 4 - dot(weights, half4(4, 3, 2, 1));
}
inline half ComputeShadowAttenuation(float3 posWorld, half3 vertexNormal, half3 shadowDir)
inline half RealtimeShadowAttenuation(float3 posWorld, half3 vertexNormal, half3 shadowDir)
#if !defined(_SHADOWS_ENABLED)
return 1.0;
#endif
half NdotL = dot(vertexNormal, shadowDir);
half bias = saturate(1.0 - NdotL) * _ShadowData.z;

#ifdef _SHADOW_CASCADES
#ifdef _SHADOWS_CASCADE
cascadeIndex = ComputeCascadeIndex(posWorldOffsetNormal);
if (cascadeIndex >= MAX_SHADOW_CASCADES)
return 1.0;

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


#pragma target 3.0
// -------------------------------------
// Material Keywords
#pragma shader_feature _NORMALMAP
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
#pragma shader_feature _EMISSION

#pragma shader_feature _GLOSSYREFLECTIONS_OFF
#pragma shader_feature _SPECULAR_SETUP
// -------------------------------------
// Lightweight Pipeline keywords
// We have no good approach exposed to skip shader variants, e.g, ideally we would like to skip _CASCADE for all puctual lights
// Lightweight combines light classification and shadows keywords to reduce shader variants.
// Lightweight shader library declares defines based on these keywords to avoid having to check them in the shaders
// Core.hlsl defines _MAIN_LIGHT_DIRECTIONAL and _MAIN_LIGHT_SPOT (point lights can't be main light)
// Shadow.hlsl defines _SHADOWS_ENABLED, _SHADOWS_SOFT, _SHADOWS_CASCADE, _SHADOWS_PERSPECTIVE
#pragma multi_compile _ _MAIN_LIGHT_DIRECTIONAL_SHADOW _MAIN_LIGHT_DIRECTIONAL_SHADOW_CASCADE _MAIN_LIGHT_DIRECTIONAL_SHADOW_SOFT _MAIN_LIGHT_DIRECTIONAL_SHADOW_CASCADE_SOFT _MAIN_LIGHT_SPOT_SHADOW _MAIN_LIGHT_SPOT_SHADOW_SOFT
#pragma multi_compile _MAIN_DIRECTIONAL_LIGHT _MAIN_SPOT_LIGHT
#pragma multi_compile _ _VERTEX_LIGHTS
// -------------------------------------
// Unity defined keywords
#pragma multi_compile _ _HARD_SHADOWS _SOFT_SHADOWS _HARD_SHADOWS_CASCADES _SOFT_SHADOWS_CASCADES
#pragma multi_compile _ _VERTEX_LIGHTS
#pragma multi_compile_fog
#pragma vertex LitPassVertex

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


// No support to Distortion
// No support to Shadows
// ------------------------------------------
// Only directional light is supported for lit particles
// No shadow
// No distortion
Shader "LightweightPipeline/Particles/Standard"
{
Properties

#pragma vertex ParticlesLitVertex
#pragma fragment ParticlesLitFragment
#pragma multi_compile __ SOFTPARTICLES_ON
#pragma multi_compile _MAIN_DIRECTIONAL_LIGHT _MAIN_SPOT_LIGHT
#pragma target 3.5
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON

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


// Required to compile gles 2.0 with standard srp library
#pragma prefer_hlslcc gles
#pragma target 3.0
// -------------------------------------
// Material Keywords
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON
#pragma shader_feature _ _SPECGLOSSMAP _SPECULAR_COLOR
#pragma shader_feature _ _GLOSSINESS_FROM_BASE_ALPHA

// -------------------------------------
// Lightweight Pipeline keywords
// We have no good approach exposed to skip shader variants, e.g, ideally we would like to skip _CASCADE for all puctual lights
// Lightweight combines light classification and shadows keywords to reduce shader variants.
// Lightweight shader library declares defines based on these keywords to avoid having to check them in the shaders
// Core.hlsl defines _MAIN_LIGHT_DIRECTIONAL and _MAIN_LIGHT_SPOT (point lights can't be main light)
// Shadow.hlsl defines _SHADOWS_ENABLED, _SHADOWS_SOFT, _SHADOWS_CASCADE, _SHADOWS_PERSPECTIVE
#pragma multi_compile _ _MAIN_LIGHT_DIRECTIONAL_SHADOW _MAIN_LIGHT_DIRECTIONAL_SHADOW_CASCADE _MAIN_LIGHT_DIRECTIONAL_SHADOW_SOFT _MAIN_LIGHT_DIRECTIONAL_SHADOW_CASCADE_SOFT _MAIN_LIGHT_SPOT_SHADOW _MAIN_LIGHT_SPOT_SHADOW_SOFT
#pragma multi_compile _MAIN_DIRECTIONAL_LIGHT _MAIN_SPOT_LIGHT
#pragma multi_compile _ _VERTEX_LIGHTS
// -------------------------------------
// Unity defined keywords
#pragma multi_compile _ _HARD_SHADOWS _SOFT_SHADOWS _HARD_SHADOWS_CASCADES _SOFT_SHADOWS_CASCADES
#pragma multi_compile _ _VERTEX_LIGHTS
#pragma multi_compile_fog
#pragma vertex LitPassVertex

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


#pragma vertex SplatmapVert
#pragma fragment SpatmapFragment
#pragma multi_compile _ _MAIN_LIGHT_DIRECTIONAL_SHADOW _MAIN_LIGHT_DIRECTIONAL_SHADOW_CASCADE _MAIN_LIGHT_DIRECTIONAL_SHADOW_SOFT _MAIN_LIGHT_DIRECTIONAL_SHADOW_CASCADE_SOFT _MAIN_LIGHT_SPOT_SHADOW _MAIN_LIGHT_SPOT_SHADOW_SOFT
#pragma multi_compile _MAIN_DIRECTIONAL_LIGHT _MAIN_SPOT_LIGHT
#pragma multi_compile _ _VERTEX_LIGHTS
#pragma multi_compile _ _HARD_SHADOWS _SOFT_SHADOWS _HARD_SHADOWS_CASCADES _SOFT_SHADOWS_CASCADES
#pragma multi_compile _ _VERTEX_LIGHTS
#pragma multi_compile_fog
#pragma multi_compile_fog
#include "LightweightShaderLibrary/Lighting.hlsl"

正在加载...
取消
保存