WebGL渲染管线

渲染管线

  • WebGL是个状态机,需要先提前设置所有状态,通过DrawCall命令GPU顺着渲染管线来调用设置好的所有状态,最终获得Framebuffer

  • 设置所有状态的过程都是在CPU上跑,DrawCall命令下的渲染管线是GPU上跑

  • 渲染管线存在可编程阶段,可配置阶段,不可配置阶段,可选阶段等

  • 不同厂商实现的渲染管线部分不同
    空间

顶点数据(Vertex Data)

  • 缓冲对象来存储顶点数据(位置,纹理坐标,法线等),它会在GPU内存(通常被称为显存)中储存大量顶点数据。
  • 使用这些缓冲对象的好处是我们可以一次性的发送一大批数据到显卡上,而不是每个顶点发送一次。
  • 常见的图元包括:点(GL_POINTS)、线(GL_LINES)、线条(GL_LINE_STRIP)、三角面(GL_TRIANGLES)。
  • 常见的处理信息有uv,position,normal,indices,color
  • API:gl.getAttribLocation();gl.getUniformLocation()glGenVertexArrays()、glGenBuffers()、glBindBuffer()、glBindVertexArray()、glVertexAttribPointer()、VBO

顶点着色器(Vertex Shader)

  • 如果存在非均匀缩放变换(Scaling)我们需要使用矩阵的逆的转置来变换法线。

  • 一旦你的顶点坐标已经在顶点着色器中处理过,它们就应该是标准化设备坐标(NDC)了,标准化设备坐标是一个x、y和z值在-1.0到1.0的一小段空间。

  • 着色器里涉及到的关键字有(gl_Position,gl_PointSize,gl_)

  • attribute变量:用户自定义变量,一般是存储顶点属性的变量;

  • uniform变量:恒值变量,一般表示每个顶点都一致的变量,比如变换矩阵、光照等;

  • varying变量:易变变量,将顶点着色器的数据传递给片段着色器时使用;

  • 顶点的xyz靠近远平面(还没除w);图元

曲面细分

  • 可选阶段

几何着色器(Geometry Shader)

  • 可选阶段

