WebGL入门学习:绘制圆锥

1、圆锥的几何构造

从上面看:是一个圆,严格说是一个正N多边形,N值越大,越接近圆。绘制时要用三角函数计算正N多边形的N个顶点坐标。

 

 从侧面看是个三角形:最下面是一个顶点,和上面的正N多边形顶点相连构成圆锥网格。

 

 

2、WebGL代码实现

1)顶点着色器:

const VSHADER_SOURCE = `
  attribute vec4 a_Position;
  attribute vec4 a_Color;
  uniform mat4 u_MvpMatrix;
  varying vec4 v_Color;
  void main() {
    gl_Position = u_MvpMatrix * a_Position;
    v_Color = a_Color;
  }`;

 

2)片元着色器:

const FSHADER_SOURCE = `
  #ifdef GL_ES
  precision mediump float;
  #endif
  varying vec4 v_Color;
  void main() {
    gl_FragColor = v_Color;
  }`;

  

3)初始化顶点坐标缓冲区

function initVertexBuffers(gl) {
  let radius = 1;
  let height = 2;
  let divideNum = 60;
  let theta = Math.PI * 2 / divideNum;

  /**
   *  
   *      4
   *   /    \
   * 3        1
   *  \      /
   *     2 /
   *    \ /
   */    0
  let vertices = [0, -height / 2, 0];
  for (let i = 0; i < divideNum; i++) {
    let x = radius * Math.cos(theta * i);
    let z = radius * Math.sin(theta * i);
    vertices.push(x, height / 2, z);
  }


  let colors = [];
  let baseColor = [[1.0, 0.4, 0.4], [0.4, 1.0, 0.4], [0.4, 0.4, 1.0], [0.2, 0.4, 0.0], [0.4, 0.3, 0.8],[0.8, 1, 0.1] ];

  colors.push(1.0, 0.4, 0.4);
  for(let i=1; i<vertices.length; i++) {
    // let color = baseColor[Math.floor(Math.random()*6)];
    // colors = colors.concat(color);
    colors.push(0.4, 1.0, 0.4);
  }


  let indices = [];
  for(let i=1; i<=divideNum; i++) {
    if(i===divideNum){
      indices.push(0, i, 1);
    }else{
      indices.push(0, i, i+1);
    }
  }

  vertices = Float32Array.from(vertices);
  colors = Float32Array.from(colors);
  indices = Uint8Array.from(indices);


  // Create a buffer object
  var indexBuffer = gl.createBuffer();
  if (!indexBuffer)
    return -1;

  // Write the vertex coordinates and color to the buffer object
  if (!initArrayBuffer(gl, vertices, 3, gl.FLOAT, 'a_Position'))
    return -1;

  if (!initArrayBuffer(gl, colors, 3, gl.FLOAT, 'a_Color'))
    return -1;

  // Write the indices to the buffer object
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);

  return indices.length;
}

  

function initArrayBuffer(gl, data, num, type, attribute) {
  var buffer = gl.createBuffer();   // Create a buffer object
  if (!buffer) {
    console.log('Failed to create the buffer object');
    return false;
  }
  // Write date into the buffer object
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
  // Assign the buffer object to the attribute variable
  var a_attribute = gl.getAttribLocation(gl.program, attribute);
  if (a_attribute < 0) {
    console.log('Failed to get the storage location of ' + attribute);
    return false;
  }
  gl.vertexAttribPointer(a_attribute, num, type, false, 0, 0);
  // Enable the assignment of the buffer object to the attribute variable
  gl.enableVertexAttribArray(a_attribute);

  return true;
}

  

3)初始化WebGL上下文,绘制圆锥

function main() {
  // Retrieve <canvas> element
  var canvas = document.getElementById('webgl');

  // Get the rendering context for WebGL
  var gl = getWebGLContext(canvas);
  if (!gl) {
    console.log('Failed to get the rendering context for WebGL');
    return;
  }

  // Initialize shaders
  if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
    console.log('Failed to intialize shaders.');
    return;
  }

  // Set the vertex information
  var n = initVertexBuffers(gl);
  if (n < 0) {
    console.log('Failed to set the vertex information');
    return;
  }

  // Set the clear color and enable the depth test
  gl.clearColor(0.0, 0.0, 0.0, 1.0);
  gl.enable(gl.DEPTH_TEST);

  // Get the storage location of u_MvpMatrix
  var u_MvpMatrix = gl.getUniformLocation(gl.program, 'u_MvpMatrix');
  if (!u_MvpMatrix) {
    console.log('Failed to get the storage location of u_MvpMatrix');
    return;
  }

  // Set the eye point and the viewing volume
  var mvpMatrix = new Matrix4();
  mvpMatrix.setPerspective(30, 1, 1, 100);
  // mvpMatrix.lookAt(0, 2, 8, 0, 0, 0, 0, 2, 0);
  // mvpMatrix.lookAt(0, 6, 0, 0, 0, 0, 0, 0, -2);  //view from top
  // mvpMatrix.lookAt(0, 1, 5, 0, 0, 0, 0, 1, 0);    //view from front
  mvpMatrix.lookAt(0, 2, 5, 0, 0, 0, 0, 1, 0);    //view from front and more high
  // Pass the model view projection matrix to u_MvpMatrix
  gl.uniformMatrix4fv(u_MvpMatrix, false, mvpMatrix.elements);

  // Clear color and depth buffer
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

  // Draw the cube
  // gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0);
  gl.drawElements(gl.LINE_LOOP, n, gl.UNSIGNED_BYTE, 0);
}

  

4)HTML文件,这里的部分WebGL封装代码引用之《WebGL编程指南》

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Cone</title>
  </head>
  <body onload="main()">
    <canvas id="webgl" width="400" height="400">
    Please use a browser that supports "canvas"
    </canvas>
 
    <script src="../lib/webgl-utils.js"></script>
    <script src="../lib/webgl-debug.js"></script>
    <script src="../lib/cuon-utils.js"></script>
    <script src="../lib/cuon-matrix.js"></script>
    <script src="cone.js"></script>
  </body>
</html>

  

 3、效果展示:

 

 

posted on 2020-10-11 16:46  DavidXu2014  阅读(952)  评论(0编辑  收藏  举报