在webgl

时间:2016-01-03 21:06:43

标签: graphics opengl-es webgl

我用线段近似曲线:

for (i=1; i<=100; i=i+0.2)
    {
        arr = calculateCurve(i, 1, 1, 1, 1); //function returns an array of verticles
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
            prevArr[0]/scale,
            prevArr[1]/scale,
            prevArr[2]/scale,
            arr[0]/scale,
            arr[1]/scale,
            arr[2]/scale
        ]), gl.STATIC_DRAW);
        gl.drawArrays(gl.LINES, 0, 2);

        prevArr = arr;

    }

我需要再次使用gl.drawArrays()来旋转曲线,因为在这种情况下性能非常慢。 我会创建一个包含100个顶点的巨大缓冲区,但我想知道是否可以通过更改顶点着色器中的旋转矩阵来重绘场景。

3 个答案:

答案 0 :(得分:1)

创建“巨大”缓冲区不是问题,缓冲区的大小甚至达不到10kb(如果使用的绘制模式不同于LINE_STRIP - > glDrawArrays或{{1但是,多次调用Float32Array是。

这里正确的方法是缓冲孔线。为此,生成一个glBufferData,其大小可以容纳所有要渲染的浮点数。然后只拨打glDrawArraysglBufferData一次。

如果你没有每帧更改一行,你也可以在第一次缓冲线后跳过nav{ position: absolute; width: 100%;left: 0;top: 0;}

答案 1 :(得分:0)

通过旋转曲线不太清楚你的意思。我看到至少有两种解释。一个是您希望曲线顶点位于相同的位置,但更改观察者位置,以便您以不同的角度查看相同的曲线。第二个是你想要每帧都有不同的曲线形状。

如果你想要的是1),那么你所要做的就是将一个矩阵作为统一发送到GPU并在顶点着色器中进行gl_Position = matrix * position。这样做意味着您不必每帧都重新生成曲线上的顶点位置。

如果你想要的是2),那么你需要提出一些数学来计算顶点着色器中曲线上每个点的位置。如何做到这一点非常依赖于案例,我认为您需要显示更多关于如何计算曲线上位置的代码。

答案 2 :(得分:0)

您可以通过将它们乘以旋转矩阵来旋转WebGL中的顶点。

例如,此代码将生成一个在Z轴上旋转顶点的矩阵。

function rotationZ(angleInRadians) {

  var c = Math.cos(angleInRadians);
  var s = Math.sin(angleInRadians);

  return [
    c, s, 0, 0,
   -s, c, 0, 0,
    0, 0, 1, 0,
    0, 0, 0, 1,
  ];
}

这是一个有效的例子:

function rotationZ(angleInRadians) {

  var c = Math.cos(angleInRadians);
  var s = Math.sin(angleInRadians);

  return [
    c, s, 0, 0,
    -s, c, 0, 0,
    0, 0, 1, 0,
    0, 0, 0, 1,
  ];
}
    
// Using TWGL (twgljs.org) to keep the code small

  var gl = document.getElementById("c").getContext("webgl");
  // compiles shader, links and looks up locations
  var programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);

  // make some curve points
  points = [];
  for (var i = 0; i < 100; ++i) {
    var a = i / 100 * Math.PI * 2;
    var r = 0.5;
    points.push(
      Math.sin(Math.sin(a * 2.)) * r , 
      Math.cos(a) * r);
  }

  var arrays = {
    position: { numComponents: 2, data: points, },
  };
  // calls gl.createBuffer, gl.bindBuffer, gl.bufferData for each array
  var bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);

  function render(time) {
    var uniforms = {
      u_matrix: rotationZ(time * 0.001),
    };

    gl.useProgram(programInfo.program);
    // calls gl.bindBuffer, gl.enableVertexAttribArray, gl.vertexAttribPointer
    twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
    // calls gl.uniformXXX, gl.activeTexture, gl.bindTexture
    twgl.setUniforms(programInfo, uniforms);
    // calls gl.drawArray or gl.drawElements
    twgl.drawBufferInfo(gl, bufferInfo, gl.LINE_LOOP);

    requestAnimationFrame(render);
  }
  requestAnimationFrame(render);
canvas { border: 1px solid blue; }
<!-- 

note! I'm using a square canvas so I don't have to deal with aspect 
which would complicate the example

See the articles linked in the answer for details about aspect

-->
<canvas id="c" width="150" height="150"></canvas>
<script src="https://twgljs.org/dist/3.x/twgl-full.min.js"></script>
<script id="vs" type="notjs">
attribute vec4 position;
uniform mat4 u_matrix;

void main() {
  gl_Position = u_matrix * position;
}
</script>
<script id="fs" type="notjs">
precision mediump float;

void main() {
  gl_FragColor = vec4(0,0,0,1);
}
</script>

This article explains how rotation works及其后面的文章将转换为使用矩阵。