mehrere OpenGL Fenster welche die selben Texturen verwenden



  • Hallo

    ich habe mir gestern eine Klasse zum schnellen Erstellen von OpenGL-Fenster geschrieben und dazu einen Texture-Loader. In MAIN.CPP erstelle ich 3 OpenGL-Fenster. In jedem der Fenster soll sich ein rotierenden Viereck befinden. Jedes Viereck soll die gleiche Texture verwenden ohne das ich diese mehrmals Laden muss.

    Problem: nur in einem Fenster wird die Textur angezeigt, Window 3 (blau). Ist es nicht möglich eine Textur einmal zu laden und für mehrere Fenster zu verwenden?

    MAIN.CPP

    #include <windows.h>
    #include "glwindow.h"    // OpenGL Window Class
    #include "gltextures.h"  // Klasse zum S3TC-aktiveren, Laden, Entladen von Texturen in BLP2-Format
    
    Cgltextures texture;
    
    void DrawGLScene(float R, float G, float B)					// Here's Where We Do All The Drawing
    {
    	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);		// Clear The Screen And The Depth Buffer
    	glLoadIdentity();										// Reset The View
    	glTranslatef(0.0f,0.0f,-3.0f);							// Move Into The Screen 6.0
    	glRotatef(GetTickCount()*0.1f,0.0f,1.0f,0.0f);
    	glColor3f(R,G,B);
    	//glColor3f(1.0f,1.0f,1.0f);
    	glEnable(GL_TEXTURE_2D);
    	glBindTexture(GL_TEXTURE_2D, texture.blp2[0]);			// Select Our Texture
    
    	glBegin(GL_QUADS);										// Draw A Quad
    		glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 0.0f);	// Bottom Left Of The Texture
    		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 0.0f);	// Bottom Right Of The Texture
    		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, 0.0f);	// Top Right Of The Texture
    		glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, 0.0f);	// Top Left Of The Texture
    	glEnd();												// Done Drawing The Quad
    }
    
    int WINAPI WinMain(	HINSTANCE	hInstance,					// Instance
    					HINSTANCE	hPrevInstance,				// Previous Instance
    					LPSTR		lpCmdLine,					// Command Line Parameters
    					int			nCmdShow)					// Window Show State
    {
    	Cglwindow wnd1,wnd2,wnd3;	// Erstelle OpenGL Window 1+2+3
    
    	wnd1.CreateGLwindow(200, 200);
    	if (!texture.EnableS3TC())	// enable S3TC texture compression, atleast one GL-RC must exist for this to work
    		return false;
    	//if (!texture.LoadBLP2Disk("font.blp")) // Comment entfernen und wnd1 ist texturiert
    	//	return false;
    	wnd2.CreateGLwindow(150, 150);
    	//if (!texture.LoadBLP2Disk("font.blp")) // Comment entfernen und wnd2 ist texturiert
    	//	return false;
    	wnd3.CreateGLwindow(100, 100);
    	if (!texture.LoadBLP2Disk("font.blp"))
    		return false;
    
    	while(!wnd1.done && !wnd2.done && !wnd3.done)
    	{
    		wnd1.Update();
    		DrawGLScene(1.0f,0.0f,0.0f);	// Red
    		wnd2.Update();
    		DrawGLScene(0.0f,1.0f,0.0f);	// Green
    		wnd3.Update();
    		DrawGLScene(0.0f,0.0f,1.0f);	// Blue
    	}
    	return 0;
    }
    

    GLTEXTURES.H:
    ...gelöscht - unrelevant

    GLTEXTURES.CPP:
    ...gelöscht - unrelevant


  • Mod

    cuppuccinofreak schrieb:

    Ist es nicht möglich eine Textur einmal zu laden und für mehrere Fenster zu verwenden?

    texturen werden pro context angebunden, ein ogl context wird pro fenster erstellt...

    bei primitiven fensteranordnungen kannst du statt den fenster einfach mit opengl in die geweiligen stellen in einem fenster rendern, z.b. die typische 4quadranten ansicht (glViewPort ist dann dein freund).

    es gibt wohl auch ein paar extension um die texturen zwischen mehreren context zu sharen, wenn du die such hier benutzt koenntest du nen thread dazu finden.

    alternativ kannst du immer in eine textur rendern und dann mit glreadpixel usw. die pixel rauskopieren und ins gewuenschte fenster schieben (mit den funktionen die dein OS bietet).



  • texturen werden pro context angebunden, ein ogl context wird pro fenster erstellt...

    Mist, sowas in der Art hatte ich vermutet. Zum Glück habe ich dank deinem Hinweis eine Lösung gefunden: wglShareLists();

    http://www.opengl.org/resources/faq/technical/texture.htm
    Siehe: 16.020 How can I share display lists between different contexts?

    In meinem Testcode funktioniert es so:

    wnd1.CreateGLwindow(200, 200);
    wnd2.CreateGLwindow(150, 150);
    wnd3.CreateGLwindow(100, 100);
    
    if (!texture.EnableS3TC())	// enable S3TC texture compression
    	return false;
    if (!texture.LoadBLP2Disk("font.blp")) // Load Textures for wnd3.hrc
    	return false;
    
    wglShareLists(wnd3.hrc, wnd2.hrc); // share wnd3.hrc -> wnd2.hrc
    wglShareLists(wnd2.hrc, wnd1.hrc); // share wnd2.hrc -> wnd1.hrc
    

    Eine Frage hätte ich dazu noch:
    Ich werde später ca. 70 Texturen statisch laden, sprich beim Programmstart. Während das Programm läuft muss ich bis zu 1200 weitere Texturen dynamisch laden. Wenn ich MSDN richtig verstehe reicht es aus wglShareLists nur einmal aufzurufen. Auch wenn sich die Displaylist ändert (wenn neue Texturen geladen oder alte gelöscht werden) müssten jedem Fenster die gleichen Texturen zur Verfügung stehen. (weil sie ja 'shared' sind) korrekt?

    MSDN:

    ...Once a rendering context shares a display-list space, the rendering context always uses the display-list space until the rendering context is deleted. When the last rendering context of a shared display-list space is deleted, the shared display-list space is deleted. ...


  • Mod

    da steht, dass eine list solange existiert wie der am laengsten lebende context. soll also heissen, dass du einen context loeschen/freigeben kannst und die anderen trotzdem noch auf die list zugreifen koennen.
    du musst dich also nicht drum sorgen dass sie eventuel verschwindet.

    wenn du die list selber loescht/freigibst, ist sie natuerlich fuer alle context weg.



  • perfekt! Genau das was ich brauche. Danke dir rapso. Habe es auch gerade durchgetestet und alles funtioniert so wie es soll.


Anmelden zum Antworten