如何将三角形条带与退化三角形链接在一起?

时间:2017-10-24 02:53:19

标签: webgl

var gl;
var canvas;
var shaderProgram;
var triangleVertexBuffer;
var triangleVertexColorBuffer;
var stripElementBuffer;
var stripVertexBuffer;

//Declare new variables here


function createGLContext(canvas) {
  var names = ["webgl", "experimental-webgl"];
  var context = null;
  for (var i=0; i < names.length; i++) {
    try {
      context = canvas.getContext(names[i]);
    } catch(e) {}
    if (context) {
      break;
    }
  }

  if (context) {
    context.viewportWidth = canvas.width;
    context.viewportHeight = canvas.height;
  } else {
    alert("Failed to create WebGL context!");
  }
  return context;
}

function loadShaderFromDOM(id) {
  var shaderScript = document.getElementById(id);
  if (!shaderScript) {
    return null;
  }
  var shaderSource = "";
  var currentChild = shaderScript.firstChild;
  while (currentChild) {
    if (currentChild.nodeType == 3) { // 3 corresponds to TEXT_NODE
      shaderSource += currentChild.textContent;
    }
    currentChild = currentChild.nextSibling;
  }

  var shader;

  if (shaderScript.type == "x-shader/x-fragment") {
    shader = gl.createShader(gl.FRAGMENT_SHADER);
  } else if (shaderScript.type == "x-shader/x-vertex") {
    shader = gl.createShader(gl.VERTEX_SHADER);
  } else {
    return null;
  }

  gl.shaderSource(shader, shaderSource);
  gl.compileShader(shader);

  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
    alert(gl.getShaderInfoLog(shader));
    return null;
  }
  return shader;
}

function setupShaders() {
  vertexShader = loadShaderFromDOM("shader-vs");
  fragmentShader = loadShaderFromDOM("shader-fs");
  shaderProgram = gl.createProgram();
  gl.attachShader(shaderProgram, vertexShader);
  gl.attachShader(shaderProgram, fragmentShader);
  gl.linkProgram(shaderProgram);

  if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
    alert("Failed to setup shaders");
  }

  gl.useProgram(shaderProgram);

  shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
  shaderProgram.vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor");
  gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
  // For the triangle we want to use per-vertex color so
  // the vertexColorAttribute, aVertexColor, in the vertex shader
  // is enabled.
  // You must enable this attribute here or in draw method before the
  //triangle is drawn
  gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);

}

function setupBuffers() {
  triangleVertexBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexBuffer);
  var triangleVertices = [
    0.0,  0.5, 0.0,
      -0.5, -0.5, 0.0,
          0.5, -0.5, 0.0
    ];

  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVertices), gl.STATIC_DRAW);
  triangleVertexBuffer.itemSize = 3;
  triangleVertexBuffer.numberOfItems = 3;

  // Triangle vertex colours
  triangleVertexColorBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexColorBuffer);
  var colors = [
            1.0, 0.0, 0.0, 1.0, //v0
            0.0, 1.0, 0.0, 1.0, //v1
            0.0, 0.0, 1.0, 1.0  //v2
        ];

  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
  triangleVertexColorBuffer.itemSize = 4;
  triangleVertexColorBuffer.numberOfItems = 3;


  // Add new items: the followings are newly added items

  //hexagon vertices
  hexagonVertexBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, hexagonVertexBuffer);
  var hexagonVertices = [
        -0.3,  0.6,  0.0, //v0
        -0.4,  0.8,  0.0, //v1
        -0.6,  0.8,  0.0, //v2
        -0.7,  0.6,  0.0, //v3
        -0.6,  0.4,  0.0, //v4
        -0.4,  0.4,  0.0, //v5
        -0.3,  0.6,  0.0, //v6
  					];

  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(hexagonVertices), gl.STATIC_DRAW);
  hexagonVertexBuffer.itemSize = 3;
  hexagonVertexBuffer.numberOfItems = 7;


  //Triangle strip vertices.
  stripVertexBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, stripVertexBuffer);
  var stripVertices = [
        -0.5,  0.2,  0.0, //v0
        -0.4,  0.0,  0.0, //v1
        -0.3,  0.2,  0.0, //v2
        -0.2,  0.0,  0.0, //v3
        -0.1,  0.2,  0.0, //v4
         0.0,  0.0,  0.0, //v5
         0.1,  0.2,  0.0, //v6
         0.2,  0.0,  0.0, //v7
         0.3,  0.2,  0.0, //v8
         0.4,  0.0,  0.0, //v9
         0.5,  0.2,  0.0, //v10

         // Second strip
        -0.5, -0.3,  0.0, //v11
        -0.4, -0.5,  0.0, //v12
        -0.3, -0.3,  0.0, //v13
        -0.2, -0.5,  0.0, //v14
        -0.1, -0.3,  0.0, //v15
         0.0, -0.5,  0.0, //v16
         0.1, -0.3,  0.0, //v17
         0.2, -0.5,  0.0, //v18
         0.3, -0.3,  0.0, //v19
         0.4, -0.5,  0.0, //v20
         0.5, -0.3,  0.0  //v21
  ];

  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(stripVertices), gl.STATIC_DRAW);
  stripVertexBuffer.itemSize = 3;
  stripVertexBuffer.numberOfItems = 22;

  // Strip vertex indices
  stripElementBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, stripElementBuffer);

  var indices = [
    0.0,  0.5, 0.0,
      -0.5, -0.5, 0.0,
          0.5, -0.5, 0.0
// put correct indices here. Use degenerated triangles to link the
  	// strips together
];

  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
  stripElementBuffer.numberOfItems = 25;
}

