浏览代码

Ported Lightweight to SRP shader library.

/main
Felipe Lira 7 年前
当前提交
a5dbc063
共有 43 个文件被更改,包括 2143 次插入1307 次删除
  1. 2
      ScriptableRenderPipeline/Core/ShaderLibrary/Common.hlsl
  2. 42
      ScriptableRenderPipeline/Core/ShaderLibrary/EntityLighting.hlsl
  3. 34
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightStandard.shader
  4. 73
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightStandardParticles.shader
  5. 30
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightStandardSimpleLighting.shader
  6. 25
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightUnlit.shader
  7. 98
      ScriptableRenderPipeline/Core/ShaderLibrary/API/GLES3.hlsl
  8. 10
      ScriptableRenderPipeline/Core/ShaderLibrary/API/GLES3.hlsl.meta
  9. 8
      ScriptableRenderPipeline/Core/ShaderLibrary/ShaderVariables.meta
  10. 199
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightCore.hlsl
  11. 69
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightInput.hlsl
  12. 425
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightLighting.hlsl
  13. 214
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightParticle.hlsl
  14. 9
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightParticle.hlsl.meta
  15. 133
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassLit.hlsl
  16. 123
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassMeta.hlsl
  17. 22
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassShadow.hlsl
  18. 149
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightShadows.hlsl
  19. 168
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightSurfaceInput.hlsl
  20. 8
      ScriptableRenderPipeline/LightweightPipeline/Shaders/ShaderVariables.meta
  21. 252
      ScriptableRenderPipeline/LightweightPipeline/Shaders/ShaderVariables/LightweightShaderVariables.hlsl
  22. 9
      ScriptableRenderPipeline/LightweightPipeline/Shaders/ShaderVariables/LightweightShaderVariables.hlsl.meta
  23. 21
      ScriptableRenderPipeline/LightweightPipeline/Shaders/ShaderVariables/LightweightShaderVariablesCamera.hlsl
  24. 9
      ScriptableRenderPipeline/LightweightPipeline/Shaders/ShaderVariables/LightweightShaderVariablesCamera.hlsl.meta
  25. 114
      ScriptableRenderPipeline/LightweightPipeline/Shaders/ShaderVariables/LightweightShaderVariablesFunctions.hlsl
  26. 9
      ScriptableRenderPipeline/LightweightPipeline/Shaders/ShaderVariables/LightweightShaderVariablesFunctions.hlsl.meta
  27. 20
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassShadow.cginc
  28. 166
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightCore.cginc
  29. 137
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassLit.cginc
  30. 70
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassMeta.cginc
  31. 142
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightShadows.cginc
  32. 69
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightInput.cginc
  33. 425
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightLighting.cginc
  34. 166
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightSurfaceInput.cginc
  35. 0
      /ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightCore.hlsl.meta
  36. 0
      /ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightInput.hlsl.meta
  37. 0
      /ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightLighting.hlsl.meta
  38. 0
      /ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassLit.hlsl.meta
  39. 0
      /ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassMeta.hlsl.meta
  40. 0
      /ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassShadow.hlsl.meta
  41. 0
      /ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightShadows.hlsl.meta
  42. 0
      /ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightSurfaceInput.hlsl.meta

2
ScriptableRenderPipeline/Core/ShaderLibrary/Common.hlsl


#include "API/Metal.hlsl"
#elif defined(SHADER_API_VULKAN)
#include "API/Vulkan.hlsl"
#elif defined(SHADER_API_GLES3)
#include "API/GLES3.hlsl"
#else
#error unsupported shader api
#endif

42
ScriptableRenderPipeline/Core/ShaderLibrary/EntityLighting.hlsl


// RGBM lightmaps are currently always gamma encoded, so we use a constant of range^2.2 = 5^2.2
#define LIGHTMAP_RGBM_RANGE 34.493242f
// DLRD lightmaps are currently alwasy gamma encoded, so we use a constant of 2.0^2.2 = 4.59
#define LIGHTMAP_DLDR_RANGE 4.59f
// TODO: This is the max value allowed for emissive (bad name - but keep for now to retrieve it) (It is 8^2.2 (gamma) and 8 is the limit of punctual light slider...), comme from UnityCg.cginc. Fix it!
// Ask Jesper if this can be change for HDRenderPipeline
#define EMISSIVE_RGBM_SCALE 97.0

return rgbm;
}
float3 UnpackLightmapRGBM(float4 rgbmInput)
half3 UnpackLightmapRGBM(half4 rgbmInput)
float3 SampleSingleLightmap(TEXTURE2D_ARGS(lightmapTex, lightmapSampler), float2 uv, float4 transform, bool lightmapRGBM)
half3 UnpackLightmapDoubleLDR(half4 encodedColor)
{
return encodedColor.rgb * LIGHTMAP_DLDR_RANGE;
}
half3 DecodeHDRLightmap(half4 encodedIlluminance)
{
#if defined(UNITY_LIGHTMAP_RGBM_ENCODING)
return UnpackLightmapRGBM(encodedIlluminance);
#else // DLDR encoding on mobile platforms
return UnpackLightmapDoubleLDR(encodedIlluminance);
#endif
}
half3 DecodeHDREnvironment(half4 encodedIrradiance, half4 decodeInstructions)
{
// Take into account texture alpha if decodeInstructions.w is true(the alpha value affects the RGB channels)
half alpha = max(decodeInstructions.w * (encodedIrradiance.a - 1.0) + 1.0, 0.0);
// If Linear mode is not supported we can skip exponent part
return (decodeInstructions.x * pow(alpha, decodeInstructions.y)) * encodedIrradiance.rgb;
}
float3 SampleSingleLightmap(TEXTURE2D_ARGS(lightmapTex, lightmapSampler), float2 uv, float4 transform, bool encodedLightmap)
if (lightmapRGBM)
if (encodedLightmap)
illuminance = UnpackLightmapRGBM(SAMPLE_TEXTURE2D(lightmapTex, lightmapSampler, uv).rgba);
half4 encodedIlluminance = SAMPLE_TEXTURE2D(lightmapTex, lightmapSampler, uv).rgba;
illuminance = DecodeHDRLightmap(encodedIlluminance);
}
else
{

}
float3 SampleDirectionalLightmap(TEXTURE2D_ARGS(lightmapTex, lightmapSampler), TEXTURE2D_ARGS(lightmapDirTex, lightmapDirSampler), float2 uv, float4 transform, float3 normalWS, bool lightmapRGBM)
float3 SampleDirectionalLightmap(TEXTURE2D_ARGS(lightmapTex, lightmapSampler), TEXTURE2D_ARGS(lightmapDirTex, lightmapDirSampler), float2 uv, float4 transform, float3 normalWS, bool encodedLightmap)
{
// In directional mode Enlighten bakes dominant light direction
// in a way, that using it for half Lambert and then dividing by a "rebalancing coefficient"

float4 direction = SAMPLE_TEXTURE2D(lightmapDirTex, lightmapDirSampler, uv);
// Remark: baked lightmap is RGBM for now, dynamic lightmap is RGB9E5
float3 illuminance = float3(0.0, 0.0, 0.0);
if (lightmapRGBM)
if (encodedLightmap)
illuminance = UnpackLightmapRGBM(SAMPLE_TEXTURE2D(lightmapTex, lightmapSampler, uv).rgba);
half4 encodedIlluminance = SAMPLE_TEXTURE2D(lightmapTex, lightmapSampler, uv).rgba;
illuminance = DecodeHDRLightmap(encodedIlluminance);
}
else
{

34
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightStandard.shader


Blend[_SrcBlend][_DstBlend]
ZWrite[_ZWrite]
CGPROGRAM
HLSLPROGRAM
#pragma target 3.0
// -------------------------------------

#pragma multi_compile _MAIN_DIRECTIONAL_LIGHT _MAIN_SPOT_LIGHT
#pragma multi_compile _ _ADDITIONAL_LIGHTS
#pragma multi_compile _ _MIXED_LIGHTING_SUBTRACTIVE
#pragma multi_compile _ UNITY_SINGLE_PASS_STEREO STEREO_INSTANCING_ON STEREO_MULTIVIEW_ON
#pragma multi_compile _ UNITY_SINGLE_PASS_STEREO STEREO_INSTANCING_ENABLED STEREO_MULTIVIEW_ENABLED
#pragma multi_compile _ LIGHTMAP_ON
#pragma multi_compile _ DIRLIGHTMAP_COMBINED
#pragma multi_compile _ _HARD_SHADOWS _SOFT_SHADOWS _HARD_SHADOWS_CASCADES _SOFT_SHADOWS_CASCADES

#pragma multi_compile_instancing
#include "LightweightPassLit.cginc"
ENDCG
#include "LightweightPassLit.hlsl"
ENDHLSL
}
Pass

ZWrite On ZTest LEqual
CGPROGRAM
HLSLPROGRAM
#include "UnityCG.cginc"
#include "LightweightPassShadow.cginc"
ENDCG
#include "LightweightPassShadow.hlsl"
ENDHLSL
}
Pass

ZWrite On
ColorMask 0
CGPROGRAM
HLSLPROGRAM
#include "UnityCG.cginc"
#include "LightweightCore.hlsl"
return UnityObjectToClipPos(pos);
return TransformObjectToHClip(pos.xyz);
}
half4 frag() : SV_TARGET

ENDCG
ENDHLSL
}
// This pass it not used during regular rendering, only for lightmap baking.

Cull Off
CGPROGRAM
HLSLPROGRAM
#pragma vertex LightweightVertexMeta
#pragma fragment LightweightFragmentMeta

#pragma shader_feature _SPECGLOSSMAP
#include "LightweightPassMeta.cginc"
ENDCG
#include "LightweightPassMeta.hlsl"
ENDHLSL
FallBack "Hidden/InternalErrorShader"
//FallBack "Hidden/InternalErrorShader"
CustomEditor "LightweightStandardGUI"
}

73
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightStandardParticles.shader


Pass
{
Tags {"LightMode" = "LightweightForward"}
CGPROGRAM
HLSLPROGRAM
#pragma vertex ParticlesLitVertex
#pragma fragment ParticlesLitFragment
#pragma multi_compile __ SOFTPARTICLES_ON

#pragma shader_feature _FADING_ON
#pragma shader_feature _REQUIRE_UV2
#define NO_LIGHTMAP
#define NO_ADDITIONAL_LIGHTS
#include "UnityStandardParticles.cginc"
#include "LightweightLighting.cginc"
struct VertexOutputLit
{
half4 color : COLOR;
float2 texcoord : TEXCOORD0;
#if _NORMALMAP
half3 tangent : TEXCOORD1;
half3 binormal : TEXCOORD2;
half3 normal : TEXCOORD3;
#else
half3 normal : TEXCOORD1;
#endif
#if defined(_FLIPBOOK_BLENDING)
float3 texcoord2AndBlend : TEXCOORD4;
#endif
#if defined(SOFTPARTICLES_ON) || defined(_FADING_ON)
float4 projectedPosition : TEXCOORD5;
#endif
float4 posWS : TEXCOORD6; // xyz: position; w = fogFactor;
float4 clipPos : SV_POSITION;
};
void InitializeSurfaceData(VertexOutputLit IN, out SurfaceOutputStandard surfaceData)
{
Input input;
input.color = IN.color;
input.texcoord = IN.texcoord;
#if defined(_FLIPBOOK_BLENDING)
input.texcoord2AndBlend = IN.texcoord2AndBlend;
#endif
#if defined(SOFTPARTICLES_ON) || defined(_FADING_ON)
input.projectedPosition = IN.projectedPosition;
#endif
// No distortion Support
surfaceData.Normal = half3(0, 0, 1);
surfaceData.Occlusion = 1.0;
surf(input, surfaceData);
}
#include "LightweightParticle.hlsl"
#include "LightweightLighting.hlsl"
float4 clipPosition = UnityObjectToClipPos(v.vertex);
float4 clipPosition = TransformObjectToHClip(v.vertex.xyz);
o.normal = normalize(UnityObjectToWorldNormal(v.normal));
o.normal = normalize(TransformObjectToWorldNormal(v.normal));
o.posWS.xyz = mul(unity_ObjectToWorld, v.vertex).xyz;
o.posWS.w = ComputeFogFactor(clipPosition.z);
o.posWS.xyz = TransformObjectToWorld(v.vertex.xyz).xyz;
o.clipPos = TransformWorldToHClip(o.posWS.xyz);
o.posWS.w = ComputeFogFactor(o.clipPos.z);
vertTexcoord(v, o);
vertFading(o);
o.clipPos = clipPosition;

half4 ParticlesLitFragment(VertexOutputLit IN) : SV_Target
{
SurfaceOutputStandard surfaceData;
SurfaceData surfaceData;
InitializeSurfaceData(IN, surfaceData);
float3 positionWS = IN.posWS.xyz;

#if _NORMALMAP
half3 normalWS = TangentToWorldNormal(surfaceData.Normal, IN.tangent, IN.binormal, IN.normal);
half3 normalWS = TangentToWorldNormal(surfaceData.normal, IN.tangent, IN.binormal, IN.normal);
half4 color = LightweightFragmentPBR(positionWS, normalWS, viewDirWS, /*indirectDiffuse*/ zero, /*vertex lighting*/ zero, surfaceData.Albedo,
surfaceData.Metallic, /* specularColor */ zero, surfaceData.Smoothness, surfaceData.Occlusion, surfaceData.Emission, surfaceData.Alpha);
half4 color = LightweightFragmentPBR(positionWS, normalWS, viewDirWS, /*indirectDiffuse*/ zero, /*vertex lighting*/ zero, surfaceData.albedo,
surfaceData.metallic, /* specularColor */ zero, surfaceData.smoothness, surfaceData.occlusion, surfaceData.emission, surfaceData.alpha);
return OUTPUT_COLOR(color);
return color;
ENDCG
ENDHLSL
Fallback "LightweightPipeline/Unlit"
Fallback "LightweightPipeline/Particles/Standard Unlit"
CustomEditor "LightweightStandardParticlesShaderGUI"
}

30
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightStandardSimpleLighting.shader


Blend[_SrcBlend][_DstBlend]
ZWrite[_ZWrite]
CGPROGRAM
HLSLPROGRAM
#pragma target 3.0
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON
#pragma shader_feature _ _SPECGLOSSMAP _SPECULAR_COLOR

#pragma multi_compile _MAIN_DIRECTIONAL_LIGHT _MAIN_SPOT_LIGHT
#pragma multi_compile _ _ADDITIONAL_LIGHTS
#pragma multi_compile _ _MIXED_LIGHTING_SUBTRACTIVE
#pragma multi_compile _ UNITY_SINGLE_PASS_STEREO STEREO_INSTANCING_ON STEREO_MULTIVIEW_ON
#pragma multi_compile _ UNITY_SINGLE_PASS_STEREO STEREO_INSTANCING_ENABLED STEREO_MULTIVIEW_ENABLED
#pragma multi_compile_instancing
#include "LightweightPassLit.cginc"
ENDCG
#include "LightweightPassLit.hlsl"
ENDHLSL
}
Pass

