Advertisement

unity shader入门精要_《Untiy Shader 入门精要》读书笔记 (一)基础篇

阅读量:
e679ec68146c3f58a1c9fc6dedd5b28e.png

本文是冯乐乐著的《Untiy Shader 入门精要》的读书笔记第一篇。主要是记录一些读书中的知识点,请配合图书一块食用。

一、渲染流水线

1. 概述

由一个三维场景出发,渲染一张二维的图像。

2 . 概念渲染流水线

《Real-Time Rendering,Third Edition》将渲染流程划分为三个部分。

应用阶段 -> 几何阶段 -> 光栅化阶段

  • 应用阶段: 开发者可以自由主导的阶段,通常由 CPU 负责。开发者主要通过以下 3个 主要任务,输出渲染需要的几何信息,即 渲染图元
    • 布置好场景。模型、相机和光照的摆放。
    • 粗粒度剔除(culling)。将被遮挡,不可见的物体剔除出去。
    • 设置模型的渲染状态。包括材质、纹理、shader等。
  • 几何阶段: 通常在 GPU 中进行。对输入的渲染图元进行多步处理,将输出屏幕空间二维顶点坐标,没个顶点包含深度值、着色等信息。
  • 光栅化阶段: 通常在 GPU 上运行。主要是决定每一个渲染图元中那些像素应该绘制到屏幕上。需要对几何阶段得到的顶点数据进行插值,然后逐像素处理。

3. CPU 和 GPU 之间通信(应用阶段)

应用阶段的起点是 CPU。主要分为三部分。

  1. 应用阶段
    1. 把数据加载到显存中: 所有需要渲染的数据,需要从硬盘中加载到内存中,再将网格、纹理等信息加载到 GPU 显存中。
    2. 设置渲染状态: 定义了场景中网格是被怎么渲染的。使用哪个顶点着色器/片元着色器、光源属性、材质等。
    3. 调用 Draw Call: CPU 通知 GPU 对一个被需要渲染的图元列表进行渲染。

4. GPU 流水线(几何阶段 + 光栅化阶段)

GPU 接受到了 CPU 的 Draw Call 指令。会按照顺序执行下面的步骤

  1. 几何阶段
    1. 顶点着色器(Vertex Shader): 完全可编程。顶点变换、着色等功能。
    2. 曲面细分着色器(Tessellation Shader): 可选着色器,用于细分图元。
    3. 几何着色器(Geometry Shader): 可选着色器。用于逐图元的着色,或生成更多的图元。
    4. 裁剪(Clipping): 可配置。将不在摄像机内的顶点裁剪掉,并剔除某些三角图元的面片。
    5. 屏幕映射(Screen Mapping): 不可配置和编程。负责将图元坐标转换到屏幕坐标系中。
  2. 光栅化阶段
    1. 三角形设置(Triangle Setup): 固定函数
    2. 三角形遍历(Triangle Traversal): 固定函数
    3. 片元着色器(Fragment Shader): 完全可编程。逐片元着色。
    4. 逐片元操作(Per-Fragement Operations): 可配置。能够修改颜色、深度缓冲、进行混合等。

5. 常见问题:OpenGL 和 DirectX

这俩个都是图像应用编程接口 。应用程序通过这些接口发送渲染命令,接口将把命令发送给显卡驱动 ,驱动将会把命令翻译成 GPU 指令,进行真正的渲染。

OpenGL:左下角为原点(0,0)

DirectX:左上角为原点(0,0)

显卡商为了让显卡支持 OpenGL 和 DirectX,就必须提供支持两个接口的显卡驱动

6. 常见问题:HLSL、GLSL、Cg

在可编程渲染管线出来之前,最初是使用汇编进行着色器编码,之后就出现了更高级的着色语言。

  • HLSL(High level Shading Language): DirectX 的着色器语言,只支持微软 自家平台。硬件不同,表现相同。
  • GLSL(OpenGL Shading Language): *OpenGL * 的着色器语言,跨平台,但是平台不同,表现不可控
  • Cg(C for Graphic): NVIDA 推出的着色器语言,跨平台,能和 HLSL 转换。

在 Unity Shader 中,我们可以选择 “Cg/HLSL” or "GLSL"

二、Unity Shader 基础

在 Unity 中,Unity Shader 是依托材质来表现效果的。通过创建材质,赋予不同的 Shader,然后在材质面板中设置 Shader 属性。

