我正在努力使用 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);
我不完全确定这是否正确(感觉就像我每帧都发送相同的顶点和纹理坐标),但它正在工作。
关于opengl - 如何使用 WebGL 渲染 2D Sprite?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26203379/