【Unity3D】Particle粒子特效或3D物体显示在UGUI上的方案

news2024/12/25 10:23:41

目录

一、RawImage + Camera + RenderTexture方式

(1)扩展知识:实现射线检测RawImage内的3D物体

(2)扩展知识:实现粒子特效显示RawImage上

二、UI摄像机 + Canvas(Screen Space - Camera模式)方式

(1)尝试使用模板测试裁剪粒子特效(失败案例)

(2)传递Mask区域Rect数据进行裁剪粒子特效


一、RawImage + Camera + RenderTexture方式

(1)扩展知识:实现射线检测RawImage内的3D物体

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class SphereTest : MonoBehaviour
{
    //是否忽略UI检测
    public bool ignoreUICheck = false;
    //发送射线的摄像机
    public Camera rayCamera;
    public RectTransform canvasRectTrans;
    public Camera uiCamera;
    public RectTransform rawImageRectTrans;
    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
#if (UNITY_ANDROID || UNITY_IOS) && !UNITY_EDITOR
        if (!ignoreUICheck && EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId))
#else
            if (!ignoreUICheck && EventSystem.current.IsPointerOverGameObject(-1))
#endif
            {
                Debug.Log("点击到UI物体:" + EventSystem.current.currentSelectedGameObject);
            }
            else
            {
                //ScreenPointToRay仅适用于主摄像机的射线(主摄像机即MainCamera 直接渲染到屏幕的)

                //针对RawImage内的3D物体进行射线检测,首先要使用渲染3D物体的摄像机(非主摄像机,它深度会被我们调到比主摄像机低,以及CullingMask剔除掉这层的物体)
                //其次是无法使用ScreenPointToRay检测到的,即使你将3D物体和摄像机都挪到主摄像机相同的位置朝向..

                //使用ViewportPointToRay转用视角发射射线, 获取RawImage视角坐标需要将屏幕点击坐标转RawImage所在Canvas的UI坐标,再转到RawImage空间的视角坐标

                //1.利用API(RectTransformUtility.ScreenPointToLocalPointInRectangle)将屏幕坐标点击位置转化为UGUI坐标
                Vector2 uiPos;
                if (RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRectTrans, Input.mousePosition, uiCamera, out uiPos))
                {
                    //2.转RawImage空间的视角坐标,需知道uiPos相对该空间的位置,以及该空间的宽高
                    //2.1获取RawImage物体的x,y,width,height (位于Canvas空间内的)
                    float width = rawImageRectTrans.rect.width;
                    float height = rawImageRectTrans.rect.height;
                    float x = rawImageRectTrans.localPosition.x - (width * rawImageRectTrans.pivot.x);
                    float y = rawImageRectTrans.localPosition.y - (height * rawImageRectTrans.pivot.y);

                    //2.2根据上述参数求出uiPos位于RawImage空间的相对位置
                    float uiPosXRelativeRawImage = (uiPos.x - x) / width;
                    float uiPosYRelativeRawImage = (uiPos.y - y) / height;
                    Vector2 relativeRawImagePos = new Vector2(uiPosXRelativeRawImage, uiPosYRelativeRawImage);
                    Ray ray = rayCamera.ViewportPointToRay(relativeRawImagePos);
                    RaycastHit raycastHit;
                    if (Physics.Raycast(ray, out raycastHit, 1000))
                    {
                        if (raycastHit.collider.gameObject != null)
                        {
                            Debug.Log("点击3D物体:" + raycastHit.collider.gameObject);
                        }
                    }
                    Debug.DrawLine(ray.origin, raycastHit.point, Color.red, 1);
                }
            }
        }
    }
}

(2)扩展知识:实现粒子特效显示RawImage上

由于粒子特效的ColorMask默认是RGB,没有A(透明通道),而渲染粒子特效的摄像机Background的Alpha是0,就会导致没有A通道的是无法被摄像机渲染出来的(反正测试是这样)

因此我们需要修改粒子特效的Shader,去官网下载对应Unity版本的Shader源码找到对应的shader文件拷贝到我们工程内开始修改。

Unity官方下载_Unity新版_从Unity Hub下载安装 | Unity中国官网

修改如下2个地方,以保证粒子特效渲染于透明层级以及开放RGBA通道渲染

Tags {
    "Queue" = "Transparent"
}

ColorMask RGBA

二、UI摄像机 + Canvas(Screen Space - Camera模式)方式

 

注意ClearFlags是清空所有位于它前面的摄像机缓存到ColorBuffer和DeepBuffer的,位于前面是指深度小于当前摄像机的。

此处是仅清空了深度(Deep Only),背景颜色保持用主摄像机。

选中Canvas,右击创建粒子特效,会帮你默认处理将粒子特效的Layer设置为UI

想让粒子特效显示的层级高于UI的Image则使用如下图控制,大于Canvas的Order即可。

