Last active
December 17, 2025 19:44
-
-
Save Vavassor/a46b8e3e3ed1599b47a78a6ab4a1dfe4 to your computer and use it in GitHub Desktop.
Lit shader template for Unity game engine's built-in render pipeline
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // This is a lit shader example that doesn't use surface shaders. | |
| // It supports forward rendering in the Built-in render pipeline. (BiRP) | |
| // | |
| // Annoyingly, it's not possible to support baked emission without a custom inspector, | |
| // because there's no other way to set globalIlluminationFlags. So if baked emissions are required, | |
| // switch the inspector to debug mode and change the flags manually. | |
| Shader "Orchid Seal/Lit Shader Template" | |
| { | |
| Properties | |
| { | |
| _Color("Color", Color) = (1,1,1,1) | |
| _MainTex("Texture", 2D) = "white" {} | |
| _Roughness("Roughness", Range(0.0, 1.0)) = 0.5 | |
| [Gamma] _Metallic("Metallic", Range(0.0, 1.0)) = 0.0 | |
| [Toggle(ALPHA_TEST_ON)] _AlphaTestOn("Alpha Test", Integer) = 0 | |
| _Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5 | |
| [Header(Rendering)] | |
| [Enum(UnityEngine.Rendering.BlendMode)] _BlendSrc("Source Blend", Float) = 1 // "One" | |
| [Enum(UnityEngine.Rendering.BlendMode)] _BlendDst("Destination Blend", Float) = 10 // "OneMinusSrcAlpha" | |
| [Enum(Add,0,Sub,1,RevSub,2,Min,3,Max,4)] _BlendOp("Blend Operation", Float) = 0 // "Add" | |
| // Opposite of URP's "Preserve Specular Lighting" | |
| [Toggle(FADE_TRANSPARENCY_ON)] _FadeTransparencyOn("Fade Transparency", Integer) = 0 | |
| [Toggle(PREMULTIPLY_ALPHA_ON)] _PremultiplyAlphaOn("Premultiply Alpha", Integer) = 1 | |
| [Header(Lighting)] | |
| [KeywordEnum(None, Probes)] Reflection_Mode("Reflection Mode", Integer) = 1 | |
| [ToggleOff] _SpecularHighlights("Specular Highlights", Integer) = 1 | |
| [Header(Culling and Depth Test)] | |
| [Enum(UnityEngine.Rendering.CullMode)] _CullMode("Cull Mode", Int) = 2 // "Back" | |
| [Enum(UnityEngine.Rendering.CompareFunction)] _ZTest("ZTest", Float) = 4 // "LessEqual" | |
| [Enum(Off,0,On,1)] _ZWrite("ZWrite", Float) = 1.0 // "On" | |
| [Header(Mask Map)] | |
| [Toggle(MASK_MAP_ON)] _MaskMapOn("Enabled", Integer) = 0 | |
| [NoScaleOffset] _MaskMap("Mask Map (ARMD format)", 2D) = "white" {} | |
| _OcclusionScale("Ambient Occlusion Scale", Range(0.0, 1.0)) = 1.0 | |
| _RoughnessScale("Roughness Scale", Range(0.0, 1.0)) = 1.0 | |
| _MetallicScale("Metallic Scale", Range(0.0, 1.0)) = 1.0 | |
| [Header(Normal)] | |
| [Toggle(NORMAL_MAP_ON)] _NormalMapOn("Enabled", Integer) = 0 | |
| _BumpScale("Normal Scale", Float) = 1.0 | |
| [Normal] [NoScaleOffset] _BumpMap("Normal Map", 2D) = "bump" {} | |
| [Header(Parallax)] | |
| [Toggle(PARALLAX_MAP_ON)] _ParallaxMapOn("Enabled", Integer) = 0 | |
| _Parallax("Height Scale", Range(0.005, 0.08)) = 0.02 | |
| [NoScaleOffset] _ParallaxMap("Parallax Map", 2D) = "black" {} | |
| [Header(Emission)] | |
| [Toggle(EMISSION_MAP_ON)] _EmissionMapOn("Enabled", Integer) = 0 | |
| _EmissionColor("Color", Color) = (0,0,0) | |
| [NoScaleOffset] _EmissionMap("Emission", 2D) = "white" {} | |
| [Header(Detail)] | |
| [Toggle(DETAIL_MAP_ON)] _DetailMapOn("Enabled", Integer) = 0 | |
| [Enum(Multiply X2, 0, Multiply, 1, Add, 2, Lerp, 3)] _DetailBlendMode("Blend Mode", Integer) = 0 | |
| _DetailAlbedoMap("Detail Color", 2D) = "grey" {} | |
| _DetailNormalScale("Normal Scale", Float) = 1.0 | |
| [Normal] [NoScaleOffset] _DetailNormalMap("Normal Map", 2D) = "bump" {} | |
| [Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3)] _DetailUvSet("UV Set", Integer) = 0 | |
| } | |
| HLSLINCLUDE | |
| #include "UnityCG.cginc" | |
| #include "AutoLight.cginc" | |
| #include "UnityPBSLighting.cginc" | |
| #if UNITY_PASS_META | |
| #include "UnityMetaPass.cginc" | |
| #endif | |
| // Indirect Specular........................................................................... | |
| half3 GlossyEnvironment(UNITY_ARGS_TEXCUBE(tex), half4 hdr, half perceptualRoughness, half3 reflUvw) | |
| { | |
| perceptualRoughness = perceptualRoughness * (1.7 - 0.7 * perceptualRoughness); | |
| half mip = perceptualRoughnessToMipmapLevel(perceptualRoughness); | |
| half4 rgbm = UNITY_SAMPLE_TEXCUBE_LOD(tex, reflUvw, mip); | |
| return DecodeHDR(rgbm, hdr); | |
| } | |
| half3 GetProbeIndirectSpecular(half3 reflUvw, float3 positionWs, half perceptualRoughness) | |
| { | |
| #ifdef UNITY_SPECCUBE_BOX_PROJECTION | |
| // we will tweak reflUVW in glossIn directly (as we pass it to GlossyEnvironment twice for probe0 and probe1), so keep original to pass into BoxProjectedCubemapDirection | |
| half3 originalReflUvw = reflUvw; | |
| reflUvw = BoxProjectedCubemapDirection(originalReflUvw, positionWs, unity_SpecCube0_ProbePosition, unity_SpecCube0_BoxMin, unity_SpecCube0_BoxMax); | |
| #endif | |
| half3 env0 = GlossyEnvironment(UNITY_PASS_TEXCUBE(unity_SpecCube0), unity_SpecCube0_HDR, perceptualRoughness, reflUvw); | |
| #ifdef UNITY_SPECCUBE_BLENDING | |
| const float kBlendFactor = 0.99999; | |
| float blendLerp = unity_SpecCube0_BoxMin.w; | |
| UNITY_BRANCH | |
| if (blendLerp < kBlendFactor) | |
| { | |
| #ifdef UNITY_SPECCUBE_BOX_PROJECTION | |
| reflUvw = BoxProjectedCubemapDirection(originalReflUvw, positionWs, unity_SpecCube1_ProbePosition, unity_SpecCube1_BoxMin, unity_SpecCube1_BoxMax); | |
| #endif | |
| half3 env1 = GlossyEnvironment(UNITY_PASS_TEXCUBE_SAMPLER(unity_SpecCube1, unity_SpecCube0), unity_SpecCube1_HDR, perceptualRoughness, reflUvw); | |
| return lerp(env1, env0, blendLerp); | |
| } | |
| else | |
| { | |
| return env0; | |
| } | |
| #else | |
| return env0; | |
| #endif | |
| } | |
| // Inputs...................................................................................... | |
| struct VertexInput | |
| { | |
| // "vertex" and "normal" are the names used by macros in AutoLight.cginc | |
| float4 vertex : POSITION; | |
| float3 normal : NORMAL; | |
| float4 tangent : TANGENT; | |
| float2 uv0 : TEXCOORD0; | |
| float2 uv1 : TEXCOORD1; | |
| float2 uv2 : TEXCOORD2; | |
| float2 uv3 : TEXCOORD3; | |
| UNITY_VERTEX_INPUT_INSTANCE_ID | |
| }; | |
| struct FragmentInput | |
| { | |
| // "pos" is the name used by macros in AutoLight.cginc | |
| float4 pos : SV_POSITION; | |
| float4 uv0 : TEXCOORD0; | |
| // "worldPos" is the name used by fog macros in UnityCG.cginc | |
| float4 worldPos : TEXCOORD1; // [xyz : positionWs | w : fogCoord] | |
| float4 tangentToWorldAndPackedData[3] : TEXCOORD2; // [3x3 : tangentToWorld | 1x3:viewDirForParallax] | |
| half4 ambientOrLightmapUv : TEXCOORD5; | |
| UNITY_LIGHTING_COORDS(6, 7) | |
| float3 lightDirectionWs : TEXCOORD8; | |
| #if defined(SHADOWS_CUBE) && !defined(SHADOWS_CUBE_IN_DEPTH_TEX) | |
| // This is usually defined using V2F_SHADOW_CASTER_NOPOS, but that uses TEXCOORD0. | |
| float3 vec : TEXCOORD9; | |
| #endif | |
| #ifdef EDITOR_VISUALIZATION | |
| float2 vizUV : TEXCOORD10; | |
| float4 lightCoord : TEXCOORD11; | |
| #endif | |
| UNITY_VERTEX_INPUT_INSTANCE_ID | |
| UNITY_VERTEX_OUTPUT_STEREO | |
| }; | |
| // UV Sets..................................................................................... | |
| float2 SelectUvSet(VertexInput v, half set) | |
| { | |
| switch (set) | |
| { | |
| default: | |
| case 0: return v.uv0; | |
| case 1: return v.uv1; | |
| case 2: return v.uv2; | |
| case 3: return v.uv3; | |
| } | |
| } | |
| // Properties.................................................................................. | |
| UNITY_DECLARE_TEX2D(_MainTex); | |
| UNITY_DECLARE_TEX2D(_MaskMap); | |
| UNITY_DECLARE_TEX2D(_BumpMap); | |
| UNITY_DECLARE_TEX2D(_EmissionMap); | |
| UNITY_DECLARE_TEX2D(_ParallaxMap); | |
| UNITY_DECLARE_TEX2D(_DetailAlbedoMap); | |
| UNITY_DECLARE_TEX2D(_DetailNormalMap); | |
| CBUFFER_START(UnityPerMaterial) | |
| half4 _Color; | |
| float4 _MainTex_ST; | |
| half _Cutoff; | |
| half _Metallic; | |
| half _MetallicScale; | |
| float _Roughness; | |
| float _RoughnessScale; | |
| half _OcclusionScale; | |
| half _BumpScale; | |
| half4 _EmissionColor; | |
| half _Parallax; | |
| float4 _DetailAlbedoMap_ST; | |
| half _DetailUvSet; | |
| half _DetailNormalScale; | |
| half _DetailBlendMode; | |
| CBUFFER_END | |
| // Programs.................................................................................... | |
| // Often, there are separate vertex and fragment programs per pass like | |
| // "FragmentShadow" vs "FragmentForwardBase". However this is difficult to add new features because if | |
| // I want to change how emissions work, for example, I have to modify a bunch of separate pieces of code. | |
| // Instead, I tried writing all passes together in big functions. With sections like "#if UNITY_PASS_META" | |
| // for the parts specific to a particular pass. Sorry if it makes *reading* more confusing! | |
| FragmentInput VertexProgram(VertexInput v) | |
| { | |
| FragmentInput o; | |
| UNITY_SETUP_INSTANCE_ID(v); | |
| UNITY_INITIALIZE_OUTPUT(FragmentInput, o); | |
| UNITY_TRANSFER_INSTANCE_ID(v, o); | |
| UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); | |
| #if UNITY_PASS_META | |
| o.pos = UnityMetaVertexPosition(v.vertex, v.uv1.xy, v.uv2.xy, unity_LightmapST, unity_DynamicLightmapST); | |
| #elif UNITY_PASS_SHADOWCASTER | |
| TRANSFER_SHADOW_CASTER_NOPOS(o, o.pos) | |
| #else | |
| o.pos = UnityObjectToClipPos(v.vertex); | |
| #endif | |
| o.uv0.xy = TRANSFORM_TEX(v.uv0, _MainTex); | |
| #if UNITY_PASS_FORWARDBASE || UNITY_PASS_FORWARDADD | |
| float4 positionWs = mul(unity_ObjectToWorld, v.vertex); | |
| o.worldPos.xyz = positionWs.xyz; | |
| o.uv0.zw = TRANSFORM_TEX(SelectUvSet(v, _DetailUvSet), _DetailAlbedoMap); | |
| float3 normalWs = UnityObjectToWorldNormal(v.normal); | |
| #ifdef NORMAL_MAP_ON | |
| float4 tangentWs = float4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w); | |
| float3x3 tangentToWorld = CreateTangentToWorldPerVertex(normalWs, tangentWs.xyz, tangentWs.w); | |
| o.tangentToWorldAndPackedData[0].xyz = tangentToWorld[0]; | |
| o.tangentToWorldAndPackedData[1].xyz = tangentToWorld[1]; | |
| o.tangentToWorldAndPackedData[2].xyz = tangentToWorld[2]; | |
| #else | |
| o.tangentToWorldAndPackedData[0].xyz = 0; | |
| o.tangentToWorldAndPackedData[1].xyz = 0; | |
| o.tangentToWorldAndPackedData[2].xyz = normalWs; | |
| #endif | |
| UNITY_TRANSFER_LIGHTING(o, v.uv1); | |
| #endif | |
| #if UNITY_PASS_FORWARDBASE | |
| half4 ambientOrLightmapUV = 0; | |
| // Static lightmaps | |
| #ifdef LIGHTMAP_ON | |
| ambientOrLightmapUV.xy = v.uv1.xy * unity_LightmapST.xy + unity_LightmapST.zw; | |
| ambientOrLightmapUV.zw = 0; | |
| // Sample light probe for Dynamic objects only (no static or dynamic lightmaps) | |
| #elif UNITY_SHOULD_SAMPLE_SH | |
| #ifdef VERTEXLIGHT_ON | |
| // Approximated illumination from non-important point lights | |
| ambientOrLightmapUV.rgb = Shade4PointLights( | |
| unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0, | |
| unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb, | |
| unity_4LightAtten0, positionWs.xyz, normalWs); | |
| #endif | |
| ambientOrLightmapUV.rgb = ShadeSHPerVertex(normalWs, ambientOrLightmapUV.rgb); | |
| #endif | |
| #ifdef DYNAMICLIGHTMAP_ON | |
| ambientOrLightmapUV.zw = v.uv2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw; | |
| #endif | |
| o.ambientOrLightmapUv = ambientOrLightmapUV; | |
| #endif | |
| #ifdef UNITY_PASS_FORWARDADD | |
| o.lightDirectionWs = _WorldSpaceLightPos0.xyz - positionWs.xyz * _WorldSpaceLightPos0.w; | |
| #endif | |
| #if PARALLAX_MAP_ON | |
| float3 bitangent = cross(normalize(v.normal), normalize(v.tangent.xyz)) * v.tangent.w; | |
| float3x3 rotation = float3x3(v.tangent.xyz, bitangent, v.normal); | |
| half3 viewDirForParallax = mul(rotation, ObjSpaceViewDir(v.vertex)); | |
| o.tangentToWorldAndPackedData[0].w = viewDirForParallax.x; | |
| o.tangentToWorldAndPackedData[1].w = viewDirForParallax.y; | |
| o.tangentToWorldAndPackedData[2].w = viewDirForParallax.z; | |
| #endif | |
| #ifdef EDITOR_VISUALIZATION | |
| o.vizUV = 0; | |
| o.lightCoord = 0; | |
| if (unity_VisualizationMode == EDITORVIZ_TEXTURE) | |
| { | |
| o.vizUV = UnityMetaVizUV(unity_EditorViz_UVIndex, v.uv0.xy, v.uv1.xy, v.uv2.xy, unity_EditorViz_Texture_ST); | |
| } | |
| else if (unity_VisualizationMode == EDITORVIZ_SHOWLIGHTMASK) | |
| { | |
| o.vizUV = v.uv1.xy * unity_LightmapST.xy + unity_LightmapST.zw; | |
| o.lightCoord = mul(unity_EditorViz_WorldToLight, mul(unity_ObjectToWorld, float4(v.vertex.xyz, 1))); | |
| } | |
| #endif | |
| UNITY_TRANSFER_FOG_COMBINED_WITH_WORLD_POS(o, o.pos); | |
| return o; | |
| } | |
| half4 FragmentProgram(FragmentInput i) : SV_Target | |
| { | |
| UNITY_APPLY_DITHER_CROSSFADE(i.pos.xy); | |
| // Transparent cutout | |
| float4 uv0 = i.uv0; | |
| #if PARALLAX_MAP_ON | |
| half3 parallaxViewDirection = normalize(half3( | |
| i.tangentToWorldAndPackedData[0].w, | |
| i.tangentToWorldAndPackedData[1].w, | |
| i.tangentToWorldAndPackedData[2].w)); | |
| half h = UNITY_SAMPLE_TEX2D(_ParallaxMap, uv0.xy).g; | |
| float2 offset = ParallaxOffset1Step(h, _Parallax, parallaxViewDirection); | |
| uv0 = float4(uv0.xy + offset, uv0.zw + offset); | |
| #endif | |
| fixed4 baseColor = _Color * UNITY_SAMPLE_TEX2D(_MainTex, uv0.xy); | |
| #if ALPHA_TEST_ON | |
| clip(baseColor.a - _Cutoff); | |
| #endif | |
| UNITY_SETUP_INSTANCE_ID(i); | |
| UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); | |
| #if UNITY_PASS_FORWARDBASE || UNITY_PASS_FORWARDADD || UNITY_PASS_META | |
| // Get material properties | |
| #if MASK_MAP_ON | |
| fixed4 masks = UNITY_SAMPLE_TEX2D(_MaskMap, uv0.xy); | |
| half occlusion = _OcclusionScale * masks.r; | |
| half perceptualRoughness = _RoughnessScale * masks.g; | |
| half metallic = _MetallicScale * masks.b; | |
| half detailMask = masks.a; | |
| #else | |
| half occlusion = 1.0; | |
| half perceptualRoughness = _Roughness; | |
| half metallic = _Metallic; | |
| half detailMask = 1.0; | |
| #endif | |
| half3 albedo = baseColor.rgb; | |
| #if DETAIL_MAP_ON | |
| fixed4 detailBaseColor = UNITY_SAMPLE_TEX2D(_DetailAlbedoMap, uv0.zw); | |
| switch (_DetailBlendMode) | |
| { | |
| default: | |
| case 0: | |
| albedo.rgb *= LerpWhiteTo(unity_ColorSpaceDouble.rgb * detailBaseColor.rgb, detailMask); | |
| break; | |
| case 1: | |
| albedo.rgb *= LerpWhiteTo(detailBaseColor.rgb, detailMask); | |
| break; | |
| case 2: | |
| albedo.rgb += detailMask * detailBaseColor.rgb; | |
| break; | |
| case 3: | |
| albedo.rgb = lerp(albedo.rgb, detailBaseColor.rgb, detailMask); | |
| break; | |
| } | |
| #endif | |
| half oneMinusReflectivity = OneMinusReflectivityFromMetallic(metallic); | |
| half3 diffuseColor = albedo * oneMinusReflectivity; | |
| half3 specularColor = lerp(unity_ColorSpaceDielectricSpec.rgb, albedo, metallic); | |
| #if PREMULTIPLY_ALPHA_ON | |
| diffuseColor *= baseColor.a; | |
| #endif | |
| #endif | |
| #if EMISSION_MAP_ON | |
| half4 emissionSample = UNITY_SAMPLE_TEX2D(_EmissionMap, i.uv0.xy); | |
| half3 emission = _EmissionColor.rgb * emissionSample.rgb; | |
| #endif | |
| #if UNITY_PASS_FORWARDBASE || UNITY_PASS_FORWARDADD | |
| // Get geometric properties | |
| float3 positionWs = i.worldPos.xyz; | |
| float3 viewDirectionWs = positionWs.xyz - _WorldSpaceCameraPos; | |
| float3 unitViewDirectionWs = normalize(viewDirectionWs); | |
| #if NORMAL_MAP_ON | |
| half3 tangent = i.tangentToWorldAndPackedData[0].xyz; | |
| half3 bitangent = i.tangentToWorldAndPackedData[1].xyz; | |
| half3 normal = i.tangentToWorldAndPackedData[2].xyz; | |
| half3 normalTs = UnpackScaleNormal(UNITY_SAMPLE_TEX2D(_BumpMap, uv0.xy), _BumpScale); | |
| #if DETAIL_MAP_ON | |
| half3 detailNormalTs = UnpackScaleNormal(UNITY_SAMPLE_TEX2D(_DetailNormalMap, uv0.xy), _DetailNormalScale); | |
| switch (_DetailBlendMode) | |
| { | |
| default: | |
| normalTs = lerp(normalTs, BlendNormals(normalTs, detailNormalTs), detailMask); | |
| break; | |
| case 3: | |
| normalTs = lerp(normalTs, detailNormalTs, detailMask); | |
| break; | |
| } | |
| #endif | |
| float3 normalWs = normalize(tangent * normalTs.x + bitangent * normalTs.y + normal * normalTs.z); | |
| #else | |
| float3 normalWs = normalize(i.tangentToWorldAndPackedData[2].xyz); | |
| #endif | |
| // Get direct lighting properties | |
| UnityLight directLight; | |
| directLight.ndotl = 0; | |
| directLight.color = _LightColor0.rgb; | |
| #if UNITY_PASS_FORWARDBASE | |
| directLight.dir = _WorldSpaceLightPos0.xyz; | |
| #else | |
| directLight.dir = i.lightDirectionWs; | |
| #endif | |
| #ifndef USING_DIRECTIONAL_LIGHT | |
| directLight.dir = normalize(directLight.dir); | |
| #endif | |
| UNITY_LIGHT_ATTENUATION(attenuation, i, positionWs); | |
| // Get indirect lighting properties (Global Illumination) | |
| UnityIndirect indirectLight; | |
| indirectLight.diffuse = 0; | |
| indirectLight.specular = 0; | |
| #ifdef UNITY_PASS_FORWARDBASE | |
| // Indirect diffuse light | |
| #if UNITY_SHOULD_SAMPLE_SH | |
| // Light Probes | |
| indirectLight.diffuse = ShadeSHPerPixel(normalWs, i.ambientOrLightmapUv, positionWs); | |
| #endif | |
| #if defined(HANDLE_SHADOWS_BLENDING_IN_GI) | |
| half bakedAtten = UnitySampleBakedOcclusion(i.ambientOrLightmapUv.xy, positionWs); | |
| float zDist = dot(_WorldSpaceCameraPos - positionWs, UNITY_MATRIX_V[2].xyz); | |
| float fadeDist = UnityComputeShadowFadeDistance(positionWs, zDist); | |
| attenuation = UnityMixRealtimeAndBakedShadows(attenuation, bakedAtten, UnityComputeShadowFade(fadeDist)); | |
| #endif | |
| #if defined(LIGHTMAP_ON) | |
| // Baked lightmaps | |
| half4 bakedColorTex = UNITY_SAMPLE_TEX2D(unity_Lightmap, i.ambientOrLightmapUv.xy); | |
| half3 bakedColor = DecodeLightmap(bakedColorTex); | |
| #ifdef DIRLIGHTMAP_COMBINED | |
| fixed4 bakedDirTex = UNITY_SAMPLE_TEX2D_SAMPLER(unity_LightmapInd, unity_Lightmap, i.ambientOrLightmapUv.xy); | |
| indirectLight.diffuse += DecodeDirectionalLightmap(bakedColor, bakedDirTex, normalWs); | |
| #if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN) | |
| ResetUnityLight(directLight); | |
| indirectLight.diffuse = SubtractMainLightWithRealtimeAttenuationFromLightmap(indirectLight.diffuse, attenuation, bakedColorTex, normalWs); | |
| #endif | |
| #else | |
| indirectLight.diffuse += bakedColor; | |
| #if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN) | |
| ResetUnityLight(directLight); | |
| indirectLight.diffuse = SubtractMainLightWithRealtimeAttenuationFromLightmap(indirectLight.diffuse, attenuation, bakedColorTex, normalWs); | |
| #endif | |
| #endif | |
| #endif | |
| #ifdef DYNAMICLIGHTMAP_ON | |
| // Dynamic lightmaps | |
| fixed4 realtimeColorTex = UNITY_SAMPLE_TEX2D(unity_DynamicLightmap, i.ambientOrLightmapUv.zw); | |
| half3 realtimeColor = DecodeRealtimeLightmap(realtimeColorTex); | |
| #ifdef DIRLIGHTMAP_COMBINED | |
| half4 realtimeDirTex = UNITY_SAMPLE_TEX2D_SAMPLER(unity_DynamicDirectionality, unity_DynamicLightmap, i.ambientOrLightmapUv.zw); | |
| indirectLight.diffuse += DecodeDirectionalLightmap(realtimeColor, realtimeDirTex, normalWs); | |
| #else | |
| indirectLight.diffuse += realtimeColor; | |
| #endif | |
| #endif | |
| indirectLight.diffuse *= occlusion; | |
| // Indirect specular light | |
| #if REFLECTION_MODE_NONE | |
| indirectLight.specular = unity_IndirectSpecColor.rgb; | |
| #elif REFLECTION_MODE_PROBES | |
| // Reflection Probes | |
| indirectLight.specular = GetProbeIndirectSpecular(reflect(unitViewDirectionWs, normalWs), positionWs, perceptualRoughness); | |
| #endif | |
| indirectLight.specular *= occlusion; | |
| #endif | |
| directLight.color *= attenuation; | |
| // Lighting | |
| half4 color = UNITY_BRDF_PBS(diffuseColor, specularColor, oneMinusReflectivity, 1.0 - perceptualRoughness, normalWs, -unitViewDirectionWs, directLight, indirectLight); | |
| #if EMISSION_MAP_ON | |
| color.rgb += emission.rgb; | |
| #endif | |
| // Effects | |
| UNITY_EXTRACT_FOG_FROM_WORLD_POS(i); | |
| UNITY_APPLY_FOG(_unity_fogCoord, color.rgb); | |
| // Final transparency | |
| #if FADE_TRANSPARENCY_ON | |
| color.a = baseColor.a; | |
| #else | |
| color.a = 1.0 - oneMinusReflectivity + baseColor.a * oneMinusReflectivity; | |
| #endif | |
| return color; | |
| #endif | |
| // Cast shadows. Also, how the object appears in the camera depth texture. | |
| #if UNITY_PASS_SHADOWCASTER | |
| SHADOW_CASTER_FRAGMENT(i); | |
| #endif | |
| // Lightmapping | |
| #if UNITY_PASS_META | |
| UnityMetaInput o; | |
| UNITY_INITIALIZE_OUTPUT(UnityMetaInput, o); | |
| #ifdef EDITOR_VISUALIZATION | |
| o.Albedo = diffuseColor; | |
| o.VizUV = i.vizUV; | |
| o.LightCoord = i.lightCoord; | |
| #else | |
| o.Albedo = diffuseColor + 0.5 * perceptualRoughness * specularColor; | |
| #endif | |
| o.SpecularColor = specularColor; | |
| #if EMISSION_MAP_ON | |
| o.Emission = emission; | |
| #endif | |
| return UnityMetaFragment(o); | |
| #endif | |
| return 0; | |
| } | |
| ENDHLSL | |
| SubShader | |
| { | |
| Tags | |
| { | |
| "PerformanceChecks" = "False" | |
| "Queue" = "Geometry" | |
| "RenderType" = "Opaque" | |
| } | |
| Cull [_CullMode] | |
| ZTest [_ZTest] | |
| ZWrite [_ZWrite] | |
| Pass | |
| { | |
| Tags | |
| { | |
| "LightMode" = "ForwardBase" | |
| } | |
| Blend [_BlendSrc] [_BlendDst] | |
| BlendOp [_BlendOp] | |
| HLSLPROGRAM | |
| #pragma vertex VertexProgram | |
| #pragma fragment FragmentProgram | |
| #pragma target 3.0 | |
| #pragma multi_compile_fog | |
| #pragma multi_compile_fwdbase | |
| #pragma multi_compile_instancing | |
| #pragma shader_feature_local ALPHA_TEST_ON | |
| #pragma shader_feature_local DETAIL_MAP_ON | |
| #pragma shader_feature_local EMISSION_MAP_ON | |
| #pragma shader_feature_local FADE_TRANSPARENCY_ON | |
| #pragma shader_feature_local MASK_MAP_ON | |
| #pragma shader_feature_local NORMAL_MAP_ON | |
| #pragma shader_feature_local PARALLAX_MAP_ON | |
| #pragma shader_feature_local PREMULTIPLY_ALPHA_ON | |
| #pragma shader_feature_local REFLECTION_MODE_NONE REFLECTION_MODE_PROBES | |
| #pragma shader_feature_local _SPECULARHIGHLIGHTS_OFF | |
| ENDHLSL | |
| } | |
| Pass | |
| { | |
| Tags | |
| { | |
| "LightMode" = "ForwardAdd" | |
| } | |
| Blend [_BlendSrc] One | |
| Fog { Color (0,0,0,0) } | |
| ZTest LEqual | |
| ZWrite Off | |
| HLSLPROGRAM | |
| #pragma vertex VertexProgram | |
| #pragma fragment FragmentProgram | |
| #pragma target 3.0 | |
| #pragma multi_compile_fog | |
| #pragma multi_compile_fwdadd_fullshadows | |
| #pragma shader_feature_local ALPHA_TEST_ON | |
| #pragma shader_feature_local DETAIL_MAP_ON | |
| #pragma shader_feature_local EMISSION_MAP_ON | |
| #pragma shader_feature_local FADE_TRANSPARENCY_ON | |
| #pragma shader_feature_local MASK_MAP_ON | |
| #pragma shader_feature_local NORMAL_MAP_ON | |
| #pragma shader_feature_local PARALLAX_MAP_ON | |
| #pragma shader_feature_local PREMULTIPLY_ALPHA_ON | |
| #pragma shader_feature_local _SPECULARHIGHLIGHTS_OFF | |
| ENDHLSL | |
| } | |
| Pass | |
| { | |
| Tags | |
| { | |
| "LightMode" = "ShadowCaster" | |
| } | |
| ZTest LEqual | |
| ZWrite On | |
| HLSLPROGRAM | |
| #pragma vertex VertexProgram | |
| #pragma fragment FragmentProgram | |
| #pragma target 3.0 | |
| #pragma multi_compile_instancing | |
| #pragma multi_compile_shadowcaster | |
| #pragma shader_feature_local ALPHA_TEST_ON | |
| #pragma shader_feature_local PARALLAX_MAP_ON | |
| ENDHLSL | |
| } | |
| Pass | |
| { | |
| Tags | |
| { | |
| "LightMode" = "Meta" | |
| } | |
| Cull Off | |
| HLSLPROGRAM | |
| #pragma vertex VertexProgram | |
| #pragma fragment FragmentProgram | |
| #pragma target 3.0 | |
| #pragma shader_feature_local ALPHA_TEST_ON | |
| #pragma shader_feature_local DETAIL_MAP_ON | |
| #pragma shader_feature EDITOR_VISUALIZATION | |
| #pragma shader_feature_local EMISSION_MAP_ON | |
| #pragma shader_feature_local MASK_MAP_ON | |
| #pragma shader_feature_local PARALLAX_MAP_ON | |
| #pragma shader_feature_local PREMULTIPLY_ALPHA_ON | |
| ENDHLSL | |
| } | |
| } | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Revision 8 - Removed custom stuff copied from
AutoLight.cgincandUnityCG.cginc. I only had that so I could change the names of a few variables. But it made this more complicated to read.