浏览代码

Added support to subtractive mixed light mode.

/Add-support-for-light-specular-color-tint
Felipe Lira 7 年前
当前提交
2d7d95e7
共有 10 个文件被更改,包括 343 次插入182 次删除
  1. 7
      ScriptableRenderPipeline/LightweightPipeline/Editor/LightweightLightEditor.cs
  2. 1
      ScriptableRenderPipeline/LightweightPipeline/LightweightConstantBuffer.cs
  3. 92
      ScriptableRenderPipeline/LightweightPipeline/LightweightPipeline.cs
  4. 286
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightLighting.cginc
  5. 46
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightShadows.cginc
  6. 1
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightStandard.shader
  7. 1
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightStandardSimpleLighting.shader
  8. 1
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightStandardTerrain.shader
  9. 81
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightInput.cginc
  10. 9
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightInput.cginc.meta

7
ScriptableRenderPipeline/LightweightPipeline/Editor/LightweightLightEditor.cs


if (group.visible) DrawRuntimeShadow();
EditorGUI.indentLevel -= 1;
if (RealtimeShadowsWarningValue || BakingWarningValue)
{
if (BakingWarningValue)
EditorGUILayout.HelpBox(s_Styles.BakingWarning.text, MessageType.Warning);
if (RealtimeShadowsWarningValue)
}
EditorGUILayout.Space();
}

1
ScriptableRenderPipeline/LightweightPipeline/LightweightConstantBuffer.cs


public static class PerFrameBuffer
{
public static int _GlossyEnvironmentColor;
public static int _SubtractiveShadowColor;
}
public static class PerCameraBuffer

92
ScriptableRenderPipeline/LightweightPipeline/LightweightPipeline.cs


public bool shadowsRendered;
}
public enum MixedLightingSetup
{
None = 0,
ShadowMask,
Subtractive,
};
public static class CameraRenderTargetID
{
// Camera color target. Not used when camera is rendering to backbuffer or camera

private readonly LightweightPipelineAsset m_Asset;
// Maximum amount of visible lights the shader can process. This controls the constant global light buffer size.
// It must match the MAX_VISIBLE_LIGHTS in LightweightCore.cginc
// It must match the MAX_VISIBLE_LIGHTS in LightweightInput.cginc
private static readonly int kMaxVisibleAdditionalLights = 16;
// Lights are culled per-object. This holds the maximum amount of additional lights that can shade each object.

private Vector4[] m_LightSpotDirections = new Vector4[kMaxVisibleAdditionalLights];
private Vector4[] m_LightSpotAttenuations = new Vector4[kMaxVisibleAdditionalLights];
private Camera m_CurrCamera = null;
private Camera m_CurrCamera;
private static readonly int kMaxCascades = 4;
private int m_ShadowCasterCascadesCount = kMaxCascades;

private RenderTargetIdentifier m_CopyDepth;
private RenderTargetIdentifier m_Color;
private bool m_IntermediateTextureArray = false;
private bool m_RequiredDepth = false;
private bool m_IntermediateTextureArray;
private bool m_RequiredDepth;
private MixedLightingSetup m_MixedLightingSetup;
private const int kShadowDepthBufferBits = 16;
private const int kCameraDepthBufferBits = 32;

BuildShadowSettings();
PerFrameBuffer._GlossyEnvironmentColor = Shader.PropertyToID("_GlossyEnvironmentColor");
PerFrameBuffer._SubtractiveShadowColor = Shader.PropertyToID("_SubtractiveShadowColor");
// Lights are culled per-camera. Therefore we need to reset light buffers on each camera render
PerCameraBuffer._MainLightPosition = Shader.PropertyToID("_MainLightPosition");

// instead this should be forced when using SRP, since all SRP use linear lighting.
GraphicsSettings.lightsUseLinearIntensity = true;
SetupPerFrameShaderConstants(ref context);
SetupPerFrameShaderConstants();
// Sort cameras array by camera depth
Array.Sort(cameras, m_CameraComparer);

lightData.mainLightIndex = SortLights(visibleLights);
// If we have a main light we don't shade it in the per-object light loop. We also remove it from the per-object cull list
int additionalLightsCount = (lightData.mainLightIndex > 0) ? visibleLightsCount - 1 : visibleLightsCount;
int additionalLightsCount = (lightData.mainLightIndex >= 0) ? visibleLightsCount - 1 : visibleLightsCount;
additionalLightsCount = Math.Min(additionalLightsCount, kMaxPerObjectAdditionalLights);
int pixelLightsCount = Math.Min(additionalLightsCount, m_Asset.MaxAdditionalPixelLights);

lightData.totalAdditionalLightsCount = pixelLightsCount + vertexLightCount;
m_MixedLightingSetup = MixedLightingSetup.None;
}
private int SortLights(VisibleLight[] visibleLights)

