Farbendreher bei sdl_ttf fonts mit opengl



  • Hallo

    Ich habe ine eigenartiges Problem: Immer wenn ich mit meiner Klasse text einen Schritftextur erstelle und diese dann rendere, werden die Farben red und blue vertauscht. Der Wert für blue wird zu anscheinend zu red geschrieben. Wenn ich den Text nun ändere mittels der Funktion set_text wird die init-Funktiuon erneut aufgerufen und diesmal stimmen die Farbwerte aber überein. Da bei meinen Spiel so der Punktestand dargestellt wird, wechselt bei jeder Punktänderung die Farbe. Hier mal Code:

    chrische::sdl::opengl::text::text()
    {
    
    }
    
    chrische::sdl::opengl::text::~text()
    {
    	glDeleteTextures(1, &texture);
    	TTF_CloseFont(p_font);
    }
    
    int chrische::sdl::opengl::text::next_power_of_two(int x)
    {
    	double logbase2 = log(static_cast<double>(x)) / log(2.0f);
    	return round(pow(2,ceil(logbase2)));
    }
    
    void chrische::sdl::opengl::text::init(const std::string& text_to_write, const std::string& file_name, const int r, const int g, const int b, int pos_x, int pos_y, const int text_height)
    {
    	file_name_ = file_name;
    	text_height_ = text_height;
    	text_to_write_ = text_to_write;
    
    	// red und blue wird vertauscht
    	color_.r = b;
    	color_.g = g;
    	color_.b = r;
    
    	p_font = TTF_OpenFont(file_name_.c_str(),text_height_);
    	if(!p_font)
    	{
    		get_logfile()->write("Fehler beim initialisieren vom Font ");
    		get_logfile()->write(TTF_GetError());
    		get_logfile()->write("<br>");
    		exit(1);
    	} // if(!p_font)
    
    	assert(pos_x != VCENTER);
    	assert(pos_y != HCENTER);
    	if(pos_x == HCENTER)
    		pos_x = get_horz_center_pos();
    	if(pos_y == VCENTER)
    		pos_y = get_vert_center_pos();
    
    	if(pos_x > 19999)
    		pos_x = get_horz_center_pos_on_line(pos_x - 20000);
    
    	position_.x = pos_x;
    	position_.y = pos_y;
    
    	SDL_Surface* temp_surface = TTF_RenderText_Blended(p_font, text_to_write.c_str(), color_);
    	w = next_power_of_two(temp_surface->w);
    	h = next_power_of_two(temp_surface->h);
    
    	SDL_Surface* temp_surface_two = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32,
    	#if SDL_BYTEORDER == SDL_BIG_ENDIAN
    		0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
    	#else
    		0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
    	#endif
    
    	SDL_BlitSurface(temp_surface, 0, temp_surface_two, 0);
    
    	glGenTextures(1, &texture);
    	glBindTexture(GL_TEXTURE_2D, texture);
    	glTexImage2D(GL_TEXTURE_2D, 0, 4, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, temp_surface_two->pixels );
    	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    
    	position_.w = temp_surface->w;
    	position_.h = temp_surface->h;
    
    	SDL_FreeSurface(temp_surface);
    	SDL_FreeSurface(temp_surface_two);
    }
    
    int chrische::sdl::opengl::text::get_horz_center_pos()
    {
    	return ((get_framework()->get_screen_width()-get_length_in_pixel()) /2);
    }
    
    int chrische::sdl::opengl::text::get_vert_center_pos()
    {
    	return ((get_framework()->get_screen_height()-get_height_in_pixel())/2);
    }
    
    void chrische::sdl::opengl::text::set_text_height(const int new_height)
    {
    	init(text_to_write_, file_name_, color_.r, color_.g, color_.b, position_.x, position_.y, new_height);
    }
    
    void chrische::sdl::opengl::text::set_color(const int r, const int g, const int b)
    {
    	init(text_to_write_, file_name_, r, g, b, position_.x, position_.y, text_height_);
    }
    
    void chrische::sdl::opengl::text::set_text(const std::string& text_to_write)
    {
    	init(text_to_write, file_name_, color_.r, color_.g, color_.b, position_.x, position_.y, text_height_);
    }
    
    void chrische::sdl::opengl::text::set_pos(int pos_x, int pos_y)
    {
    	assert(pos_x != VCENTER);
    	assert(pos_y != HCENTER);
    	if(pos_x == HCENTER)
    		pos_x = get_horz_center_pos();
    	if(pos_y == VCENTER)
    		pos_y = get_vert_center_pos();
    
    	if(pos_x > 19999)
    		pos_x = get_horz_center_pos_on_line(pos_x - 20000);
    
    	position_.x = pos_x;
    	position_.y = pos_y;
    }
    
    int chrische::sdl::opengl::text::get_length_in_pixel() 
    {
    	int width;
    	int height;
    	TTF_SizeText(p_font, text_to_write_.c_str(), &width, &height);
    	return width;
    }
    
    int chrische::sdl::opengl::text::get_height_in_pixel()
    {
    	int width;
    	int height;
    	TTF_SizeText(p_font, text_to_write_.c_str(), &width, &height);
    	return height;
    }
    
    int chrische::sdl::opengl::text::HCENTEREX(const int pos_x)
    {
    	return pos_x + 20000;
    }
    
    int chrische::sdl::opengl::text::get_horz_center_pos_on_line(const int pos_x)
    {
    	int diff = get_length_in_pixel()/2;
    	return pos_x - diff;
    }
    
    void chrische::sdl::opengl::text::render()
    {
    	glEnable(GL_TEXTURE_2D);
    	glBindTexture(GL_TEXTURE_2D, texture);
    	glColor3f(1.0f, 1.0f, 1.0f);
    
    	glBegin(GL_QUADS);
    	glTexCoord2f(0.0f, 1.0f); 
    	glVertex2f(position_.x    , position_.y + h);
    	glTexCoord2f(1.0f, 1.0f); 
    	glVertex2f(position_.x + w, position_.y + h);
    	glTexCoord2f(1.0f, 0.0f); 
    	glVertex2f(position_.x + w, position_.y);
    	glTexCoord2f(0.0f, 0.0f); 
    	glVertex2f(position_.x    , position_.y);
    	glEnd();
    }
    

    Seht ihr den Fehler?

    chrische



  • Anscheinend hast du eine globale Variable color.
    Du rufst dann die setText-Methode mit den Parameter color.r, color.g, color.b auf.
    In der init-Methode vertauscht du nun die R und B Werte der globalen Variable color.

    color_.r = b;
    color_.g = g;
    color_.b = r;
    

    Wenn du die setText-Methode das nächste mal aufrufst passiert das gleiche wieder. D.h. Rot und Blau werden wieder vertauscht. Ich nehme mal an irgendetwas hieran ist nicht beabsichtigt.



  • Hallo

    Den Dreher habe ich nur damit die Farben bei einmaliger Initialisierung eben stimmen.

    chrische



  • Ich glaube dir ja dass du den Dreher absichtlich eingebaut hast. Aber du sagst doch selbst, dass jedesmal wenn du setText aufrufst die Farben wieder vertauscht werden. Angenommen color ist am anfang { 0, 1, 2 }. Jetzt rufst du setText auf was wiederum init mit den Parametern 0, 1, 2 aufruft. setText verändert nun die globale variable color, die nun die Werte { 2, 1, 0 } hat. Wenn du jetzt setText wieder aufrust ändert init die Werte von color wieder auf { 0, 1, 2 } usw. Mit einmaliger Initialisierung ist da ja nichts.



  • Hallo

    Okay nun habe ich die Zuweisung wieder gedreht und jetzt zeigt er mir wieder die falschen Farben:

    void chrische::sdl::opengl::text::init(const std::string& text_to_write, const std::string& file_name, const int r, const int g, const int b, int pos_x, int pos_y, const int text_height)
    {
    	file_name_ = file_name;
    	text_height_ = text_height;
    	text_to_write_ = text_to_write;
    
    	// red und blue wird vertauscht
    	color_.r = r;
    	color_.g = g;
    	color_.b = b;
    
    	p_font = TTF_OpenFont(file_name_.c_str(),text_height_);
    	if(!p_font)
    	{
    		get_logfile()->write("Fehler beim initialisieren vom Font ");
    		get_logfile()->write(TTF_GetError());
    		get_logfile()->write("<br>");
    		exit(1);
    	} // if(!p_font)
    
    	assert(pos_x != VCENTER);
    	assert(pos_y != HCENTER);
    	if(pos_x == HCENTER)
    		pos_x = get_horz_center_pos();
    	if(pos_y == VCENTER)
    		pos_y = get_vert_center_pos();
    
    	if(pos_x > 19999)
    		pos_x = get_horz_center_pos_on_line(pos_x - 20000);
    
    	position_.x = pos_x;
    	position_.y = pos_y;
    
    	SDL_Surface* temp_surface = TTF_RenderText_Blended(p_font, text_to_write.c_str(), color_);
    	w = next_power_of_two(temp_surface->w);
    	h = next_power_of_two(temp_surface->h);
    
    	SDL_Surface* temp_surface_two = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32,
    	#if SDL_BYTEORDER == SDL_BIG_ENDIAN
    		0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
    	#else
    		0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
    	#endif
    
    	SDL_BlitSurface(temp_surface, 0, temp_surface_two, 0);
    
    	glGenTextures(1, &texture);
    	glBindTexture(GL_TEXTURE_2D, texture);
    	glTexImage2D(GL_TEXTURE_2D, 0, 4, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, temp_surface_two->pixels );
    	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    
    	position_.w = temp_surface->w;
    	position_.h = temp_surface->h;
    
    	SDL_FreeSurface(temp_surface);
    	SDL_FreeSurface(temp_surface_two);
    }
    

    So wirde eine Text initialisiert:

    static_points.init("Punkte", "fonts\\myriad.ttf", 248, 152, 0, static_points.HCENTEREX(static_cast<int>(((screen_width/3.2)+20)/2)), 30, 20);
    

    Nun hat der Text aber eine blaue Farbe. Es sollte aber orange sein.

    Wenn ich den Text nun so initialisiere, wird der orange:

    static_points.init("Punkte", "fonts\\myriad.ttf", 0, 152, 248, static_points.HCENTEREX(static_cast<int>(((screen_width/3.2)+20)/2)), 30, 20);
    

    Da ist doch was verdreht.

    chrische



  • Das ist doch schonmal etwas. Immerhin bist du jetzt den Fehler mit den ständig wechselnden Farben los. Für den Farbendreher ist ein anderer Teil des Codes verantwortlich. Du hast mit deiner bisherigen Lösung zwar die Symtome behandelt aber noch nichts gegen die Ursache unternommen. Vielleicht irgendein Problem mit der Byte-Order deiner Surface? Ich werde mir mal ein kleines Testprogramm schreiben um deinen Fehler besser nachzuvollziehen sobald ich Zeit hab.


Anmelden zum Antworten