LibGdx 中同一 OpenGl TriStrip 内的不透明度重叠

Opacity overlap within the same OpenGl TriStrip in LibGdx

虽然我的问题完全出在三条带的不透明度上,但我想先给出一些背景信息。

最近我开始通过 LibGdx 开发一款游戏,其中涉及在屏幕上弹跳的 2D 圆圈。为了提供简洁的图形效果,我创建了一个小系统,可以为演员提供 "tail",它会随着时间的推移逐渐消失。在视觉上,它看起来像这样:

Nice Trail Example

现在看起来很满意。然而,我的问题在于部分 "trail" 效果重叠的情况,创建了一个丑陋的人工制品,我猜它是点不透明度的总和。

Ugly Trail Example

我认为这个问题在于绘制三条带的方式,特别是使用的混合方法。 用于生成trail的代码如下:

Array<Vector2> tristrip = new Array<Vector2>(); //Contains the vector information for OpenGL to build the strip.
Array<Vector2> texcoord = new Array<Vector2>(); //Contains the opacity information for the corresponding tristrip point.

// ... Code Here.... //


gl20.begin(camera.combined, GL20.GL_TRIANGLE_STRIP);
    for (int i = 0; i < tristrip.size; i++) {
        if (i == batchSize) {
            gl20.end();
            gl20.begin(camera.combined, GL20.GL_TRIANGLE_STRIP);
        }

        Vector2 point = tristrip.get(i);
        Vector2 textcoord = texcoord.get(i);
        gl20.color(color.r, color.g, color.b, color.a);  // Color.WHITE
        gl20.texCoord(textcoord.x, 0f);
        gl20.vertex(point.x, point.y, 0);
    }
gl20.end();

同样重要的是要注意条带的绘制函数在另一个 class 中以这种方式调用:

private void renderFX() {
    Gdx.gl.glEnable(GL20.GL_BLEND);
    Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);


    Array<Ball> balls = mainstage.getBalls();

    for (int i = 0; i < balls.size; i++) { //Draws the trails for each actor
        balls.get(i).drawFX();
    }

} 

这个问题是我新手犯的错误,还是我绘制矢量数组 tristrip 的实现从一开始就存在缺陷?如何解决混合问题,以便即使在存在急转弯的情况下也能创建更平滑的轨迹?

提前致谢...

编辑:自从最初提出这个问题以来,我已经尝试了一些可能的解决方案,还实施了 Deniz Yılmaz 关于使用 FBO 促进混合的建议。鉴于此,我的渲染函数目前看起来像这样:

private void renderFX() {
    frameBuffer.begin();

    Gdx.gl20.glDisable(GL20.GL_BLEND);

    Gdx.gl20.glClearColor(0f, 0f, 0f, 0);
    Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT);

    Gdx.gl20.glEnable(GL20.GL_STENCIL_TEST);
    Gdx.gl20.glStencilOp(GL20.GL_KEEP, GL20.GL_INCR, GL20.GL_INCR);
    Gdx.gl20.glStencilMask(0xFF);

    Gdx.gl20.glClear(GL20.GL_STENCIL_BUFFER_BIT);

    Array<Ball> balls = mainstage.getBalls();

    for (int i = 0; i < balls.size; i++) {

        Gdx.gl20.glStencilFunc(GL20.GL_EQUAL, 0, 0xFF);

        balls.get(i).drawFX(1f, Color.RED);
    }
    frameBuffer.end();

}

如图所示,我还尝试使用模板来掩盖轨迹的重叠部分。然而,这种方法会产生以下视觉效果:

Stenciled Version

同样,这并不理想,并且让我意识到通过遮罩解决这个问题不是一个好主意,因为不透明度渐变在角落永远不会平滑,因为在角落之间总会有一条锐线两个重叠的不透明度值,即使逻辑以某种方式阻止混合。

鉴于此,我还能如何解决这个问题?如果我打算为这种轨迹效果实现平滑渐变,是否应该完全放弃这种方法?

再次感谢。

glBlendFunc() 在这种情况下没有用,因为默认情况下会添加基于混合函数计算的值。

所以需要像 glBlendEquation(GL_MAX) 这样的东西

但是

单独混合是行不通的,因为它无法区分什么是背景和什么是重叠形状。

改为使用 FrameBuffer 通过 glBlendEquation 绘制轨迹。

https://github.com/mattdesl/lwjgl-basics/wiki/FrameBufferObjects