function draw() {
  gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
  gl.clear(gl.COLOR_BUFFER_BIT);

  // Draw triangle. No change is made to the last week's code here
  // For the triangle we want to use per-vertex color so
  // the vertexColorAttribute, aVertexColor, in the vertex shader
  // is enabled
  // gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);

  // Make vertex buffer "triangleVertexBuffer" the current buffer
  gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexBuffer);

  // Link the current buffer to the attribute "aVertexPosition" in
  // the vertex shader
  gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, triangleVertexBuffer.itemSize, gl.FLOAT, false, 0, 0);

  // Make color buffer "triangleVertexColorBuffer" the current buffer
  gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexColorBuffer);
  // Link the current buffer to the attribute "aVertexColor" in
  // the vertex shader
  gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, triangleVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
  gl.drawArrays(gl.TRIANGLES, 0, triangleVertexBuffer.numberOfItems);
  
  gl.drawElements(gl.TRIANGLE_STRIP, 0, stripVertexBuffer.numberOfItems, 25);



  // Draw the newly added items



  }

function startup() {
  canvas = document.getElementById("myGLCanvas");
  gl = createGLContext(canvas);
  setupShaders();
  setupBuffers();
  gl.clearColor(1.0, 1.0, 1.0, 1.0);

  draw();
}

startup();
<script id="shader-vs" type="x-shader/x-vertex">
  attribute vec3 aVertexPosition;
  attribute vec4 aVertexColor;
  varying vec4 vColor;

  void main() {
    vColor = aVertexColor;
    gl_Position = vec4(aVertexPosition, 1.0);
  }
</script>

<script id="shader-fs" type="x-shader/x-fragment">
  precision mediump float;
  varying vec4 vColor;

  void main() {
    gl_FragColor = vColor;
  }
</script>

<canvas id="myGLCanvas" width="250" height="250"></canvas>

嘿伙计们。 WEBGL的新手,尝试绘制三角形条带但不知道如何处理这个问题。

我所知道的:

  • 使用gl.TRIANGLE_STRIP模式绘制时,缓冲区中顶点坐标或索引的顺序非常重要。
  • WebGL不是由程序员指定三角形,而是自动构造三角形。
  • 它读取顶点坐标缓冲区或索引缓冲区,并按以下顺序使用它们来构造三角形:

1 个答案:

答案 0 :(得分:1)

代码中的这两行没有任何意义

gl.drawArrays(gl.TRIANGLES, 0, triangleVertexBuffer.numberOfItems);

gl.drawElements(gl.TRIANGLE_STRIP, 0, stripVertexBuffer.numberOfItems, 25);

通常无需在两者之间进行任何更改就调用绘图是没有意义的,因为绘制2件事需要设置不同的数据。

此外,第二行是完全错误的

gl.drawElements(gl.TRIANGLE_STRIP, 0, stripVertexBuffer.numberOfItems, 25);

如果您打开了JavaScript控制台,则会看到类似

的错误

javascript console

有几个问题

  • 代码将错误值传递给type

    gl.drawElements参数

    gl.drawElements的类型参数是当前ELEMENT_ARRAY_BUFFER中的数据类型。

  • 第二个参数是计数。

  • 它传递了顶点数(stripVertexBuffer.numberOfItems)而不是索引数(stripElementBuffer.numberOfItems

它应该是这样的

{
  const primitive = gl.TRIANGLE_STRIP;
  const count = stripElementBuffer.numberOfItems;
  const offset = 0;
  const indexType = gl.UNSIGNED_SHORT;

  gl.drawElements(primitive, count, indexType, offset);
}

修复它虽然不够,因为代码实际上并没有将索引放在索引缓冲区中。那段代码

  // Strip vertex indices
  stripElementBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, stripElementBuffer);

  var indices = [
    0.0,  0.5, 0.0,
      -0.5, -0.5, 0.0,
          0.5, -0.5, 0.0
// put correct indices here. Use degenerated triangles to link the
    // strips together
];

  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
  stripElementBuffer.numberOfItems = 25;

也毫无意义。索引是从0到N的无符号整数值,其中N小于绑定到属性的顶点数。此外,只输入了9个值,但代码集stripElementBuffer.numberOfItems为25 ..?

然后,除此之外,代码没有设置使用条带顶点的属性。

在WebGL中绘制多个内容就像这样

for each thing you want to draw
   gl.useProgram(theProgramYouWantToDrawWith);

   // setup attributes
   for each attribute
     gl.bindBuffer(gl.ARRAY_BUFFER, bufferWithDataForAttribute);
     gl.enableVertexAttribArray(attribLocation);
     gl.vertexAttribPointer(attribLocation, ... how to get data out of buffer ...)

   // if using indices setup the ELEMENT_ARRAY_BUFFER
   gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufferWithIndices);

   // setup textures
   for each texture you're going to draw with
     gl.activeTexture(gl.TEXTURE0 + unit);
     gl.bindTexture(gl.TEXTURE_??, someTexture);

   // setup uniforms
   for each uniform
     gl.uniformXXX(...)

   // draw
   gl.drawXXX (either gl.drawArrays or gl.drawElements)

在您尝试退化三角形条之前,您需要修复代码以遵循该模式。另外here's some other tutorials you might find helpful