377 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			HLSL
		
	
	
	
	
	
		
		
			
		
	
	
			377 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			HLSL
		
	
	
	
	
	
|  | #if (SHADERPASS != SHADERPASS_DEPTHONLY) && (SHADERPASS != SHADERPASS_DBUFFER_PROJECTOR) && (SHADERPASS != SHADERPASS_DBUFFER_MESH) && (SHADERPASS != SHADERPASS_FORWARD_EMISSIVE_PROJECTOR) && (SHADERPASS != SHADERPASS_FORWARD_EMISSIVE_MESH) && (SHADERPASS != SHADERPASS_DECAL_SCREEN_SPACE_PROJECTOR) && (SHADERPASS != SHADERPASS_DECAL_SCREEN_SPACE_MESH) && (SHADERPASS != SHADERPASS_DECAL_GBUFFER_PROJECTOR) && (SHADERPASS != SHADERPASS_DECAL_GBUFFER_MESH) | ||
|  | #error SHADERPASS_is_not_correctly_define | ||
|  | #endif | ||
|  | 
 | ||
|  | #if !defined(SHADERPASS) | ||
|  | #error SHADERPASS_is_not_define | ||
|  | #endif | ||
|  | 
 | ||
|  | #if (SHADERPASS == SHADERPASS_DBUFFER_PROJECTOR) || (SHADERPASS == SHADERPASS_FORWARD_EMISSIVE_PROJECTOR) || (SHADERPASS == SHADERPASS_DECAL_SCREEN_SPACE_PROJECTOR) || (SHADERPASS == SHADERPASS_DECAL_GBUFFER_PROJECTOR) | ||
|  | #define DECAL_PROJECTOR | ||
|  | #endif | ||
|  | 
 | ||
|  | #if (SHADERPASS == SHADERPASS_DBUFFER_MESH) || (SHADERPASS == SHADERPASS_FORWARD_EMISSIVE_MESH) || (SHADERPASS == SHADERPASS_DECAL_SCREEN_SPACE_MESH) || (SHADERPASS == SHADERPASS_DECAL_GBUFFER_MESH) | ||
|  | #define DECAL_MESH | ||
|  | #endif | ||
|  | 
 | ||
|  | #if (SHADERPASS == SHADERPASS_DBUFFER_PROJECTOR) || (SHADERPASS == SHADERPASS_DBUFFER_MESH) | ||
|  | #define DECAL_DBUFFER | ||
|  | #endif | ||
|  | 
 | ||
|  | #if (SHADERPASS == SHADERPASS_DECAL_SCREEN_SPACE_PROJECTOR) || (SHADERPASS == SHADERPASS_DECAL_SCREEN_SPACE_MESH) | ||
|  | #define DECAL_SCREEN_SPACE | ||
|  | #endif | ||
|  | 
 | ||
|  | #if (SHADERPASS == SHADERPASS_DECAL_GBUFFER_PROJECTOR) || (SHADERPASS == SHADERPASS_DECAL_GBUFFER_MESH) | ||
|  | #define DECAL_GBUFFER | ||
|  | #endif | ||
|  | 
 | ||
|  | #if (SHADERPASS == SHADERPASS_FORWARD_EMISSIVE_PROJECTOR) || (SHADERPASS == SHADERPASS_FORWARD_EMISSIVE_MESH) | ||
|  | #define DECAL_FORWARD_EMISSIVE | ||
|  | #endif | ||
|  | 
 | ||
|  | #if ((!defined(_MATERIAL_AFFECTS_NORMAL) && defined(_MATERIAL_AFFECTS_ALBEDO)) || (defined(_MATERIAL_AFFECTS_NORMAL) && defined(_MATERIAL_AFFECTS_NORMAL_BLEND))) && (defined(DECAL_SCREEN_SPACE) || defined(DECAL_GBUFFER)) | ||
|  | #define DECAL_RECONSTRUCT_NORMAL | ||
|  | #elif defined(DECAL_ANGLE_FADE) | ||
|  | #define DECAL_LOAD_NORMAL | ||
|  | #endif | ||
|  | 
 | ||
|  | #ifdef _DECAL_LAYERS | ||
|  | #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareRenderingLayerTexture.hlsl" | ||
|  | #endif | ||
|  | 
 | ||