private void InitializeLightConstants(VisibleLight[] lights, int lightIndex, out Vector4 lightPos, out Vector4 lightColor, out Vector4 lightDistanceAttenuation, out Vector4 lightSpotDir,
out Vector4 lightSpotAttenuation)
{
float directContributionNotBaked = 1.0f;
lightDistanceAttenuation = new Vector4(0.0f, 1.0f, 0.0f, 0.0f);
lightDistanceAttenuation = new Vector4(0.0f, 1.0f, 0.0f, directContributionNotBaked);
lightSpotDir = new Vector4(0.0f, 0.0f, 1.0f, 0.0f);
lightSpotAttenuation = new Vector4(0.0f, 1.0f, 0.0f, 0.0f);

return;
VisibleLight light = lights[lightIndex];
if (light.lightType == LightType.Directional)
VisibleLight lightData = lights[lightIndex];
if (lightData.lightType == LightType.Directional)
Vector4 dir = -light.localToWorld.GetColumn(2);
Vector4 dir = -lightData.localToWorld.GetColumn(2);
Vector4 pos = light.localToWorld.GetColumn(3);
Vector4 pos = lightData.localToWorld.GetColumn(3);
lightColor = light.finalColor;
lightColor = lightData.finalColor;
if (light.lightType != LightType.Directional)
if (lightData.lightType != LightType.Directional)
{
// Light attenuation in lightweight matches the unity vanilla one.
// attenuation = 1.0 / 1.0 + distanceToLightSqr * quadraticAttenuation

// with one MAD instruction
// smoothFactor = distanceSqr * (1.0 / (fadeDistanceSqr - lightRangeSqr)) + (-lightRangeSqr / (fadeDistanceSqr - lightRangeSqr)
// distanceSqr * oneOverFadeRangeSqr + lightRangeSqrOverFadeRangeSqr
float lightRangeSqr = light.range * light.range;
float lightRangeSqr = lightData.range * lightData.range;
lightDistanceAttenuation = new Vector4(quadAtten, oneOverFadeRangeSqr, lightRangeSqrOverFadeRangeSqr, 0.0f);
lightDistanceAttenuation = new Vector4(quadAtten, oneOverFadeRangeSqr, lightRangeSqrOverFadeRangeSqr, directContributionNotBaked);
if (light.lightType == LightType.Spot)
if (lightData.lightType == LightType.Spot)
Vector4 dir = light.localToWorld.GetColumn(2);
Vector4 dir = lightData.localToWorld.GetColumn(2);
lightSpotDir = new Vector4(-dir.x, -dir.y, -dir.z, 0.0f);
// Spot Attenuation with a linear falloff can be defined as

// SdotL * invAngleRange + (-cosOuterAngle * invAngleRange)
// If we precompute the terms in a MAD instruction
float spotAngle = Mathf.Deg2Rad * light.spotAngle;
float spotAngle = Mathf.Deg2Rad * lightData.spotAngle;
float cosOuterAngle = Mathf.Cos(spotAngle * 0.5f);
float cosInneAngle = Mathf.Cos(spotAngle * 0.25f);
float smoothAngleRange = cosInneAngle - cosOuterAngle;

float add = -cosOuterAngle * invAngleRange;
lightSpotAttenuation = new Vector4(invAngleRange, add, 0.0f);
}
Light light = lightData.light;
if (light.lightmapBakeType == LightmapBakeType.Mixed)
{
// TODO: Add support to shadow mask
if (m_MixedLightingSetup == MixedLightingSetup.None && lightData.light.shadows != LightShadows.None)
{
m_MixedLightingSetup = MixedLightingSetup.Subtractive;
lightDistanceAttenuation.w = 0.0f;
}
}
private void SetupPerFrameShaderConstants(ref ScriptableRenderContext context)
private void SetupPerFrameShaderConstants()
// Used when subtractive mode is selected
Shader.SetGlobalColor(PerFrameBuffer._SubtractiveShadowColor, RenderSettings.subtractiveShadowColor.linear);
}
private void SetupShaderLightConstants(CommandBuffer cmd, VisibleLight[] lights, ref LightData lightData)