ZWrite On ZTest LEqual
CGPROGRAM
HLSLPROGRAM
#include "UnityCG.cginc"
#include "LightweightPassShadow.cginc"
ENDCG
#include "LightweightPassShadow.hlsl"
ENDHLSL
}
Pass

ZWrite On
ColorMask 0
CGPROGRAM
HLSLPROGRAM
#include "UnityCG.cginc"
#include "LightweightCore.hlsl"
return UnityObjectToClipPos(pos);
return TransformObjectToHClip(pos.xyz);
}
half4 frag() : SV_TARGET

ENDCG
ENDHLSL
}
// This pass it not used during regular rendering, only for lightmap baking.

Cull Off
CGPROGRAM
HLSLPROGRAM
#define UNITY_SETUP_BRDF_INPUT SpecularSetup
#pragma vertex LightweightVertexMeta
#pragma fragment LightweightFragmentMetaSimple

#include "LightweightPassMeta.cginc"
ENDCG
#include "LightweightPassMeta.hlsl"
ENDHLSL
}
}
Fallback "Hidden/InternalErrorShader"

25
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightUnlit.shader


Pass
{
CGPROGRAM
HLSLPROGRAM
#pragma multi_compile _ UNITY_SINGLE_PASS_STEREO STEREO_INSTANCING_ON STEREO_MULTIVIEW_ON
#pragma multi_compile _ UNITY_SINGLE_PASS_STEREO STEREO_INSTANCING_ENABLE STEREO_MULTIVIEW_ENABLE
#include "LightweightCore.cginc"
#include "LightweightSurfaceInput.cginc"
#include "LightweightCore.hlsl"
#include "LightweightSurfaceInput.hlsl"
struct VertexInput
{

float3 normal : NORMAL;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct VertexOutput

#endif
#endif
float4 vertex : SV_POSITION;
UNITY_VERTEX_OUTPUT_STEREO
};
VertexOutput vert(VertexInput v)

UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
o.vertex = UnityObjectToClipPos(v.vertex);
o.vertex = TransformObjectToHClip(v.vertex.xyz);
o.uv0AndFogCoord.xy = TRANSFORM_TEX(v.uv, _MainTex);
o.uv0AndFogCoord.z = ComputeFogFactor(o.vertex.z);

return o;
}
fixed4 frag(VertexOutput IN) : SV_Target
half4 frag(VertexOutput IN) : SV_Target
half4 texColor = tex2D(_MainTex, uv);
half4 texColor = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv);
half3 color = texColor.rgb * _Color.rgb;
half alpha = texColor.a * _Color.a;

ApplyFog(color, IN.uv0AndFogCoord.z);
#ifdef _ALPHABLEND_ON
return fixed4(color, alpha);
return half4(color, alpha);
return fixed4(color, 1.0);
return half4(color, 1.0);
ENDCG
ENDHLSL
}
}
CustomEditor "LightweightUnlitGUI"

98
ScriptableRenderPipeline/Core/ShaderLibrary/API/GLES3.hlsl


// This file assume SHADER_API_GLES3 is defined
#define UNITY_UV_STARTS_AT_TOP 0
#define UNITY_REVERSED_Z 0
#define UNITY_GATHER_SUPPORTED 0
#define UNITY_NEAR_CLIP_VALUE (-1.0)
// This value will not go through any matrix projection convertion
#define UNITY_RAW_FAR_CLIP_VALUE (1.0)
#define FRONT_FACE_SEMATIC VFACE
#define FRONT_FACE_TYPE float
#define IS_FRONT_VFACE(VAL, FRONT, BACK) ((VAL > 0.0) ? (FRONT) : (BACK))
#define CBUFFER_START(name)
#define CBUFFER_END
// Initialize arbitrary structure with zero values.
// Do not exist on some platform, in this case we need to have a standard name that call a function that will initialize all parameters to 0
#define ZERO_INITIALIZE(type, name) name = (type)0;
#define ZERO_INITIALIZE_ARRAY(type, name, arraySize) { for (int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++) { name[arrayIndex] = (type)0; } }
// Texture util abstraction
#define CALCULATE_TEXTURE2D_LOD(textureName, samplerName, coord2) // TODO:
// Texture abstraction
#define TEXTURE2D(textureName) sampler2D textureName
#define TEXTURE2D_ARRAY(textureName) sampler2DArray textureName
#define TEXTURECUBE(textureName) samplerCUBE textureName
#define TEXTURECUBE_ARRAY(textureName) samplerCUBEArray textureName
#define TEXTURE3D(textureName) sampler3D textureName
#define TEXTURE2D_SHADOW(textureName) sampler2DShadow textureName
#define RW_TEXTURE2D(type, textureNam)
#define SAMPLER2D(samplerName)
#define SAMPLERCUBE(samplerName)
#define SAMPLER3D(samplerName)
#define SAMPLER2D_SHADOW(samplerName)
#define SAMPLERCUBE_SHADOW(samplerName)
#define TEXTURE2D_ARGS(textureName, samplerName) sampler2D textureName
#define TEXTURE2D_ARRAY_ARGS(textureName, samplerName) sampler2DArray textureName
#define TEXTURECUBE_ARGS(textureName, samplerName) samplerCUBE textureName
#define TEXTURECUBE_ARRAY_ARGS(textureName, samplerName) samplerCUBEArray textureName
#define TEXTURE3D_ARGS(textureName, samplerName) sampler3D textureName
#define TEXTURE2D_SHADOW_ARGS(textureName, samplerName) sampler2DShadow textureName
#define TEXTURE2D_ARRAY_SHADOW_ARGS(textureName, samplerName) sampler2DArrayShadow textureName
#define TEXTURECUBE_SHADOW_ARGS(textureName, samplerName) samplerCUBEArrayShadow textureName
#define TEXTURE2D_PARAM(textureName, samplerName) textureName
#define TEXTURE2D_ARRAY_PARAM(textureName, samplerName) textureName
#define TEXTURECUBE_PARAM(textureName, samplerName) textureName
#define TEXTURECUBE_ARRAY_PARAM(textureName, samplerName) textureName
#define TEXTURE3D_PARAM(textureName, samplerName) textureName
#define TEXTURE2D_SHADOW_PARAM(textureName, samplerName) textureName
#define TEXTURE2D_ARRAY_SHADOW_PARAM(textureName, samplerName) textureName
#define TEXTURECUBE_SHADOW_PARAM(textureName, samplerName) textureName
#define SAMPLE_TEXTURE2D(textureName, samplerName, coord2) tex2D(textureName, coord2)
#define SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod) tex2Dlod(textureName, float4(coord2, 0, lod))
#define SAMPLE_TEXTURE2D_BIAS(textureName, samplerName, coord2, bias) tex2Dbias(textureName, float4(coord2, 0, bias))
#define SAMPLE_TEXTURE2D_GRAD(textureName, samplerName, coord2, ddx, ddy) tex2Dgrad(coord2.x, coord2.y, ddx, ddy)
#define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) tex2DArray(textureName, float3(coord2, index))
#define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) tex2DArraylod(textureName, float4(coord2, index, lod))
#define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) tex2DArraybias(textureName, float4(coord2, index, bias))
#define SAMPLE_TEXTURECUBE(textureName, samplerName, coord3) texCUBE(textureName, coord3)
#define SAMPLE_TEXTURECUBE_LOD(textureName, samplerName, coord3, lod) texCUBElod(textureName, float4(coord3, lod))
#define SAMPLE_TEXTURECUBE_BIAS(textureName, samplerName, coord3, bias) texCUBEbias(textureName, float4(coord3, bias))
#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) // TODO:
#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) // TODO:
#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) // TODO:
#define SAMPLE_TEXTURE3D(textureName, samplerName, coord3) tex3D(textureName, coord3)
#define SAMPLE_TEXTURE2D_SHADOW(textureName, samplerName, coord3) shadow2D(textureName, coord3)
#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) // TODO:
#define SAMPLE_TEXTURECUBE_SHADOW(textureName, samplerName, coord4) ((texCUBE(tex,(coord).xyz) < (coord).w) ? 0.0 : 1.0)
#define SAMPLE_TEXTURECUBE_ARRAY_SHADOW(textureName, samplerName, coord4, index) // TODO:
#define SAMPLE_DEPTH_TEXTURE(textureName, samplerName, coord2) SAMPLE_TEXTURE2D(textureName, samplerName, coord2).r
#define SAMPLE_DEPTH_TEXTURE_LOD(textureName, samplerName, coord2, lod) SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod).r
#define TEXTURE2D_HALF TEXTURE2D
#define TEXTURE2D_FLOAT TEXTURE2D
#define TEXTURE3D_HALF TEXTURE3D
#define TEXTURE3D_FLOAT TEXTURE3D
#define SAMPLER2D_HALF SAMPLER2D
#define SAMPLER2D_FLOAT SAMPLER2D
#define LOAD_TEXTURE2D(textureName, unCoord2) textureName.Load(int3(unCoord2, 0))
#define LOAD_TEXTURE2D_LOD(textureName, unCoord2, lod) textureName.Load(int3(unCoord2, lod))
#define LOAD_TEXTURE2D_MSAA(textureName, unCoord2, sampleIndex) textureName.Load(unCoord2, sampleIndex)
#define LOAD_TEXTURE2D_ARRAY(textureName, unCoord2, index) textureName.Load(int4(unCoord2, index, 0))
#define LOAD_TEXTURE2D_ARRAY_LOD(textureName, unCoord2, index, lod) textureName.Load(int4(unCoord2, index, lod))
#define GATHER_TEXTURE2D(textureName, samplerName, coord2)
#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index)
#define GATHER_TEXTURECUBE(textureName, samplerName, coord3)
#define GATHER_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index)

10
ScriptableRenderPipeline/Core/ShaderLibrary/API/GLES3.hlsl.meta


fileFormatVersion: 2
guid: 14a46e0dac04a0245b3f95359167b663
timeCreated: 1506072929
licenseType: Pro
ShaderImporter:
externalObjects: {}
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

8
ScriptableRenderPipeline/Core/ShaderLibrary/ShaderVariables.meta


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

199
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightCore.hlsl


#ifndef LIGHTWEIGHT_PIPELINE_CORE_INCLUDED
#define LIGHTWEIGHT_PIPELINE_CORE_INCLUDED
#include "ShaderVariables\LightweightShaderVariables.hlsl"
#include "ShaderLibrary\Common.hlsl"
#include "ShaderLibrary\EntityLighting.hlsl"
#ifdef _NORMALMAP
#define OUTPUT_NORMAL(IN, OUT) OutputTangentToWorld(IN.tangent, IN.normal, OUT.tangent, OUT.binormal, OUT.normal)
#else
#define OUTPUT_NORMAL(IN, OUT) OUT.normal = TransformObjectToWorldNormal(IN.normal)
#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 = EvaluateSHPerVertex(normalWS)
#endif
#if defined(UNITY_REVERSED_Z)
#if UNITY_REVERSED_Z == 1
//D3d with reversed Z => z clip range is [near, 0] -> remapping to [0, far]
//max is required to protect ourselves from near plane not being correct/meaningfull in case of oblique matrices.
#define UNITY_Z_0_FAR_FROM_CLIPSPACE(coord) max(((1.0-(coord)/_ProjectionParams.y)*_ProjectionParams.z),0)
#else
//GL with reversed z => z clip range is [near, -far] -> should remap in theory but dont do it in practice to save some perf (range is close enough)
#define UNITY_Z_0_FAR_FROM_CLIPSPACE(coord) max(-(coord), 0)
#endif
#elif UNITY_UV_STARTS_AT_TOP
//D3d without reversed z => z clip range is [0, far] -> nothing to do
#define UNITY_Z_0_FAR_FROM_CLIPSPACE(coord) (coord)
#else
//Opengl => z clip range is [-near, far] -> should remap in theory but dont do it in practice to save some perf (range is close enough)
#define UNITY_Z_0_FAR_FROM_CLIPSPACE(coord) (coord)
#endif
half Pow4(half x)
{
return x * x * x * x;
}
half LerpOneTo(half b, half t)
{
half oneMinusT = 1 - t;
return oneMinusT + b * t;
}
void AlphaDiscard(half alpha, half cutoff)
{
#ifdef _ALPHATEST_ON
clip(alpha - cutoff);
#endif
}
half3 SafeNormalize(half3 inVec)
{
half dp3 = max(1.e-4h, dot(inVec, inVec));
return inVec * rsqrt(dp3);
}
half3 UnpackNormalScale(half4 packednormal, half bumpScale)
{
#if defined(UNITY_NO_DXT5nm)
half3 normal = packednormal.xyz * 2 - 1;
#if (SHADER_TARGET >= 30)
// SM2.0: instruction count limitation
// SM2.0: normal scaler is not supported
normal.xy *= bumpScale;
#endif
return normal;
#else
// This do the trick
packednormal.x *= packednormal.w;
half3 normal;
normal.xy = (packednormal.xy * 2 - 1);
#if (SHADER_TARGET >= 30)
// SM2.0: instruction count limitation
// SM2.0: normal scaler is not supported
normal.xy *= bumpScale;
#endif
normal.z = sqrt(1.0 - saturate(dot(normal.xy, normal.xy)));
return normal;
#endif
}
half3 SampleSH(half3 normalWS)
{
// LPPV is not supported in Ligthweight Pipeline
float4 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 SampleSH9(SHCoefficients, normalWS);
}
half3 EvaluateSHPerVertex(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);
}
half3 EvaluateSHPerPixel(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 max(half3(0, 0, 0), SampleSH(normalWS));
}
half3 SampleGI(float4 sampleData, half3 normalWS)
{
#ifdef LIGHTMAP_ON
// Only baked GI is sample as dynamic GI is not supported in Lightweight
#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),
sampleData.xy, transformCoords, normalWS, encodedLightmap);
#else
return SampleSingleLightmap(TEXTURE2D_PARAM(unity_Lightmap, samplerunity_Lightmap), sampleData.xy, transformCoords, encodedLightmap);
#endif
#endif // LIGHTMAP_ON
// If lightmap is not enabled we sample GI from SH
return EvaluateSHPerPixel(sampleData.xyz, normalWS);
}
void OutputTangentToWorld(half4 vertexTangent, half3 vertexNormal, out half3 tangentWS, out half3 binormalWS, out half3 normalWS)
{
half sign = vertexTangent.w * GetOddNegativeScale();
normalWS = TransformObjectToWorldNormal(vertexNormal);
tangentWS = normalize(mul((half3x3)unity_ObjectToWorld, vertexTangent.xyz));
binormalWS = cross(normalWS, tangentWS) * sign;
}
half3 TangentToWorldNormal(half3 normalTangent, half3 tangent, half3 binormal, half3 normal)
{
half3x3 tangentToWorld = half3x3(tangent, binormal, normal);
return normalize(mul(normalTangent, tangentToWorld));
}
float ComputeFogFactor(float z)
{
float clipZ_01 = UNITY_Z_0_FAR_FROM_CLIPSPACE(z);
#if defined(FOG_LINEAR)
// factor = (end-z)/(end-start) = z * (-1/(end-start)) + (end/(end-start))
float fogFactor = saturate(clipZ_01 * unity_FogParams.z + unity_FogParams.w);
return half(fogFactor);
#elif defined(FOG_EXP)
// factor = exp(-density*z)
float unityFogFactor = unity_FogParams.y * clipZ_01;
return half(saturate(exp2(-unityFogFactor)));
#elif defined(FOG_EXP2)
// factor = exp(-(density*z)^2)
float unityFogFactor = unity_FogParams.x * clipZ_01;
return half(saturate(exp2(-unityFogFactor*unityFogFactor)));
#else
return 0.0h;
#endif
}
void ApplyFog(inout half3 color, half fogFactor)
{
#if defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2)
color = lerp(unity_FogColor, color, fogFactor);
#endif
}
#endif

