Dart WebGL无法渲染

时间:2014-08-20 15:55:56

标签: opengl-es dart webgl dart-html

我正在尝试用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工作,导致清晰的颜色工作正常。我不知道问题是什么,所以任何建议都表示赞赏。

1 个答案:

答案 0 :(得分:1)

如何使用Pixi DartStageXL等渲染库或游戏引擎代替普通WebGL? 这两个库还抽象渲染器后端(尽可能使用WebGL并使用canvas作为后备)。

希望如果您正在考虑开发游戏,这会有所帮助:)