使用 SDL2 和 OpenGL 使用 SDL TTF 显示文本
Displaying text with SDL TTF with SDL2 and OpenGL
我正在尝试使用 SDL2 TTF 和 OpenGL 显示文本。 window 中出现奇怪的纹理,它的大小和位置都正确,但您看不到任何字母。
我试过使用 SDL_CreateRGBSurface() 认为它可能是恢复像素的更干净的方法,但它也没有用。我的表面从不为 NULL,并且总是通过验证测试。
我在 while() 循环之前使用 get_front() 函数,并在其中使用 displayMoney() 函数,紧接着使用 glClear(GL_COLOR_BUFFER_BIT).
SDL、TTF 和 OpenGL 已正确初始化,我已创建 OpenGL 上下文。这是有问题的代码:
SDL_Surface* get_font()
{
TTF_Font *font;
font = TTF_OpenFont("lib/ariali.ttf", 35);
if (!font) cout << "problem loading font" << endl;
SDL_Color white = {150,200,200};
SDL_Color black = {0,100,0};
SDL_Surface* text = TTF_RenderText_Shaded(font, "MO", white, black);
if (!text) cout << "text not loaded" << endl;
return text;
}
void displayMoney(SDL_Surface* surface)
{
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glEnable(GL_TEXTURE_2D);
GLuint TextureID = 0;
glGenTextures(1, &TextureID);
glBindTexture(GL_TEXTURE_2D, TextureID);
int Mode = GL_RGB;
if(surface->format->BytesPerPixel == 4) {
Mode = GL_RGBA;
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, Mode, 128, 64, 0, Mode, GL_UNSIGNED_BYTE, surface->pixels);
glPushMatrix();
glTranslated(100,100,0);
glScalef(100,100,0);
glBegin(GL_QUADS);
glTexCoord2f(0, 1); glVertex2f(-0.5f, -0.5f);
glTexCoord2f(1, 1); glVertex2f(0.5f, -0.5f);
glTexCoord2f(1, 0); glVertex2f(0.5f, 0.5f);
glTexCoord2f(0, 0); glVertex2f(-0.5f, 0.5f);
glEnd();
glPopMatrix();
glBindTexture(GL_TEXTURE_2D, 0);
}
#include <SDL2/SDL.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using namespace std;
#include <GL/gl.h>
#include <GL/glu.h>
#include <stb_image/stb_image.h>
#include <SDL2_ttf/SDL_ttf.h>
#include "init.h"
int main(int argc, char **argv) {
SDL_Window* window = init();
if (window == nullptr) {
cout << "Error window init" << endl;
}
if (TTF_Init() < 0) {
cout << "Error TTF init" << endl;
}
SDL_Surface* text = get_font();
while (loop) {
glClear(GL_COLOR_BUFFER_BIT);
displayMoney(text);
...
SDL_GL_SwapWindow(window);
没有任何错误消息。此外,我没有使用我的表面,而是使用 stbi_load 函数用图像测试了我的代码,它运行得非常好。因此,问题似乎与 SDL 部分有关。
EDIT :我最近发现我从文本中得到的表面具有以下属性:Rmask=Gmask=Bmask=Amask = 0。这显然是个问题但我不知道如何解决它...
如 https://www.libsdl.org/projects/SDL_ttf/docs/SDL_ttf.html#SEC42 的 SDL_ttf 文档所述,
阴影: 创建一个 8 位调色板表面并使用给定的字体和颜色以高质量呈现给定的文本。 0像素值是背景,而其他像素的前景色与背景色有不同程度的变化。
所以你得到的表面是用 8 位调色板索引的,而不是 RGBA(也由表面格式中缺少的颜色掩码表示,正如你所指出的)。具有 alpha 通道的 RGBA 表面由例如产生TTF_RenderText_Blended
,或者使用不同的贴图格式,或者进行格式转换。您需要将曲面 width/height 传递给 glTexImage2D
而不是 128/64 常量,因为曲面大小可能会有所不同。
您在问题代码中也有几个资源泄漏:在每次绘制时创建新纹理并且从不删除它(如果文本没有更改,这也是不必要的),并且从不使用 TTF_CloseFont
关闭字体。
我正在尝试使用 SDL2 TTF 和 OpenGL 显示文本。 window 中出现奇怪的纹理,它的大小和位置都正确,但您看不到任何字母。
我试过使用 SDL_CreateRGBSurface() 认为它可能是恢复像素的更干净的方法,但它也没有用。我的表面从不为 NULL,并且总是通过验证测试。
我在 while() 循环之前使用 get_front() 函数,并在其中使用 displayMoney() 函数,紧接着使用 glClear(GL_COLOR_BUFFER_BIT).
SDL、TTF 和 OpenGL 已正确初始化,我已创建 OpenGL 上下文。这是有问题的代码:
SDL_Surface* get_font()
{
TTF_Font *font;
font = TTF_OpenFont("lib/ariali.ttf", 35);
if (!font) cout << "problem loading font" << endl;
SDL_Color white = {150,200,200};
SDL_Color black = {0,100,0};
SDL_Surface* text = TTF_RenderText_Shaded(font, "MO", white, black);
if (!text) cout << "text not loaded" << endl;
return text;
}
void displayMoney(SDL_Surface* surface)
{
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glEnable(GL_TEXTURE_2D);
GLuint TextureID = 0;
glGenTextures(1, &TextureID);
glBindTexture(GL_TEXTURE_2D, TextureID);
int Mode = GL_RGB;
if(surface->format->BytesPerPixel == 4) {
Mode = GL_RGBA;
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, Mode, 128, 64, 0, Mode, GL_UNSIGNED_BYTE, surface->pixels);
glPushMatrix();
glTranslated(100,100,0);
glScalef(100,100,0);
glBegin(GL_QUADS);
glTexCoord2f(0, 1); glVertex2f(-0.5f, -0.5f);
glTexCoord2f(1, 1); glVertex2f(0.5f, -0.5f);
glTexCoord2f(1, 0); glVertex2f(0.5f, 0.5f);
glTexCoord2f(0, 0); glVertex2f(-0.5f, 0.5f);
glEnd();
glPopMatrix();
glBindTexture(GL_TEXTURE_2D, 0);
}
#include <SDL2/SDL.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using namespace std;
#include <GL/gl.h>
#include <GL/glu.h>
#include <stb_image/stb_image.h>
#include <SDL2_ttf/SDL_ttf.h>
#include "init.h"
int main(int argc, char **argv) {
SDL_Window* window = init();
if (window == nullptr) {
cout << "Error window init" << endl;
}
if (TTF_Init() < 0) {
cout << "Error TTF init" << endl;
}
SDL_Surface* text = get_font();
while (loop) {
glClear(GL_COLOR_BUFFER_BIT);
displayMoney(text);
...
SDL_GL_SwapWindow(window);
没有任何错误消息。此外,我没有使用我的表面,而是使用 stbi_load 函数用图像测试了我的代码,它运行得非常好。因此,问题似乎与 SDL 部分有关。
EDIT :我最近发现我从文本中得到的表面具有以下属性:Rmask=Gmask=Bmask=Amask = 0。这显然是个问题但我不知道如何解决它...
如 https://www.libsdl.org/projects/SDL_ttf/docs/SDL_ttf.html#SEC42 的 SDL_ttf 文档所述,
阴影: 创建一个 8 位调色板表面并使用给定的字体和颜色以高质量呈现给定的文本。 0像素值是背景,而其他像素的前景色与背景色有不同程度的变化。
所以你得到的表面是用 8 位调色板索引的,而不是 RGBA(也由表面格式中缺少的颜色掩码表示,正如你所指出的)。具有 alpha 通道的 RGBA 表面由例如产生TTF_RenderText_Blended
,或者使用不同的贴图格式,或者进行格式转换。您需要将曲面 width/height 传递给 glTexImage2D
而不是 128/64 常量,因为曲面大小可能会有所不同。
您在问题代码中也有几个资源泄漏:在每次绘制时创建新纹理并且从不删除它(如果文本没有更改,这也是不必要的),并且从不使用 TTF_CloseFont
关闭字体。