J'essaye d'utiliser OpenGL et SDL, en utilisant SDL_ttf pour rendre le texte à une texture, mais le code rend le garbage.SDL_TTF rendre les ordures à la texture
Mon "rendu au code de texture":
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;
}
Le code de calcul des dimensions correctes pour le rembourrage:
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;
}
et enfin, le code qui copie les octets à une texture de la dimensions correctes:
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;
}
Le résultat de ce code est le suivant: [! [Garbled Texture] [1 ]] [1]
J'ai vérifié et vérifié l'erreur que SDL_TTF est correctement initialisé ailleurs dans la base de code, et que la police est également en cours de chargement. J'ai testé avec trois polices différentes ttf, avec les mêmes résultats.
Aussi, si j'utilise toute autre fonction TTF_rendering (ombrée, etc solide), est rendu un quad solide, et la variable « couleurs » dans la fonction textToTexture se termine également comme 1.
supplémentaires:
Comme je l'aidéjà dit, j'ai testé avec trois polices TTF: MavenPro-Regular,
HelveticaNeueLTStd-Th
et un autre je trouve sur internet. J'essayais de rendre la chaîne "Select Scenario".
Les dimensions de l'image pré-rembourrée sont de 138x25 pixels.
Les dimensions de l'image après remplissage sont de 256 x 32 pixels.
Mise à jour 1:
Après avoir résolu la question BPP la nouvelle texture est la suivante:
Cette image change à chaque fois que je lance le programme.
Mise à jour 2: Après avoir corrigé les erreurs tachetées supplémentaires avec rembourrage de l'image et la définition des données de pixels à la texture elle-même, quand je l'utilise TTF_RenderText_Blended
tout ce que je reçois est un quad noir, et quand je l'utilise TTF_RenderText_Shaded
je reçois:
Mise à jour 3:
J'utilisé SDL_SaveBMP
immedietly avant d'appeler le code GL et après avoir appelé SDL_RenderText_Blended
, le résultat était une image complètement blanche, (étant donné la couleur de texte).
Lorsque je fais la même chose en utilisant TTF_RenderText_Solid
, l'image enregistrée est comme elle devrait l'être, mais elle est rendue par opengl comme les images que vous voyez ci-dessus.
SDL_TTF initialisé correctement, les polices se chargent sans erreur, et le rendu du texte ne renvoie aucune erreur, donc je ne peux pas penser à quoi faire ensuite.
Mise à jour 4:
J'ai depuis refondus tout le code TTF en une seule fonction et supprimé le code de remplissage (comme opengl moderne ne semble pas se soucier à ce sujet). Cependant, malgré tous les paramètres du projet et le code étant identique à un projet de test connu pour fonctionner sur le même matériel, le problème persiste.
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;
}
J'ai une solution qui sauve l'image à bmp, et puis recharge crée une texture, mais seulement quand j'utiliser TTF_RenderText_Shaded
. Si j'utilise TTF_RenderText_Blended
, j'obtiens une image couleur unique qui correspond à la couleur du texte.
'src + (srcW * i)' - vous devez multiplier par BPP trop (même pour dst). De plus, vous ne libérez jamais votre tampon de pixels, mais cela n'a aucun rapport avec votre problème actuel. – keltar
Ok, j'ai corrigé cette erreur (joliment repérée btw), mais cela n'a pas amélioré la texture résultante, donc est-il possible qu'il y ait un autre problème? –
Techniquement, vous devez aligner les lignes, mais avec bpp = 4 elles le sont déjà. Mettez à jour la question avec les modifications que vous avez apportées et les résultats que vous obtenez. Il peut également être utile de connaître les valeurs réelles de largeur et de hauteur de la surface d'origine, quelle police a été utilisée et quel texte est rendu. – keltar