学习WebGL之绘制正方体

作者: handyTOOL | 来源:发表于2017-07-13 16:35 被阅读101次

本系列所有文章目录

下面是本文例子的运行截图,可以前往我的博客查看代码演示。

经过前面7篇文章的铺垫,绘制正方体已经不是什么难事了。正方体其实就是由6个矩形组成的几何体,X,Y,Z轴上各两个矩形。下面是Z轴上两个矩形的示意图。


绘制Z轴需要的顶点数据如下。

-0.5,   0.5,    0.5,  
-0.5,   -0.5,   0.5, 
0.5,    -0.5,   0.5, 
0.5,    -0.5,   0.5,  
0.5,    0.5,    0.5,   
-0.5,   0.5,    0.5, 

-0.5,   0.5,    -0.5, 
-0.5,   -0.5,   -0.5,
0.5,    -0.5,   -0.5,
0.5,    -0.5,   -0.5, 
0.5,    0.5,    -0.5,  
-0.5,   0.5,    -0.5,

其他轴的平面绘制规则一样,将Z轴数据第三列交换到第一列或者第二列即可生成X,Y轴上的矩形数据。

// X轴上的平面
0.5,    -0.5,   0.5,
0.5,    -0.5,   -0.5,
0.5,    0.5,    -0.5,
0.5,    0.5,    -0.5,
0.5,    0.5,    0.5,
0.5,    -0.5,   0.5,
-0.5,   -0.5,   0.5,
-0.5,   -0.5,   -0.5,
-0.5,   0.5,    -0.5,
-0.5,   0.5,    -0.5,
-0.5,   0.5,    0.5,
-0.5,   -0.5,   0.5,
// Y轴上的平面
-0.5,   0.5,    0.5,  
-0.5,   0.5,    -0.5,  
0.5,    0.5,    -0.5,  
0.5,    0.5,    -0.5,  
0.5,    0.5,    0.5,  
-0.5,   0.5,    0.5,  
-0.5,   -0.5,   0.5,
-0.5,   -0.5,   -0.5,
0.5,    -0.5,   -0.5,
0.5,    -0.5,   -0.5,
0.5,    -0.5,   0.5,
-0.5,   -0.5,   0.5,

使用上面这些的顶点数据生成Buffer供渲染使用。

function makeBuffer() {
  var triangle = [
      // Z轴上的平面
      -0.5,   0.5,    0.5,  
      -0.5,   -0.5,   0.5, 
      0.5,    -0.5,   0.5, 
      0.5,    -0.5,   0.5,  
      0.5,    0.5,    0.5,   
      -0.5,   0.5,    0.5, 
      -0.5,   0.5,    -0.5, 
      -0.5,   -0.5,   -0.5,
      0.5,    -0.5,   -0.5,
      0.5,    -0.5,   -0.5, 
      0.5,    0.5,    -0.5,  
      -0.5,   0.5,    -0.5,
      // X轴上的平面
      0.5,    -0.5,   0.5,
      0.5,    -0.5,   -0.5,
      0.5,    0.5,    -0.5,
      0.5,    0.5,    -0.5,
      0.5,    0.5,    0.5,
      0.5,    -0.5,   0.5,
      -0.5,   -0.5,   0.5,
      -0.5,   -0.5,   -0.5,
      -0.5,   0.5,    -0.5,
      -0.5,   0.5,    -0.5,
      -0.5,   0.5,    0.5,
      -0.5,   -0.5,   0.5,
      // Y轴上的平面
      -0.5,   0.5,    0.5,  
      -0.5,   0.5,    -0.5,  
      0.5,    0.5,    -0.5,  
      0.5,    0.5,    -0.5,  
      0.5,    0.5,    0.5,  
      -0.5,   0.5,    0.5,  
      -0.5,   -0.5,   0.5,
      -0.5,   -0.5,   -0.5,
      0.5,    -0.5,   -0.5,
      0.5,    -0.5,   -0.5,
      0.5,    -0.5,   0.5,
      -0.5,   -0.5,   0.5,
  ];
  buffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangle), gl.STATIC_DRAW);
  return buffer;
}

我移除了modelMatrix2,将modelMatrix1改为modelMatrix。每一次render的时候我将modelMatrix的赋值修改为围绕1,1,1轴旋转。

window.onWebGLRender = function render(deltaTime, elapesdTime) {
   ...
  var varyingFactor = (Math.sin(elapsedTime / 1000) + 1) / 2.0; // 0 ~ 1

  var rotateMatrix = mat4.create();
  var translateMatrix = mat4.create();
  mat4.rotate(rotateMatrix, rotateMatrix, varyingFactor * Math.PI * 2, vec3.fromValues(1, 1, 1));
  mat4.translate(translateMatrix, translateMatrix, vec3.fromValues(0, 0, -0.5));
  mat4.multiply(modelMatrix, translateMatrix, rotateMatrix);

  ...
}

