【问题标题】:Rotate curve in webgl在webgl中旋转曲线
【发布时间】:2017-03-17 20:09:25
【问题描述】:

我用线段近似曲线:

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 个顶点的巨大缓冲区,但我想知道是否有一种方法可以通过更改顶点着色器中的旋转矩阵来重绘场景。

【问题讨论】:

  • this article teaches how to rotate。如果你跟着它看完之后的文章,你就会开始使用矩阵来旋转。
  • 编辑了我的答案,使其更适合您的问题。

标签: graphics opengl-es webgl


【解决方案1】:

在这里创建一个“巨大”的缓冲区不是问题,缓冲区的大小甚至没有达到 10kb(如果您使用不同于 LINE 的绘制模式 -> LINE_LOOPLINE_STRIP ),但是调用 @ 987654324@多次是。

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

如果您不每帧更改行,您也可以在第一次缓冲行后跳过glBufferData

【讨论】:

    【解决方案2】:

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

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

    如果您想要的是 2),那么您需要提出一些数学运算来计算顶点着色器中曲线上每个点的位置。如何做到这一点取决于具体情况,我认为您需要显示更多关于如何计算曲线位置的代码。

    【讨论】:

      【解决方案3】:

      您可以在 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 及其后面的文章将过渡到使用矩阵。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-08
        相关资源
        最近更新 更多