zoukankan      html  css  js  c++  java
  • WebGL 踩坑系列-1

    WebGL 中的一些选项
    WebGL 中开启颜色混合(透明效果)
    gl.enable(gl.BLEND);   
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);

    设置遮挡剔除有效。生成三角形时,沿着逆时针方向的那面会被生成出来,而另一面就不会生成出来。

    gl.enable(gl.CULL_FACE); 
    gl.cullFace(gl.BACK);

    观察球面的效果:

    当设置透明效果却不开启遮挡剔除的时候,用 web GL 生成球面,在球外观察球面时就会看到一些奇怪的角。

     第二个球就很明显的有一些不同的部分。

    在 web GL 中使用矩阵

    可以利用矩阵的平移、旋转、缩放实现物体的各种动作。

    我在最开始使用 Web GL 绘图的时候,球面上的点都是利用循环得到,但是由于有缩放球面的需求,所以最开始的做法是

    1. 创建缓冲区时用的 gl.DYNAMIC_DRAW

    2. 当要缩放球面时,重新计算顶点

    3. 用 gl.updateBufferData 函数更新定点数据

    当缩放的时候就能明显看到画面撕裂,帧率下降。

    可能的原因是:

    1. 每次重新计算都要使用大量的计算资源,若帧率为 60,那么每秒要计算上千个顶点,如果球面较精细,那么需要计算的顶点数更多。

    2. 并且每次计算之后都要将这些顶点传入到 GPU 中,可能会占用一部分的传输带宽

    正常的做法是用坐标变换矩阵,将变换后的矩阵通过  gl.uniformMatrix4fv 传入到着色器,就可以轻松的实现平移旋转和缩放。并且不会造成性能严重下降。

    但是矩阵的乘法与普通的数乘有所差别,矩阵的乘法一般不满足交换律。

    若 pMatrix 表示透视矩阵,vMatrix 表示视图矩阵,mMatrix 表示模型矩阵,aVertex 表示传入的顶点,那么一般的乘式是

    gl_Position = pMatrix * vMatrix * mMatrix * aVertex;

    如果矩阵的顺序不同,可能最后得到的图形也就不同。

    对矩阵先进行旋转操作,再进行平移操作。缩放操作的顺序一般没有影响。

    但我在使用 gl-Matrix.js 时,对一个矩阵先进行旋转,再进行平移操作:

    1 mat4.identity(this.mMatrix);
    2 
    3 mat4.fromRotation(this.mMatrix, angle[1] * Math.PI*2, [0, 0, 1]);
    4 mat4.rotate(this.mMatrix, this.mMatrix, angle[0] * Math.PI, [0, 1, 0]);
    5 mat4.translate(this.mMatrix, this.mMatrix, pos);
    6 
    7 mat4.multiply(mvpMatrix, pvMatrix, this.mMatrix);
    8 gl.uniformMatrix4fv(uniforms.pmv_matrix, false, mvpMatrix);

    和将旋转操作和平移操作放在两个矩阵中进行得到的结果并不相同。

    1 mat4.identity(this.mMatrix);
    2 
    3 mat4.fromRotation(this.rMatrix, angle[1] * Math.PI*2, [0, 0, 1]);
    4 mat4.rotate(this.rMatrix, this.rMatrix, angle[0] * Math.PI, [0, 1, 0]);
    5 mat4.translate(this.mMatrix, this.mMatrix, pos);
    6 mat4.mul(this.mMatrix, this.mMatrix, this.rMatrix);
    7 
    8 mat4.multiply(mvpMatrix, pvMatrix, this.mMatrix);
    9 gl.uniformMatrix4fv(uniforms.pmv_matrix, false, mvpMatrix);

    注意这里用 pvMatrix 乘  mMatrix 之前先用 mMatrix 乘了一个附加矩阵 rMatrix

    具体的原因并不清楚,但是第二个操作实现的图像符合我的需求。

    =========================

    这几天又重新测试了下代码,发现上面的旋转平移操作的矩阵还是有些问题,

    具体问题在于经过旋转平移后的面上反的,以下矩阵操作可以方便的做到旋转平移,并且得到的面上正的

    1 mat4.fromZRotation(this.rMatrix,         this.beta);   // 绕 Z 轴旋转 beta 角
    2 mat4.rotateY(this.rMatrix, this.rMatrix, this.theta);  // 再绕 Y 轴旋转 theta 角 
    3 mat4.fromRotationTranslation(this.mMatrix, this.rMatrix, pos);
    4 mat4.rotateZ(this.mMatrix, this.mMatrix, this.beta);
    5 mat4.rotateY(this.mMatrix, this.mMatrix, this.theta);

    最后得到的面就是我想要的

    完整的代码可以在我的 GitHub 上查看。

    本博客由 BriFuture 原创,并在个人博客(WordPress构建) BriFuture's Blog 上发布。欢迎访问。
    欢迎遵照 CC-BY-NC-SA 协议规定转载,请在正文中标注并保留本人信息。
  • 相关阅读:
    【EF学习笔记11】----------查询中常用的扩展方法
    .NET 扩展方法
    【EF学习笔记10】----------主从表级联操作
    【EF学习笔记09】----------使用 EntityState 枚举标记实体状态,实现增删改查
    【EF学习笔记08】----------加载关联表的数据 显式加载
    【EF学习笔记07】----------加载关联表的数据 贪婪加载
    【EF学习笔记06】----------加载关联表的数据 延迟加载
    Linux内核ROP姿势详解(二)
    见微知著(三):解析ctf中的pwn--Fastbin和bins的溢出
    见微知著(二):解析ctf中的pwn--怎么利用double free
  • 原文地址:https://www.cnblogs.com/brifuture/p/8206867.html
Copyright © 2011-2022 走看看