69
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightInput.hlsl


#ifndef LIGHTWEIGHT_INPUT_INCLUDED
#define LIGHTWEIGHT_INPUT_INCLUDED
#define MAX_VISIBLE_LIGHTS 16
struct LightInput
{
float4 pos;
half3 color;
half4 distanceAttenuation;
half4 spotDirection;
half4 spotAttenuation;
};
// Main light initialized without indexing
#define INITIALIZE_MAIN_LIGHT(light) \
light.pos = _MainLightPosition; \
light.color = _MainLightColor.rgb; \
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].rgb; \
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)
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
sampler2D _MainLightCookie;
// 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

425
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightLighting.hlsl


#ifndef LIGHTWEIGHT_LIGHTING_INCLUDED
#define LIGHTWEIGHT_LIGHTING_INCLUDED
#include "LightweightCore.hlsl"
#include "LightweightShadows.hlsl"
#include "ShaderLibrary\ImageBasedLighting.hlsl"
#define kDieletricSpec half4(0.04, 0.04, 0.04, 1.0 - 0.04) // standard dielectric reflectivity coef at incident angle (= 4%)
#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)
#if SHADER_TARGET < 30
// 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
///////////////////////////////////////////////////////////////////////////////
// BRDF Functions //
///////////////////////////////////////////////////////////////////////////////
struct BRDFData
{
half3 diffuse;
half3 specular;
half perceptualRoughness;
half roughness;
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 = 1.0h - smoothness;
outBRDFData.roughness = outBRDFData.perceptualRoughness * outBRDFData.perceptualRoughness;
#ifdef _ALPHAPREMULTIPLY_ON
outBRDFData.diffuse *= alpha;
alpha = alpha * oneMinusReflectivity + reflectivity;
#endif
}
half3 LightweightEnvironmentBRDF(BRDFData brdfData, half3 indirectDiffuse, half3 indirectSpecular, half roughness2, half fresnelTerm)
{
half3 c = indirectDiffuse * brdfData.diffuse;
float surfaceReduction = 1.0 / (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 LightweightDirectBDRF(BRDFData brdfData, half roughness2, half3 normal, half3 lightDirection, half3 viewDir)
{
#ifndef _SPECULARHIGHLIGHTS_OFF
half3 halfDir = SafeNormalize(lightDirection + viewDir);
half NoH = saturate(dot(normal, halfDir));
half LoH = saturate(dot(lightDirection, 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 * (roughness2 - 1.h) + 1.00001h;
half LoH2 = LoH * LoH;
half specularTerm = 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 - 1e-4h;
#endif
#if defined (SHADER_API_MOBILE)
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
}
///////////////////////////////////////////////////////////////////////////////
// Attenuation Functions /
///////////////////////////////////////////////////////////////////////////////
half CookieAttenuation(float3 worldPos)
{
#ifdef _MAIN_LIGHT_COOKIE
#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;
}
// Matches Unity Vanila attenuation
// Attenuation smoothly decreases to light range.
half DistanceAttenuation(half distanceSqr, half4 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);
return saturate(SdotL * spotAttenuation.x + spotAttenuation.y);
}
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);
// normalized light dir
lightDirection = half3(posToLightVec * rsqrt(distanceSqr));
half lightAtten = DistanceAttenuation(distanceSqr, lightInput.distanceAttenuation);
lightAtten *= SpotAttenuation(lightInput.spotDirection.xyz, lightDirection, lightInput.spotAttenuation);
return lightAtten;
}
inline half GetMainLightDirectionAndRealtimeAttenuation(LightInput lightInput, half3 normalWS, float3 positionWS, out half3 lightDirection)
{
#ifdef _MAIN_DIRECTIONAL_LIGHT
// Light pos holds normalized light dir
lightDirection = lightInput.pos.xyz;
half attenuation = 1.0;
#else
half attenuation = GetLightDirectionAndRealtimeAttenuation(lightInput, normalWS, positionWS, lightDirection);
#endif
// Cookies and shadows are only computed for main light
attenuation *= CookieAttenuation(positionWS);
attenuation *= LIGHTWEIGHT_SHADOW_ATTENUATION(positionWS, normalWS, lightDirection);
return attenuation;
}
///////////////////////////////////////////////////////////////////////////////
// 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);
#if defined(_VERTEX_LIGHTS)
int vertexLightStart = _AdditionalLightCount.x;
int vertexLightEnd = min(_AdditionalLightCount.y, unity_LightIndicesOffsetAndCount.y);
for (int lightIter = vertexLightStart; lightIter < vertexLightEnd; ++lightIter)
{
LightInput light;
INITIALIZE_LIGHT(light, lightIter);
half3 lightDirection;
half atten = GetLightDirectionAndRealtimeAttenuation(light, normalWS, positionWS, lightDirection);
half3 lightColor = light.color * atten;
vertexLightColor += LightingLambert(lightColor, lightDirection, normalWS);
}
#endif
return vertexLightColor;
}
///////////////////////////////////////////////////////////////////////////////
// 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 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
return _GlossyEnvironmentColor.rgb * 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);
BRDFData brdfData;
InitializeBRDFData(albedo, metallic, specular, smoothness, alpha, brdfData);
half3 lightDirectionWS;
LightInput mainLight;
INITIALIZE_MAIN_LIGHT(mainLight);
// 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;
half fresnelTerm = Pow4(1.0 - saturate(dot(normalWS, viewDirectionWS)));
half3 color = LightweightEnvironmentBRDF(brdfData, indirectDiffuse, indirectSpecular, roughness2, fresnelTerm);
half mainLightAtten = MixRealtimeAndBakedOcclusion(realtimeMainLightAtten, bakedOcclusion, mainLight.distanceAttenuation);
radiance *= mainLightAtten;
color += LightweightDirectBDRF(brdfData, roughness2, normalWS, lightDirectionWS, viewDirectionWS) * radiance;
color += vertexLighting * brdfData.diffuse;
#ifdef _ADDITIONAL_LIGHTS
int pixelLightCount = min(_AdditionalLightCount.x, unity_LightIndicesOffsetAndCount.y);
for (int lightIter = 0; lightIter < pixelLightCount; ++lightIter)
{
LightInput light;
INITIALIZE_LIGHT(light, lightIter);
half lightAttenuation = GetLightDirectionAndRealtimeAttenuation(light, normalWS, positionWS, lightDirectionWS);
lightAttenuation = MixRealtimeAndBakedOcclusion(lightAttenuation, bakedOcclusion, light.distanceAttenuation);
half NdotL = saturate(dot(normalWS, lightDirectionWS));
half3 radiance = light.color * (lightAttenuation * NdotL);
color += LightweightDirectBDRF(brdfData, roughness2, normalWS, lightDirectionWS, viewDirectionWS) * radiance;
}
#endif
color += emission;
return half4(color, 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 lightDirection;
LightInput mainLight;
INITIALIZE_MAIN_LIGHT(mainLight);
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;
#ifdef _ADDITIONAL_LIGHTS
int pixelLightCount = min(_AdditionalLightCount.x, unity_LightIndicesOffsetAndCount.y);
for (int lightIter = 0; lightIter < pixelLightCount; ++lightIter)
{
LightInput light;
INITIALIZE_LIGHT(light, lightIter);
half lightAttenuation = GetLightDirectionAndRealtimeAttenuation(light, normalWS, positionWS, lightDirection);
lightAttenuation = MixRealtimeAndBakedOcclusion(lightAttenuation, bakedOcclusion, light.distanceAttenuation);
half3 attenuatedLightColor = light.color * lightAttenuation;
diffuseColor += LightingLambert(attenuatedLightColor, lightDirection, normalWS);
}
#endif
half3 finalColor = diffuseColor * diffuse + emission;
// Computes Fog Factor per vextex
ApplyFog(finalColor, fogFactor);
return half4(finalColor, 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 lightDirection;
LightInput mainLight;
INITIALIZE_MAIN_LIGHT(mainLight);
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;
half3 specularColor = LightingSpecular(mainLight.color * mainLightAtten, lightDirection, normalWS, viewDirectionWS, specularGloss, shininess);
#ifdef _ADDITIONAL_LIGHTS
int pixelLightCount = min(_AdditionalLightCount.x, unity_LightIndicesOffsetAndCount.y);
for (int lightIter = 0; lightIter < pixelLightCount; ++lightIter)
{
LightInput light;
INITIALIZE_LIGHT(light, lightIter);
half lightAttenuation = GetLightDirectionAndRealtimeAttenuation(light, normalWS, positionWS, lightDirection);
lightAttenuation = MixRealtimeAndBakedOcclusion(lightAttenuation, bakedOcclusion, light.distanceAttenuation);
half3 attenuatedLightColor = light.color * lightAttenuation;
diffuseColor += LightingLambert(attenuatedLightColor, lightDirection, normalWS);
specularColor += LightingSpecular(attenuatedLightColor, lightDirection, normalWS, viewDirectionWS, specularGloss, shininess);
}
#endif
half3 finalColor = diffuseColor * diffuse + emission;
finalColor += specularColor;
// Computes Fog Factor per vextex
ApplyFog(finalColor, fogFactor);
return half4(finalColor, alpha);
}
#endif

214
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightParticle.hlsl


#include "LightweightCore.hlsl"
#include "LightweightSurfaceInput.hlsl"
#if defined (_COLORADDSUBDIFF_ON)
half4 _ColorAddSubDiff;
#endif
#if defined(_COLORCOLOR_ON)
half3 RGBtoHSV(half3 arg1)
{
half4 K = half4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
half4 P = lerp(half4(arg1.bg, K.wz), half4(arg1.gb, K.xy), step(arg1.b, arg1.g));
half4 Q = lerp(half4(P.xyw, arg1.r), half4(arg1.r, P.yzx), step(P.x, arg1.r));
half D = Q.x - min(Q.w, Q.y);
half E = 1e-10;
return half3(abs(Q.z + (Q.w - Q.y) / (6.0 * D + E)), D / (Q.x + E), Q.x);
}
half3 HSVtoRGB(half3 arg1)
{
half4 K = half4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
half3 P = abs(frac(arg1.xxx + K.xyz) * 6.0 - K.www);
return arg1.z * lerp(K.xxx, saturate(P - K.xxx), arg1.y);
}
#endif
// Color function
#if defined(UNITY_PARTICLE_INSTANCING_ENABLED)
#define vertColor(c) \
vertInstancingColor(c);
#else
#define vertColor(c)
#endif
// Flipbook vertex function
#if defined(UNITY_PARTICLE_INSTANCING_ENABLED)
#if defined(_FLIPBOOK_BLENDING)
#define vertTexcoord(v, o) \
vertInstancingUVs(v.texcoords.xy, o.texcoord, o.texcoord2AndBlend);
#else
#define vertTexcoord(v, o) \
vertInstancingUVs(v.texcoords.xy, o.texcoord); \
o.texcoord = TRANSFORM_TEX(o.texcoord, _MainTex);
#endif
#else
#if defined(_FLIPBOOK_BLENDING)
#define vertTexcoord(v, o) \
o.texcoord = v.texcoords.xy; \
o.texcoord2AndBlend.xy = v.texcoords.zw; \
o.texcoord2AndBlend.z = v.texcoordBlend;
#else
#define vertTexcoord(v, o) \
o.texcoord = TRANSFORM_TEX(v.texcoords.xy, _MainTex);
#endif
#endif
// Fading vertex function
#if defined(SOFTPARTICLES_ON) || defined(_FADING_ON)
#define vertFading(o) \
o.projectedPosition = ComputeScreenPos (clipPosition); \
COMPUTE_EYEDEPTH(o.projectedPosition.z);
#else
#define vertFading(o)
#endif
// Color blending fragment function
#if defined(_COLOROVERLAY_ON)
#define fragColorMode(albedo, color) \
albedo.rgb = lerp(1 - 2 * (1 - albedo.rgb) * (1 - i.color.rgb), 2 * albedo.rgb * i.color.rgb, step(albedo.rgb, 0.5)); \
albedo.a *= i.color.a;
#elif defined(_COLORCOLOR_ON)
#define fragColorMode(i) \
half3 aHSL = RGBtoHSV(albedo.rgb); \
half3 bHSL = RGBtoHSV(i.color.rgb); \
half3 rHSL = half3(bHSL.x, bHSL.y, aHSL.z); \
albedo = half4(HSVtoRGB(rHSL), albedo.a * i.color.a);
#elif defined(_COLORADDSUBDIFF_ON)
#define fragColorMode(i) \
albedo.rgb = albedo.rgb + i.color.rgb * _ColorAddSubDiff.x; \
albedo.rgb = lerp(albedo.rgb, abs(albedo.rgb), _ColorAddSubDiff.y); \
albedo.a *= i.color.a;
#else
#define fragColorMode(i) \
albedo *= i.color;
#endif
// Pre-multiplied alpha helper
#if defined(_ALPHAPREMULTIPLY_ON)
#define ALBEDO_MUL albedo
#else
#define ALBEDO_MUL albedo.a
#endif
// Soft particles fragment function
#if defined(SOFTPARTICLES_ON) && defined(_FADING_ON)
#define fragSoftParticles(i) \
if (SOFT_PARTICLE_NEAR_FADE > 0.0 || SOFT_PARTICLE_INV_FADE_DISTANCE > 0.0) \
{ \
float sceneZ = LinearEyeDepth (SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.projectedPosition))); \
float fade = saturate (SOFT_PARTICLE_INV_FADE_DISTANCE * ((sceneZ - SOFT_PARTICLE_NEAR_FADE) - i.projectedPosition.z)); \
ALBEDO_MUL *= fade; \
}
#else
#define fragSoftParticles(i)
#endif
// Camera fading fragment function
#if defined(_FADING_ON)
#define fragCameraFading(i) \
float cameraFade = saturate((i.projectedPosition.z - CAMERA_NEAR_FADE) * CAMERA_INV_FADE_DISTANCE); \
ALBEDO_MUL *= cameraFade;
#else
#define fragCameraFading(i)
#endif
// Vertex shader input
struct appdata_particles
{
float4 vertex : POSITION;
float3 normal : NORMAL;
half4 color : COLOR;
#if defined(_FLIPBOOK_BLENDING) && !defined(UNITY_PARTICLE_INSTANCING_ENABLED)
float4 texcoords : TEXCOORD0;
float texcoordBlend : TEXCOORD1;
#else
float2 texcoords : TEXCOORD0;
#endif
#if defined(_NORMALMAP)
float4 tangent : TANGENT;
#endif
};
struct VertexOutputLit
{
half4 color : COLOR;
float2 texcoord : TEXCOORD0;
#if _NORMALMAP
half3 tangent : TEXCOORD1;
half3 binormal : TEXCOORD2;
half3 normal : TEXCOORD3;
#else
half3 normal : TEXCOORD1;
#endif
#if defined(_FLIPBOOK_BLENDING)
float3 texcoord2AndBlend : TEXCOORD4;
#endif
#if defined(SOFTPARTICLES_ON) || defined(_FADING_ON)
float4 projectedPosition : TEXCOORD5;
#endif
float4 posWS : TEXCOORD6; // xyz: position; w = fogFactor;
float4 clipPos : SV_POSITION;
};
half4 readTexture(TEXTURE2D_ARGS(_Texture, sampler_Texture), VertexOutputLit IN)
{
half4 color = SAMPLE_TEXTURE2D(_Texture, sampler_Texture, IN.texcoord);
#ifdef _FLIPBOOK_BLENDING
half4 color2 = SAMPLE_TEXTURE2D(_Texture, sampler_Texture, IN.texcoord2AndBlend.xy);
color = lerp(color, color2, IN.texcoord2AndBlend.z);
#endif
return color;
}
void InitializeSurfaceData(VertexOutputLit IN, out SurfaceData surfaceData)
{
half4 albedo = readTexture(_MainTex, sampler_MainTex, IN) * IN.color;
// No distortion Support
fragColorMode(IN);
fragSoftParticles(IN);
fragCameraFading(IN);
#if defined(_METALLICGLOSSMAP)
half2 metallicGloss = readTexture(_MetallicGlossMap, sampler_MetallicGlossMap, IN).ra * half2(1.0, _Glossiness);
#else
half2 metallicGloss = half2(_Metallic, _Glossiness);
#endif
#if defined(_NORMALMAP)
float3 normal = normalize(UnpackNormalScale(readTexture(_BumpMap, sampler_BumpMap, IN), _BumpScale));
#else
float3 normal = float3(0, 0, 1);
#endif
#if defined(_EMISSION)
half3 emission = readTexture(_EmissionMap, sampler_EmissionMap, IN).rgb;
#else
half3 emission = 0;
#endif
surfaceData.albedo = albedo.rbg;
surfaceData.specular = half3(0, 0, 0);
surfaceData.normal = normal;
surfaceData.emission = emission * _EmissionColor.rgb;
surfaceData.metallic = metallicGloss.r;
surfaceData.smoothness = metallicGloss.g;
surfaceData.occlusion = 1.0;
#if defined(_ALPHABLEND_ON) || defined(_ALPHAPREMULTIPLY_ON) || defined(_ALPHAOVERLAY_ON)
surfaceData.alpha = albedo.a;
#else
surfaceData.alpha = 1;
#endif
#if defined(_ALPHAMODULATE_ON)
surfaceData.albedo = lerp(half3(1.0, 1.0, 1.0), surfaceData.albedo, surfaceData.alpha);
#endif
#if defined(_ALPHATEST_ON)
clip(surfaceData.alpha - _Cutoff + 0.0001);
#endif
}

