1

Stencil buffer を使用してマスクとして使用したいこのテクスチャがあります:

次に、上の画像が見える場所 (色がある場所) にのみ表示される画像 IMG を画面に描画し、上端とグラデーションの下の透明なピクセルを除外します。

問題は、画面にイメージ IMG を描画するたびに、ピクセルが透明かどうかに関係なく、イメージが描画されたすべての場所に表示されることです。

だから私は使用することを考えALPHA_TESTましたが、最新のOpenGLバージョンではなくなったので、フラグメントシェーダーで、v_color.a == 0またはv_color.r == 0フラグメントシェーダーでフラグメントを破棄しようとしましたが、何もしません...

フラグメント シェーダ :

#ifdef GL_ES
    #define LOWP lowp
    precision mediump float;
#else
    #define LOWP
#endif

uniform sampler2D u_texture;

varying LOWP vec4 v_color;
varying vec2 v_texCoords;

void main() {
    if (v_color.a == 0) {
        discard;
    }

    gl_FragColor = v_color * texture2D(u_texture, v_texCoords);
}

頂点シェーダー :

attribute vec4 a_color;
attribute vec4 a_position;
attribute vec2 a_texCoord0;

uniform mat4 u_projTrans;

varying vec4 v_color;
varying vec2 v_texCoords;

void main() {
    v_color = a_color;
    v_texCoords = a_texCoord0;
    gl_Position = u_projTrans * a_position;
}

コード :

@Override
public void draw(final DrawConfig drawConfig) {
    this.applyTransform(drawConfig.getBatch(), this.computeTransform());

    // Draw mask to stencil buffer

    drawConfig.end();
    final GL20 gl = Gdx.gl;

    gl.glEnable(GL20.GL_STENCIL_TEST);
    gl.glStencilFunc(GL20.GL_ALWAYS, 1, 0xFF);
    gl.glStencilOp(GL20.GL_REPLACE, GL20.GL_REPLACE, GL20.GL_REPLACE);
    gl.glStencilMask(0xFF);
    gl.glColorMask(false, false, false, false);
    gl.glClearStencil(0);
    gl.glClear(GL20.GL_STENCIL_BUFFER_BIT);

    drawConfig.begin(Mode.BATCH);
    this.mBackground.setClippingEnabled(true); // The clipping area is a rectangle centered in the screen
    this.mBackground.draw(drawConfig);
    this.mBottomBorder.draw(drawConfig); // Border below the rectangle area
    this.mTopBorder.draw(drawConfig); // Border above the rectangle area
    drawConfig.end();

    gl.glColorMask(true, true, true, true);
    gl.glStencilFunc(GL20.GL_EQUAL, 1, 0xFF);
    gl.glStencilMask(0x00);

    // Draw elements

    this.mBackground.setClippingEnabled(false); // No clipping area, use stencil test
    this.mBackground.draw(drawConfig);
    this.mBottomBorder.draw(drawConfig);
    this.mTopBorder.draw(drawConfig);

    drawConfig.end();
    Gdx.gl.glDisable(GL20.GL_STENCIL_TEST);

    this.resetTransform(drawConfig.getBatch());
}

結果 :

赤い矢印は、境界線からはみ出し、消したい部分を示しています。黄色の四角はクリッピング エリアです。

4

1 に答える 1

1

複製しようとしている固定関数アルファ テスト ( GL_ALPHA_TEST) は、フラグメントごとのテストでした。以前はフラグメント シェーダーが終了した後に発生していましたが、 を使用して自分で実装できますdiscard

ただし、現在のソリューションは補間された頂点ごとのアルファ値を使用しており、マスクとして使用しようとしているテクスチャとは関係ありません。gl_FragColorこれを適切に行うには、に割り当てられたアルファ値をテストする必要があります。

void main() {
    gl_FragColor = v_color * texture2D(u_texture, v_texCoords);

    if (gl_FragColor.a == 0.0) {
        discard;
    }
}

これは、次のものに相当する最新のシェーダーベースのものです。

glAlphaFunc (GL_NOTEQUAL, 0.0f); // Reject fragments with alpha == 0.0
glEnable    (GL_ALPHA_TEST);
于 2015-03-28T03:04:56.860 に答える