我正在尝试用WebGL和Dart写一些东西,但我遇到了问题。这是我的源代码。
这是我的主要文件:
library warmup;
import 'dart:html';
import 'dart:math';
import 'dart:web_gl' as WebGL;
import 'dart:typed_data';
import 'package:vector_math/vector_math.dart';
part 'graphics.dart';
WebGL.RenderingContext gl;
CanvasElement canvas;
QuadRenderer renderer;
Random random = new Random();
void main() {
querySelector("#paragraf").setInnerHtml("HELLO!");
canvas = querySelector("#game_canvas");
new Game().start();
}
class Game {
Texture test = new Texture("tex/test.png");
void start() {
gl = canvas.getContext3d();
if (gl == null) {
print("No WebGL!");
}
Texture.loadAll();
renderer = new QuadRenderer();
renderer.projMatrix = makeOrthographicMatrix(0, canvas.width, 0, canvas.height, -1, 1);
gl.disable(WebGL.DEPTH_TEST);
gl.enable(WebGL.BLEND);
gl.blendFunc(WebGL.SRC_ALPHA, WebGL.ONE_MINUS_SRC_ALPHA);
gl.clearColor(0.0, 0.0, 0.0, 1.0);
window.requestAnimationFrame(_update);
}
int now, last = new DateTime.now().millisecondsSinceEpoch;
double unprocessedFrames;
void _update(double time) {
now = new DateTime.now().millisecondsSinceEpoch;
unprocessedFrames = (now - last) * 60 / 1000;
while (unprocessedFrames > 1.0) {
tick();
unprocessedFrames--;
}
renderGame();
window.requestAnimationFrame(_update);
}
void tick() {
}
void renderGame() {
gl.viewport(0, 0, canvas.width, canvas.height);
gl.clear(WebGL.COLOR_BUFFER_BIT);
renderer.bindTexture(test);
renderer.renderQuad(new Vector2(canvas.width / 2.0, canvas.height / 2.0), 128, 128, 0, 0, false);
}
}
这是我的graphics.dart文件:
part of warmup;
class Texture {
static List<Texture> _pending = new List<Texture>();
String url;
int width, height;
WebGL.Texture data;
bool loaded = false;
Texture(this.url) {
if (gl == null) {
_pending.add(this);
}
else {
load();
}
}
static void loadAll() {
_pending.forEach((e) => e.load());
_pending.clear();
}
void load() {
ImageElement img = new ImageElement();
data = gl.createTexture();
img.onLoad.listen((e) {
gl.bindTexture(WebGL.TEXTURE_2D, data);
gl.texImage2DImage(WebGL.TEXTURE_2D, 0, WebGL.RGBA, WebGL.RGBA, WebGL.UNSIGNED_BYTE, img);
gl.texParameteri(WebGL.TEXTURE_2D, WebGL.TEXTURE_MIN_FILTER, WebGL.NEAREST);
gl.texParameteri(WebGL.TEXTURE_2D, WebGL.TEXTURE_MAG_FILTER, WebGL.NEAREST);
width = img.width;
height = img.height;
loaded = true;
});
img.src = url;
}
}
class Vertex {
Vector2 pos;
Vector4 color;
Vector2 texCoord;
static int elementBytes = 8;
static int posElementCount = 2;
static int colorElementCount = 4;
static int textureElementCount = 2;
static int posBytesCount = posElementCount * elementBytes;
static int colorByteCount = colorElementCount * elementBytes;
static int textureByteCount = textureElementCount * elementBytes;
static int posByteOffset = 0;
static int colorByteOffset = posByteOffset + posBytesCount;
static int textureByteOffset = colorByteOffset + colorByteCount;
static int elementCount = posElementCount +
colorElementCount + textureElementCount;
static int stride = posBytesCount + colorByteCount +
textureByteCount;
Vertex() {
pos = new Vector2(0.0, 0.0);
color = new Vector4(1.0, 1.0, 1.0, 1.0);
texCoord = new Vector2(0.0, 0.0);
}
List<double> getElements() {
List<double> result;
result = [pos.x, pos.y, color.r, color.g, color.b, color.a, texCoord.x, texCoord.y];
return result;
}
}
class QuadRenderer {
String _vsSource = """
precision highp float;
attribute vec2 a_pos;
attribute vec2 a_texCoord;
attribute vec4 a_color;
uniform mat4 proj;
uniform mat4 model;
varying vec2 v_texCoord;
varying vec4 v_pos;
varying vec4 v_color;
void main() {
v_pos = proj * model * vec4(a_pos, 0, 1);
v_color = a_color;
gl_Position = proj * model * vec4(a_pos, 0, 1);
}
""", _fsSource = """
precision highp float;
uniform sampler2D texture;
varying vec2 v_texCoord;
varying vec4 v_pos;
varying vec4 v_color;
void main() {
vec4 texColor = texture2D(texture, v_texCoord);
gl_FragColor = vec4(1, 1, 1, 1);
}
""";
WebGL.Shader vs, fs;
WebGL.Program program;
WebGL.Buffer vab, iab;
int posLocation;
Matrix4 projMatrix;
Vertex v0, v1, v2, v3;
WebGL.UniformLocation projLocation, modelLocation;
Texture texture;
void renderQuad(Vector2 pos, num w, num h, num uo, num vo, bool normalize, {Vector4 color, double rotation}) {
if (!texture.loaded) return;
if (color == null) color = new Vector4(1.0, 1.0, 1.0, 1.0);
if (rotation == null) rotation = 0.0;
Matrix4 model = new Matrix4.identity();
model.translate(pos.x, pos.y);
model.scale(w*1.0, h*1.0, 0.0);
gl.uniformMatrix4fv(modelLocation, false, model.storage);
gl.uniformMatrix4fv(projLocation, false, projMatrix.storage);
if (normalize) {
uo /= texture.width;
vo /= texture.height;
}
v0.color = v1.color = v2.color = v3.color = color;
v0.texCoord = new Vector2(uo + w * 1.0, vo + h * 1.0); v1.texCoord = new Vector2(uo + w * 1.0, vo * 1.0);
v2.texCoord = new Vector2(uo * 1.0, vo * 1.0); v3.texCoord = new Vector2(uo * 1.0, vo + h * 1.0);
_compileVertices();
gl.drawElements(WebGL.TRIANGLES, 6, WebGL.UNSIGNED_SHORT, 0);
}
void bindTexture(Texture tex) {
texture = tex;
gl.bindTexture(WebGL.TEXTURE_2D, texture.data);
}
void _compileVertices() {
List<Vertex> vertices = [v0, v1, v2, v3];
Float32List vertexBuffer = new Float32List(vertices.length * Vertex.elementCount);
for (int i = 0; i < vertices.length; i++) {
Vertex vertex = vertices[i];
vertexBuffer.setAll(i * Vertex.elementCount, vertex.getElements());
}
gl.bindBuffer(WebGL.ARRAY_BUFFER, vab);
gl.bufferData(WebGL.ARRAY_BUFFER, vertexBuffer, WebGL.STATIC_DRAW);
gl.vertexAttribPointer(0, Vertex.posElementCount, WebGL.FLOAT, false, Vertex.stride, Vertex.posByteOffset);
gl.vertexAttribPointer(1, Vertex.colorElementCount, WebGL.FLOAT, false, Vertex.stride, Vertex.colorByteOffset);
gl.vertexAttribPointer(2, Vertex.textureElementCount, WebGL.FLOAT, false, Vertex.stride, Vertex.textureByteOffset);
}
QuadRenderer() {
vs = gl.createShader(WebGL.VERTEX_SHADER);
gl.shaderSource(vs, _vsSource);
gl.compileShader(vs);
if (!gl.getShaderParameter(vs, WebGL.COMPILE_STATUS)) {
throw gl.getShaderInfoLog(vs);
}
fs = gl.createShader(WebGL.FRAGMENT_SHADER);
gl.shaderSource(fs, _fsSource);
gl.compileShader(fs);
if (!gl.getShaderParameter(fs, WebGL.COMPILE_STATUS)) {
throw gl.getShaderInfoLog(fs);
}
program = gl.createProgram();
gl.attachShader(program, vs);
gl.attachShader(program, fs);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, WebGL.LINK_STATUS)) {
throw gl.getProgramInfoLog(program);
}
projLocation = gl.getUniformLocation(program, "proj");
modelLocation = gl.getUniformLocation(program, "model");
gl.useProgram(program);
v0 = new Vertex(); v1 = new Vertex(); v2 = new Vertex(); v3 = new Vertex();
v0.pos = new Vector2(0.5, 0.5); v1.pos = new Vector2(0.5, -0.5);
v2.pos = new Vector2(-0.5, -0.5); v3.pos = new Vector2(-0.5, 0.5);
gl.bindAttribLocation(program, 0, "a_pos");
gl.bindAttribLocation(program, 1, "a_color");
gl.bindAttribLocation(program, 2, "a_texCoord");
List<Vertex> vertices = [v0, v1, v2, v3];
Float32List vertexBuffer = new Float32List(vertices.length * Vertex.elementCount);
for (int i = 0; i < vertices.length; i++) {
Vertex vertex = vertices[i];
vertexBuffer.setAll(i * Vertex.elementCount, vertex.getElements());
}
vab = gl.createBuffer();
gl.bindBuffer(WebGL.ARRAY_BUFFER, vab);
gl.bufferData(WebGL.ARRAY_BUFFER, vertexBuffer, WebGL.STATIC_DRAW);
gl.vertexAttribPointer(0, Vertex.posElementCount, WebGL.FLOAT, false, Vertex.stride, Vertex.posByteOffset);
gl.vertexAttribPointer(1, Vertex.colorElementCount, WebGL.FLOAT, false, Vertex.stride, Vertex.colorByteOffset);
gl.vertexAttribPointer(2, Vertex.textureElementCount, WebGL.FLOAT, false, Vertex.stride, Vertex.textureByteOffset);
Int16List indexBuffer = new Int16List(6);
indexBuffer.setAll(0, [0, 1, 2, 0, 2, 3]);
iab = gl.createBuffer();
gl.bindBuffer(WebGL.ELEMENT_ARRAY_BUFFER, iab);
gl.bufferData(WebGL.ELEMENT_ARRAY_BUFFER, indexBuffer, WebGL.STATIC_DRAW);
}
}
问题是渲染调用renderGame()不起作用。我知道WebGL工作,导致清晰的颜色工作正常。我不知道问题是什么,所以任何建议都表示赞赏。