|  | #if defined(DECAL_LOAD_NORMAL) | ||
|  | #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareNormalsTexture.hlsl" | ||
|  | #endif | ||
|  | 
 | ||
|  | #if defined(DECAL_PROJECTOR) || defined(DECAL_RECONSTRUCT_NORMAL) | ||
|  | #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl" | ||
|  | #endif | ||
|  | 
 | ||
|  | #ifdef DECAL_MESH | ||
|  | #include "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/DecalMeshBiasTypeEnum.cs.hlsl" | ||
|  | #endif | ||
|  | #ifdef DECAL_RECONSTRUCT_NORMAL | ||
|  | #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/NormalReconstruction.hlsl" | ||
|  | #endif | ||
|  | 
 | ||
|  | #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRendering.hlsl" | ||
|  | 
 | ||
|  | void MeshDecalsPositionZBias(inout Varyings input) | ||
|  | { | ||
|  | #if UNITY_REVERSED_Z | ||
|  |     input.positionCS.z -= _DecalMeshDepthBias; | ||
|  | #else | ||
|  |     input.positionCS.z += _DecalMeshDepthBias; | ||
|  | #endif | ||
|  | } | ||
|  | 
 | ||
|  | void InitializeInputData(Varyings input, float3 positionWS, half3 normalWS, half3 viewDirectionWS, out InputData inputData) | ||
|  | { | ||
|  |     inputData = (InputData)0; | ||
|  | 
 | ||
|  |     inputData.positionWS = positionWS; | ||
|  |     inputData.normalWS = normalWS; | ||
|  |     inputData.viewDirectionWS = viewDirectionWS; | ||
|  | 
 | ||
|  | #if defined(VARYINGS_NEED_SHADOW_COORD) && defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR) | ||
|  |     inputData.shadowCoord = input.shadowCoord; | ||
|  | #elif defined(MAIN_LIGHT_CALCULATE_SHADOWS) | ||
|  |     inputData.shadowCoord = TransformWorldToShadowCoord(positionWS); | ||
|  | #else | ||
|  |     inputData.shadowCoord = float4(0, 0, 0, 0); | ||
|  | #endif | ||
|  | 
 | ||
|  | #ifdef VARYINGS_NEED_FOG_AND_VERTEX_LIGHT | ||
|  |     inputData.fogCoord = InitializeInputDataFog(float4(positionWS, 1.0), input.fogFactorAndVertexLight.x); | ||
|  |     inputData.vertexLighting = input.fogFactorAndVertexLight.yzw; | ||
|  | #endif | ||
|  | 
 | ||
|  | #if defined(VARYINGS_NEED_DYNAMIC_LIGHTMAP_UV) && defined(DYNAMICLIGHTMAP_ON) | ||
|  |     inputData.bakedGI = SAMPLE_GI(input.staticLightmapUV, input.dynamicLightmapUV.xy, half3(input.sh), normalWS); | ||
|  |     #if defined(VARYINGS_NEED_STATIC_LIGHTMAP_UV) | ||
|  |     inputData.shadowMask = SAMPLE_SHADOWMASK(input.staticLightmapUV); | ||
|  |     #endif | ||
|  | #elif defined(VARYINGS_NEED_STATIC_LIGHTMAP_UV) | ||
|  | #if !defined(LIGHTMAP_ON) && (defined(PROBE_VOLUMES_L1) || defined(PROBE_VOLUMES_L2)) | ||
|  |     inputData.bakedGI = SAMPLE_GI(input.sh, | ||
|  |         GetAbsolutePositionWS(inputData.positionWS), | ||
|  |         inputData.normalWS, | ||
|  |         inputData.viewDirectionWS, | ||
|  |         input.positionCS.xy, | ||
|  |         input.probeOcclusion, | ||
|  |         inputData.shadowMask); | ||
|  | #else | ||
|  |     inputData.bakedGI = SAMPLE_GI(input.staticLightmapUV, half3(input.sh), normalWS); | ||
|  |     #if defined(VARYINGS_NEED_STATIC_LIGHTMAP_UV) | ||
|  |     inputData.shadowMask = SAMPLE_SHADOWMASK(input.staticLightmapUV); | ||
|  |     #endif | ||
|  | #endif | ||
|  | #endif | ||
|  | 
 | ||
|  |     #if defined(DEBUG_DISPLAY) | ||
|  |     #if defined(VARYINGS_NEED_DYNAMIC_LIGHTMAP_UV) && defined(DYNAMICLIGHTMAP_ON) | ||
|  |     inputData.dynamicLightmapUV = input.dynamicLightmapUV.xy; | ||
|  |     #endif | ||
|  |     #if defined(VARYINGS_NEED_STATIC_LIGHTMAP_UV) && defined(LIGHTMAP_ON) | ||
|  |     inputData.staticLightmapUV = input.staticLightmapUV; | ||
|  |     #elif defined(VARYINGS_NEED_SH) | ||
|  |     inputData.vertexSH = input.sh; | ||
|  |     #endif | ||
|  |     #if defined(USE_APV_PROBE_OCCLUSION) | ||
|  |     inputData.probeOcclusion = input.probeOcclusion; | ||
|  |     #endif | ||
|  |     #endif | ||
|  | 
 | ||
|  |     inputData.normalizedScreenSpaceUV = GetNormalizedScreenSpaceUV(input.positionCS); | ||
|  | } | ||
|  | 
 | ||