最后在onWebGLRender中绘制正方体。

window.onWebGLRender = function render(deltaTime, elapesdTime) {
  ...
  var varyingFactor = (Math.sin(elapsedTime / 1000) + 1) / 2.0; // 0 ~ 1

  var rotateMatrix = mat4.create();
  var translateMatrix = mat4.create();
  mat4.rotate(rotateMatrix, rotateMatrix, varyingFactor * Math.PI * 2, vec3.fromValues(1, 1, 1));
  mat4.translate(translateMatrix, translateMatrix, vec3.fromValues(0, 0, -0.5));
  mat4.multiply(modelMatrix, translateMatrix, rotateMatrix);

  // 设置投影和观察矩阵
  var projectionMatrixUniformLoc = gl.getUniformLocation(program, 'projectionMatrix');
  gl.uniformMatrix4fv(projectionMatrixUniformLoc, false, perspectiveProjectionMatrix);
  var cameraMatrixUniformLoc = gl.getUniformLocation(program, 'cameraMatrix');
  gl.uniformMatrix4fv(cameraMatrixUniformLoc, false, cameraMatrix);

  var modelMatrixUniformLoc = gl.getUniformLocation(program, 'modelMatrix');
  gl.uniformMatrix4fv(modelMatrixUniformLoc, false, modelMatrix);
  gl.drawArrays(gl.TRIANGLES, 0, 36);
}

为了使正方体绘制正常,还有一个很重要的配置代码gl.enable(gl.DEPTH_TEST);。如果不调用它,绘制的结果是这样的。你会发现像素的前后顺序有些不对。

为什么会这样呢?默认情况下,谁后绘制谁在最上面,而gl.enable(gl.DEPTH_TEST);之后;绘制顺序则按照Z轴的坐标为准。为了配合gl.enable(gl.DEPTH_TEST);,还要将gl.clear(gl.COLOR_BUFFER_BIT);改成gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);,因为按照Z轴排序是要激活一个新的深度缓存区的,所以每次清除缓存区的时候不仅要清除颜色缓存数据还要清除深度缓存数据,否则会影响新的深度数据的写入。修改了两处之后,效果如下。

这次就正常了。本文主要介绍了绘制正方体的思路和方法,读者可以拓展一下,比如绘制由4个三角形构成的三角锥。立体几何体基本都可以分解成很多三角形,只要找到规律,绘制起来就很简单。

下一篇开始讲解基本的光照模型,让立方体看起来更真实。

相关文章

  • 学习WebGL之绘制正方体

    本系列所有文章目录 下面是本文例子的运行截图,可以前往我的博客查看代码演示。 经过前面7篇文章的铺垫,绘制正方体已...

  • 学习WebGL文章目录

    基础篇 第一个WebGL程序绘制三角形深入了解Shader绘制点线面变换矩阵透视和正交投影摄像机绘制正方体基本光照...

  • WebGL之物体选择

    原文地址: WebGL之物体选择 使用WebGL将图形绘制到画布后,如何与外部进行交互?这其中最关键的就是如何实现...

  • TWaver3D直线、曲线、曲面的绘制

    1. WebGL原生线 WebGL支持绘制点、线、三角;绘制线的方法比较简单,给定顶点,设置绘制方式即可; 假设给...

  • 学习WebGL之绘制点线面

    本系列所有文章目录 本文将详细介绍WebGL三角形之外的其余绘制模式,下面是运行截图,通过下拉菜单可以选择不同的绘...

  • WebGL 绘制Line的bug(一)

    熟悉WebGL的同学都知道,WebGL绘制模式有点、线、面三种;通过点的绘制可以实现粒子系统等,通过线可以绘制一些...

  • webgl入门(一)

    webgl是基于 canvas 进行绘制,通过 getWebGLContext()来获取 webgl 的绘图上下文...

  • OpenGL-ES 学习示例

    OpenGL-ES 学习示例 描述:1、GLKit 绘制图片和正方体2、GLSL 绘制金字塔、颜色纹理混合3、GL...

  • 用线段绘制球体(three.js webgl_lines_spe

    用线段绘制球体(three.js webgl_lines_spere例子) Three.js中的webgl_lin...

  • Threejs in autonomous driving -(

    绘制各种几何体是webgl的强项,相反各种异性几何体就非常麻烦。比如圆角矩形来说在webgl中绘制就相对比较麻烦。...

网友评论

    本文标题:学习WebGL之绘制正方体

    本文链接:https://www.haomeiwen.com/subject/opkwhxtx.html