Vector4 lightPos, lightColor, lightDistanceAttenuation, lightSpotDir, lightSpotAttenuation;
InitializeLightConstants(lights, lightIndex, out lightPos, out lightColor, out lightDistanceAttenuation, out lightSpotDir, out lightSpotAttenuation);
if (lightIndex >= 0)
{
LightType mainLightType = lights[lightIndex].lightType;
Light mainLight = lights[lightIndex].light;
if (LightweightUtils.IsSupportedCookieType(mainLightType) && mainLight.cookie != null)
{
Matrix4x4 lightCookieMatrix;
LightweightUtils.GetLightCookieMatrix(lights[lightIndex], out lightCookieMatrix);
cmd.SetGlobalTexture(PerCameraBuffer._MainLightCookie, mainLight.cookie);
cmd.SetGlobalMatrix(PerCameraBuffer._WorldToLight, lightCookieMatrix);
}
}
if (lightIndex >= 0 && LightweightUtils.IsSupportedCookieType(lights[lightIndex].lightType) && lights[lightIndex].light.cookie != null)
{
Matrix4x4 lightCookieMatrix;
LightweightUtils.GetLightCookieMatrix(lights[lightIndex], out lightCookieMatrix);
cmd.SetGlobalTexture(PerCameraBuffer._MainLightCookie, lights[lightIndex].light.cookie);
cmd.SetGlobalMatrix(PerCameraBuffer._WorldToLight, lightCookieMatrix);
}
}
private void SetupAdditionalListConstants(CommandBuffer cmd, VisibleLight[] lights, ref LightData lightData)

private void SetupShadowShaderConstants(CommandBuffer cmd, ref VisibleLight shadowLight, int cascadeCount)
{
Light light = shadowLight.light;
float strength = 1.0f - light.shadowStrength;
float nearPlane = light.shadowNearPlane;
float shadowResolution = m_ShadowSlices[0].shadowResolution;
const int maxShadowCascades = 4;

cmd.SetGlobalMatrixArray("_WorldToShadow", shadowMatrices);
cmd.SetGlobalVectorArray("_DirShadowSplitSpheres", m_DirectionalShadowSplitDistances);
cmd.SetGlobalVector("_ShadowData", new Vector4(0.0f, bias, normalBias, 0.0f));
cmd.SetGlobalVector("_ShadowData", new Vector4(strength, bias, normalBias, nearPlane));
cmd.SetGlobalFloatArray("_PCFKernel", pcfKernel);
}

LightweightUtils.SetKeyword (cmd, "_MAIN_SPOT_LIGHT", mainLightIndex != -1 && visibleLights[mainLightIndex].lightType == LightType.Spot);
LightweightUtils.SetKeyword (cmd, "_MAIN_POINT_LIGHT", mainLightIndex != -1 && visibleLights[mainLightIndex].lightType == LightType.Point);
LightweightUtils.SetKeyword(cmd, "_ADDITIONAL_LIGHTS", lightData.totalAdditionalLightsCount > 0);
LightweightUtils.SetKeyword(cmd, "_MIXED_LIGHTING_SHADOWMASK", m_MixedLightingSetup == MixedLightingSetup.ShadowMask);
LightweightUtils.SetKeyword(cmd, "_MIXED_LIGHTING_SUBTRACTIVE", m_MixedLightingSetup == MixedLightingSetup.Subtractive);
string[] shadowKeywords = new string[] { "_HARD_SHADOWS", "_SOFT_SHADOWS", "_HARD_SHADOWS_CASCADES", "_SOFT_SHADOWS_CASCADES" };
for (int i = 0; i < shadowKeywords.Length; ++i)

286
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightLighting.cginc


#define PI 3.14159265359f
#define kDieletricSpec half4(0.04, 0.04, 0.04, 1.0 - 0.04) // standard dielectric reflectivity coef at incident angle (= 4%)
#define MAX_VISIBLE_LIGHTS 16
#ifndef UNITY_SPECCUBE_LOD_STEPS
#define UNITY_SPECCUBE_LOD_STEPS 6
#endif

