I am trying to find a solution that will allow me to rotate point sprites about the z-axis with a varying attribute (i.e. uniform will not do).
In my app I have many hundreds/thousands of point sprites being drawn per frame, which are then stored in VBOs (can quite feasibly end up being >1,000,000). As such, I am looking for the best compromise between memory usage and performance.
Vertex & fragment shaders current look like this:
// VERTEX SHADER
attribute vec4 a_position;
attribute vec4 a_color;
attribute float a_size;
uniform mat4 u_mvpMatrix;
varying vec4 v_color;
void main()
{
v_color = a_color;
gl_Position = u_mvpMatrix * a_position;
gl_PointSize = a_size;
}
// FRAGMENT SHADER
precision mediump float;
uniform sampler2D s_texture;
varying vec4 v_color;
void main()
{
vec4 textureColor = texture2D(s_texture, gl_PointCoord);
gl_FragColor = v_color * textureColor;
}
I can currently imagine the following possibilities:
Add a
mat4 rotMatrix
attribute to my point sprite data. Pass this to the fragment shader and rotate each fragment:vec2 texCoord = (rotMatrix * vec4(gl_PointCoord, 0, 1)).xy gl_FragColor = v_color * texture2D(s_texture, texCoord);
- Advantages:
- Keeps shaders simple.
- Simple code to compute matrices outside the shaders (using
GLKit
for example).
- Disadvantages:
- Massively increases the size of my point sprite data (from 16 to 80 bytes/point for a 4x4 matrix; to 52 bytes/point for a 3x3 matrix... I believe it's possible to use a 3x3 rotation matrix?). This could potentially cause my app to crash 3-5 times sooner!
- Pushes a lot more computation onto the CPU (hundreds/thousands of matrix calculations per frame).
- Advantages:
Add a
float angle
attribute to my point sprite data, then calculate the rotation matrix in the vertex shader. Pass the rotation matrix to the fragment shader as above.- Advantages:
- Keeps point sprite data size small (from 16 to 20 bytes/point).
- Pushes the heavy lifting matrix maths to the GPU.
- Keeps point sprite data size small (from 16 to 20 bytes/point).
- Disadvantages:
- Need to write custom GLSL function to create rotation matrix. Not a massive problem, but my matrix maths is rusty, so this could be error prone, especially if I'm trying to figure out the 3x3 matrix solution...
- Given that this must happen on hundreds/thousands of vertices, is this going to be a serious drag on performance (despite being handled by the GPU)?
- Advantages:
- I could realistically cope with 1 byte for the angle attribute (255 different angles would be sufficient). Is there any way I could use some kind of lookup so that I don't need to needlessly recalculate the same rotation matrices? Storing constants in the vertex shader was my first thought, but I don't want to start putting branch statements in my shaders.
Any thoughts as to a good approach?