opengl - 如何使用 WebGL 渲染 2D Sprite?

标签 opengl opengl-es html5-canvas dart webgl

我正在努力使用 Dart 和 WebGL 将 2D Sprite 渲染到 Canvas。我可以在网上找到很少的例子;大多数要么是 3D 的,要么包含大量意大利面条代码,而没有真正解释他们在做什么。我正在尝试做最简单的渲染 Sprite 的事情。

到目前为止,我已经成功地在 Canvas 上渲染了一个绿色正方形(两个三角形)。我正在努力解决的问题是如何将其从绿色方 block 更改为使用我的纹理(我相信纹理已正确加载和绑定(bind))。我认为这将需要更改着色器(以获取纹理坐标,而不是颜色)以及传递与缓冲区中的顶点相关的纹理坐标。

此代码 also exists in a Gist .

注意:这只是一个一次性样本;大多数代码都存在于构造函数中;我现在对代码的整洁程度不太感兴趣。当我在屏幕上看到一个 Sprite 时,我可以整理一下!

注意:我对使用第三方库不感兴趣;我这样做是为了学习 WebGL!

<!DOCTYPE html>
<html>
  <head>
    <title>MySecondGame</title>
  </head>
  <body>
    <canvas width="1024" height="768"></canvas>

    <div style="display: none;">
      <img id="img-player" src="assets/player.png" />
    </div>

    <script id="vertex" type="x-shader">
      attribute vec2 aVertexPosition;

      void main() {
        gl_Position = vec4(aVertexPosition, 0.0, 1.0);
      }
    </script>
    <script id="fragment" type="x-shader">
      #ifdef GL_ES
      precision highp float;
      #endif

      uniform vec4 uColor;

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

    <script type="application/dart">
      import 'dart:async';
      import 'dart:html';
      import 'dart:math';
      import 'dart:typed_data';
      import 'dart:web_gl';

      Game game;

      main() {
        game = new Game(document.querySelector('canvas'));
      }

      class Game {
        RenderingContext _gl;
        Buffer vbuffer;
        int numItems;
        Texture playerTexture;
        double elapsedTime;
        double fadeAmount;

        Game(CanvasElement canvas) {
          _gl = canvas.getContext3d();
          playerTexture = _gl.createTexture();
          _gl.bindTexture(TEXTURE_2D, playerTexture);
          _gl.texImage2DUntyped(TEXTURE_2D, 0, RGBA, RGBA, UNSIGNED_BYTE, document.querySelector('#img-player'));
          _gl.texParameteri(TEXTURE_2D, TEXTURE_MAG_FILTER, NEAREST);
          _gl.texParameteri(TEXTURE_2D, TEXTURE_MIN_FILTER, LINEAR_MIPMAP_NEAREST);
          _gl.generateMipmap(TEXTURE_2D);
          _gl.bindTexture(TEXTURE_2D, null);

          var vsScript = document.querySelector('#vertex');
          var vs = _gl.createShader(VERTEX_SHADER);
          _gl.shaderSource(vs, vsScript.text);
          _gl.compileShader(vs);

          var fsScript = document.querySelector('#fragment');
          var fs = _gl.createShader(FRAGMENT_SHADER);
          _gl.shaderSource(fs, fsScript.text);
          _gl.compileShader(fs);

          var program = _gl.createProgram();
          _gl.attachShader(program, vs);
          _gl.attachShader(program, fs);
          _gl.linkProgram(program);

          if (!_gl.getShaderParameter(vs, COMPILE_STATUS))
            print(_gl.getShaderInfoLog(vs));

          if (!_gl.getShaderParameter(fs, COMPILE_STATUS))
            print(_gl.getShaderInfoLog(fs));

          if (!_gl.getProgramParameter(program, LINK_STATUS))
            print(_gl.getProgramInfoLog(program));

          var aspect = canvas.width / canvas.height;
          var vertices = new Float32List.fromList([
            -0.5, 0.5 * aspect, 0.5, 0.5 * aspect,  0.5, -0.5 * aspect,  // Triangle 1
            -0.5, 0.5 * aspect, 0.5,-0.5 * aspect, -0.5, -0.5 * aspect   // Triangle 2
          ]);

          vbuffer = _gl.createBuffer();
          _gl.bindBuffer(ARRAY_BUFFER, vbuffer);                                       
          _gl.bufferData(ARRAY_BUFFER, vertices, STATIC_DRAW);
          numItems = vertices.length ~/ 2;

          _gl.useProgram(program);

          var uColor = _gl.getUniformLocation(program, "uColor");
          _gl.uniform4fv(uColor, new Float32List.fromList([0.0, 0.3, 0.0, 1.0]));

          var aVertexPosition = _gl.getAttribLocation(program, "aVertexPosition");
          _gl.enableVertexAttribArray(aVertexPosition);
          _gl.vertexAttribPointer(aVertexPosition, 2, FLOAT, false, 0, 0);

          window.animationFrame.then(_gameLoop);
        }

        _gameLoop(num time) {
          elapsedTime = time;
          _update();
          _render();
          window.animationFrame.then(_gameLoop);
        }

        _update() {
          // Use sine curve for fading. Sine is -1-1, so tweak to be 0 - 1.
          fadeAmount = (sin(elapsedTime/1000) / 2) + 0.5;
        }

        _render() {
          // Set colour for clearing to.
          _gl.clearColor(fadeAmount, 1 - fadeAmount, 0.0, 1.0);
          // Clear.
          _gl.clear(RenderingContext.COLOR_BUFFER_BIT);

          _gl.bindTexture(TEXTURE_2D, playerTexture);
          _gl.drawArrays(TRIANGLES, 0, numItems);
          _gl.bindTexture(TEXTURE_2D, null);
        }
      }
    </script>
    <script src="packages/browser/dart.js"></script>
  </body>