#endif
#endif
// Main light initialized without indexing
#define INITIALIZE_MAIN_LIGHT(light) \
light.pos = _MainLightPosition; \
light.color = _MainLightColor; \
light.distanceAttenuation = _MainLightDistanceAttenuation; \
light.spotDirection = _MainLightSpotDir; \
light.spotAttenuation = _MainLightSpotAttenuation
// Indexing might have a performance hit for old mobile hardware
#define INITIALIZE_LIGHT(light, i) \
half4 indices = (i < 4) ? unity_4LightIndices0 : unity_4LightIndices1; \
int index = (i < 4) ? i : i - 4; \
int lightIndex = indices[index]; \
light.pos = _AdditionalLightPosition[lightIndex]; \
light.color = _AdditionalLightColor[lightIndex]; \
light.distanceAttenuation = _AdditionalLightDistanceAttenuation[lightIndex]; \
light.spotDirection = _AdditionalLightSpotDir[lightIndex]; \
light.spotAttenuation = _AdditionalLightSpotAttenuation[lightIndex]
CBUFFER_START(_PerObject)
half4 unity_LightIndicesOffsetAndCount;
half4 unity_4LightIndices0;
half4 unity_4LightIndices1;
CBUFFER_END
CBUFFER_START(_PerCamera)
sampler2D _MainLightCookie;
float4 _MainLightPosition;
half4 _MainLightColor;
half4 _MainLightDistanceAttenuation;
half4 _MainLightSpotDir;
half4 _MainLightSpotAttenuation;
float4x4 _WorldToLight;
half4 _AdditionalLightCount;
float4 _AdditionalLightPosition[MAX_VISIBLE_LIGHTS];
half4 _AdditionalLightColor[MAX_VISIBLE_LIGHTS];
half4 _AdditionalLightDistanceAttenuation[MAX_VISIBLE_LIGHTS];
half4 _AdditionalLightSpotDir[MAX_VISIBLE_LIGHTS];
half4 _AdditionalLightSpotAttenuation[MAX_VISIBLE_LIGHTS];
CBUFFER_END
CBUFFER_START(_PerFrame)
half4 _GlossyEnvironmentColor;
CBUFFER_END
// Must match Lightweigth ShaderGraph master node
struct SurfaceData
{
half3 albedo;
half3 specular;
half metallic;
half smoothness;
half3 normal;
half3 emission;
half occlusion;
half alpha;
};
struct LightInput
{
float4 pos;
half4 color;
half4 distanceAttenuation;
half4 spotDirection;
half4 spotAttenuation;
};
///////////////////////////////////////////////////////////////////////////////
// BRDF Functions //
///////////////////////////////////////////////////////////////////////////////
struct BRDFData
{
half3 diffuse;

#endif
}
half3 GlossyEnvironment(half3 reflectVector, half perceptualRoughness)
{
#if !defined(_GLOSSYREFLECTIONS_OFF)
half roughness = perceptualRoughness * (1.7 - 0.7 * perceptualRoughness);
half mip = roughness * UNITY_SPECCUBE_LOD_STEPS;
half4 rgbm = UNITY_SAMPLE_TEXCUBE_LOD(unity_SpecCube0, reflectVector, mip);
return DecodeHDR(rgbm, unity_SpecCube0_HDR);
#endif
return _GlossyEnvironmentColor;
}
half3 LightweightEnvironmentBRDF(BRDFData brdfData, half3 indirectDiffuse, half3 indirectSpecular, half roughness2, half fresnelTerm)
{
half3 c = indirectDiffuse * brdfData.diffuse;

// * NDF [Modified] GGX
// * Modified Kelemen and Szirmay-​Kalos for Visibility term
// * Fresnel approximated with 1/LdotH
half3 LightweightBDRF(BRDFData brdfData, half roughness2, half3 normal, half3 lightDirection, half3 viewDir)
half3 LightweightDirectBDRF(BRDFData brdfData, half roughness2, half3 normal, half3 lightDirection, half3 viewDir)
{
#ifndef _SPECULARHIGHLIGHTS_OFF
half3 halfDir = SafeNormalize(lightDirection + viewDir);

#endif
}
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;
}
///////////////////////////////////////////////////////////////////////////////
// Attenuation Functions /
///////////////////////////////////////////////////////////////////////////////
#ifdef _MAIN_DIRECTIONAL_LIGHT
float2 cookieUV = mul(_WorldToLight, float4(worldPos, 1.0)).xy;
return tex2D(_MainLightCookie, cookieUV).a;
#elif defined(_MAIN_SPOT_LIGHT)
float4 projPos = mul(_WorldToLight, float4(worldPos, 1.0));
float2 cookieUV = projPos.xy / projPos.w + 0.5;
return tex2D(_MainLightCookie, cookieUV).a;
#endif // POINT LIGHT cookie not supported
#ifdef _MAIN_DIRECTIONAL_LIGHT
float2 cookieUV = mul(_WorldToLight, float4(worldPos, 1.0)).xy;
return tex2D(_MainLightCookie, cookieUV).a;
#elif defined(_MAIN_SPOT_LIGHT)
float4 projPos = mul(_WorldToLight, float4(worldPos, 1.0));
float2 cookieUV = projPos.xy / projPos.w + 0.5;
return tex2D(_MainLightCookie, cookieUV).a;
#endif // POINT LIGHT cookie not supported
#endif
return 1;

