Problem z wydajnością w wyświetlaniu czcionki (opengl/SDL_ttf)

0

Hej
Oto kod generujacy i wyswietlajacy czcionke:

int Laduj::Nextpoweroftwo(int x){
double logbase2 = log(x) / log(2);
	return (pow(2,ceil(logbase2)));
}

void Laduj::LoadFont(std::string font_name, int font_size, std::string text, int pos_x, int pos_y,
                            Uint8 r, Uint8 g, Uint8 b){
int w, h;
TTF_Init();
    SDL_Surface *message = NULL;
    SDL_Surface *background = NULL;
TTF_Font *font = NULL;
GLuint texture2;
    SDL_Color fontcolor = {r, g, b};

font = TTF_OpenFont(font_name.c_str(), font_size);
message = TTF_RenderText_Blended(font, text.c_str(), fontcolor);
w = Nextpoweroftwo(message->w);
h = Nextpoweroftwo(message->h);

background = SDL_CreateRGBSurface(0, w, h, 32,
			0, 0, 0, 0);
SDL_BlitSurface(message, 0, background, 0);

glGenTextures(1, &texture2);
	glBindTexture(GL_TEXTURE_2D, texture2);
	glTexImage2D(GL_TEXTURE_2D, 0, 4, w, h, 0, GL_RGBA,
			GL_UNSIGNED_BYTE, background->pixels );

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	glBindTexture(GL_TEXTURE_2D, texture2);

	glBegin(GL_QUADS);
		glTexCoord2f(0.0f, 1.0f);  glVertex2f(pos_x    , pos_y+h);
		glTexCoord2f(1.0f, 1.0f);  glVertex2f(pos_x + w, pos_y+h);
		glTexCoord2f(1.0f, 0.0f);  glVertex2f(pos_x + w, pos_y);
		glTexCoord2f(0.0f, 0.0f);  glVertex2f(pos_x    , pos_y);
	glEnd();

	glFinish();

SDL_FreeSurface(message);
SDL_FreeSurface(background);
TTF_CloseFont(font);
TTF_Quit();
}

Problem polega na tym ze podczas pracy programu gdy wyswietlana jest czcionka w ten sposob, Pamiec zadeklarowana ciagle wzrasta a praca procesora siega 90% ;p. Jak poprawić ten kod aby byl wydajniejszy?;p Bede ogromnie wdzieczny za pomoc

0

Dziwisz się że tyle zżera? O ile dobrze rozumiem to przy każdym wyświetlaniu ładuje od nowa.

Skoro już masz teksturę, to zostaw ją gdzieś załadowaną i przy rysowaniu ją rysuj, a nie od nowa ładować

0

To co mam stworzyc tablice z teksturami? To niezbyt swobodny sposob uzycia, Tak zrobilem z grafika, to jeszcze ujdzie ale w przypadku tekstu to juz inna sprawa. Tekst nie zawsze bede znal Od razu wiec zrobienie teksturek z gotowymi tekstami to zle rozwiazanie. Chcialem moc swobodnie wyswietlac jakikolwiek tekst bez ograniczen no i na razie udalo mi sie wymyslic tylko powyzszy kod ;/

1

Więc zrób nową klasę, która będzie przychowywała każdy znak z osobna (tekstura + wymiary) i jedną klasę, która będzie rysowała tekst korzystając z tablicy znaków. Przykładowe klasy:

class GLChar{
  GLuint texture;
  GLuint list;
  public:
    GLChar(short znak);
    int width;
    int height;
    void draw();
}

class GLText{
  GLChar *chars[256];
  public:
    GLText();
    drawText(char* text, double x, double y);
}

W konstruktorze GLText wypełniasz całą tablicę chars nowymi obiektami GLChar w konstruktorach podając kolejne liczby.

Konstruktor GLChar tworzy i zapisuje do tekstury teksturę pojedynczego znaku.

Metoda drawText będzie rysowała tekst w danym miejscu. Będzie po prostu rysowała po kolei znaki i przechodziła w prawo o szerokość znaku.

0

Dzieki za pomysl, zrobilem to tak:

int Laduj::Nextpoweroftwo(int x){
double logbase2 = log(x) / log(2);
	return (pow(2,ceil(logbase2)));
}

void Laduj::LoadFont(std::string Font_name, int Font_size, Uint8 r, Uint8 g, Uint8 b){
int w, h;
int j = 0;
    SDL_Surface *message = NULL;
    SDL_Surface *background = NULL;
TTF_Font *font;
GLuint texture2[91];
char znaki[] = "abcdefghijklmnopqrstuwxyzvABCDEFGHIJKLMNOPQRSTWUXYZV1234567890-=!@#$%^&*()_+{}|:<>?[]\;',./";
    SDL_Color fontcolor = {r, g, b};
    font = TTF_OpenFont(Font_name.c_str(), Font_size);
for(int i = 0; i < 90; i++){ //90 to liczba znakow
std::string znak(1, znaki[i]);
message = TTF_RenderText_Blended(font, znak.c_str(), fontcolor);
w = message->w;
h = message->h;

background = SDL_CreateRGBSurface(0, w, h, 32,
			0, 0, 0, 0);
SDL_BlitSurface(message, 0, background, 0);

glGenTextures(1, &texture2[j]);
	glBindTexture(GL_TEXTURE_2D, texture2[j]);
	glTexImage2D(GL_TEXTURE_2D, 0, 4, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, background->pixels );
	j++;
}
SDL_FreeSurface(message);
SDL_FreeSurface(background);
}