正常显示出粒子特效,但发现没法被Mask组件裁剪,因为Mask裁剪原理是模板测试裁剪,而粒子特效Shader并没有模板测试,也尝试过将模板测试写到粒子特效Shader中,但是观察FrameDebugger发现其渲染是在Mask恢复了模板值为0之后进行的,所以这种依赖模板测试的方式裁剪行不通,具体如下图说明一切。

(1)尝试使用模板测试裁剪粒子特效(失败案例)

 

如果我将粒子特效的模板值改为0去比较,那肯定通过测试,全都会被渲染出来

(2)传递Mask区域Rect数据进行裁剪粒子特效

原理:传递Mask区域的左下角和右上角世界坐标到粒子Shader进行一个是否在(左下角,右上角)区域内判定,若不在则将透明度设置为0,达到裁剪目的。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyMask : MonoBehaviour
{
    public Camera uiCamera;
    public ParticleSystem particle;
    public RectTransform canvasRectTrans;

    private void Start()
    {
        var renderer = particle.GetComponent<ParticleSystemRenderer>();
        Material particleMat = renderer.material;

        //获取Mask裁剪区域四个点坐标
        RectTransform rectTransform = this.gameObject.GetComponent<RectTransform>();
        Vector3[] worldPosArray = new Vector3[4];
        rectTransform.GetWorldCorners(worldPosArray);

        Vector3 lbPos = worldPosArray[0];
        Vector3 rtPos = worldPosArray[2];

        //针对3D物体裁剪(粒子特效也是3D),需传递3D空间坐标(即世界坐标)
        particleMat.SetVector("_CustomClipRect", new Vector4(lbPos.x, lbPos.y, rtPos.x, rtPos.y));

        //注意 若针对UI裁剪,这必须传递UI空间系的坐标,如下注释内容...
        //lbPos = uiCamera.WorldToScreenPoint(lbPos);
        //rtPos = uiCamera.WorldToScreenPoint(rtPos);

        //Vector2 lbLocalPos = Vector2.zero;
        //Vector2 rtLocalPos = Vector2.zero;
        //RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRectTrans, lbPos, uiCamera, out lbLocalPos);
        //RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRectTrans, rtPos, uiCamera, out rtLocalPos);
        
        //particleMat.SetVector("_CustomClipRect", new Vector4(lbLocalPos.x, lbLocalPos.y, rtLocalPos.x, rtLocalPos.y));
    }
}

解释下为什么传递的是世界坐标系的Mask区域,因为Shader使用的是直接将vertex模型坐标系传递到frag,此时frag的worldPosition是精细化的粒子特效模型坐标,而粒子特效位于3D空间下,不属于Canvas空间的,这个模型坐标实际就是世界坐标,因此需要用同样是世界坐标的坐标进行计算。反之,若裁剪的对象是一个UGUI(属于Canvas空间下的)那这个裁剪物体的模型空间就是Canvas空间,需要使用将注释的代码恢复,将坐标一步步转为Canvas空间。 

上面这个解释模型空间就是3D空间的世界坐标感觉有点怪怪的...上面红色那段我只能这么理解它才能进行裁剪。

 粒子特效Shader改动点如下:

Properties
{
    _CustomClipRect("CustomClipRect", vector) = (0,0,0,0)
}
Pass
{
Tags { Queue="Transparent" }

Blend SrcAlpha OneMinusSrcAlpha                        

CGPROGRAM

#include "UnityUI.cginc"

struct appdata_particles
{
    float4 vertex : POSITION;
};

struct VertexOutput
{
    float4 worldPosition : TEXCOORD5;
};

void vertParticleUnlit(appdata_particles v, out VertexOutput o)
{
    o.worldPosition = v.vertex;
}

half4 fragParticleUnlit(VertexOutput IN) : SV_Target
{
    result.a *= UnityGet2DClipping(IN.worldPosition.xy, _CustomClipRect);
}

ENDCG
}

Shader代码:(源码是针对Particles/Standard Unlit修改,注释了很多Pass...)

// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)

