さまざまな属性を使用してポイントスプライトを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の異なる角度で十分です)。同じ回転行列を不必要に再計算する必要がないように、ある種のルックアップを使用できる方法はありますか?定数を頂点シェーダーに格納することは私の最初の考えでしたが、ブランチステートメントをシェーダーに配置し始めたくありません。
良いアプローチについて何か考えはありますか?