3

2 点間の線の各ステップの各ピクセルでフレーム バッファにスプライトを描画していますが、ブレンドに問題があります。

ここに画像の説明を入力

私は現在使用しています:

(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

次に、シェーダーで次のことを行います。

if( color.a == 0 )
  color.rgb = 0;

ただし、赤と緑の星を見ると、アルファが (0,1) の間隔で発生する「加算ブレンディング」が見られます。


加算ブレンドを使用しないと、次の 3D 効果が発生します。

ここに画像の説明を入力


似たような色を加法ブレンドする方法はありますが、色が一致しない場合は避けてください。

次のようになります。

ここに画像の説明を入力

4

1 に答える 1

2

これは、あらかじめ乗算されたアルファを使用して行うことができます。

まず、テクスチャを適切に設定する必要があります。次のように黒地に白で描画します。 ここに画像の説明を入力

次に、テクスチャの明るさをアルファ チャネルに複製します。GIMP では、レイヤーを右クリックし、[レイヤー マスクの追加]、[レイヤーのグレースケール コピー] の順に選択して、これを行うことができます。これは次のようになります (Gimp で示されているように)。

ここに画像の説明を入力

次に、必要に応じて RGB チャネルの色を変更できますが、白のままにしてコード内で色を付ける方が汎用性があります。

コードでシェイプを描画するときは、あらかじめ乗算されたアルファにブレンド関数を使用します。

batch.setBlendFunction(GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA);

そして、デフォルトの SpriteBatch シェーダーを使用して描画します。シェイプを描画したら、通常のアルファ ブレンディングに戻ります。

batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);

サンプルゲーム:

ここに画像の説明を入力

public class GameMain extends ApplicationAdapter implements InputProcessor{
    SpriteBatch batch;

    Texture star;
    Color color = new Color();
    Viewport viewport;
    int screenWidth, screenHeight;
    FrameBuffer fbo;
    boolean shouldClearFBO = false;
    boolean fboUpdated = false;
    OrthographicCamera fullScreenCamera;

    boolean touchDown = false;
    Vector2 touchLocation = new Vector2();

    int colorIndex = 0;
    static final int[] COLORS = {0xff0000ff, 0x00ff00ff, 0x0000ffff, 0xffff00ff, 0xff00ffff, 0x00ffffff, 0xffffffff};

    static final float SIZE = 150;

    @Override
    public void create () {
        batch = new SpriteBatch();
        star = new Texture("star.png");
        viewport = new ExtendViewport(800, 480);
        fullScreenCamera = new OrthographicCamera();
        Gdx.input.setInputProcessor(this);
    }

    @Override
    public void resize (int width, int height){
        viewport.update(width, height, true);
        fullScreenCamera.setToOrtho(false, width, height);
        fullScreenCamera.position.set(width/2, height/2, 0);
        fullScreenCamera.update();
        fboUpdated = false;
        screenWidth = width;
        screenHeight = height;
    }

    @Override
    public void render () {
        if (!fboUpdated){
            fboUpdated = true;
            if (fbo!=null)
                fbo.dispose();
            fbo = new FrameBuffer(Pixmap.Format.RGBA8888, screenWidth, screenHeight, false);
            fbo.begin();
            Gdx.gl.glClearColor(0, 0, 0, 1);
            Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
            fbo.end();
        }

        color.set(COLORS[colorIndex]);

        fbo.begin();
        if (shouldClearFBO){
            shouldClearFBO = false;
            Gdx.gl.glClearColor(0, 0, 0, 1);
            Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        }
        if (touchDown){
            batch.setProjectionMatrix(viewport.getCamera().combined);
            batch.setBlendFunction(GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA);
            batch.begin();
            batch.setColor(color);
            batch.draw(star, touchLocation.x - SIZE/2, touchLocation.y - SIZE/2, SIZE, SIZE);
            batch.end();
        }
        fbo.end();

        Gdx.gl.glClearColor(0, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        batch.setColor(Color.WHITE);
        batch.setProjectionMatrix(fullScreenCamera.combined);
        batch.setBlendFunction(GL20.GL_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
        batch.begin();
        batch.draw(fbo.getColorBufferTexture(), 0, screenHeight, screenWidth, -screenHeight);
        batch.end();
    }

    @Override
    public boolean keyDown(int keycode) {
        switch (keycode){
            case Input.Keys.SPACE:
                colorIndex = (++colorIndex) % COLORS.length;
                return true;
            case Input.Keys.X:
                shouldClearFBO = true;
                return true;
        }

        return false;
    }

    @Override
    public boolean keyUp(int keycode) {
        return false;
    }

    @Override
    public boolean keyTyped(char character) {
        return false;
    }

    @Override
    public boolean touchDown(int screenX, int screenY, int pointer, int button) {
        viewport.unproject(touchLocation.set(screenX, screenY));
        if (pointer==1){
                colorIndex = (++colorIndex) % COLORS.length;
                return true;
        }
        if (pointer == 2){
            shouldClearFBO = true;
            return true;
        }
        touchDown = true;
        return true;
    }

    @Override
    public boolean touchUp(int screenX, int screenY, int pointer, int button) {
        touchDown = false;
        return true;
    }

    @Override
    public boolean touchDragged(int screenX, int screenY, int pointer) {
        viewport.unproject(touchLocation.set(screenX, screenY));
        return true;
    }

    @Override
    public boolean mouseMoved(int screenX, int screenY) {
        return false;
    }

    @Override
    public boolean scrolled(int amount) {
        return false;
    }
}
于 2015-02-16T22:14:54.517 に答える