私は(iOSで)GLSLを試していますが、2つの円(、、、)の色の値とパラメーターを受け取る単純なシェーダーを作成しcenter
ましradius
たedgeSmoothing
。画面全体に単一のクワッドを使用して描画され、シェーダーはgl_FragCoord
各ポイントが円の内側にあるか外側にあるかを使用して決定します-円の内側に1.0のアルファを計算し、外側に0.0までスムーズにシェーディングしradius + edgeSmoothing
、ミラーを適用します-クランプをアルファ(偶数奇数のフィルルール効果を得るための三角波)にスタイル設定し、を設定しますgl_FragColor = mix(vec4(0.0), color, alpha);
。
glUniform
これは問題なく機能しますが、5つの異なる色で10個の円が必要なので、すべてのシェーダーユニフォームを呼び出しglDrawElements
、クワッドを5回別々に描画します(異なる色と円のパラメーターを使用)。ブレンドモードは加法であるため、異なる色が追加されます。私が望むパターンを与えるためにうまくアップしてください、完璧です!
これは実験であるため、円を描くだけでなく、GLとGLSLについても学ぼうとしています。
centers[10]
これで、クワッドを1回だけ描画し、10個の円すべてのパラメーターを均一な配列( 、radii[10]
など)に渡して、GLSLでループし、シェーダーで生成される色を合計する方がはるかに効率的だと思います。 。そこで、このシェーダーを作成し、コードをリファクタリングして、すべての円パラメーターを一度に渡します。正しい結果が得られます(出力はまったく同じに見えます)が、フレームレートが15fpsから約3fpsに低下します-5倍遅くなります!!
シェーダーコードにループが追加されましたが、同じ計算を使用して、円の各ペアのアルファ値を計算します。なぜこれほど遅いのですか?確かに、画面全体を5回塗りつぶし、GLが5回加法ブレンド(つまり、ピクセル値の読み取り、ブレンド、書き戻し)を行うよりも少ない作業を行っていますか?今、私は蓄積された色を計算し、画面全体を一度だけ塗りつぶしていますか?
最適化だと思ったことが逆の効果をもたらした理由を誰かが説明できますか?
更新:このコードをShaderToyに貼り付けて、私が話していることを確認してください。
#ifdef GL_ES
precision highp float;
#endif
uniform float time;
void main(void)
{
float r, d2, a0, a1, a2;
vec2 pos, mid, offset;
vec4 bg, fg;
bg = vec4(.20, .20, .40, 1.0);
fg = vec4(.90, .50, .10, 1.0);
mid = vec2(256.0, 192.0);
// Circle 0
pos = gl_FragCoord.xy - mid;
d2 = dot(pos, pos);
r = 160.0;
a0 = smoothstep(r * r, (r + 1.0) * (r + 1.0), d2);
// Circle 1
offset = vec2(110.0 * sin(iGlobalTime*0.8), 110.0 * cos(iGlobalTime));
pos = gl_FragCoord.xy - mid + offset;
d2 = dot(pos, pos);
r = 80.0;
a1 = smoothstep(r * r, (r + 1.0) * (r + 1.0), d2);
// Circle 2
offset = vec2(100.0 * sin(iGlobalTime*1.1), -100.0 * cos(iGlobalTime*0.7));
pos = gl_FragCoord.xy - mid + offset;
d2 = dot(pos, pos);
r = 80.0;
a2 = smoothstep(r * r, (r + 1.0) * (r + 1.0), d2);
// Calculate the final alpha
float a = a0 + a1 + a2;
a = abs(mod(a, 2.0) - 1.0);
gl_FragColor = mix(bg, fg, a);
}