[WebGL] Reconcile the global matrix
See original GitHub issueThis ticket will pick up where #591 leaves off. The goal here is to remove dependence on the global matrix, as much as possible. It will allow us to put almost every matrix transformation entirely within the GPU, where it can take advantage of highly parallelized vector ALUs that we don’t have access to in JavaScript.
To start, recall that 3D rendering typically uses three matrices; called “model matrix”, “view matrix”, and “projection matrix”. Working backwards, melonJS needs the projection matrix to transform our pixel coordinates to WebGL cube space coordinates using orthographic projection; and a view matrix is used for nested containers and other object that need relative drawing operations. The model matrix is unnecessary because the majority of entities drawn in melonJS are quads (exactly two triangles). A model matrix is more useful with large meshes, which have a greater number of vertices.
The scaling and rotation values can be streamed to the GPU as part of the vertex attribute array. These can be packed into 2 floats (a 3x3 matrix requires 6 floats for full precision) assuming 16 bits for each of the scaling coordinates. Additionally, the rotation angle and texture index can be packed into the same float. The anchor point will also be required, which is a 3rd float. These attributes can be applied within the vertex shader, since the order of operations is static; translation can be added to the destination coordinates before calling drawImage
.
Entities that need a model matrix can implement one with a custom compositor and shader. Spine is an example that will benefit from a model matrix.
To reconcile the global matrix, we need to remove most of the matrix transformation usage. me.Sprite
and me.Particle
make heavy use of the global matrix right now. Here is the last proposal for a replacement: https://github.com/melonjs/melonJS/issues/591#issuecomment-68618550 The important part is that the first argument provides information about things like scaling and rotation for each drawImage
call. The function signature will have to change to accept a texture region instead of coordinates, as an additional optimization. See: https://github.com/melonjs/melonJS/commit/e785724ac5439f27e43a3a9c42a5eaa082bff1f2#commitcomment-9329151
With that part done, each view matrix transformation will be treated as change in WebGL state; it will be sent to the GPU as a uniform variable, so changes to the matrix require flushing the compositor. This will be pretty efficient, assuming view matrix transformations only occur on me.Container
boundaries.
Additional TODO items:
- Implement fonts (hard), lines (easy), stroke (hard)
- Create a packet inspector for debugging
- Enable mipmapping on power-of-two textures
- Pack multiple attributes into each float
- Use a standard sampler2D-uniform on mobile
Attribute Packing: E.g. texture coordinates can be packed into a single float, since each axis will never be bigger than 65,536 pixels (fits into 16-bits). The packing algorithms will provide less than 16-bits of precision, probably 15-bits, which is still plenty for texture coordinates. Another candidate is colors, and much bigger win: pack a vec4
into a single float with almost no loss in precision!
Issue Analytics
- State:
- Created 9 years ago
- Comments:11 (7 by maintainers)
Top GitHub Comments
@obiot I would be glad to help, but I have very limited time atm. I’ve not been able to even complete the typings yet.
But, I can give some quick tips for now from skimming over the description:
closing this one, lots of improvements were done during the last 2 majors version, at a point where we don’t really need this ticket to track the here above left over points.