我正在尝试使用STB在Java中从ttf文件渲染字体,但是我在渲染时遇到了问题。我认为问题在于烘焙的字体数据是某种格式,我没有正确使用它,而是查看this 使用LWJGL3进行演示,但使用的是旧版OpenGL。查看代码,我首先看到它被称为
glBindTexture(GL_TEXTURE_2D, texID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, BITMAP_W, BITMAP_H, 0,
GL_ALPHA, GL_UNSIGNED_BYTE, bitmap);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glClearColor(43f / 255f, 43f / 255f, 43f / 255f, 0f); // BG color
glColor3f(169f / 255f, 183f / 255f, 198f / 255f); // Text color
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
所以在我的代码中,我绑定了纹理,而不是这个:
glTexCoord2f(q.s0(), q.t0());
glVertex2f(x0, y0);
glTexCoord2f(q.s1(), q.t0());
glVertex2f(x1, y0);
glTexCoord2f(q.s1(), q.t1());
glVertex2f(x1, y1);
glTexCoord2f(q.s0(), q.t1());
glVertex2f(x0, y1);
我将数据添加到FloatBuffer中,如下所示:
if (vertices.remaining() < 7 * 6) {
/* We need more space in the buffer, so flush it */
flush();
}
float r = c.getRed();
float g = c.getGreen();
float b = c.getBlue();
float a = c.getAlpha();
vertices.put(x1).put(y1).put(r).put(g).put(b).put(a).put(s1).put(t1);
vertices.put(x1).put(y2).put(r).put(g).put(b).put(a).put(s1).put(t2);
vertices.put(x2).put(y2).put(r).put(g).put(b).put(a).put(s2).put(t2);
vertices.put(x1).put(y1).put(r).put(g).put(b).put(a).put(s1).put(t1);
vertices.put(x2).put(y2).put(r).put(g).put(b).put(a).put(s2).put(t2);
vertices.put(x2).put(y1).put(r).put(g).put(b).put(a).put(s2).put(t1);
numVertices += 6;
然后将其冲洗:
if (numVertices > 0) {
vertices.flip();
if (vao != null) {
vao.bind();
} else {
vbo.bind(GL_ARRAY_BUFFER);
specifyVertexAttributes();
}
program.use();
/* Upload the new vertex data */
vbo.bind(GL_ARRAY_BUFFER);
vbo.uploadSubData(GL_ARRAY_BUFFER, 0, vertices);
/* Draw batch */
glDrawArrays(GL_TRIANGLES, 0, numVertices);
/* Clear vertex data for next batch */
vertices.clear();
numVertices = 0;
}
我在这里得到ByteBuffer:
STBTTBakedChar.Buffer cdata = STBTTBakedChar.malloc(96);
ByteBuffer bitmap = BufferUtils.createByteBuffer(BITMAP_W*BITMAP_H);
stbtt_BakeFontBitmap(ttf, font.getSize()*Window.getContentScaleY(), bitmap,
BITMAP_W, BITMAP_H, 32, cdata);
每个字形都在此处呈现:
try (MemoryStack stack = stackPush()) {
IntBuffer pCodePoint = stack.mallocInt(1);
FloatBuffer x = stack.floats(0.0f);
FloatBuffer y = stack.floats(0.0f);
STBTTAlignedQuad q = STBTTAlignedQuad.mallocStack(stack);
float factorX = 1.0f/Window.getContentScaleX();
float factorY = 1.0f/Window.getContentScaleY();
float lineY = 0.0f;
for (int i = 0, to = text.length(); i < to; ) {
int cp = pCodePoint.get(0);
if (cp == '\n') {
y.put(0, lineY = y.get(0)+(ascent-
descent+lineGap)*font.getSize());
x.put(0, 0.0f);
i += getCP(text, to, i, pCodePoint);
continue;
} else if (cp < 32 || 128 <= cp) {
i += getCP(text, to, i, pCodePoint);
continue;
}
float cpX = x.get(0);
stbtt_GetBakedQuad(cdata, BITMAP_W, BITMAP_H, cp-32, x, y, q,
true);
x.put(0, scale(cpX, x.get(0), factorX));
getCP(text, to, i, pCodePoint);
x.put(0, x.get(0)+stbtt_GetCodepointKernAdvance(info, cp,
pCodePoint.get(0))*font.getSize());
float
x0 = scale(cpX, q.x0(), factorX),
x1 = scale(cpX, q.x1(), factorX),
y0 = scale(lineY, q.y0(), factorY),
y1 = scale(lineY, q.y1(), factorY);
font.genMipmaps();
drawTextureRegion(x0, y0, x1, y1, q.s0(), q.s1(), q.t0(),
q.t1(), font.getC());
i += getCP(text, to, i, pCodePoint);
}
}
(getCP仅用于堆叠的字符,出于我的目的,它将始终返回1) 现在,无需渲染字体,我只能看到应该绘制的一种播放器纹理,包括颜色和所有内容。当我渲染字体时。一个大黑盒子覆盖了播放器的区域,并且没有文本呈现。
我尝试用纹理进行贴图,但这没有用。我确保调用glEnableVertexAttribArray()。 那么,为什么黑匣子在那里,为什么文本没有呈现? (我在右上角制作了图片,在左下角制作了文字)
Here is the GitHub with the entire project
仔细检查ByteBuffer我很确定这些值的顺序正确。
添加了glTexImage2D和glTexParameteri,但仍然没有。
浏览问题时,我看到的唯一答案是mipmapping(我尝试过)并调用glEnableVertexAttribArray()。
本来没有做很多,但是经过更多的移动研究之后,我仍然茫然无措。