</html>

(也用 opengl 标记它,因为我相信 WebGL/OpenGL 的解决方案可能相同)。

最佳答案

好的,设法使这项工作。您可以see the full diff in a gist here .

我可能错了;但似乎我希望在设置缓冲区时将数据设置在缓冲区中;但我找不到任何方法来说明哪些数据用于哪个缓冲区。我将代码拆分为一些设置代码:

vbuffer = _gl.createBuffer();
_gl.bindBuffer(ARRAY_BUFFER, vbuffer);
_gl.bufferData(ARRAY_BUFFER, vertices, STATIC_DRAW);
numItems = vertices.length ~/ 2;

tbuffer = _gl.createBuffer();
_gl.bindBuffer(ARRAY_BUFFER, tbuffer);                                       
_gl.bufferData(ARRAY_BUFFER, textureCoords, STATIC_DRAW);

aVertexPosition = _gl.getAttribLocation(program, "aVertexPosition");
_gl.enableVertexAttribArray(aVertexPosition);

aTextureCoord = _gl.getAttribLocation(program, "aTextureCoord");
_gl.enableVertexAttribArray(aTextureCoord);

uSampler = _gl.getUniformLocation(program, "uSampler");

和一些渲染代码:
_gl.bindBuffer(ARRAY_BUFFER, vbuffer);
_gl.vertexAttribPointer(aVertexPosition, 2, FLOAT, false, 0, 0);

_gl.bindBuffer(ARRAY_BUFFER, tbuffer);
_gl.vertexAttribPointer(aTextureCoord, 2, FLOAT, false, 0, 0);

_gl.bindTexture(TEXTURE_2D, playerTexture);
_gl.uniform1i(uSampler, 0);

_gl.drawArrays(TRIANGLES, 0, numItems);

我不完全确定这是否正确(感觉就像我每帧都发送相同的顶点和纹理坐标),但它正在工作。

I MADE A GAME!!!!111

关于opengl - 如何使用 WebGL 渲染 2D Sprite?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26203379/

相关文章:

c++ - 具有缩放拉伸(stretch)纵横比的 glm 旋转

opengl - 哪里可以找到简单的 YUV(可能是 YUV420P)图像来测试? (我可以用ffmpeg提取吗?)

jquery - 在电子商务应用程序的 mvc 中构建自定义标志和标志模式

javascript - 在 Canvas 中循环背景图像动画

javascript将图像裁剪到 Canvas

c - 当尝试为 OS X 10.6 (Snow Leopard) 配置 pcb-2011-018 时,配置报告找不到 openGL 库?

python - 在 OpenGL 中使用正交投影纹理

ios - 自 iOS6 以来,GLKTexture 未正确映射

ios - 在 OpenGLES 中组合多个着色器

android - Android 上 SurfaceView 与 GLSurfaceView 的区别和优势?