|  | void GetSurface(DecalSurfaceData decalSurfaceData, inout SurfaceData surfaceData) | ||
|  | { | ||
|  |     surfaceData.albedo = decalSurfaceData.baseColor.rgb; | ||
|  |     surfaceData.metallic = saturate(decalSurfaceData.metallic); | ||
|  |     surfaceData.specular = 0; | ||
|  |     surfaceData.smoothness = saturate(decalSurfaceData.smoothness); | ||
|  |     surfaceData.occlusion = decalSurfaceData.occlusion; | ||
|  |     surfaceData.emission = decalSurfaceData.emissive; | ||
|  |     surfaceData.alpha = saturate(decalSurfaceData.baseColor.w); | ||
|  |     surfaceData.clearCoatMask = 0; | ||
|  |     surfaceData.clearCoatSmoothness = 1; | ||
|  | } | ||
|  | 
 | ||
|  | PackedVaryings Vert(Attributes inputMesh) | ||
|  | { | ||
|  |     Varyings output = (Varyings)0; | ||
|  |     UNITY_SETUP_INSTANCE_ID(inputMesh); | ||
|  |     UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); | ||
|  | #ifdef DECAL_MESH | ||
|  |     if (_DecalMeshBiasType == DECALMESHDEPTHBIASTYPE_VIEW_BIAS) // TODO: Check performance of branch | ||
|  |     { | ||
|  |         float3 viewDirectionOS = GetObjectSpaceNormalizeViewDir(inputMesh.positionOS); | ||
|  |         inputMesh.positionOS += viewDirectionOS * (_DecalMeshViewBias); | ||
|  |     } | ||
|  |     output = BuildVaryings(inputMesh); | ||
|  |     if (_DecalMeshBiasType == DECALMESHDEPTHBIASTYPE_DEPTH_BIAS) // TODO: Check performance of branch | ||
|  |     { | ||
|  |         MeshDecalsPositionZBias(output); | ||
|  |     } | ||
|  | #else | ||
|  |     output = BuildVaryings(inputMesh); | ||
|  | #endif | ||
|  | 
 | ||
|  | #if defined(VARYINGS_NEED_STATIC_LIGHTMAP_UV) | ||
|  |     OUTPUT_LIGHTMAP_UV(inputMesh.uv1, unity_LightmapST, output.staticLightmapUV); | ||
|  | #endif | ||
|  | 
 | ||
|  | #if defined(VARYINGS_NEED_DYNAMIC_LIGHTMAP_UV) && defined(DYNAMICLIGHTMAP_ON) | ||
|  |     output.dynamicLightmapUV.xy = inputMesh.uv2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw; | ||
|  | #endif | ||
|  | 
 | ||
|  | #if defined(VARYINGS_NEED_SH) && !defined(LIGHTMAP_ON) | ||
|  |     output.sh = float3(SampleSHVertex(half3(output.normalWS))); | ||
|  | #endif | ||
|  | 
 | ||
|  |     PackedVaryings packedOutput = (PackedVaryings)0; | ||
|  |     packedOutput = PackVaryings(output); | ||
|  | 
 | ||
