#ifndef NBSHADER_INPUT #define NBSHADER_INPUT #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl" #include "NBShaderFlags.hlsl" #if defined(_PROGRAM_NOISE) && (defined(_PROGRAM_NOISE_SIMPLE) || defined(_PROGRAM_NOISE_VORONOI)) #define _PROGRAM_NOISE_ACTIVE #endif //---------------particleInput------------------- CBUFFER_START(UnityPerMaterial) float4 _SoftParticleFadeParams; float4 _CameraFadeParams; // #ifdef _INTERSECT_ON float _IntersectRadius; half4 _IntersectColor; // #endif half _AdditiveToPreMultiplyAlphaLerp; half _Saturability; half _HueShift; half _Contrast; half3 _ContrastMidColor; half4 _BaseMapColorRefine; half _AlphaAll; float4 _BaseMap_ST; float4 _BaseMap_AnimationSheetBlend_ST;//20240826 暂时只是给AnimationSheetHelper用。 half _AnimationSheetHelperBlendIntensity; float4 _MaskMap_ST; half4 _BaseColor; half4 _BaseBackColor; half _BaseColorIntensityForTimeline; half4 _EmissionMap_ST; half4 _NoiseMap_ST; half4 _NoiseMaskMap_ST; half4 _DistortionDirection; half4 _BaseColorAddSubDiff; half _fogintensity; half _Emi_Distortion_intensity; half _BaseMapUVRotation; half _BaseMapUVRotationSpeed; float _MaskMapUVRotation; float _NoiseMapUVRotation; half _ScreenDistortIntensity; half _ScreenDistortAlphaPow; half _ScreenDistortAlphaAdd; half _ScreenDistortAlphaMulti; half _NoiseIntensity; half _RefractionIOR; half _uvRapSoft; half4 _EmissionMapColor; half _EmissionMapColorIntensity; //--------------光照部分------------- float4 _BumpTex_ST; half _BumpScale; half4 _MaterialInfo; half4 _SpecularColor; //-----------SixWayLight---------- half4 _SixWayInfo; half4 _SixWayEmissionColor; half4 _MatCapColor; half4 _MatCapInfo; half _EdgeFade; half4 _NoiseOffset; half4 _EmissionMapUVOffset; half _EmissionMapUVRotation; half _EmissionSelfAlphaWeight; half _TexDistortion_intensity; // //half _RJ_Distortion_intensity; // half _XianXingCH_UVRota; // half _jingxiangCH_dire; half _MaskDistortion_intensity; half4 _BaseMapMaskMapOffset; half4 _MaskMapOffsetAnition; half4 _MaskMap3OffsetAnition; half4 _MaskMapVec; half4 _MaskRefineVec; int _MaskMapGradientCount; half4 _MaskMapGradientFloat0; half4 _MaskMapGradientFloat1; half4 _MaskMapGradientFloat2; int _MaskMap2GradientCount; half4 _MaskMap2GradientFloat0; half4 _MaskMap2GradientFloat1; half4 _MaskMap2GradientFloat2; int _MaskMap3GradientCount; half4 _MaskMap3GradientFloat0; half4 _MaskMap3GradientFloat1; half4 _MaskMap3GradientFloat2; float4 _PCCenter; float4 _TWParameter; float _TWStrength; float4 _Fade; float _OverrideZValue; float _MaskMapRotationSpeed; half _FrePower; half _FresnelInOutSlider; half4 _FresnelRotation; half _FresnelSelfAlphaWeight; half4 _FresnelUnit; half4 _FresnelUnit2; half4 _DepthOutline_Vec; half4 _DepthOutline_Color; half4 _FresnelColor; half4 _ColorA; float4 _ClipRect; float4 _CylinderMatrix0; float4 _CylinderMatrix1; float4 _CylinderMatrix2; float4 _CylinderMatrix3; half4 _Color; float4 _UI_MainTex_ST;//在UI中,RawImage组件的功能和正常的TexST不一致,所以这里使用另外传的方式。 float4 _MainTex_Reverse_ST; half _Cutoff; float4 _MaskMap2_ST; float4 _MaskMap3_ST; float time; half _FresnelFadeDistance; half4 LB_RT; half4 _Dissolve; half4 _DissolveMap_ST; half4 _DissolveOffsetRotateDistort; half4 _DissolveMaskMap_ST; half _DissolveMaskMode; half4 _DissolveLineColor; half4 _DissolveRampColor; float4 _DissolveVoronoi_Vec; half4 _DissolveVoronoi_Vec2; float4 _DissolveVoronoi_Vec3; float4 _DissolveVoronoi_Vec4; half4 _DissolveRampMap_ST; half4 _Dissolve_Vec2; half _ProgramNoise_Rotate; half4 _SharedUV_ST; half4 _SharedUV_Vec; // half _SharedUV_Distort_Intensity; half4 _ColorBlendMap_ST; float4 _ColorBlendMapOffset; half4 _ColorBlendColor; half4 _ColorBlendVec; half4 _RampColor0; half4 _RampColor1; half4 _RampColor2; half4 _RampColor3; half4 _RampColor4; half4 _RampColor5; half4 _RampColorAlpha0; half4 _RampColorAlpha1; half4 _RampColorAlpha2; uint _RampColorCount; half4 _RampColorBlendColor; float4 _RampColorMapOffset; half4 _RampColorMap_ST; half4 _DissolveRampColor0; half4 _DissolveRampColor1; half4 _DissolveRampColor2; half4 _DissolveRampColor3; half4 _DissolveRampColor4; half4 _DissolveRampColor5; half4 _DissolveRampAlpha0; half4 _DissolveRampAlpha1; half4 _DissolveRampAlpha2; uint _DissolveRampCount; half3 _VertexOffset_Vec; half3 _VertexOffset_CustomDir; half4 _VertexOffset_Map_ST; half4 _VertexOffset_MaskMap_ST; half3 _VertexOffset_MaskMap_Vec; float _VAT_Toggle; float _VATMode; float _ImportScale; float _TyFlowVATSubMode; float _DeformingSkin; float _SkinBoneCount; float _RGBAEncoded; float _RGBAHalf; float _LinearToGamma; float _VATIncludesNormals; float _AffectsShadows; float _Frame; float _Frames; float _FrameInterpolation; float _Loop; float _InterpolateLoop; float _Autoplay; float _AutoplaySpeed; half _ParallaxMapping_Intensity; half4 _ParallaxMapping_Map_ST; half4 _ParallaxMapping_Vec; half _WorldSpaceUVModeSelector; half _ObjectSpaceUVModeSelector; uint _W9ParticleShaderFlags; uint _W9ParticleShaderFlags1; uint _W9ParticleShaderWrapFlags; uint _W9ParticleCustomDataFlag0; uint _W9ParticleCustomDataFlag1; uint _W9ParticleCustomDataFlag2; uint _W9ParticleCustomDataFlag3; uint _UVModeFlag0; uint _UVModeFlagType0; uint _W9ParticleShaderColorChannelFlag; uint _W9ParticleShaderPNoiseBlendFlag; half _ProgramNoiseBaseBlendOpacity; half _MaskPNoiseBlendOpacity; half _DissolvePNoiseBlendOpacity; half _DistortPNoiseBlendOpacity; float4x4 _CustomLocalTransformLocalToWorld; float4x4 _CustomLocalTransformWorldToLocal; CBUFFER_END #define NB_SHADER_FLAGS _W9ParticleShaderFlags #define NB_SHADER_FLAGS1 _W9ParticleShaderFlags1 #define NB_SHADER_WRAP_FLAGS _W9ParticleShaderWrapFlags #define NB_SHADER_COLOR_CHANNEL_FLAG _W9ParticleShaderColorChannelFlag #define NB_SHADER_PNOISE_BLEND_FLAG _W9ParticleShaderPNoiseBlendFlag #define NB_CUSTOM_DATA_FLAG_0 _W9ParticleCustomDataFlag0 #define NB_CUSTOM_DATA_FLAG_1 _W9ParticleCustomDataFlag1 #define NB_CUSTOM_DATA_FLAG_2 _W9ParticleCustomDataFlag2 #define NB_CUSTOM_DATA_FLAG_3 _W9ParticleCustomDataFlag3 float3x3 GetCustomLocalToWorld3x3() { return (float3x3)_CustomLocalTransformLocalToWorld; } float3x3 GetCustomWorldToLocal3x3() { return (float3x3)_CustomLocalTransformWorldToLocal; } float3 TransformWorldToObject_NB(float3 positionWS) { #ifdef _CUSTOM_LOCAL_TRANSFORM return mul(_CustomLocalTransformWorldToLocal, float4(positionWS, 1.0)).xyz; #else return mul(unity_WorldToObject, float4(positionWS, 1.0)).xyz; #endif } float3 TransformObjectToWorld_NB(float3 positionOS) { #ifdef _CUSTOM_LOCAL_TRANSFORM return mul(_CustomLocalTransformLocalToWorld, float4(positionOS, 1.0)).xyz; #else return mul(unity_ObjectToWorld, float4(positionOS, 1.0)).xyz; #endif } float4 TransformObjectToHClip_NB(float3 positionOS) { #ifdef _CUSTOM_LOCAL_TRANSFORM return TransformWorldToHClip(TransformObjectToWorld_NB(positionOS)); #else return TransformObjectToHClip(positionOS); #endif } float3 TransformWorldToObjectDir_NB(float3 dirWS, bool doNormalize = true) { #ifdef _CUSTOM_LOCAL_TRANSFORM float3 dirOS = mul(GetCustomWorldToLocal3x3(), dirWS); return doNormalize ? SafeNormalize(dirOS) : dirOS; #else float3 dirOS = mul((float3x3)unity_WorldToObject, dirWS); return doNormalize ? SafeNormalize(dirOS) : dirOS; #endif } float3 TransformWorldToObjectNormal_NB(float3 normalWS) { #ifdef _CUSTOM_LOCAL_TRANSFORM return SafeNormalize(mul(normalWS, GetCustomLocalToWorld3x3())); #else return SafeNormalize(mul(normalWS, (float3x3)unity_ObjectToWorld)); #endif } float3 TransformObjectToWorldDir_NB(float3 dirOS, bool doNormalize = true) { #ifdef _CUSTOM_LOCAL_TRANSFORM float3 dirWS = mul(GetCustomLocalToWorld3x3(), dirOS); return doNormalize ? SafeNormalize(dirWS) : dirWS; #else return TransformObjectToWorldDir(dirOS, doNormalize); #endif } float3 TransformObjectToWorldNormal_NB(float3 normalOS) { #ifdef _CUSTOM_LOCAL_TRANSFORM return SafeNormalize(mul(normalOS, GetCustomWorldToLocal3x3())); #else return TransformObjectToWorldNormal(normalOS); #endif } real3 NBTransformWorldToTangentDir(real3 dirWS, real3x3 tangentToWorld, bool doNormalize = false) { // Unity 2021 / URP 12 does not expose TransformWorldToTangentDir. real3 result = mul(tangentToWorld, dirWS); return doNormalize ? SafeNormalize(result) : result; } float3 GetCustomLocalSpaceNormalizeViewDir(float3 positionOS) { #ifdef _CUSTOM_LOCAL_TRANSFORM float3 viewDir = TransformWorldToObject_NB(_WorldSpaceCameraPos) - positionOS; return SafeNormalize(viewDir); #else return GetObjectSpaceNormalizeViewDir(positionOS); #endif } float GetCustomLocalOddNegativeScale() { #ifdef _CUSTOM_LOCAL_TRANSFORM return determinant(GetCustomLocalToWorld3x3()) < 0.0 ? -1.0 : 1.0; #else return GetOddNegativeScale(); #endif } bool CheckLocalFlags(uint bits) { return (_W9ParticleShaderFlags&bits) != 0; } bool CheckLocalFlags1(uint bits) { return (_W9ParticleShaderFlags1&bits) != 0; } int CheckLocalWrapFlags(uint bits) { bool bit0 = (_W9ParticleShaderWrapFlags&bits) != 0; bool bit1 = (_W9ParticleShaderWrapFlags&(bits<<16)) != 0; if(!bit0 && !bit1) { return 0; } else if(bit0 && !bit1) { return 1; } else if(!bit0 && bit1) { return 2; } else if(bit0 && bit1) { return 3; } else { return -1; } } SamplerState sampler_linear_repeat; SamplerState sampler_linear_clamp; SamplerState sampler_linear_RepeatU_ClampV; SamplerState sampler_linear_ClampU_RepeatV; SamplerState sampler_point_clamp; half4 SampleTexture2D(Texture2D tex,float2 uv,SAMPLER( textureSampler),bool sampleLOD = false,int lod = 0) { if (sampleLOD) { return SAMPLE_TEXTURE2D_LOD(tex,textureSampler,uv,lod); } else { return SAMPLE_TEXTURE2D(tex,textureSampler,uv); } } half4 SampleTexture2DWithWrapFlags(Texture2D tex,float2 uv,uint bits,bool sampleLOD = false,int lod = 0) { #ifdef _CAMERA_OPAQUE_DISTORT_PASS int wrapMode; if (bits == FLAG_BIT_WRAPMODE_BASEMAP) { wrapMode = 1; } else { wrapMode = CheckLocalWrapFlags(bits); } #else const int wrapMode = CheckLocalWrapFlags(bits); #endif #if defined(SHADER_TARGET_GLSL) ||defined (SHADER_API_GLES)|| defined(SHADER_API_GLES3) switch (wrapMode) { case 0: uv = frac(uv);break; case 1: uv = saturate(uv);break; case 2: uv = float2(frac(uv.x),saturate(uv.y));break; case 3: uv = float2(saturate(uv.x),frac(uv.y));break; } if (sampleLOD) { return SAMPLE_TEXTURE2D_LOD(tex,sampler_linear_clamp,uv,lod);//SamplerWillIgnore;需要在GLSL相关平台打包时强制设置为Clamp循环。 } else { return SAMPLE_TEXTURE2D(tex,sampler_linear_clamp,uv);//SamplerWillIgnore;需要在GLSL相关平台打包时强制设置为Clamp循环。 } #else switch (wrapMode) { case 0: return SampleTexture2D(tex,uv,sampler_linear_repeat,sampleLOD,lod); break; case 1: return SampleTexture2D(tex,uv,sampler_linear_clamp,sampleLOD,lod); case 2: return SampleTexture2D(tex,uv,sampler_linear_RepeatU_ClampV,sampleLOD,lod); break; case 3: return SampleTexture2D(tex,uv,sampler_linear_ClampU_RepeatV,sampleLOD,lod); break; default: return SampleTexture2D(tex,uv,sampler_linear_repeat,sampleLOD,lod); break; } #endif } half GetColorChannel(half4 color, int bitPos) { uint bits = _W9ParticleShaderColorChannelFlag >> bitPos; bits = bits & 3; if (bits == 0) return color.x; if (bits == 1) return color.y; if (bits == 2) return color.z; return color.w; } samplerCUBE _FresnelHDRITex; sampler2D _MainTex; #define SOFT_PARTICLE_NEAR_FADE _SoftParticleFadeParams.x //�궨��SOFT_PARTICLE_NEAR_FADE ��Ϊ_SoftParticleFadeParams���Ե�x����~ #define SOFT_PARTICLE_INV_FADE_DISTANCE _SoftParticleFadeParams.y #define CAMERA_NEAR_FADE _CameraFadeParams.x #define CAMERA_INV_FADE_DISTANCE _CameraFadeParams.y Texture2D _BaseMap; Texture2D _NoiseMap; Texture2D _NoiseMaskMap; Texture2D _EmissionMap; Texture2D _MaskMap; Texture2D _MaskMap2; Texture2D _MaskMap3; #ifdef _NORMALMAP Texture2D _BumpTex; #endif #ifdef _FX_LIGHT_MODE_SIX_WAY Texture2D _RigRTBk; Texture2D _RigLBtF; Texture2D _SixWayEmissionRamp; #endif #ifdef _CAMERA_OPAQUE_DISTORT_PASS Texture2D _CameraOpaqueTexture; #endif #ifdef _MATCAP Texture2D _MatCapTex; #endif // Pre-multiplied alpha helper #if defined(_ALPHAPREMULTIPLY_ON) //if( blend: One OneMinusSrcAlpha) #define ALBEDO_MUL albedo #else #define ALBEDO_MUL albedo.a #endif #ifdef SOFT_UI_FRAME sampler2D _SoftUIFrameMask; // half4 LB_RT; #endif #ifdef _DISSOLVE Texture2D _DissolveMap; Texture2D _DissolveMaskMap; Texture2D _DissolveRampMap; #endif # ifdef _COLORMAPBLEND Texture2D _ColorBlendMap; #endif #ifdef _COLOR_RAMP Texture2D _RampColorMap; #endif Texture2D _VATTex; float4 _VATTex_TexelSize; half4 tex2D_TryLinearizeWithoutAlphaFX(sampler2D tex, float2 uv) { half4 outColor = 0; #if defined(PARTICLE)//UI下使用ParticleBase不需要做 Gamma2Linear 转换 UNITY_FLATTEN if(CheckLocalFlags(FLAG_BIT_PARTICLE_UIEFFECT_ON)) { outColor = tex2D(tex, uv); } else { outColor = TryLinearizeWithoutAlpha(tex2D(tex, uv)); } #endif return outColor; } // // Color blending fragment function float4 MixParticleColor(float4 baseColor, float4 particleColor, float4 colorAddSubDiff) { #if defined(_COLOROVERLAY_ON) // Overlay blend float4 output = baseColor; output.rgb = lerp(1 - 2 * (1 - baseColor.rgb) * (1 - particleColor.rgb), 2 * baseColor.rgb * particleColor.rgb, step(baseColor.rgb, 0.5)); output.a *= particleColor.a; return output; #elif defined(_COLORCOLOR_ON) // Color blend half3 aHSL = RgbToHsv(baseColor.rgb); half3 bHSL = RgbToHsv(particleColor.rgb); half3 rHSL = half3(bHSL.x, bHSL.y, aHSL.z); return half4(HsvToRgb(rHSL), baseColor.a * particleColor.a); #elif defined(_COLORADDSUBDIFF_ON) // Additive, Subtractive and Difference blends based on 'colorAddSubDiff' float4 output = baseColor; output.rgb = baseColor.rgb + particleColor.rgb * colorAddSubDiff.x; output.rgb = lerp(output.rgb, abs(output.rgb), colorAddSubDiff.y); output.a *= particleColor.a; return output; #else // Default to Multiply blend return baseColor * particleColor; #endif } // Soft particles - returns alpha value for fading particles based on the depth to the background pixel float SoftParticles(float near, float far, float sceneZ,float thisZ) { float fade = 1; if (near > 0.0 || far > 0.0) { // fade = saturate(far * ((sceneZ - near) - thisZ)); float dist = sceneZ - thisZ; fade = NB_Remap(dist, near,far,0,1); } return fade; } // Camera fade - returns alpha value for fading particles based on camera distance half CameraFade(float near, float far, float thisZ) { return saturate((thisZ - near) * far); } //相交位置渐变功能 half4 Intersect(float IntersectRadius,half4 IntersectColor,float sceneZ,float thisZ) { half fade = sceneZ - thisZ; fade =1- NB_Remap(fade,0,IntersectRadius,0,1); half4 c = 0; c.rgb = IntersectColor.rgb; c.a = fade*IntersectColor.a; return c; } //遮挡穿透显示功能。 half OccludeOpacity(half preAlpha,half _OccludeOpacity,half sceneZ,half thisZ) { half fakeZtest = step(thisZ,sceneZ); return lerp(preAlpha*_OccludeOpacity,preAlpha,fakeZtest); } // Sample a texture and do blending for texture sheet animation if needed half4 BlendTexture(sampler2D _Texture, float2 uv, float3 blendUv) { half4 color = tex2D_TryLinearizeWithoutAlphaFX(_Texture, uv); half4 color2; #ifdef _FLIPBOOKBLENDING_ON color2 = tex2D_TryLinearizeWithoutAlphaFX(_Texture, blendUv.xy); color = lerp(color, color2, blendUv.z); #endif // if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_ANIMATION_SHEET_HELPER)) // { // color2 = tex2D_TryLinearizeWithoutAlphaFX(_Texture, blendUv.xy); // color = lerp(color, color2, blendUv.z); // } return color; } half4 BlendTexture(Texture2D _Texture, float2 uv, float3 blendUv,uint bits) { half4 color = SampleTexture2DWithWrapFlags(_Texture,uv,bits); half4 color2; #ifdef _FLIPBOOKBLENDING_ON color2 = SampleTexture2DWithWrapFlags(_Texture,blendUv.xy,bits); color = lerp(color, color2, blendUv.z); #endif // if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_ANIMATION_SHEET_HELPER)) // { // color2 = SampleTexture2DWithWrapFlags(_Texture, blendUv.xy,bits); // color = lerp(color, color2, blendUv.z); // } return color; } float2 UVOffsetAnimaiton(float2 UV,half2 OffsetSpeed) { float2 newUV = float2(OffsetSpeed.x*time+UV.x,OffsetSpeed.y*time+UV.y); return newUV; } // 采样噪波 half4 SampleNoise(half4 NoiseOffset, Texture2D _Texture,float2 UV, half3 wordPos) { float2 UV2 = float2(NoiseOffset.x * time + UV.x, NoiseOffset.y * time + UV.y); //_Time.y half4 color = SampleTexture2DWithWrapFlags(_Texture, UV2 ,FLAG_BIT_WRAPMODE_NOISEMAP); // color.xy *= color.a; return color; } // // 替换颜色 // half3 ReplaceColor_float(float3 In, float3 From, float3 To, float Range, float Fuzziness) // { // float Distance = distance(From, In); // half3 Out = lerp(To, In, saturate((Distance - Range) / max(Fuzziness, 0.001))); //e-f? 0.00001 // return Out; // } //漩涡 圆形区域内变形。圆圈中心处的像素会旋转指定角度;圆圈中其他像素的旋转会随着相对于中心距离的变化而减小,在圆圈边缘处减小为零 float2 UTwirl(float2 UV, float2 Center, float Strength) { float2 delta = UV - Center; float angle = Strength * length(delta); float x = cos(angle) * delta.x - sin(angle) * delta.y; float y = sin(angle) * delta.x + cos(angle) * delta.y; return float2(x + Center.x , y + Center.y ); } //Fresnel half4 Unity_FresnelEffect(float3 Normal, float3 ViewDir, float Power, float Dire,half fresnelPos) { // half aa = saturate(dot(normalize(Normal), (ViewDir))); half aa = dot(normalize(Normal), (ViewDir)); aa = (aa+1)*0.5; aa = NB_Remap(aa,fresnelPos,1,0,1); aa = lerp(aa, (1 - aa), Dire); half Out = pow( aa, Power); return Out; } half3 Rotation(half3 normalizedDirection,half3 rotation) { half4 Dir = half4(normalizedDirection,1); float4x4 M_RotationX = float4x4( 1,0,0,0, 0,cos(rotation.x),sin(rotation.x),0, 0,-sin(rotation.x),cos(rotation.x),0, 0,0,0,1 ); float4x4 M_RotationY = float4x4( cos(rotation.y),0,sin(rotation.y),0, 0,1,0,0, -sin(rotation.y),0,cos(rotation.y),0, 0,0,0,1 ); float4x4 M_RotationZ = float4x4( cos(rotation.z),sin(rotation.z),0,0, -sin(rotation.z),cos(rotation.z),0,0, 0,0,1,0, 0,0,0,1 ); return mul(M_RotationZ,mul(M_RotationY,mul(M_RotationX,Dir))); } //----------------公告板功能-----------------// half3 BillBoard(float3 camPos, float3 vertexPos, int billboardType, int _ReverseZ) { float3 Z = normalize(mul(unity_WorldToObject, float4(_WorldSpaceCameraPos,1))); if(_ReverseZ == 1) { Z *= -1; } Z.y *= billboardType; float3 Y = float3(0,1,0); float3 X = normalize(cross(Z,Y)); Y = normalize(cross(X,Z)); float4x4 M = float4x4( X.x, Y.x, Z.x, 0, X.y, Y.y, Z.y, 0, X.z, Y.z, Z.z, 0, 0,0,0,1 ); float3 newPos = mul(M, vertexPos); return newPos; } half3 BillBoardNormal(float3 camPos, float3 vertexPos, int billboardType, int _ReverseZ) { float3 Z = normalize(mul(unity_WorldToObject, float4(_WorldSpaceCameraPos,1))); if(_ReverseZ == 1) { Z *= -1; } Z.y *= billboardType; float3 Y = float3(0,1,0); float3 X = normalize(cross(Y,Z)); Y = normalize(cross(X,Z)); float4x4 M = float4x4( X.x, Y.x, Z.x, 0, X.y, Y.y, Z.y, 0, X.z, Y.z, Z.z, 0, 0,0,0,1 ); float3 newPos = -mul(M, vertexPos); return newPos; } float2 ParticleUVCommonProcess(float2 originUVAfterTwirlPolar,float4 scaleTilling,float2 offset = float2(0,0),float rotation = 0,float2 rotationCenter = float2(0.5,0.5)) { float2 uv = originUVAfterTwirlPolar; uv = Rotate_Radians_float(uv,rotationCenter,rotation); uv = uv*scaleTilling.xy + scaleTilling.zw; uv = UVOffsetAnimaiton(uv,offset); return uv; } struct ParticleUVs { float2 mainTexUV; float2 specUV; float2 animBlendUV; float2 maskMapUV; float2 maskMap2UV; float2 maskMap3UV; float2 emissionUV; float2 dissolve_uv; float2 dissolve_mask_uv; float2 dissolve_noise1_UV; float2 dissolve_noise2_UV; float2 colorBlendUV; float2 noiseMapUV; float2 noiseMaskMapUV; float2 bumpTexUV; float2 colorRampMapUV; float2 sharedUV; }; float2 getPosUVByPosUVMode(float3 pos,half posUVMode) { switch ((int)posUVMode) { case 0: return pos.xy; case 1: return pos.xz; case 2: return pos.yz; default: return pos.xz; } } BaseUVs ProcessBaseUVs(float4 meshTexcoord0, float2 specialUVInTexcoord3,float4 VaryingsP_Custom1,float4 VaryingsP_Custom2,float3 postionOS,float3 positionWS,float2 screenUV) { //UV2的内容在外边就决定好。 float2 defaultUVChannel = meshTexcoord0.xy; float2 specialUVChannel = meshTexcoord0.zw; #if _FLIPBOOKBLENDING_ON if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM) & CheckLocalFlags1(FLAG_BIT_PARTICLE_1_USE_TEXCOORD2)) { specialUVChannel = specialUVInTexcoord3; } #else if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_UV_FROM_MESH)) { //Mesh条件下开启使用特殊UV通道的情况 if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_USE_TEXCOORD1)) { specialUVChannel = VaryingsP_Custom1.xy; } if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_USE_TEXCOORD2)) { specialUVChannel = VaryingsP_Custom2.xy; } } else { //只有在粒子系统下开启特殊通道的情况,会在面板层引导合并相关内容。UI/Mesh不开启特殊通道没有意义。 specialUVChannel = meshTexcoord0.zw; } #endif if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_UIEFFECT_SPRITE_MODE)) { defaultUVChannel = defaultUVChannel*_MainTex_Reverse_ST.xy +_MainTex_Reverse_ST.zw; } //TODO:补写MeshUV的实现 float2 cylinderUV = meshTexcoord0.xy; if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_CYLINDER_CORDINATE)) { float4x4 _CylinderUVMatrix = float4x4(_CylinderMatrix0,_CylinderMatrix1,_CylinderMatrix2,_CylinderMatrix3); postionOS = mul(_CylinderUVMatrix,float4(postionOS,1)); cylinderUV = CylinderCoordinate(postionOS); } float2 UVAfterTwirlPolar = defaultUVChannel; if(CheckLocalFlags(FLAG_BIT_PARTICLE_UTWIRL_ON)) { UVAfterTwirlPolar = UTwirl(defaultUVChannel,_TWParameter.xy, _TWStrength); } if(CheckLocalFlags(FLAG_BIT_PARTICLE_POLARCOORDINATES_ON)) { float2 UVAfterTwirl = UVAfterTwirlPolar; UVAfterTwirlPolar = PolarCoordinates(UVAfterTwirlPolar,_PCCenter.xy); UVAfterTwirlPolar = lerp(UVAfterTwirl,UVAfterTwirlPolar,_PCCenter.z); } BaseUVs baseUVs = (BaseUVs)0; baseUVs.defaultUVChannel = defaultUVChannel; baseUVs.specialUVChannel = specialUVChannel; baseUVs.uvAfterTwirlPolar = UVAfterTwirlPolar; baseUVs.cylinderUV = cylinderUV; baseUVs.screenUV = screenUV; baseUVs.worldPosUV = getPosUVByPosUVMode(positionWS,_WorldSpaceUVModeSelector); baseUVs.objectPosUV = getPosUVByPosUVMode(postionOS,_ObjectSpaceUVModeSelector); baseUVs.sharedUV = defaultUVChannel; float2 sharedUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_SHAREDUV,baseUVs); _SharedUV_Vec.z += time * _SharedUV_Vec.w; sharedUV = Rotate_Radians_float(sharedUV, half2(0.5, 0.5), _SharedUV_Vec.z); //主贴图旋转 sharedUV.x += GetCustomData(_W9ParticleCustomDataFlag3,FLAGBIT_POS_3_CUSTOMDATA_SHARED_UV_OFFSET_X,0,VaryingsP_Custom1,VaryingsP_Custom2); sharedUV.y += GetCustomData(_W9ParticleCustomDataFlag3,FLAGBIT_POS_3_CUSTOMDATA_SHARED_UV_OFFSET_Y,0,VaryingsP_Custom1,VaryingsP_Custom2); sharedUV = sharedUV *_SharedUV_ST.xy +_SharedUV_ST.zw ; //主帖图UV重复和偏移 sharedUV = UVOffsetAnimaiton(sharedUV,_SharedUV_Vec.xy); baseUVs.sharedUV = sharedUV; baseUVs.mainTexUV = defaultUVChannel; float2 baseMapUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_MAINTEX,baseUVs); float2 mainTexUV = 0; _BaseMapUVRotation += time * _BaseMapUVRotationSpeed; baseMapUV = Rotate_Radians_float(baseMapUV, half2(0.5, 0.5), _BaseMapUVRotation); //主贴图旋转 UNITY_BRANCH if(CheckLocalFlags(FLAG_BIT_PARTICLE_UIEFFECT_ON) & !CheckLocalFlags1(FLAG_BIT_PARTICLE_1_UIEFFECT_BASEMAP_MODE)) { if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_UIEFFECT_SPRITE_MODE)) { float2 originUV = meshTexcoord0.xy;//精灵主贴图不调整。 mainTexUV = originUV*_UI_MainTex_ST.xy+_UI_MainTex_ST.zw; } else { mainTexUV = baseMapUV*_UI_MainTex_ST.xy+_UI_MainTex_ST.zw; } } else { baseMapUV.x += GetCustomData(_W9ParticleCustomDataFlag0,FLAGBIT_POS_0_CUSTOMDATA_MAINTEX_OFFSET_X,0,VaryingsP_Custom1,VaryingsP_Custom2); baseMapUV.y += GetCustomData(_W9ParticleCustomDataFlag0,FLAGBIT_POS_0_CUSTOMDATA_MAINTEX_OFFSET_Y,0,VaryingsP_Custom1,VaryingsP_Custom2); mainTexUV = TRANSFORM_TEX(baseMapUV, _BaseMap); //主帖图UV重复和偏移 } mainTexUV = UVOffsetAnimaiton(mainTexUV,_BaseMapMaskMapOffset.xy); baseUVs.mainTexUV = mainTexUV; return baseUVs; } void ParticleProcessUV(inout ParticleUVs particleUVs,float4 meshTexcoord0,float4 VaryingsP_Custom1,float4 VaryingsP_Custom2,BaseUVs baseUVs) { particleUVs.specUV = baseUVs.specialUVChannel; particleUVs.mainTexUV = baseUVs.mainTexUV; //------------------------------------------------- #ifdef _FLIPBOOKBLENDING_ON //开启序列帧融合 if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_ANIMATION_SHEET_HELPER)) { // float2 baseMapUV = (baseUVs.mainTexUV - _BaseMap_ST.zw)/_BaseMap_ST.xy; //走AnimationSheetHelper脚本的情况,永远和baseMap同步。 particleUVs.animBlendUV = meshTexcoord0.xy*_BaseMap_AnimationSheetBlend_ST.xy+_BaseMap_AnimationSheetBlend_ST.zw; } else { //走粒子的情况 particleUVs.animBlendUV = meshTexcoord0.zw; } #endif #if defined(_NORMALMAP) float2 bumpTexUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_BUMPTEX,baseUVs); bumpTexUV = TRANSFORM_TEX(bumpTexUV, _BumpTex); particleUVs.bumpTexUV = bumpTexUV; #endif #if defined(_MASKMAP_ON) float2 MaskMapuv = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_MASKMAP,baseUVs); UNITY_BRANCH if(CheckLocalFlags(FLAG_BIT_PARTILCE_MASKMAPROTATIONANIMATION_ON)) { _MaskMapUVRotation += time * _MaskMapRotationSpeed; } MaskMapuv= Rotate_Radians_float(MaskMapuv, half2(0.5, 0.5), _MaskMapUVRotation); MaskMapuv = TRANSFORM_TEX(MaskMapuv, _MaskMap); MaskMapuv.x += GetCustomData(_W9ParticleCustomDataFlag0,FLAGBIT_POS_0_CUSTOMDATA_MASK_OFFSET_X,0,VaryingsP_Custom1,VaryingsP_Custom2); MaskMapuv.y += GetCustomData(_W9ParticleCustomDataFlag0,FLAGBIT_POS_0_CUSTOMDATA_MASK_OFFSET_Y,0,VaryingsP_Custom1,VaryingsP_Custom2); MaskMapuv = UVOffsetAnimaiton(MaskMapuv,_MaskMapOffsetAnition.xy); particleUVs.maskMapUV = MaskMapuv; #if defined(_MASKMAP2_ON) { float2 maskMap2UV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_MASKMAP_2,baseUVs); maskMap2UV = Rotate_Radians_float(maskMap2UV,half2(0.5,0.5),_MaskMapVec.y); maskMap2UV = maskMap2UV * _MaskMap2_ST.xy + _MaskMap2_ST.zw; maskMap2UV = UVOffsetAnimaiton(maskMap2UV,_MaskMapOffsetAnition.zw); particleUVs.maskMap2UV = maskMap2UV; } #endif #if defined(_MASKMAP3_ON) { float2 maskMap3UV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_MASKMAP_3,baseUVs); maskMap3UV = Rotate_Radians_float(maskMap3UV,half2(0.5,0.5),_MaskMapVec.z); maskMap3UV = maskMap3UV* _MaskMap3_ST.xy + _MaskMap3_ST.zw; maskMap3UV = UVOffsetAnimaiton(maskMap3UV,_MaskMap3OffsetAnition.xy); particleUVs.maskMap3UV = maskMap3UV; } #endif #endif #if defined(_EMISSION) float2 emissionUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_EMISSION_MAP,baseUVs); emissionUV.x += GetCustomData(_W9ParticleCustomDataFlag3,FLAGBIT_POS_3_CUSTOMDATA_EMISSION_OFFSET_X,0,VaryingsP_Custom1,VaryingsP_Custom2); emissionUV.y += GetCustomData(_W9ParticleCustomDataFlag3,FLAGBIT_POS_3_CUSTOMDATA_EMISSION_OFFSET_Y,0,VaryingsP_Custom1,VaryingsP_Custom2); particleUVs.emissionUV = ParticleUVCommonProcess(emissionUV,_EmissionMap_ST,_EmissionMapUVOffset.xy,_EmissionMapUVRotation); #endif #if defined(_DISSOLVE) _DissolveMap_ST.z += GetCustomData(_W9ParticleCustomDataFlag1,FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_OFFSET_X,0,VaryingsP_Custom1,VaryingsP_Custom2); _DissolveMap_ST.w += GetCustomData(_W9ParticleCustomDataFlag1,FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_OFFSET_Y,0,VaryingsP_Custom1,VaryingsP_Custom2); float2 dissolveUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_DISSOLVE_MAP,baseUVs); particleUVs.dissolve_uv = ParticleUVCommonProcess(dissolveUV,_DissolveMap_ST,_DissolveOffsetRotateDistort.xy,_DissolveOffsetRotateDistort.z); #if defined(_DISSOLVE_MASK) { float2 dissolveMaskUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_DISSOLVE_MASK_MAP,baseUVs); particleUVs.dissolve_mask_uv = ParticleUVCommonProcess(dissolveMaskUV,_DissolveMaskMap_ST,float2(0,0),_DissolveOffsetRotateDistort.z); } #endif #endif #ifdef _PROGRAM_NOISE_ACTIVE float2 programNoiseUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_PROGRAM_NOISE,baseUVs); programNoiseUV = Rotate_Radians_float(programNoiseUV,half2(0.5,0.5),_ProgramNoise_Rotate); #if defined(_PROGRAM_NOISE_SIMPLE) { _DissolveVoronoi_Vec4.x += GetCustomData(_W9ParticleCustomDataFlag2,FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE1_OFFSET_X,0,VaryingsP_Custom1,VaryingsP_Custom2); _DissolveVoronoi_Vec4.y += GetCustomData(_W9ParticleCustomDataFlag2,FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE1_OFFSET_Y,0,VaryingsP_Custom1,VaryingsP_Custom2); particleUVs.dissolve_noise1_UV = programNoiseUV * _DissolveVoronoi_Vec.xy + _DissolveVoronoi_Vec4.xy + time*_DissolveVoronoi_Vec3.xy; } #endif #if defined(_PROGRAM_NOISE_VORONOI) { _DissolveVoronoi_Vec4.z += GetCustomData(_W9ParticleCustomDataFlag2,FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE2_OFFSET_X,0,VaryingsP_Custom1,VaryingsP_Custom2); _DissolveVoronoi_Vec4.w += GetCustomData(_W9ParticleCustomDataFlag2,FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE2_OFFSET_Y,0,VaryingsP_Custom1,VaryingsP_Custom2); particleUVs.dissolve_noise2_UV = programNoiseUV * _DissolveVoronoi_Vec.zw + _DissolveVoronoi_Vec4.zw + time*_DissolveVoronoi_Vec3.zw; } #endif #endif #ifdef _COLORMAPBLEND float2 colorBlendUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_COLOR_BLEND_MAP,baseUVs); colorBlendUV.x += GetCustomData(_W9ParticleCustomDataFlag3,FLAGBIT_POS_3_CUSTOMDATA_COLOR_BLEND_OFFSET_X,0,VaryingsP_Custom1,VaryingsP_Custom2); colorBlendUV.y += GetCustomData(_W9ParticleCustomDataFlag3,FLAGBIT_POS_3_CUSTOMDATA_COLOR_BLEND_OFFSET_Y,0,VaryingsP_Custom1,VaryingsP_Custom2); particleUVs.colorBlendUV = ParticleUVCommonProcess(colorBlendUV,_ColorBlendMap_ST,_ColorBlendMapOffset.xy,_ColorBlendVec.w); #endif #ifdef _COLOR_RAMP float2 colorRampMapUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_RAMP_COLOR_MAP,baseUVs); particleUVs.colorRampMapUV = ParticleUVCommonProcess(colorRampMapUV,_RampColorMap_ST,_RampColorMapOffset.xy,_RampColorMapOffset.w); #endif half cum_noise = 0; //TODO #if defined(_NOISEMAP) //和ParticleUVCommonProcess相比,此处没有UV动画,NoiseMap的UV流动在最终的SampleNoise中进行 float2 noiseMapUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_NOISE_MAP,baseUVs); particleUVs.noiseMapUV = ParticleUVCommonProcess(noiseMapUV,_NoiseMap_ST,half2(0,0),_NoiseMapUVRotation); #if defined(_NOISE_MASKMAP) { float2 noiseMaskMapUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_NOISE_MASK_MAP,baseUVs); particleUVs.noiseMaskMapUV = ParticleUVCommonProcess(noiseMaskMapUV,_NoiseMaskMap_ST,half2(0,0),0); } #endif #endif } #if defined(_VERTEX_OFFSET) Texture2D _VertexOffset_Map; #if defined(_VERTEX_OFFSET_MASKMAP) Texture2D _VertexOffset_MaskMap; #endif // half3 _VertexOffset_Vec; // half3 _VertexOffset_CustomDir; // half4 _VertexOffset_Map_ST; half3 VetexOffset(half3 positionOS,half2 originUV,half2 originMaskUV,half3 normalOS,out half3 offsetOS) { half2 uv = TRANSFORM_TEX(originUV,_VertexOffset_Map); uv = UVOffsetAnimaiton(uv,_VertexOffset_Vec.xy); // half vertexOffsetSample = tex2Dlod(_VertexOffset_Map,half4(uv,0,0)); half vertexOffsetSample = SampleTexture2DWithWrapFlags(_VertexOffset_Map,uv,FLAG_BIT_WRAPMODE_VERTEXOFFSETMAP,true,0); // UNITY_BRANCH // if(CheckLocalWrapFlags(FLAG_BIT_WRAPMODE_VERTEXOFFSETMAP)) // { // vertexOffsetSample = SAMPLE_TEXTURE2D_LOD(_VertexOffset_Map,sampler_linear_clamp,uv,0); // } // else // { // vertexOffsetSample = SAMPLE_TEXTURE2D_LOD(_VertexOffset_Map,sampler_linear_repeat,uv,0); // } if (!CheckLocalFlags1(FLAG_BIT_PARTICLE_1_VERTEXOFFSET_START_FROM_ZERO)) { vertexOffsetSample = vertexOffsetSample*2-1; } half vertexOffsetMask = 1; #if defined(_VERTEX_OFFSET_MASKMAP) { half2 maskUV = TRANSFORM_TEX(originMaskUV,_VertexOffset_MaskMap); maskUV = UVOffsetAnimaiton(maskUV,_VertexOffset_MaskMap_Vec.xy); half vertexOffsetMaskSample = SampleTexture2DWithWrapFlags(_VertexOffset_MaskMap,maskUV,FLAG_BIT_WRAPMODE_VERTEXOFFSET_MASKMAP,true,0); vertexOffsetMask = lerp(1,vertexOffsetMaskSample,_VertexOffset_MaskMap_Vec.z); } #endif UNITY_BRANCH if(CheckLocalFlags(FLAG_BIT_PARTICLE_VERTEX_OFFSET_NORMAL_DIR)) { offsetOS = normalOS*_VertexOffset_Vec.z*vertexOffsetSample*vertexOffsetMask; } else { offsetOS = _VertexOffset_CustomDir*_VertexOffset_Vec.z*vertexOffsetSample*vertexOffsetMask; } return positionOS + offsetOS; } #endif //向UV横向两边的色散。 #if defined(_CHROMATIC_ABERRATION) half4 DistortionChoraticaberrat(Texture2D baseTexture,half2 originUV, half2 uvAfterNoise,half ChoraticaberratIntensity,uint bits) { half2 delta = half2(originUV.x *2-1,0); if(CheckLocalFlags(FLAG_BIT_PARTICLE_NOISE_CHORATICABERRAT_WITH_NOISE)) { half2 NoiseIntensity = uvAfterNoise - originUV; // half noiseXIntensity = abs(NoiseIntensity.x); // delta *= ChoraticaberratIntensity*noiseXIntensity; delta = NoiseIntensity*ChoraticaberratIntensity*10; } else { delta *= ChoraticaberratIntensity; } half2 ra = SampleTexture2DWithWrapFlags(baseTexture,uvAfterNoise,bits).xw; ra.r *= ra.y; half2 ga = SampleTexture2DWithWrapFlags(baseTexture,uvAfterNoise - delta,bits).yw; ga.r *= ga.y; half2 ba = SampleTexture2DWithWrapFlags(baseTexture,uvAfterNoise - delta*2,bits).zw; ba.r *= ba.y; return half4(ra.r,ga.r,ba.r,clamp(ra.y*0.5+ga.y*0.5+ba.y*0.5,0,1)); } #endif bool needSceneDepth() { #if defined(_DEPTH_DECAL) || defined(_SOFTPARTICLES_ON) || defined(_DEPTH_OUTLINE) return true; #endif return false; } bool needEyeDepth() { #if defined(_SOFTPARTICLES_ON) || defined(_DEPTH_OUTLINE) || defined(_DISTANCE_FADE) return true; #endif return false; } bool needPositionVS() { #if defined(_MATCAP) return true; #endif if (unity_OrthoParams.w == 1) { return true; } return false; } bool ignoreFresnel() { #if defined(PARTICLE_BACKFACE_PASS) return true; #endif return false; } float3 CustomRefract(float3 incident, float3 normal, float eta) { float N_dot_I = dot(normal, incident); float k = 1.0f - eta * eta * (1.0f - N_dot_I * N_dot_I); // 检查全内反射 if (k < 0.0) { // 全内反射时返回零向量 return float3(0, 0, 0); } else { // 计算折射方向 return eta * incident - (eta * N_dot_I + sqrt(k)) * normal; } } Texture2D _ParallaxMapping_Map; half2 ParallaxMappingSimple(half2 texCoords, half3 viewDir) { float height = SampleTexture2DWithWrapFlags(_ParallaxMapping_Map,texCoords,FLAG_BIT_WRAPMODE_PARALLAXMAPPINGMAP).r; height *= _ParallaxMapping_Intensity; viewDir = normalize(viewDir); viewDir.xy /= (viewDir.z); texCoords -= viewDir.xy * height; return texCoords; } half2 ParallaxMappingPeelDepth(half2 texCoords, half3 viewDir) { const float minLayers = 2; const float maxLayers = 32; float numLayers = lerp(maxLayers, minLayers, abs(dot(half3(0.0, 0.0, 1.0), viewDir)));//视线越垂直于表面,层数越少,反之越多。 float layerDepth = 1/numLayers; float currentLayerDepth = 0; // viewDir.xy/=viewDir.z; half2 p = viewDir.xy*_ParallaxMapping_Intensity; half2 deltaTexcoord = p/numLayers; half2 currentTexcoords = texCoords; float currentMapDepthValue = SampleTexture2DWithWrapFlags(_ParallaxMapping_Map,currentTexcoords,FLAG_BIT_WRAPMODE_PARALLAXMAPPINGMAP).r; [loop] while (currentLayerDepth < currentMapDepthValue ) { currentTexcoords -= deltaTexcoord; currentMapDepthValue = SampleTexture2DWithWrapFlags(_ParallaxMapping_Map,currentTexcoords,FLAG_BIT_WRAPMODE_PARALLAXMAPPINGMAP).r; currentLayerDepth += layerDepth; } return currentTexcoords; } float2 ParallaxOcclusionMapping(float2 texCoords, float3 viewDir) { texCoords = texCoords * _ParallaxMapping_Map_ST + _ParallaxMapping_Map_ST.zw; // number of depth layers // const float minLayers = 10; // const float maxLayers = 10; const float minLayers = _ParallaxMapping_Vec.x; const float maxLayers = _ParallaxMapping_Vec.y; float numLayers = lerp(maxLayers, minLayers, abs(dot(half3(0.0, 0.0, 1.0), viewDir))); // calculate the size of each layer float layerDepth = 1.0 / numLayers; // depth of current layer float currentLayerDepth = 0.0; // the amount to shift the texture coordinates per layer (from vector P) float2 P = viewDir.xy / viewDir.z * _ParallaxMapping_Intensity; float2 deltaTexCoords = P / numLayers; // get initial values float2 currentTexCoords = texCoords; float currentDepthMapValue = SampleTexture2DWithWrapFlags(_ParallaxMapping_Map, currentTexCoords,FLAG_BIT_WRAPMODE_PARALLAXMAPPINGMAP).r; currentLayerDepth = clamp(currentLayerDepth,0,1); int i = 0; [loop] while(currentLayerDepth < currentDepthMapValue && i= timeArr[arrCount - 1]) { // return int2(arrCount - 1, arrCount); // 大于等于最大值 // } // 顺序查找第一个大于X的元素索引 [unroll] for (int i = 0; i < arrCount; i++) { if (timeArr[i] > gradientTime) { return int2(i - 1, i); // 返回区间索引 } } return int2(-1, 0); // 理论上不会执行此处 } half GetGradientIndexInterval(half timeArr[6],int arrCount,int2 indexes,half gradientTime) { //超出范围的直接在外面就判断好。 // half smallVal = indexes.x < 0 ? 0:timeArr[indexes.x]; half smallVal = timeArr[indexes.x]; // half bigVal = indexes.y >= arrCount ? 1 : timeArr[indexes.y]; half bigVal = timeArr[indexes.y]; return (gradientTime - smallVal) / (bigVal - smallVal); } half3 GetGradientColorValue(half3 colorArr[6],half timeArr[6], int arrCount,half gradientTime) { if (gradientTime <= timeArr[0]) { return colorArr[0]; } else if (gradientTime >= timeArr[arrCount - 1] ) { return colorArr[arrCount - 1]; } else { int2 indexes = GetGradientIndex(timeArr, arrCount, gradientTime); half interval = GetGradientIndexInterval(timeArr, arrCount, indexes, gradientTime); interval = SmoothStep01(interval); return lerp(colorArr[indexes.x], colorArr[indexes.y], interval); } } half GetGradientAlphaValue(half alphaArr[6],half timeArr[6], int arrCount,half gradientTime) { if (gradientTime <= timeArr[0]) { return alphaArr[0]; } else if (gradientTime >= timeArr[arrCount - 1] ) { return alphaArr[arrCount - 1]; } else { int2 indexes = GetGradientIndex(timeArr, arrCount, gradientTime); half interval = GetGradientIndexInterval(timeArr, arrCount, indexes, gradientTime); interval = SmoothStep01(interval);//TODO:消耗很大,如何避免? half alpha = lerp(alphaArr[indexes.x], alphaArr[indexes.y], interval); alpha *= alpha;//Make Alpha Smoother return alpha ; } } half3 GetPackedGradientColorKey(half4 key0, half4 key1, half4 key2, half4 key3, half4 key4, half4 key5, int index) { if (index <= 0) return key0.rgb; if (index == 1) return key1.rgb; if (index == 2) return key2.rgb; if (index == 3) return key3.rgb; if (index == 4) return key4.rgb; return key5.rgb; } half GetPackedGradientColorTime(half4 key0, half4 key1, half4 key2, half4 key3, half4 key4, half4 key5, int index) { if (index <= 0) return key0.a; if (index == 1) return key1.a; if (index == 2) return key2.a; if (index == 3) return key3.a; if (index == 4) return key4.a; return key5.a; } half GetPackedGradientAlphaKey(half4 pack0, half4 pack1, half4 pack2, int index) { if (index <= 0) return pack0.x; if (index == 1) return pack0.z; if (index == 2) return pack1.x; if (index == 3) return pack1.z; if (index == 4) return pack2.x; return pack2.z; } half GetPackedGradientAlphaTime(half4 pack0, half4 pack1, half4 pack2, int index) { if (index <= 0) return pack0.y; if (index == 1) return pack0.w; if (index == 2) return pack1.y; if (index == 3) return pack1.w; if (index == 4) return pack2.y; return pack2.w; } int2 GetPackedGradientColorIndex(half4 key0, half4 key1, half4 key2, half4 key3, half4 key4, half4 key5, int arrCount, half gradientTime) { int2 indexes = int2(-1, 0); bool found = false; [unroll] for (int i = 0; i < 6; i++) { if (!found && i < arrCount && GetPackedGradientColorTime(key0, key1, key2, key3, key4, key5, i) > gradientTime) { indexes = int2(i - 1, i); found = true; } } return indexes; } int2 GetPackedGradientAlphaIndex(half4 pack0, half4 pack1, half4 pack2, int arrCount, half gradientTime) { int2 indexes = int2(-1, 0); bool found = false; [unroll] for (int i = 0; i < 6; i++) { if (!found && i < arrCount && GetPackedGradientAlphaTime(pack0, pack1, pack2, i) > gradientTime) { indexes = int2(i - 1, i); found = true; } } return indexes; } half3 SamplePackedGradientColor(half4 key0, half4 key1, half4 key2, half4 key3, half4 key4, half4 key5, int arrCount, half gradientTime) { if (gradientTime <= GetPackedGradientColorTime(key0, key1, key2, key3, key4, key5, 0)) { return GetPackedGradientColorKey(key0, key1, key2, key3, key4, key5, 0); } else if (gradientTime >= GetPackedGradientColorTime(key0, key1, key2, key3, key4, key5, arrCount - 1)) { return GetPackedGradientColorKey(key0, key1, key2, key3, key4, key5, arrCount - 1); } else { int2 indexes = GetPackedGradientColorIndex(key0, key1, key2, key3, key4, key5, arrCount, gradientTime); half smallVal = GetPackedGradientColorTime(key0, key1, key2, key3, key4, key5, indexes.x); half bigVal = GetPackedGradientColorTime(key0, key1, key2, key3, key4, key5, indexes.y); half interval = SmoothStep01((gradientTime - smallVal) / (bigVal - smallVal)); return lerp( GetPackedGradientColorKey(key0, key1, key2, key3, key4, key5, indexes.x), GetPackedGradientColorKey(key0, key1, key2, key3, key4, key5, indexes.y), interval); } } half SamplePackedGradientAlpha(half4 pack0, half4 pack1, half4 pack2, int arrCount, half gradientTime) { if (gradientTime <= GetPackedGradientAlphaTime(pack0, pack1, pack2, 0)) { return GetPackedGradientAlphaKey(pack0, pack1, pack2, 0); } else if (gradientTime >= GetPackedGradientAlphaTime(pack0, pack1, pack2, arrCount - 1)) { return GetPackedGradientAlphaKey(pack0, pack1, pack2, arrCount - 1); } else { int2 indexes = GetPackedGradientAlphaIndex(pack0, pack1, pack2, arrCount, gradientTime); half smallVal = GetPackedGradientAlphaTime(pack0, pack1, pack2, indexes.x); half bigVal = GetPackedGradientAlphaTime(pack0, pack1, pack2, indexes.y); half interval = SmoothStep01((gradientTime - smallVal) / (bigVal - smallVal)); half alpha = lerp( GetPackedGradientAlphaKey(pack0, pack1, pack2, indexes.x), GetPackedGradientAlphaKey(pack0, pack1, pack2, indexes.y), interval); alpha *= alpha; return alpha; } } void ColorAdjustment(inout half3 result,inout half alpha,half4 customData1,half4 customData2) { UNITY_BRANCH if(CheckLocalFlags(FLAG_BIT_HUESHIFT_ON)) { half3 hsv = RgbToHsv(result); _HueShift = GetCustomData(_W9ParticleCustomDataFlag0,FLAGBIT_POS_0_CUSTOMDATA_HUESHIFT,_HueShift,customData1,customData2); hsv.r += _HueShift; result = HsvToRgb(hsv); } UNITY_BRANCH if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_MAINTEX_CONTRAST)) { _Contrast = GetCustomData(_W9ParticleCustomDataFlag2,FLAGBIT_POS_2_CUSTOMDATA_MAINTEX_CONTRAST,_Contrast,customData1,customData2); result.rgb = lerp(_ContrastMidColor,result.rgb,_Contrast); } UNITY_BRANCH if(CheckLocalFlags(FLAG_BIT_SATURABILITY_ON)) { half3 resultWB = luminance(result); _Saturability = GetCustomData(_W9ParticleCustomDataFlag1,FLAGBIT_POS_1_CUSTOMDATA_SATURATE,_Saturability,customData1,customData2); result.rgb = lerp(resultWB.rgb, result.rgb, _Saturability); } if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_MAINTEX_COLOR_REFINE)) { half3 colorA = result.rgb*_BaseMapColorRefine.x; half3 colorB = pow(result.rgb,_BaseMapColorRefine.y)*_BaseMapColorRefine.z; result.rgb = lerp(colorA,colorB,_BaseMapColorRefine.w); } if (CheckLocalFlags(FLAG_BIT_PARTICLE_COLOR_MULTI_ALPHA)) { result.rgb *= alpha; } } #endif