Unity | Shader基础知识(第十九集:顶点着色器的进一步理解-易错点讲解)

目录

一、前言

二、网格

三、方法UnityObjectToClipPos

四、顶点着色器和片元着色器的POSITION

五、作者的碎碎念


一、前言

之前我们简单讲解过顶点着色器,也简单讲解了表面着色器,并且一起做了一些案例,因为顶点着色器本身是更自由一些的,后续很多效果是基于顶点着色器之上的,所以我们对顶点着色器做进一步理解。

二、网格

之前讲过,顶点着色器就是把每个顶点上了颜色,然后再上线,再面,所以我们必须了解一下物体的网格。这里以unity常见的平面:Plane和Quad举例。

备注:

如果你想调出来后面的界面,只需要换显示界面为wireframe(线框)。(如图1所示)
图1 线框界面

plane的网格(如图2所示)。
图2 plane的网格

在unity中,无论你的plane有多大,都是由宽10格和高10格的方块组成的,每个方块分成两个三角形。

Quad的网格(如图3所示)。
图3 quad的网格

同样,无论你的quad有多大,都是由一个方块组成的,方块分成两个三角形。

所以,我们之前说过,如果需要显示地形之类比较细致的纹理,你就用plane,如果你只是要播放视频,就用quad就足够了,就是这个原因。


备注:(这里不想看可以不看哦)

在这里我们也可以通过程序来打印出来模型顶点的坐标,代码如下:

cs 复制代码
    void Start()
    {
        //声明网格                获取网格过滤器中的网格
        Mesh mesh = GetComponent<MeshFilter>().mesh;
        //把顶点坐标提取出来
        Vector3[] vertics = mesh.vertices;
        foreach (Vector3 v in vertics)
        {
            //打印顶点坐标
            Debug.Log(v);
        }
    }

三、方法UnityObjectToClipPos

之前也粗略说过,unityObjectToClipPos的作用是把3d的坐标,转换成2D的坐标,所以我们在这里可以一起看看,它到底变成了什么。

我们知道在颜色里r通道,0及以下就是黑色,1及以上就是红色。那么,我们只要在顶点方法中,把我们的坐标赋值进去就可以了。代码如下:

cs 复制代码
Shader "Custom/015"
{
    SubShader
    {
        Pass{
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag

        //自己写了一个结构体
        struct appdata
        {
            float4 vertex:POSITION;
        };

        //自己又写了一个结构体
        struct v2f
        {
            float4 vertex:SV_POSITION;
            float4 color:COLOR;
        };

        v2f vert(appdata v)
        {
             v2f o;
             //坐标变换
             o.vertex = UnityObjectToClipPos(v.vertex);
             //变换以后吧x的值放到颜色里,我们就可以通过颜色来反推x的值
             o.color.r = v.vertex.x;
             return o;
        }

        fixed4 frag (v2f i): SV_Target
        {
            return i.color;
        }

        ENDCG
        }
    }
}

把这个shader分别放到plane和quad身上。

quad:

可以明显看到从方块中间到最右边是红色逐渐变深的一个过程,但没有完全变红。(如图4所示)我们并不知道它到底是到了1还是没有到。
图4 方块颜色

为了得出具体数据,我们把shader下方部分做一下修改。我们假设最右边是0.5,如果减去以后没有红色了,就说明它小于等于0.5。

cs 复制代码
//o.color.r = v.vertex.x;
o.color.r = v.vertex.x-0.5;

于是我们得到了全黑的图。(如图5所示)
图5 全黑

如果我们改成0.4,右边是有红色的。(如图6所示)
图6 稍微有点红色

那么我们就可以推测出,它的x是从0到0.5,因为是对称的,所以左边就是0到-0.5。 再仔细想一下,这是一个网格组层的,如果边长是1,那么刚好左右各0.5。

plane:

我们可以看到,从黑色到红色过度的部分是0到1,后面的长度刚好是前面的4个那么长,那我们就推测,后面是0到5,前面是-5到0。(如图7所示)
图7 plane的着色

如果你继续测试,会发现你即使放大scale,也是不会改变现在的颜色布局的。

我们可以继续推测出,我们的坐标实际上和我们的网格有关系,这篇文章的第二部分,plane刚好是左边5个右边5个,所以坐标就是左边是-5,右边是5。

四、顶点着色器和片元着色器的POSITION

上面的内容,我们都是把vertex放在顶点着色器中的,如果我们放到片元着色器中,会出现奇怪的现象。代码如下:

cs 复制代码
Shader "Custom/015"
{
    SubShader
    {
        Pass{
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag

        struct appdata
        {
            float4 vertex:POSITION;
        };

        struct v2f
        {
            float4 vertex:SV_POSITION;
            float4 color:COLOR;
        };

        v2f vert(appdata v)
        {
             v2f o;
             o.vertex = UnityObjectToClipPos(v.vertex);
             //在这里去掉
             //o.color.r = v.vertex.x;
             return o;
        }

        fixed4 frag (v2f i): SV_Target
        {
            //写在这里
            i.color.r = i.vertex.x;
            return i.color;
        }

        ENDCG
        }
    }
}

你就会发现,全红了。(如图8所示)
图8 全红的方块

然后我们可以和之前一样,通过去减少数字去测试。(测试过程略,自己去测吧,宝子们)

这里直接放结果:

你会发现这里的0在左下角,最右边是1920(如图9所示)
图9 界面

所以,片元着色器中的坐标和顶点着色器中是不一样的, 在这里的坐标已经变成了屏幕坐标,因为我的屏幕分辨率设置的是1920*1080(左上角那里能看见),所以我红色的方块坐标也是按照这个设定了,因为我所有的方块都在0的右边,都是大于1的数,所以都是红色。

**结论:**顶点坐标系中的坐标是根据网格来计算的,片元着色器中的坐标是按屏幕坐标来的。(片元着色器中的z坐标是0哦,你可以去试试)

五、作者的碎碎念

这一章没有什么应用是不是怪无趣的,但是基础打好了以后,后面才好写啊~

看到这里了,点个赞吧,宝子们~

相关推荐
蓝裕安2 小时前
伪工厂模式制造敌人
开发语言·unity·游戏引擎
谢泽浩6 小时前
Unity 给模型贴上照片
unity·游戏引擎
z2014z6 小时前
Unity Resource System 优化笔记
unity·游戏引擎
王维志6 小时前
Unity 高亮插件HighlightPlus介绍
unity·游戏引擎
zaizai10077 小时前
我的demo保卫萝卜中的技术要点
unity
菌菌巧乐兹8 小时前
Unity 百度AI实现无绿幕拍照抠像功能(详解版)
人工智能·百度·unity
孑么1 天前
C# 委托与事件 观察者模式
开发语言·unity·c#·游戏引擎·游戏程序
wangduqiang7471 天前
unity的学习
学习·unity·游戏引擎
@Sunset...1 天前
Unity程序基础框架
unity·游戏引擎
咩咩觉主2 天前
Unity实战案例全解析 :PVZ 植物脚本分析
unity·游戏引擎