1

私はシェーダーの完全な初心者なので、基本的に画面を 2D の黒いテクスチャで覆い、明るい領域がある透明な穴のある 2D 照明システムを動作させようとしているときに、いくつかの問題が発生しました。

テクスチャを 1 つしか使用していないので、フラグメント シェーダーでこれを行う必要があると思いますよね?

フラグメント シェーダー:

#ifdef GL_ES
precision mediump float;
#endif

// Texture, coordinates and size
uniform sampler2D u_texture;
varying vec2 v_texCoord;
uniform vec2 textureSize;

uniform int lightCount;

struct LightSource
{
    vec2 position;
    float radius;
    float strength;
};

uniform LightSource lights[10];

void main()
{
    float alpha = 1.0;

    vec2 pos = vec2(v_texCoord.x * textureSize.x, v_texCoord.y * textureSize.y);

    int i;
    for (i = 0; i < lightCount; i++)
    {
        LightSource source = lights[i];

        float distance = distance(source.position, pos);

        if (distance < source.radius)
        {
            alpha -= mix(source.strength, 0.0, distance/source.radius);
        }
    }

    gl_FragColor = vec4(0.0, 0.0, 0.0, alpha);
}

問題は、パフォーマンスが本当にひどいことです (2 つのライトがあり、画面上に他に何もない状態で 60fps で実行することはできません)。改善するための提案や、この問題に対処するための別の方法はありますか?

ちなみに、私はcocos2d-xからこれをやっているので、誰かがcocos2d要素を使用するアイデアを持っていれば、それも歓迎されます:)

4

2 に答える 2

2


私はティムに完全に同意します。全体の速度を向上させたい場合は、for ループを避ける必要があります。ライト配列のサイズが常に 10 である場合は、ループ ステートメントをループ コンテンツの 10 個のコピーと交換することをお勧めします。ループ ステートメントで宣言した変数は、ループの最後で解放されることに注意してください。したがって、ループを 10 の部分にまたがることをお勧めします (醜いですが、これは昔ながらのトリックです ;))))
また、すべてのステートメントに println を入れて、どの命令が混乱しているかを確認することもお勧めします。ミックス操作が原因だと思います。cocos2d については何も知らないのですが、プロセスの最後に、距離と強度の要約を使用して、独自の呼び出しで mix を行うことは可能でしょうか? ある時点であるようです」

于 2012-09-06T08:04:12.537 に答える
1

私が試みる2つのこと(役立つとは限りません)

  1. forループを削除し、2つのライトでハードコードします。forループは、ドライバーによって適切に処理されない場合、コストがかかる可能性があります。それがあなたを遅くしているのかどうかを知るのは良いことです。

  2. ステートメントが高額になる可能性があり、それが適切なアプリケーションではないと思うmix場合(あなたは、を実行していて、a*(1-c) + 0.0 * cその用語の後半は無意味です)。私はこれをifステートメントに置き換えてみるかもしれません:

    if (distance < source.radius)
    {
        alpha -= mix(source.strength, 0.0, distance/source.radius);
    }
    

    この一行で:

    alpha -= (1.0-min(distance/source.radius, 1.0)) * source.strength;
    
于 2012-09-05T17:07:04.690 に答える