Shader "Custom/Standard Unlit"
{
    Properties
    {
        _MainTex("Albedo", 2D) = "white" {}
        _Color("Color", Color) = (1,1,1,1)

        _Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5

        _BumpScale("Scale", Float) = 1.0
        _BumpMap("Normal Map", 2D) = "bump" {}

        _EmissionColor("Color", Color) = (0,0,0)
        _EmissionMap("Emission", 2D) = "white" {}

        _DistortionStrength("Strength", Float) = 1.0
        _DistortionBlend("Blend", Range(0.0, 1.0)) = 0.5

        _SoftParticlesNearFadeDistance("Soft Particles Near Fade", Float) = 0.0
        _SoftParticlesFarFadeDistance("Soft Particles Far Fade", Float) = 1.0
        _CameraNearFadeDistance("Camera Near Fade", Float) = 1.0
        _CameraFarFadeDistance("Camera Far Fade", Float) = 2.0

        _StencilComp("Stencil Comparison", Float) = 8
        _Stencil("Stencil ID", Float) = 0
        _StencilOp("Stencil Operation", Float) = 0
        _StencilWriteMask("Stencil Write Mask", Float) = 255
        _StencilReadMask("Stencil Read Mask", Float) = 255

        _ColorMask("Color Mask", Float) = 15
        _CustomClipRect("CustomClipRect", vector) = (0,0,0,0)

            // Hidden properties
            [HideInInspector] _Mode("__mode", Float) = 0.0
            [HideInInspector] _ColorMode("__colormode", Float) = 0.0
            [HideInInspector] _FlipbookMode("__flipbookmode", Float) = 0.0
            [HideInInspector] _LightingEnabled("__lightingenabled", Float) = 0.0
            [HideInInspector] _DistortionEnabled("__distortionenabled", Float) = 0.0
            [HideInInspector] _EmissionEnabled("__emissionenabled", Float) = 0.0
            [HideInInspector] _BlendOp("__blendop", Float) = 0.0
            [HideInInspector] _SrcBlend("__src", Float) = 1.0
            [HideInInspector] _DstBlend("__dst", Float) = 0.0
            [HideInInspector] _ZWrite("__zw", Float) = 1.0
            [HideInInspector] _Cull("__cull", Float) = 2.0
            [HideInInspector] _SoftParticlesEnabled("__softparticlesenabled", Float) = 0.0
            [HideInInspector] _CameraFadingEnabled("__camerafadingenabled", Float) = 0.0
            [HideInInspector] _SoftParticleFadeParams("__softparticlefadeparams", Vector) = (0,0,0,0)
            [HideInInspector] _CameraFadeParams("__camerafadeparams", Vector) = (0,0,0,0)
            [HideInInspector] _ColorAddSubDiff("__coloraddsubdiff", Vector) = (0,0,0,0)
            [HideInInspector] _DistortionStrengthScaled("__distortionstrengthscaled", Float) = 0.0
    }

        Category
        {
            SubShader
            {
                Tags {
                    "Queue" = "Transparent"
                    "IgnoreProjector" = "True"
                    "RenderType" = "Transparent"                  
                    "PreviewType" = "Plane" 
                    "PerformanceChecks" = "False"             
                }

                BlendOp[_BlendOp]
                Blend[_SrcBlend][_DstBlend]
                ZWrite[_ZWrite]
                Lighting Off
                Cull[_Cull]                
                ColorMask [_ColorMask]     

                Stencil
                {
                    Ref[_Stencil]
                    Comp[_StencilComp]
                    Pass[_StencilOp]
                    ReadMask[_StencilReadMask]
                    WriteMask[_StencilWriteMask]
                }


                GrabPass
                {
                    Tags { "LightMode" = "Always" }
                    "_GrabTexture"
                }

              /*  Pass
                {
                    Name "ShadowCaster"
                    Tags { "LightMode" = "ShadowCaster" }

                    BlendOp Add
                    Blend One Zero
                    ZWrite On
                    Cull Off

                    CGPROGRAM
                    #pragma target 2.5

                    #pragma shader_feature_local _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON
                    #pragma shader_feature_local _ _COLOROVERLAY_ON _COLORCOLOR_ON _COLORADDSUBDIFF_ON
                    #pragma shader_feature_local _REQUIRE_UV2
                    #pragma multi_compile_shadowcaster
                    #pragma multi_compile_instancing
                    #pragma instancing_options procedural:vertInstancingSetup

                    #pragma vertex vertParticleShadowCaster
                    #pragma fragment fragParticleShadowCaster

                    #include "UnityStandardParticleShadow.cginc"
                    ENDCG
                }*/

              /*  Pass
                {
                    Name "SceneSelectionPass"
                    Tags { "LightMode" = "SceneSelectionPass" }

                    BlendOp Add
                    Blend One Zero
                    ZWrite On
                    Cull Off

                    CGPROGRAM
                    #pragma target 2.5

                    #pragma shader_feature_local _ALPHATEST_ON
                    #pragma shader_feature_local _REQUIRE_UV2
                    #pragma multi_compile_instancing
                    #pragma instancing_options procedural:vertInstancingSetup

                    #pragma vertex vertEditorPass
                    #pragma fragment fragSceneHighlightPass

                    #include "UnityStandardParticleEditor.cginc"
                    ENDCG
                }*/

               /* Pass
                {
                    Name "ScenePickingPass"
                    Tags{ "LightMode" = "Picking" }

                    BlendOp Add
                    Blend One Zero
                    ZWrite On
                    Cull Off

                    CGPROGRAM
                    #pragma target 2.5

                    #pragma shader_feature_local _ALPHATEST_ON
                    #pragma shader_feature_local _REQUIRE_UV2
                    #pragma multi_compile_instancing
                    #pragma instancing_options procedural:vertInstancingSetup

                    #pragma vertex vertEditorPass
                    #pragma fragment fragScenePickingPass

                    #include "UnityStandardParticleEditor.cginc"
                    ENDCG
                }*/

                Pass
                {
                    Tags { "LightMode" = "ForwardBase" }

                    Blend SrcAlpha OneMinusSrcAlpha                                        

                    CGPROGRAM
                    #pragma multi_compile __ SOFTPARTICLES_ON
                    #pragma multi_compile_fog
                    #pragma target 2.5

                    #pragma shader_feature_local _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON
                    #pragma shader_feature_local _ _COLOROVERLAY_ON _COLORCOLOR_ON _COLORADDSUBDIFF_ON
                    #pragma shader_feature_local _NORMALMAP
                    #pragma shader_feature _EMISSION
                    #pragma shader_feature_local _FADING_ON
                    #pragma shader_feature_local _REQUIRE_UV2
                    #pragma shader_feature_local EFFECT_BUMP

                    #pragma vertex vertParticleUnlit
                    #pragma fragment fragParticleUnlit
                    #pragma multi_compile_instancing
                    #pragma instancing_options procedural:vertInstancingSetup

                    //#include "UnityStandardParticles.cginc"

                    // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)

#ifndef UNITY_STANDARD_PARTICLES_INCLUDED
#define UNITY_STANDARD_PARTICLES_INCLUDED

#if _REQUIRE_UV2
#define _FLIPBOOK_BLENDING 1
#endif

#if EFFECT_BUMP
#define _DISTORTION_ON 1
#endif

#include "UnityPBSLighting.cginc"
#include "UnityStandardParticleInstancing.cginc"
#include "UnityUI.cginc"

// Particles surface shader has a lot of variants in it, but some of those do not affect
// code generation (i.e. don't have inpact on which Input/SurfaceOutput things are read or written into).
// Surface shader analysis done during import time skips "completely identical" shader variants, so to
// help this process we'll turn off some features that we know are not affecting the inputs/outputs.
//
// If you change the logic of what the below variants do, make sure to not regress code generation though,
// e.g. compare full "show generated code" output of the surface shader before & after the change.
#if defined(SHADER_TARGET_SURFACE_ANALYSIS)
    // All these only alter the color in various ways
    #undef _COLOROVERLAY_ON
    #undef _COLORCOLOR_ON
    #undef _COLORADDSUBDIFF_ON
    #undef _ALPHAMODULATE_ON
    #undef _ALPHATEST_ON

    // For inputs/outputs analysis SoftParticles and Fading are identical; so make sure to only keep one
    // of them ever defined.
    #if defined(SOFTPARTICLES_ON)
        #undef SOFTPARTICLES_ON
        #define _FADING_ON
    #endif
#endif


// Vertex shader input
struct appdata_particles
{
    float4 vertex : POSITION;
    float3 normal : NORMAL;
    fixed4 color : COLOR;
    #if defined(_FLIPBOOK_BLENDING) && !defined(UNITY_PARTICLE_INSTANCING_ENABLED)
    float4 texcoords : TEXCOORD0;
    float texcoordBlend : TEXCOORD1;
    #else
    float2 texcoords : TEXCOORD0;
    #endif
    #if defined(_NORMALMAP)
    float4 tangent : TANGENT;
    #endif
    UNITY_VERTEX_INPUT_INSTANCE_ID
};

                // Surface shader input
                struct Input
                {
                    float4 color : COLOR;
                    float2 texcoord;
                    #if defined(_FLIPBOOK_BLENDING)
                    float3 texcoord2AndBlend;
                    #endif
                    #if defined(SOFTPARTICLES_ON) || defined(_FADING_ON)
                    float4 projectedPosition;
                    #endif
                    #if _DISTORTION_ON
                    float4 grabPassPosition;
                    #endif
                };

                // Non-surface shader v2f structure
                struct VertexOutput
                {
                    float4 vertex : SV_POSITION;
                    float4 color : COLOR;
                    UNITY_FOG_COORDS(0)
                    float2 texcoord : TEXCOORD1;
                    #if defined(_FLIPBOOK_BLENDING)
                    float3 texcoord2AndBlend : TEXCOORD2;
                    #endif
                    #if defined(SOFTPARTICLES_ON) || defined(_FADING_ON)
                    float4 projectedPosition : TEXCOORD3;
                    #endif
                    #if _DISTORTION_ON
                    float4 grabPassPosition : TEXCOORD4;
                    #endif
                    float4 worldPosition : TEXCOORD5;
                    UNITY_VERTEX_OUTPUT_STEREO

                };

                fixed4 readTexture(sampler2D tex, Input IN)
                {
                    fixed4 color = tex2D(tex, IN.texcoord);
                    #ifdef _FLIPBOOK_BLENDING
                    fixed4 color2 = tex2D(tex, IN.texcoord2AndBlend.xy);
                    color = lerp(color, color2, IN.texcoord2AndBlend.z);
                    #endif
                    return color;
                }

                fixed4 readTexture(sampler2D tex, VertexOutput IN)
                {
                    fixed4 color = tex2D(tex, IN.texcoord);
                    #ifdef _FLIPBOOK_BLENDING
                    fixed4 color2 = tex2D(tex, IN.texcoord2AndBlend.xy);
                    color = lerp(color, color2, IN.texcoord2AndBlend.z);
                    #endif
                    return color;
                }

                sampler2D _MainTex;
                float4 _MainTex_ST;
                half4 _Color;
                sampler2D _BumpMap;
                half _BumpScale;
                sampler2D _EmissionMap;
                half3 _EmissionColor;
                sampler2D _MetallicGlossMap;
                half _Metallic;
                half _Glossiness;
                UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
                float4 _SoftParticleFadeParams;
                float4 _CameraFadeParams;
                half _Cutoff;

                #define 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

                #if _DISTORTION_ON
                sampler2D _GrabTexture;
                half _DistortionStrengthScaled;
                half _DistortionBlend;
                #endif

                #if defined (_COLORADDSUBDIFF_ON)
                half4 _ColorAddSubDiff;
                #endif

                #if defined(_COLORCOLOR_ON)
                half3 RGBtoHSV(half3 arg1)
                {
                    half4 K = half4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
                    half4 P = lerp(half4(arg1.bg, K.wz), half4(arg1.gb, K.xy), step(arg1.b, arg1.g));
                    half4 Q = lerp(half4(P.xyw, arg1.r), half4(arg1.r, P.yzx), step(P.x, arg1.r));
                    half D = Q.x - min(Q.w, Q.y);
                    half E = 1e-10;
                    return half3(abs(Q.z + (Q.w - Q.y) / (6.0 * D + E)), D / (Q.x + E), Q.x);
                }

                half3 HSVtoRGB(half3 arg1)
                {
                    half4 K = half4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
                    half3 P = abs(frac(arg1.xxx + K.xyz) * 6.0 - K.www);
                    return arg1.z * lerp(K.xxx, saturate(P - K.xxx), arg1.y);
                }
                #endif

                // Color function
                #if defined(UNITY_PARTICLE_INSTANCING_ENABLED)
                #define vertColor(c) \
                        vertInstancingColor(c);
                #else
                #define vertColor(c)
                #endif

                // Flipbook vertex function
                #if defined(UNITY_PARTICLE_INSTANCING_ENABLED)
                    #if defined(_FLIPBOOK_BLENDING)
                    #define vertTexcoord(v, o) \
                        vertInstancingUVs(v.texcoords.xy, o.texcoord, o.texcoord2AndBlend);
                    #else
                    #define vertTexcoord(v, o) \
                        vertInstancingUVs(v.texcoords.xy, o.texcoord); \
                        o.texcoord = TRANSFORM_TEX(o.texcoord, _MainTex);
                    #endif
                #else
                    #if defined(_FLIPBOOK_BLENDING)
                    #define vertTexcoord(v, o) \
                        o.texcoord = v.texcoords.xy; \
                        o.texcoord2AndBlend.xy = v.texcoords.zw; \
                        o.texcoord2AndBlend.z = v.texcoordBlend;
                    #else
                    #define vertTexcoord(v, o) \
                        o.texcoord = TRANSFORM_TEX(v.texcoords.xy, _MainTex);
                    #endif
                #endif

                // Fading vertex function
                #if defined(SOFTPARTICLES_ON) || defined(_FADING_ON)
                #define vertFading(o) \
                    o.projectedPosition = ComputeScreenPos (clipPosition); \
                    COMPUTE_EYEDEPTH(o.projectedPosition.z);
                #else
                #define vertFading(o)
                #endif

                // Distortion vertex function
                #if _DISTORTION_ON
                #define vertDistortion(o) \
                    o.grabPassPosition = ComputeGrabScreenPos (clipPosition);
                #else
                #define vertDistortion(o)
                #endif

                // Color blending fragment function
                #if defined(_COLOROVERLAY_ON)
                #define fragColorMode(i) \
                    albedo.rgb = lerp(1 - 2 * (1 - albedo.rgb) * (1 - i.color.rgb), 2 * albedo.rgb * i.color.rgb, step(albedo.rgb, 0.5)); \
                    albedo.a *= i.color.a;
                #elif defined(_COLORCOLOR_ON)
                #define fragColorMode(i) \
                    half3 aHSL = RGBtoHSV(albedo.rgb); \
                    half3 bHSL = RGBtoHSV(i.color.rgb); \
                    half3 rHSL = fixed3(bHSL.x, bHSL.y, aHSL.z); \
                    albedo = fixed4(HSVtoRGB(rHSL), albedo.a * i.color.a);
                #elif defined(_COLORADDSUBDIFF_ON)
                #define fragColorMode(i) \
                    albedo.rgb = albedo.rgb + i.color.rgb * _ColorAddSubDiff.x; \
                    albedo.rgb = lerp(albedo.rgb, abs(albedo.rgb), _ColorAddSubDiff.y); \
                    albedo.a *= i.color.a;
                #else
                #define fragColorMode(i) \
                    albedo *= i.color;
                #endif

                // Pre-multiplied alpha helper
                #if defined(_ALPHAPREMULTIPLY_ON)
                #define ALBEDO_MUL albedo
                #else
                #define ALBEDO_MUL albedo.a
                #endif

                // Soft particles fragment function
                #if defined(SOFTPARTICLES_ON) && defined(_FADING_ON)
                #define fragSoftParticles(i) \
                    float softParticlesFade = 1.0f; \
                    if (SOFT_PARTICLE_NEAR_FADE > 0.0 || SOFT_PARTICLE_INV_FADE_DISTANCE > 0.0) \
                    { \
                        float sceneZ = LinearEyeDepth (SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.projectedPosition))); \
                        softParticlesFade = saturate (SOFT_PARTICLE_INV_FADE_DISTANCE * ((sceneZ - SOFT_PARTICLE_NEAR_FADE) - i.projectedPosition.z)); \
                        ALBEDO_MUL *= softParticlesFade; \
                    }
                #else
                #define fragSoftParticles(i) \
                    float softParticlesFade = 1.0f;
                #endif

                // Camera fading fragment function
                #if defined(_FADING_ON)
                #define fragCameraFading(i) \
                    float cameraFade = saturate((i.projectedPosition.z - CAMERA_NEAR_FADE) * CAMERA_INV_FADE_DISTANCE); \
                    ALBEDO_MUL *= cameraFade;
                #else
                #define fragCameraFading(i) \
                    float cameraFade = 1.0f;
                #endif

                #if _DISTORTION_ON
                #define fragDistortion(i) \
                    float4 grabPosUV = UNITY_PROJ_COORD(i.grabPassPosition); \
                    grabPosUV.xy += normal.xy * _DistortionStrengthScaled * albedo.a; \
                    half3 grabPass = tex2Dproj(_GrabTexture, grabPosUV).rgb; \
                    albedo.rgb = lerp(grabPass, albedo.rgb, saturate(albedo.a - _DistortionBlend));
                #else
                #define fragDistortion(i)
                #endif

                float4 _CustomClipRect;

                void vert(inout appdata_particles v, out Input o)
                {
                    UNITY_INITIALIZE_OUTPUT(Input, o);
                    float4 clipPosition = UnityObjectToClipPos(v.vertex);

                    vertColor(v.color);
                    vertTexcoord(v, o);
                    vertFading(o);
                    vertDistortion(o);
                }

                void surf(Input IN, inout SurfaceOutputStandard o)
                {
                    half4 albedo = readTexture(_MainTex, IN);
                    albedo *= _Color;

                    fragColorMode(IN);
                    fragSoftParticles(IN);
                    fragCameraFading(IN);

                    #if defined(_METALLICGLOSSMAP)
                    fixed2 metallicGloss = readTexture(_MetallicGlossMap, IN).ra * fixed2(1.0, _Glossiness);
                    #else
                    fixed2 metallicGloss = fixed2(_Metallic, _Glossiness);
                    #endif

                    #if defined(_NORMALMAP)
                    float3 normal = normalize(UnpackScaleNormal(readTexture(_BumpMap, IN), _BumpScale));
                    #else
                    float3 normal = float3(0,0,1);
                    #endif

                    #if defined(_EMISSION)
                    half3 emission = readTexture(_EmissionMap, IN).rgb * cameraFade * softParticlesFade;
                    #else
                    half3 emission = 0;
                    #endif

                    fragDistortion(IN);

                    o.Albedo = albedo.rgb;
                    #if defined(_NORMALMAP)
                    o.Normal = normal;
                    #endif
                    o.Emission = emission * _EmissionColor;
                    o.Metallic = metallicGloss.r;
                    o.Smoothness = metallicGloss.g;

                    #if defined(_ALPHABLEND_ON) || defined(_ALPHAPREMULTIPLY_ON) || defined(_ALPHAOVERLAY_ON)
                    o.Alpha = albedo.a;
                    #else
                    o.Alpha = 1;
                    #endif

                    #if defined(_ALPHAMODULATE_ON)
                    o.Albedo = lerp(half3(1.0, 1.0, 1.0), albedo.rgb, albedo.a);
                    #endif

                    #if defined(_ALPHATEST_ON)
                    clip(albedo.a - _Cutoff + 0.0001);
                    #endif
                }

                void vertParticleUnlit(appdata_particles v, out VertexOutput o)
                {
                    UNITY_SETUP_INSTANCE_ID(v);

                    UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);

                    o.worldPosition = v.vertex;

                    float4 clipPosition = UnityObjectToClipPos(v.vertex);
                    o.vertex = clipPosition;
                    o.color = v.color;                    

                    vertColor(o.color);
                    vertTexcoord(v, o);
                    vertFading(o);
                    vertDistortion(o);

                    UNITY_TRANSFER_FOG(o, o.vertex);
                }

                half4 fragParticleUnlit(VertexOutput IN) : SV_Target
                {
                    half4 albedo = readTexture(_MainTex, IN);
                    albedo *= _Color;

                    fragColorMode(IN);
                    fragSoftParticles(IN);
                    fragCameraFading(IN);

                    #if defined(_NORMALMAP)
                    float3 normal = normalize(UnpackScaleNormal(readTexture(_BumpMap, IN), _BumpScale));
                    #else
                    float3 normal = float3(0,0,1);
                    #endif

                    #if defined(_EMISSION)
                    half3 emission = readTexture(_EmissionMap, IN).rgb;
                    #else
                    half3 emission = 0;
                    #endif

                    fragDistortion(IN);

                    half4 result = albedo;

                    #if defined(_ALPHAMODULATE_ON)
                    result.rgb = lerp(half3(1.0, 1.0, 1.0), albedo.rgb, albedo.a);
                    #endif

                    result.rgb += emission * _EmissionColor * cameraFade * softParticlesFade;

                    #if !defined(_ALPHABLEND_ON) && !defined(_ALPHAPREMULTIPLY_ON) && !defined(_ALPHAOVERLAY_ON)
                    result.a = 1;
                    #endif

                    result.a *= UnityGet2DClipping(IN.worldPosition.xy, _CustomClipRect);

                    #if defined(_ALPHATEST_ON)
                    clip(albedo.a - _Cutoff + 0.0001);
                    #endif

                    UNITY_APPLY_FOG_COLOR(IN.fogCoord, result, fixed4(0,0,0,0));
                    return result;
                }

                #endif // UNITY_STANDARD_PARTICLES_INCLUDED


                    ENDCG
                }
            }
        }

            Fallback "VertexLit"
            //CustomEditor "StandardParticlesShaderGUI"
}

 测试针对UI(2D物体)的裁剪

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2265229.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