9
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightParticle.hlsl.meta


fileFormatVersion: 2
guid: 58997c4bd657ad848919e91029ee01eb
timeCreated: 1488965025
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

133
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassLit.hlsl


#ifndef LIGHTWEIGHT_PASS_LIT_INCLUDED
#define LIGHTWEIGHT_PASS_LIT_INCLUDED
#include "LightweightSurfaceInput.hlsl"
#include "LightweightLighting.hlsl"
struct LightweightVertexInput
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 tangent : TANGENT;
float2 texcoord : TEXCOORD0;
float2 lightmapUV : TEXCOORD1;
};
struct LightweightVertexOutput
{
float2 uv : TEXCOORD0;
float4 lightmapUVOrVertexSH : TEXCOORD1; // holds either lightmapUV or vertex SH. depending on LIGHTMAP_ON
float3 posWS : TEXCOORD2;
half3 normal : TEXCOORD3;
#if _NORMALMAP
half3 tangent : TEXCOORD4;
half3 binormal : TEXCOORD5;
#endif
half3 viewDir : TEXCOORD6;
half4 fogFactorAndVertexLight : TEXCOORD7; // x: fogFactor, yzw: vertex light
float4 clipPos : SV_POSITION;
//UNITY_VERTEX_OUTPUT_STEREO
};
///////////////////////////////////////////////////////////////////////////////
// Vertex and Fragment functions //
///////////////////////////////////////////////////////////////////////////////
// Vertex: Used for Standard and StandardSimpleLighting shaders
LightweightVertexOutput LitPassVertex(LightweightVertexInput v)
{
LightweightVertexOutput o = (LightweightVertexOutput)0;
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
o.posWS = TransformObjectToWorld(v.vertex.xyz);
o.clipPos = TransformWorldToHClip(o.posWS);
o.viewDir = SafeNormalize(_WorldSpaceCameraPos - o.posWS);
// initializes o.normal and if _NORMALMAP also o.tangent and o.binormal
OUTPUT_NORMAL(v, o);
// We either sample GI from lightmap or SH. lightmap UV and vertex SH coefficients
// are packed in lightmapUVOrVertexSH to save interpolator.
// The following funcions initialize
OUTPUT_LIGHTMAP_UV(v.lightmapUV, unity_LightmapST, o.lightmapUVOrVertexSH);
OUTPUT_SH(o.normal, o.lightmapUVOrVertexSH);
half3 vertexLight = VertexLighting(o.posWS, o.normal);
half fogFactor = ComputeFogFactor(o.clipPos.z);
o.fogFactorAndVertexLight = half4(fogFactor, vertexLight);
return o;
}
// Used for Standard shader
half4 LitPassFragment(LightweightVertexOutput IN) : SV_Target
{
SurfaceData surfaceData;
InitializeStandardLitSurfaceData(IN.uv, surfaceData);
#if _NORMALMAP
half3 normalWS = TangentToWorldNormal(surfaceData.normal, IN.tangent, IN.binormal, IN.normal);
#else
half3 normalWS = normalize(IN.normal);
#endif
half3 indirectDiffuse = SampleGI(IN.lightmapUVOrVertexSH, normalWS);
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;
}
// Used for StandardSimpleLighting shader
half4 LitPassFragmentSimple(LightweightVertexOutput IN) : SV_Target
{
float2 uv = IN.uv;
half4 diffuseAlpha = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv);
half3 diffuse = diffuseAlpha.rgb * _Color.rgb;
#ifdef _GLOSSINESS_FROM_BASE_ALPHA
half alpha = _Color.a;
#else
half alpha = diffuseAlpha.a * _Color.a;
#endif
AlphaDiscard(alpha, _Cutoff);
#if _NORMALMAP
half3 normalTangent = Normal(uv);
half3 normalWS = TangentToWorldNormal(normalTangent, IN.tangent, IN.binormal, IN.normal);
#else
half3 normalWS = normalize(IN.normal);
#endif
half3 emission = Emission(uv);
half3 viewDirectionWS = SafeNormalize(IN.viewDir.xyz);
float3 positionWS = IN.posWS.xyz;
half3 diffuseGI = SampleGI(IN.lightmapUVOrVertexSH, normalWS);
#if _VERTEX_LIGHTS
diffuseGI += IN.fogFactorAndVertexLight.yzw;
#endif
half shininess = _Shininess * 128.0h;
half fogFactor = IN.fogFactorAndVertexLight.x;
#if defined(_SPECGLOSSMAP) || defined(_SPECULAR_COLOR)
half4 specularGloss = SpecularGloss(uv, diffuseAlpha.a);
return LightweightFragmentBlinnPhong(positionWS, normalWS, viewDirectionWS, fogFactor, diffuseGI, diffuse, specularGloss, shininess, emission, alpha);
#else
return LightweightFragmentLambert(positionWS, normalWS, viewDirectionWS, fogFactor, diffuseGI, diffuse, emission, alpha);
#endif
};
#endif

123
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassMeta.hlsl


#ifndef LIGHTWEIGHT_PASS_META_INCLUDED
#define LIGHTWEIGHT_PASS_META_INCLUDED
#include "LightweightSurfaceInput.hlsl"
#include "LightweightLighting.hlsl"
CBUFFER_START(UnityMetaPass)
// x = use uv1 as raster position
// y = use uv2 as raster position
bool4 unity_MetaVertexControl;
// x = return albedo
// y = return normal
bool4 unity_MetaFragmentControl;
CBUFFER_END
float unity_OneOverOutputBoost;
float unity_MaxOutputValue;
float unity_UseLinearSpace;
struct MetaInput
{
half3 Albedo;
half3 Emission;
half3 SpecularColor;
};
struct MetaVertexInput
{
float4 vertex : POSITION;
half3 normal : NORMAL;
float2 uv0 : TEXCOORD0;
float2 uv1 : TEXCOORD1;
float2 uv2 : TEXCOORD2;
#ifdef _TANGENT_TO_WORLD
half4 tangent : TANGENT;
#endif
};
struct MetaVertexOuput
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
float4 MetaVertexPosition(float4 vertex, float2 uv1, float2 uv2, float4 lightmapST, float4 dynlightmapST)
{
if (unity_MetaVertexControl.x)
{
vertex.xy = uv1 * lightmapST.xy + lightmapST.zw;
// OpenGL right now needs to actually use incoming vertex position,
// so use it in a very dummy way
vertex.z = vertex.z > 0 ? 1.0e-4f : 0.0f;
}
if (unity_MetaVertexControl.y)
{
vertex.xy = uv2 * dynlightmapST.xy + dynlightmapST.zw;
// OpenGL right now needs to actually use incoming vertex position,
// so use it in a very dummy way
vertex.z = vertex.z > 0 ? 1.0e-4f : 0.0f;
}
return TransformObjectToHClip(vertex.xyz);
}
half4 MetaFragment(MetaInput IN)
{
half4 res = 0;
if (unity_MetaFragmentControl.x)
{
res = half4(IN.Albedo, 1);
// d3d9 shader compiler doesn't like NaNs and infinity.
unity_OneOverOutputBoost = saturate(unity_OneOverOutputBoost);
// Disable pow(f, e) warning will not work with negative values
#pragma warning (disable : 3571)
// Apply Albedo Boost from LightmapSettings.
res.rgb = clamp(pow(res.rgb, unity_OneOverOutputBoost), 0, unity_MaxOutputValue);
#pragma warning (enable : 3571)
}
if (unity_MetaFragmentControl.y)
{
res = half4(IN.Emission, 1.0);
}
return res;
}
MetaVertexOuput LightweightVertexMeta(MetaVertexInput v)
{
MetaVertexOuput o;
o.pos = MetaVertexPosition(v.vertex, v.uv1.xy, v.uv2.xy, unity_LightmapST, unity_DynamicLightmapST);
o.uv = TRANSFORM_TEX(v.uv0, _MainTex);
return o;
}
half4 LightweightFragmentMeta(MetaVertexOuput i) : SV_Target
{
SurfaceData surfaceData;
InitializeStandardLitSurfaceData(i.uv, surfaceData);
BRDFData brdfData;
InitializeBRDFData(surfaceData.albedo, surfaceData.metallic, surfaceData.specular, surfaceData.smoothness, surfaceData.alpha, brdfData);
MetaInput o;
o.Albedo = brdfData.diffuse + brdfData.specular * brdfData.roughness * 0.5;
o.SpecularColor = surfaceData.specular;
o.Emission = surfaceData.emission;
return MetaFragment(o);
}
half4 LightweightFragmentMetaSimple(MetaVertexOuput i) : SV_Target
{
float2 uv = i.uv;
MetaInput o;
o.Albedo = _Color.rgb * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv).rgb;
o.SpecularColor = SpecularGloss(uv, 1.0).xyz;
o.Emission = Emission(uv);
return MetaFragment(o);
}
#endif

22
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassShadow.hlsl


#ifndef LIGHTWEIGHT_PASS_SHADOW_INCLUDED
#define LIGHTWEIGHT_PASS_SHADOW_INCLUDED
#include "LightweightCore.hlsl"
float4 ShadowPassVertex(float4 pos : POSITION) : SV_POSITION
{
float4 clipPos = TransformObjectToHClip(pos.xyz);
#if defined(UNITY_REVERSED_Z)
clipPos.z = min(clipPos.z, UNITY_NEAR_CLIP_VALUE);
#else
clipPos.z = max(clipPos.z, UNITY_NEAR_CLIP_VALUE);
#endif
return clipPos;
}
half4 ShadowPassFragment() : SV_TARGET
{
return 0;
}
#endif

149
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightShadows.hlsl


