1288 lines
50 KiB
HLSL
1288 lines
50 KiB
HLSL
#ifndef NBSHADER_FORWARD_PASS
|
||
#define NBSHADER_FORWARD_PASS
|
||
#include "NBShaderInput.hlsl"
|
||
#include "Packages/com.xuanxuan.nb.fx/XuanXuanRenderUtility/Shader/HLSL/VAT.hlsl"
|
||
#include "Packages/com.xuanxuan.nb.fx/XuanXuanRenderUtility/Shader/HLSL/SixWaySmokeLit.hlsl"
|
||
|
||
#if defined(NB_DEPTH_ONLY_PASS) || defined(NB_SHADOW_CASTER_PASS)
|
||
#define NB_DEPTH_SHADOW_PASS
|
||
#endif
|
||
|
||
#if defined(NB_SHADOW_CASTER_PASS)
|
||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
|
||
float3 _LightDirection;
|
||
float3 _LightPosition;
|
||
#endif
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
// Vertex and Fragment functions //
|
||
|
||
struct ParticleFragmentOutput
|
||
{
|
||
half4 color : SV_Target;
|
||
#if defined(_OVERRIDE_Z)
|
||
float depth : SV_Depth;
|
||
#endif
|
||
};
|
||
|
||
#if defined(_OVERRIDE_Z)
|
||
float OverrideZToDeviceDepth()
|
||
{
|
||
float nearClip = _ProjectionParams.y;
|
||
float farClip = _ProjectionParams.z;
|
||
float eyeDepth = clamp(_OverrideZValue, nearClip, farClip);
|
||
|
||
if (unity_OrthoParams.w == 0)
|
||
{
|
||
float reciprocalEyeDepth = rcp(max(eyeDepth, 1e-6));
|
||
return saturate((reciprocalEyeDepth - _ZBufferParams.w) / _ZBufferParams.z);
|
||
}
|
||
|
||
float linearDepth = saturate((eyeDepth - nearClip) / max(farClip - nearClip, 1e-6));
|
||
#if UNITY_REVERSED_Z
|
||
return 1.0 - linearDepth;
|
||
#else
|
||
return linearDepth;
|
||
#endif
|
||
}
|
||
#endif
|
||
|
||
ParticleFragmentOutput MakeParticleFragmentOutput(half4 color)
|
||
{
|
||
ParticleFragmentOutput output;
|
||
output.color = color;
|
||
#if defined(_OVERRIDE_Z)
|
||
output.depth = OverrideZToDeviceDepth();
|
||
#endif
|
||
return output;
|
||
}
|
||
|
||
|
||
|
||
VaryingsParticle vertParticleUnlit(AttributesParticle input)
|
||
{
|
||
VaryingsParticle output = (VaryingsParticle)0;
|
||
|
||
output.VaryingsP_Custom1 = input.Custom1;
|
||
output.VaryingsP_Custom2 = input.Custom2;
|
||
|
||
UNITY_SETUP_INSTANCE_ID(input);
|
||
UNITY_TRANSFER_INSTANCE_ID(input, output);
|
||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
|
||
|
||
time = _Time.y;
|
||
|
||
float4 positionOS = input.vertex;
|
||
float3 normalOS = input.normalOS;
|
||
#if defined(_PARALLAX_MAPPING) || defined(_NORMALMAP) || defined(_FX_LIGHT_MODE_SIX_WAY)
|
||
float4 tangentOS = input.tangentOS;
|
||
#endif
|
||
#ifdef _CUSTOM_LOCAL_TRANSFORM
|
||
positionOS.xyz = TransformWorldToObject_NB(input.vertex.xyz);
|
||
normalOS = TransformWorldToObjectNormal_NB(input.normalOS);
|
||
#if defined(_PARALLAX_MAPPING) || defined(_NORMALMAP) || defined(_FX_LIGHT_MODE_SIX_WAY)
|
||
tangentOS.xyz = TransformWorldToObjectDir_NB(input.tangentOS.xyz);
|
||
#endif
|
||
#endif
|
||
ApplyVAT(input, positionOS, normalOS);
|
||
// position ws is used to compute eye depth in vertFading
|
||
output.positionWS.xyz = TransformObjectToWorld_NB(positionOS.xyz);
|
||
output.positionOS.xyz = positionOS;
|
||
|
||
output.clipPos = TransformObjectToHClip_NB(positionOS.xyz);
|
||
|
||
float unityFogFactor = ComputeFogFactor(output.clipPos.z);
|
||
|
||
output.positionWS.w = unityFogFactor;
|
||
|
||
output.color = TryLinearize(input.color);
|
||
|
||
// output.viewDirWS = GetWorldSpaceNormalizeViewDir(output.positionWS.xyz);
|
||
output.normalWSAndAnimBlend.xyz = TransformObjectToWorldNormal_NB(normalOS.xyz);
|
||
|
||
#if defined(_PARALLAX_MAPPING)||defined(_NORMALMAP)||defined(_FX_LIGHT_MODE_SIX_WAY)
|
||
real sign = tangentOS.w * GetCustomLocalOddNegativeScale();
|
||
half3 tangentWS = TransformObjectToWorldDir_NB(tangentOS.xyz);
|
||
#if (defined(_PARALLAX_MAPPING) || defined(_NORMALMAP)) && !defined(_FX_LIGHT_MODE_SIX_WAY)
|
||
output.tangentWS = half4(tangentWS,sign);
|
||
#endif
|
||
#endif
|
||
|
||
|
||
#ifndef _FX_LIGHT_MODE_UNLIT
|
||
#ifdef _FX_LIGHT_MODE_SIX_WAY
|
||
float3 bitangent = sign * cross(output.normalWSAndAnimBlend.xyz, tangentWS);
|
||
half3 bakeDiffuseLighting0;
|
||
half3 bakeDiffuseLighting1;
|
||
half3 bakeDiffuseLighting2;
|
||
half3 backBakeDiffuseLighting0;
|
||
half3 backBakeDiffuseLighting1;
|
||
half3 backBakeDiffuseLighting2;
|
||
GetSixWayBakeDiffuseLight(output.normalWSAndAnimBlend.xyz,tangentWS,bitangent,
|
||
bakeDiffuseLighting0,bakeDiffuseLighting1,bakeDiffuseLighting2,
|
||
backBakeDiffuseLighting0,backBakeDiffuseLighting1,backBakeDiffuseLighting2);
|
||
|
||
output.bakeDiffuseLighting0 = half4(bakeDiffuseLighting0,tangentWS.x);
|
||
output.bakeDiffuseLighting1 = half4(bakeDiffuseLighting1,tangentWS.y);
|
||
output.bakeDiffuseLighting2 = half4(bakeDiffuseLighting2,tangentWS.z);
|
||
output.backBakeDiffuseLighting0 = half4(backBakeDiffuseLighting0,sign);
|
||
output.backBakeDiffuseLighting1 = half4(backBakeDiffuseLighting1,0);
|
||
output.backBakeDiffuseLighting2 = half4(backBakeDiffuseLighting2,0);
|
||
|
||
#else
|
||
OUTPUT_SH(output.normalWSAndAnimBlend.xyz, output.vertexSH);
|
||
#ifdef _ADDITIONAL_LIGHTS_VERTEX
|
||
output.vertexLight = VertexLighting(output.positionWS.xyz, output.normalWSAndAnimBlend.xyz);
|
||
#endif
|
||
#endif
|
||
#endif
|
||
|
||
|
||
|
||
// UNITY_FLATTEN
|
||
// Fresnel enable is keyword-driven by _FRESNEL.
|
||
// {
|
||
// output.fresnelViewDir = output.viewDirWS;
|
||
// }
|
||
|
||
output.texcoord.xy = input.texcoords.xy;
|
||
|
||
//顶点处理的原则:
|
||
//Twirl和极坐标,贴花处理,在片段着色器层处理UV。
|
||
//BaseMap,遮罩Mask,Noise,高光(自发光) 和极坐标处理相关。
|
||
BaseUVs baseUVs;
|
||
if(!isProcessUVInFrag())
|
||
{
|
||
|
||
float2 specialUVInTexcoord3 = 0;
|
||
//如果同时在粒子系统里开启序列帧融帧和特殊UV通道模式。
|
||
#if _FLIPBOOKBLENDING_ON
|
||
if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM) & (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_USE_TEXCOORD1)|CheckLocalFlags1(FLAG_BIT_PARTICLE_1_USE_TEXCOORD2)))
|
||
{
|
||
specialUVInTexcoord3 = input.texcoordBlend.yz;
|
||
output.texcoord2AndSpecialUV.zw = specialUVInTexcoord3;
|
||
}
|
||
#endif
|
||
ParticleUVs particleUVs = (ParticleUVs)0;
|
||
float2 screenUV = output.clipPos.xy/output.clipPos.w;
|
||
screenUV = screenUV*0.5+0.5;
|
||
baseUVs = ProcessBaseUVs(input.texcoords,specialUVInTexcoord3,output.VaryingsP_Custom1,output.VaryingsP_Custom2,output.positionOS.xyz,output.positionWS,screenUV);
|
||
ParticleProcessUV(particleUVs,input.texcoords,output.VaryingsP_Custom1,output.VaryingsP_Custom2,baseUVs);
|
||
output.texcoord2AndSpecialUV.xy = particleUVs.animBlendUV;
|
||
output.texcoord2AndSpecialUV.zw= particleUVs.specUV;
|
||
output.texcoord.xy = particleUVs.mainTexUV;
|
||
output.texcoord.zw = particleUVs.maskMapUV;
|
||
|
||
#if defined(_MASKMAP2_ON) || defined(_MASKMAP3_ON)
|
||
output.texcoordMaskMap2.xy = particleUVs.maskMap2UV;
|
||
output.texcoordMaskMap2.zw = particleUVs.maskMap3UV;
|
||
#endif
|
||
#if defined (_NORMALMAP) || defined(_COLOR_RAMP)
|
||
output.bumpTexAndColorRampMapTexcoord.xy = particleUVs.bumpTexUV;
|
||
output.bumpTexAndColorRampMapTexcoord.zw = particleUVs.colorRampMapUV;
|
||
|
||
#endif
|
||
|
||
#if defined (_EMISSION) || defined(_COLORMAPBLEND)
|
||
output.emissionColorBlendTexcoord.xy = particleUVs.emissionUV;
|
||
output.emissionColorBlendTexcoord.zw = particleUVs.colorBlendUV;
|
||
#endif
|
||
|
||
#ifdef _NOISEMAP
|
||
output.noisemapTexcoord.xy = particleUVs.noiseMapUV;
|
||
output.noisemapTexcoord.zw = particleUVs.noiseMaskMapUV;
|
||
#endif
|
||
#if defined(_DISSOLVE)
|
||
output.dissolveTexcoord.xy = particleUVs.dissolve_uv;
|
||
output.dissolveTexcoord.zw = particleUVs.dissolve_mask_uv;
|
||
#endif
|
||
|
||
#ifdef _PROGRAM_NOISE_ACTIVE
|
||
output.dissolveNoiseTexcoord.xy = particleUVs.dissolve_noise1_UV;
|
||
output.dissolveNoiseTexcoord.zw = particleUVs.dissolve_noise2_UV;
|
||
#endif
|
||
}
|
||
else
|
||
{
|
||
output.texcoord = input.texcoords;
|
||
#if _FLIPBOOKBLENDING_ON
|
||
if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM) & CheckLocalFlags1(FLAG_BIT_PARTICLE_1_USE_TEXCOORD2))
|
||
{
|
||
output.texcoord2AndSpecialUV.zw = input.texcoordBlend.yz;
|
||
}
|
||
#endif
|
||
}
|
||
#ifdef _FLIPBOOKBLENDING_ON
|
||
//粒子帧融合的情况,兼容一下。
|
||
output.normalWSAndAnimBlend.w = input.texcoordBlend.x;
|
||
#endif
|
||
|
||
#if defined(_VERTEX_OFFSET)
|
||
{
|
||
BaseUVs baseUVsForVertexOffset;
|
||
if(!isProcessUVInFrag())
|
||
{
|
||
baseUVsForVertexOffset = baseUVs;
|
||
}
|
||
else
|
||
{
|
||
float2 screenUV = output.clipPos.xy/output.clipPos.w;
|
||
screenUV = screenUV*0.5+0.5;
|
||
baseUVsForVertexOffset = ProcessBaseUVs(input.texcoords,0,output.VaryingsP_Custom1,output.VaryingsP_Custom2,positionOS,output.positionWS,screenUV);
|
||
}
|
||
|
||
//因为极坐标和旋转会强制到Frag计算,所以顶点在这边特殊处理一遍。
|
||
|
||
_VertexOffset_Map_ST.z += GetCustomData(_W9ParticleCustomDataFlag1,FLAGBIT_POS_1_CUSTOMDATA_VERTEX_OFFSET_X,0,input.Custom1,input.Custom2);
|
||
_VertexOffset_Map_ST.w += GetCustomData(_W9ParticleCustomDataFlag1,FLAGBIT_POS_1_CUSTOMDATA_VERTEX_OFFSET_Y,0,input.Custom1,input.Custom2);
|
||
_VertexOffset_Vec.z = GetCustomData(_W9ParticleCustomDataFlag1,FLAGBIT_POS_1_CUSTOMDATA_VERTEXOFFSET_INTENSITY,_VertexOffset_Vec.z,input.Custom1,input.Custom2);
|
||
|
||
#if defined(_VERTEX_OFFSET_MASKMAP)
|
||
_VertexOffset_MaskMap_ST.z += GetCustomData(_W9ParticleCustomDataFlag3,FLAGBIT_POS_3_CUSTOMDATA_VERTEX_OFFSET_MASK_X,0,input.Custom1,input.Custom2);
|
||
_VertexOffset_MaskMap_ST.w += GetCustomData(_W9ParticleCustomDataFlag3,FLAGBIT_POS_3_CUSTOMDATA_VERTEX_OFFSET_MASK_Y,0,input.Custom1,input.Custom2);
|
||
#endif
|
||
|
||
float2 vertexOffsetUVs = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_VERTEX_OFFSET_MAP,baseUVsForVertexOffset);
|
||
float2 vertexOffsetMaskUVs = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_VERTEX_OFFSET_MASKMAP,baseUVsForVertexOffset);
|
||
|
||
half3 vertexOffsetOS = 0;
|
||
positionOS.xyz = VetexOffset(positionOS,vertexOffsetUVs,vertexOffsetMaskUVs,normalOS,vertexOffsetOS);
|
||
#ifdef NB_DEBUG_VERTEX_OFFSET
|
||
half3 vertexOffsetWS = TransformObjectToWorldDir_NB(vertexOffsetOS,false);
|
||
output.color = half4(abs(vertexOffsetWS),1);
|
||
#endif
|
||
output.positionWS.xyz = TransformObjectToWorld_NB(positionOS.xyz);
|
||
|
||
//再算一遍
|
||
output.positionWS.xyz = TransformObjectToWorld_NB(positionOS.xyz);
|
||
output.positionOS.xyz = positionOS;
|
||
output.clipPos = TransformObjectToHClip_NB(positionOS.xyz);
|
||
}
|
||
#endif
|
||
|
||
#if defined(NB_SHADOW_CASTER_PASS)
|
||
#if _CASTING_PUNCTUAL_LIGHT_SHADOW
|
||
float3 lightDirectionWS = normalize(_LightPosition - output.positionWS.xyz);
|
||
#else
|
||
float3 lightDirectionWS = _LightDirection;
|
||
#endif
|
||
|
||
output.clipPos = TransformWorldToHClip(ApplyShadowBias(output.positionWS.xyz, output.normalWSAndAnimBlend.xyz, lightDirectionWS));
|
||
|
||
#if UNITY_REVERSED_Z
|
||
output.clipPos.z = min(output.clipPos.z, UNITY_NEAR_CLIP_VALUE);
|
||
#else
|
||
output.clipPos.z = max(output.clipPos.z, UNITY_NEAR_CLIP_VALUE);
|
||
#endif
|
||
#endif
|
||
|
||
#if !defined(NB_DEPTH_SHADOW_PASS)
|
||
UNITY_BRANCH
|
||
if(needEyeDepth())
|
||
{
|
||
float4 ndc = output.clipPos*0.5f;
|
||
output.positionNDC.xy = float2(ndc.x, ndc.y * _ProjectionParams.x) + ndc.w;
|
||
output.positionNDC.zw = output.clipPos.zw;
|
||
}
|
||
#endif
|
||
|
||
return output;
|
||
}
|
||
|
||
|
||
#if defined(NB_SHADOW_CASTER_PASS)
|
||
uint NBShadowBayer2(uint x, uint y)
|
||
{
|
||
return (((x ^ y) & 1u) << 1) | (y & 1u);
|
||
}
|
||
|
||
half NBShadowDitherMaskClip(float4 positionCS, half alpha)
|
||
{
|
||
uint x = (uint)positionCS.x & 3u;
|
||
uint y = (uint)positionCS.y & 3u;
|
||
uint bayer = NBShadowBayer2(x & 1u, y & 1u) * 4u + NBShadowBayer2((x >> 1) & 1u, (y >> 1) & 1u);
|
||
half coverage = floor(saturate(alpha) * 16.0);
|
||
return coverage - (half)bayer - 0.01;
|
||
}
|
||
#endif
|
||
|
||
|
||
///////////////////////Fragment functions ////////////////////////
|
||
|
||
ParticleFragmentOutput fragParticleUnlit(VaryingsParticle input, half facing : VFACE)
|
||
{
|
||
|
||
#if !defined(NB_DEPTH_SHADOW_PASS)
|
||
float3 viewDirWS = GetWorldSpaceNormalizeViewDir(input.positionWS.xyz);
|
||
input.normalWSAndAnimBlend.xyz = facing > 0 ? input.normalWSAndAnimBlend.xyz : -input.normalWSAndAnimBlend.xyz;
|
||
#endif
|
||
|
||
|
||
UNITY_SETUP_INSTANCE_ID(input);
|
||
#if !defined(NB_DEPTH_SHADOW_PASS)
|
||
#ifdef NB_DEBUG_VERTEX_OFFSET
|
||
return MakeParticleFragmentOutput(input.color);
|
||
#endif
|
||
#endif
|
||
|
||
time = _Time.y;
|
||
|
||
float2 screenUV = input.clipPos.xy / _ScaledScreenParams.xy;
|
||
|
||
#if !defined(NB_DEPTH_SHADOW_PASS)
|
||
real sceneZBufferDepth = 0;
|
||
real sceneZ = 0;
|
||
|
||
UNITY_BRANCH
|
||
if(needSceneDepth())
|
||
{
|
||
#if UNITY_REVERSED_Z
|
||
sceneZBufferDepth = SampleSceneDepth(screenUV);
|
||
#else
|
||
// Adjust z to match NDC for OpenGL
|
||
sceneZBufferDepth = lerp(UNITY_NEAR_CLIP_VALUE, 1, SampleSceneDepth(screenUV));
|
||
#endif
|
||
sceneZ = (unity_OrthoParams.w == 0) ? LinearEyeDepth(sceneZBufferDepth, _ZBufferParams) : LinearDepthToEyeDepth(sceneZBufferDepth);//场景当前深度
|
||
}
|
||
|
||
real thisZ = 0;
|
||
|
||
|
||
half3 positionVS = 0;
|
||
if(needPositionVS())
|
||
{
|
||
positionVS = TransformWorldToView(input.positionWS);
|
||
}
|
||
|
||
if(needEyeDepth())
|
||
{
|
||
thisZ = (unity_OrthoParams.w == 0) ? LinearEyeDepth(input.positionNDC.z / input.positionNDC.w, _ZBufferParams) : -positionVS.z;//场景当前深度
|
||
}
|
||
|
||
|
||
#ifdef _DEPTH_DECAL
|
||
float3 fragWorldPos = ComputeWorldSpacePosition(screenUV, sceneZBufferDepth, UNITY_MATRIX_I_VP);
|
||
float3 fragobjectPos = TransformWorldToObject_NB(fragWorldPos);
|
||
|
||
float3 absFragObjectPos = abs(fragobjectPos);
|
||
half clipValue = step(absFragObjectPos.x,0.5);
|
||
clipValue *= step(absFragObjectPos.y,0.5);
|
||
clipValue *= step(absFragObjectPos.z,0.5);
|
||
half decalAlpha = NB_Remap (abs(fragobjectPos.y),0.1,0.5,1,0);
|
||
decalAlpha = decalAlpha*decalAlpha;
|
||
decalAlpha *= clipValue;
|
||
float2 decalUV = fragobjectPos.xz + 0.5;
|
||
#endif
|
||
#endif
|
||
|
||
float4 uv = input.texcoord;
|
||
#if !defined(NB_DEPTH_SHADOW_PASS)
|
||
#ifdef _DEPTH_DECAL
|
||
uv.xy = decalUV;
|
||
#endif
|
||
#endif
|
||
|
||
float2 MainTex_UV;
|
||
float3 blendUv;
|
||
blendUv.xy = input.texcoord2AndSpecialUV.xy;
|
||
if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_ANIMATION_SHEET_HELPER))
|
||
{
|
||
blendUv.z = _AnimationSheetHelperBlendIntensity;
|
||
}
|
||
else
|
||
{
|
||
blendUv.z = input.normalWSAndAnimBlend.w;
|
||
}
|
||
float2 MaskMapuv;
|
||
float2 MaskMapuv2;
|
||
float2 MaskMapuv3;
|
||
float2 noiseMap_uv;
|
||
float2 noiseMaskMap_uv;
|
||
float2 colorBlendMap_uv;
|
||
float2 emission_uv;
|
||
float2 dissolve_uv;
|
||
float2 dissolve_mask_uv;
|
||
float4 dissolve_noise_uv;
|
||
float2 BumpTex_uv;
|
||
float2 colorRamp_uv;
|
||
|
||
//如果同时在粒子系统里开启序列帧融帧和特殊UV通道模式。
|
||
|
||
if(isProcessUVInFrag())
|
||
{
|
||
float2 specialUVInTexcoord3 = 0;
|
||
#if _FLIPBOOKBLENDING_ON
|
||
if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM) & (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_USE_TEXCOORD2)))
|
||
{
|
||
specialUVInTexcoord3 = input.texcoord2AndSpecialUV.zw;
|
||
}
|
||
|
||
#endif
|
||
ParticleUVs particleUVs = (ParticleUVs)0;
|
||
BaseUVs baseUVs = ProcessBaseUVs(uv,specialUVInTexcoord3,input.VaryingsP_Custom1,input.VaryingsP_Custom2,input.positionOS.xyz,input.positionWS.xyz,screenUV);
|
||
ParticleProcessUV(particleUVs,uv,input.VaryingsP_Custom1,input.VaryingsP_Custom2,baseUVs);
|
||
MainTex_UV.xy = particleUVs.mainTexUV;
|
||
blendUv.xy = particleUVs.animBlendUV;
|
||
MaskMapuv = particleUVs.maskMapUV;
|
||
MaskMapuv2 = particleUVs.maskMap2UV;
|
||
MaskMapuv3 = particleUVs.maskMap3UV;
|
||
emission_uv = particleUVs.emissionUV;
|
||
dissolve_uv = particleUVs.dissolve_uv;
|
||
dissolve_mask_uv = particleUVs.dissolve_mask_uv;
|
||
colorBlendMap_uv = particleUVs.colorBlendUV;
|
||
noiseMap_uv = particleUVs.noiseMapUV;
|
||
noiseMaskMap_uv = particleUVs.noiseMaskMapUV;
|
||
dissolve_noise_uv = float4(particleUVs.dissolve_noise1_UV,particleUVs.dissolve_noise2_UV);
|
||
BumpTex_uv = particleUVs.bumpTexUV;
|
||
colorRamp_uv = particleUVs.colorRampMapUV;
|
||
}
|
||
else
|
||
{
|
||
MainTex_UV = input.texcoord.xy;
|
||
MaskMapuv = input.texcoord.zw;
|
||
#if defined(_MASKMAP2_ON) || defined(_MASKMAP3_ON)
|
||
MaskMapuv2 = input.texcoordMaskMap2.xy;
|
||
MaskMapuv3 = input.texcoordMaskMap2.zw;
|
||
#endif
|
||
|
||
#if defined (_NORMALMAP)||defined(_COLOR_RAMP)
|
||
BumpTex_uv = input.bumpTexAndColorRampMapTexcoord.xy;
|
||
colorRamp_uv = input.bumpTexAndColorRampMapTexcoord.zw;
|
||
#endif
|
||
|
||
#ifdef _NOISEMAP
|
||
noiseMap_uv = input.noisemapTexcoord.xy;
|
||
noiseMaskMap_uv = input.noisemapTexcoord.zw;
|
||
#endif
|
||
|
||
#if defined (_EMISSION) || defined(_COLORMAPBLEND)
|
||
emission_uv = input.emissionColorBlendTexcoord.xy;
|
||
colorBlendMap_uv = input.emissionColorBlendTexcoord.zw;
|
||
#endif
|
||
|
||
#ifdef _DISSOLVE
|
||
dissolve_uv = input.dissolveTexcoord.xy;
|
||
dissolve_mask_uv = input.dissolveTexcoord.zw;
|
||
#endif
|
||
#ifdef _PROGRAM_NOISE_ACTIVE
|
||
dissolve_noise_uv = input.dissolveNoiseTexcoord;
|
||
#endif
|
||
}
|
||
|
||
|
||
half programNoise;
|
||
#ifdef _PROGRAM_NOISE_ACTIVE
|
||
half programSimpleNoise;
|
||
half programVoronoiNoise;
|
||
|
||
#if defined(_PROGRAM_NOISE_SIMPLE)
|
||
{
|
||
programSimpleNoise = SimplexNoise(dissolve_noise_uv.xy,_Time.y*_DissolveVoronoi_Vec2.z);
|
||
programNoise = programSimpleNoise;
|
||
}
|
||
#endif
|
||
|
||
#if defined(_PROGRAM_NOISE_VORONOI)
|
||
{
|
||
half cell;
|
||
Unity_Voronoi_float(dissolve_noise_uv.zw,_Time.y*_DissolveVoronoi_Vec2.w,1,programVoronoiNoise,cell);
|
||
programNoise = programVoronoiNoise ;
|
||
}
|
||
#endif
|
||
|
||
#if defined(_PROGRAM_NOISE_SIMPLE) && defined(_PROGRAM_NOISE_VORONOI)
|
||
{
|
||
programNoise = BlendPNoise(_W9ParticleShaderPNoiseBlendFlag,FLAG_BIT_PNOISE_BLEND_POS_0_BASE_BLEND,programSimpleNoise,programVoronoiNoise,_ProgramNoiseBaseBlendOpacity);
|
||
// Unity_Blend_HardLight_half(programSimpleNoise,programVoronoiNoise,_DissolveVoronoi_Vec2.x,programNoise);
|
||
}
|
||
#endif
|
||
|
||
// half dissolveSample = dissolveValue;
|
||
// Unity_Blend_HardLight_half(overlayVoroni,dissolveSample,_DissolveVoronoi_Vec2.y,dissolveValue);
|
||
#ifdef NB_DEBUG_PNOISE
|
||
return MakeParticleFragmentOutput(half4(programNoise.xxx,1));
|
||
#endif
|
||
|
||
#endif
|
||
|
||
half2 originUV = MainTex_UV;
|
||
|
||
//预先处理好法线贴图部分
|
||
half metallic = 1;
|
||
half smoothness = 1;
|
||
half3 normalTS = half3(0, 0, 1);//TODO
|
||
half3x3 tangentToWorld = (half3x3)0;
|
||
#if defined(_PARALLAX_MAPPING) || defined(_NORMALMAP) || defined(_FX_LIGHT_MODE_SIX_WAY)
|
||
half4 tangentWS = 0;
|
||
#if defined(_FX_LIGHT_MODE_SIX_WAY)
|
||
tangentWS = half4(input.bakeDiffuseLighting0.w,input.bakeDiffuseLighting1.w,input.bakeDiffuseLighting2.w,input.backBakeDiffuseLighting0.w);
|
||
#else
|
||
tangentWS = input.tangentWS;
|
||
#endif
|
||
#endif
|
||
#if defined(_PARALLAX_MAPPING) || defined(_NORMALMAP)
|
||
float sgn = tangentWS.w; // should be either +1 or -1
|
||
float3 bitangent = sgn * cross(input.normalWSAndAnimBlend.xyz, tangentWS.xyz);
|
||
tangentToWorld = half3x3(tangentWS.xyz, bitangent.xyz, input.normalWSAndAnimBlend.xyz);
|
||
#endif
|
||
#ifdef _PARALLAX_MAPPING
|
||
float3 tangentViewDir = NBTransformWorldToTangentDir(viewDirWS, tangentToWorld, true);
|
||
MainTex_UV.xy = ParallaxOcclusionMapping(MainTex_UV, tangentViewDir);
|
||
#endif
|
||
#ifdef _NORMALMAP
|
||
half4 normalMapSample = SampleTexture2DWithWrapFlags(_BumpTex,BumpTex_uv,FLAG_BIT_WRAPMODE_BUMPTEX);
|
||
if (CheckLocalFlags(FLAG_BIT_PARTICLE_NORMALMAP_MASK_MODE))
|
||
{
|
||
normalTS = UnpackNormalRGB(half4(normalMapSample.xy,1,1),_BumpScale);
|
||
metallic *= normalMapSample.z;
|
||
smoothness *= normalMapSample.w;
|
||
}
|
||
else
|
||
{
|
||
normalTS = UnpackNormalScale(half4(normalMapSample),_BumpScale);
|
||
}
|
||
|
||
input.normalWSAndAnimBlend.xyz = normalize(TransformTangentToWorld(normalTS, tangentToWorld));
|
||
#endif
|
||
|
||
half2 cum_noise = 0;
|
||
// half2 cum_noise_xy = half2(0.5,0.5);
|
||
half3 screenDistort_Noise = half3(0,0,1);//xy:noise,z:mask;
|
||
half noiseMask = 1;
|
||
#if defined(_NOISEMAP)
|
||
#ifdef _DISTORT_REFRACTION
|
||
half3 refracVec = CustomRefract(-viewDirWS,input.normalWSAndAnimBlend.xyz,1/_RefractionIOR);
|
||
refracVec = TransformWorldToHClipDir(refracVec);
|
||
cum_noise = refracVec.xy;
|
||
// distortFlow = refracVec.xy * props._NormalRefractionBias;
|
||
#else
|
||
half4 noiseSample = SampleNoise(_NoiseOffset, _NoiseMap, noiseMap_uv, input.positionWS.xyz);
|
||
cum_noise = noiseSample.xy;
|
||
UNITY_FLATTEN
|
||
if(CheckLocalFlags(FLAG_BIT_PARTICLE_NOISEMAP_NORMALIZEED_ON))
|
||
{
|
||
cum_noise = cum_noise * 2 - 1;
|
||
}
|
||
noiseMask *= noiseSample.a;
|
||
_DistortionDirection.x += GetCustomData(_W9ParticleCustomDataFlag2,FLAGBIT_POS_2_CUSTOMDATA_NOISE_DIRECTION_X,0,input.VaryingsP_Custom1,input.VaryingsP_Custom2);
|
||
_DistortionDirection.y += GetCustomData(_W9ParticleCustomDataFlag2,FLAGBIT_POS_2_CUSTOMDATA_NOISE_DIRECTION_Y,0,input.VaryingsP_Custom1,input.VaryingsP_Custom2);
|
||
#endif
|
||
#if defined(_NOISE_MASKMAP)
|
||
{
|
||
half4 noiseMaskSample = SampleTexture2DWithWrapFlags(_NoiseMaskMap,noiseMaskMap_uv,FLAG_BIT_WRAPMODE_NOISE_MASKMAP);
|
||
noiseMask *= GetColorChannel(noiseMaskSample,FLAG_BIT_COLOR_CHANNEL_POS_0_NOISE_MASK);
|
||
}
|
||
#endif
|
||
_NoiseIntensity = GetCustomData(_W9ParticleCustomDataFlag1,FLAGBIT_POS_1_CUSTOMDATA_NOISE_INTENSITY,_NoiseIntensity,input.VaryingsP_Custom1,input.VaryingsP_Custom2);
|
||
|
||
cum_noise = cum_noise *_DistortionDirection.xy*_NoiseIntensity;
|
||
|
||
#ifdef _PROGRAM_NOISE_ACTIVE
|
||
cum_noise = BlendPNoise(_W9ParticleShaderPNoiseBlendFlag,FLAG_BIT_PNOISE_BLEND_POS_0_DISTORT,cum_noise,programNoise,_DistortPNoiseBlendOpacity);
|
||
#endif
|
||
|
||
|
||
|
||
#if defined(_SCREEN_DISTORT_MODE)
|
||
screenDistort_Noise.xy = cum_noise;
|
||
screenDistort_Noise.z = noiseMask;
|
||
#endif
|
||
// #if defined(_SCREEN_DISTORT_MODE)
|
||
// cum_noise_xy = cum_noise * _ScreenDistortIntensity;
|
||
// #endif
|
||
|
||
cum_noise *= noiseMask;
|
||
|
||
#ifdef NB_DEBUG_DISTORT
|
||
return MakeParticleFragmentOutput(half4(cum_noise,0,1));
|
||
#endif
|
||
#endif
|
||
|
||
// SampleAlbedo--------------------
|
||
half4 albedo = 0;
|
||
|
||
#if !defined(NB_DEPTH_SHADOW_PASS)
|
||
UNITY_FLATTEN
|
||
if(CheckLocalFlags(FLAG_BIT_PARTICLE_BACKCOLOR))
|
||
{
|
||
_BaseColor = facing > 0 ? _BaseColor : _BaseBackColor;
|
||
}
|
||
#endif
|
||
|
||
|
||
Texture2D baseMap = _BaseMap;
|
||
|
||
|
||
|
||
float2 mainTexNoise = cum_noise * _TexDistortion_intensity;
|
||
|
||
MainTex_UV.xy += mainTexNoise;//主贴图纹理扭曲
|
||
blendUv.xy += mainTexNoise;
|
||
|
||
|
||
UNITY_BRANCH
|
||
if (CheckLocalFlags(FLAG_BIT_PARTICLE_UIEFFECT_ON) & !CheckLocalFlags1(FLAG_BIT_PARTICLE_1_UIEFFECT_BASEMAP_MODE))
|
||
{
|
||
albedo = BlendTexture(_MainTex, MainTex_UV, blendUv) * _Color;
|
||
}
|
||
else
|
||
{
|
||
#if defined(_CHROMATIC_ABERRATION)
|
||
#if !defined(NB_DEPTH_SHADOW_PASS)
|
||
_DistortionDirection.z = GetCustomData(_W9ParticleCustomDataFlag0,FLAGBIT_POS_0_CUSTOMDATA_CHORATICABERRAT_INTENSITY,_DistortionDirection.z,input.VaryingsP_Custom1,input.VaryingsP_Custom2);
|
||
_DistortionDirection.z *= 0.1;
|
||
albedo = DistortionChoraticaberrat(baseMap,originUV,MainTex_UV,_DistortionDirection.z,FLAG_BIT_WRAPMODE_BASEMAP);
|
||
#else
|
||
albedo = BlendTexture(baseMap, MainTex_UV, blendUv,FLAG_BIT_WRAPMODE_BASEMAP);
|
||
#endif
|
||
#else
|
||
albedo = BlendTexture(baseMap, MainTex_UV, blendUv,FLAG_BIT_WRAPMODE_BASEMAP);
|
||
#endif
|
||
}
|
||
|
||
// #ifndef _CAMERA_OPAQUE_DISTORT_PASS
|
||
|
||
albedo.a = GetColorChannel(albedo,FLAG_BIT_COLOR_CHANNEL_POS_0_MAINTEX_ALPHA);
|
||
|
||
albedo *= _BaseColor ;
|
||
#if !defined(NB_DEPTH_SHADOW_PASS)
|
||
albedo.rgb *= _BaseColorIntensityForTimeline;
|
||
#endif
|
||
// #endif
|
||
|
||
|
||
// #endif
|
||
|
||
half alpha = albedo.a;
|
||
half3 result = albedo.rgb;
|
||
#if !defined(NB_DEPTH_SHADOW_PASS)
|
||
UNITY_BRANCH
|
||
if (CheckLocalFlags(FLAG_BIT_PARTICLE_COLOR_ADJUSTMENT_ONLY_AFFECT_MAINTEX))
|
||
{
|
||
ColorAdjustment(result,alpha,input.VaryingsP_Custom1,input.VaryingsP_Custom2);
|
||
}
|
||
#endif
|
||
|
||
#ifdef _FX_LIGHT_MODE_SIX_WAY
|
||
float4 rigRTBkSample = BlendTexture(_RigRTBk, MainTex_UV, blendUv,FLAG_BIT_WRAPMODE_BASEMAP);
|
||
float4 rigLBtFSample = BlendTexture(_RigLBtF, MainTex_UV, blendUv,FLAG_BIT_WRAPMODE_BASEMAP);
|
||
#endif
|
||
|
||
|
||
//光照模式
|
||
#ifndef _FX_LIGHT_MODE_UNLIT
|
||
|
||
InputData inputData;
|
||
InitializeInputData(input, tangentToWorld,viewDirWS, inputData);
|
||
metallic *= _MaterialInfo.x;
|
||
half3 specular = 0;
|
||
smoothness *= _MaterialInfo.y;
|
||
half occlusion = 1;
|
||
half3 pbrEmission = 0;
|
||
// return half4(inputData.bakedGI,1);
|
||
#if defined (_FX_LIGHT_MODE_BLINN_PHONG) || defined(_FX_LIGHT_MODE_HALF_LAMBERT)
|
||
half4 specularGloss = _SpecularColor;
|
||
#ifdef _FX_LIGHT_MODE_BLINN_PHONG
|
||
half4 blinnPhong = UniversalFragmentBlinnPhong(inputData,result.rgb, specularGloss, smoothness, pbrEmission, alpha,normalTS);
|
||
#else //_FX_LIGHT_MODE_HALF_LAMBERT
|
||
half4 blinnPhong = UniversalFragmentHalfLambert(inputData,result.rgb, specularGloss, smoothness, pbrEmission, alpha,normalTS);
|
||
#endif
|
||
result = blinnPhong.rgb;
|
||
alpha = blinnPhong.a;
|
||
#elif _FX_LIGHT_MODE_PBR
|
||
half4 pbr = UniversalFragmentPBR(inputData,result.rgb, metallic, specular, smoothness, occlusion, pbrEmission, alpha);
|
||
result = pbr.rgb;
|
||
alpha = pbr.a;
|
||
#elif _FX_LIGHT_MODE_SIX_WAY
|
||
BSDFData bsdfData = (BSDFData)0;
|
||
bsdfData.absorptionRange = GetAbsorptionRange(_SixWayInfo.x);
|
||
bsdfData.diffuseColor = albedo;
|
||
bsdfData.normalWS = inputData.normalWS;
|
||
bsdfData.tangentWS = tangentWS;
|
||
bsdfData.rigRTBk = rigRTBkSample.xyz * INV_PI;//AccordingTo SixWayForwardPass
|
||
bsdfData.rigLBtF = rigLBtFSample.xyz * INV_PI;//AccordingTo SixWayForwardPass
|
||
bsdfData.bakeDiffuseLighting0 = input.bakeDiffuseLighting0.xyz;
|
||
bsdfData.bakeDiffuseLighting1 = input.bakeDiffuseLighting1.xyz;
|
||
bsdfData.bakeDiffuseLighting2 = input.bakeDiffuseLighting2.xyz;
|
||
bsdfData.backBakeDiffuseLighting0 = input.backBakeDiffuseLighting0.xyz;
|
||
bsdfData.backBakeDiffuseLighting1 = input.backBakeDiffuseLighting1.xyz;
|
||
bsdfData.backBakeDiffuseLighting2 = input.backBakeDiffuseLighting2.xyz;
|
||
bsdfData.emissionInput = rigLBtFSample.a;
|
||
GetSixWayEmission(bsdfData,_SixWayEmissionRamp,_SixWayEmissionColor,CheckLocalFlags1(FLAG_BIT_PARTICLE_1_SIXWAY_RAMPMAP));//Init Emission
|
||
bsdfData.alpha = rigRTBkSample.a * _BaseColor.a;
|
||
|
||
ModifyBakedDiffuseLighting(bsdfData,inputData.bakedGI);
|
||
|
||
half4 sixWay = UniversalFragmentSixWay(inputData,bsdfData);
|
||
|
||
|
||
// half3 dir = _MainLightPosition.xyz;
|
||
// dir = TransformToLocalFrame(dir, bsdfData);
|
||
// return half4(dir,1);
|
||
|
||
result = sixWay.rgb;
|
||
alpha = sixWay.a;
|
||
|
||
#endif
|
||
|
||
#ifdef _ADDITIONAL_LIGHTS_VERTEX
|
||
result.rgb *= input.vertexLight;
|
||
#endif
|
||
|
||
// input.normalWSAndAnimBlend.xyz = inputData.normalWS;
|
||
#endif
|
||
|
||
|
||
#ifdef _MATCAP
|
||
// URP
|
||
half3 normalVS = mul(input.normalWSAndAnimBlend.xyz, (float3x3)UNITY_MATRIX_I_V); // 逆转置矩阵
|
||
//half3 positionVS = TransformWorldToView(input.positionWS);
|
||
|
||
|
||
float3 r = reflect(positionVS, normalVS);
|
||
r = normalize(r);
|
||
float m = 2.828427f * sqrt(r.z + 1.0);
|
||
float2 matCapUV = r.xy / m + 0.5;
|
||
half3 matCapSample = SAMPLE_TEXTURE2D(_MatCapTex,sampler_linear_clamp,matCapUV);
|
||
|
||
matCapSample *= _MatCapColor.rgb;
|
||
|
||
half3 matCapMutilResult = result * matCapSample;
|
||
half3 matAddResult = result + matCapSample;
|
||
half3 matCapResult = lerp(matAddResult,matCapMutilResult,_MatCapInfo.x);
|
||
|
||
result = lerp(result,matCapResult,_MatCapColor.a);
|
||
#endif
|
||
|
||
|
||
|
||
//流光部分
|
||
half4 emission = half4(0, 0, 0,1);
|
||
#if defined(_EMISSION)
|
||
#ifdef _NOISEMAP
|
||
emission_uv += cum_noise * _Emi_Distortion_intensity;
|
||
#endif
|
||
// emission = tex2D_TryLinearizeWithoutAlphaFX(_EmissionMap,emission_uv);
|
||
emission = SampleTexture2DWithWrapFlags(_EmissionMap,emission_uv,FLAG_BIT_WRAPMODE_EMISSIONMAP);
|
||
emission.xyz *= emission.a;
|
||
_EmissionMapColor *= _EmissionMapColorIntensity;
|
||
emission.xyz *= _EmissionMapColor;
|
||
|
||
#endif
|
||
|
||
result += emission;
|
||
|
||
|
||
#if defined(_COLOR_RAMP)
|
||
half rampValue = 0;
|
||
#if defined(_COLOR_RAMP_MAP)
|
||
half4 RampColorSample = SampleTexture2DWithWrapFlags(_RampColorMap,colorRamp_uv,FLAG_BIT_WRAPMODE_RAMP_COLOR_MAP);
|
||
rampValue = GetColorChannel(RampColorSample,FLAG_BIT_COLOR_CHANNEL_POS_0_RAMP_COLOR_MAP);
|
||
#else
|
||
const int rampColorWrapMode = CheckLocalWrapFlags(FLAG_BIT_WRAPMODE_RAMP_COLOR_MAP);
|
||
if (rampColorWrapMode == 0 || rampColorWrapMode == 2)
|
||
{
|
||
rampValue = frac(colorRamp_uv.x);
|
||
}
|
||
else
|
||
{
|
||
rampValue = saturate(colorRamp_uv.x);
|
||
}
|
||
#endif
|
||
|
||
int colorRampColorCount = _RampColorCount & 0xFFFF;
|
||
|
||
int colorRampAlphaCount = _RampColorCount >> 16;
|
||
|
||
half4 rampColor;
|
||
rampColor.rgb = SamplePackedGradientColor(_RampColor0, _RampColor1, _RampColor2, _RampColor3, _RampColor4, _RampColor5, colorRampColorCount, rampValue);
|
||
rampColor.a = SamplePackedGradientAlpha(_RampColorAlpha0, _RampColorAlpha1, _RampColorAlpha2, colorRampAlphaCount, rampValue);
|
||
|
||
rampColor *= _RampColorBlendColor;
|
||
|
||
if (CheckLocalFlags(FLAG_BIT_PARTICLE_RAMP_COLOR_BLEND_ADD))
|
||
{
|
||
result += rampColor;
|
||
alpha += rampColor.a;
|
||
}
|
||
else
|
||
{
|
||
result *= rampColor;
|
||
alpha *= rampColor.a;
|
||
}
|
||
#endif
|
||
|
||
|
||
|
||
//溶解部分
|
||
#if defined(_DISSOLVE)
|
||
#ifdef _NOISEMAP
|
||
dissolve_uv += cum_noise * _DissolveOffsetRotateDistort.w;
|
||
|
||
#if defined(_DISSOLVE_MASK)
|
||
dissolve_mask_uv += cum_noise * _DissolveOffsetRotateDistort.w;
|
||
#endif
|
||
#endif
|
||
|
||
half4 dissolveMapSample = SampleTexture2DWithWrapFlags(_DissolveMap,dissolve_uv,FLAG_BIT_WRAPMODE_DISSOLVE_MAP);
|
||
|
||
half dissolveValue = GetColorChannel(dissolveMapSample,FLAG_BIT_COLOR_CHANNEL_POS_0_DISSOLVE_MAP);
|
||
|
||
#ifdef _PROGRAM_NOISE_ACTIVE
|
||
dissolveValue = BlendPNoise(_W9ParticleShaderPNoiseBlendFlag,FLAG_BIT_PNOISE_BLEND_POS_0_DISSOLVE,dissolveValue,programNoise,_DissolvePNoiseBlendOpacity);
|
||
#endif
|
||
|
||
|
||
dissolveValue = pow(dissolveValue,_Dissolve.y);
|
||
|
||
|
||
|
||
|
||
half dissolveMaskValue = 0;
|
||
half dissolveMaskStrength = 0;
|
||
#if defined(_DISSOLVE_MASK)
|
||
{
|
||
half4 dissolveMaskSample = SampleTexture2DWithWrapFlags(_DissolveMaskMap,dissolve_mask_uv,FLAG_BIT_WRAPMODE_DISSOLVE_MASKMAP);
|
||
dissolveMaskValue = GetColorChannel(dissolveMaskSample,FLAG_BIT_COLOR_CHANNEL_POS_0_DISSOLVE_MASK_MAP);
|
||
dissolveMaskStrength = _Dissolve.z + GetCustomData(_W9ParticleCustomDataFlag1,FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_MASK_INTENSITY,0,input.VaryingsP_Custom1,input.VaryingsP_Custom2);
|
||
|
||
if (_DissolveMaskMode < 0.5)
|
||
{
|
||
dissolveMaskValue = lerp(dissolveValue, dissolveMaskValue, dissolveMaskStrength);
|
||
dissolveValue = (dissolveValue +dissolveMaskValue)*0.5;//Smart Way By Panda
|
||
}
|
||
}
|
||
#endif
|
||
|
||
#ifdef NB_DEBUG_DISSOLVE //后续Test类的关键字要找机会排除
|
||
return MakeParticleFragmentOutput(half4(dissolveValue.rrr,1));
|
||
#endif
|
||
half dissolveStrenth = _Dissolve.x + GetCustomData(_W9ParticleCustomDataFlag0,FLAGBIT_POS_0_CUSTOMDATA_DISSOLVE_INTENSITY,0,input.VaryingsP_Custom1,input.VaryingsP_Custom2);
|
||
|
||
half invSoftStep = 1/_Dissolve.w;
|
||
half dissolveValueBeforeSoftStep = dissolveValue - ((dissolveStrenth)*(invSoftStep + 1)-1)*_Dissolve.w ;
|
||
dissolveValue = dissolveValue*invSoftStep -(1+invSoftStep)*dissolveStrenth +1;
|
||
// dissolveValue = smoothstep(dissolveStrenth-_Dissolve.w,dissolveStrenth,dissolveValue);//Smart Way By Panda
|
||
|
||
|
||
dissolveValue = saturate(dissolveValue);
|
||
#if defined(_DISSOLVE_MASK)
|
||
if(_DissolveMaskMode > 0.5)
|
||
{
|
||
dissolveMaskStrength = dissolveMaskStrength -1;
|
||
dissolveMaskValue = saturate(dissolveMaskValue - dissolveMaskStrength);
|
||
dissolveValue = lerp(1, dissolveValue, dissolveMaskValue);
|
||
}
|
||
#endif
|
||
|
||
alpha *= dissolveValue;
|
||
#if !defined(NB_DEPTH_SHADOW_PASS)
|
||
#if defined(_DISSOLVE_RAMP)
|
||
{
|
||
// half rampRange = (dissolveValueBeforeSoftStep - _Dissolve_Vec2.x)*_Dissolve_Vec2.y;
|
||
half rampRange = dissolveValueBeforeSoftStep;
|
||
rampRange = rampRange * _DissolveRampMap_ST.x +_DissolveRampMap_ST.z;
|
||
|
||
half4 rampSample ;
|
||
#if defined(_DISSOLVE_RAMP_MAP)
|
||
rampSample = SampleTexture2DWithWrapFlags(_DissolveRampMap,half2(rampRange,0.5),FLAG_BIT_WRAPMODE_DISSOLVE_RAMPMAP);
|
||
#else
|
||
int dissolveRampColorCount = _DissolveRampCount & 0xFFFF;
|
||
|
||
int dissolveRampAlphaCount = _DissolveRampCount >> 16;
|
||
|
||
const int rampWrapMode = CheckLocalWrapFlags(FLAG_BIT_WRAPMODE_DISSOLVE_RAMPMAP);
|
||
if (rampWrapMode == 0 || rampWrapMode == 2)
|
||
{
|
||
rampRange = frac(rampRange);
|
||
}
|
||
else
|
||
{
|
||
rampRange = saturate(rampRange);
|
||
}
|
||
|
||
|
||
rampSample.rgb = SamplePackedGradientColor(_DissolveRampColor0, _DissolveRampColor1, _DissolveRampColor2, _DissolveRampColor3, _DissolveRampColor4, _DissolveRampColor5, dissolveRampColorCount, rampRange);
|
||
rampSample.a = SamplePackedGradientAlpha(_DissolveRampAlpha0, _DissolveRampAlpha1, _DissolveRampAlpha2, dissolveRampAlphaCount, rampRange);
|
||
#endif
|
||
|
||
if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_DISSOLVE_RAMP_MULITPLY))
|
||
{
|
||
result = result * lerp(1,rampSample.rgb*_DissolveRampColor.rgb,rampSample.a*_DissolveRampColor.a);
|
||
}
|
||
else
|
||
{
|
||
result = lerp(result,rampSample.rgb*_DissolveRampColor.rgb,rampSample.a*_DissolveRampColor.a);
|
||
}
|
||
}
|
||
#endif
|
||
|
||
|
||
|
||
if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_DISSOLVE_LINE_MASK))
|
||
{
|
||
half lineMask = dissolveValueBeforeSoftStep;//SmoothStep要优化
|
||
lineMask = saturate(NB_Remap01(lineMask,_Dissolve_Vec2.x-_Dissolve_Vec2.y,_Dissolve_Vec2 + _Dissolve_Vec2.y));
|
||
lineMask = 1- lineMask;
|
||
|
||
result = lerp(result,_DissolveLineColor.rgb,lineMask*_DissolveLineColor.a);
|
||
}
|
||
#endif
|
||
//
|
||
|
||
|
||
#endif
|
||
|
||
//颜色渐变
|
||
#ifdef _COLORMAPBLEND
|
||
#if defined(_NOISEMAP)
|
||
colorBlendMap_uv += cum_noise * _ColorBlendVec.x; //加入扭曲效果
|
||
#endif
|
||
half4 colorBlend = SampleTexture2DWithWrapFlags(_ColorBlendMap,colorBlendMap_uv,FLAG_BIT_WRAPMODE_COLORBLENDMAP);
|
||
colorBlend.rgb = colorBlend.rgb * _ColorBlendColor.rgb;
|
||
colorBlend.a = lerp(1,colorBlend.a*_ColorBlendColor.a,_ColorBlendVec.z);
|
||
if (CheckLocalFlags(FLAG_BIT_PARTICLE_COLOR_BLEND_ALPHA_MULTIPLY_MODE))
|
||
{
|
||
result *= colorBlend.rgb;
|
||
alpha *= colorBlend.a;
|
||
}
|
||
else
|
||
{
|
||
result.rgb = lerp(result.rgb,result.rgb * colorBlend.rgb,colorBlend.a);
|
||
}
|
||
#endif
|
||
|
||
//遮罩部分
|
||
#if defined(_MASKMAP_ON)
|
||
|
||
#if defined(_NOISEMAP)
|
||
MaskMapuv += cum_noise * _MaskDistortion_intensity; //加入扭曲效果
|
||
#endif
|
||
|
||
half mask1 = 1;
|
||
if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_MASKMAP_GRADIENT))
|
||
{
|
||
const int maskMapWrapMode = CheckLocalWrapFlags(FLAG_BIT_WRAPMODE_MASKMAP);
|
||
half maskMapTimeValue;
|
||
if (maskMapWrapMode == 0 || maskMapWrapMode == 2)
|
||
{
|
||
maskMapTimeValue = frac(MaskMapuv.x);
|
||
}
|
||
else
|
||
{
|
||
maskMapTimeValue = saturate(MaskMapuv.x);
|
||
}
|
||
|
||
int maskMapAlphaCount = _MaskMapGradientCount;
|
||
mask1 = SamplePackedGradientAlpha(_MaskMapGradientFloat0, _MaskMapGradientFloat1, _MaskMapGradientFloat2, maskMapAlphaCount, maskMapTimeValue);
|
||
}
|
||
else
|
||
{
|
||
half4 maskmap1Sample = SampleTexture2DWithWrapFlags(_MaskMap, MaskMapuv,FLAG_BIT_WRAPMODE_MASKMAP);
|
||
mask1 = GetColorChannel(maskmap1Sample,FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP1);
|
||
|
||
}
|
||
|
||
#if defined(_MASKMAP2_ON)
|
||
{
|
||
half mask2 = 1;
|
||
if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_MASKMAP_2_GRADIENT))
|
||
{
|
||
const int maskMap2WrapMode = CheckLocalWrapFlags(FLAG_BIT_WRAPMODE_MASKMAP2);
|
||
half maskMap2TimeValue;
|
||
if (maskMap2WrapMode == 0 || maskMap2WrapMode == 3)
|
||
{
|
||
maskMap2TimeValue = frac(MaskMapuv2.y);
|
||
}
|
||
else
|
||
{
|
||
maskMap2TimeValue = saturate(MaskMapuv2.y);
|
||
}
|
||
|
||
int maskMap2AlphaCount = _MaskMap2GradientCount;
|
||
mask2 = SamplePackedGradientAlpha(_MaskMap2GradientFloat0, _MaskMap2GradientFloat1, _MaskMap2GradientFloat2, maskMap2AlphaCount, maskMap2TimeValue);
|
||
}
|
||
else
|
||
{
|
||
half4 maskMap2Sample = SampleTexture2DWithWrapFlags(_MaskMap2, MaskMapuv2,FLAG_BIT_WRAPMODE_MASKMAP2);
|
||
mask2 = GetColorChannel(maskMap2Sample,FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP2);
|
||
}
|
||
mask1 *= mask2;
|
||
}
|
||
#endif
|
||
|
||
#if defined(_MASKMAP3_ON)
|
||
{
|
||
half mask3 = 1;
|
||
if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_MASKMAP_3_GRADIENT))
|
||
{
|
||
const int maskMap3WrapMode = CheckLocalWrapFlags(FLAG_BIT_WRAPMODE_MASKMAP3);
|
||
half maskMap3TimeValue;
|
||
if (maskMap3WrapMode == 0 || maskMap3WrapMode == 2)
|
||
{
|
||
maskMap3TimeValue = frac(MaskMapuv3.x);
|
||
}
|
||
else
|
||
{
|
||
maskMap3TimeValue = saturate(MaskMapuv3.x);
|
||
}
|
||
|
||
int maskMap3AlphaCount = _MaskMap3GradientCount;
|
||
mask3 = SamplePackedGradientAlpha(_MaskMap3GradientFloat0, _MaskMap3GradientFloat1, _MaskMap3GradientFloat2, maskMap3AlphaCount, maskMap3TimeValue);
|
||
}
|
||
else
|
||
{
|
||
half4 maskMap3Sample = SampleTexture2DWithWrapFlags(_MaskMap3, MaskMapuv3,FLAG_BIT_WRAPMODE_MASKMAP3);
|
||
mask3 = GetColorChannel(maskMap3Sample,FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP3);
|
||
}
|
||
mask1 *= mask3;
|
||
}
|
||
#endif
|
||
|
||
#ifdef _PROGRAM_NOISE_ACTIVE
|
||
mask1 = BlendPNoise(_W9ParticleShaderPNoiseBlendFlag,FLAG_BIT_PNOISE_BLEND_POS_0_MASK,mask1,programNoise,_MaskPNoiseBlendOpacity);
|
||
#endif
|
||
|
||
|
||
if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_MASK_REFINE))
|
||
{
|
||
mask1 = pow(mask1,_MaskRefineVec.x);
|
||
mask1 = mask1 * _MaskRefineVec.y;
|
||
mask1 += _MaskRefineVec.z;
|
||
}
|
||
|
||
mask1 = lerp(1,mask1,_MaskMapVec.x);
|
||
mask1 = saturate(mask1);
|
||
|
||
#ifdef NB_DEBUG_MASK
|
||
return MakeParticleFragmentOutput(half4(mask1.rrr,1));
|
||
#endif
|
||
|
||
|
||
alpha *= mask1; //mask边缘
|
||
#endif
|
||
|
||
//菲涅
|
||
|
||
#if !defined(NB_DEPTH_SHADOW_PASS)
|
||
#if defined(_FRESNEL)
|
||
{
|
||
half fresnelValue = 0;
|
||
if(!ignoreFresnel())
|
||
{
|
||
half3 fresnelDir = normalize(viewDirWS+_FresnelRotation.rgb);
|
||
|
||
half dotNV = dot(fresnelDir,input.normalWSAndAnimBlend.xyz) ;
|
||
fresnelValue = dotNV;
|
||
|
||
|
||
_FresnelUnit.x += GetCustomData(_W9ParticleCustomDataFlag0,FLAGBIT_POS_0_CUSTOMDATA_FRESNEL_OFFSET,0,input.VaryingsP_Custom1,input.VaryingsP_Custom2);;
|
||
|
||
// half fresnelHardness = - _FresnelUnit.w*0.5 +0.5;
|
||
fresnelValue = NB_Remap(fresnelValue,_FresnelUnit.x,_FresnelUnit.x + 1.01 - _FresnelUnit.w,0,1);
|
||
UNITY_BRANCH
|
||
if(!CheckLocalFlags(FLAG_BIT_PARTICLE_FRESNEL_INVERT_ON))
|
||
{
|
||
fresnelValue = 1- fresnelValue;
|
||
}
|
||
fresnelValue = pow(fresnelValue,_FresnelUnit.y);
|
||
|
||
|
||
// fresnelValue = smoothstep(0.5-fresnelHardness,0.5+fresnelHardness,fresnelValue);
|
||
}
|
||
|
||
#ifdef NB_DEBUG_FRESNEL
|
||
return MakeParticleFragmentOutput(half4(fresnelValue.rrr*_FresnelUnit.z,1));
|
||
#endif
|
||
|
||
|
||
UNITY_BRANCH
|
||
if(CheckLocalFlags(FLAG_BIT_PARTICLE_FRESNEL_FADE_ON))
|
||
{
|
||
fresnelValue *= alpha;
|
||
alpha = lerp(alpha,fresnelValue,_FresnelUnit.z);
|
||
}
|
||
else
|
||
{
|
||
float fresnelColorIntensity = fresnelValue*_FresnelColor.a*_FresnelUnit.z;
|
||
|
||
result = lerp(result,_FresnelColor.rgb,fresnelColorIntensity);
|
||
if (!CheckLocalFlags(FLAG_BIT_PARTICLE_FRESNEL_COLOR_AFFETCT_BY_ALPHA))
|
||
{
|
||
alpha = max(alpha,fresnelColorIntensity);//颜色要不要不被主贴图Alpha影响呢?
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
#endif
|
||
|
||
#if defined(_DEPTH_OUTLINE)
|
||
{
|
||
half depthOutlineValue = 1- SoftParticles(_DepthOutline_Vec.x, _DepthOutline_Vec.y, sceneZ,thisZ);
|
||
depthOutlineValue *= _DepthOutline_Color.a;
|
||
half3 originResult = result;
|
||
//如何在一个pass里,完美的给出两个颜色的Fade。这个问题,没有想清楚。
|
||
result = lerp(result,_DepthOutline_Color.rgb,clamp(depthOutlineValue*3,0,1));
|
||
result = lerp(result,originResult,clamp(alpha-depthOutlineValue,0,1));
|
||
alpha = max(alpha,depthOutlineValue);
|
||
|
||
}
|
||
#endif
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
//可以看https://www.cyanilux.com/tutorials/depth/
|
||
// float4 projectedPosition = input.positionNDC;
|
||
// float thisZ1 = LinearEyeDepth(projectedPosition.z / projectedPosition.w, _ZBufferParams);
|
||
|
||
|
||
#if defined(_DISTANCE_FADE)
|
||
{
|
||
half fade = DepthFactor(thisZ, _Fade.x, _Fade.y);
|
||
alpha *= fade;
|
||
}
|
||
#endif
|
||
|
||
|
||
#if defined(_SOFTPARTICLES_ON)
|
||
|
||
half softAlpha = SoftParticles(SOFT_PARTICLE_NEAR_FADE, SOFT_PARTICLE_INV_FADE_DISTANCE, sceneZ,thisZ);
|
||
alpha *= softAlpha;
|
||
|
||
#endif
|
||
#endif
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
//和粒子颜色信息运算。雨轩:乘顶点色。
|
||
if(!CheckLocalFlags1(FLAG_BIT_PARTICLE_1_IGNORE_VERTEX_COLOR))
|
||
{
|
||
#if !defined(NB_DEPTH_SHADOW_PASS)
|
||
result *= input.color.rgb;
|
||
#endif
|
||
alpha *= input.color.a;
|
||
}
|
||
// 程序额外的颜色
|
||
#if !defined(NB_DEPTH_SHADOW_PASS)
|
||
result *= _ColorA.rgb;
|
||
#endif
|
||
alpha *= _ColorA.a;
|
||
// // alpha *= _ColorA * 0.8;
|
||
|
||
|
||
#if !defined(NB_DEPTH_SHADOW_PASS)
|
||
#ifdef _DEPTH_DECAL
|
||
alpha *= decalAlpha;
|
||
#endif
|
||
|
||
half3 beforeFogResult = result;
|
||
result = MixFog(result,input.positionWS.w);
|
||
result = lerp(beforeFogResult, result, _fogintensity);
|
||
|
||
UNITY_BRANCH
|
||
if (!CheckLocalFlags(FLAG_BIT_PARTICLE_COLOR_ADJUSTMENT_ONLY_AFFECT_MAINTEX))
|
||
{
|
||
ColorAdjustment(result,alpha,input.VaryingsP_Custom1,input.VaryingsP_Custom2);
|
||
}
|
||
|
||
UNITY_FLATTEN
|
||
if(CheckLocalFlags(FLAG_BIT_PARTICLE_LINEARTOGAMMA_ON))
|
||
{
|
||
result.rgb = LinearToGammaSpace(result.rgb);
|
||
}
|
||
#endif
|
||
|
||
|
||
alpha *= _AlphaAll;
|
||
alpha = saturate(alpha);
|
||
|
||
#if defined(NB_DEPTH_ONLY_PASS)
|
||
#ifdef _ALPHATEST_ON
|
||
clip(alpha - _Cutoff);
|
||
#endif
|
||
return MakeParticleFragmentOutput(half4(input.clipPos.z, 0, 0, 0));
|
||
#elif defined(NB_SHADOW_CASTER_PASS)
|
||
#ifdef _ALPHATEST_ON
|
||
clip(alpha - _Cutoff);
|
||
#endif
|
||
|
||
if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_TRANSPARENT_MODE))
|
||
{
|
||
if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_TRANSPARENT_SHADOW_DITHER))
|
||
{
|
||
clip(NBShadowDitherMaskClip(input.clipPos, alpha));
|
||
}
|
||
else
|
||
{
|
||
clip(alpha - 0.5);
|
||
}
|
||
}
|
||
|
||
return MakeParticleFragmentOutput(0);
|
||
#endif
|
||
|
||
half alphaStrength = alpha;
|
||
#if defined (_ALPHAPREMULTIPLY_ON) || defined(_ALPHAMODULATE_ON)
|
||
result *= alpha;
|
||
#ifdef _ALPHAPREMULTIPLY_ON
|
||
alpha *= _AdditiveToPreMultiplyAlphaLerp;
|
||
#endif
|
||
#endif
|
||
|
||
|
||
#ifdef _SCREEN_DISTORT_MODE
|
||
|
||
//在这里可以进行Alpha的修改
|
||
half screenDistortAlpha = alphaStrength * screenDistort_Noise.z;
|
||
if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_SCREEN_DISTORT_ALPHA_REFINE))
|
||
{
|
||
screenDistortAlpha = pow(screenDistortAlpha,_ScreenDistortAlphaPow);
|
||
screenDistortAlpha *= _ScreenDistortAlphaMulti;
|
||
screenDistortAlpha += _ScreenDistortAlphaAdd;
|
||
}
|
||
#ifdef _DEFERRED_DISTORT_PASS
|
||
result = half3(screenDistort_Noise.xy,1.0);
|
||
alpha = screenDistortAlpha * _ScreenDistortIntensity;
|
||
#endif
|
||
|
||
#ifdef _CAMERA_OPAQUE_DISTORT_PASS
|
||
float2 screenDistortUV = screenUV;
|
||
screenDistortUV = screenDistortUV + screenDistort_Noise.xy * screenDistortAlpha * _ScreenDistortIntensity;
|
||
half4 screenTexDistortSample = SampleTexture2DWithWrapFlags(_CameraOpaqueTexture,screenDistortUV,FLAG_BIT_WRAPMODE_BASEMAP);
|
||
result = screenTexDistortSample.xyz;
|
||
alpha = 1;
|
||
// alpha = screenTexDistortSample.a;
|
||
#endif
|
||
|
||
#endif
|
||
|
||
|
||
|
||
|
||
half4 color = half4(result, alpha);
|
||
|
||
|
||
|
||
#ifdef _ALPHATEST_ON
|
||
clip(color.a - _Cutoff);
|
||
|
||
#endif
|
||
|
||
color = min(color,1000);
|
||
|
||
|
||
return MakeParticleFragmentOutput(color);
|
||
}
|
||
|
||
#endif
|