zoukankan      html  css  js  c++  java
  • UnityShader笔记一:Shader的顶点着色函数与片元着色函数

    虽然看了很多网络上Shader的教程,但是这些教程总是缺点什么东西,看过之后还是一知半解,所以这里再次做了一下试验,以及添加个人的理解,不对的地方以后慢慢学习。这里根据具体问题做出笔记。

    1.第一个问题,顶点函数和片元函数到底各自执行了多少次,这个问题问过网络上很多人不知道多少次,但是似乎每个人都在回避这个问题(就是两次啊,因为是并行的啊,等等巴拉巴拉,所以认真就输了),因为不能像C#函数那样直接显示记录整型数据,所以这里我不得不试验一下具体现象。

    这里试验为,创建一个Shader,Shader的颜色分成三个部分,将场景空间中世界坐标pos.x > -0.5 && pos.x< -0.5 + 0.33为白色,(pos.x > -0.5 + 0.33 && pos.x < -0.5 + 0.66)为红色,其余为绿色,简单说就是将世界空间中坐标x=0附近的颜色分为三种颜色显示。

    结果如下第二张图所示。这里我们正方体顶点数量为8个顶点,那么正方体Vert就应该执行了8次(虽然可能不止8次,因为在没有片元函数的时候底层还要进行插值运算)。片元函数传入的是顶点的值,但是只有8个顶点,但是要计算获取某个点上的颜色值就需要这个点的坐标值,但是我们使用的却是顶点的坐标值,但是这个顶点的坐标值也不是顶点函数穿过来的值啊,因为我们就假定四个顶点传过来的值决定了四个颜色的值,但是如第二图四个顶点的位置位置在不同的颜色区域时,颜色仍然能正确的着色。因此这里我们这里得出一个个人结论,传过来的结构体的坐标已经不是原来顶点的坐标了,而是经过系统处理后的生成的片元所在的坐标。也就是说这里的系统在顶点运行结束后生成的顶点数量已经不是8个,而是等于片元数量,至于片元的数量,这里先理解成显示器需要显示的像素数量或者是显卡的片元处理数量。

    pass
            {
                CGPROGRAM
    
                #pragma vertex vert
                #pragma fragment frag
    
                #include "UnityCG.cginc"
    
                struct v2f {
    
                    float4 pos : SV_POSITION;
                    float4 worldPos :Textcoord0;
                };
    
                v2f vert(appdata_full v)
                {
                    v2f o;
    
                    o.pos = UnityObjectToClipPos(v.vertex);//将顶点坐标转换成裁剪坐标
    
                    //将当前的顶点坐标存储到结构体中
                    o.worldPos = v.vertex;
    
                    return o;
                }
    
    
                fixed4 frag(v2f i) : SV_Target
                {
                    float4 pos = mul(unity_ObjectToWorld, i.worldPos);//将模型坐标转换成世界坐标
    
                    if (pos.x > -0.5 && pos.x< -0.5 + 0.33)
                    {
                        return fixed4(1.0, 1.0, 1.0, 1.0);
                    }
                    else if (pos.x > -0.5 + 0.33 && pos.x < -0.5 + 0.66) {
                        return fixed4(1.0f, 0, 0, 1.0f);
                    }
                    return fixed4(0, 1, 0, 1.0f);
    
                    return i.worldPos;
                }
    
                ENDCG
            }

    2.坐标转换,坐标转换到底该怎么进行,自从从学校考研结束后我实在不想再去碰高数和线性代数,反正unity都做好了封装,理解原理用就是了,所以还是老样子这里我们做个试验:这里我们从顶点函数将模型坐标转换成世界坐标,然后将整个模型的颜色渲染成红色。

    结果如下面第二张图所示(这里的结果是假的,我在自己的电脑上运行的结果什么都没有显示,在公司上和下图二一样,这里为了做笔记弄了个UI来代替=》“尴尬”),然后我们发现模型颜色直接被渲染到了屏幕上而且占据的区域很大,并且会跟随窗口的缩放而缩放。并且如果将模型拖出相机裁剪区域,就直接不显示。这里发生这个结果的原因是由于我们没有进行裁剪区域裁剪,就直接输出结果,注意这里的顶点函数的返回结果是直接输出到显卡缓存,而没有经过裁剪处理,相当于直接到屏幕。因此处理前,输出的顶点坐标应该先经过到裁剪区域的处理,即o.pos = UnityObjectToClipPos(v.vertex);//将顶点坐标转换成裁剪坐标

            pass
            {
                CGPROGRAM
    
                #pragma vertex vert
                #pragma fragment frag
    
                #include "UnityCG.cginc"
    
                struct v2f {
    
                    float4 pos : SV_POSITION;
                };
    
                v2f vert(appdata_full v)
                {
                    v2f o;
    
                    o.pos = mul(unity_ObjectToWorld, v.vertex); //将顶点坐标转换成世界坐标
    
                    return o;
                }
    
    
                fixed4 frag(v2f i) : SV_Target
                {
                    return fixed4(1.0,0,0,1.0);;
                }
    
                ENDCG
            }

    3.系统对颜色自动插值:如下我们设置顶点的颜色,然后在片元函数中输出,结果如下图,这说明,如果设置了顶点的颜色,那么剩余区域的颜色就会根据顶点的颜色进行插值获取

    pass
            {
                CGPROGRAM
    
                #pragma vertex vert
                #pragma fragment frag
    
                struct a2v
                {
                    float4 vertex:POSITION;
                    float3 normal:NORMAL;
                    float4 texcoord:TEXCOORD0;
                };
    
                struct v2f {
                    float4 pos:SV_POSITION;
                    fixed3 color : COLOR0;
                };
    
                v2f vert(a2v v)
                {
                    v2f o;
                    o.pos = UnityObjectToClipPos(v.vertex);
    
                    o.color = v.normal * 0.5 + fixed3(0.5, 0.5, 0.5);
                    return o;
                }
    
                fixed4 frag(v2f i) : SV_Target
                {
                    return fixed4(i.color,1.0);
                }
    
                ENDCG
            }

  • 相关阅读:
    docker mysql
    dotnet core webapi +vue 搭建前后端完全分离web架构
    npm run dev
    docker pureftpd
    虚拟主机连接FTP发送"AUTH TLS"命令后提示“无法连接到服务器”
    [mobile开发碎碎念]手机页面上显示PDF文件
    T-SQL注意事项(1)——SET NOCOUNT ON的去与留
    Tomcat 部署多个项目出现错误
    十进制小数和二进制小数之间的转换
    sed 替换多个空格为一个
  • 原文地址:https://www.cnblogs.com/xiaoahui/p/13917320.html
Copyright © 2011-2022 走看看