// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt) #ifndef UNITY_STANDARD_CORE_INCLUDED #define UNITY_STANDARD_CORE_INCLUDED #include "UnityCG.cginc" #include "UnityShaderVariables.cginc" #include "UnityLightingCommon.cginc" // Workaround for some failsafes #define UNITY_BRDF_PBS #include "FilamentMaterialInputs.cginc" #include "FilamentCommonMath.cginc" #include "FilamentCommonLighting.cginc" #include "FilamentCommonMaterial.cginc" #include "FilamentCommonShading.cginc" #include "FilamentShadingParameters.cginc" #include "UnityStandardConfig.cginc" #include "UnityStandardInput.cginc" //#include "UnityPBSLighting.cginc" #include "UnityStandardUtils.cginc" #include "UnityImageBasedLightingMinimal.cginc" #include "UnityGBuffer.cginc" #include "UnityGlobalIllumination.cginc" #include "FilamentShadingLit.cginc" #include "SharedFilteringLib.hlsl" // Note: AutoLight.cginc is included below. //------------------------------------------------------------------------------------- // counterpart for NormalizePerPixelNormal // skips normalization per-vertex and expects normalization to happen per-pixel half3 NormalizePerVertexNormal (float3 n) // takes float to avoid overflow { #if (SHADER_TARGET < 30) || UNITY_STANDARD_SIMPLE return normalize(n); #else return n; // will normalize per-pixel instead #endif } float3 NormalizePerPixelNormal (float3 n) { #if (SHADER_TARGET < 30) || UNITY_STANDARD_SIMPLE return n; #else return normalize((float3)n); // takes float to avoid overflow #endif } //------------------------------------------------------------------------------------- fixed4 SampleShadowMaskBicubic(float2 uv) { #if defined(SHADER_API_D3D11) float width, height; unity_ShadowMask.GetDimensions(width, height); float4 unity_ShadowMask_TexelSize = float4(width, height, 1.0/width, 1.0/height); return SampleTexture2DBicubicFilter(TEXTURE2D_ARGS(unity_ShadowMask, samplerunity_ShadowMask), uv, unity_ShadowMask_TexelSize); #else return SAMPLE_TEXTURE2D(unity_ShadowMask, samplerunity_ShadowMask, uv); #endif } fixed UnitySampleBakedOcclusionBicubic (float2 lightmapUV, float3 worldPos) { #if defined (SHADOWS_SHADOWMASK) #if defined(LIGHTMAP_ON) fixed4 rawOcclusionMask = SampleShadowMaskBicubic(lightmapUV.xy); #else fixed4 rawOcclusionMask = fixed4(1.0, 1.0, 1.0, 1.0); #if UNITY_LIGHT_PROBE_PROXY_VOLUME if (unity_ProbeVolumeParams.x == 1.0) rawOcclusionMask = LPPV_SampleProbeOcclusion(worldPos); else rawOcclusionMask = SampleShadowMaskBicubic(lightmapUV.xy); #else rawOcclusionMask = SampleShadowMaskBicubic(lightmapUV.xy); #endif #endif return saturate(dot(rawOcclusionMask, unity_OcclusionMaskSelector)); #else //In forward dynamic objects can only get baked occlusion from LPPV, light probe occlusion is done on the CPU by attenuating the light color. fixed atten = 1.0f; #if defined(UNITY_INSTANCING_ENABLED) && defined(UNITY_USE_SHCOEFFS_ARRAYS) // ...unless we are doing instancing, and the attenuation is packed into SHC array's .w component. atten = unity_SHC.w; #endif #if UNITY_LIGHT_PROBE_PROXY_VOLUME && !defined(LIGHTMAP_ON) && !UNITY_STANDARD_SIMPLE fixed4 rawOcclusionMask = atten.xxxx; if (unity_ProbeVolumeParams.x == 1.0) rawOcclusionMask = LPPV_SampleProbeOcclusion(worldPos); return saturate(dot(rawOcclusionMask, unity_OcclusionMaskSelector)); #endif return atten; #endif } void GetBakedAttenuation(inout float atten, float2 lightmapUV, float3 worldPos) { // Base pass with Lightmap support is responsible for handling ShadowMask / blending here for performance reason #if defined(HANDLE_SHADOWS_BLENDING_IN_GI) half bakedAtten = UnitySampleBakedOcclusionBicubic(lightmapUV.xy, worldPos); float zDist = dot(_WorldSpaceCameraPos - worldPos, UNITY_MATRIX_V[2].xyz); float fadeDist = UnityComputeShadowFadeDistance(worldPos, zDist); atten = UnityMixRealtimeAndBakedShadows(atten, bakedAtten, UnityComputeShadowFade(fadeDist)); #endif } #define UnitySampleBakedOcclusion UnitySampleBakedOcclusionBicubic #include "AutoLight.cginc" //------------------------------------------------------------------------------------- // Common fragment setup #ifdef _PARALLAXMAP #define IN_VIEWDIR4PARALLAX(i) NormalizePerPixelNormal(half3(i.tangentToWorldAndPackedData[0].w,i.tangentToWorldAndPackedData[1].w,i.tangentToWorldAndPackedData[2].w)) #define IN_VIEWDIR4PARALLAX_FWDADD(i) NormalizePerPixelNormal(i.viewDirForParallax.xyz) #else #define IN_VIEWDIR4PARALLAX(i) half3(0,0,0) #define IN_VIEWDIR4PARALLAX_FWDADD(i) half3(0,0,0) #endif #if UNITY_REQUIRE_FRAG_WORLDPOS #if UNITY_PACK_WORLDPOS_WITH_TANGENT #define IN_WORLDPOS(i) half3(i.tangentToWorldAndPackedData[0].w,i.tangentToWorldAndPackedData[1].w,i.tangentToWorldAndPackedData[2].w) #else #define IN_WORLDPOS(i) i.posWorld #endif #define IN_WORLDPOS_FWDADD(i) i.posWorld #else #define IN_WORLDPOS(i) half3(0,0,0) #define IN_WORLDPOS_FWDADD(i) half3(0,0,0) #endif #define IN_LIGHTDIR_FWDADD(i) half3(i.tangentToWorldAndLightDir[0].w, i.tangentToWorldAndLightDir[1].w, i.tangentToWorldAndLightDir[2].w) #define MATERIAL_SETUP(x) MaterialInputs x = \ MaterialSetup(i.tex, i.eyeVec.xyz, IN_VIEWDIR4PARALLAX(i), i.tangentToWorldAndPackedData, IN_WORLDPOS(i)); #define MATERIAL_SETUP_FWDADD(x) MaterialInputs x = \ MaterialSetup(i.tex, i.eyeVec.xyz, IN_VIEWDIR4PARALLAX_FWDADD(i), i.tangentToWorldAndLightDir, IN_WORLDPOS_FWDADD(i)); #if !defined(SKIP_UNITY_STANDARD_INPUT_DEFINES) #if defined(SHADING_MODEL_CLOTH) #define SETUP_BRDF_INPUT ClothMaterialSetup inline MaterialInputs ClothMaterialSetup (float4 i_tex) { half4 baseColor = half4(Albedo(i_tex), Alpha(i_tex)); half4 specGloss = SheenColorGlossCloth(i_tex.xy); half3 specColor = specGloss.rgb; half smoothness = specGloss.a; MaterialInputs material = (MaterialInputs)0; initMaterial(material); material.baseColor = baseColor; #if defined(MATERIAL_HAS_SHEEN_COLOR) material.sheenColor = specColor; #endif #if defined(SHADING_MODEL_SPECULAR_GLOSSINESS) material.glossiness = smoothness; #else material.roughness = computeRoughnessFromGlossiness(smoothness); #endif return material; } #else // Filament's preferred model, but not Unity's default #if defined(SHADING_MODEL_METALLIC_ROUGHNESS) #define SETUP_BRDF_INPUT RoughnessMaterialSetup inline MaterialInputs RoughnessMaterialSetup (float4 i_tex) { half4 baseColor = half4(Albedo(i_tex), Alpha(i_tex)); half2 metallicGloss = MetallicRough(i_tex.xy); half metallic = metallicGloss.x; half smoothness = metallicGloss.y; // this is 1 minus the square root of real roughness m. MaterialInputs material = (MaterialInputs)0; initMaterial(material); material.baseColor = baseColor; material.metallic = metallic; material.roughness = computeRoughnessFromGlossiness(smoothness); return material; } #else #if defined(SHADING_MODEL_SPECULAR_GLOSSINESS) #define SETUP_BRDF_INPUT SpecularMaterialSetup inline MaterialInputs SpecularMaterialSetup (float4 i_tex) { half4 baseColor = half4(Albedo(i_tex), Alpha(i_tex)); half4 specGloss = SpecularGloss(i_tex.xy); half3 specColor = specGloss.rgb; half smoothness = specGloss.a; MaterialInputs material = (MaterialInputs)0; initMaterial(material); material.baseColor = baseColor; material.specularColor = specColor; material.glossiness = smoothness; return material; } #endif #if (!defined(SHADING_MODEL_SPECULAR_GLOSSINESS)) #define SETUP_BRDF_INPUT MetallicMaterialSetup inline MaterialInputs MetallicMaterialSetup (float4 i_tex) { half4 baseColor = half4(Albedo(i_tex), Alpha(i_tex)); half2 metallicGloss = MetallicGloss(i_tex.xy); half metallic = metallicGloss.x; half smoothness = metallicGloss.y; // this is 1 minus the square root of real roughness m. MaterialInputs material = (MaterialInputs)0; initMaterial(material); material.baseColor = baseColor; material.metallic = metallic; material.roughness = computeRoughnessFromGlossiness(smoothness); return material; } #endif #endif #endif #endif #ifndef SETUP_BRDF_INPUT #define SETUP_BRDF_INPUT NoneMaterialSetup #endif inline MaterialInputs NoneMaterialSetup (float4 i_tex) { MaterialInputs material = (MaterialInputs)0; initMaterial(material); return material; } // parallax transformed texcoord is used to sample occlusion inline MaterialInputs MaterialSetup (inout float4 i_tex, float3 i_eyeVec, half3 i_viewDirForParallax, float4 tangentToWorld[3], float3 i_posWorld) { #if defined(SKIP_UNITY_STANDARD_INPUT_DEFINES) MaterialInputs material = SETUP_BRDF_INPUT (i_tex); return material; #else float3 viewDirWS = -normalize(i_posWorld - _WorldSpaceCameraPos); float3 normalWS = normalize(tangentToWorld[2]); // normalize to avoid weird values float parallaxLod = dot(normalWS, viewDirWS); #if !defined(PARALLAX_CUSTOM_INPUT) i_tex = Parallax(i_tex, i_viewDirForParallax, parallaxLod); #endif MaterialInputs material = SETUP_BRDF_INPUT (i_tex); // Added tangent output #if _NORMALMAP material.normal = NormalInTangentSpace(i_tex); #endif #if _EMISSION material.emissive.rgb = Emission (i_tex); material.emissive.a = 1.0; #endif material.ambientOcclusion = Occlusion(i_tex); return material; #endif } //------------------------------------------------------------------------------------- inline half4 VertexGIForward(VertexInput v, float3 posWorld, half3 normalWorld) { 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, posWorld, normalWorld); #endif ambientOrLightmapUV.rgb = ShadeSHPerVertex (normalWorld, ambientOrLightmapUV.rgb); #endif #ifdef DYNAMICLIGHTMAP_ON ambientOrLightmapUV.zw = v.uv2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw; #endif #if defined(USING_BAKERY_VERTEXLMMASK) if (getIsBakeryVertexMode()) { ambientOrLightmapUV = unpack4NFloats(v.uv1.x); } #endif return ambientOrLightmapUV; } // ------------------------------------------------------------------ // Base forward pass (directional light, emission, lightmaps, ...) struct VertexOutputForwardBase { UNITY_POSITION(pos); float4 tex : TEXCOORD0; float4 eyeVec : TEXCOORD1; // eyeVec.xyz | fogCoord float4 tangentToWorldAndPackedData[3] : TEXCOORD2; // [3x3:tangentToWorld | 1x3:viewDirForParallax or worldPos] half4 ambientOrLightmapUV : TEXCOORD5_centroid; // SH or Lightmap UV UNITY_LIGHTING_COORDS(6,7) // next ones would not fit into SM2.0 limits, but they are always for SM3.0+ #if UNITY_REQUIRE_FRAG_WORLDPOS && !UNITY_PACK_WORLDPOS_WITH_TANGENT float3 posWorld : TEXCOORD8; #endif #if (defined(_NORMALMAP) && defined(NORMALMAP_SHADOW)) float3 lightDirTS : TEXCOORD9; #endif #if defined(_BAKERY_VERTEXLM) float4 color : COLOR_centroid; #if defined(USING_BAKERY_VERTEXLMDIR) float3 lightDirection : TEXCOORD10_centroid; #elif defined(_BAKERY_SH) float3 shL1x : TEXCOORD10_centroid; float3 shL1y : TEXCOORD11_centroid; float3 shL1z : TEXCOORD12_centroid; #endif #else #if defined(HAS_ATTRIBUTE_COLOR) float4 color : COLOR_centroid; #endif #endif UNITY_VERTEX_INPUT_INSTANCE_ID UNITY_VERTEX_OUTPUT_STEREO }; VertexOutputForwardBase vertForwardBase (VertexInput v) { UNITY_SETUP_INSTANCE_ID(v); VertexOutputForwardBase o; UNITY_INITIALIZE_OUTPUT(VertexOutputForwardBase, o); UNITY_TRANSFER_INSTANCE_ID(v, o); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); v.normal = normalize(v.normal.xyz); #ifdef _TANGENT_TO_WORLD v.tangent.xyz = normalize(v.tangent.xyz); #endif float4 posWorld = mul(unity_ObjectToWorld, v.vertex); #if UNITY_REQUIRE_FRAG_WORLDPOS #if UNITY_PACK_WORLDPOS_WITH_TANGENT o.tangentToWorldAndPackedData[0].w = posWorld.x; o.tangentToWorldAndPackedData[1].w = posWorld.y; o.tangentToWorldAndPackedData[2].w = posWorld.z; #else o.posWorld = posWorld.xyz; #endif #endif o.pos = UnityObjectToClipPos(v.vertex); o.tex = TexCoords(v); o.eyeVec.xyz = NormalizePerVertexNormal(posWorld.xyz - _WorldSpaceCameraPos); float3 normalWorld = UnityObjectToWorldNormal(v.normal); #ifdef _TANGENT_TO_WORLD float4 tangentWorld = float4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w); float3x3 tangentToWorld = CreateTangentToWorldPerVertex(normalWorld, tangentWorld.xyz, tangentWorld.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 = normalWorld; #endif //We need this for shadow receving UNITY_TRANSFER_LIGHTING(o, v.uv1); o.ambientOrLightmapUV = VertexGIForward(v, posWorld, normalWorld); #ifdef _PARALLAXMAP TANGENT_SPACE_ROTATION; 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 _TANGENT_TO_WORLD #if defined(NORMALMAP_SHADOW) float3 lightDirWS = normalize(_WorldSpaceLightPos0.xyz - posWorld.xyz * _WorldSpaceLightPos0.w); o.lightDirTS = TransformToTangentSpace(tangentToWorld[0],tangentToWorld[1],tangentToWorld[2],lightDirWS); #endif #endif #if defined(HAS_ATTRIBUTE_COLOR) o.color = v.color; #endif #if defined(USING_BAKERY_VERTEXLM) // Unpack from RGBM o.color = v.color; o.color.rgb *= o.color.a * 8.0f; o.color.rgb *= o.color.rgb; #if defined(USING_BAKERY_VERTEXLMDIR) o.lightDirection = unpack3NFloats(v.uv1.y) * 2 - 1; #elif defined(USING_BAKERY_VERTEXLMSH) o.shL1x = unpack3NFloats(v.uv1.y) * 2 - 1; o.shL1y = unpack3NFloats(v.uv3.x) * 2 - 1; o.shL1z = unpack3NFloats(v.uv3.y) * 2 - 1; #endif #endif UNITY_TRANSFER_FOG_COMBINED_WITH_EYE_VEC(o,o.pos); return o; } void computeShadingParamsForwardBase(inout ShadingParams shading, VertexOutputForwardBase i, bool gl_FrontFacing = true) { float3x3 tangentToWorld; tangentToWorld[0] = i.tangentToWorldAndPackedData[0].xyz; tangentToWorld[1] = i.tangentToWorldAndPackedData[1].xyz; tangentToWorld[2] = i.tangentToWorldAndPackedData[2].xyz; if (getIsDoubleSided()) { tangentToWorld[0] *= gl_FrontFacing ? 1 : -1; tangentToWorld[1] *= gl_FrontFacing ? 1 : -1; tangentToWorld[2] *= gl_FrontFacing ? 1 : -1; } shading.geometricNormal = normalize(tangentToWorld[2].xyz); shading.tangentToWorld = transpose(tangentToWorld); float2 viewportUV = i.pos.xy / _ScreenParams.xy; #if defined(UNITY_SINGLE_PASS_STEREO) viewportUV.x = viewportUV.x * 2.0 - float(unity_StereoEyeIndex); #endif shading.normalizedViewportCoord = viewportUV; shading.normal = shading.geometricNormal; shading.position = IN_WORLDPOS(i); shading.view = -NormalizePerPixelNormal(i.eyeVec); UNITY_LIGHT_ATTENUATION(atten, i, shading.position) #if (defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)) GetBakedAttenuation(atten, i.ambientOrLightmapUV.xy, shading.position); #endif shading.attenuation = atten; #if (defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)) shading.ambient = 0; shading.lightmapUV = i.ambientOrLightmapUV; #else shading.ambient = i.ambientOrLightmapUV.rgb; shading.lightmapUV = 0; #endif #if defined(USING_BAKERY_VERTEXLMMASK) if (getIsBakeryVertexMode()) { shading.attenuation = saturate(dot(i.ambientOrLightmapUV, unity_OcclusionMaskSelector)); } #endif #if defined(USING_BAKERY_VERTEXLM) shading.ambient = i.color; #endif #if defined(USING_BAKERY_VERTEXLMSH) shading.ambientSH[0] = i.shL1x; shading.ambientSH[1] = i.shL1y; shading.ambientSH[2] = i.shL1z; #elif defined(USING_BAKERY_VERTEXLMDIR) shading.ambientDir = i.lightDirection; #endif } half4 fragForwardBaseInternal (VertexOutputForwardBase i, bool gl_FrontFacing) { UNITY_APPLY_DITHER_CROSSFADE(i.pos.xy); float4 i_texBase = i.tex; MATERIAL_SETUP(material) UNITY_SETUP_INSTANCE_ID(i); UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); ShadingParams shading = (ShadingParams)0; // Initialize shading with expected parameters computeShadingParamsForwardBase(shading, i, gl_FrontFacing); prepareMaterial(shading, material); #if ((defined(_NORMALMAP) || defined(_PARALLAXMAP)) && defined(NORMALMAP_SHADOW)) float noise = noiseR2(i.pos.xy); #if defined(_PARALLAXMAP) PerPixelHeightDisplacementParam ppd = InitPerPixelHeightDisplacementParam(i.tex.xy); float hShadow = GetParallaxSelfShadow(i.lightDirTS, i.tex.xy, ppd, noise); shading.attenuation = min(shading.attenuation, hShadow); #else float nmShade = NormalTangentShadow (i.tex, i.lightDirTS, noise); shading.attenuation = min(shading.attenuation, max(1-nmShade, 0)); #endif #endif float4 c = evaluateMaterial (shading, material); UNITY_EXTRACT_FOG_FROM_EYE_VEC(i); UNITY_APPLY_FOG(_unity_fogCoord, c.rgb); return c; } half4 fragForwardBase (VertexOutputForwardBase i, bool facing : SV_IsFrontFace) : SV_Target // backward compatibility (this used to be the fragment entry function) { return fragForwardBaseInternal(i, facing); } // ------------------------------------------------------------------ // Additive forward pass (one light per pass) struct VertexOutputForwardAdd { UNITY_POSITION(pos); float4 tex : TEXCOORD0; float4 eyeVec : TEXCOORD1; // eyeVec.xyz | fogCoord float4 tangentToWorldAndLightDir[3] : TEXCOORD2; // [3x3:tangentToWorld | 1x3:lightDir] float3 posWorld : TEXCOORD5; UNITY_LIGHTING_COORDS(6, 7) // next ones would not fit into SM2.0 limits, but they are always for SM3.0+ #if defined(_PARALLAXMAP) half3 viewDirForParallax : TEXCOORD8; #endif #if (defined(_NORMALMAP) && defined(NORMALMAP_SHADOW)) float3 lightDirTS : TEXCOORD9; #endif // If Bakery LM mode is active, vertex colour is base lightmap. #if defined(USING_BAKERY_VERTEXLMMASK) fixed4 shadowMask : COLOR_centroid; #else #if defined(HAS_ATTRIBUTE_COLOR) float4 color : COLOR_centroid; #endif #endif UNITY_VERTEX_OUTPUT_STEREO }; VertexOutputForwardAdd vertForwardAdd (VertexInput v) { UNITY_SETUP_INSTANCE_ID(v); VertexOutputForwardAdd o; UNITY_INITIALIZE_OUTPUT(VertexOutputForwardAdd, o); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); float4 posWorld = mul(unity_ObjectToWorld, v.vertex); o.pos = UnityObjectToClipPos(v.vertex); o.tex = TexCoords(v); o.eyeVec.xyz = NormalizePerVertexNormal(posWorld.xyz - _WorldSpaceCameraPos); o.posWorld = posWorld.xyz; float3 normalWorld = UnityObjectToWorldNormal(v.normal); #ifdef _TANGENT_TO_WORLD float4 tangentWorld = float4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w); float3x3 tangentToWorld = CreateTangentToWorldPerVertex(normalWorld, tangentWorld.xyz, tangentWorld.w); o.tangentToWorldAndLightDir[0].xyz = tangentToWorld[0]; o.tangentToWorldAndLightDir[1].xyz = tangentToWorld[1]; o.tangentToWorldAndLightDir[2].xyz = tangentToWorld[2]; #else o.tangentToWorldAndLightDir[0].xyz = 0; o.tangentToWorldAndLightDir[1].xyz = 0; o.tangentToWorldAndLightDir[2].xyz = normalWorld; #endif //We need this for shadow receiving and lighting UNITY_TRANSFER_LIGHTING(o, v.uv1); float3 lightDir = _WorldSpaceLightPos0.xyz - posWorld.xyz * _WorldSpaceLightPos0.w; #ifndef USING_DIRECTIONAL_LIGHT lightDir = NormalizePerVertexNormal(lightDir); #endif o.tangentToWorldAndLightDir[0].w = lightDir.x; o.tangentToWorldAndLightDir[1].w = lightDir.y; o.tangentToWorldAndLightDir[2].w = lightDir.z; #ifdef _PARALLAXMAP TANGENT_SPACE_ROTATION; o.viewDirForParallax = mul (rotation, ObjSpaceViewDir(v.vertex)); #endif #ifdef _TANGENT_TO_WORLD #if (defined(_NORMALMAP) && defined(NORMALMAP_SHADOW)) float3 lightDirWS = normalize(_WorldSpaceLightPos0.xyz - posWorld.xyz * _WorldSpaceLightPos0.w); o.lightDirTS = TransformToTangentSpace(tangentToWorld[0],tangentToWorld[1],tangentToWorld[2],lightDirWS); #endif #endif #if defined(USING_BAKERY_VERTEXLMMASK) o.shadowMask = unpack4NFloats(v.uv1.x); #else #if defined(HAS_ATTRIBUTE_COLOR) o.color = v.color; #endif #endif UNITY_TRANSFER_FOG_COMBINED_WITH_EYE_VEC(o, o.pos); return o; } void computeShadingParamsForwardAdd(inout ShadingParams shading, VertexOutputForwardAdd i, bool gl_FrontFacing = true) { float3x3 tangentToWorld; tangentToWorld[0] = i.tangentToWorldAndLightDir[0].xyz; tangentToWorld[1] = i.tangentToWorldAndLightDir[1].xyz; tangentToWorld[2] = i.tangentToWorldAndLightDir[2].xyz; if (getIsDoubleSided()) { tangentToWorld[0] *= gl_FrontFacing ? 1 : -1; tangentToWorld[1] *= gl_FrontFacing ? 1 : -1; tangentToWorld[2] *= gl_FrontFacing ? 1 : -1; } shading.geometricNormal = normalize(tangentToWorld[2].xyz); shading.tangentToWorld = transpose(tangentToWorld); float2 viewportUV = i.pos.xy / _ScreenParams.xy; #if defined(UNITY_SINGLE_PASS_STEREO) viewportUV.x = viewportUV.x * 2.0 - float(unity_StereoEyeIndex); #endif shading.normalizedViewportCoord = viewportUV; shading.normal = normalize(shading.geometricNormal); shading.position = IN_WORLDPOS_FWDADD(i); shading.view = -NormalizePerPixelNormal(i.eyeVec); UNITY_LIGHT_ATTENUATION(atten, i, shading.position) shading.attenuation = atten; #if defined(USING_BAKERY_VERTEXLMMASK) if (getIsBakeryVertexMode()) { shading.attenuation *= saturate(dot(i.shadowMask, unity_OcclusionMaskSelector)); } #endif } half4 fragForwardAddInternal (VertexOutputForwardAdd i, bool gl_FrontFacing) { UNITY_APPLY_DITHER_CROSSFADE(i.pos.xy); MATERIAL_SETUP_FWDADD(material) UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); ShadingParams shading = (ShadingParams)0; // Initialize shading with expected parameters computeShadingParamsForwardAdd(shading, i, gl_FrontFacing); prepareMaterial(shading, material); #if ((defined(_NORMALMAP) || defined(_PARALLAXMAP)) && defined(NORMALMAP_SHADOW)) float noise = noiseR2(i.pos.xy); #if defined(_PARALLAXMAP) PerPixelHeightDisplacementParam ppd = InitPerPixelHeightDisplacementParam(i.tex.xy); float hShadow = GetParallaxSelfShadow(i.lightDirTS, i.tex.xy, ppd, noise); shading.attenuation = min(shading.attenuation, hShadow); #else float nmShade = NormalTangentShadow (i.tex, i.lightDirTS, noise); shading.attenuation = min(shading.attenuation, max(1-nmShade, 0)); #endif #endif float4 c = evaluateMaterial (shading, material); UNITY_EXTRACT_FOG_FROM_EYE_VEC(i); UNITY_APPLY_FOG_COLOR(_unity_fogCoord, c.rgb, half4(0,0,0,0)); // fog towards black in additive pass return c; } half4 fragForwardAdd (VertexOutputForwardAdd i, bool facing : SV_IsFrontFace) : SV_Target // backward compatibility (this used to be the fragment entry function) { return fragForwardAddInternal(i, facing); } #endif // UNITY_STANDARD_CORE_INCLUDED