【Unity Shader入门精要 第2章】渲染流水线

渲染流水线的工作任务在于,由一个三维场景出发,生成(或叫渲染)一张二维图像。换句话说,计算机需要从一系列的顶点数据、纹理信息出发,把这些信息最终转换成一张人眼可见的图像。

这个过程通常是由CPU和GPU共同完成的。

1. 三个概念阶段

在这里插入图片描述

2. 应用阶段

在CPU中进行

渲染流水线的作用简单用一个字概括就是“画”,应用阶段作为渲染流水线的起始阶段,其主要作用就是准备好“画”的材料并通知“开始画”。

因此,应用阶段的主要工作可以概括为以下三个方面:

  • 准备要画的内容——主要针对Mesh,准备顶点信息,顶点位置、法线、uv坐标等,并上传ObjectBuffer
  • 准备画的材料和方法——主要针对Material,设置渲染状态,设置shader、设置光源属性、设置纹理、上传MaterialBuffer等
  • 通知开始画——调用DrawCall,由CPU调用图形绘制接口,如glDrawElements

2. 几何阶段

在GPU中进行

几何阶段操作的目标是应用阶段提交的顶点信息,其最重要的作用包括四个:

  1. 逐顶点计算(如顶点光照)
  2. 将顶点坐标转换到齐次空间
  3. 裁剪无效顶点
  4. 将顶点坐标映射到屏幕空间

几何阶段细分

在这里插入图片描述
几何阶段中最重要的三个细分阶段分别为顶点着色器、裁剪、屏幕映射,而曲面细分着色器和几何着色器均为可选阶段。

顶点着色器

  • 可编程
  • 对每个由CPU提交的顶点进行并行处理
  • 不可以增减顶点,也没有顶点间的关系数据
  • 可以进行顶点变换、顶点光照等
  • 最重要的作用是将顶点坐标从模型空间转换到投影空间(齐次剪裁空间)

裁剪

  • 不可编程,但可以配置
  • 依据顶点的齐次坐标裁剪掉摄像机范围以外的顶点

屏幕映射

  • 将顶点的齐次坐标映射到二维的屏幕空间中
  • 经过屏幕映射,我们可以得到每个顶点对应在屏幕上的像素坐标,以及该顶点与屏幕的距离(深度)
  • 注意OpenGL的屏幕空间是左下到右上,即左下角为(0,0)右上角为(maxX,
    maxY),而DX的屏幕空间是左上到右下,即左上角为(0,0)右下角为(maxX, maxY)

3. 光栅化阶段

在GPU中进行

经过几何阶段的处理,顶点坐标已经转化为屏幕上的像素坐标,这样就得到了一系列像素坐标以及这些像素坐标对应的光照、法线、深度等信息,我们可以将其称为“片元”。

然而我们从几何阶段获得的片元只是模型三角面顶点对应的片元,为了能够正确完整地将模型绘制在屏幕上,还需要找出这些三角面内部覆盖到的像素坐标以及这些像素坐标对应的光照、法线等等绘制需要的信息,也就是需要生成三角面内部的片元。

光栅化阶段就是从顶点对应的片元信息出发,生成三角面内部片元并最终生成每个片元的颜色信息的阶段。

光栅化阶段细分

在这里插入图片描述

三角形设置

  • 根据三角形的顶点确定三角形的边界
  • 最终确定三角形覆盖范围的表示
  • 是一个构建三角形的过程

三角形遍历

  • 计算上一步构建出的三角形网格覆盖到了哪些像素
  • 用三角形顶点的各种信息进行线性插值,得到其中覆盖的像素对应的各种信息
  • 是一个通过顶点片元插值得到三角面内每个片元的过程