// Attenuation smoothly decreases to light range.
half DistanceAttenuation(half3 distanceSqr, half4 distanceAttenuation)
{
// We use a shared distance attenuation for additional directional and puctual lights

return saturate(SdotL * spotAttenuation.x + spotAttenuation.y);
}
// Attenuation smoothly decreases to light range.
inline half ComputeLightAttenuation(LightInput lightInput, half3 normal, float3 worldPos, out half3 lightDirection)
inline half GetLightDirectionAndRealtimeAttenuation(LightInput lightInput, half3 normal, float3 worldPos, out half3 lightDirection)
{
float3 posToLightVec = lightInput.pos.xyz - worldPos * lightInput.pos.w;
float distanceSqr = max(dot(posToLightVec, posToLightVec), 0.001);

return lightAtten;
}
inline half ComputeMainLightAttenuation(LightInput lightInput, half3 normalWS, float3 positionWS, out half3 lightDirection)
inline half GetMainLightDirectionAndRealtimeAttenuation(LightInput lightInput, half3 normalWS, float3 positionWS, out half3 lightDirection)
{
#ifdef _MAIN_DIRECTIONAL_LIGHT
// Light pos holds normalized light dir

half attenuation = ComputeLightAttenuation(lightInput, normalWS, positionWS, lightDirection);
half attenuation = GetLightDirectionAndRealtimeAttenuation(lightInput, normalWS, positionWS, lightDirection);
///////////////////////////////////////////////////////////////////////////////
// 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 VertexLighting(float3 positionWS, half3 normalWS)
{
half3 vertexLightColor = half3(0.0, 0.0, 0.0);

INITIALIZE_LIGHT(light, lightIter);
half3 lightDirection;
half atten = ComputeLightAttenuation(light, normalWS, positionWS, lightDirection);
half atten = GetLightDirectionAndAttenuation(light, normalWS, positionWS, lightDirection);
half3 lightColor = light.color * atten;
vertexLightColor += LightingLambert(lightColor, lightDirection, normalWS);
}

}
half4 LightweightFragmentPBR(float3 positionWS, half3 normalWS, half3 viewDirectionWS, half3 indirectDiffuse, half3 vertexLighting, half3 albedo, half metallic, half3 specular, half smoothness, half occlusion, half3 emission, half alpha)
///////////////////////////////////////////////////////////////////////////////
// Global Illumination //
///////////////////////////////////////////////////////////////////////////////
half3 DiffuseGI(half3 indirectDiffuse, half3 lambert, half mainLightRealtimeAttenuation, half occlusion)
// 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)
indirectDiffuse = SubtractDirectMainLightFromLightmap(indirectDiffuse, mainLightRealtimeAttenuation, lambert);
#endif
return indirectDiffuse * occlusion;
}
half3 GlossyEnvironmentReflection(half3 viewDirectionWS, half3 normalWS, half perceptualRoughness, half occlusion)
{
half3 reflectVector = reflect(-viewDirectionWS, normalWS);
#if !defined(_GLOSSYREFLECTIONS_OFF)
half roughness = perceptualRoughness * (1.7 - 0.7 * perceptualRoughness);
half mip = roughness * UNITY_SPECCUBE_LOD_STEPS;
half4 rgbm = UNITY_SAMPLE_TEXCUBE_LOD(unity_SpecCube0, reflectVector, mip);
return DecodeHDR(rgbm, unity_SpecCube0_HDR) * occlusion;
#endif
return _GlossyEnvironmentColor * occlusion;
}
///////////////////////////////////////////////////////////////////////////////
// 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)
{
half4 bakedOcclusion = half4(0, 0, 0, 0);
half3 reflectVec = reflect(-viewDirectionWS, normalWS);
half roughness2 = brdfData.roughness * brdfData.roughness;
indirectDiffuse *= occlusion;
half3 indirectSpecular = GlossyEnvironment(reflectVec, brdfData.perceptualRoughness) * occlusion;
half3 lightDirectionWS;
LightInput mainLight;
INITIALIZE_MAIN_LIGHT(mainLight);
// PBS
// No distance fade.
half realtimeMainLightAtten = GetMainLightDirectionAndRealtimeAttenuation(mainLight, normalWS, positionWS, lightDirectionWS);
half NdotL = saturate(dot(normalWS, lightDirectionWS));
half3 radiance = mainLight.color * NdotL;
half3 indirectDiffuse = DiffuseGI(bakedGI, radiance, realtimeMainLightAtten, occlusion);
half3 indirectSpecular = GlossyEnvironmentReflection(viewDirectionWS, normalWS, brdfData.perceptualRoughness, occlusion);
half roughness2 = brdfData.roughness * brdfData.roughness;
half3 lightDirectionWS;
LightInput light;
INITIALIZE_MAIN_LIGHT(light);
half lightAtten = ComputeMainLightAttenuation(light, normalWS, positionWS, lightDirectionWS);
half NdotL = saturate(dot(normalWS, lightDirectionWS));
half3 radiance = light.color * (lightAtten * NdotL);
color += LightweightBDRF(brdfData, roughness2, normalWS, lightDirectionWS, viewDirectionWS) * radiance;
half mainLightAtten = MixRealtimeAndBakedOcclusion(realtimeMainLightAtten, bakedOcclusion, mainLight.distanceAttenuation);
radiance *= mainLightAtten;
color += LightweightDirectBDRF(brdfData, roughness2, normalWS, lightDirectionWS, viewDirectionWS) * radiance;
color += vertexLighting * brdfData.diffuse;
#ifdef _ADDITIONAL_LIGHTS

LightInput light;
INITIALIZE_LIGHT(light, lightIter);
half lightAtten = ComputeLightAttenuation(light, normalWS, positionWS, lightDirectionWS);
half lightAttenuation = GetLightDirectionAndRealtimeAttenuation(light, normalWS, positionWS, lightDirectionWS);
lightAttenuation = MixRealtimeAndBakedOcclusion(lightAttenuation, bakedOcclusion, light.distanceAttenuation);
half3 radiance = light.color * (lightAtten * NdotL);
color += LightweightBDRF(brdfData, roughness2, normalWS, lightDirectionWS, viewDirectionWS) * radiance;
half3 radiance = light.color * (lightAttenuation * NdotL);
color += LightweightDirectBDRF(brdfData, roughness2, normalWS, lightDirectionWS, viewDirectionWS) * radiance;
}
#endif

