您现在的位置是:首页 >其他 >用Unity Shader实现边缘发光的效果网站首页其他

用Unity Shader实现边缘发光的效果

菜鸟秦笙_ 2026-04-07 12:01:04
简介用Unity Shader实现边缘发光的效果

写这个Shader需要知道一些基础知识:

物体的每个地方的法线都是垂直于这个地方的

在Unity里我们看物体,实际上就是相机在看物体,我们看到的所有东西都是通过相机视角

根据上边两点,可以知道,我们看物体的边缘地方跟我们看物体的中心地方,角度是有一定的区别的,物体的中心区域的法线方向是垂直于物体中心区域,也就是与相机的视线平行,而物体的边缘区域的法线方向是垂直于物体边缘区域,也就是向外的(上下左右的方向)。

所以可以通过各个像素的法线方向跟相机视线的角度来做一个点乘:

viewDir:相机角度

normal:法线的方向

VDotN=dot(viewDir,normal)

众所周知,法线的取值范围是[-1.1]

所以需要使用shader的内置函数clamp来使得点乘的结果在[0,1]

具体做法:

VDotN=clamp(dot(viewDir,normal),0,1)

这样取得的结果就是在[0,1]

根据公式可以知道,物体越靠近中心区域,点乘的值越大,我们需要边缘区域更加明显,那么就做一个取反的操作:

VDotN= 1-clamp(dot(viewDir,IN.normal),0,1)

通过这个值,我们可以判断出哪里是物体的边缘区域

这里用SurfaceShader来举例:

在SurfaceShader中,默认的片段着色器:

        void surf (Input IN, inout SurfaceOutput o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }

这里没有需要的法线信息,需要自己加一张法线贴图:

 Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Normal ("Normal (RGB)", 2D) = "white" {}//法线贴图
        _Glossiness ("Smoothness",Range(1,3)) = 1
    }

如何读取法线:

        sampler2D _MainTex;
        sampler2D _Normal;

        void surf (Input IN, inout SurfaceOutput o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex);

           float3 tmpNormal =UnpackNormal( tex2D (_Normal, IN.uv_MainTex));
            o.Albedo = c.rgb;              o.Normal=tmpNormal;      o.Alpha = c.a;
         
        }

这样就取到了法线,UnpackNormal这是Shader的内置函数,作用就是取法线

如果让边缘的颜色变成红色,那么需要配合上边的算式:

        sampler2D _MainTex;
        sampler2D _Normal;

        void surf (Input IN, inout SurfaceOutput o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex);

            float3 tmpNormal =UnpackNormal( tex2D (_Normal, IN.uv_MainTex));
            o.Albedo = c.rgb;              o.Normal=tmpNormal;      o.Alpha = c.a;
            float VDotN= 1-clamp(dot(viewDir,IN.normal),0,1);

            o.Emission=floa4(1,0,0,1)*VDotN;
        }

o.Emission这是SurfaceOutput里的变量,代表自发光

这里的意思就是,让物体的自发光为红色,越是边缘的地方,红色越明显,颜色可以自己定义一个变量来进行调整,或者用其他纹理图片的rgba来代替

这样就可以实现类似边缘发光的效果了

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。