OpenGL Framebuffer



  • Moin.
    Ich mal wieder :D.

    Hab gestern Abend mal wieder mit meinem Sorgenkind, meiner Fontklasse rumgemacht.
    Also Font darstellen an sich ist ja kein Problem.
    Ich wollte nun die Darstellung optimieren.
    Ich verwende einen normalen Bitmap Font, der über Subtexture-Koordinaten wie bei einem Spritesheet über die Quadrate gelegt wird (2 Polygone).

    (Zum erstellen der Font-Textur verwende ich übrigens BMFont vom Autor von AngelScript, sehr zu empfehlen das kleine Tool. Nur am rande. 🤡)

    Folgende Idee und damit auch mein Problem:

    Klasse StaticText:
    Text wird beim Erstellen der Klasse im Framebuffer auf eine Textur gerendert, da er zu Lebzeiten nie geändert wird. Ich stelle dann nur noch die Textur in der Größe des Fonts dar (Werte werden von der Fontklasse beim übergeben der Textur-/VerticeDaten berechnet). So weit so gut. Ist denke ich Gang und gebe diese Technik.
    Ich habe es auch geschafft von OpenGL die Meldung GL_FRAMEBUFFER_COMPLETE zu erhalten.
    Nur, die Textur blieb hartnäckig schwarz. Hier meine Fragen dazu:

    😉 Muss ich, wenn ich auf einen FBO Render genauso eine Orthographische Matrix im Shader setzen? (GL_TEXTURE_2D)
    😉 Wie bekomme ich die Textur (auf die gerendert wird) transparent, damit nur das was gerendert wird auch dargestellt wird?
    😉 Welche Positionierungsdaten erwartet OpenGL hier? Oder muss ich Shader einfach nur die ProjektionsMatrix auf die Größe der Textur setzen? Als bsp. glOrtho(0, 256,256,0, -1,1) für eine 256x256 Textur. Also wie sieht OpenGL die GL_TEXTURE_2D? Von 0 - width bzw 0 - height?

    Shader:
    http://code.google.com/p/nightlighttv/source/browse/NightLight/trunk/bin/shaders/FontShader.vert

    Der Fragment Shader ist mit der Endung .frag abrufbar.

    Die Matrix wird hier gesetzt:
    http://code.google.com/p/nightlighttv/source/browse/NightLight/trunk/NightLightDLL/NLShader.cpp#203
    (glOrtho im Prinzip)



  • Scorcher24 schrieb:

    Nur, die Textur blieb hartnäckig schwarz. Hier meine Fragen dazu:

    😉 Muss ich, wenn ich auf einen FBO Render genauso eine Orthographische Matrix im Shader setzen? (GL_TEXTURE_2D)

    Natürlich. Ob du nun offscreen renderst oder nicht ist doch völlig egal. Projeziert werden muss ja trotzdem.

    Scorcher24 schrieb:

    😉 Wie bekomme ich die Textur (auf die gerendert wird) transparent, damit nur das was gerendert wird auch dargestellt wird?

    Beim rendern in die Textur des FBOs kannst du ja im FS überprüfen welche Farbwerte das aktuelle Fragment hat. Abhängig davon setzt du dann eben noch den Alphawert und nutzt später beim rendern des Textur (des Textes) alpha-blending.

    Scorcher24 schrieb:

    😉 Welche Positionierungsdaten erwartet OpenGL hier? Oder muss ich Shader einfach nur die ProjektionsMatrix auf die Größe der Textur setzen? Als bsp. glOrtho(0, 256,256,0, -1,1) für eine 256x256 Textur. Also wie sieht OpenGL die GL_TEXTURE_2D? Von 0 - width bzw 0 - height?

    Öh - hab ich jetzt nicht ganz verstanden. Die Grösse der Textur sollte natürlich der des verwendeten Renderbuffers entsprechen.
    [/quote]

    Grüsse.

    P.S.: Ich verwende FreeType 2 wenns um fonts geht. Vielleicht ja auch für dich Interessant.



  • Was du suchst ist erstmal:
    glViewport(0, 0, textureSizeX, textureSizeY);

    und glOrtho setzt dann deine gewünschte Matrix.
    Die kann dann z.B. auch glOrtho(0, 1, 0, 1, -1, 1) sein.



  • Danke euch beiden. Habs jetzt hinbekommen:

    void NLStaticText::renderToTexture(NLFont* font, const glm::vec3& position, const std::string& text, NLShader* shader, const glm::vec4& color)
    {
    	u32 fbo = 0, rbo = 0, texture = 0;
    	u32 width = 0, height = 0;
    
    	// Calculate Bounding Box
    	{
    
    		NLSpriteList::TSpriteList::iterator it = m_batcher->begin();		
    
    		height = font->getLineHeight();	
    		for ( it; it != m_batcher->end(); it++ )
    		{
    			width += static_cast<u32>(it->getSize().x);			
    		}
    	}
    
    	// Texture
    	{
    		glGenTextures(1, &texture);
    		glBindTexture(GL_TEXTURE_2D, texture);
    		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    
    		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    
    		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    		glBindTexture(GL_TEXTURE_2D, 0);
    	}
    
    	// FBO
    	{
    		glGenFramebuffers(1, &fbo);
    		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    	}
    
    	// RBO
    	{
    		glGenRenderbuffers(1, & rbo);
    		glBindRenderbuffer(GL_RENDERBUFFER, rbo);
    		glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height);
    		glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
    	}
    
    	// Attach the texture
    	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texture, 0);
    
    	// Attach Renderbuffer to depth attachment point
    	glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rbo);
    
    	// Error handling
    	{
    		u32 error = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    		if ( error != GL_FRAMEBUFFER_COMPLETE ){
    			NLError("[NLStaticText] Framebuffer incomplete!");
    		}
    	}
    
    	// Render
    	{
    		shader->sendNewOrthoMatrix(width, height);
    
    		glEnable(GL_BLEND);
    		glViewport(0,0, width, height);
    		glClearColor(0,0,0,0);
    		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );		
    		m_batcher->renderObject();
    		SystemController().getWindow().setClearColor(NLCOLOR4F_BLUE);
    		glDisable(GL_BLEND);
    
    	}
    
    	// Clean up
    	{
    		glBindRenderbuffer(GL_RENDERBUFFER, 0);
    		glBindFramebuffer(GL_FRAMEBUFFER, 0);
    		glDeleteFramebuffers(1, &fbo);
    		glDeleteRenderbuffers(1, &rbo);
    
    		f32 screen_w = SystemController().getScreenBoundingBox().getSize().x;
    		f32 screen_h = SystemController().getScreenBoundingBox().getSize().y; 
    		shader->sendNewOrthoMatrix(screen_w, screen_h);
    		glViewport(0,0, screen_w, screen_h);
    	}
    
    	// Create Sprite
    	std::string tex_name = std::string("FrameBufferTextureForText_") + m_text;
    	m_texture = new NLTexture(tex_name.c_str(), glm::vec2(width, height), texture);
    	NLShader* sprite_shader = SystemController().getResourceManager().getShader("TexturedWithAlphaTest");
    
    	m_sprite = new NLSprite(glm::vec2(width, height), position, sprite_shader, m_texture);
    }
    


  • inter2k3 schrieb:

    P.S.: Ich verwende FreeType 2 wenns um fonts geht. Vielleicht ja auch für dich Interessant.

    Ne, FreeType isn Monster. Das will ich nicht einbinden. Und auch nicht lernen.
    Ich verwende wie gesagt das hier:
    http://www.angelcode.com/products/bmfont/

    Das generiert mir ne Textur mit allen Glyphen, es fällt also der FreeType part weg. Und das Dateiformat habe ich mit einem Parser ausm gamedev.net Forum schnell eingebaut. Wenns schon zur Verfügung gestellt wird, braucht man das Rad (in dem Fall) nicht neu erfinden. Das habe ich mir zur maxime gemacht.
    Der Generator ist sehr nice.

    Ich möchte nur bei statischem Text das auf einer Textur haben. Das reduziert nochmal ein wenig die gerenderten Polygone.


Log in to reply