Unity Shader > Shader:Unity Shader 不光对 Shader 进行了封装,也同时能够直接设置不属于 Shader 控制的渲染设置,例如开启混合、深度测试等。
d755deee84932d3ee0d5971c013f94f9.png

1. 4 种 Unity Shader 模板

  • Standard Surface Shader :包含了标准光照的表面着色器模板
  • Unlit Shader:不包含光照的基本的顶点/片元着色器模板
  • Image Effect Shader:为屏幕后处理提供一个基本模板
  • Compute Shader:特殊 Shader 文件,旨在利用 GPU 的并行性来进行一些与常规渲染流水线无关的计算

2. ShaderLab

Untiy 提供的编写 Unity Shader 的一种说明性语言。定义了要显示一个材质所需要的全部东西,不仅仅是着色器代码 ,内嵌了 Cg/HLSL 的着色器代码。

3. SubShader

每一个 Unity Shader 包含多个 Subshader 语义块,但是最少有一个。

SubShader 中定义了一系列 Pass 以及可选的 状态(RenderSetup)标签(Tags) 。每个 Pass 定义了一次完整的渲染流程。应按尽量使用最小数目的 Pass。状态(RenderSetup)标签(Tags) 也能定义在 pass 中。

复制代码
 SubuShader{

    
     [Tags] // 标签,可选
    
     [RenderSetup] // 状态,可选
    
  
    
     pass{
    
  
    
     }   // other pass
    
 }
    
    
    
    
    AI写代码

4. 常见渲染状态设置(RenderSetup)

fb17f77ecfb7146a5ce8a02c323684bc.png

5. 表面着色器(Surface Shader)

是 Unity 创建的一种着色器代码类型。是对于 顶点/片元着色器更高一层的抽象。

三、数学基础

1. 笛卡尔坐标系

相互垂直的坐标系。

1.1. 左手坐标系、右手坐标系

两个坐标系无法通过旋转进行重合,x轴和z轴的正方向。有个判断方法,x轴 正方向在右手,y轴 正方向朝上,此时看面朝的向是 Z轴 正方向,则是左手坐标系,反则为右手坐标系。
1b1d3861609f538e5f345418df6eacd1.png
ca99b56d350d906390a839980c5e6ccd.png

Unity 中模型空间和世界空间使用的是左手坐标系,但是对于观察空间(以摄像机为原点的坐标系)使用的是右手坐标系。
387103d5cba643a9b6cc9b8b252a99c7.png

旋转的时候两个坐标系采用不同的正向旋转,左手法则和右手法则。
78eca8b5909aec9aece50c853f2a1e0c.png

2. 矢量

矢量:包含了方向 的有向线段。

2.1 模

模是一个标量,代表线段的长度。

2.2 单位矢量

模为 1 的矢量。

归一化操作:

2.3 零矢量

模为 0 的矢量,即各个分量值都为 0,(0,0,0)

2.4 点积(内积)

计算后的值为 标量

几何意义 :投影,b 在 a向量方向上的投影

可以通过点积可以判断两个向量的夹角。常用于判断两个向量垂直。

2.5 叉积(外积)

计算后的结果为 矢量

59d31e45e15526d4d5a78e174144279f.png

几何意义: 获得平面的法向量,计算得出垂直于 a 和 b 的矢量。axb,具有方向,是从 a 旋转到 b,再根据左手右手定理,确定 axb 正方向。

计算垂直于一个平面或者三角形的矢量。也用于判断三角形面片朝向。

3. 矩阵

引用 wiki 上描述的数学概念。矩阵就是一个由 m 行 n列 元素排列成的矩形阵列。是在三维数学中一个强有力的计算工具。

3.1 矩阵乘法

和标量 k 相乘,就讲矩阵内所有的元素与标量 k 相乘。

和另一个矩阵相乘:
5c67bd5ba993f86625a105bbe6a3ab5f.png

3.2 方阵(方块矩阵)

行列相等的矩阵,e.g. 3x3、4x4

3.3 单位矩阵

对角元素值为1,其他元素为0的矩阵。

3.4 转置矩阵

对原矩阵进行转置运算后的矩阵。转置运算后,行变列,列变行。

3.4 逆矩阵

部分方阵 ,有一个矩阵 M^{-1} 能够满足以下条件:

