4

I've been trying to create billboarding effects for a game I'm making in dart using lwjgl.

I've been reading that you should have each billboard vertex is at the worlds center position and then just displace them by the cameras vectors. I do not quite understand how to do this.

Here's my rendering class:

class Quad {

  Shader shader;
  int posLocation;
  Texture texture;
  WebGL.UniformLocation objectTransformLocation, viewTransformLocation, textureTransformLocation,
      colorLocation, fogColorLocation, cameraTransformLocation;

  Quad(this.shader) {
    posLocation = gl.getAttribLocation(shader.program, "a_pos");
    objectTransformLocation = gl.getUniformLocation(shader.program, "u_objectTransform");
    textureTransformLocation = gl.getUniformLocation(shader.program, "u_textureTransform");
    viewTransformLocation = gl.getUniformLocation(shader.program, "u_viewTransform");
    cameraTransformLocation = gl.getUniformLocation(shader.program, "u_cameraTransform");
    colorLocation = gl.getUniformLocation(shader.program, "u_color");
    fogColorLocation = gl.getUniformLocation(shader.program, "u_fogColor");

    gl.useProgram(shader.program);

    Float32List vertexArray = new Float32List(4 * 3);
    vertexArray.setAll(0 * 3, [.5, .5, 0.0]);
    vertexArray.setAll(1 * 3, [.5, -.5, 0.0]);
    vertexArray.setAll(2 * 3, [-.5, -.5, 0.0]);
    vertexArray.setAll(3 * 3, [-.5, .5, 0.0]);

    Int16List elementArray = new Int16List(6);
    elementArray.setAll(0, [0, 1, 2, 0, 2, 3]);

    gl.enableVertexAttribArray(posLocation);
    WebGL.Buffer vertexBuffer = gl.createBuffer();
    gl.bindBuffer(WebGL.ARRAY_BUFFER, vertexBuffer);
    gl.bufferDataTyped(WebGL.ARRAY_BUFFER, vertexArray, WebGL.STATIC_DRAW);
    gl.vertexAttribPointer(posLocation, 3, WebGL.FLOAT, false, 0, 0);

    WebGL.Buffer elementBuffer = gl.createBuffer();
    gl.bindBuffer(WebGL.ELEMENT_ARRAY_BUFFER, elementBuffer);
    gl.bufferDataTyped(WebGL.ELEMENT_ARRAY_BUFFER, elementArray, WebGL.STATIC_DRAW);
    gl.bindBuffer(WebGL.ELEMENT_ARRAY_BUFFER, elementBuffer);
  }

  void setCamera(Matrix4 camera, Matrix4 viewMatrix) {

    gl.uniformMatrix4fv(viewTransformLocation, false, viewMatrix.storage);
    gl.uniformMatrix4fv(cameraTransformLocation, false, camera.storage);
  }

  void setTexture(Texture texture) {
    this.texture = texture;
    gl.bindTexture(WebGL.TEXTURE_2D, texture.texture);
  }

  void setFogColor(Vector4 fogColor) {
    gl.uniform4fv(fogColorLocation, fogColor.storage); 
  }

  Vector4 defaultColor = new Vector4(1.0, 1.0, 1.0, 1.0);

  Matrix4 objectMatrix = new Matrix4.identity();
  Matrix4 textureMatrix = new Matrix4.identity();

  void render(Vector3 pos, num w, num h, num uo, num vo, {Vector4 color, Vector3 rotation, num tw, num th}) {

    if (!texture.loaded) return;
    if (color == null) color = defaultColor;
    if (rotation == null) rotation = new Vector3(0.0, 0.0, 0.0);
    if (tw == null) tw = w;
    if (th == null) th = h;

    objectMatrix.setIdentity();
    objectMatrix.translate(pos.x, pos.y, pos.z);
    objectMatrix.rotateX(rotation.x);
    objectMatrix.rotateY(rotation.y);
    objectMatrix.rotateZ(rotation.z);
    objectMatrix.scale(w * 1.0, h * 1.0, 0.0);
    gl.uniformMatrix4fv(objectTransformLocation, false, objectMatrix.storage);

    textureMatrix.setIdentity();
    textureMatrix.scale(1.0 / texture.width, -(1.0 / texture.height), 0.0);
    textureMatrix.translate((uo + tw / 2.0), (vo  + th / 2.0), 0.0);
    textureMatrix.scale((tw - 0.5), (th - 0.5), 0.0);
    gl.uniformMatrix4fv(textureTransformLocation, false, textureMatrix.storage);

    gl.uniform4fv(colorLocation, color.storage);
    gl.drawElements(WebGL.TRIANGLES, 6, WebGL.UNSIGNED_SHORT, 0);
  }
}

And here's the tree I want to render as a billboard:

class Tree extends Object {

  Tree(var pos): super(pos);

  void render() {

    quad.render(getRenderPos(), 48, 48, 0, 208);
  }

  Vector3 getRenderPos() {

    return new Vector3(pos.x, pos.y + 24, pos.z);
  }
}
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
Dramentiaras
  • 193
  • 1
  • 3
  • 12

1 Answers1

1

I understand you want to know how to implement a camera in WebGL, right?

As you are probably aware, the WebGL API does not provide a camera abstraction, so you must build your own camera by hand.

I think the most straightforward approach is to build a transform matrix representing your camera (scale, rotation, translation), then calculate its inverse matrix, and finally apply it to all objects of the scene.

Have a look at this superb introduction by Gregg Tavares:

WebGL 3D Cameras

Everton
  • 12,589
  • 9
  • 47
  • 59