编程新选择:深入了解仓颉语言的优雅与高效

初识仓颉编程语言 仓颉编程语言&#xff08;Cangjie Programming Language&#xff09;是一种现代化的、面向未来的通用编程语言&#xff0c;其设计理念是为了降低编程的门槛&#xff0c;同时提供高度灵活性和表达力的开发体验。这种语言以其简洁优雅的语法和直观的设计理念受…

vue3项目history路由模式部署上线405、刷新404问题(包括部分页面刷新404问题)

一、找不到js模块 解决方法&#xff1a;配置Nginx配置文件&#xff1a; // root /your/program/path/dist root /www/wwwroot/my_manage_backend_v1/dist;二、刷新页面导致404问题(Not found) 经过一系列配置后发现进入页面一切正常&#xff0c;包括路由前进和回退&#xff0…

谷歌开发者工具 - 控制台篇

Chrome DevTools - Console控制台篇 一、官网二、主要用途三、控制台篇1.JavaScript/浏览器消息记录&#xff08;1&#xff09;演示效果 / 两种记录状态&#xff08;2&#xff09;显示导致调用的堆栈轨迹 2.过滤消息&#xff08;1&#xff09;按日志级别过滤&#xff08;2&…

003-aop-切点表达式

spring-aop-切点表达式 spring-aop-pom依赖