片元着色器

  • 可编程(对应shader里的#pragma fragment XXX)
  • 对每个被三角形覆盖的片元进行并行处理
  • 没有片元之间的关系数据
  • 通常会在片元着色器进行各种纹理采样(有时候根据需要也可以直接在顶点着色器采样)
  • 输出片元的颜色值用于更新对应的渲染目标(颜色缓冲区或者Render Texture)

输出合并

  • 逐片元操作
  • 不可编程,但可配置
  • 经过模板测试、深度测试等对片元的可见性进行测试 舍弃不可见的片元
  • 按照配置的混合模式对可见片元进行颜色混合

4. 一些补充信息

深度测试

  • 针对指定片元对应的像素坐标读取深度缓冲区中记录的深度值
  • 对片元本身的深度值和从深度缓冲区中读取的深度值进行比较
  • 比较的方式可以在shader中进行配置
  • 不满足比较结果的片元视为未通过深度测试,舍弃该片元,满足比较结果的片元视为通过深度测试,进入后续流程
  • 未通过深度测试的片元不会更新深度缓冲区中的深度值
  • 通过深度测试的片元要看shader中是否开启了深度写入,只有开启了深度写入的情况下才会更新深度缓冲区中的值

Early-Z

上面提到深度测试在片元着色器之后进行,但是对于那些没有通过深度测试而舍弃的片元来说,其在片元着色器中的计算完全是没有必要的,因此为了节省这部分性能,可以把深度测试提前,在经过三角形遍历之后,先进行深度测试,只有通过了深度测试的片元才会进入片元着色器进行计算,从而提高效率

但是如果开启了透明度测试,可能出现某一片元先通过了深度测试将其深度写入了深度缓冲区,但该片元可能因为没有通过后续的透明度测试而被舍弃,最终导致深度缓冲区中记录的深度值发生错误

因此,在开启透明度测试的时候不能进行Early-Z,这也是透明度测试会影响效率的原因

透明度测试会在后面介绍

双缓冲机制

我们在屏幕上看到的图像,反映的是颜色缓冲区中的颜色值

在没有中间渲染目标的情况下( 比如Render Texture),光栅化阶段的输出结果会直接写入颜色缓冲区中

此时如果屏幕将颜色缓冲区中的颜色实时显示出来,就会由于渲染流水线中间状态的颜色更新导致画面错误

双缓冲机制通过设置前置缓冲区和后置缓冲区两个颜色缓冲区来解决这个问题

屏幕上显示的颜色始终是前置缓冲区中的颜色

在渲染流水线过程中的颜色更新只写入后置缓冲区,只有当渲染完全结束之后,才会将前置缓冲区和后置缓冲区进行对换,将流水线渲染的结果显示到屏幕上

  • 16
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity Shader是一种用于渲染图形的程序,它可以控制对象的表面颜色、纹理、透明度、反射等属性,从而实现特殊的视觉效果。对于游戏开发者来说,掌握Shader编写技巧是非常重要的。 以下是关于Unity Shader入门精要: 1. ShaderLab语言 ShaderLab是Unity中用于编写Shader的语言,它是一种基于标记的语言,类似于HTML。ShaderLab可以用于定义Shader的属性、子着色器渲染状态等信息。 2. CG语言 CG语言是Unity中用于编写Shader的主要语言,它是一种类似于C语言的语言,可以进行数学运算、向量计算、流程控制等操作。CG语言可以在ShaderLab中嵌入,用于实现Shader的具体逻辑。 3. Unity渲染管线 Unity渲染管线包括顶点着色器、片元着色器、几何着色器等组件,每个组件都有不同的作用。顶点着色器用于对对象的顶点进行变换,片元着色器用于计算每个像素的颜色,几何着色器用于处理几何图形的变形和细节等。 4. 模板和纹理 在Shader中,我们可以使用纹理来给对象添加图案或者贴图,也可以使用模板来控制对象的透明度、反射等属性。纹理可以通过内置函数tex2D()来获取,模板可以通过内置函数clip()来实现裁剪。 5. Shader的实现 Shader的实现需要注意以下几点: - 在ShaderLab中定义Shader的属性、子着色器渲染状态等信息。 - 在CG语言中实现Shader的具体逻辑,包括顶点着色器、片元着色器等内容。 - 使用纹理和模板来实现特定的视觉效果。 - 在对象上应用Shader,通过调整Shader的属性来达到不同的效果。 以上是关于Unity Shader入门精要,希望对你有所帮助。如果你想更深入地了解Shader的编写技巧,可以参考官方文档或者相关教程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值