half4 LightweightFragmentLambert(float3 positionWS, half3 normalWS, half3 viewDirectionWS, half fogFactor, half3 diffuseGI, half3 diffuse, half3 emission, half alpha)
half4 LightweightFragmentLambert(float3 positionWS, half3 normalWS, half3 viewDirectionWS,
half fogFactor, half3 diffuseGI, half3 diffuse, half3 emission, half alpha)
half4 bakedOcclusion = half4(0, 0, 0, 0);
half3 diffuseColor = diffuseGI;
half lightAtten = ComputeMainLightAttenuation(mainLight, normalWS, positionWS, lightDirection);
half3 lightColor = mainLight.color * lightAtten;
diffuseColor += LightingLambert(lightColor, lightDirection, normalWS);
half realtimeMainLightAtten = GetMainLightDirectionAndRealtimeAttenuation(mainLight, normalWS, positionWS, lightDirection);
half3 NdotL = saturate(dot(normalWS, lightDirection));
half3 lambert = mainLight.color * NdotL;
half3 indirectDiffuse = DiffuseGI(diffuseGI, lambert, realtimeMainLightAtten, 1.0);
half mainLightAtten = MixRealtimeAndBakedOcclusion(realtimeMainLightAtten, bakedOcclusion, mainLight.distanceAttenuation);
half3 diffuseColor = lambert * mainLightAtten + indirectDiffuse;
LightInput lightData;
INITIALIZE_LIGHT(lightData, lightIter);
lightAtten = ComputeLightAttenuation(lightData, normalWS, positionWS, lightDirection);
lightColor = lightData.color * lightAtten;
LightInput light;
INITIALIZE_LIGHT(light, lightIter);
half lightAttenuation = GetLightDirectionAndRealtimeAttenuation(light, normalWS, positionWS, lightDirection);
lightAttenuation = MixRealtimeAndBakedOcclusion(lightAttenuation, bakedOcclusion, light.distanceAttenuation);
diffuseColor += LightingLambert(lightColor, lightDirection, normalWS);
half3 attenuatedLightColor = light.color * lightAttenuation;
diffuseColor += LightingLambert(attenuatedLightColor, lightDirection, normalWS);
#endif // _ADDITIONAL_LIGHTS
#endif
half3 finalColor = diffuseColor * diffuse + emission;