#ifndef LIGHTWEIGHT_SHADOWS_INCLUDED
#define LIGHTWEIGHT_SHADOWS_INCLUDED
#include "LightweightInput.hlsl"
#include "ShaderLibrary\Common.hlsl"
#define MAX_SHADOW_CASCADES 4
#if defined(_HARD_SHADOWS) || defined(_SOFT_SHADOWS) || defined(_HARD_SHADOWS_CASCADES) || defined(_SOFT_SHADOWS_CASCADES)
#define _SHADOWS
#endif
#if defined(_HARD_SHADOWS_CASCADES) || defined(_SOFT_SHADOWS_CASCADES)
#define _SHADOW_CASCADES
#endif
#ifdef _SHADOWS
#define LIGHTWEIGHT_SHADOW_ATTENUATION(posWorld, vertexNormal, shadowDir) ComputeShadowAttenuation(posWorld, vertexNormal, shadowDir)
#else
#define LIGHTWEIGHT_SHADOW_ATTENUATION(posWorld, vertexNormal, shadowDir) 1.0h
#endif
// TODO: replace with TEXTURE2D_SHADOW as soon as all APIs defined it.
#if !defined(SHADER_API_GLES) && !defined(SHADER_API_GLES3)
#define TEXTURE2D_SHADOW(tex) TEXTURE2D(tex);
#endif
TEXTURE2D_SHADOW(_ShadowMap);
SAMPLER2D_SHADOW(sampler_ShadowMap);
float4x4 _WorldToShadow[MAX_SHADOW_CASCADES];
float4 _DirShadowSplitSpheres[MAX_SHADOW_CASCADES];
half4 _ShadowOffset0;
half4 _ShadowOffset1;
half4 _ShadowOffset2;
half4 _ShadowOffset3;
half4 _ShadowData; // (x: 1.0 - shadowStrength, y: bias, z: normal bias, w: near plane offset)
float ApplyDepthBias(float clipZ)
{
#ifdef UNITY_REVERSED_Z
return clipZ + _ShadowData.y;
#endif
return clipZ - _ShadowData.y;
}
inline half SampleShadowmap(float4 shadowCoord)
{
float3 coord = shadowCoord.xyz /= shadowCoord.w;
coord.z = saturate(ApplyDepthBias(coord.z));
if (coord.x <= 0 || coord.x >= 1 || coord.y <= 0 || coord.y >= 1)
return 1;
#if defined(_SOFT_SHADOWS) || defined(_SOFT_SHADOWS_CASCADES)
// 4-tap hardware comparison
half4 attenuation;
attenuation.x = SAMPLE_TEXTURE2D_SHADOW(_ShadowMap, sampler_ShadowMap, coord + _ShadowOffset0.xyz);
attenuation.y = SAMPLE_TEXTURE2D_SHADOW(_ShadowMap, sampler_ShadowMap, coord + _ShadowOffset1.xyz);
attenuation.z = SAMPLE_TEXTURE2D_SHADOW(_ShadowMap, sampler_ShadowMap, coord + _ShadowOffset2.xyz);
attenuation.w = SAMPLE_TEXTURE2D_SHADOW(_ShadowMap, sampler_ShadowMap, coord + _ShadowOffset3.xyz);
lerp(attenuation, 1.0, _ShadowData.xxxx);
return dot(attenuation, 0.25);
#else
// 1-tap hardware comparison
half attenuation = SAMPLE_TEXTURE2D_SHADOW(_ShadowMap, sampler_ShadowMap, coord);
return lerp(attenuation, 1.0, _ShadowData.x);
#endif
}
inline half ComputeCascadeIndex(float3 wpos)
{
float3 fromCenter0 = wpos.xyz - _DirShadowSplitSpheres[0].xyz;
float3 fromCenter1 = wpos.xyz - _DirShadowSplitSpheres[1].xyz;
float3 fromCenter2 = wpos.xyz - _DirShadowSplitSpheres[2].xyz;
float3 fromCenter3 = wpos.xyz - _DirShadowSplitSpheres[3].xyz;
float4 distances2 = float4(dot(fromCenter0, fromCenter0), dot(fromCenter1, fromCenter1), dot(fromCenter2, fromCenter2), dot(fromCenter3, fromCenter3));
float4 vDirShadowSplitSphereSqRadii;
vDirShadowSplitSphereSqRadii.x = _DirShadowSplitSpheres[0].w;
vDirShadowSplitSphereSqRadii.y = _DirShadowSplitSpheres[1].w;
vDirShadowSplitSphereSqRadii.z = _DirShadowSplitSpheres[2].w;
vDirShadowSplitSphereSqRadii.w = _DirShadowSplitSpheres[3].w;
half4 weights = half4(distances2 < vDirShadowSplitSphereSqRadii);
weights.yzw = saturate(weights.yzw - weights.xyz);
return 4 - dot(weights, half4(4, 3, 2, 1));
}
inline half ComputeShadowAttenuation(float3 posWorld, half3 vertexNormal, half3 shadowDir)
{
half NdotL = dot(vertexNormal, shadowDir);
half bias = saturate(1.0 - NdotL) * _ShadowData.z;
float3 posWorldOffsetNormal = posWorld + vertexNormal * bias;
int cascadeIndex = 0;
#ifdef _SHADOW_CASCADES
cascadeIndex = ComputeCascadeIndex(posWorldOffsetNormal);
if (cascadeIndex >= MAX_SHADOW_CASCADES)
return 1.0;
#endif
float4 shadowCoord = mul(_WorldToShadow[cascadeIndex], float4(posWorldOffsetNormal, 1.0));
return SampleShadowmap(shadowCoord);
}
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.xyz);
realtimeShadow = lerp(realtimeShadow, lightmap, shadowStrength);
// 3) Pick darkest color
return min(lightmap, realtimeShadow);
}
#endif

168
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightSurfaceInput.hlsl


#ifndef LIGHTWEIGHT_SURFACE_INPUT_INCLUDED
#define LIGHTWEIGHT_SURFACE_INPUT_INCLUDED
#include "LightweightCore.hlsl"
#include "ShaderLibrary/Packing.hlsl"
#include "ShaderLibrary/SampleUVMapping.hlsl"
#ifdef _SPECULAR_SETUP
#define SAMPLE_METALLICSPECULAR(uv) SAMPLE_TEXTURE2D(_SpecGlossMap, sampler_SpecGlossMap, uv)
#else
#define SAMPLE_METALLICSPECULAR(uv) SAMPLE_TEXTURE2D(_MetallicGlossMap, sampler_MetallicGlossMap, uv)
#endif
CBUFFER_START(MaterialProperties)
half4 _MainTex_ST;
half4 _Color;
half _Cutoff;
half _Glossiness;
half _GlossMapScale;
half _SmoothnessTextureChannel;
half _Metallic;
half4 _SpecColor;
half _BumpScale;
half _OcclusionStrength;
half4 _EmissionColor;
half _Shininess;
CBUFFER_END
TEXTURE2D(_MainTex); SAMPLER2D(sampler_MainTex);
TEXTURE2D(_MetallicGlossMap); SAMPLER2D(sampler_MetallicGlossMap);
TEXTURE2D(_SpecGlossMap); SAMPLER2D(sampler_SpecGlossMap);
TEXTURE2D(_BumpMap); SAMPLER2D(sampler_BumpMap);
TEXTURE2D(_OcclusionMap); SAMPLER2D(sampler_OcclusionMap);
TEXTURE2D(_EmissionMap); SAMPLER2D(sampler_EmissionMap);
// Must match Lightweigth ShaderGraph master node
struct SurfaceData
{
half3 albedo;
half3 specular;
half metallic;
half smoothness;
half3 normal;
half3 emission;
half occlusion;
half alpha;
};
///////////////////////////////////////////////////////////////////////////////
// Material Property Helpers //
///////////////////////////////////////////////////////////////////////////////
inline half Alpha(half albedoAlpha)
{
#if defined(_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A)
half alpha = _Color.a;
#else
half alpha = albedoAlpha * _Color.a;
#endif
#if defined(_ALPHATEST_ON)
clip(alpha - _Cutoff);
#endif
return alpha;
}
half3 Normal(float2 uv)
{
#if _NORMALMAP
return UnpackNormalScale(SAMPLE_TEXTURE2D(_BumpMap, sampler_BumpMap, uv), _BumpScale);
#else
return half3(0.0h, 0.0h, 1.0h);
#endif
}
half4 SpecularGloss(half2 uv, half alpha)
{
half4 specularGloss = half4(0, 0, 0, 1);
#ifdef _SPECGLOSSMAP
specularGloss = SAMPLE_TEXTURE2D(_SpecGlossMap, sampler_SpecGlossMap, uv);
specularGloss.rgb = specularGloss.rgb;
#elif defined(_SPECULAR_COLOR)
specularGloss = _SpecColor;
#endif
#ifdef _GLOSSINESS_FROM_BASE_ALPHA
specularGloss.a = alpha;
#endif
return specularGloss;
}
half4 MetallicSpecGloss(float2 uv, half albedoAlpha)
{
half4 specGloss;
#ifdef _METALLICSPECGLOSSMAP
specGloss = specGloss = SAMPLE_METALLICSPECULAR(uv);
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
specGloss.a = albedoAlpha * _GlossMapScale;
#else
specGloss.a *= _GlossMapScale;
#endif
#else // _METALLICSPECGLOSSMAP
#if _SPECULAR_SETUP
specGloss.rgb = _SpecColor.rgb;
#else
specGloss.rgb = _Metallic.rrr;
#endif
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
specGloss.a = albedoAlpha * _GlossMapScale;
#else
specGloss.a = _Glossiness;
#endif
#endif
return specGloss;
}
half Occlusion(float2 uv)
{
#ifdef _OCCLUSIONMAP
#if (SHADER_TARGET < 30)
// SM20: instruction count limitation
// SM20: simpler occlusion
return SAMPLE_TEXTURE2D(_OcclusionMap, sampler_OcclusionMap, uv).g;
#else
half occ = SAMPLE_TEXTURE2D(_OcclusionMap, sampler_OcclusionMap, uv).g;
return LerpOneTo(occ, _OcclusionStrength);
#endif
#else
return 1.0;
#endif
}
half3 Emission(float2 uv)
{
#ifndef _EMISSION
return 0;
#else
return SAMPLE_TEXTURE2D(_EmissionMap, sampler_EmissionMap, uv).rgb * _EmissionColor.rgb;
#endif
}
inline void InitializeStandardLitSurfaceData(float2 uv, out SurfaceData outSurfaceData)
{
half4 albedoAlpha = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv);
half4 specGloss = MetallicSpecGloss(uv, albedoAlpha.a);
outSurfaceData.albedo = albedoAlpha.rgb * _Color.rgb;
#if _SPECULAR_SETUP
outSurfaceData.metallic = 1.0h;
outSurfaceData.specular = specGloss.rgb;
#else
outSurfaceData.metallic = specGloss.r;
outSurfaceData.specular = half3(0.0h, 0.0h, 0.0h);
#endif
outSurfaceData.smoothness = specGloss.a;
outSurfaceData.normal = Normal(uv);
outSurfaceData.occlusion = Occlusion(uv);
outSurfaceData.emission = Emission(uv);
outSurfaceData.alpha = Alpha(albedoAlpha.a);
}
#endif

8
ScriptableRenderPipeline/LightweightPipeline/Shaders/ShaderVariables.meta


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

252
ScriptableRenderPipeline/LightweightPipeline/Shaders/ShaderVariables/LightweightShaderVariables.hlsl


