我正在嘗試使用OpenGL和SDL,使用SDL_ttf來渲染文本到紋理,但代碼呈現垃圾。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;
}
該代碼的結果如下:[![Garbled Texture] [1 ]] [1]
我已確認並檢查錯誤,確定SDL_TTF在代碼庫中的其他位置正確初始化,並且字體也正在加載。 我用三種不同的ttf字體進行了測試,結果相同。
另外,如果我使用任何其他TTF_rendering功能(陰影,固體等),固體四被渲染,而在textToTexture功能的「顏色」變量也結束爲1
附加:
MavenPro正規,HelveticaNeueLTStd釷
和另一個我發現了互聯網:
正如我前面提到的,我有三個ttf字體進行測試。 我試圖呈現字符串「Select Scenario」。
預填充的圖像尺寸是138x25像素。
後置填充的圖像尺寸是256x32像素。
更新1:
固定BPP問題後,新的紋理如下:
此影像學改變,每次我運行程序。
更新2: 與填充的圖像,並且像素數據設置爲本身的質感,當我使用TTF_RenderText_Blended
我得到的是一個黑色的方形,並固定更多的斑點錯誤後,當我使用TTF_RenderText_Shaded
我得到:
更新3:
我immedietly調用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
,我會得到一個與文本顏色相對應的單色圖像。
'SRC +(srcW * I)' - 你需要通過BPP乘過(這同樣適用於DST)。你也從來沒有釋放你的像素緩衝區,但它與你目前的問題無關。 – keltar
好吧,我修正了這個錯誤(很好地發現btw),但它沒有改善產生的紋理,所以有可能還有一些其他問題? –
從技術上講,你需要對齊行,但它們已經是bpp = 4。更新您所做的更改和結果的問題。瞭解原始表面的寬度和高度的實際值,使用哪種字體以及正在呈現哪些文本也可能會有幫助。 – keltar