return OUTPUT_COLOR(color);
}
half4 LightweightFragmentBlinnPhong(float3 positionWS, half3 normalWS, half3 viewDirectionWS, half fogFactor, half3 diffuseGI, half3 diffuse, half4 specularGloss, half shininess, half3 emission, half alpha)
half4 LightweightFragmentBlinnPhong(float3 positionWS, half3 normalWS, half3 viewDirectionWS,
half fogFactor, half3 diffuseGI, half3 diffuse, half4 specularGloss, half shininess, half3 emission, half alpha)
half4 bakedOcclusion = half4(0, 0, 0, 0);
half3 diffuseColor = diffuseGI;
half3 specularColor;
half lightAtten = ComputeMainLightAttenuation(mainLight, normalWS, positionWS, lightDirection);
half realtimeMainLightAtten = GetMainLightDirectionAndRealtimeAttenuation(mainLight, normalWS, positionWS, lightDirection);
half3 NdotL = saturate(dot(normalWS, lightDirection));
half3 lambert = mainLight.color * NdotL;
half3 lightColor = mainLight.color * lightAtten;
diffuseColor += LightingLambert(lightColor, lightDirection, normalWS);
specularColor = LightingSpecular(lightColor, lightDirection, normalWS, viewDirectionWS, specularGloss, shininess);
half3 indirectDiffuse = DiffuseGI(diffuseGI, lambert, realtimeMainLightAtten, 1.0);
half mainLightAtten = MixRealtimeAndBakedOcclusion(realtimeMainLightAtten, bakedOcclusion, mainLight.distanceAttenuation);
half3 diffuseColor = lambert * mainLightAtten + indirectDiffuse;
half3 specularColor = LightingSpecular(mainLight.color * mainLightAtten, lightDirection, normalWS, viewDirectionWS, specularGloss, shininess);
LightInput lightData;
INITIALIZE_LIGHT(lightData, lightIter);
lightAtten = ComputeLightAttenuation(lightData, normalWS, positionWS, lightDirection);
lightColor = lightData.color * lightAtten;
LightInput light;
INITIALIZE_LIGHT(light, lightIter);
half lightAttenuation = GetLightDirectionAndRealtimeAttenuation(light, normalWS, positionWS, lightDirection);
lightAttenuation = MixRealtimeAndBakedOcclusion(lightAttenuation, bakedOcclusion, light.distanceAttenuation);
diffuseColor += LightingLambert(lightColor, lightDirection, normalWS);
specularColor += LightingSpecular(lightColor, lightDirection, normalWS, viewDirectionWS, specularGloss, shininess);
half3 attenuatedLightColor = light.color * lightAttenuation;
diffuseColor += LightingLambert(attenuatedLightColor, lightDirection, normalWS);
specularColor += LightingSpecular(attenuatedLightColor, lightDirection, normalWS, viewDirectionWS, specularGloss, shininess);
#endif // _ADDITIONAL_LIGHTS
#endif
half3 finalColor = diffuseColor * diffuse + emission;
finalColor += specularColor;

46
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightShadows.cginc


#ifndef LIGHTWEIGHT_SHADOWS_INCLUDED
#define LIGHTWEIGHT_SHADOWS_INCLUDED
#include "LightweightInput.cginc"
#define MAX_SHADOW_CASCADES 4
#if defined(_HARD_SHADOWS) || defined(_SOFT_SHADOWS) || defined(_HARD_SHADOWS_CASCADES) || defined(_SOFT_SHADOWS_CASCADES)

#else
return ShadowAttenuation(shadowCoord.xyz);
#endif
}
half MixRealtimeAndBakedOcclusion(half realtimeAttenuation, half4 bakedOcclusion, half4 distanceAttenuation)
{
#if defined(LIGHTMAP_ON)
#if defined(_MIXED_LIGHTING_SHADOWMASK)
// TODO:
#elif defined(_MIXED_LIGHTING_SUBTRACTIVE)
// Subtractive Light mode has direct light contribution baked into lightmap for mixed lights.
// 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;
#endif
#endif
return realtimeAttenuation;
}
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);
realtimeShadow = lerp(realtimeShadow, lightmap, shadowStrength);
// 3) Pick darkest color
return min(lightmap, realtimeShadow);
}
#endif

1
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightStandard.shader


#pragma multi_compile _ _MAIN_LIGHT_COOKIE
#pragma multi_compile _MAIN_DIRECTIONAL_LIGHT _MAIN_SPOT_LIGHT _MAIN_POINT_LIGHT
#pragma multi_compile _ _ADDITIONAL_LIGHTS
#pragma multi_compile _ _MIXED_LIGHTING_SUBTRACTIVE _MIXED_LIGHTING_SHADOWMASK
#pragma multi_compile _ UNITY_SINGLE_PASS_STEREO STEREO_INSTANCING_ON STEREO_MULTIVIEW_ON
#pragma multi_compile _ LIGHTMAP_ON
#pragma multi_compile _ DIRLIGHTMAP_COMBINED

1
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightStandardSimpleLighting.shader