|  |     return packedOutput; | ||
|  | } | ||
|  | 
 | ||
|  | void Frag(PackedVaryings packedInput, | ||
|  | #if defined(DECAL_DBUFFER) | ||
|  |     OUTPUT_DBUFFER(outDBuffer) | ||
|  | #elif defined(DECAL_SCREEN_SPACE) | ||
|  |     out half4 outColor : SV_Target0 | ||
|  | #elif defined(DECAL_GBUFFER) | ||
|  |     out GBufferFragOutput fragmentOutput | ||
|  | #elif defined(DECAL_FORWARD_EMISSIVE) | ||
|  |     out half4 outEmissive : SV_Target0 | ||
|  | #elif defined(SCENEPICKINGPASS) | ||
|  |     out float4 outColor : SV_Target0 | ||
|  | #else | ||
|  | #error SHADERPASS_is_not_correctly_define | ||
|  | #endif | ||
|  | ) | ||
|  | { | ||
|  | #ifdef SCENEPICKINGPASS | ||
|  |     outColor = _SelectionID; | ||
|  | #else | ||
|  |     UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(packedInput); | ||
|  |     UNITY_SETUP_INSTANCE_ID(packedInput); | ||
|  |     Varyings input = UnpackVaryings(packedInput); | ||
|  | 
 | ||
|  |     half angleFadeFactor = 1.0; | ||
|  | 
 | ||
|  |     float2 positionCS = input.positionCS.xy; | ||
|  | 
 | ||
|  |     // Only screen space needs flip logic, other passes do not setup needed properties so we skip here | ||
|  | #if defined(DECAL_SCREEN_SPACE) | ||
|  |     TransformScreenUV(positionCS, _ScreenSize.y); | ||
|  | #endif | ||
|  | 
 | ||
|  | #ifdef _DECAL_LAYERS | ||
|  | #ifdef _RENDER_PASS_ENABLED | ||
|  |     uint surfaceRenderingLayer = LOAD_FRAMEBUFFER_X_INPUT(GBUFFER4, positionCS.xy).r; | ||
|  | #else | ||
|  |     uint surfaceRenderingLayer = LoadSceneRenderingLayer(positionCS.xy); | ||
|  | #endif | ||
|  |     uint projectorRenderingLayer = uint(UNITY_ACCESS_INSTANCED_PROP(Decal, _DecalLayerMaskFromDecal)); | ||
|  |     // This is simple trick to clip if there is no matching layers | ||
|  |     // Part (surfaceRenderingLayer & projectorRenderingLayer) will produce 0, 1, 2 ... | ||
|  |     // Finally we subtract with small value to remmap only zero to negative value | ||
|  |     clip((surfaceRenderingLayer & projectorRenderingLayer) - 0.1); | ||
|  | #endif | ||
|  | 
 | ||
|  | #if defined(DECAL_PROJECTOR) | ||
|  | #if UNITY_REVERSED_Z | ||
|  | #if _RENDER_PASS_ENABLED | ||
|  |     float depth = LOAD_FRAMEBUFFER_X_INPUT(GBUFFER3, positionCS.xy).x; | ||
|  | #else | ||
|  |     float depth = LoadSceneDepth(positionCS.xy); | ||
|  | #endif | ||
|  | #else | ||
|  | #if _RENDER_PASS_ENABLED | ||
|  |     float depth = lerp(UNITY_NEAR_CLIP_VALUE, 1, LOAD_FRAMEBUFFER_X_INPUT(GBUFFER3, positionCS.xy)); | ||
|  | #else | ||
|  |     // Adjust z to match NDC for OpenGL | ||
|  |     float depth = lerp(UNITY_NEAR_CLIP_VALUE, 1, LoadSceneDepth(positionCS.xy)); | ||
|  | #endif | ||
|  | #endif | ||
|  | #endif | ||
|  | 
 | ||
|  | #if defined(DECAL_RECONSTRUCT_NORMAL) | ||
|  |     #if defined(_DECAL_NORMAL_BLEND_HIGH) | ||
|  |         half3 normalWS = half3(ReconstructNormalTap9(positionCS.xy)); | ||
|  |     #elif defined(_DECAL_NORMAL_BLEND_MEDIUM) | ||
|  |         half3 normalWS = half3(ReconstructNormalTap5(positionCS.xy)); | ||
|  |     #else | ||
|  |         half3 normalWS = half3(ReconstructNormalDerivative(input.positionCS.xy)); | ||
|  |     #endif | ||
|  | #elif defined(DECAL_LOAD_NORMAL) | ||
|  |     half3 normalWS = half3(LoadSceneNormals(positionCS.xy)); | ||
|  | #endif | ||
|  | 
 | ||
|  |     float2 positionSS = FoveatedRemapNonUniformToLinearCS(input.positionCS.xy) * _ScreenSize.zw; | ||
|  | 
 | ||
|  | #ifdef DECAL_PROJECTOR | ||
|  |     float3 positionWS = ComputeWorldSpacePosition(positionSS, depth, UNITY_MATRIX_I_VP); | ||
|  | 
 | ||
|  | #ifdef VARYINGS_NEED_POSITION_WS | ||
|  |     input.positionWS = positionWS; | ||
|  | #endif | ||
|  | 
 | ||
|  |     // Transform from relative world space to decal space (DS) to clip the decal | ||
|  |     float3 positionDS = TransformWorldToObject(positionWS); | ||
|  |     positionDS = positionDS * float3(1.0, -1.0, 1.0); | ||
|  | 
 | ||
|  |     // call clip as early as possible | ||
|  |     float clipValue = 0.5 - Max3(abs(positionDS).x, abs(positionDS).y, abs(positionDS).z); | ||
|  |     clip(clipValue); | ||
|  | 
 | ||
|  |     float2 texCoord = positionDS.xz + float2(0.5, 0.5); | ||
|  | #ifdef VARYINGS_NEED_TEXCOORD0 | ||
|  |     input.texCoord0.xy = texCoord; | ||
|  | #endif | ||
|  | #ifdef VARYINGS_NEED_TEXCOORD1 | ||
|  |     input.texCoord1.xy = texCoord; | ||
|  | #endif | ||
|  | #ifdef VARYINGS_NEED_TEXCOORD2 | ||
|  |     input.texCoord2.xy = texCoord; | ||
|  | #endif | ||
|  | #ifdef VARYINGS_NEED_TEXCOORD3 | ||
|  |     input.texCoord3.xy = texCoord; | ||
|  | #endif | ||
|  | 
 | ||
|  | #ifdef DECAL_ANGLE_FADE | ||
|  |     // Check if this decal projector require angle fading | ||
|  |     half4x4 normalToWorld = UNITY_ACCESS_INSTANCED_PROP(Decal, _NormalToWorld); | ||
|  |     half2 angleFade = half2(normalToWorld[1][3], normalToWorld[2][3]); | ||
|  | 
 | ||
|  |     if (angleFade.y < 0.0f) // if angle fade is enabled | ||
|  |     { | ||
|  |         half3 decalNormal = half3(normalToWorld[0].z, normalToWorld[1].z, normalToWorld[2].z); | ||
|  |         half dotAngle = dot(normalWS, decalNormal); | ||
|  |         // See equation in DecalCreateDrawCallSystem.cs - simplified to a madd mul add here | ||
|  |         angleFadeFactor = saturate(angleFade.x + angleFade.y * (dotAngle * (dotAngle - 2.0))); | ||
|  |     } | ||
|  | #endif | ||
|  | 
 | ||
|  | 
 | ||
|  | #else // Decal mesh | ||
|  |     float3 positionWS = input.positionWS.xyz; | ||
|  | #endif | ||
|  | 
 | ||
|  |     half3 viewDirectionWS = GetWorldSpaceNormalizeViewDir(positionWS); | ||
|  | 
 | ||
|  |     DecalSurfaceData surfaceData; | ||
|  |     GetSurfaceData(input, input.positionCS, angleFadeFactor, surfaceData); | ||
|  | 
 | ||
|  | #if defined(DECAL_DBUFFER) | ||
|  |     ENCODE_INTO_DBUFFER(surfaceData, outDBuffer); | ||
|  | #elif defined(DECAL_SCREEN_SPACE) | ||
|  | 
 | ||
|  |     // Blend normal with background | ||
|  | #ifdef DECAL_RECONSTRUCT_NORMAL | ||
|  |     surfaceData.normalWS.xyz = normalize(lerp(normalWS.xyz, surfaceData.normalWS.xyz, surfaceData.normalWS.w)); | ||
|  | #endif | ||
|  | 
 | ||
|  |     InputData inputData; | ||
|  |     InitializeInputData(input, positionWS, surfaceData.normalWS.xyz, viewDirectionWS, inputData); | ||
|  | 
 | ||
|  |     SurfaceData surface = (SurfaceData)0; | ||
|  |     GetSurface(surfaceData, surface); | ||
|  | 
 | ||
|  |     half4 color = UniversalFragmentPBR(inputData, surface); | ||
|  | 
 | ||
|  |     color.rgb = MixFog(color.rgb, inputData.fogCoord); | ||
|  | 
 | ||
|  |     outColor = color; | ||
|  | #elif defined(DECAL_GBUFFER) | ||
|  | 
 | ||
|  |     // Need to reconstruct normal here for inputData.bakedGI, but also save off surfaceData.normalWS for correct GBuffer blending | ||
|  |     half3 normalToPack = surfaceData.normalWS.xyz; | ||
|  | #ifdef DECAL_RECONSTRUCT_NORMAL | ||
|  |     surfaceData.normalWS.xyz = normalize(lerp(normalWS.xyz, surfaceData.normalWS.xyz, surfaceData.normalWS.w)); | ||
|  | #endif | ||
|  | 
 | ||
|  |     InputData inputData; | ||
|  |     InitializeInputData(input, positionWS, surfaceData.normalWS.xyz, viewDirectionWS, inputData); | ||
|  | 
 | ||
|  |     SurfaceData surface = (SurfaceData)0; | ||
|  |     GetSurface(surfaceData, surface); | ||
|  | 
 | ||
|  |     BRDFData brdfData; | ||
|  |     InitializeBRDFData(surface.albedo, surface.metallic, 0, surface.smoothness, surface.alpha, brdfData); | ||
|  | 
 | ||
|  |     // Skip GI if there is no abledo | ||
|  | #ifdef _MATERIAL_AFFECTS_ALBEDO | ||
|  |     Light mainLight = GetMainLight(inputData.shadowCoord, inputData.positionWS, inputData.shadowMask); | ||
|  |     MixRealtimeAndBakedGI(mainLight, surfaceData.normalWS.xyz, inputData.bakedGI, inputData.shadowMask); | ||
|  |     half3 color = GlobalIllumination(brdfData, inputData.bakedGI, surface.occlusion, surfaceData.normalWS.xyz, inputData.viewDirectionWS); | ||
|  | #else | ||
|  |     half3 color = 0; | ||
|  | #endif | ||
|  | 
 | ||
|  |     // We can not use usual GBuffer functions (etc. BRDFDataToGbuffer) as we use alpha for blending | ||
|  |     #pragma warning (disable : 3578) // The output value isn't completely initialized. | ||
|  |     half3 packedNormalWS = PackGBufferNormal(normalToPack); | ||
|  |     fragmentOutput.gBuffer0 = half4(surfaceData.baseColor.rgb, surfaceData.baseColor.a); | ||
|  |     fragmentOutput.gBuffer1 = 0; | ||
|  |     fragmentOutput.gBuffer2 = half4(packedNormalWS, surfaceData.normalWS.a); | ||
|  |     fragmentOutput.color = half4(surfaceData.emissive + color, surfaceData.baseColor.a); | ||
|  | 
 | ||
|  | #if defined(GBUFFER_FEATURE_SHADOWMASK) | ||
|  |     fragmentOutput.shadowMask = inputData.shadowMask; // will have unity_ProbesOcclusion value if subtractive lighting is used (baked) | ||
|  | #endif | ||
|  | 
 | ||
|  |     #pragma warning (default : 3578) // Restore output value isn't completely initialized. | ||
|  | 
 | ||
|  | #elif defined(DECAL_FORWARD_EMISSIVE) | ||
|  |     // Emissive need to be pre-exposed | ||
|  |     outEmissive.rgb = surfaceData.emissive * GetCurrentExposureMultiplier(); | ||
|  |     outEmissive.a = surfaceData.baseColor.a; | ||
|  | #else | ||
|  | #endif | ||
|  | #endif | ||
|  | } |