图元装配(Primitive Setup)

  • 裁剪 (Culling And Clipping)
    • 把坐标的x、y、z分量不全在(-1,1)区间内的图元(或者图元的部分)抛弃掉

    • 线段的两个顶点一个位于视椎体内而另一个位于视椎体外,那么位于外部的顶点将被裁剪掉,而且在视椎体与线段的交界处产生新的顶点。

    • 用户可以指定额外的裁剪面:glClipPlane(GL_CLIP_PLANE0[1,2,…],double eqn[4]),glEnable/Disable(GL_CLIP_DISTANCE0[1,2,…]

  • 背面剔除 (Back-Face Culling)
    • 光栅化在对多边形图元进行“方块化”之前,要给出多边形是front-facing还是back-facing
    • 根据多边形顶点的环绕方向确定的是顺时针还是逆时针,默认逆时针为front-facing,可由glFrontFace(GL_CCW[CW])控制
    • 通过glCullFace()函数来配置剔除的是正面还是背面,参数为GL_FRONT、GL_BACK(默认值)和GL_FRONT_AND_BACK
    • 通过glEnable(GL_CULL_FACE)函数来开启背面剔除的优化。
    • 渲染半透明或不透明物体时,不能使用该技术
  • 透视除法(Perspective Division)
    • 执行透射除法后(除以w分量),我们可以得到标准设备空间,该空间一般也称作标准视体(Canonical View Volume,CVV)
    • 透射除法是由硬件自动执行的
    • 正交投影变换并没有改变W分量的值(W分量的值仍是1)
  • 视口变换 (Viewport Transform)
    • 视口变换同时也将原来z坐标缩放到[0,1]变成Depth值;可以指定深度值范围:glDepthRange(GLclampd n,GLclampd f)

光栅化

  • 光栅化主要包括两个过程:三角形的组装和三角形的遍历。
  • 三角形组装会对顶点的输入数据进行插值。
  • 三角形遍历覆盖了哪些片段的采样点,随后得到该图元所对应的片元,对于透射投影,我们需要用到透射校正插值(Perspetive-Correct-Interpolation)
  • 点和直线只有正面
  • 光栅化除了直接对多边形进行填充这种方式之外,还可以只构造边或只有点,这由glPolyMode(GL_FRONT[BACK,FRONT_AND_BACK],GL_FILL[LINE,POINT])控制。
  • 光栅化对图元进行“小方块化”并对“小方块”进行插值
  • 点采样

片段着色器

  • 片段着色器是通过编程控制屏幕上显示颜色和它的深度值
  • 这个过程颜色并非最终颜色

测试混合阶段(Tests & Blending)

  • 各种测试(下图中共5个),每步测试,不通过的片断将被丢弃从而不能进入后续操作,然后进行一些操作(如混合),最终通过所有处理的片断将被写入FrameBuffer用于最终屏幕显示

  • 这些操作可以用glEnable/glDisable(GL_ALPHA/STENCIL/DEPTH_TEST)、glEnable/glDisable(GL_BLEND)等打开或关闭,对于RGBA, Depth, Stencil Buffer,可以用glColor/Depth/StencilMask(GLboolean/GLuint)进行控制是否可写。

  • 裁切测试
    • Scissor Test对用户指定的scissor rectangle进行测试
    • 裁切测试可以避免当视口比屏幕窗口小时造成的渲染浪费问题。
    • 通过glEnable(GL_SCISSOR_TEST)来开启裁切测试,通过glScissor()来指定裁切区域。
  • alpha测试
    • 指的是将一个像素点的alpha值和一个固定值比较,如果比较的结果失败,像素将不会被写到显示输出中;
    • alpha测试本身消耗较大,性能较低,必要的情况下才会使用alpha测试。
  • 深度测试
    • 抛弃掉位置靠后的像素值,因为这个位置的像素本身就是被更前面的像素覆盖的;
    • 通过glEnable(GL_DEPTH_TEST)来开启深度测试
    • 通过深度函数glDepthFunc()来设置深度比较运算符
    • 渲染半透明物体时,需要开启深度测试而关闭深度写入功能。
  • 模板测试
    • Stencil Test可以根据Stencil或Depth Buffer Test结果分条件更新Stencil Buffer实现很多功能。
    • 通过glEnable(GL_STENCIL_TEST);开启模板测试
    • 我们可以利用模板测试来实现平面镜效果、平面阴影和物体轮廓等功能。
  • Alpha混合
    • Alpha混合可以根据片段的alpha值进行混合,用来产生半透明的效果。
    • 通过glEnable(GL_BLEND)来开启混合的功能
    • 通过glBlendFuncSeparate()、glBlendFunc()和glBlendEquation()来设置各种混合效果,常见的选项有GL_ZERO、GL_ONE、GL_SRC_ALPHA、GL_FUNC_ADD等。
  • 抖动处理 (Dithering)
    • 抖动可以用来增加可用的颜色数量
    • 通过glEnable(GL_DITHER)来控制抖动输出功能,默认是开启的

帧缓存FBO(Frame Buffer Object)

  • 数据经过整个渲染管线处理之后,最终会写入到帧缓存中,帧缓存存储了最终会显示到屏幕上的颜色数据。
  • 帧缓存是颜色缓存、深度缓存、模板缓存、累积缓存的集合。
  • API:gl.clearColor();gl.clear();gl.COLOR_BUFFER_BIT;
颜色缓存(比深度缓存精度更高)
  • 16位:RGB565,红色5位,绿色6位,蓝色5位,不保存透明通道(之所以绿色多1位是因为人眼对绿色更加敏感);
  • 24位:RGB888,红色8位,绿色8位,蓝色8位,不保存透明通道;
  • 32位:RGBA8888,红色8位,绿色8位,蓝色8位,透明通道8位;
Z-缓存(深度缓存)
  • 存储每个像素点的深度,用来决定是丢弃当前像素颜色还是保留,假设,新渲染的颜色在旧颜色的前面,那么就覆盖旧颜色,如果新颜色在旧颜色的后面(被遮挡了)则保留旧颜色。
模板缓存
  • 用来控制颜色缓存某个位置的写入操作,常用来处理阴影。
参考资料

(1条消息) OpenGL——GPU图形渲染管线_&动感超人的博客-CSDN博客
细说图形学渲染管线 - 知乎 (zhihu.com)
WebGL学习笔记(一):理解基本概念和渲染管线 - 阿诚de窝 - 博客园 (cnblogs.com)
(1条消息) 关于DrawCall及渲染流程的认识总结_GR90的博客-CSDN博客
(1条消息) WebGL—实现使用FBO离屏渲染(亦同拷贝纹理)off-screen rendering的两种方式_weixin_43787178的博客-CSDN博客
https://zhuanlan.zhihu.com/p/65969162

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值