欢迎来到本书的第2 篇一一初级篇。在基础篇中,我们学习了渲染流水线, 并给出了Unity Shader 的基本概况, 同时还打下了一定的数学基础。从本章开始,我们将真正开始学习如何在Unity中编写Unity Shader 。
本章的结构如下:
在5.1 节, 我们将给出编写本书时使用的软件,包括Unity 的版本等。这是为了让读者可以在实践时不会出现因版本不同而造成困扰。在5.2 节,我们将看到一个最简单的顶点/片元着色器,并详细地解释这个顶点/片元着色器的组成结构。
5.3 节将介绍Unity 内置的Unity Shader 文件,以及提供给用户的一些包含文件、内置变量和函数等。
5.4 节则向读者阐述Unity Shader 中使用的CG 语义, 这是很多初学者容易困惑的地方。
在5.5 节中, 我们会介绍如何对Unity Shader 进行调试。
5.6 节将介绍平台差异对Unity Shader 的影响。
最后, 5.7 节将给出一些在编写Unity Shader 时很容易实现的优化技巧。为了让读者养成良好的编程习惯, 我们在这节也给出了一些建议。
5.1 本书使用的软件和环境
本书使用的Unity 版本是Unity 5.2.1 免费版。使用更高版本的Unity 通常不会有什么影响。但如果你打算使用更低版本的Unity , 那么在学习本书时可能就会遇到一些问题。例如, 你发现有些菜单或变量在你安装的Unity 中找不到, 可能就是因为Unity 版本不同造成的。绝大多数情况下, 本书的代码和指令仍然可以工作良好,但在一些特殊情况下, Unity 可能会更改底层的实现细节,造成同样的代码得到不一样的效果(例如,在非统一缩放时对法线进行变换,详见19.3节〉。还有一些问题是Unity 提供的内置变量、宏和函数, 例如我们在书中经常会使用UnityObjectToWorldNormal 内置函数把法线从模型空间变换到世界空间中,但这个函数是在Unity5 中被引入的,因此如果读者使用的是Unity 5 之前的版本就会 错。类似的情况还有和阴影相关的宏和变量等。和Unity 4.x 版本相比, Unity 5.x 最大的变化之一就是很多以前只有在专业版才支持的功能, 在免费版也同样提供了。因此,如果读者使用的是Unity 4.x 免费版, 可能会发现本书中的某些示例无法实现。
本书工程编写的系统环境是Mac OS X 10.9.5 。如果读者使用的是其他系统, 绝大部分情况也不会有任何问题。但有时会由于图像编程接口的种类和版本不同而有一些差别,这是因为Mac 使用的图像编程接口是基于OpenGL 的, 而其他平台如Windows , 可能使用的是DirectX . 例如, 在OpenGL 中,渲染纹理( Render Texture )的(0, 0)点是在左下角,而在DirectX 中,(0, 0)点是在左上角。在5.6 节,我们将总结一些由于平台而造成的差异问题。
5.2 一个最简单的顶点/片元着色器
现在,我们正式开始学习如何编写Unity Shader,更准确地说是,学习如何编写顶点/片元着色器。
5.2.1 顶点/片元着色器的基本结构
我们在3.3 节已经看到了Unity Shader 的基本结构。它包含了Shader, Properties 、SubShader、Fallback 等语义块。顶点/片元着色器的结构与之大体类似,它的结构如下:
其中,最重要的部分是Pass 语义块,我们绝大部分的代码都是写在这个语义块里面的。下面我们就来创建一个最简单的顶点/片元着色器。
(1 )新建一个场景,把它命名为Scene_5_2 。在Unity 5 中可以得到图5.1 中的效果。
5.2.2 模型数据从哪里来
在上面的例子中,在顶点着色器中我们使用POSITION 语义得到了模型的顶点位置。那么,如果我们想要得到更多模型数据怎么办呢br> 现在,我们想要得到模型上每个顶点的纹理坐标和法线方向。这个需求是很常见的,我们需要使用纹理坐标来访问纹理,而法线可用于计算光照。因此,我们需要为顶点着色器定义一个新的输入参数,这个参数不再是一个简单的数据类型,而是一个结构体。修改后的代码如下:
- Shader "Unity Shaders Book/Chapter 5/Simple Shader" {
- SubShader {
- Pass {
- CGPROGRAM
-
- #pragma vertex vert
- #pragma fragment frag
-
- uniform fixed4 _Color;
-
- struct a2v {
- float4 vertex : POSITION;
- float3 normal : NORMAL;
- float4 texcoord : TEXCOORD0;
- };
-
- // 使用一个结构体来定义顶点着色器的输入
- struct a2v {
- // POSITION 语义告诉Unity ,用模型空间的顶点坐标填充vertex 变量
- float4 vertex : POSITION;
- // NORMAL 语义告诉Unity ,用模型空间的法线方向填充normal 变量
- float3 normal : NORMAL;
- // TEXCOORDO 语义告诉Unity ,用模型的第一套纹理坐标填充texcoord 变量
- float4 texcoord : TEXCOORDO;
- };
-
- float4 vert(a2v v) : SV_POSITION {
- // 使用v.vertex 来访问在模型空间的顶点坐标
- return mul(UNITY—_MATRIX_MVP, v.vertex);
- }
-
- fixed4 frag() : SV_Target {
-
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!