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哦,你可以去试试)

五、作者的碎碎念

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

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

相关推荐
red_redemption21 分钟前
自由学习记录(23)
学习·unity·lua·ab包
/**书香门第*/4 小时前
Cocos creator 3.8 支持的动画 7
学习·游戏·游戏引擎·游戏程序·cocos2d
向宇it18 小时前
【unity小技巧】unity 什么是反射?反射的作用?反射的使用场景?反射的缺点?常用的反射操作?反射常见示例
开发语言·游戏·unity·c#·游戏引擎
Heaphaestus,RC19 小时前
【Unity3D】获取 GameObject 的完整层级结构
unity·c#
芋芋qwq19 小时前
Unity UI射线检测 道具拖拽
ui·unity·游戏引擎
tealcwu20 小时前
【Unity服务】关于Unity LevelPlay的基本情况
unity·游戏引擎
大眼睛姑娘1 天前
Unity3d场景童话梦幻卡通Q版城镇建筑植物山石3D模型游戏美术素材
unity·游戏美术
鹿野素材屋1 天前
Unity Dots下的动画合批工具:GPU ECS Animation Baker
unity·游戏引擎
小春熙子1 天前
Unity图形学之着色器之间传递参数
unity·游戏引擎·技术美术·着色器
优雅永不过时·1 天前
three.js实现地球 外部扫描的着色器
前端·javascript·webgl·three.js·着色器