我正在尝试找到一个解决方案,它允许我围绕 z 轴旋转具有不同属性的点精灵(即统一不会这样做)。
在我的应用程序中,我每帧绘制了成百上千个点精灵,然后将它们存储在 VBO 中(很可能最终会超过 1,000,000)。因此,我正在寻找内存使用和性能之间的最佳折衷方案。
当前的顶点和片段着色器如下所示:
// 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;
}
我目前可以想象以下可能性:
mat4 rotMatrix
为我的点精灵数据添加一个属性。将此传递给片段着色器并旋转每个片段:vec2 texCoord = (rotMatrix * vec4(gl_PointCoord, 0, 1)).xy gl_FragColor = v_color * texture2D(s_texture, texCoord);
- 优点:
- 保持着色器简单。
- 计算着色器之外的矩阵的简单代码(
GLKit
例如使用)。
- 缺点:
- 大大增加了我的点精灵数据的大小(对于 4x4 矩阵,从 16 字节/点增加到 80 字节/点;对于 3x3 矩阵,增加到 52 字节/点……我相信可以使用 3x3 旋转矩阵?)。这可能会导致我的应用程序提前 3-5 次崩溃!
- 将更多的计算推到 CPU 上(每帧数十/千次矩阵计算)。
- 优点:
为我的点精灵数据添加一个
float angle
属性,然后在顶点着色器中计算旋转矩阵。如上所述将旋转矩阵传递给片段着色器。- 优点:
- 使点精灵数据大小保持较小(从 16 到 20 字节/点)。
- 将繁重的矩阵数学推送到 GPU。
- 使点精灵数据大小保持较小(从 16 到 20 字节/点)。
- 缺点:
- 需要编写自定义 GLSL 函数来创建旋转矩阵。不是一个大问题,但我的矩阵数学生锈了,所以这可能容易出错,特别是如果我试图找出 3x3 矩阵解决方案......
- 鉴于这必须发生在成百上千个顶点上,这是否会严重拖累性能(尽管由 GPU 处理)?
- 优点:
- 我可以实际处理角度属性的 1 个字节(255 个不同的角度就足够了)。有什么方法可以使用某种查找,这样我就不需要不必要地重新计算相同的旋转矩阵?在顶点着色器中存储常量是我的第一个想法,但我不想开始在我的着色器中放置分支语句。
关于好方法的任何想法?