<十>入门CocosShader之WebGL基础知识

渲染管线

渲染管线描述了游戏中一帧渲染的流程顺序,包含了所有渲染有关的环节。
涉及到的核心硬件是CPU和GPU。
CPU是单行通道,处理任务的效率取决于处理单个任务的时间。
CPU处理复杂的逻辑以及大型的任务都游刃有余,但处理图像的效率却很低。这是因为图像是有成千上万个像素点构成的,每一个像素的处理都是一个任务。
GPU是由大量的小型处理单元构成的,处理能力不如CPU,但胜在处理单元多而且能并行处理,所以处理并不复杂的像素非常合适。
对于图像来说,CPU不做数据处理,而是把数据都丢给GPU,GPU开始处理这些数量多又不复杂的数据,最后组装出可以在屏幕上显示的图像。

什么是WebGL

WebGL是一种3D的绘图API,它的本质是通过JS调用OpenGL的接口封装而成的一套标准。
WebGL可以根据代码绘制出点、线、三角形,任何复杂的场景都可以通过点、线、三角形构成。
WebGL是运行在GPU中,因此需要可以运行在GPU上的程序(Shader),这样的程序需要成对的提供,每对方法中都需要提供一个顶点着色器和一个片元着色器,着色程序使用GLSL编写,这样的成对的程序组合起来就是一个着色程序(Shader)。

在WebGL中,任何事物都是在3D空间里,而最终输出呈现给观众的往往都是屏幕或窗口这种2D像素。因此在渲染引擎的底层工作中,大部分都是将3D坐标转换成适应屏幕的2D像素。
3D坐标转2D的过程是由渲染管线处理的,它的主要流程分为两步:

  1. 3D坐标转2D坐标
  2. 把2D坐标转换成有实际颜色的像素
    这两个主要的步骤又分为几个阶段,每个阶段都会把上一个阶段的输出作为输入。
    image
    如图,顶点数据是渲染管线中处理数据的主要来源,输入到渲染管线的顶点数据主要包括:
  • 顶点坐标
  • 纹理坐标
  • 顶点法线
  • 顶点颜色
    ...

顶点数据

顶点数据和矩阵都来自CPU,顶点数据想要传入顶点着色器需要先传入缓存区,这是一个CPU向GPU传入数据的过程。
指定解析方式数据传入顶点着色器,矩阵则可以通过uniform的方式传递,uniform相当于一个全局变量。
因为在WebGL中顶点之间是无法获取相互的数据的,而通过uniform的方式,所有的顶点都可以获得矩阵变换信息。

顶点着色器

顶点着色器的主要功能是坐标转换。
把一个单独的顶点作为输入,并对顶点进行从局部坐标到裁剪坐标的变换,其实就是将游戏里操作的 3D 坐标转换成另一种 3D 坐标。
image
通常在游戏开发工具里操作的都是局部坐标,也叫本地坐标(也有一些工具是直接操作的世界坐标)。
如果是局部坐标,需要通过模型变换矩阵将局部坐标转换为世界坐标。
一个物体如何呈现还需要通过相机来决定,因此需要将世界坐标通过视图变换矩阵转换到观察空间。
最后通过投影矩阵变换转换到裁剪空间,最后输出到屏幕上。

图元装配

图元装配阶段会将所有顶点着色器输出的所有顶点作为输入。
image
根据对应的指令,比如要绘制成点、还是线、或是面,将所有的点装配成指定图元的形状。
图元装配完成后还需要进行屏幕映射,确定最终需要在屏幕上绘制的点。
然后开始下一个阶段“光栅化”处理。

光栅化

光栅化阶段会遍历所有的像素,依次判断它们是否落入了组装的图形内,如果在图形内则进行下一步的操作。
还会对非顶点的位置进行插值处理,赋予每个像素其他的信息。

片段着色器

片段着色器主要是图形内的片元进行着色处理。在该阶段会进行光照计算处理和阴影处理,也就是高级效果产生的阶段。
在对应的颜色被处理以后,所有的对象都会被传入最后一个阶段:alpha测试与混合阶段。

alpha测试与混合阶段

该阶段会检测片段对应的深度,以此来判断该像素是在其他物体的前面还是后面,判断是否应该丢弃。也会检测透明度alpha的值,并对物体进行混合。
所以,即使在片段着色器中计算出了最终要显示的像素的输出颜色,在最终显示时也可能完全不同。

GLSL基础

着色器程序是由GLSL编写的,GLSL是为图形计算量身定制的语言,它包含了一些针对向量和矩阵运算的特性。

一个着色器通常包含了输入、输出变量、uniform和main函数。
每个着色器的入口都是main函数,在main函数中处理所有输入变量,并将结构输出到输出变量。

示例:顶点着色器
image
如图:
1.最后输出的(返回的)gl_position是一个Vec4,如果输入的变量是vec2或ve c3需要做一下转换
2.顶点数据是无法直接传递给片段着色器的,但渲染管线中每个阶段的输出可以作为下一个阶段的输入,所以如上如果需要把顶点坐标传递给片元着色器,就需要声明一个对应的输出变量并赋值,以此传递给片元着色阶段,需要注意在片元着色器中定义的该输入变量类型需要和顶点着色器中定义的输出变量类型一致。

示例:片段着色器
image
如上,在片段着色器中声明一个uniform 的2D纹理,在main函数中将2D纹理和顶点坐标作用后的颜色作用与gl内置变量gl_color.
当然如果只是绘制一个纯色图形的话,可以不传纹理。

image

image

image
也可以直接对每一个向量的分量赋值
image

image
向量和矩阵都是可以通过逐分量操作的。

限定符

image

存储限定符

image

参数限定符

image

精度限定符

image

状态机和上下文

状态机

在WebGL中,大多数的元素都可以用状态来描述,比如是否开启了光照,是否启用了纹理,是否启用了混合...
通常WebGL都会执行一个默认的状态,除非调用相关的接口来改变它。
比如是否开始光照就可以通过gl.Enablexxx来启用,通过gl.disEnablexxx来禁用。

上下文

WebGL需要依赖Canvas这个载体来获取对应绘图上下文,通过绘图上下文来调用对应的绘图API。
WebGL绘图上下文创建的方法如下:
image

posted @ 2025-02-18 14:13  EricShx  阅读(30)  评论(0)    收藏  举报