我正在努力使用Dart和WebGL将2D Sprite渲染到Canvas。我在网上找到很少的例子;大多数都是3D,或包含大量的意大利面条代码,没有真正解释他们正在做什么。我试图做一个渲染精灵的最简单的事情。
到目前为止,我已设法在画布上渲染绿色方块(两个三角形)。我挣扎的那一点,是如何将它从绿色方块改为使用我的纹理(纹理加载和绑定正确,我相信)。我认为这需要更改着色器(采用纹理合作而不是颜色)以及传递与缓冲区中顶点相关的纹理坐标。
注意:这只是一次性的样本;大多数代码都存在于构造函数中;我现在对代码的整洁程度不太感兴趣;当我在屏幕上看到一个精灵时,我可以整理一下!
注意:我对使用第三方库不感兴趣;我这样做是为了学习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 :(得分: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),但它正在工作。