【蓝桥杯——物联网设计与开发】基础模块8 - RTC

目录 一、RTC &#xff08;1&#xff09;资源介绍 &#x1f505;简介 &#x1f505;时钟与分频&#xff08;十分重要‼️&#xff09; &#xff08;2&#xff09;STM32CubeMX 软件配置 &#xff08;3&#xff09;代码编写 &#xff08;4&#xff09;实验现象 二、RTC接口…

Web3.0安全开发实践:探索比特币DeFi生态中的PSBT

近年来&#xff0c;部分签名比特币交易&#xff08;PSBT&#xff09;在比特币生态系统中获得了显著关注。随着如Ordinal和基于铭文的资产等创新的兴起&#xff0c;安全的多方签名和复杂交易的需求不断增加&#xff0c;这使得PSBT成为应对比特币生态不断发展中不可或缺的工具。 …

MaxKB基于大语言模型和 RAG的开源知识库问答系统的快速部署教程

1 部署要求 1.1 服务器配置 部署服务器要求&#xff1a; 操作系统&#xff1a;Ubuntu 22.04 / CentOS 7.6 64 位系统CPU/内存&#xff1a;4C/8GB 以上磁盘空间&#xff1a;100GB 1.2 端口要求 在线部署MaxKB需要开通的访问端口说明如下&#xff1a; 端口作用说明22SSH安装…