// UNITY_SHADER_NO_UPGRADE
#ifndef LIGHTWEIGHT_SHADER_VARIABLES_INCLUDED
#define LIGHTWEIGHT_SHADER_VARIABLES_INCLUDED
#include "ShaderLibrary/Common.hlsl"
// CAUTION:
// Currently the shaders compiler always include regualr Unity shaderVariables, so I get a conflict here were UNITY_SHADER_VARIABLES_INCLUDED is already define, this need to be fixed.
// As I haven't change the variables name yet, I simply don't define anything, and I put the transform function at the end of the file outside the guard header.
// This need to be fixed.
#if defined (DIRECTIONAL_COOKIE) || defined (DIRECTIONAL)
#define USING_DIRECTIONAL_LIGHT
#endif
#if defined(UNITY_SINGLE_PASS_STEREO) || defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED)
#define USING_STEREO_MATRICES
#endif
#if defined(USING_STEREO_MATRICES)
#define glstate_matrix_projection unity_StereoMatrixP[unity_StereoEyeIndex]
#define unity_MatrixV unity_StereoMatrixV[unity_StereoEyeIndex]
#define unity_MatrixInvV unity_StereoMatrixInvV[unity_StereoEyeIndex]
#define unity_MatrixVP unity_StereoMatrixVP[unity_StereoEyeIndex]
#define unity_CameraProjection unity_StereoCameraProjection[unity_StereoEyeIndex]
#define unity_CameraInvProjection unity_StereoCameraInvProjection[unity_StereoEyeIndex]
#define unity_WorldToCamera unity_StereoWorldToCamera[unity_StereoEyeIndex]
#define unity_CameraToWorld unity_StereoCameraToWorld[unity_StereoEyeIndex]
#define _WorldSpaceCameraPos unity_StereoWorldSpaceCameraPos[unity_StereoEyeIndex]
#endif
#define UNITY_LIGHTMODEL_AMBIENT (glstate_lightmodel_ambient * 2)
// ----------------------------------------------------------------------------
CBUFFER_START(UnityPerCamera)
// Time (t = time since current level load) values from Unity
float4 _Time; // (t/20, t, t*2, t*3)
float4 _SinTime; // sin(t/8), sin(t/4), sin(t/2), sin(t)
float4 _CosTime; // cos(t/8), cos(t/4), cos(t/2), cos(t)
float4 unity_DeltaTime; // dt, 1/dt, smoothdt, 1/smoothdt
#if !defined(USING_STEREO_MATRICES)
float3 _WorldSpaceCameraPos;
#endif
// x = 1 or -1 (-1 if projection is flipped)
// y = near plane
// z = far plane
// w = 1/far plane
float4 _ProjectionParams;
// x = width
// y = height
// z = 1 + 1.0/width
// w = 1 + 1.0/height
float4 _ScreenParams;
// Values used to linearize the Z buffer (http://www.humus.name/temp/Linearize%20depth.txt)
// x = 1-far/near
// y = far/near
// z = x/far
// w = y/far
// or in case of a reversed depth buffer (UNITY_REVERSED_Z is 1)
// x = -1+far/near
// y = 1
// z = x/far
// w = 1/far
float4 _ZBufferParams;
// x = orthographic camera's width
// y = orthographic camera's height
// z = unused
// w = 1.0 if camera is ortho, 0.0 if perspective
float4 unity_OrthoParams;
CBUFFER_END
CBUFFER_START(UnityPerCameraRare)
float4 unity_CameraWorldClipPlanes[6];
#if !defined(USING_STEREO_MATRICES)
// Projection matrices of the camera. Note that this might be different from projection matrix
// that is set right now, e.g. while rendering shadows the matrices below are still the projection
// of original camera.
float4x4 unity_CameraProjection;
float4x4 unity_CameraInvProjection;
float4x4 unity_WorldToCamera;
float4x4 unity_CameraToWorld;
#endif
CBUFFER_END
// ----------------------------------------------------------------------------
CBUFFER_START(UnityPerDraw : register(b0))
#ifdef UNITY_USE_PREMULTIPLIED_MATRICES
float4x4 glstate_matrix_mvp;
float4x4 glstate_matrix_modelview0;
float4x4 glstate_matrix_invtrans_modelview0;
#endif
float4x4 unity_ObjectToWorld;
float4x4 unity_WorldToObject;
float4 unity_LODFade; // x is the fade value ranging within [0,1]. y is x quantized into 16 levels
float4 unity_WorldTransformParams; // w is usually 1.0, or -1.0 for odd-negative scale transforms
float4 unity_LightmapST;
float4 unity_DynamicLightmapST;
// SH lighting environment
float4 unity_SHAr;
float4 unity_SHAg;
float4 unity_SHAb;
float4 unity_SHBr;
float4 unity_SHBg;
float4 unity_SHBb;
float4 unity_SHC;
// x = Disabled(0)/Enabled(1)
// y = Computation are done in global space(0) or local space(1)
// z = Texel size on U texture coordinate
float4 unity_ProbeVolumeParams;
float4x4 unity_ProbeVolumeWorldToObject;
float3 unity_ProbeVolumeSizeInv;
float3 unity_ProbeVolumeMin;
// This contain occlusion factor from 0 to 1 for dynamic objects (no SH here)
float4 unity_ProbesOcclusion;
// HDR environment map decode instructions
half4 unity_SpecCube0_HDR;
CBUFFER_END
#if defined(USING_STEREO_MATRICES)
CBUFFER_START(UnityStereoGlobals)
float4x4 unity_StereoMatrixP[2];
float4x4 unity_StereoMatrixV[2];
float4x4 unity_StereoMatrixInvV[2];
float4x4 unity_StereoMatrixVP[2];
float4x4 unity_StereoCameraProjection[2];
float4x4 unity_StereoCameraInvProjection[2];
float4x4 unity_StereoWorldToCamera[2];
float4x4 unity_StereoCameraToWorld[2];
float3 unity_StereoWorldSpaceCameraPos[2];
float4 unity_StereoScaleOffset[2];
CBUFFER_END
#endif
#if defined(USING_STEREO_MATRICES) && defined(UNITY_STEREO_MULTIVIEW_ENABLED)
CBUFFER_START(UnityStereoEyeIndices)
float4 unity_StereoEyeIndices[2];
CBUFFER_END
#endif
#if defined(UNITY_STEREO_MULTIVIEW_ENABLED) && defined(SHADER_STAGE_VERTEX)
#define unity_StereoEyeIndex UNITY_VIEWID
UNITY_DECLARE_MULTIVIEW(2);
#elif defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED)
static uint unity_StereoEyeIndex;
#elif defined(UNITY_SINGLE_PASS_STEREO)
CBUFFER_START(UnityStereoEyeIndex)
int unity_StereoEyeIndex;
CBUFFER_END
#endif
CBUFFER_START(UnityPerDrawRare)
float4x4 glstate_matrix_transpose_modelview0;
CBUFFER_END
// ----------------------------------------------------------------------------
CBUFFER_START(UnityPerFrame)
float4 glstate_lightmodel_ambient;
float4 unity_AmbientSky;
float4 unity_AmbientEquator;
float4 unity_AmbientGround;
float4 unity_IndirectSpecColor;
float4 unity_FogParams;
half4 unity_FogColor;
#if !defined(USING_STEREO_MATRICES)
float4x4 glstate_matrix_projection;
float4x4 unity_MatrixV;
float4x4 unity_MatrixInvV;
float4x4 unity_MatrixVP;
float4 unity_StereoScaleOffset;
int unity_StereoEyeIndex;
#endif
float4 unity_ShadowColor;
CBUFFER_END
// ----------------------------------------------------------------------------
TEXTURE2D_FLOAT(_MainDepthTexture);
SAMPLER2D(sampler_MainDepthTexture);
TEXTURECUBE(unity_SpecCube0);
SAMPLERCUBE(samplerunity_SpecCube0);
// Main lightmap
TEXTURE2D(unity_Lightmap);
SAMPLER2D(samplerunity_Lightmap);
// Dual or directional lightmap (always used with unity_Lightmap, so can share sampler)
TEXTURE2D(unity_LightmapInd);
// We can have shadowMask only if we have lightmap, so no sampler
TEXTURE2D(unity_ShadowMask);
// ----------------------------------------------------------------------------
// TODO: all affine matrices should be 3x4.
// TODO: sort these vars by the frequency of use (descending), and put commonly used vars together.
// Note: please use UNITY_MATRIX_X macros instead of referencing matrix variables directly.
CBUFFER_START(UnityPerPass)
float4x4 _PrevViewProjMatrix;
float4x4 _ViewProjMatrix;
float4x4 _NonJitteredViewProjMatrix;
float4x4 _ViewMatrix;
float4x4 _ProjMatrix;
float4x4 _InvViewProjMatrix;
float4x4 _InvViewMatrix;
float4x4 _InvProjMatrix;
float4 _InvProjParam;
float4 _ScreenSize; // {w, h, 1/w, 1/h}
float4 _FrustumPlanes[6]; // {(a, b, c) = N, d = -dot(N, P)} [L, R, T, B, N, F]
CBUFFER_END
float4x4 OptimizeProjectionMatrix(float4x4 M)
{
// Matrix format (x = non-constant value).
// Orthographic Perspective Combined(OR)
// | x 0 0 x | | x 0 x 0 | | x 0 x x |
// | 0 x 0 x | | 0 x x 0 | | 0 x x x |
// | x x x x | | x x x x | | x x x x | <- oblique projection row
// | 0 0 0 1 | | 0 0 x 0 | | 0 0 x x |
// Notice that some values are always 0.
// We can avoid loading and doing math with constants.
M._21_41 = 0;
M._12_42 = 0;
return M;
}
#include "ShaderVariables/LightweightShaderVariablesCamera.hlsl"
#include "ShaderVariables/LightweightShaderVariablesFunctions.hlsl"
#endif // LIGHTWEIGHT_SHADER_VARIABLES_INCLUDED

9
ScriptableRenderPipeline/LightweightPipeline/Shaders/ShaderVariables/LightweightShaderVariables.hlsl.meta


fileFormatVersion: 2
guid: 6564342aa7c6ca44a86b97323a311d74
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

21
ScriptableRenderPipeline/LightweightPipeline/Shaders/ShaderVariables/LightweightShaderVariablesCamera.hlsl


#ifdef UNITY_SHADER_VARIABLES_MATRIX_DEFS_LEGACY_UNITY_INCLUDED
#error Mixing LightweightCamera and legacy Unity matrix definitions
#endif
#ifndef UNITY_SHADER_VARIABLES_MATRIX_DEFS_LIGHTWEIGHT_INCLUDED
#define UNITY_SHADER_VARIABLES_MATRIX_DEFS_LIGHTWEIGHT_INCLUDED
#define UNITY_MATRIX_M unity_ObjectToWorld
#define UNITY_MATRIX_I_M unity_WorldToObject
#define UNITY_MATRIX_V unity_MatrixV
#define UNITY_MATRIX_I_V unity_MatrixInvV
#define UNITY_MATRIX_P OptimizeProjectionMatrix(glstate_matrix_projection)
#define UNITY_MATRIX_I_P ERROR_UNITY_MATRIX_I_P_IS_NOT_DEFINED
#define UNITY_MATRIX_VP unity_MatrixVP
#define UNITY_MATRIX_I_VP ERROR_UNITY_MATRIX_I_VP_IS_NOT_DEFINED
#define UNITY_MATRIX_MV mul(UNITY_MATRIX_V, UNITY_MATRIX_M)
#define UNITY_MATRIX_T_MV transpose(UNITY_MATRIX_MV)
#define UNITY_MATRIX_IT_MV transpose(mul(UNITY_MATRIX_I_M, UNITY_MATRIX_I_V))
#define UNITY_MATRIX_MVP mul(UNITY_MATRIX_VP, UNITY_MATRIX_M)
#endif // UNITY_SHADER_VARIABLES_MATRIX_DEFS_LIGHTWEIGHT_INCLUDED

9
ScriptableRenderPipeline/LightweightPipeline/Shaders/ShaderVariables/LightweightShaderVariablesCamera.hlsl.meta


fileFormatVersion: 2
guid: 034efa35d41944e41a5ac36341ffd9c7
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

114
ScriptableRenderPipeline/LightweightPipeline/Shaders/ShaderVariables/LightweightShaderVariablesFunctions.hlsl


#ifndef UNITY_SHADER_VARIABLES_FUNCTIONS_INCLUDED
#define UNITY_SHADER_VARIABLES_FUNCTIONS_INCLUDED
float4x4 GetWorldToViewMatrix()
{
return UNITY_MATRIX_V;
}
float4x4 GetObjectToWorldMatrix()
{
return UNITY_MATRIX_M;
}
float4x4 GetWorldToObjectMatrix()
{
return UNITY_MATRIX_I_M;
}
// Transform to homogenous clip space
float4x4 GetWorldToHClipMatrix()
{
return UNITY_MATRIX_VP;
}
float GetOddNegativeScale()
{
return unity_WorldTransformParams.w;
}
float3 TransformWorldToView(float3 positionWS)
{
return mul(GetWorldToViewMatrix(), float4(positionWS, 1.0)).xyz;
}
float3 TransformObjectToWorld(float3 positionOS)
{
return mul(GetObjectToWorldMatrix(), float4(positionOS, 1.0)).xyz;
}
float3 TransformWorldToObject(float3 positionWS)
{
return mul(GetWorldToObjectMatrix(), float4(positionWS, 1.0)).xyz;
}
float3 TransformObjectToWorldDir(float3 dirOS)
{
// Normalize to support uniform scaling
return normalize(mul((float3x3)GetObjectToWorldMatrix(), dirOS));
}
float3 TransformWorldToObjectDir(float3 dirWS)
{
// Normalize to support uniform scaling
return normalize(mul((float3x3)GetWorldToObjectMatrix(), dirWS));
}
// Transforms normal from object to world space
float3 TransformObjectToWorldNormal(float3 normalOS)
{
#ifdef UNITY_ASSUME_UNIFORM_SCALING
return UnityObjectToWorldDir(normalOS);
#else
// Normal need to be multiply by inverse transpose
// mul(IT_M, norm) => mul(norm, I_M) => {dot(norm, I_M.col0), dot(norm, I_M.col1), dot(norm, I_M.col2)}
return normalize(mul(normalOS, (float3x3)GetWorldToObjectMatrix()));
#endif
}
// Transforms position from object space to homogenous space
float4 TransformObjectToHClip(float3 positionWS)
{
// More efficient than computing M*VP matrix product
return mul(GetWorldToHClipMatrix(), mul(GetObjectToWorldMatrix(), float4(positionWS, 1.0)));
}
// Tranforms position from world space to homogenous space
float4 TransformWorldToHClip(float3 positionWS)
{
return mul(GetWorldToHClipMatrix(), float4(positionWS, 1.0));
}
float3x3 CreateWorldToTangent(float3 normal, float3 tangent, float flipSign)
{
// For odd-negative scale transforms we need to flip the sign
float sgn = flipSign * GetOddNegativeScale();
float3 bitangent = cross(normal, tangent) * sgn;
return float3x3(tangent, bitangent, normal);
}
float3 TransformTangentToWorld(float3 dirTS, float3x3 worldToTangent)
{
// Use transpose transformation to go from tangent to world as the matrix is orthogonal
return mul(dirTS, worldToTangent);
}
float3 TransformWorldToTangent(float3 dirWS, float3x3 worldToTangent)
{
return mul(worldToTangent, dirWS);
}
float3 TransformTangentToObject(float3 dirTS, float3x3 worldToTangent)
{
// Use transpose transformation to go from tangent to world as the matrix is orthogonal
float3 normalWS = mul(dirTS, worldToTangent);
return mul((float3x3)GetWorldToObjectMatrix(), normalWS);
}
float3 TransformObjectToTangent(float3 dirOS, float3x3 worldToTangent)
{
return mul(worldToTangent, TransformObjectToWorldDir(dirOS));
}
#endif // UNITY_SHADER_VARIABLES_FUNCTIONS_INCLUDED

9
ScriptableRenderPipeline/LightweightPipeline/Shaders/ShaderVariables/LightweightShaderVariablesFunctions.hlsl.meta


fileFormatVersion: 2
guid: 20914acf41b53ba42bf665e94496a288
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

20
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassShadow.cginc


#ifndef LIGHTWEIGHT_PASS_SHADOW_INCLUDED
#define LIGHTWEIGHT_PASS_SHADOW_INCLUDED
float4 ShadowPassVertex(float4 pos : POSITION) : SV_POSITION
{
float4 clipPos = UnityObjectToClipPos(pos);
#if defined(UNITY_REVERSED_Z)
clipPos.z = min(clipPos.z, UNITY_NEAR_CLIP_VALUE);
#else
clipPos.z = max(clipPos.z, UNITY_NEAR_CLIP_VALUE);
#endif
return clipPos;
}
half4 ShadowPassFragment() : SV_TARGET
{
return 0;
}
#endif

166
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightCore.cginc


