Unity Shader学习(九)物体边缘实现

25 篇文章 10 订阅
24 篇文章 1 订阅

根据前面的学习,我们了解到除了可以对点的颜色进行处理,还可以对点本身进行操作,例如我们可以改变点的位置,这样就可以实现对模型渲染的操控。物体边缘效果是我们常用的一种效果,要实现物体边缘,原理也很简单。
首先我们要了解到,模型在渲染时,有正面和背面之分,背面一般是不渲染,进行剔除,我们看到的模型往往是正常渲染正面,如下图所示:
在这里插入图片描述
了解到这,因此我们可以控制是否显示正面或者背面。进一步了解物体轮廓,物体轮廓其实就是物体在显示的屏幕上最外侧的边缘部分,因此要对模型最外部的边缘部分进行处理,如上图的边缘部分就是立方体的几条边,如下图所示,红色所在范围即为边缘部分。为了获取到边缘部分,需要将点转换到裁切空间进行处理。
在这里插入图片描述
关于裁剪空间,参考裁剪空间这篇文章
说明白点,裁剪空间就是摄像机视野范围内的一个矩阵转换空间,在该空间内可以进行点处理。首先,我们把边缘处理的流程分为两个pass,一个处理剔除正面的渲染,一个处理正面的正常渲染。
第一个pass:

 Pass
        {
            //剔除正面   只看背面
            Cull Front
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            float _Outline;
            float4 _OutlineColor;

            struct appdata
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };

            struct v2f
            {
                float4 pos : SV_POSITION;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex + normalize(v.vertex) * _Outline);
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                return _OutlineColor;
            }

            ENDCG
        }

使用UnityObjectToClipPos函数,可以将模型空间的点转换到裁剪空间,下面这行在原来点的基础上,乘以法线点和轮廓值,向外延伸,如下图所示。

 o.pos = UnityObjectToClipPos(v.vertex + normalize(v.vertex) * _Outline);

在这里插入图片描述
完成背面处理的pass后,进行正常的pass处理,不需要添加cull,默认渲染只正面,代码如下:

 Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            sampler2D _MainTex;

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

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

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                return tex2D(_MainTex, i.uv);
            }
            ENDCG
        }

整体的效果如下:
在这里插入图片描述
完整code:

Shader "Custom/Study/Simple Outline"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}

        _Outline ("Outline", Range(0, 1)) = 0.1
        _OutlineColor ("Outline Color", Color) = (1,1,1,1)
    }

    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            //剔除正面   只看背面
            Cull Front

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            float _Outline;
            float4 _OutlineColor;

            struct appdata
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };

            struct v2f
            {
                float4 pos : SV_POSITION;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex + normalize(v.vertex) * _Outline);
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                return _OutlineColor;
            }

            ENDCG
        }

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            sampler2D _MainTex;

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

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

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                return tex2D(_MainTex, i.uv);
            }
            ENDCG
        }

    }
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ToDoNothing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值