【VMware虚拟机】安装win10系统教程双机可ping通

目录 1、下载1.1、点击链接下载媒体创建工具&#xff1a;1.2、下载后得到MediaCreationTool_22H2.exe&#xff1a;1.3、获取ISO镜像 2、安装3、显示4、配置网络4.1、配置4.2、排查4.2.1、关闭防火墙4.2.2、增加路由 1、下载 Windows10微软官网下载链接: https://www.microsoft…

AI一键制作圣诞帽头像丨附详细教程

我用AI换上圣诞帽头像啦~&#x1f385; 不管是搞笑表情、宠物头像还是你的自拍&#xff01;&#xff01;都能一键添加圣诞帽元素&#xff0c;毫无违和感&#xff01;&#x1f389; 详细教程在P3、P4&#xff0c;手残党也能轻松搞定&#xff01; 宝子们需要打“need”&#xff0…

活动图的理解和实践

在软件开发和系统设计中&#xff0c;理解系统的工作流程和并发行为是至关重要的。活动图作为一种重要的建模工具&#xff0c;为我们提供了一种直观且有效的方法来描述这些复杂的过程。本文将详细探讨活动图的理解与实践&#xff0c;包括其基本概念、用途、构建方法以及实际应用…

电磁兼容(EMC):一文解读磁芯复合材料——塑磁