#ifndef LIGHTWEIGHT_PIPELINE_CORE_INCLUDED
#define LIGHTWEIGHT_PIPELINE_CORE_INCLUDED
#include "UnityCG.cginc"
#if defined(UNITY_COLORSPACE_GAMMA)
#define LIGHTWEIGHT_GAMMA_TO_LINEAR(gammaColor) gammaColor * gammaColor
#define LIGHTWEIGHT_LINEAR_TO_GAMMA(linColor) sqrt(linColor)
#define OUTPUT_COLOR(color) half4(LIGHTWEIGHT_LINEAR_TO_GAMMA(color.rgb), color.a)
#else
#define LIGHTWEIGHT_GAMMA_TO_LINEAR(color) color
#define LIGHTWEIGHT_LINEAR_TO_GAMMA(color) color
#define OUTPUT_COLOR(color) color
#endif
#ifdef _NORMALMAP
#define OUTPUT_NORMAL(IN, OUT) OutputTangentToWorld(IN.tangent, IN.normal, OUT.tangent, OUT.binormal, OUT.normal)
#else
#define OUTPUT_NORMAL(IN, OUT) OUT.normal = UnityObjectToWorldNormal(IN.normal)
#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 = EvaluateSHPerVertex(normalWS)
#endif
half _Pow4(half x)
{
return x * x * x * x;
}
half _LerpOneTo(half b, half t)
{
half oneMinusT = 1 - t;
return oneMinusT + b * t;
}
void AlphaDiscard(half alpha, half cutoff)
{
#ifdef _ALPHATEST_ON
clip(alpha - cutoff);
#endif
}
half3 SafeNormalize(half3 inVec)
{
half dp3 = max(1.e-4h, dot(inVec, inVec));
return inVec * rsqrt(dp3);
}
half3 UnpackNormalScale(half4 packednormal, half bumpScale)
{
#if defined(UNITY_NO_DXT5nm)
half3 normal = packednormal.xyz * 2 - 1;
#if (SHADER_TARGET >= 30)
// SM2.0: instruction count limitation
// SM2.0: normal scaler is not supported
normal.xy *= bumpScale;
#endif
return normal;
#else
// This do the trick
packednormal.x *= packednormal.w;
half3 normal;
normal.xy = (packednormal.xy * 2 - 1);
#if (SHADER_TARGET >= 30)
// SM2.0: instruction count limitation
// SM2.0: normal scaler is not supported
normal.xy *= bumpScale;
#endif
normal.z = sqrt(1.0 - saturate(dot(normal.xy, normal.xy)));
return normal;
#endif
}
half3 EvaluateSHPerVertex(half3 normalWS)
{
#if defined(EVALUATE_SH_VERTEX)
return max(half3(0, 0, 0), ShadeSH9(half4(normalWS, 1.0)));
#elif defined(EVALUATE_SH_MIXED)
// no max since this is only L2 contribution
return SHEvalLinearL2(half4(normalWS, 1.0));
#endif
// Fully per-pixel. Nothing to compute.
return half3(0.0, 0.0, 0.0);
}
half3 EvaluateSHPerPixel(half3 L2Term, half3 normalWS)
{
#ifdef EVALUATE_SH_MIXED
return max(half3(0, 0, 0), L2Term + SHEvalLinearL0L1(half4(normalWS, 1.0)));
#endif
// Default: Evaluate SH fully per-pixel
return max(half3(0, 0, 0), ShadeSH9(half4(normalWS, 1.0)));
}
half3 SampleLightmap(float2 lightmapUV, half3 normalWS)
{
half4 encodedBakedColor = UNITY_SAMPLE_TEX2D(unity_Lightmap, lightmapUV);
half3 bakedColor = DecodeLightmap(encodedBakedColor);
#if DIRLIGHTMAP_COMBINED
half4 bakedDirection = UNITY_SAMPLE_TEX2D_SAMPLER(unity_LightmapInd, unity_Lightmap, lightmapUV);
bakedColor = DecodeDirectionalLightmap(bakedColor, bakedDirection, normalWS);
#endif
return bakedColor;
}
half3 SampleGI(float4 sampleData, half3 normalWS)
{
#if LIGHTMAP_ON
return SampleLightmap(sampleData.xy, normalWS);
#endif
return EvaluateSHPerPixel(sampleData.xyz, normalWS);
}
void OutputTangentToWorld(half4 vertexTangent, half3 vertexNormal, out half3 tangentWS, out half3 binormalWS, out half3 normalWS)
{
half sign = vertexTangent.w * unity_WorldTransformParams.w;
normalWS = normalize(UnityObjectToWorldNormal(vertexNormal));
tangentWS = normalize(mul((half3x3)unity_ObjectToWorld, vertexTangent.xyz));
binormalWS = cross(normalWS, tangentWS) * sign;
}
half3 TangentToWorldNormal(half3 normalTangent, half3 tangent, half3 binormal, half3 normal)
{
half3x3 tangentToWorld = half3x3(tangent, binormal, normal);
return normalize(mul(normalTangent, tangentToWorld));
}
float ComputeFogFactor(float z)
{
float clipZ_01 = UNITY_Z_0_FAR_FROM_CLIPSPACE(z);
#if defined(FOG_LINEAR)
// factor = (end-z)/(end-start) = z * (-1/(end-start)) + (end/(end-start))
float fogFactor = saturate(clipZ_01 * unity_FogParams.z + unity_FogParams.w);
return half(fogFactor);
#elif defined(FOG_EXP)
// factor = exp(-density*z)
float unityFogFactor = unity_FogParams.y * clipZ_01;
return half(saturate(exp2(-unityFogFactor)));
#elif defined(FOG_EXP2)
// factor = exp(-(density*z)^2)
float unityFogFactor = unity_FogParams.x * clipZ_01;
return half(saturate(exp2(-unityFogFactor*unityFogFactor)));
#else
return 0.0h;
#endif
}
void ApplyFog(inout half3 color, half fogFactor)
{
#if defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2)
color = lerp(unity_FogColor, color, fogFactor);
#endif
}
#endif

137
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassLit.cginc


#ifndef LIGHTWEIGHT_PASS_LIT_INCLUDED
#define LIGHTWEIGHT_PASS_LIT_INCLUDED
#include "LightweightSurfaceInput.cginc"
#include "LightweightLighting.cginc"
struct LightweightVertexInput
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 tangent : TANGENT;
float2 texcoord : TEXCOORD0;
float2 lightmapUV : TEXCOORD1;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct LightweightVertexOutput
{
float2 uv : TEXCOORD0;
float4 lightmapUVOrVertexSH : TEXCOORD1; // holds either lightmapUV or vertex SH. depending on LIGHTMAP_ON
float4 posWS : TEXCOORD2;
half3 normal : TEXCOORD3;
#if _NORMALMAP
half3 tangent : TEXCOORD4;
half3 binormal : TEXCOORD5;
#endif
half3 viewDir : TEXCOORD6;
half4 fogFactorAndVertexLight : TEXCOORD7; // x: fogFactor, yzw: vertex light
float4 clipPos : SV_POSITION;
UNITY_VERTEX_OUTPUT_STEREO
};
///////////////////////////////////////////////////////////////////////////////
// Vertex and Fragment functions //
///////////////////////////////////////////////////////////////////////////////
// Vertex: Used for Standard and StandardSimpleLighting shaders
LightweightVertexOutput LitPassVertex(LightweightVertexInput v)
{
LightweightVertexOutput o = (LightweightVertexOutput)0;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
o.posWS = mul(unity_ObjectToWorld, v.vertex);
o.clipPos = mul(UNITY_MATRIX_VP, o.posWS);
o.viewDir = SafeNormalize(_WorldSpaceCameraPos - o.posWS.xyz);
// initializes o.normal and if _NORMALMAP also o.tangent and o.binormal
OUTPUT_NORMAL(v, o);
// We either sample GI from lightmap or SH. lightmap UV and vertex SH coefficients
// are packed in lightmapUVOrVertexSH to save interpolator.
// The following funcions initialize
OUTPUT_LIGHTMAP_UV(v.lightmapUV, unity_LightmapST, o.lightmapUVOrVertexSH);
OUTPUT_SH(o.normal, o.lightmapUVOrVertexSH);
half3 vertexLight = VertexLighting(o.posWS.xyz, o.normal);
half fogFactor = ComputeFogFactor(o.clipPos.z);
o.fogFactorAndVertexLight = half4(fogFactor, vertexLight);
return o;
}
// Used for Standard shader
half4 LitPassFragment(LightweightVertexOutput IN) : SV_Target
{
SurfaceData surfaceData;
InitializeStandardLitSurfaceData(IN.uv, surfaceData);
#if _NORMALMAP
half3 normalWS = TangentToWorldNormal(surfaceData.normal, IN.tangent, IN.binormal, IN.normal);
#else
half3 normalWS = normalize(IN.normal);
#endif
half3 indirectDiffuse = SampleGI(IN.lightmapUVOrVertexSH, normalWS);
float fogFactor = IN.fogFactorAndVertexLight.x;
half4 color = LightweightFragmentPBR(IN.posWS, 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 OUTPUT_COLOR(color);
}
// Used for StandardSimpleLighting shader
half4 LitPassFragmentSimple(LightweightVertexOutput IN) : SV_Target
{
float2 uv = IN.uv;
half4 diffuseAlpha = tex2D(_MainTex, uv);
half3 diffuse = LIGHTWEIGHT_GAMMA_TO_LINEAR(diffuseAlpha.rgb) * _Color.rgb;
#ifdef _GLOSSINESS_FROM_BASE_ALPHA
half alpha = _Color.a;
#else
half alpha = diffuseAlpha.a * _Color.a;
#endif
AlphaDiscard(alpha, _Cutoff);
#if _NORMALMAP
half3 normalTangent = Normal(uv);
half3 normalWS = TangentToWorldNormal(normalTangent, IN.tangent, IN.binormal, IN.normal);
#else
half3 normalWS = normalize(IN.normal);
#endif
half3 emission = Emission(uv);
half3 viewDirectionWS = SafeNormalize(IN.viewDir.xyz);
float3 positionWS = IN.posWS.xyz;
half3 diffuseGI = SampleGI(IN.lightmapUVOrVertexSH, normalWS);
#if _VERTEX_LIGHTS
diffuseGI += IN.fogFactorAndVertexLight.yzw;
#endif
half shininess = _Shininess * 128.0h;
half fogFactor = IN.fogFactorAndVertexLight.x;
#if defined(_SPECGLOSSMAP) || defined(_SPECULAR_COLOR)
half4 specularGloss = SpecularGloss(uv, diffuseAlpha.a);
return LightweightFragmentBlinnPhong(positionWS, normalWS, viewDirectionWS, fogFactor, diffuseGI, diffuse, specularGloss, shininess, emission, alpha);
#else
return LightweightFragmentLambert(positionWS, normalWS, viewDirectionWS, fogFactor, diffuseGI, diffuse, emission, alpha);
#endif
};
#endif

70
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassMeta.cginc


#ifndef LIGHTWEIGHT_PASS_META_INCLUDED
#define LIGHTWEIGHT_PASS_META_INCLUDED
#include "LightweightSurfaceInput.cginc"
#include "LightweightLighting.cginc"
#include "UnityMetaPass.cginc"
struct MetaVertexInput
{
float4 vertex : POSITION;
half3 normal : NORMAL;
float2 uv0 : TEXCOORD0;
float2 uv1 : TEXCOORD1;
float2 uv2 : TEXCOORD2;
#ifdef _TANGENT_TO_WORLD
half4 tangent : TANGENT;
#endif
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct MetaVertexOuput
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
MetaVertexOuput LightweightVertexMeta(MetaVertexInput v)
{
MetaVertexOuput o;
o.pos = UnityMetaVertexPosition(v.vertex, v.uv1.xy, v.uv2.xy, unity_LightmapST, unity_DynamicLightmapST);
o.uv = TRANSFORM_TEX(v.uv0, _MainTex);
return o;
}
fixed4 LightweightFragmentMeta(MetaVertexOuput i) : SV_Target
{
SurfaceData surfaceData;
InitializeStandardLitSurfaceData(i.uv, surfaceData);
BRDFData brdfData;
InitializeBRDFData(surfaceData.albedo, surfaceData.metallic, surfaceData.specular, surfaceData.smoothness, surfaceData.alpha, brdfData);
UnityMetaInput o;
UNITY_INITIALIZE_OUTPUT(UnityMetaInput, o);
#if defined(EDITOR_VISUALIZATION)
o.Albedo = brdfData.diffuse;
#else
o.Albedo = brdfData.diffuse + brdfData.specular * brdfData.roughness * 0.5;
#endif
o.SpecularColor = surfaceData.specular;
o.Emission = surfaceData.emission;
return UnityMetaFragment(o);
}
fixed4 LightweightFragmentMetaSimple(MetaVertexOuput i) : SV_Target
{
UnityMetaInput o;
UNITY_INITIALIZE_OUTPUT(UnityMetaInput, o);
float2 uv = i.uv;
o.Albedo = _Color.rgb * tex2D(_MainTex, uv).rgb;
o.SpecularColor = SpecularGloss(uv, 1.0);
o.Emission = Emission(uv);
return UnityMetaFragment(o);
}
#endif

142
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)
#define _SHADOWS
#endif
#if defined(_HARD_SHADOWS_CASCADES) || defined(_SOFT_SHADOWS_CASCADES)
#define _SHADOW_CASCADES
#endif
#ifdef _SHADOWS
#define LIGHTWEIGHT_SHADOW_ATTENUATION(posWorld, vertexNormal, shadowDir) ComputeShadowAttenuation(posWorld, vertexNormal, shadowDir)
#else
#define LIGHTWEIGHT_SHADOW_ATTENUATION(posWorld, vertexNormal, shadowDir) 1.0h
#endif
UNITY_DECLARE_SHADOWMAP(_ShadowMap);
float4x4 _WorldToShadow[MAX_SHADOW_CASCADES];
float4 _DirShadowSplitSpheres[MAX_SHADOW_CASCADES];
half4 _ShadowOffset0;
half4 _ShadowOffset1;
half4 _ShadowOffset2;
half4 _ShadowOffset3;
half4 _ShadowData; // (x: 1.0 - shadowStrength, y: bias, z: normal bias, w: near plane offset)
float ApplyDepthBias(float clipZ)
{
#ifdef UNITY_REVERSED_Z
return clipZ + _ShadowData.y;
#endif
return clipZ - _ShadowData.y;
}
inline half SampleShadowmap(float4 shadowCoord)
{
float3 coord = shadowCoord.xyz /= shadowCoord.w;
coord.z = saturate(ApplyDepthBias(coord.z));
if (coord.x <= 0 || coord.x >= 1 || coord.y <= 0 || coord.y >= 1)
return 1;
#if defined(_SOFT_SHADOWS) || defined(_SOFT_SHADOWS_CASCADES)
// 4-tap hardware comparison
half4 attenuation;
attenuation.x = UNITY_SAMPLE_SHADOW(_ShadowMap, coord + _ShadowOffset0.xyz);
attenuation.y = UNITY_SAMPLE_SHADOW(_ShadowMap, coord + _ShadowOffset1.xyz);
attenuation.z = UNITY_SAMPLE_SHADOW(_ShadowMap, coord + _ShadowOffset2.xyz);
attenuation.w = UNITY_SAMPLE_SHADOW(_ShadowMap, coord + _ShadowOffset3.xyz);
lerp(attenuation, 1.0, _ShadowData.xxxx);
return dot(attenuation, 0.25);
#else
// 1-tap hardware comparison
half attenuation = UNITY_SAMPLE_SHADOW(_ShadowMap, coord);
return lerp(attenuation, 1.0, _ShadowData.x);
#endif
}
inline half ComputeCascadeIndex(float3 wpos)
{
float3 fromCenter0 = wpos.xyz - _DirShadowSplitSpheres[0].xyz;
float3 fromCenter1 = wpos.xyz - _DirShadowSplitSpheres[1].xyz;
float3 fromCenter2 = wpos.xyz - _DirShadowSplitSpheres[2].xyz;
float3 fromCenter3 = wpos.xyz - _DirShadowSplitSpheres[3].xyz;
float4 distances2 = float4(dot(fromCenter0, fromCenter0), dot(fromCenter1, fromCenter1), dot(fromCenter2, fromCenter2), dot(fromCenter3, fromCenter3));
float4 vDirShadowSplitSphereSqRadii;
vDirShadowSplitSphereSqRadii.x = _DirShadowSplitSpheres[0].w;
vDirShadowSplitSphereSqRadii.y = _DirShadowSplitSpheres[1].w;
vDirShadowSplitSphereSqRadii.z = _DirShadowSplitSpheres[2].w;
vDirShadowSplitSphereSqRadii.w = _DirShadowSplitSpheres[3].w;
fixed4 weights = fixed4(distances2 < vDirShadowSplitSphereSqRadii);
weights.yzw = saturate(weights.yzw - weights.xyz);
return 4 - dot(weights, fixed4(4, 3, 2, 1));
}
inline half ComputeShadowAttenuation(float3 posWorld, half3 vertexNormal, half3 shadowDir)
{
half NdotL = dot(vertexNormal, shadowDir);
half bias = saturate(1.0 - NdotL) * _ShadowData.z;
float3 posWorldOffsetNormal = posWorld + vertexNormal * bias;
int cascadeIndex = 0;
#ifdef _SHADOW_CASCADES
cascadeIndex = ComputeCascadeIndex(posWorldOffsetNormal);
if (cascadeIndex >= MAX_SHADOW_CASCADES)
return 1.0;
#endif
float4 shadowCoord = mul(_WorldToShadow[cascadeIndex], float4(posWorldOffsetNormal, 1.0));
return SampleShadowmap(shadowCoord);
}
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.xyz);
realtimeShadow = lerp(realtimeShadow, lightmap, shadowStrength);
// 3) Pick darkest color
return min(lightmap, realtimeShadow);
}
#endif