Powyzsza funkcje odpalam tylko raz na starcie programu aby zaladowac tekstury znakow ktorych bede uzywal w programie.

void Laduj::RenderFont(char tekst[255], int pos_x, int pos_y){
	for(int j = 0; j < 20; j++){
for(int i =0; i < 90; i++){
if(tekst[j] == znaki[i]){
glBindTexture(GL_TEXTURE_2D, texture2[i]);
int w = 10;
int h = 16;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glBegin(GL_QUADS);
		glTexCoord2f(0.0f, 1.0f);  glVertex2f(pos_x    , pos_y+h);
		glTexCoord2f(1.0f, 1.0f);  glVertex2f(pos_x + w, pos_y+h);
		glTexCoord2f(1.0f, 0.0f);  glVertex2f(pos_x + w, pos_y);
		glTexCoord2f(0.0f, 0.0f);  glVertex2f(pos_x    , pos_y);
		pos_x+=w;
	glEnd();
	glFinish();
break;
}
	}
	}
}

Powyzsza funkcje wyswietlam nonstop aby wyswietlac czcionke ale zamiast liter wyswietlaja sie zamalowane kwadraty ;/
I niestety na razie nie udalo mi sie doprowadzic tego do dzialania ;/. Sory ze tak ciagle sie dopytuje ale juz mam dosc tych wszystkich problemow z czcionka... Chcialem juz zaczac na powaznie gre robic a tu kilka dni nad czcionkami pracuje :P

1

Kod z mojej starej gierki:

int sizeofChar(const char text[]){
	int i=0;
	for(i=0; text[i]; i++){}
	return i;
}

short charNumber(const char *letter){
	//printf("%s - %d\n", letter, short(letter[0]));
	if(sizeofChar(letter)==1) return short(letter[0]);
	else{
		short number=short(letter[0]);
		for(int i=1; i<sizeofChar(letter); i++){
			number=number<<8;
			number+=short(letter[i]);
		}
		return number;
	}
	return 0;
}

struct charTexture{ //public:
	GLuint id;
	bool rendered;
	unsigned short w, h;
	void make(const char* letter){
		SDL_Surface *charTMP1;
		SDL_Surface *charTMP;
		SDL_Surface *charTexture;
		Uint32 rmask, gmask, bmask, amask;
		#if SDL_BYTEORDER == SDL_BIG_ENDIAN
		rmask = 0xff000000;gmask = 0x00ff0000;
		bmask = 0x0000ff00;amask = 0x000000ff;
		#else
		rmask = 0x000000ff;gmask = 0x0000ff00;
		bmask = 0x00ff0000;amask = 0xff000000;
		#endif

		SDL_Color color;
		color.r=255;
		color.g=255;
		color.b=255;
		charTMP=TTF_RenderUTF8_Blended(font,letter,color);
		SDL_Rect rect;
			rect.x=0;
			rect.y=0;
			rect.w=charTMP->w;
			rect.h=charTMP->h;
		
		charTexture=SDL_CreateRGBSurface(SDL_SWSURFACE|SDL_SRCALPHA, 64,64, 32,
					rmask, gmask, bmask, amask);
		if(charTexture==NULL) printf("ERROR");
		SDL_BlitSurface(charTMP, NULL, charTexture, &rect);
		w=charTMP->w;
		h=charTMP->h;
		
		glGenTextures(1, &id);
		glBindTexture(GL_TEXTURE_2D, id);
		gluBuild2DMipmaps(GL_TEXTURE_2D, 4,
			charTMP->w, charTMP->h, GL_RGBA,GL_UNSIGNED_BYTE, charTMP->pixels);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_LINEAR);
		SDL_FreeSurface(charTMP);
		SDL_FreeSurface(charTexture);
		rendered=true;
		printf("char %s rendered at: %d\n", letter, id);
	}
	int draw(int x, int y){
 		glBindTexture(GL_TEXTURE_2D, id);
		glBegin(GL_QUADS);
			glTexCoord2f(0,0); glVertex2f(x, y);
			glTexCoord2f(0,1); glVertex2f(x, y+h);
			glTexCoord2f(1,1); glVertex2f(x+w, y+h);
			glTexCoord2f(1,0); glVertex2f(x+w, y);
		glEnd();
		return w;
	}
	bool Crendered(const char letter[]){
		if(!rendered) 
			return false;
		return true;
	}
};

map<const short, charTexture> charMap;

int drawLetter(const char letter[], int x, int y){
	short number=charNumber(letter);
	if(!charMap[number].Crendered(letter)){
		charMap[number].make(letter);
	}
	return charMap[number].draw(x, y);
}

void drawText(const char text[], int x, int y, float r, float g, float b){
	int size=sizeofChar(text);
	char bufor[5];
	glColor3f(r,g,b);
	for(int i=0; i<size; i++){
		sprintf(bufor, "%c", text[i]);
		x+=drawLetter(bufor, x, y);
	}
}

i jeszcze gdzieś w Inicie:

font = TTF_OpenFont("fonts/TribalTwo.ttf",26);

Nie pamiętam typu, bo dawno w tym nie siedziałem, ale dasz se radę.

Jak to konkretnie działało, nie pamiętam. Ale na pewno działa. Wystarczy uruchomić funkcję drawText i textury znaków same się zrobią.
Pamiętam że próbowałem polskich znaków, ale nie pamiętam czy działały.

0

wielkie dzieki za twoja pomoc, na pewno sie przyda ^^

1 użytkowników online, w tym zalogowanych: 0, gości: 1