繁体   English   中英

在opengl中使用带有freetype的纹理数组

[英]use of texture arrays with freetype in opengl

阅读并运行以下教程( http://learnopengl.com/code_viewer.php?code=in-practice/text_rendering )后,我学会了如何在OpenGL中使用freetype呈现文本。 我现在想知道是否有可能避免为每个字形调用glDrawArrays。 因此我对VBO进行了一些修改,将其用于整个字符串而不是一个字形。 作为第一步,我使用了字符串“AA”,因为两个字形都相同,所以它们也共享相同的纹理。 因此,运行以下代码不是问题:

glGenVertexArrays(1, & textVAO);
glBindVertexArray(textVAO);
glGenBuffers(1, &textVBO);
glBindBuffer(GL_ARRAY_BUFFER,textVBO);
glBufferData(GL_ARRAY_BUFFER, 24* 2* sizeof(float), NULL, GL_DYNAMIC_DRAW);
glVertexPointer( 4, GL_FLOAT, 0, NULL);

其次是:

textShader.Use();
glm::vec3 color;
color = glm::vec3(1.0, 0.7f, 0.9f);
glUniform3f(glGetUniformLocation(textShader.Program, "textColor"), color.x, color.y, color.z);
glBindVertexArray(textVAO);
glActiveTexture(GL_TEXTURE0);
int k=0;
for(c = text.begin(); c != text.end(); c++){
    Character ch = Characters[*c];
    GLfloat xpos = x + ch.Bearing.x * scale;
    GLfloat ypos = y - (ch.Size.y - ch.Bearing.y) * scale;
    GLfloat w = ch.Size.x * scale;
    GLfloat h = ch.Size.y * scale;
    V.block(0,k,24,1) << xpos, ypos + h,0.0,0.0,xpos, ypos,0.0,1.0,xpos + w, ypos,1.0,1.0,xpos, ypos + h,0.0,0.0,xpos + w,ypos,1.0,1.0,xpos + w, ypos+h,1.0,0.0;
    k++;
    x += ( (ch.Advance >> 6) * scale);
}
glBindTexture(GL_TEXTURE_2D,66);

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glBindBuffer(GL_ARRAY_BUFFER,textVBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, 24* 2* sizeof(float), V.data());
glDrawArrays(GL_TRIANGLES,0,4*3);
glBindTexture(GL_TEXTURE_2D,0);
glDisableClientState(GL_VERTEX_ARRAY);
glUseProgramObjectARB(0);

我希望能够在屏幕上呈现“AB”或“ZW”,所以我现在尝试将GL_TEXTURE_2D_ARRAY与glTexImage3D和glTexSubImage3D一起使用。 同样为了简化,我使用“AA”以使字形具有相同的宽度和高度。 所以我补充道

GLuint textureArray;
glEnable(GL_TEXTURE_2D_ARRAY);
glGenTextures(1, &textureArray);
glBindTexture(GL_TEXTURE_2D_ARRAY, textureArray);
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, 4, 30, 35, 2, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);

到先例代码的第一部分,第二部分变成:

textShader.Use();
glm::vec3 color;
color = glm::vec3(1.0, 0.7f, 0.9f);
glUniform3f(glGetUniformLocation(textShader.Program, "textColor"), color.x, color.y, color.z);
glBindVertexArray(textVAO);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_2D_ARRAY);
for(c = text.begin(); c != text.end(); c++) {
    Character ch = Characters[*c];
    GLfloat xpos = x + ch.Bearing.x * scale;
    GLfloat ypos = y - (ch.Size.y - ch.Bearing.y) * scale;
    GLfloat w = ch.Size.x * scale;
    GLfloat h = ch.Size.y * scale;
    V.block(0,k,24,1) << xpos, ypos + h,0.0,0.0,xpos, ypos,0.0,1.0,xpos + w, ypos,1.0,1.0,xpos, ypos + h,0.0,0.0,xpos + w,ypos,1.0,1.0,xpos + w, ypos+h,1.0,0.0;
    glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, k, 30,35, 1, GL_RED, GL_UNSIGNED_BYTE, ch.pointeur);
    k++;
    x += ( (ch.Advance >> 6) * scale);
    }
glBindTexture(GL_TEXTURE_2D_ARRAY,textureArray);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER,textVBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, 24* 2* sizeof(float), V.data());
glDrawArrays(GL_TRIANGLES,0,4*3);
glBindTexture(GL_TEXTURE_2D,0);
glDisableClientState(GL_VERTEX_ARRAY);
glUseProgramObjectARB(0);

代码编译,但我没有在屏幕上得到任何东西。 所以我想知道我是否正确使用了GL_TEXTURE_2D_ARRAY以及我是否必须使用着色器的“数组版本”。 我正在使用OpenGL 4.5,谢谢。

有(至少)两个问题。

首先,您使用的是固定功能管道,它不能与数组纹理一起使用。 访问东西的纹理环境不知道如何处理它们。 如果要使用数组纹理,则必须使用着色器。

其次,即使你使用着色器,你也是这样做的。 然后,教程错误地教你(在这种情况下,教导这样的不良实践,它会对OpenGL用户产生积极的破坏)。 您将每个字形放在自己的数组层中。 好吧,许多OpenGL实现只支持256个数组层 ,如果你想要包含非英文文本,这不是很多字形。

进行字形渲染的正确方法是构建字形的纹理图集,而不是使用每纹理字形(如蹩脚的教程所做)或每个数组层的字形(就像你一样)。 您将多个字形放在单个2D纹理的不同位置,然后使用纹理坐标选择要使用的字形。 这将允许您通过一次绘制调用提交整个文本块。

如今,2D纹理大小可以超过16K像素。 即使只有4096x4096纹理,你也可以在其中加入超过16,000 32x32字形。

我找到了另外两个部分的教程,第一部分(与Joey的教程非常相似)为每个字形调用gldraw,第二部分解释如何在一次调用中绘制整个字符串。 这是第二部分的链接。 可以下载完整的代码(向下滚动页面)。 谢谢!

https://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_Text_Rendering_02

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM