2014-10-05 73 views
4

我正努力使用Dart和WebGL將2D Sprite渲染到畫布。我可以在網上找到很少的例子。大多數都是3D,或者包含大量的意大利麪條代碼,沒有真正解釋他們在做什麼。我試圖做最簡單的事情,呈現一個精靈。如何使用WebGL渲染2D Sprite?

到目前爲止,我已經設法在畫布上呈現綠色正方形(兩個三角形)。我正在努力的一點是,如何將這個從綠色方塊改變爲使用我的紋理(紋理加載和綁定正確,我相信)。我認爲這需要對着色器進行更改(以獲取紋理合作夥伴而不是顏色)以及傳遞與緩衝區中頂點相關的紋理座標。

此代碼also exists in a Gist

注意:這只是一次性樣品;大部分代碼都存在於構造函數中;我現在對代碼的整潔程度不太感興趣;當我能看到屏幕上的精靈時,我可以收拾起來!

注意:我對使用第三方庫不感興趣;我正在做這個來學習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的相同)。

+0

[嘗試這些教程](http://webglfundamentals.org)? – gman 2014-10-05 16:39:09

+0

@gman謝謝;沒看過這個,會看看通過! – 2014-10-05 16:53:00

回答

1

好吧,設法使這項工作。您可以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); 

我不能完全肯定,如果這是正確的(這感覺就像我發送相同的頂點和textureCoord每一幀),但它的工作。

I MADE A GAME!!!!111

+0

你不會每幀發送任何數據。你告訴WebGL你已經發送了哪些數據。 – gman 2014-10-05 16:41:07

+0

@gman哦,是的!我知道這是紋理的情況,但不知何故,我的頂點緩衝區與實際數組混淆。這是一個漫長的下午! :) – 2014-10-05 16:51:18

+0

@gman這是否看起來相同;我在安裝過程中還是在循環中得到了正確的代碼? – 2014-10-05 16:52:10