#pragma multi_compile _ _MAIN_LIGHT_COOKIE
#pragma multi_compile _MAIN_DIRECTIONAL_LIGHT _MAIN_SPOT_LIGHT _MAIN_POINT_LIGHT
#pragma multi_compile _ _ADDITIONAL_LIGHTS
#pragma multi_compile _ _MIXED_LIGHTING_SUBTRACTIVE _MIXED_LIGHTING_SHADOWMASK
#pragma multi_compile _ UNITY_SINGLE_PASS_STEREO STEREO_INSTANCING_ON STEREO_MULTIVIEW_ON
#pragma multi_compile _ LIGHTMAP_ON
#pragma multi_compile _ DIRLIGHTMAP_COMBINED

1
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightStandardTerrain.shader


#pragma multi_compile _ _MAIN_LIGHT_COOKIE
#pragma multi_compile _MAIN_DIRECTIONAL_LIGHT _MAIN_SPOT_LIGHT _MAIN_POINT_LIGHT
#pragma multi_compile _ _ADDITIONAL_LIGHTS
#pragma multi_compile _ _MIXED_LIGHTING_SUBTRACTIVE _MIXED_LIGHTING_SHADOWMASK
#pragma multi_compile _ UNITY_SINGLE_PASS_STEREO STEREO_INSTANCING_ON STEREO_MULTIVIEW_ON
#pragma multi_compile _ LIGHTMAP_ON
#pragma multi_compile _ DIRLIGHTMAP_COMBINED

81
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightInput.cginc


#ifndef LIGHTWEIGHT_INPUT_INCLUDED
#define LIGHTWEIGHT_INPUT_INCLUDED
#define MAX_VISIBLE_LIGHTS 16
// Must match Lightweigth ShaderGraph master node
struct SurfaceData
{
half3 albedo;
half3 specular;
half metallic;
half smoothness;
half3 normal;
half3 emission;
half occlusion;
half alpha;
};
struct LightInput
{
float4 pos;
half4 color;
half4 distanceAttenuation;
half4 spotDirection;
half4 spotAttenuation;
};
// Main light initialized without indexing
#define INITIALIZE_MAIN_LIGHT(light) \
light.pos = _MainLightPosition; \
light.color = _MainLightColor; \
light.distanceAttenuation = _MainLightDistanceAttenuation; \
light.spotDirection = _MainLightSpotDir; \
light.spotAttenuation = _MainLightSpotAttenuation
// Indexing might have a performance hit for old mobile hardware
#define INITIALIZE_LIGHT(light, i) \
half4 indices = (i < 4) ? unity_4LightIndices0 : unity_4LightIndices1; \
int index = (i < 4) ? i : i - 4; \
int lightIndex = indices[index]; \
light.pos = _AdditionalLightPosition[lightIndex]; \
light.color = _AdditionalLightColor[lightIndex]; \
light.distanceAttenuation = _AdditionalLightDistanceAttenuation[lightIndex]; \
light.spotDirection = _AdditionalLightSpotDir[lightIndex]; \
light.spotAttenuation = _AdditionalLightSpotAttenuation[lightIndex]
///////////////////////////////////////////////////////////////////////////////
// Constant Buffers //
///////////////////////////////////////////////////////////////////////////////
CBUFFER_START(_PerFrame)
half4 _GlossyEnvironmentColor;
half4 _SubtractiveShadowColor;
CBUFFER_END
CBUFFER_START(_PerCamera)
sampler2D _MainLightCookie;
float4 _MainLightPosition;
half4 _MainLightColor;
half4 _MainLightDistanceAttenuation;
half4 _MainLightSpotDir;
half4 _MainLightSpotAttenuation;
float4x4 _WorldToLight;
half4 _AdditionalLightCount;
float4 _AdditionalLightPosition[MAX_VISIBLE_LIGHTS];
half4 _AdditionalLightColor[MAX_VISIBLE_LIGHTS];
half4 _AdditionalLightDistanceAttenuation[MAX_VISIBLE_LIGHTS];
half4 _AdditionalLightSpotDir[MAX_VISIBLE_LIGHTS];
half4 _AdditionalLightSpotAttenuation[MAX_VISIBLE_LIGHTS];
CBUFFER_END
// These are set internally by the engine upon request by RendererConfiguration.
// Check GetRendererSettings in LightweightPipeline.cs
CBUFFER_START(_PerObject)
half4 unity_LightIndicesOffsetAndCount;
half4 unity_4LightIndices0;
half4 unity_4LightIndices1;
CBUFFER_END
#endif

9
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightInput.cginc.meta


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