- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试使用 OpenGL 和 SDL,使用 SDL_ttf 将文本渲染到纹理,但代码渲染垃圾。
我的“渲染到纹理代码”:
GLuint textToTexture(std::string & text, TTF_Font* font, glm::vec4 textColour, glm::vec4 bgColour)
{
if (!TTF_WasInit())
{
if (TTF_Init() == -1)
exit(6);
}
SDL_Color colour = { (Uint8)(textColour.r*255), (Uint8)(textColour.g*255), (Uint8)(textColour.b*255), (Uint8)(textColour.a*255) };
SDL_Color bg = { (Uint8)(bgColour.r*255), (Uint8)(bgColour.g*255), (Uint8)(bgColour.b*255), (Uint8)(bgColour.a*255) };
SDL_Surface *stringImage = NULL;
stringImage = TTF_RenderText_Blended(font, text.c_str(), colour);
if (stringImage == NULL)
{
exit(5);
}
GLuint trueH = powerofTwo(stringImage->h);
GLuint trueW = powerofTwo(stringImage->w);
unsigned char* pixels = NULL;
GLuint w = stringImage->w;
GLuint h = stringImage->h;
GLuint colours = stringImage->format->BytesPerPixel;
pixels = padTexture((unsigned char*)stringImage->pixels, w, h, pixels, trueW, trueH, colours);
GLuint format, internalFormat;
if (colours == 4) {
if (stringImage->format->Rmask == 0x000000ff)
format = GL_RGBA;
else
format = GL_BGRA;
}
else {
// no alpha
if (stringImage->format->Rmask == 0x000000ff)
format = GL_RGB;
else
format = GL_BGR;
}
internalFormat = (colours == 4) ? GL_RGBA : GL_RGB;
GLuint texId = 0;
//GLuint texture;
glGenTextures(1, &texId);
glBindTexture(GL_TEXTURE_2D, texId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, trueW, trueH, 0,format, GL_UNSIGNED_BYTE, pixels);
// SDL surface was used to generate the texture but is no longer
// required. Release it to free memory
SDL_FreeSurface(stringImage);
free(pixels)
return texId;
}
计算正确的填充尺寸的代码:
int powerofTwo(int num)
{
if (num != 0)
{
num--;
num |= num >> 1; // Divide by 2^k for consecutive doublings of k up to 32,
num |= num >> 2; // and then or the results.
num |= num >> 4;
num |= num >> 8;
num |= num >> 16;
num++;
}
return num;
}
最后,将字节复制到正确尺寸的纹理的代码:
unsigned char* padTexture(unsigned char * src, int srcW, int srcH, unsigned char * dest, int width, int height, int bpp)
{
dest = (unsigned char*)calloc(1, width*height*bpp);
for (int i = 0; i < srcH; i++)
{
memcpy(dest + (width*i*bpp),src + (srcW*i*bpp), srcW*bpp);
}
return dest;
}
这段代码的结果如下:[![乱码纹理][1]][1]
我已确认并错误检查了 SDL_TTF 已在代码库的其他地方正确初始化,并且字体也正在加载。我用三种不同的 ttf 字体进行了测试,结果相同。
此外,如果我使用任何其他 TTF_rendering 函数(Shaded、Solid 等),则会渲染一个实心四边形,textToTexture 函数中的“colours”变量也最终为 1。
附加:
如前所述,我使用三种 ttf 字体进行了测试:MavenPro-常规,
HelveticaNeueLTStd-Th
还有一个是我在网上找到的。我试图呈现字符串“Select Scenario”。
预填充的图像尺寸为 138x25 像素。
后填充图像尺寸为 256x32 像素。
更新 1:
修复bpp问题后新贴图如下:
每次运行该程序时,此图像都会发生变化。
更新 2:在通过填充图像修复了额外的发现错误并将像素数据设置为纹理本身之后,当我使用 TTF_RenderText_Blended
时,我得到的只是一个黑色四边形,而当我使用 TTF_RenderText_Shaded
我得到:
更新 3:
我在调用 GL 代码之前和调用 SDL_RenderText_Blended
之后立即使用了 SDL_SaveBMP
,结果是一个完全白色的图像(给定的文本颜色)。
当我使用 TTF_RenderText_Solid
执行相同操作时,保存的图像应该是它应该的样子,但它是由 opengl 渲染的,就像您在上面看到的图像一样。
SDL_TTF 初始化正常,字体加载没有错误,文本渲染也没有返回错误,所以我想不出下一步该做什么。
更新 4:
我已经将所有 ttf 代码重构为一个函数并删除了填充代码(因为现代 opengl 似乎并不关心它)。然而,尽管所有项目设置和代码现在都与已知可在同一硬件上运行的测试项目相同,但问题仍然存在。
GLuint textToTexture(const char * text, const char * font, glm::vec4 textColour, glm::vec4 bgColour, unsigned int & texID)
{
if (!TTF_WasInit()) {
if (TTF_Init() == -1)
exit(6);
}
SDL_Color colour = { (Uint8)(textColour.r * 255), (Uint8)(textColour.g * 255), (Uint8)(textColour.b * 255),(Uint8)(textColour.a * 255) };
SDL_Color bg = { (Uint8)(bgColour.r * 255), (Uint8)(bgColour.g * 255), (Uint8)(bgColour.b * 255),255 };
TTF_Font* fontObj = TTF_OpenFont(font, 24);
if (!fontObj)
{
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
"Texture Error",
"Cannot load font to create texture.",
NULL);
return 0;
}
SDL_Surface *image = NULL;
image = TTF_RenderText_Blended(fontObj, text, colour);
if (image == NULL)
{
exit(5);
//exitFatalError("String surface not created.");
std::cout << "String surface not created." << std::endl;
}
unsigned char* pixels = NULL;
GLuint w = image->w;
GLuint h = image->h;
GLuint colours = image->format->BytesPerPixel;
GLuint externalFormat, internalFormat;
SDL_PixelFormat *format = image->format;
if (colours == 4) {
if (image->format->Rmask == 0x000000ff)
externalFormat = GL_RGBA;
else
externalFormat = GL_BGRA;
}
else {
// no alpha
if (image->format->Rmask == 0x000000ff)
externalFormat = GL_RGB;
else
externalFormat = GL_BGR;
}
internalFormat = (colours == 4) ? GL_RGBA : GL_RGB;
GLuint texId = 0;
//GLuint texture;
glGenTextures(1, &texID);
glBindTexture(GL_TEXTURE_2D, texID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, w, h, 0, externalFormat, GL_UNSIGNED_BYTE, image->pixels);
//glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, trueW, trueH, 0, externalFormat, GL_UNSIGNED_BYTE, pixels);
glGenerateMipmap(GL_TEXTURE_2D);
//// SDL surface was used to generate the texture but is no longer
//// required. Release it to free memory
SDL_FreeSurface(image);
TTF_CloseFont(fontObj);
return texID;
}
我有一个解决方法,将图像保存为 bmp,然后重新加载它并创建纹理,但仅当我使用 TTF_RenderText_Shaded
时。如果我使用 TTF_RenderText_Blended
,我会得到一个与文本颜色相对应的单色图像。
最佳答案
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, trueH, trueW, 0,format, GL_UNSIGNED_BYTE, pixels);
trueH
和trueW
顺序颠倒
memcpy(src + (srcW*i*bpp), dest + (width*i*bpp), srcW*bpp);
源和目标顺序颠倒。
dest = (unsigned char*)calloc(0, width*height*bpp);
分配了 0 个大小为 width*height*bpp
的元素,即 0 字节。应该是 1 而不是 0。
这是一个完整的例子:
#include <SDL2/SDL.h>
#include <GL/gl.h>
#include <SDL2/SDL_ttf.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static unsigned char* padTexture(unsigned char * src, int srcW, int srcH, unsigned char * dest, int width, int height, int bpp, const SDL_Palette *palette)
{
int dst_bpp = (bpp == 1) ? 4 : bpp;
dest = (unsigned char*)calloc(1, width*height*dst_bpp);
if(bpp != 1) {
for (int i = 0; i < srcH; i++)
{
memcpy(dest + (width*i*bpp), src + (srcW*i*bpp), srcW*bpp);
}
} else {
/* indexed - read colours from palette */
for(int i = 0; i < srcH; i++) {
for(int j = 0; j < srcW; j++) {
memcpy(dest + (width*i+j)*dst_bpp,
&palette->colors[src[srcW*i+j]], sizeof(SDL_Color));
}
}
}
return dest;
}
static int powerofTwo(int num) {
if (num != 0)
{
num--;
num |= num >> 1; // Divide by 2^k for consecutive doublings of k up to 32,
num |= num >> 2; // and then or the results.
num |= num >> 4;
num |= num >> 8;
num |= num >> 16;
num++;
}
return num;
}
static GLuint textToTexture(const char *text, TTF_Font* font) {
if (!TTF_WasInit()) {
if (TTF_Init() == -1)
exit(6);
}
SDL_Color colour = { 255, 255, 255, 255 };
SDL_Color bg = { 0, 0, 0, 255 };
SDL_Surface *stringImage = NULL;
// stringImage = TTF_RenderText_Blended(font, text, colour);
stringImage = TTF_RenderText_Shaded(font, text, colour, bg);
if (stringImage == NULL) {
exit(5);
}
GLuint trueH = powerofTwo(stringImage->h);
GLuint trueW = powerofTwo(stringImage->w);
unsigned char* pixels = NULL;
GLuint w = stringImage->w;
GLuint h = stringImage->h;
GLuint colours = stringImage->format->BytesPerPixel;
pixels = padTexture((unsigned char*)stringImage->pixels, w, h, pixels, trueW, trueH,
colours, stringImage->format->palette);
GLuint format, internalFormat;
/* If indexed, want resulting image to be 32bit */
if(colours == 1) {
colours = 4;
}
if (colours == 4) {
if (stringImage->format->Rmask == 0x000000ff)
format = GL_RGBA;
else
format = GL_BGRA;
}
else {
// no alpha
if (stringImage->format->Rmask == 0x000000ff)
format = GL_RGB;
else
format = GL_BGR;
}
internalFormat = (colours == 4) ? GL_RGBA : GL_RGB;
GLuint texId = 0;
//GLuint texture;
glGenTextures(1, &texId);
glBindTexture(GL_TEXTURE_2D, texId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, trueW, trueH, 0,format, GL_UNSIGNED_BYTE, pixels);
// SDL surface was used to generate the texture but is no longer
// required. Release it to free memory
SDL_FreeSurface(stringImage);
free(pixels);
return texId;
}
int main(int argc, char* argv[])
{
SDL_Init(SDL_INIT_VIDEO);
TTF_Init();
SDL_Window *window = SDL_CreateWindow("SDL2 Example", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 600, 400, SDL_WINDOW_OPENGL);
SDL_GLContext gl_ctx = SDL_GL_CreateContext(window);
TTF_Font *font = TTF_OpenFont(".fonts/tahoma.ttf", 16);
if(font) {
printf("font loaded\n");
textToTexture("Select Scenario", font);
TTF_CloseFont(font);
}
int quit = 0;
while(!quit) {
SDL_Event ev;
while(SDL_PollEvent(&ev)) {
if(ev.type == SDL_QUIT || ev.type == SDL_KEYUP) {
quit = 1;
}
}
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D);
glColor3f(1.0f, 1.0f, 1.0f);
glBegin(GL_QUADS);
glTexCoord2f(0, 1);
glVertex2f(-0.5, -0.5);
glTexCoord2f(0, 0);
glVertex2f(-0.5, 0.5);
glTexCoord2f(1, 0);
glVertex2f(0.5, 0.5);
glTexCoord2f(1, 1);
glVertex2f(0.5, -0.5);
glEnd();
glFlush();
SDL_GL_SwapWindow(window);
}
SDL_GL_DeleteContext(gl_ctx);
SDL_DestroyWindow(window);
TTF_Quit();
SDL_Quit();
return 0;
}
关于c++ - SDL_TTF 将垃圾渲染到纹理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40609280/
我在通过 SDL_ttf 在 OpenGL 中显示文本时遇到问题。我编写了 LoadFont() 函数,它加载字体并制作 OpenGL 纹理。 int LoadFont( char *name, GL
如何在代码块中设置 sdl_ttf?我已经阅读了lazyfoo关于向sdl添加新库的教程,并已成功向其中添加了sdl_image。然而,ttf 拒绝工作。我已经下载了文件,将头文件放入 sdl 文件夹
我发布了我认为相关的部分代码。我正在尝试通过 SDL_TTF 为我的菜单绘制一些文本。每次单击按钮时,我都会从服务器获取一串字符。类似于“I1P1I2P1I3P1I4P1I5P1I6P1I7P1I8P
我是编程初学者,我在使用 SDL_TTF 调用的函数时遇到了麻烦: SDL_Surface *TTF_RenderText_Solid(TTF_Font *字体,const char *text,SD
我正在尝试使用 OpenGL 和 SDL,使用 SDL_ttf 将文本渲染到纹理,但代码渲染垃圾。 我的“渲染到纹理代码”: GLuint textToTexture(std::string & te
我遇到了 SDL_ttf 的问题,无论我用 TTF_RenderText_Solid 函数做什么,它都拒绝呈现任何文本。我的源代码在这个问题中有点重(大约 150 行之类)所以我将它们的链接放在 Pa
我正在使用 SDL_ttf,但在 mingw32 中,我下载所有内容并尝试以下程序 #include #include "SDL_ttf.h" #include using namespace s
我使用 SDL 进行开发已有一段时间了,但我认为我需要另一个挑战。所以我决定使用 SDL_TTF 在屏幕上绘制一些文本。 我尝试在 0,0 处渲染文本,但它有点低于屏幕边框。所以这意味着它没有在 0,
我正在尝试用 C++ 制作一个 openGL 游戏,并且我正在尝试实现一个文本系统,为此,我正在尝试使用 SDL_ttf。 我已经在另一个项目中使用了 SDL_ttf,但使用了另一个 api,所以我编
我正在使用 codeblocks 并且我已经安装了 librares 并且那里没有错误...当我构建项目时,编译器说它没有错误,当我运行它时,它只是弹出一个窗口,里面只有黑色,它应该会出现“Hola
所以,我正在开发一个命令提示符游戏,现在我从小处着手。我已经掌握了打印速度较慢的文本系统的基础知识,但我遇到了一个我不确定如何解决的问题。 基本上;文本会拉伸(stretch)以适合预定义的框: 预定
有没有办法在 SDL_TFF 中使用默认系统字体,而无需编写特定于平台的代码?目前我只使用 GNU FreeFont's 之一, 但我希望能够使用默认的系统字体。 最佳答案 那么,什么是“默认系统字体
当一串文本的长度超过 300 时,我希望它换行并继续。我读到这就是您的做法,但它不起作用 - 它只是延长了文本。 如何实现? const char* message = "example text t
前几天我问了一个问题,关于使用 SDL 渲染 TTF 字体,并被指向 SDL_TTFL 我已经尝试使用 SDL_TTF 库,但我得到的只是屏幕上的垃圾 我已经包含了我的着色器,这对于这个程序来说非常简
在我的游戏中,当“时间”处于事件状态时,它总是会在 5 个“小时”后崩溃。当它运行时,它工作正常,直到它开始显示不正确的时间(原因不明)并且它会在 5 个“小时”后由于段错误而崩溃。这很奇怪,因为以前
在病毒迫使我重置为出厂状态后,我一直试图在我的计算机上设置 SDL。让 SDL 在我的 IDE CodeBlocks 上运行很容易,但设置扩展库就没那么容易了。 CodeBlocks 识别库的存在,但
我是 OpenGL 的初学者,我创建了一个使用 SDL_TTF 在 OpenGL 中写入文本的函数。这是我的函数的代码: #define WINDOW_WIDTH 832 #define WINDOW
我一直在研究 SDL 和 OpenGL(在 C++ 中),并决定在我的游戏中添加一些文本。 我已经学习了一些教程,但我总是得到同样的错误:“找不到 .ttf”我确定之前有人问过它,但是你应该把字体放在
这是一个例子: 下面是相应的代码: TTF_Font *Sans = TTF_OpenFont("resources/fonts/lato/Lato-Semibold.ttf", 36); i
我有C语言代码,可以使用Linux中的SDL_ttf库在屏幕上显示文本。 TTF_Font *font; font = TTF_OpenFont("FreeSans.ttf", 20);
我是一名优秀的程序员,十分优秀!