69
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightInput.cginc


#ifndef LIGHTWEIGHT_INPUT_INCLUDED
#define LIGHTWEIGHT_INPUT_INCLUDED
#define MAX_VISIBLE_LIGHTS 16
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)
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
sampler2D _MainLightCookie;
// 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

425
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightLighting.cginc


#ifndef LIGHTWEIGHT_LIGHTING_INCLUDED
#define LIGHTWEIGHT_LIGHTING_INCLUDED
#include "LightweightCore.cginc"
#include "LightweightShadows.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%)
#ifndef UNITY_SPECCUBE_LOD_STEPS
#define UNITY_SPECCUBE_LOD_STEPS 6
#endif
#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)
#if SHADER_TARGET < 30
// 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
///////////////////////////////////////////////////////////////////////////////
// BRDF Functions //
///////////////////////////////////////////////////////////////////////////////
struct BRDFData
{
half3 diffuse;
half3 specular;
half perceptualRoughness;
half roughness;
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 = 1.0h - smoothness;
outBRDFData.roughness = outBRDFData.perceptualRoughness * outBRDFData.perceptualRoughness;
#ifdef _ALPHAPREMULTIPLY_ON
outBRDFData.diffuse *= alpha;
alpha = alpha * oneMinusReflectivity + reflectivity;
#endif
}
half3 LightweightEnvironmentBRDF(BRDFData brdfData, half3 indirectDiffuse, half3 indirectSpecular, half roughness2, half fresnelTerm)
{
half3 c = indirectDiffuse * brdfData.diffuse;
float surfaceReduction = 1.0 / (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 LightweightDirectBDRF(BRDFData brdfData, half roughness2, half3 normal, half3 lightDirection, half3 viewDir)
{
#ifndef _SPECULARHIGHLIGHTS_OFF
half3 halfDir = SafeNormalize(lightDirection + viewDir);
half NoH = saturate(dot(normal, halfDir));
half LoH = saturate(dot(lightDirection, 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 * (roughness2 - 1.h) + 1.00001h;
half LoH2 = LoH * LoH;
half specularTerm = 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 - 1e-4h;
#endif
#if defined (SHADER_API_MOBILE)
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
}
///////////////////////////////////////////////////////////////////////////////
// Attenuation Functions /
///////////////////////////////////////////////////////////////////////////////
half CookieAttenuation(float3 worldPos)
{
#ifdef _MAIN_LIGHT_COOKIE
#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;
}
// Matches Unity Vanila attenuation
// Attenuation smoothly decreases to light range.
half DistanceAttenuation(half3 distanceSqr, half4 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);
return saturate(SdotL * spotAttenuation.x + spotAttenuation.y);
}
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);
// normalized light dir
lightDirection = half3(posToLightVec * rsqrt(distanceSqr));
half lightAtten = DistanceAttenuation(distanceSqr, lightInput.distanceAttenuation);
lightAtten *= SpotAttenuation(lightInput.spotDirection.xyz, lightDirection, lightInput.spotAttenuation);
return lightAtten;
}
inline half GetMainLightDirectionAndRealtimeAttenuation(LightInput lightInput, half3 normalWS, float3 positionWS, out half3 lightDirection)
{
#ifdef _MAIN_DIRECTIONAL_LIGHT
// Light pos holds normalized light dir
lightDirection = lightInput.pos;
half attenuation = 1.0;
#else
half attenuation = GetLightDirectionAndRealtimeAttenuation(lightInput, normalWS, positionWS, lightDirection);
#endif
// Cookies and shadows are only computed for main light
attenuation *= CookieAttenuation(positionWS);
attenuation *= LIGHTWEIGHT_SHADOW_ATTENUATION(positionWS, normalWS, lightDirection);
return attenuation;
}
///////////////////////////////////////////////////////////////////////////////
// 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);
#if defined(_VERTEX_LIGHTS)
int vertexLightStart = _AdditionalLightCount.x;
int vertexLightEnd = min(_AdditionalLightCount.y, unity_LightIndicesOffsetAndCount.y);
for (int lightIter = vertexLightStart; lightIter < vertexLightEnd; ++lightIter)
{
LightInput light;
INITIALIZE_LIGHT(light, lightIter);
half3 lightDirection;
half atten = GetLightDirectionAndRealtimeAttenuation(light, normalWS, positionWS, lightDirection);
half3 lightColor = light.color * atten;
vertexLightColor += LightingLambert(lightColor, lightDirection, normalWS);
}
#endif
return vertexLightColor;
}
///////////////////////////////////////////////////////////////////////////////
// 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);
BRDFData brdfData;
InitializeBRDFData(albedo, metallic, specular, smoothness, alpha, brdfData);
half3 lightDirectionWS;
LightInput mainLight;
INITIALIZE_MAIN_LIGHT(mainLight);
// 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;
half fresnelTerm = _Pow4(1.0 - saturate(dot(normalWS, viewDirectionWS)));
half3 color = LightweightEnvironmentBRDF(brdfData, indirectDiffuse, indirectSpecular, roughness2, fresnelTerm);
half mainLightAtten = MixRealtimeAndBakedOcclusion(realtimeMainLightAtten, bakedOcclusion, mainLight.distanceAttenuation);
radiance *= mainLightAtten;
color += LightweightDirectBDRF(brdfData, roughness2, normalWS, lightDirectionWS, viewDirectionWS) * radiance;
color += vertexLighting * brdfData.diffuse;
#ifdef _ADDITIONAL_LIGHTS
int pixelLightCount = min(_AdditionalLightCount.x, unity_LightIndicesOffsetAndCount.y);
for (int lightIter = 0; lightIter < pixelLightCount; ++lightIter)
{
LightInput light;
INITIALIZE_LIGHT(light, lightIter);
half lightAttenuation = GetLightDirectionAndRealtimeAttenuation(light, normalWS, positionWS, lightDirectionWS);
lightAttenuation = MixRealtimeAndBakedOcclusion(lightAttenuation, bakedOcclusion, light.distanceAttenuation);
half NdotL = saturate(dot(normalWS, lightDirectionWS));
half3 radiance = light.color * (lightAttenuation * NdotL);
color += LightweightDirectBDRF(brdfData, roughness2, normalWS, lightDirectionWS, viewDirectionWS) * radiance;
}
#endif
color += emission;
return half4(color, 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 lightDirection;
LightInput mainLight;
INITIALIZE_MAIN_LIGHT(mainLight);
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;
#ifdef _ADDITIONAL_LIGHTS
int pixelLightCount = min(_AdditionalLightCount.x, unity_LightIndicesOffsetAndCount.y);
for (int lightIter = 0; lightIter < pixelLightCount; ++lightIter)
{
LightInput light;
INITIALIZE_LIGHT(light, lightIter);
half lightAttenuation = GetLightDirectionAndRealtimeAttenuation(light, normalWS, positionWS, lightDirection);
lightAttenuation = MixRealtimeAndBakedOcclusion(lightAttenuation, bakedOcclusion, light.distanceAttenuation);
half3 attenuatedLightColor = light.color * lightAttenuation;
diffuseColor += LightingLambert(attenuatedLightColor, lightDirection, normalWS);
}
#endif
half3 finalColor = diffuseColor * diffuse + emission;
// Computes Fog Factor per vextex
ApplyFog(finalColor, fogFactor);
half4 color = half4(finalColor, alpha);
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 bakedOcclusion = half4(0, 0, 0, 0);
half3 lightDirection;
LightInput mainLight;
INITIALIZE_MAIN_LIGHT(mainLight);
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;
half3 specularColor = LightingSpecular(mainLight.color * mainLightAtten, lightDirection, normalWS, viewDirectionWS, specularGloss, shininess);
#ifdef _ADDITIONAL_LIGHTS
int pixelLightCount = min(_AdditionalLightCount.x, unity_LightIndicesOffsetAndCount.y);
for (int lightIter = 0; lightIter < pixelLightCount; ++lightIter)
{
LightInput light;
INITIALIZE_LIGHT(light, lightIter);
half lightAttenuation = GetLightDirectionAndRealtimeAttenuation(light, normalWS, positionWS, lightDirection);
lightAttenuation = MixRealtimeAndBakedOcclusion(lightAttenuation, bakedOcclusion, light.distanceAttenuation);
half3 attenuatedLightColor = light.color * lightAttenuation;
diffuseColor += LightingLambert(attenuatedLightColor, lightDirection, normalWS);
specularColor += LightingSpecular(attenuatedLightColor, lightDirection, normalWS, viewDirectionWS, specularGloss, shininess);
}
#endif
half3 finalColor = diffuseColor * diffuse + emission;
finalColor += specularColor;
// Computes Fog Factor per vextex
ApplyFog(finalColor, fogFactor);
half4 color = half4(finalColor, alpha);
return OUTPUT_COLOR(color);
}
#endif

166
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightSurfaceInput.cginc


#ifndef LIGHTWEIGHT_SURFACE_INPUT_INCLUDED
#define LIGHTWEIGHT_SURFACE_INPUT_INCLUDED
#include "LightweightCore.cginc"
#ifdef _SPECULAR_SETUP
#define SAMPLE_METALLICSPECULAR(uv) tex2D(_SpecGlossMap, uv)
#else
#define SAMPLE_METALLICSPECULAR(uv) tex2D(_MetallicGlossMap, uv)
#endif
CBUFFER_START(MaterialProperties)
half4 _MainTex_ST;
half4 _Color;
half _Cutoff;
half _Glossiness;
half _GlossMapScale;
half _SmoothnessTextureChannel;
half _Metallic;
half4 _SpecColor;
half _BumpScale;
half _OcclusionStrength;
half4 _EmissionColor;
half _Shininess;
CBUFFER_END
sampler2D _MainTex;
sampler2D _MetallicGlossMap;
sampler2D _SpecGlossMap;
sampler2D _BumpMap;
sampler2D _OcclusionMap;
sampler2D _EmissionMap;
// Must match Lightweigth ShaderGraph master node
struct SurfaceData
{
half3 albedo;
half3 specular;
half metallic;
half smoothness;
half3 normal;
half3 emission;
half occlusion;
half alpha;
};
///////////////////////////////////////////////////////////////////////////////
// Material Property Helpers //
///////////////////////////////////////////////////////////////////////////////
inline half Alpha(half albedoAlpha)
{
#if defined(_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A)
half alpha = _Color.a;
#else
half alpha = albedoAlpha * _Color.a;
#endif
#if defined(_ALPHATEST_ON)
clip(alpha - _Cutoff);
#endif
return alpha;
}
half3 Normal(float2 uv)
{
#if _NORMALMAP
return UnpackNormalScale(tex2D(_BumpMap, uv), _BumpScale);
#else
return half3(0.0h, 0.0h, 1.0h);
#endif
}
half4 SpecularGloss(half2 uv, half alpha)
{
half4 specularGloss = half4(0, 0, 0, 1);
#ifdef _SPECGLOSSMAP
specularGloss = tex2D(_SpecGlossMap, uv);
specularGloss.rgb = LIGHTWEIGHT_GAMMA_TO_LINEAR(specularGloss.rgb);
#elif defined(_SPECULAR_COLOR)
specularGloss = _SpecColor;
#endif
#ifdef _GLOSSINESS_FROM_BASE_ALPHA
specularGloss.a = alpha;
#endif
return specularGloss;
}
half4 MetallicSpecGloss(float2 uv, half albedoAlpha)
{
half4 specGloss;
#ifdef _METALLICSPECGLOSSMAP
specGloss = specGloss = SAMPLE_METALLICSPECULAR(uv);
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
specGloss.a = albedoAlpha * _GlossMapScale;
#else
specGloss.a *= _GlossMapScale;
#endif
#else // _METALLICSPECGLOSSMAP
#if _SPECULAR_SETUP
specGloss.rgb = _SpecColor.rgb;
#else
specGloss.rgb = _Metallic.rrr;
#endif
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
specGloss.a = albedoAlpha * _GlossMapScale;
#else
specGloss.a = _Glossiness;
#endif
#endif
return specGloss;
}
half Occlusion(float2 uv)
{
#ifdef _OCCLUSIONMAP
#if (SHADER_TARGET < 30)
// SM20: instruction count limitation
// SM20: simpler occlusion
return tex2D(_OcclusionMap, uv).g;
#else
half occ = tex2D(_OcclusionMap, uv).g;
return _LerpOneTo(occ, _OcclusionStrength);
#endif
#else
return 1.0;
#endif
}
half3 Emission(float2 uv)
{
#ifndef _EMISSION
return 0;
#else
return LIGHTWEIGHT_GAMMA_TO_LINEAR(tex2D(_EmissionMap, uv).rgb) * _EmissionColor.rgb;
#endif
}
inline void InitializeStandardLitSurfaceData(float2 uv, out SurfaceData outSurfaceData)
{
half4 albedoAlpha = tex2D(_MainTex, uv);
half4 specGloss = MetallicSpecGloss(uv, albedoAlpha);
outSurfaceData.albedo = LIGHTWEIGHT_GAMMA_TO_LINEAR(albedoAlpha.rgb) * _Color.rgb;
#if _SPECULAR_SETUP
outSurfaceData.metallic = 1.0h;
outSurfaceData.specular = specGloss.rgb;
#else
outSurfaceData.metallic = specGloss.r;
outSurfaceData.specular = half3(0.0h, 0.0h, 0.0h);
#endif
outSurfaceData.smoothness = specGloss.a;
outSurfaceData.normal = Normal(uv);
outSurfaceData.occlusion = Occlusion(uv);
outSurfaceData.emission = Emission(uv);
outSurfaceData.alpha = Alpha(albedoAlpha.a);
}
#endif

/ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightCore.cginc.meta → /ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightCore.hlsl.meta

/ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightInput.cginc.meta → /ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightInput.hlsl.meta

/ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightLighting.cginc.meta → /ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightLighting.hlsl.meta

/ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassLit.cginc.meta → /ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassLit.hlsl.meta

/ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassMeta.cginc.meta → /ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassMeta.hlsl.meta

/ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassShadow.cginc.meta → /ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassShadow.hlsl.meta

/ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightShadows.cginc.meta → /ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightShadows.hlsl.meta

/ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightSurfaceInput.cginc.meta → /ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightSurfaceInput.hlsl.meta

正在加载...
取消
保存