物体切割效果

1、物体切割效果是什么

在游戏开发中,物体切割效果就是物体看似被切割、分割或隐藏一部分的视觉效果。
这种效果常用与游戏和动画中,比如角色攻击时的切割效果,场景中的墙壁切割效果等等。

2、物体切割效果的基本原理

在片元着色器中判断片元的世界坐标是否满足切割条件,如果满足则直接抛弃片元不渲染
判断片元在模型中的正反面,决定使用哪种纹理进行渲染

关键点:

  • 如何判断世界坐标

在Shader中声明一个Vector坐标变量,通过C#代码把控制切割位置的物体世界空间位置(比如在一个物体下放一个子对象 cutObj 来控制这个位置)传递给Shader,在Shader中用片元的世界坐标和传递进来的世界坐标做比较,在这个课程中,我们可以分三种模式,分别比较x、y、z坐标,切割x、y、z方向的片元

  • 如何抛弃片元不渲染

Unity Shader中提供了一个内置函数 clip(x)它的作用就是在片元着色器中调用时来丢弃片元的
传入的值x小于0,则会丢弃当前片元,被丢弃的片元不会被进一步处理也就不会被渲染了,也就是说,当我们判断片元位置需要被切割时,直接执行clip函数传入一个负数,这个片元就会被丢弃
不会被渲染了

  • 如何判断片元的正反面

Unity Shader中提供了一个语义 VFACE,它只能在片元着色器中使用,它可以作为参数传递给片元着色器
传入值1表示为正面,-1表示为背面,我们可以利用它判断该片元是模型正面还是背面片元,决定使用哪种纹理或颜色进行渲染
注意:
在使用它时建议加上编译指令 #pragma target 3.0 或 4.0 、5.0表示设置着色器模型版本,可以让VFACE语义使用上的兼容性和稳定性更好

3、实现

Shader "ShaderProj/17/ObjectCutting"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _BackTex ("BackTex", 2D) = "white" {}
        // 切割的防线 0-x, 1-y, 2-z
        _CuttingDir ("CuttingDir", Float) = 0
        //是否翻转切割 0-不反转 1-反转
        _Invert ("Invert", Float) = 0
        _CuttingPos ("CuttingPos", Vector) = (0,0,0,0)
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        Cull Off   // 正反两面都要渲染

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma target 3.0
            #include "UnityCG.cginc"

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float3 worldPos : TEXCOORD1;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            sampler2D _BackTex;
            fixed _CuttingDir;
            fixed _Invert;
            float4 _CuttingPos;

            v2f vert (appdata_base v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
                return o;
            }

            fixed4 frag (v2f i, fixed face : VFACE) : SV_Target
            {
                fixed4 col = face > 0 ? tex2D(_MainTex, i.uv) : tex2D(_BackTex, i.uv);

                fixed cutValue;
                if (_CuttingDir == 0) 
                    cutValue = step(_CuttingPos.x, i.worldPos.x);
                else if (_CuttingDir == 1)
                    cutValue = step(_CuttingPos.y, i.worldPos.y);
                else if (_CuttingDir == 2) 
                    cutValue = step(_CuttingPos.z, i.worldPos.z); 
                cutValue = _Invert ? 1 - cutValue : cutValue;

                cutValue = cutValue == 0 ? -1 : cutValue;
                clip(cutValue);

                return col;
            }
            ENDCG
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[ExecuteAlways]
public class ObjectCutting : MonoBehaviour
{
    private Material material;
    public GameObject cutObj;

    // Start is called before the first frame update
    void Start()
    {
        material = this.GetComponent<Renderer>().sharedMaterial;
    }

    // Update is called once per frame
    void Update()
    {
        if (material != null && cutObj != null) {
            material.SetVector("_CuttingPos", cutObj.transform.position);
        }
    }
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值