簡體   English   中英

在WebGL中繪制3D形狀的第一步

[英]First steps with drawing 3D shapes in WebGL

我從幾周開始學習WebGL,但是在繪制一些3D形狀時遇到了問題。 猜猜我正在計算頂點和索引以及每個三角形的顏色,但是它不起作用。 有人可以告訴我我在做什么錯嗎? 我想制作一個看起來像的金字塔: 在此處輸入圖片說明

這是代碼:

 var gl = null, canvas = null, glProgram = null, fragmentShader = null, vertexShader = null; var coordinateArray = [ ], triangleVerticeColors = [ ], verticesArray = [ ], verticesIndexArray = [ ]; var vertexPositionAttribute = null, trianglesVerticeBuffer = null, vertexColorAttribute = null, trianglesColorBuffer = null, triangleVerticesIndexBuffer = null; var P = mat4.create(), V = mat4.create(); M = mat4.create(); function initWebGL() { canvas = document.getElementById("my-canvas"); try { gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl"); } catch (e) { } if (gl) { setupWebGL(); initShaders(); setupBuffers(); getMatrixUniforms(); setMatrixUniforms(); animationLoop(); //drawScene(); } else { alert("Error: Your browser does not appear to" + "support WebGL."); } } function animationLoop() { var R = mat4.create(); var angle = 0; var i = 0; var loop = function() { angle = performance.now() / 1000 / 6 * 2 * Math.PI; i++; mat4.rotate(M, R, angle, [ 0, 1, 0 ]); gl.uniformMatrix4fv(glProgram.mvMatrixUniform, false, M); gl.clearColor(0.1, 0.5, 0.1, 1.0); gl.clear(gl.DEPTH_BUFFER_BIT | gl.COLOR_BUFFER_BIT); drawScene(); requestAnimationFrame(loop); }; requestAnimationFrame(loop); } function setupWebGL() { gl.enable(gl.DEPTH_TEST); gl.clearColor(0.1, 0.5, 0.1, 1.0); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); console.log(P); console.log(V); console.log(M); mat4.lookAt(V, [ 3, -1, -5 ], [ 0, 0, 0 ], [ 0, 1, 0 ]); mat4.perspective(P, glMatrix.toRadian(45), canvas.width / canvas.height, 0.1, 1000.0); } function initShaders() { var fs_source = document.getElementById('shader-fs').innerHTML, vs_source = document.getElementById('shader-vs').innerHTML; vertexShader = makeShader(vs_source, gl.VERTEX_SHADER); fragmentShader = makeShader(fs_source, gl.FRAGMENT_SHADER); glProgram = gl.createProgram(); gl.attachShader(glProgram, vertexShader); gl.attachShader(glProgram, fragmentShader); gl.linkProgram(glProgram); if (!gl.getProgramParameter(glProgram, gl.LINK_STATUS)) { alert("Unable to initialize the shader program."); } gl.useProgram(glProgram); } function makeShader(src, type) { var shader = gl.createShader(type); gl.shaderSource(shader, src); gl.compileShader(shader); if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { alert("Error compiling shader: " + gl.getShaderInfoLog(shader)); } return shader; } function setupBuffers() { // n-sides polygon var n = 6; var radius = 1; var angle = (Math.PI * 2) / n; var xCoordinate = 0; var yCoordinate = 0; for (var i = 0; i < n; i++) { var a = angle * i; var xNewCoordinate = xCoordinate + radius * Math.cos(a); var yNewCoordinate = yCoordinate + radius * Math.sin(a); var zNewCoordinate = 0; coordinateArray.push(xNewCoordinate); coordinateArray.push(yNewCoordinate); coordinateArray.push(zNewCoordinate); } verticesArray = [ //Bottom Face 0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 1.0, 0.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, -1.0, 1.0, 0.0, 0.0, //Front Face 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.5, 1.0, -0.5, //Right Face 1.0, 0.0, 0.0, 1.0, 0.0, -1.0, 0.5, 1.0, -0.5, //Back Face 1.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.5, 1.0, -0.5, //Left Face 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.5, 1.0, -0.5, ]; trianglesVerticeBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, trianglesVerticeBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verticesArray), gl.STATIC_DRAW); verticesIndexArray = [ 3, 2, 1, 3, 1, 0, 3, 0, 4, 0, 1, 4, 1, 2, 4, 2, 3, 4, ]; triangleVerticesIndexBuffer = gl.createBuffer(); triangleVerticesIndexBuffer.number_vertext_points = verticesIndexArray.length; gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, triangleVerticesIndexBuffer); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(verticesIndexArray), gl.STATIC_DRAW); triangleVerticeColors = [ 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.5, 0.0, 0.0, 0.5, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 5.0, 0.0, 0.0, 5.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, ]; trianglesColorBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, trianglesColorBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVerticeColors), gl.STATIC_DRAW); } function getMatrixUniforms() { glProgram.mvMatrixUniform = gl.getUniformLocation(glProgram, "uMVMatrix"); glProgram.pMatrixUniform = gl.getUniformLocation(glProgram, "uPMatrix"); glProgram.vMatrixUniform = gl.getUniformLocation(glProgram, "uVMatrix"); } function setMatrixUniforms() { gl.uniformMatrix4fv(glProgram.mvMatrixUniform, false, M); gl.uniformMatrix4fv(glProgram.pMatrixUniform, false, P); gl.uniformMatrix4fv(glProgram.vMatrixUniform, false, V); } function drawScene() { vertexPositionAttribute = gl.getAttribLocation(glProgram, "aVertexPosition"); gl.enableVertexAttribArray(vertexPositionAttribute); gl.bindBuffer(gl.ARRAY_BUFFER, trianglesVerticeBuffer); gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0); vertexColorAttribute = gl.getAttribLocation(glProgram, "aVertexColor"); gl.enableVertexAttribArray(vertexColorAttribute); gl.bindBuffer(gl.ARRAY_BUFFER, trianglesColorBuffer); gl.vertexAttribPointer(vertexColorAttribute, 3, gl.FLOAT, false, 0, 0); gl.drawElements(gl.TRIANGLE_STRIP, triangleVerticesIndexBuffer.number_vertext_points, gl.UNSIGNED_SHORT, 0); } initWebGL(); 
 body{ background-color: grey; } canvas{ background-color: white; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.3.2/gl-matrix-min.js"></script> <script id="shader-vs" type="x-shader/x-vertex"> attribute vec4 aVertexPosition; attribute vec4 aVertexColor; varying vec4 vColor; // Model matrix uniform mat4 uMVMatrix; // Projection matrix uniform mat4 uPMatrix; // View matrix uniform mat4 uVMatrix; void main(void) { vColor = aVertexColor; gl_Position = uPMatrix * uVMatrix * uMVMatrix * aVertexPosition; } </script> <script id="shader-fs" type="x-shader/x-fragment"> precision mediump float; varying vec4 vColor; void main(void) { gl_FragColor = vColor; } </script> <canvas id="my-canvas" width="400" height="300"> Your browser does not support the HTML5 canvas element. </canvas> 

輸出如下:

在此處輸入圖片說明

我正在處理atm的第二件事是在GPU中計算'gl_position'

gl_Position = uPMatrix * uVMatrix * uMVMatrix * aVertexPosition;

我該如何使用CPU?

提前致謝!

頂點索引錯誤。 嘗試

  verticesIndexArray = [
    0, 1, 2,
    3, 4, 5,
    6, 7, 8,
    9, 10, 11,
    12, 13, 14,
    15, 16, 17,
  ];

 var gl = null, canvas = null, glProgram = null, fragmentShader = null, vertexShader = null; var coordinateArray = [ ], triangleVerticeColors = [ ], verticesArray = [ ], verticesIndexArray = [ ]; var vertexPositionAttribute = null, trianglesVerticeBuffer = null, vertexColorAttribute = null, trianglesColorBuffer = null, triangleVerticesIndexBuffer = null; var P = mat4.create(), V = mat4.create(); M = mat4.create(); function initWebGL() { canvas = document.getElementById("my-canvas"); try { gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl"); } catch (e) { } if (gl) { setupWebGL(); initShaders(); setupBuffers(); getMatrixUniforms(); setMatrixUniforms(); animationLoop(); //drawScene(); } else { alert("Error: Your browser does not appear to" + "support WebGL."); } } function animationLoop() { var R = mat4.create(); var angle = 0; var i = 0; var loop = function() { angle = performance.now() / 1000 / 6 * 2 * Math.PI; i++; mat4.rotate(M, R, angle, [ 0, 1, 0 ]); gl.uniformMatrix4fv(glProgram.mvMatrixUniform, false, M); gl.clearColor(0.1, 0.5, 0.1, 1.0); gl.clear(gl.DEPTH_BUFFER_BIT | gl.COLOR_BUFFER_BIT); drawScene(); requestAnimationFrame(loop); }; requestAnimationFrame(loop); } function setupWebGL() { gl.enable(gl.DEPTH_TEST); gl.clearColor(0.1, 0.5, 0.1, 1.0); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); mat4.lookAt(V, [ 3, -1, -5 ], [ 0, 0, 0 ], [ 0, 1, 0 ]); mat4.perspective(P, glMatrix.toRadian(45), canvas.width / canvas.height, 0.1, 1000.0); } function initShaders() { var fs_source = document.getElementById('shader-fs').innerHTML, vs_source = document.getElementById('shader-vs').innerHTML; vertexShader = makeShader(vs_source, gl.VERTEX_SHADER); fragmentShader = makeShader(fs_source, gl.FRAGMENT_SHADER); glProgram = gl.createProgram(); gl.attachShader(glProgram, vertexShader); gl.attachShader(glProgram, fragmentShader); gl.linkProgram(glProgram); if (!gl.getProgramParameter(glProgram, gl.LINK_STATUS)) { alert("Unable to initialize the shader program."); } gl.useProgram(glProgram); } function makeShader(src, type) { var shader = gl.createShader(type); gl.shaderSource(shader, src); gl.compileShader(shader); if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { alert("Error compiling shader: " + gl.getShaderInfoLog(shader)); } return shader; } function setupBuffers() { // n-sides polygon var n = 6; var radius = 1; var angle = (Math.PI * 2) / n; var xCoordinate = 0; var yCoordinate = 0; for (var i = 0; i < n; i++) { var a = angle * i; var xNewCoordinate = xCoordinate + radius * Math.cos(a); var yNewCoordinate = yCoordinate + radius * Math.sin(a); var zNewCoordinate = 0; coordinateArray.push(xNewCoordinate); coordinateArray.push(yNewCoordinate); coordinateArray.push(zNewCoordinate); } verticesArray = [ //Bottom Face 0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 1.0, 0.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, -1.0, 1.0, 0.0, 0.0, //Front Face 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.5, 1.0, -0.5, //Right Face 1.0, 0.0, 0.0, 1.0, 0.0, -1.0, 0.5, 1.0, -0.5, //Back Face 1.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.5, 1.0, -0.5, //Left Face 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.5, 1.0, -0.5, ]; trianglesVerticeBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, trianglesVerticeBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verticesArray), gl.STATIC_DRAW); verticesIndexArray = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, ]; triangleVerticesIndexBuffer = gl.createBuffer(); triangleVerticesIndexBuffer.number_vertext_points = verticesIndexArray.length; gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, triangleVerticesIndexBuffer); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(verticesIndexArray), gl.STATIC_DRAW); triangleVerticeColors = [ 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.5, 0.0, 0.0, 0.5, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 5.0, 0.0, 0.0, 5.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, ]; trianglesColorBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, trianglesColorBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVerticeColors), gl.STATIC_DRAW); } function getMatrixUniforms() { glProgram.mvMatrixUniform = gl.getUniformLocation(glProgram, "uMVMatrix"); glProgram.pMatrixUniform = gl.getUniformLocation(glProgram, "uPMatrix"); glProgram.vMatrixUniform = gl.getUniformLocation(glProgram, "uVMatrix"); } function setMatrixUniforms() { gl.uniformMatrix4fv(glProgram.mvMatrixUniform, false, M); gl.uniformMatrix4fv(glProgram.pMatrixUniform, false, P); gl.uniformMatrix4fv(glProgram.vMatrixUniform, false, V); } function drawScene() { vertexPositionAttribute = gl.getAttribLocation(glProgram, "aVertexPosition"); gl.enableVertexAttribArray(vertexPositionAttribute); gl.bindBuffer(gl.ARRAY_BUFFER, trianglesVerticeBuffer); gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0); vertexColorAttribute = gl.getAttribLocation(glProgram, "aVertexColor"); gl.enableVertexAttribArray(vertexColorAttribute); gl.bindBuffer(gl.ARRAY_BUFFER, trianglesColorBuffer); gl.vertexAttribPointer(vertexColorAttribute, 3, gl.FLOAT, false, 0, 0); gl.drawElements(gl.TRIANGLES, triangleVerticesIndexBuffer.number_vertext_points, gl.UNSIGNED_SHORT, 0); } initWebGL(); 
 body{ background-color: grey; } canvas{ background-color: white; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.3.2/gl-matrix-min.js"></script> <script id="shader-vs" type="x-shader/x-vertex"> attribute vec4 aVertexPosition; attribute vec4 aVertexColor; varying vec4 vColor; // Model matrix uniform mat4 uMVMatrix; // Projection matrix uniform mat4 uPMatrix; // View matrix uniform mat4 uVMatrix; void main(void) { vColor = aVertexColor; gl_Position = uPMatrix * uVMatrix * uMVMatrix * aVertexPosition; } </script> <script id="shader-fs" type="x-shader/x-fragment"> precision mediump float; varying vec4 vColor; void main(void) { gl_FragColor = vColor; } </script> <canvas id="my-canvas" width="400" height="300"> Your browser does not support the HTML5 canvas element. </canvas> 

這些索引也將起作用

 verticesIndexArray = [
      0, 1, 2,
      0, 2, 5,
      5, 0, 8,
      0, 1, 8,
      1, 2, 8,
      2, 5, 8,
  ];

區別在於,如果您共享頂點,它們也將共享顏色。 如果希望每個面都可以具有唯一的顏色,則每個頂點都必須是唯一的(或者必須使用基於復雜紋理的頂點索引)。

看着頂點,從底部開始的前6個頂點

  verticesArray = [

      //Bottom Face
      0.0, 0.0, 0.0,  // 0
      0.0, 0.0, -1.0, // 1       
      1.0, 0.0, -1.0, // 2       
      0.0, 0.0, 0.0,  // 3       
      1.0, 0.0, -1.0, // 4
      1.0, 0.0, 0.0,  // 5

他們制作的正方形將每個頂點放在這些位置

   1----24 
   |     |
   |     |
   03----5

所以你可以使用

0, 1, 2,
3, 4, 5,

或(例如)

0, 1, 2,
0, 2, 5,

看剩下的要點

  //Front Face
  0.0, 0.0, 0.0,  // 6
  1.0, 0.0, 0.0,  // 7
  0.5, 1.0, -0.5, // 8

  //Right Face
  1.0, 0.0, 0.0,  // 9 
  1.0, 0.0, -1.0, // 10
  0.5, 1.0, -0.5, // 11

  //Back Face
  1.0, 0.0, -1.0, // 12
  0.0, 0.0, -1.0, // 13
  0.5, 1.0, -0.5, // 14

  //Left Face
  0.0, 0.0, -1.0, // 15
  0.0, 0.0, 0.0,  // 16
  0.5, 1.0, -0.5, // 18

點8、11、14、18都位於基准上方的同一點。 所有其他點都是基點的副本。

如上所述,如果希望能夠為特定面上的每個頂點使用指定不同的顏色和/或法線和/或紋理坐標,則需要復制。

還有一個問題。 該代碼使用gl.TRIANGLE_STRIP而不是gl.TRIANGLES

因此,您可以看到其中的區別。 如果使用單個頂點,則得到此

在此處輸入圖片說明

如果使用共享頂點,您將獲得此

在此處輸入圖片說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM