625 lines
27 KiB
HLSL
625 lines
27 KiB
HLSL
// SPDX-License-Identifier: (Not available for this version, you are only allowed to use this software if you have express permission from the copyright holder and agreed to the latest NiloToonURP EULA)
|
|
// Copyright (c) 2021 Kuroneko ShaderLab Limited
|
|
|
|
// For more information, visit -> https://github.com/ColinLeung-NiloCat/UnityURPToonLitShaderExample
|
|
|
|
// This shader is a direct copy of Unity6.1 URP17.0.3's LitForwardPass.hlsl, but with some edit.
|
|
// If you want to see what is the difference, all edited lines will have a [NiloToon] tag, you can search [NiloToon] in this file,
|
|
// or compare Unity6.1 URP17.0.3's LitForwardPass.hlsl with this file using tools like SourceGear DiffMerge.
|
|
|
|
// #pragma once is a safeguard best practice in almost every .hlsl,
|
|
// doing this can make sure your .hlsl's user can include this .hlsl anywhere anytime without producing any multi include conflict
|
|
#pragma once
|
|
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
|
|
#if UNITY_VERSION >= 202220
|
|
#if defined(LOD_FADE_CROSSFADE)
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/LODCrossFade.hlsl"
|
|
#endif
|
|
#endif
|
|
|
|
// [NiloToon] add:
|
|
//==========================================================================================================
|
|
// + Rider code highlight support for all shader_feature and multi_compile
|
|
// (__RESHARPER__ is only defined while in IDE. Used to help editing this file with proper highlighting.)
|
|
#ifdef __RESHARPER__
|
|
#define _NILOTOON_GLOBAL_ENABLE_SCREENSPACE_OUTLINE 1
|
|
#define _NILOTOON_GLOBAL_ENABLE_SCREENSPACE_OUTLINE_V2 1
|
|
#define _SPLATMAP 1
|
|
#endif
|
|
|
|
#include "../../ShaderLibrary/NiloUtilityHLSL/NiloAllUtilIncludes.hlsl"
|
|
|
|
#if defined(_SPLATMAP)
|
|
#if !defined(_NORMALMAP)
|
|
#define _NORMALMAP
|
|
#endif
|
|
#endif
|
|
//==========================================================================================================
|
|
|
|
#if defined(_PARALLAXMAP)
|
|
#define REQUIRES_TANGENT_SPACE_VIEW_DIR_INTERPOLATOR
|
|
#endif
|
|
|
|
#if (defined(_NORMALMAP) || (defined(_PARALLAXMAP) && !defined(REQUIRES_TANGENT_SPACE_VIEW_DIR_INTERPOLATOR))) || defined(_DETAIL)
|
|
#define REQUIRES_WORLD_SPACE_TANGENT_INTERPOLATOR
|
|
#endif
|
|
|
|
// keep this file in sync with LitGBufferPass.hlsl
|
|
|
|
struct Attributes
|
|
{
|
|
float4 positionOS : POSITION;
|
|
float3 normalOS : NORMAL;
|
|
float4 tangentOS : TANGENT;
|
|
float2 texcoord : TEXCOORD0;
|
|
float2 staticLightmapUV : TEXCOORD1;
|
|
float2 dynamicLightmapUV : TEXCOORD2;
|
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
|
};
|
|
|
|
struct Varyings
|
|
{
|
|
float2 uv : TEXCOORD0;
|
|
|
|
#if defined(REQUIRES_WORLD_SPACE_POS_INTERPOLATOR)
|
|
float3 positionWS : TEXCOORD1;
|
|
#endif
|
|
|
|
float3 normalWS : TEXCOORD2;
|
|
#if defined(REQUIRES_WORLD_SPACE_TANGENT_INTERPOLATOR)
|
|
half4 tangentWS : TEXCOORD3; // xyz: tangent, w: sign
|
|
#endif
|
|
|
|
#if UNITY_VERSION < 202220
|
|
float3 viewDirWS : TEXCOORD4;
|
|
#endif
|
|
|
|
#ifdef _ADDITIONAL_LIGHTS_VERTEX
|
|
half4 fogFactorAndVertexLight : TEXCOORD5; // x: fogFactor, yzw: vertex light
|
|
#else
|
|
half fogFactor : TEXCOORD5;
|
|
#endif
|
|
|
|
#if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
|
|
float4 shadowCoord : TEXCOORD6;
|
|
#endif
|
|
|
|
#if defined(REQUIRES_TANGENT_SPACE_VIEW_DIR_INTERPOLATOR)
|
|
half3 viewDirTS : TEXCOORD7;
|
|
#endif
|
|
|
|
DECLARE_LIGHTMAP_OR_SH(staticLightmapUV, vertexSH, 8);
|
|
#ifdef DYNAMICLIGHTMAP_ON
|
|
float2 dynamicLightmapUV : TEXCOORD9; // Dynamic lightmap UVs
|
|
#endif
|
|
|
|
#ifdef USE_APV_PROBE_OCCLUSION
|
|
float4 probeOcclusion : TEXCOORD10;
|
|
#endif
|
|
|
|
// [NiloToon] add:
|
|
//=======================================================
|
|
float4 screenPos : TEXCOORD11;
|
|
//=======================================================
|
|
|
|
float4 positionCS : SV_POSITION;
|
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
|
UNITY_VERTEX_OUTPUT_STEREO
|
|
};
|
|
|
|
void InitializeInputData(Varyings input, half3 normalTS, out InputData inputData)
|
|
{
|
|
inputData = (InputData)0;
|
|
|
|
#if defined(REQUIRES_WORLD_SPACE_POS_INTERPOLATOR)
|
|
inputData.positionWS = input.positionWS;
|
|
#endif
|
|
|
|
#if UNITY_VERSION >= 60000000
|
|
#if defined(DEBUG_DISPLAY)
|
|
inputData.positionCS = input.positionCS;
|
|
#endif
|
|
#endif
|
|
|
|
half3 viewDirWS = GetWorldSpaceNormalizeViewDir(input.positionWS);
|
|
#if defined(_NORMALMAP) || defined(_DETAIL)
|
|
float sgn = input.tangentWS.w; // should be either +1 or -1
|
|
float3 bitangent = sgn * cross(input.normalWS.xyz, input.tangentWS.xyz);
|
|
half3x3 tangentToWorld = half3x3(input.tangentWS.xyz, bitangent.xyz, input.normalWS.xyz);
|
|
|
|
#if defined(_NORMALMAP)
|
|
inputData.tangentToWorld = tangentToWorld;
|
|
#endif
|
|
inputData.normalWS = TransformTangentToWorld(normalTS, tangentToWorld);
|
|
#else
|
|
inputData.normalWS = input.normalWS;
|
|
#endif
|
|
|
|
inputData.normalWS = NormalizeNormalPerPixel(inputData.normalWS);
|
|
inputData.viewDirectionWS = viewDirWS;
|
|
|
|
#if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
|
|
inputData.shadowCoord = input.shadowCoord;
|
|
#elif defined(MAIN_LIGHT_CALCULATE_SHADOWS)
|
|
inputData.shadowCoord = TransformWorldToShadowCoord(inputData.positionWS);
|
|
#else
|
|
inputData.shadowCoord = float4(0, 0, 0, 0);
|
|
#endif
|
|
#ifdef _ADDITIONAL_LIGHTS_VERTEX
|
|
inputData.fogCoord = InitializeInputDataFog(float4(input.positionWS, 1.0), input.fogFactorAndVertexLight.x);
|
|
inputData.vertexLighting = input.fogFactorAndVertexLight.yzw;
|
|
#else
|
|
inputData.fogCoord = InitializeInputDataFog(float4(input.positionWS, 1.0), input.fogFactor);
|
|
#endif
|
|
|
|
#if UNITY_VERSION < 60000000
|
|
#if defined(DYNAMICLIGHTMAP_ON)
|
|
inputData.bakedGI = SAMPLE_GI(input.staticLightmapUV, input.dynamicLightmapUV, input.vertexSH, inputData.normalWS);
|
|
#elif !defined(LIGHTMAP_ON) && (defined(PROBE_VOLUMES_L1) || defined(PROBE_VOLUMES_L2))
|
|
inputData.bakedGI = SAMPLE_GI(input.vertexSH,
|
|
GetAbsolutePositionWS(inputData.positionWS),
|
|
inputData.normalWS,
|
|
inputData.viewDirectionWS,
|
|
input.positionCS.xy);
|
|
#else
|
|
inputData.bakedGI = SAMPLE_GI(input.staticLightmapUV, input.vertexSH, inputData.normalWS);
|
|
#endif
|
|
#endif
|
|
|
|
inputData.normalizedScreenSpaceUV = GetNormalizedScreenSpaceUV(input.positionCS);
|
|
|
|
#if UNITY_VERSION < 60000000
|
|
inputData.shadowMask = SAMPLE_SHADOWMASK(input.staticLightmapUV);
|
|
#endif
|
|
|
|
#if defined(DEBUG_DISPLAY)
|
|
#if defined(DYNAMICLIGHTMAP_ON)
|
|
inputData.dynamicLightmapUV = input.dynamicLightmapUV;
|
|
#endif
|
|
#if defined(LIGHTMAP_ON)
|
|
inputData.staticLightmapUV = input.staticLightmapUV;
|
|
#else
|
|
inputData.vertexSH = input.vertexSH;
|
|
#endif
|
|
#if UNITY_VERSION >= 60000000
|
|
#if defined(USE_APV_PROBE_OCCLUSION)
|
|
inputData.probeOcclusion = input.probeOcclusion;
|
|
#endif
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
#if UNITY_VERSION >= 60000000
|
|
void InitializeBakedGIData(Varyings input, inout InputData inputData)
|
|
{
|
|
#if defined(DYNAMICLIGHTMAP_ON)
|
|
inputData.bakedGI = SAMPLE_GI(input.staticLightmapUV, input.dynamicLightmapUV, input.vertexSH, inputData.normalWS);
|
|
inputData.shadowMask = SAMPLE_SHADOWMASK(input.staticLightmapUV);
|
|
#elif !defined(LIGHTMAP_ON) && (defined(PROBE_VOLUMES_L1) || defined(PROBE_VOLUMES_L2))
|
|
inputData.bakedGI = SAMPLE_GI(input.vertexSH,
|
|
GetAbsolutePositionWS(inputData.positionWS),
|
|
inputData.normalWS,
|
|
inputData.viewDirectionWS,
|
|
input.positionCS.xy,
|
|
input.probeOcclusion,
|
|
inputData.shadowMask);
|
|
#else
|
|
inputData.bakedGI = SAMPLE_GI(input.staticLightmapUV, input.vertexSH, inputData.normalWS);
|
|
inputData.shadowMask = SAMPLE_SHADOWMASK(input.staticLightmapUV);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
// [NiloToon] add:
|
|
//==========================================================================================================================================================
|
|
// debug on off
|
|
float _NiloToonGlobalEnviMinimumShader;
|
|
|
|
// shadow boader color
|
|
float4 _NiloToonGlobalEnviShadowBorderTintColor;
|
|
|
|
// global GI edit
|
|
float3 _NiloToonGlobalEnviGITintColor;
|
|
float3 _NiloToonGlobalEnviGIAddColor;
|
|
|
|
// global GI override
|
|
float4 _NiloToonGlobalEnviGIOverride;
|
|
|
|
// global albedo override
|
|
float4 _NiloToonGlobalEnviAlbedoOverrideColor;
|
|
|
|
// global surface color result override
|
|
float4 _NiloToonGlobalEnviSurfaceColorResultOverrideColor;
|
|
|
|
// global screen space outline settings
|
|
float _GlobalScreenSpaceOutlineIntensityForEnvi;
|
|
float _GlobalScreenSpaceOutlineWidthMultiplierForEnvi;
|
|
float _GlobalScreenSpaceOutlineNormalsSensitivityOffsetForEnvi;
|
|
float _GlobalScreenSpaceOutlineDepthSensitivityOffsetForEnvi;
|
|
float _GlobalScreenSpaceOutlineDepthSensitivityDistanceFadeoutStrengthForEnvi;
|
|
half3 _GlobalScreenSpaceOutlineTintColorForEnvi;
|
|
|
|
// global screen space outline V2 settings
|
|
float _GlobalScreenSpaceOutlineV2IntensityForEnvi;
|
|
float _GlobalScreenSpaceOutlineV2WidthMultiplierForEnvi;
|
|
float _GlobalScreenSpaceOutlineV2EnableGeometryEdgeForEnvi;
|
|
float _GlobalScreenSpaceOutlineV2GeometryEdgeThresholdForEnvi;
|
|
float _GlobalScreenSpaceOutlineV2EnableNormalAngleEdgeForEnvi;
|
|
float _GlobalScreenSpaceOutlineV2NormalAngleCosThetaThresholdForEnvi;
|
|
|
|
// global camera uniforms
|
|
float _CurrentCameraFOV;
|
|
|
|
// include files, include as late as possible to get all defines
|
|
#include "NiloToonEnvironment_ExtendFunctionsForUserCustomLogic.hlsl"
|
|
//==========================================================================================================================================================
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Vertex and Fragment functions //
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Used in Standard (Physically Based) shader
|
|
Varyings LitPassVertex(Attributes input)
|
|
{
|
|
Varyings output = (Varyings)0;
|
|
|
|
UNITY_SETUP_INSTANCE_ID(input);
|
|
UNITY_TRANSFER_INSTANCE_ID(input, output);
|
|
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
|
|
|
|
// [NiloToon] add:
|
|
//==========================================================================================================================================================
|
|
ApplyCustomUserLogicToVertexAttributeAtVertexShaderStart(input);
|
|
//==========================================================================================================================================================
|
|
|
|
VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);
|
|
|
|
// normalWS and tangentWS already normalize.
|
|
// this is required to avoid skewing the direction during interpolation
|
|
// also required for per-vertex lighting and SH evaluation
|
|
VertexNormalInputs normalInput = GetVertexNormalInputs(input.normalOS, input.tangentOS);
|
|
|
|
half3 vertexLight = VertexLighting(vertexInput.positionWS, normalInput.normalWS);
|
|
|
|
half fogFactor = 0;
|
|
#if !defined(_FOG_FRAGMENT)
|
|
fogFactor = ComputeFogFactor(vertexInput.positionCS.z);
|
|
#endif
|
|
|
|
output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap);
|
|
|
|
// already normalized from normal transform to WS.
|
|
output.normalWS = normalInput.normalWS;
|
|
#if defined(REQUIRES_WORLD_SPACE_TANGENT_INTERPOLATOR) || defined(REQUIRES_TANGENT_SPACE_VIEW_DIR_INTERPOLATOR)
|
|
real sign = input.tangentOS.w * GetOddNegativeScale();
|
|
half4 tangentWS = half4(normalInput.tangentWS.xyz, sign);
|
|
#endif
|
|
#if defined(REQUIRES_WORLD_SPACE_TANGENT_INTERPOLATOR)
|
|
output.tangentWS = tangentWS;
|
|
#endif
|
|
|
|
#if defined(REQUIRES_TANGENT_SPACE_VIEW_DIR_INTERPOLATOR)
|
|
half3 viewDirWS = GetWorldSpaceNormalizeViewDir(vertexInput.positionWS);
|
|
half3 viewDirTS = GetViewDirectionTangentSpace(tangentWS, output.normalWS, viewDirWS);
|
|
output.viewDirTS = viewDirTS;
|
|
#endif
|
|
|
|
OUTPUT_LIGHTMAP_UV(input.staticLightmapUV, unity_LightmapST, output.staticLightmapUV);
|
|
#ifdef DYNAMICLIGHTMAP_ON
|
|
output.dynamicLightmapUV = input.dynamicLightmapUV.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;
|
|
#endif
|
|
|
|
#if UNITY_VERSION >= 60000011
|
|
OUTPUT_SH4(vertexInput.positionWS, output.normalWS.xyz, GetWorldSpaceNormalizeViewDir(vertexInput.positionWS), output.vertexSH, output.probeOcclusion);
|
|
#elif UNITY_VERSION >= 202310
|
|
OUTPUT_SH4(vertexInput.positionWS, output.normalWS.xyz, GetWorldSpaceNormalizeViewDir(vertexInput.positionWS), output.vertexSH);
|
|
#else
|
|
OUTPUT_SH(output.normalWS.xyz, output.vertexSH);
|
|
#endif
|
|
|
|
#ifdef _ADDITIONAL_LIGHTS_VERTEX
|
|
output.fogFactorAndVertexLight = half4(fogFactor, vertexLight);
|
|
#else
|
|
output.fogFactor = fogFactor;
|
|
#endif
|
|
|
|
#if defined(REQUIRES_WORLD_SPACE_POS_INTERPOLATOR)
|
|
output.positionWS = vertexInput.positionWS;
|
|
#endif
|
|
|
|
#if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
|
|
output.shadowCoord = GetShadowCoord(vertexInput);
|
|
#endif
|
|
|
|
output.positionCS = vertexInput.positionCS;
|
|
|
|
// [NiloToon] add:
|
|
//==========================================================================================================================================================
|
|
output.screenPos = ComputeScreenPos(output.positionCS);
|
|
|
|
ApplyCustomUserLogicToVertexShaderOutputAtVertexShaderEnd(output, input);
|
|
//==========================================================================================================================================================
|
|
return output;
|
|
}
|
|
|
|
// [NiloToon] add:
|
|
//==========================================================================================================================================================
|
|
half4 CalculateFinalSplatBlendFactor(half blendSoftness, half depth1, half depth2, half depth3, half depth4, half4 splatControlMapRGBA)
|
|
{
|
|
half4 blend;
|
|
|
|
blend.r = depth1 * splatControlMapRGBA.r;
|
|
blend.g = depth2 * splatControlMapRGBA.g;
|
|
blend.b = depth3 * splatControlMapRGBA.b;
|
|
blend.a = depth4 * splatControlMapRGBA.a;
|
|
|
|
half ma = max(blend.r, max(blend.g, max(blend.b, blend.a)));
|
|
blend = max(blend - ma + max(0.001,blendSoftness), 0) * splatControlMapRGBA; // 0.001 is safer than 0.00001 when testing with different textures
|
|
return blend/(blend.r + blend.g + blend.b + blend.a);
|
|
}
|
|
void ApplySplatMapToSurfaceData(inout SurfaceData surfaceData, Varyings input)
|
|
{
|
|
// for reference see URP's TerrainLitPasses.hlsl -> SplatmapMix()
|
|
#if defined(_SPLATMAP)
|
|
|
|
// uv
|
|
float2 uvR = input.uv * _SplatAlbedoMapRTiling;
|
|
float2 uvG = input.uv * _SplatAlbedoMapGTiling;
|
|
float2 uvB = input.uv * _SplatAlbedoMapBTiling;
|
|
float2 uvA = input.uv * _SplatAlbedoMapATiling;
|
|
|
|
// sample packed data map (not yet apply mask)
|
|
half4 packedDataR = SAMPLE_TEXTURE2D(_SplatPackedDataMapR, sampler_SplatPackedDataMap_linear_repeat, uvR);
|
|
half4 packedDataG = SAMPLE_TEXTURE2D(_SplatPackedDataMapG, sampler_SplatPackedDataMap_linear_repeat, uvG);
|
|
half4 packedDataB = SAMPLE_TEXTURE2D(_SplatPackedDataMapB, sampler_SplatPackedDataMap_linear_repeat, uvB);
|
|
half4 packedDataA = SAMPLE_TEXTURE2D(_SplatPackedDataMapA, sampler_SplatPackedDataMap_linear_repeat, uvA);
|
|
|
|
// get height from each type of material
|
|
half heightR = packedDataR.b * _SplatHeightMultiplierR;
|
|
half heightG = packedDataG.b * _SplatHeightMultiplierG;
|
|
half heightB = packedDataB.b * _SplatHeightMultiplierB;
|
|
half heightA = packedDataA.b * _SplatHeightMultiplierA;
|
|
|
|
// sample and remap mask (using height from PackedDataMap)
|
|
half4 mask = SAMPLE_TEXTURE2D(_SplatMaskMap, sampler_SplatMaskMap, input.uv);
|
|
mask = CalculateFinalSplatBlendFactor(_SplatMaskBlendingSoftness,heightR,heightG,heightB,heightA,mask);
|
|
|
|
// sample albedo + smoothness
|
|
half4 albedoSmoothnessR = SAMPLE_TEXTURE2D(_SplatAlbedoMapR, sampler_SplatAlbedoMap_linear_repeat, uvR) * mask.r;
|
|
half4 albedoSmoothnessG = SAMPLE_TEXTURE2D(_SplatAlbedoMapG, sampler_SplatAlbedoMap_linear_repeat, uvG) * mask.g;
|
|
half4 albedoSmoothnessB = SAMPLE_TEXTURE2D(_SplatAlbedoMapB, sampler_SplatAlbedoMap_linear_repeat, uvB) * mask.b;
|
|
half4 albedoSmoothnessA = SAMPLE_TEXTURE2D(_SplatAlbedoMapA, sampler_SplatAlbedoMap_linear_repeat, uvA) * mask.a;
|
|
|
|
// apply albedo
|
|
half3 albedoR = albedoSmoothnessR.rgb * _SplatAlbedoMapRTintColor;
|
|
half3 albedoG = albedoSmoothnessG.rgb * _SplatAlbedoMapGTintColor;
|
|
half3 albedoB = albedoSmoothnessB.rgb * _SplatAlbedoMapBTintColor;
|
|
half3 albedoA = albedoSmoothnessA.rgb * _SplatAlbedoMapATintColor;
|
|
surfaceData.albedo = lerp(surfaceData.albedo, albedoR + albedoG + albedoB + albedoA, _SplatMapFeatureOnOff);
|
|
|
|
/*
|
|
// apply metallic
|
|
half metallicR = lerp(1,packedDataR.r,_SplatOverrideMetallicR) * mask.r;
|
|
half metallicG = lerp(1,packedDataG.r,_SplatOverrideMetallicG) * mask.g;
|
|
half metallicB = lerp(1,packedDataB.r,_SplatOverrideMetallicB) * mask.b;
|
|
half metallicA = lerp(1,packedDataA.r,_SplatOverrideMetallicA) * mask.a;
|
|
surfaceData.metallic = lerp(surfaceData.metallic, metallicR + metallicG + metallicB + metallicA, _SplatMapFeatureOnOff);
|
|
|
|
// apply occlusion
|
|
half occlusionR = packedDataR.g * mask.r;
|
|
half occlusionG = packedDataG.g * mask.g;
|
|
half occlusionB = packedDataB.g * mask.b;
|
|
half occlusionA = packedDataA.g * mask.a;
|
|
surfaceData.occlusion = lerp(surfaceData.occlusion, occlusionR + occlusionG + occlusionB + occlusionA, _SplatMapFeatureOnOff);
|
|
*/
|
|
|
|
// apply smoothness
|
|
half smoothnessR = saturate(albedoSmoothnessR.a * _SplatSmoothnessMultiplierR);
|
|
half smoothnessG = saturate(albedoSmoothnessG.a * _SplatSmoothnessMultiplierG);
|
|
half smoothnessB = saturate(albedoSmoothnessB.a * _SplatSmoothnessMultiplierB);
|
|
half smoothnessA = saturate(albedoSmoothnessA.a * _SplatSmoothnessMultiplierA);
|
|
surfaceData.smoothness = lerp(surfaceData.smoothness, smoothnessR + smoothnessG + smoothnessB + smoothnessA, _SplatMapFeatureOnOff);
|
|
|
|
// sample and apply normal
|
|
half3 normalTSR = UnpackNormalScale(SAMPLE_TEXTURE2D(_SplatNormalMapR, sampler_SplatNormalMap_linear_repeat, uvR),_SplatNormalMapIntensityR) * mask.r;
|
|
half3 normalTSG = UnpackNormalScale(SAMPLE_TEXTURE2D(_SplatNormalMapG, sampler_SplatNormalMap_linear_repeat, uvG),_SplatNormalMapIntensityG) * mask.g;
|
|
half3 normalTSB = UnpackNormalScale(SAMPLE_TEXTURE2D(_SplatNormalMapB, sampler_SplatNormalMap_linear_repeat, uvB),_SplatNormalMapIntensityB) * mask.b;
|
|
half3 normalTSA = UnpackNormalScale(SAMPLE_TEXTURE2D(_SplatNormalMapA, sampler_SplatNormalMap_linear_repeat, uvA),_SplatNormalMapIntensityA) * mask.a;
|
|
surfaceData.normalTS = lerp(surfaceData.normalTS, (normalTSR + normalTSG + normalTSB + normalTSA), _SplatMapFeatureOnOff);
|
|
#endif
|
|
}
|
|
//==========================================================================================================================================================
|
|
|
|
// Used in Standard (Physically Based) shader
|
|
void LitPassFragment(
|
|
Varyings input
|
|
, out half4 outColor : SV_Target0
|
|
#ifdef _WRITE_RENDERING_LAYERS
|
|
, out float4 outRenderingLayers : SV_Target1
|
|
#endif
|
|
)
|
|
{
|
|
UNITY_SETUP_INSTANCE_ID(input);
|
|
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
|
|
|
|
#if defined(_PARALLAXMAP)
|
|
#if defined(REQUIRES_TANGENT_SPACE_VIEW_DIR_INTERPOLATOR)
|
|
half3 viewDirTS = input.viewDirTS;
|
|
#else
|
|
half3 viewDirWS = GetWorldSpaceNormalizeViewDir(input.positionWS);
|
|
half3 viewDirTS = GetViewDirectionTangentSpace(input.tangentWS, input.normalWS, viewDirWS);
|
|
#endif
|
|
ApplyPerPixelDisplacement(viewDirTS, input.uv);
|
|
#endif
|
|
|
|
SurfaceData surfaceData;
|
|
InitializeStandardLitSurfaceData(input.uv, surfaceData);
|
|
|
|
#if UNITY_VERSION >= 202220
|
|
#ifdef LOD_FADE_CROSSFADE
|
|
LODFadeCrossFade(input.positionCS);
|
|
#endif
|
|
#endif
|
|
|
|
//[NiloToon] add:
|
|
//==========================================================================================================================================================
|
|
// albedo,normal,smoothness override by splat map
|
|
ApplySplatMapToSurfaceData(surfaceData, input);
|
|
|
|
ApplyCustomUserLogicToSurfaceData(surfaceData, input);
|
|
|
|
// global albedo override
|
|
surfaceData.albedo.rgb = lerp(surfaceData.albedo.rgb, _NiloToonGlobalEnviAlbedoOverrideColor.rgb, _NiloToonGlobalEnviAlbedoOverrideColor.a);
|
|
//==========================================================================================================================================================
|
|
|
|
InputData inputData;
|
|
InitializeInputData(input, surfaceData.normalTS, inputData);
|
|
|
|
#if UNITY_VERSION >= 60000000
|
|
SETUP_DEBUG_TEXTURE_DATA(inputData, UNDO_TRANSFORM_TEX(input.uv, _BaseMap));
|
|
#else
|
|
SETUP_DEBUG_TEXTURE_DATA(inputData, input.uv, _BaseMap);
|
|
#endif
|
|
|
|
#if defined(_DBUFFER)
|
|
ApplyDecalToSurfaceData(input.positionCS, surfaceData, inputData);
|
|
#endif
|
|
|
|
#if UNITY_VERSION >= 60000000
|
|
InitializeBakedGIData(input, inputData);
|
|
#endif
|
|
|
|
//[NiloToon] add:
|
|
//==========================================================================================================================================================
|
|
// debug on off
|
|
if(_NiloToonGlobalEnviMinimumShader)
|
|
{
|
|
Light mainLight = GetMainLight();
|
|
outColor = half4(saturate(dot(mainLight.direction, input.normalWS)) * mainLight.color * surfaceData.albedo,1);
|
|
return;
|
|
}
|
|
|
|
// GI edit and override
|
|
inputData.bakedGI = inputData.bakedGI * _NiloToonGlobalEnviGITintColor + _NiloToonGlobalEnviGIAddColor;
|
|
inputData.bakedGI = lerp(inputData.bakedGI, _NiloToonGlobalEnviGIOverride.rgb, _NiloToonGlobalEnviGIOverride.a);
|
|
//==========================================================================================================================================================
|
|
|
|
half4 color = UniversalFragmentPBR(inputData, surfaceData);
|
|
|
|
//[NiloToon] add:
|
|
//==========================================================================================================================================================
|
|
// copy from URP10.4's Lighting.hlsl->UniversalFragmentPBR()
|
|
// To ensure backward compatibility we have to avoid using shadowMask input, as it is not present in older shaders
|
|
#if defined(SHADOWS_SHADOWMASK) && defined(LIGHTMAP_ON)
|
|
half4 shadowMask = inputData.shadowMask;
|
|
#elif !defined (LIGHTMAP_ON)
|
|
half4 shadowMask = unity_ProbesOcclusion;
|
|
#else
|
|
half4 shadowMask = half4(1, 1, 1, 1);
|
|
#endif
|
|
|
|
Light mainLight = GetMainLight(inputData.shadowCoord, inputData.positionWS, shadowMask);
|
|
|
|
// shadow border tint color
|
|
float isShadowEdge = 1-abs(mainLight.shadowAttenuation-0.5)*2;
|
|
color.rgb = lerp(color.rgb,color.rgb * _NiloToonGlobalEnviShadowBorderTintColor.rgb, isShadowEdge * _NiloToonGlobalEnviShadowBorderTintColor.a);
|
|
|
|
// global surface color result override
|
|
color.rgb = lerp(color.rgb,_NiloToonGlobalEnviSurfaceColorResultOverrideColor.rgb, _NiloToonGlobalEnviSurfaceColorResultOverrideColor.a);
|
|
|
|
float2 SV_POSITIONxy = input.positionCS.xy;
|
|
|
|
// screen space outline
|
|
#if _NILOTOON_GLOBAL_ENABLE_SCREENSPACE_OUTLINE || _NILOTOON_GLOBAL_ENABLE_SCREENSPACE_OUTLINE_V2
|
|
// we receive screen space outline only when material's SurfaceType is Opaque.
|
|
// (_Surface == 0 when SurfaceType is Opaque)
|
|
// (_Surface == 1 when SurfaceType is Transparent)
|
|
// *see BaseShaderGUI.cs in URP package
|
|
if(_Surface == 0)
|
|
{
|
|
#if _NILOTOON_GLOBAL_ENABLE_SCREENSPACE_OUTLINE
|
|
{
|
|
float finalOutlineWidth = _ScreenSpaceOutlineWidth * _GlobalScreenSpaceOutlineWidthMultiplierForEnvi;
|
|
float finalNormalsSensitivity = max(0,1 + _GlobalScreenSpaceOutlineNormalsSensitivityOffsetForEnvi); // max(0,x) to prevent negative sensitivity
|
|
float finalDepthSensitivity = max(0,1 + _GlobalScreenSpaceOutlineDepthSensitivityOffsetForEnvi); // max(0,x) to prevent negative
|
|
float selfLinearDepth = abs(mul(UNITY_MATRIX_V,float4(input.positionWS,1)).z);
|
|
|
|
// reduce finalDepthSensitivity according to depth
|
|
|
|
finalDepthSensitivity *= 0.35; // make GUI's default value is 1
|
|
|
|
float isScreenSpaceOutlineArea = IsScreenSpaceOutline(
|
|
SV_POSITIONxy,
|
|
finalOutlineWidth,
|
|
finalDepthSensitivity,
|
|
finalNormalsSensitivity,
|
|
selfLinearDepth,
|
|
_GlobalScreenSpaceOutlineDepthSensitivityDistanceFadeoutStrengthForEnvi,
|
|
_CurrentCameraFOV,
|
|
inputData.viewDirectionWS);
|
|
|
|
isScreenSpaceOutlineArea *= _GlobalScreenSpaceOutlineIntensityForEnvi * _ScreenSpaceOutlineIntensity;
|
|
color.rgb = lerp(color.rgb, color.rgb * _GlobalScreenSpaceOutlineTintColorForEnvi * _ScreenSpaceOutlineColor.rgb, isScreenSpaceOutlineArea);
|
|
}
|
|
#endif
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
#if _NILOTOON_GLOBAL_ENABLE_SCREENSPACE_OUTLINE_V2
|
|
{
|
|
// TODO: receive from renderer feature V2
|
|
float width = _GlobalScreenSpaceOutlineV2WidthMultiplierForEnvi;
|
|
float GeometryEdgeThreshold = _GlobalScreenSpaceOutlineV2GeometryEdgeThresholdForEnvi;
|
|
float NormalAngleCosThetaThresholdMin = _GlobalScreenSpaceOutlineV2NormalAngleCosThetaThresholdForEnvi;
|
|
float NormalAngleCosThetaThresholdMax = cos(DegToRad(180));
|
|
bool DrawGeometryEdge = _GlobalScreenSpaceOutlineV2EnableGeometryEdgeForEnvi;
|
|
bool DrawNormalAngleEdge = _GlobalScreenSpaceOutlineV2EnableNormalAngleEdgeForEnvi;
|
|
bool DrawMaterialIDBoundary = false; // not supported for envi
|
|
bool DrawCustomIDBoundary = false; // not supported for envi
|
|
bool DrawWireframe = false;
|
|
|
|
float isScreenSpaceOutlineArea = IsScreenSpaceOutlineV2(
|
|
SV_POSITIONxy,
|
|
width,
|
|
GeometryEdgeThreshold,
|
|
NormalAngleCosThetaThresholdMin,
|
|
NormalAngleCosThetaThresholdMax,
|
|
DrawGeometryEdge,
|
|
DrawNormalAngleEdge,
|
|
DrawMaterialIDBoundary,
|
|
DrawCustomIDBoundary,
|
|
DrawWireframe,
|
|
input.positionWS);
|
|
|
|
color.rgb *= 1-isScreenSpaceOutlineArea * _GlobalScreenSpaceOutlineV2IntensityForEnvi;
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
ApplyCustomUserLogicBeforeFog(color, surfaceData, inputData);
|
|
//==========================================================================================================================================================
|
|
|
|
color.rgb = MixFog(color.rgb, inputData.fogCoord);
|
|
|
|
//[NiloToon] add:
|
|
//==========================================================================================================================================================
|
|
ApplyCustomUserLogicAfterFog(color, surfaceData, inputData);
|
|
//==========================================================================================================================================================
|
|
|
|
#if UNITY_VERSION >= 202220
|
|
color.a = OutputAlpha(color.a, IsSurfaceTypeTransparent(_Surface));
|
|
#else
|
|
color.a = OutputAlpha(color.a, _Surface);
|
|
#endif
|
|
|
|
outColor = color;
|
|
|
|
#ifdef _WRITE_RENDERING_LAYERS
|
|
uint renderingLayers = GetMeshRenderingLayer();
|
|
outRenderingLayers = float4(EncodeMeshRenderingLayer(renderingLayers), 0, 0, 0);
|
|
#endif
|
|
}
|
|
|