Unity学习笔记(3) UnityShader学习笔记_2:一些渲染流水线的图形学知识 与 UnityShader编写实例

一些渲染流水线的图形学知识 与 UnityShader编写实例。
笔记都是照着“Unity Shader入门精要”摘抄的,为以后想要复习实现方便。

渲染流水线流程

从虚拟的世界渲染到屏幕上的像素。
也就是:

1.从虚拟世界定义的各种几何图形——主要是三角形面,
2.转换到数字世界裁剪空间的片元——是一个二维平面光栅化后的每一个"像素",
但不是真正意义上的显示在屏幕的像素点,而是用于插值设置颜色的最小单位
3.最后在输出到屏幕的一个个像素上。

最主要的图形学内容是各种坐标变换。
缩放、平移、旋转。
涉及到很多矩阵内容,当然不是很难了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gm2ldHSY-1642311805996)(https://raw.githubusercontent.com/camenkc/markDownPics/main/20220115195447.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bIKubf4W-1642311805997)(https://raw.githubusercontent.com/camenkc/markDownPics/main/20220115210736.png)]

学习如何编写Unity Shader

第一个UnityShader与应用方法

定义一个最简单的顶点/片元着色器。
其中顶点着色器是逐顶点调用,片元着色器是逐片元调用
新建一个Standard Surface Shader
(虽然说名字叫表面着色器,但是本身表面着色器也会被编译成顶点/片元着色器,所以本质是一样的)。
在这里插入图片描述

打开并修改代码为,这里实现的效果就是设定所有点和片元颜色为纯白色。

Shader "Custom/SimpleShader"
{
    SubShader
    {
        PASS {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            //这两句话告诉Unity 哪个函数包含了顶点着色器代码,或是片元着色器代码

            //POSITION和SV_POSITION告诉Unity这个函数的输入和输出各是什么,从而自动注入
            //POSITION就是模型的各个顶点,SV_POSITION就是模型在裁剪空间对应的顶点
            float4 vert(float4 v : POSITION) : SV_POSITION{
                return UnityObjectToClipPos (v);
                //这句话同 return mul(UNITY_MATRIX_MVP,*);等效
            }
            //SV_Target即是指定输出颜色到帧缓存中,也就是所有的片元都取这个颜色
            fixed4 frag() : SV_Target{
                return fixed4(1.0, 1.0, 1.0, 1.0);
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
}

其中顶点着色器负责将顶点从模型空间一路转化到裁剪空间,这之后的工作(从裁剪到屏幕空间由Unity自动完成)。
片元着色器就是使得每一个像素都为纯白色。

着色器要赋给材质才能作用到物体上,因此新建一个材质Material
在这里插入图片描述

在材质的Inspector面板里选择到编译好的Shader。
在这里插入图片描述

创建一个新的物体,这里用一个正方体演示,默认的材质能在光线的作用下产生明暗面。
在这里插入图片描述

将刚刚写的附着了纯白着色器的材质附着到物体上,就能看到明暗也不存在了,只是纯纯的白,就更___一样纯。

这里默认的材质可能是灰的,不给改,但是可以直接将材质托到场景物件列表Hierarchy的物件上。
在这里插入图片描述

语义

SV_POSTIONPOSITIONCOLOR0等等都称作“语义”。
用于让Shader明确从哪里读取数据并将数据输出到哪里。

其中SV_开头的指系统数值语义(System-Value semantics),这些语义有着特殊的含义,其中的变量不可以随便赋值。
例如渲染引擎会把用SV_POSITION修饰的变量经过光栅化后显示在屏幕上。
SV_POSITION和POSITION在大多数平台上等价,但在某些平台如PS4必须使用SV_POSITION来修饰顶点着色器的输出

一些常用的语义
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

传递于处理更多数据

上面的例子只传递了模型的顶点坐标数据。
可以使用结构体一次传递多个数据,如模型各个顶点的坐标、法向量、切向量、各层纹理坐标等。
下面一个更复杂点的例子

Shader "Custom/SimpleShader2"{
    Properties{
        //声明一个Color类型
        _Color ("Color Tint", Color) = (1.0, 1.0, 1.0, 1.0)
    }
    SubShader{
        Pass{
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            //同名同类型
            fixed4 _Color;

            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;
                return o;
            }

            fixed4 frag(v2f i) : SV_Target{
                return fixed4(i.color * _Color.rgb, 1.0);
            }
            ENDCG
        }
    }
}

运行结果是这样的:
在这里插入图片描述
在这里插入图片描述

可以看到放在一个立方体中,有3个面是黑色,3个面个是红蓝绿。
这是因为在顶点着色器中,o.color = v.normal;这句话的含义就是,将顶点的法向量(一个三维向量)直接设定为颜色值(rgb数组,本质也是一个三维向量)。

但是颜色值只能是[0, 1.0]的区间范围,
法向量的每个元素会在[-1.0, 1.0]之间。

因此直接赋值,显而易见只有三个向上的面(法向量各个元素为非负的)有有效的值,所有只有三个面有效颜色,另外的会转化为(0, 0, 0)也就是黑色。

此外上述代码在片元着色器中,用i.color * _Color.rgb,将每个顶点的颜色值与在属性面板中手动设置的颜色值做了乘积。

这里两个三维向量直接乘,得出另一个三维向量,应该是每个分量依次乘,而不是叉乘。

因为从结果上看,是一种过滤效果,图中只有本来是蓝色的那一面依然是蓝色,其他面均为黑色。
在这里插入图片描述

ShaderLab中的封装的属性和可以在CG代码中使用的能够互相转换的属性对应表如下
在这里插入图片描述

上面的颜色输出,也可以作为Debug时需要的数据可视化方案

再复杂一点的Shader编写

上面的Shader都很简单。再复杂一点可以利用Unity内置的许多文件中的函数和变量做更高级的库调用。
需要在CG代码中使用#include引用。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

DEBUG

使用帧调试器可以看到渲染本帧时所有的渲染事件event
在这里插入图片描述

可以用这个滑动条重放事件。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值