3.5 正交矩阵

一个方阵 和他的转置矩阵相乘为单位矩阵,我们就说这个方阵为正交矩阵。

和逆矩阵公式结合起来,就能得到一个重要性质:如果一个矩阵是正交的,那么它的转置矩阵等于逆矩阵。

运用:现实中逆矩阵计算量很大,但是如果能证明矩阵是正交的,就可以通过求矩阵的转置矩阵,进而得到逆矩阵。通过推断,可以确定三维笛卡尔坐标系的标准正交基就满足3x3的正交矩阵特性。

4. 变换矩阵

变换 指的是将一些数据,如点、方向矢量和颜色等,通过某些方式进行转换的过程。变换矩阵 就是这些方式中的一种。

4.1 线性变换

满足

e.g. 缩放、旋转、错切、镜像、正交投影

4.2 仿射变换

合并线性变换和平移变换的变换类型。因为平移变换不是线性的,无法通过3x3矩阵来表示。因此选择扩展变换矩阵到四维齐次坐标空间 (齐次坐标空间可以通过齐次除法转换到笛卡尔坐标空间)

4.3 平移矩阵

4.4 缩放矩阵

4.5 旋转矩阵



4.6 复合变换

将所有变换统一为线性变换的主要目的,就是为了能够进行组合变换(不满足乘法交换律 ,需要注意顺序)。由于我们使用的是列矩阵,因此执行顺序为从右到左,即先缩放,再旋转,最后平移。

对于旋转,xyz轴顺序和每次旋转后更新坐标系都会影响最终计算结果。Unity 中定义的顺序是 zxy(坐标系不会跟着每次旋转更新)

5. 坐标空间

5.1 模型空间(model space)

也称呼为对象空间(object space)局部空间 ,指的是模型自身的坐标空间。模型空间的原点和坐标轴通常是由美术人员在建模软件中设置好的。

5.2 世界空间(world space)

指的就是游戏空间 ,世界空间的原点就在游戏空间的原点。Unity 的世界空间使用的是左手坐标系。

5.3 观察空间(view space)

也被称呼为摄像机空间(camera space) ,指的就是摄像机的观察空间,此时依旧是三维 空间。在 Unity 中使用的是右手坐标系,因此摄像机的正方向指的是 -z 轴方向。

5.4 裁剪空间(clip space)

也称为齐次裁剪空间 。目的是为了能更方便的对图元进行裁剪,个人理解是对观察空间进行一种类归一化的处理。观察空间通过裁剪矩阵(clip matrix) ,又称投影矩阵(projection matrix) ,进行矩阵变换,转换到的裁剪空间。

根据摄像机种类,视锥体空间分为了两种一种是透视投影(perspective projection,左) ,另一种是正交投影(orthographic projection,右)
e12cc27618020399b20cac84013fd44c.png

相机有几个重要参数,Near、Far 代表剪裁平面离相机的距离,FOV 是视场,能表示视野范围。Apsect 是摄像机宽高比,由 Game 视图的纵横比和设置中的 W 和 H 属性决定。
bfa641305d314dd3a4b2aa31bdc6edb0.png

透视投影的裁剪矩阵。(建立在 Unity 坐标系上,目的是将变换后的 z分量范围约束在 [-w,w] 之间)

视锥体的变化如下图。
4b0a64c1da784a532f40ace34c0a781e.png

正交投影的剪裁矩阵。

视锥体的变化如下图。
dd0c7bb809e4821ac06abd7dc622f67d.png

一个观察空间的点P_{view} 通过对应的剪裁矩阵M变换,得到剪裁空间的点P_{clip},就能判断该坐标点是否在视锥体内

变换后的 P_{clip}坐标为(x,y,z,w),在视锥体内的点满足如下不等式

5.5 屏幕空间(screen space)

就是屏幕的二维空间。 通过齐次除法 ,将齐次裁剪空间转换到归一化的设备坐标(Normalized Device Coordinates) ,然后再通过屏幕的具体像素宽高进行映射,将坐标与屏幕像素坐标对应起来。齐次除法和屏幕映射 的公式可以使用下面公式来总结:

z 分量的值会进行
计算后的值直接存入深度缓冲中。
815b536f8088aaefd68385ef28a1c16d.png

全部评论 (0)

还没有任何评论哟~