目录 01 塑磁的定义 02 塑磁的常见规格型号 03 塑磁材料的优点 04 塑磁的应用 塑磁,也称为注塑磁,是一种将磁性粉末注入到塑料基体中制成的复合磁体材料。以下是塑磁的定义、应用和材料特性的总结: 01 塑磁的定义 塑磁是以塑料为基体,通过特殊工艺在其中加入磁性粒子(…

C语言-结构体内存大小

#include <stdio.h> #include <string.h> struct S1 { char a;//1 int b;//4 char c;//1 }; //分析 默认对齐数 成员对齐数 对齐数(前两个最小值) 最大对齐数 // 8 1 …

设计模式的主要分类是什么?请简要介绍每个分类的特点。

大家好&#xff0c;我是锋哥。今天分享关于【设计模式的主要分类是什么&#xff1f;请简要介绍每个分类的特点。】面试题。希望对大家有帮助&#xff1b; 设计模式的主要分类是什么&#xff1f;请简要介绍每个分类的特点。 1000道 互联网大厂Java工程师 精选面试题-Java资源分…

Java Web开发基础——Web应用的请求与响应机制

在本节中&#xff0c;我们将深入探讨Web应用程序中最为核心的部分之一——请求与响应机制。理解Web应用如何处理客户端请求并生成响应是成为Java Web开发者的关键。我们将从HTTP协议的基础知识开始&#xff0c;逐步过渡到请求参数的获取、响应内容的发送以及会话管理&#xff0…

免杀对抗—Behinder魔改流量特征去除

前言 在现实的攻防中&#xff0c;往往webshell要比主机后门要用得多&#xff0c;因为我们首先要突破的目标是网站嘛&#xff0c;而且waf也往往会更注重webshell的检测。webshell的免杀分为两个&#xff0c;一是静态查杀&#xff0c;二是流量查杀。静态查杀不用多说了&#xff…

Flutter 异步编程简述

1、isolate 机制 1.1 基本使用 Dart 是基于单线程模型的语言。但是在开发当中我们经常会进行耗时操作比如网络请求&#xff0c;这种耗时操作会堵塞我们的代码。因此 Dart 也有并发机制 —— isolate。APP 的启动入口main函数就是一个类似 Android 主线程的一个主 isolate。与…

RAID5原理简介和相关问题

1、RAID5工作原理 2、RAID5单块硬盘的数据连续吗&#xff1f; 3、RAID5单块硬盘存储的是原始数据&#xff0c;还是异或后的数据&#xff1f; 4、RAID5的分块大小 ‌RAID5的分块大小一般选择4KB到64KB之间较为合适‌。选择合适的分块大小主要取决于以下几个考量因素&#xff1…

四、使用langchain搭建RAG:金融问答机器人--构建web应用,问答链,带记忆功能

经过前面3节完成金融问答机器人基本流程&#xff0c;这章将使用Gradio构建web应用&#xff0c;同时加入memory令提示模板带有记忆的&#xff0c;使用LCEL构建问答链。 加载向量数据库 from langchain.vectorstores import Chroma from langchain_huggingface import HuggingF…

理解神经网络

神经网络是一种模拟人类大脑工作方式的计算模型&#xff0c;是深度学习和机器学习领域的基础。 基本原理 神经网络的基本原理是模拟人脑神经系统的功能&#xff0c;通过多个节点&#xff08;也叫神经元&#xff09;的连接和计算&#xff0c;实现非线性模型的组合和输出。每个…

Mac系统下 IDEA配置Maven本地仓库

1.为什么需要配置本地仓库&#xff1f; 在软件开发过程中&#xff0c;使用Maven工具进行依赖管理是常见的做法。Maven通过集中管理各种依赖库&#xff0c;能够帮助开发者在项目中轻松地引入所需的第三方库&#xff0c;并确保项目能够顺利构建和部署。然而&#xff0c;在使用Mav…