渐变色文本

exe*_*nza 8 opengl blending libgdx

我实际尝试实现的目标: 我想用渐变垂直颜色绘制文本。我找到了这个解决方案,但它不太适合我,因为在我的例子中它的渐变字体周围有黑色方块 - 不知道如何摆脱它,所以我开始了简单的(不相关的部分)问题更好地理解 opengl 和 libgdx 中混合和帧缓冲的物理原理

我试图理解的,与我的目标无关: 我有一个纹理,上面有一个白色方块,我把它画在红色背景上。我试图在白色方块的顶部绘制一个绿色方块,绿色方块部分覆盖白色方块,部分覆盖红色背景(见下图)。

我的意图是:绿色方块后面的白色区域应该涂成绿色,但所有红色背景不应该受到影响并保持不变(红色原样)。

我怎样才能做到这一点?

package com.mygdx.game;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;

public class Game extends ApplicationAdapter {
    SpriteBatch batch;
    Texture img;
    private int height;
    private int width;
    private ShapeRenderer shapeRenderer;

    @Override
    public void create() {
        batch = new SpriteBatch();
        img = new Texture("white.png");
        width = Gdx.graphics.getWidth();
        height = Gdx.graphics.getHeight();
        shapeRenderer = new ShapeRenderer();
        shapeRenderer.setAutoShapeType(true);
    }

    @Override
    public void render() {
        Gdx.gl.glClearColor(1, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        batch.begin();
        batch.draw(img, width / 7, height / 4);
        batch.end();

        Gdx.gl.glEnable(GL20.GL_BLEND);
        Gdx.gl.glBlendFunc(GL20.GL_ONE, GL20.GL_SRC_COLOR);
        shapeRenderer.begin();
        shapeRenderer.set(ShapeRenderer.ShapeType.Filled);
        shapeRenderer.setColor(Color.GREEN);
        shapeRenderer.rect(width / 2 - 100, height / 4 - 50, 200, 200);
        shapeRenderer.end();
        Gdx.gl.glDisable(GL20.GL_BLEND);
    }

    @Override
    public void dispose() {
        batch.dispose();
        img.dispose();
    }
}
Run Code Online (Sandbox Code Playgroud)

理想情况下,绿色方块无论如何都不应该是透明的,而应该在隐藏白色区域的地方挡住白色。

我得到的输出: 截屏

更新:我将@Xoppa 的答案标记为正确,因为它解决了我原来的问题,结果如下:

在此处输入图片说明

Xop*_*ppa 6

您确实可以使用某种蒙版来使用正方形混合它。为此,您可以首先使用自定义着色器将文本渲染到模板缓冲区,该着色器会丢弃 alpha 值低于特定阈值的片段。之后,您可以使用模板功能渲染正方形以仅影响文本“触摸”的片段。请注意,这确实涉及多个渲染调用,因此也会增加调用代码的复杂性。

但是,您说您实际上只想使用渐变呈现文本。为此,您不需要这种复杂的方法,只需在同一个渲染调用中应用渐变即可。

当你绘制文本时,你实际上渲染了许多小方块,对于文本中的每个字符一个方块。每个方块都应用了一个纹理区域,其中包含透明背景上的角色。如果您打开字体图像(例如,这是默认设置),那么您将看到此源图像。

就像您可以对普通正方形应用渐变一样,您也可以对构成文本的每个单独正方形应用渐变。有多种方法可以做到这一点。哪种最适合取决于用例。例如,如果您需要水平渐变或多行文本,则需要一些额外的步骤。由于您没有指定这一点,我将假设您想在单行文本上应用垂直渐变:

public class MyGdxGame extends ApplicationAdapter {
    public static class GradientFont extends BitmapFont {
        public static void applyGradient(float[] vertices, int vertexCount, float color1, float color2, float color3, float color4) {
            for (int index = 0; index < vertexCount; index += 20) {
                vertices[index + SpriteBatch.C1] = color1;
                vertices[index + SpriteBatch.C2] = color2;
                vertices[index + SpriteBatch.C3] = color3;
                vertices[index + SpriteBatch.C4] = color4;
            }
        }

        public GlyphLayout drawGradient(Batch batch, CharSequence str, float x, float y, Color topColor, Color bottomColor) {
            BitmapFontCache cache = getCache();
            float tc = topColor.toFloatBits();
            float bc = bottomColor.toFloatBits();
            cache.clear();
            GlyphLayout layout = cache.addText(str, x, y);
            for (int page = 0; page < cache.getFont().getRegions().size; page++) {
                applyGradient(cache.getVertices(page), cache.getVertexCount(page), bc, tc, tc, bc);
            }
            cache.draw(batch);
            return layout;
        }
    }

    SpriteBatch batch;
    GradientFont font;
    float topColor;
    float bottomColor;

    @Override
    public void create () {
        batch = new SpriteBatch();
        font = new GradientFont();
    }

    @Override
    public void render () {
        Gdx.gl.glClearColor(1, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        batch.begin();
        font.drawGradient(batch, "Hello world", 0, 100, Color.GREEN, Color.BLUE);
        batch.end();
    }

    @Override
    public void dispose () {
        batch.dispose();
        font.dispose();
    }
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,为了获得更好的答案,您应该包括您试图解决的实际问题,而不是专注于您认为的解决方案。另请参阅:https : //stackoverflow.com/help/asking