Problem mit PixelFormat (OpenGL)



  • Hey

    Ich hab ein kleines Problem und zwar hängt sich mein Programm immer auf, wenn ich bei glDrawPixels(...) den Typ GL_RGBA benutze (als 3. Parameter).
    (TBaseClassPointer ist ne Klasse zur Darstellung von Texturen,
    PIXELFORMAT_To_GLPIXELFORMAT() gibt den jeweiligen Typ zurück.
    Das Gleiche gilt für DATATYPE_To_GLDATATYPE(), nur eben für das Format.

    Solange Type = GL_RGB, GL_RED, GL_GREEN etc... bzw Format = GL_BYTE, GL_UNSIGNED_BYTE etc.. läuft alles wie es soll aber wenn ich GL_RGBA(Typ, hier nur bei RGBA) verwende oder GL_FLOAT, GL_INT (Format, da alles außer byte und ubyte), hängt er sich auf, mit APPCRASH.
    Bei dem Format kann ich mir ja theoretisch noch erklären, das es daran liegt, dass die Textur in Form eines Byte-Zeigers übergeben wird (GLbyte*), aber wieso nicht RGBA?
    Wenn ich Debuge sagt er:

    Unbehandelte Ausnahme bei 0x083ece7f in Understar Geqcone.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x0b03fc70.

    Das ist ja eigentlich eine AccessViolationException, oder nicht? Naja es wird auf jeden Fall keine geworfen.

    try{
    			glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    				if(this->TBaseClassPointer->GetTextureExists()){
    				glDrawPixels(this->TBaseClassPointer->Width, this->TBaseClassPointer->Height, GL_RGBA, // Hier
    NXG::Textures::DATATYPE_To_GLDATATYPE(this->TBaseClassPointer->GetDataType()), this->TBaseClassPointer->GetTexture);
    				}
    		}
    		catch(System::AccessViolationException^){}
    

    Kann mir jemand sagen, warum kein RGBA? Gibts da irgendwas, was ich nicht beachte?



  • Diese Violations treten in Deiner Grafikkarte bzw den Treibern auf, das kannst nicht abfangen.
    Aber ist denn das Datenfeld das du übergibst auch höhe*breite*4 groß? Die Daten für den Alphakanal müssen natürlich vorhanden sein. Sonst passiert genau das.
    rya.



  • Du meinst im Speicher? Ja das schon... Alpha kanal ist eigentlich auch vorhanden...
    soweit ich das jetzt auf die Schnelle nachgesehen hab... ich hab jetzt mal GL_BRG_EXT verwendet,
    und jetzt gehts...soweit ich sehe auch mit alpha, korrigiere mich wennn ich mich irre.
    Naja ich danke dir auf jeden fall hast mir sehr geholfen.



  • Wie lädst Du denn die Textur? Wenn Du alles über BGRA lädst, dann musst das auch angeben. Ich swappe eigentlich die Pixel wenn ich etwas in BGR lade und konvertiere das nach RGB. Sonst komme ich wieder in anderen Funktionen in die Bredoiulle.
    Welches Dateiformat lädst Du da? TGA? Das fällt mir grade ein als ein Format welches BGR verwendet... am besten Du legst Dich auf ein Format fest und speicherst entweder Deine Texturen in dem Format oder swappst wenn nötig etc etc.
    rya.



  • ja, die Texturen sind in tga. Ich lade sie eigtl in BGR, BGRA geht nicht... Wo du mir grade schon hilfst 🙂
    Ich hab noch ein anderes Problem das nicht so einfach ist... un zwar benutze ich ja CLI, also dementsprechend auch Windows Forms.
    Ich habe 4 ogl Fenster und die sind jeweils an ein Panel gedockt. Kannste dir vorstellen wie bei 3dsmax oder cinema4d.

    Der Code von einem ogl context sieht so aus: (unwichtiges mal auskommentiert)

    public ref class Perspective : public System::Windows::Forms::Form
    	{
    	private:
    			HDC hDC;
    			HGLRC hRC;
    			HWND hWnd;
    			//float SavedWidth;
    			//float SavedHeight;
    		//	float SavedDepth;
    	public:
    			//static NXG::Textures::TextureHolder^ObjectTextures = gcnew NXG::Textures::TextureHolder();
    
    		Perspective(GLsizei Width, GLsizei Height, Form^parentForm)
    		{
    			InitializeComponent();
    
    			if(buffer::Double){
    			#define CURRENTBUFFER_P 0x00000002
    			}
    			else
    			{
    			#undef CURRENTBUFFER_P
    			#define CURRENTBUFFER_P 0x00000001
    			}
    
    			this->TopLevel = false;
    			this->Parent = parentForm;
    			this->Size = System::Drawing::Size(Width,Height);
    			this->CreateHandle();
    
    	// Create the main application window
    	hWnd = (HWND)this->Handle.ToPointer();
    
    	// If window was not created, quit
    		if(hWnd == NULL){
    		MessageBox::Show("Could not create WindowHandle.","Error",MessageBoxButtons::OK,MessageBoxIcon::Error);
    		//NXG::Log::Protocole<nxgLog>::WriteEntry("Could not create WindowHandle",3,1,0);
    		}
    	}
    	virtual System::Void SetupRC(System::Void)
    	{
    		wglMakeCurrent(this->hDC,this->hRC);
    		glDrawBuffer(GL_BACK);	
    		//if(PerspectiveProperties::DepthTesting)
    		//glEnable(GL_DEPTH_TEST);
    		//if(PerspectiveProperties::Lighting){
    		//	glEnable(GL_LIGHTING);glEnable(GL_COLOR_MATERIAL);}
    		//else glDisable(GL_LIGHTING);
    		/*if(EnabledProperties::Scissoring)
    			glEnable(GL_SCISSOR_TEST);
    		else glDisable(GL_SCISSOR_TEST);*/
    
    		//EnabledProperties::EnableEverythingStatic();
    		glClearColor(0.50f, 0.50f, 0.50f, 0.0f);
    		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    		glPolygonMode(GL_FRONT_AND_BACK, GL_LINES);
    
    		//Lighting::AddToScene();
    	}
    	virtual void Render(void)
    	{
    		wglMakeCurrent(this->hDC,this->hRC);
    	// Set background clearing color to a light gray.
    		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    		glClearColor(0.50f,0.50f,0.50f, 1.0f);
    
    	glMatrixMode(GL_MODELVIEW);
    	glLoadIdentity();
    
    	//NXG::GraphiX::DoPerspectiveTransmission(this->hRC, this->hDC);
    	//NXG::GraphiX::DrawPerspectiveAxes(this->hRC, this->hDC);
    
    	//if(PerspectiveProperties::Lighting)
    	//{glEnable(GL_LIGHTING);
    	//glLightModelfv(GL_LIGHT_MODEL_AMBIENT, PerspectiveProperties::GeneralAmbientLight);
    	//glEnable(GL_COLOR_MATERIAL);}
    
    	ViewWindow::ProjektObjekte->DrawEverything(PerspectiveProperties::Lighting);  //Draw the Scene: Objects
    	}
    
    	virtual System::Void ChangeSize(int nWidth, int nHeight, Form^ parentForm)
    	{
    		wglMakeCurrent(hDC,hRC);
    
        if(nHeight == 0)
            nHeight = 1;
    	this->Size = System::Drawing::Size(nWidth,nHeight);
    
    	glViewport(0, 0, nWidth, nHeight);
    
    	//if(EnabledProperties::Scissoring)
    	//glScissor(0,0,nWidth,nHeight);
    
    		glMatrixMode(GL_PROJECTION);
    		glLoadIdentity();
    
    	//Reset it
    		gluPerspective(60.0, (nWidth/nHeight), 1.0,buffer::MAXDEPTH);
    
    		glMatrixMode(GL_MODELVIEW);
    		glLoadIdentity();
    	}
    
    	System::Void SwapBuffer(System::Void)
    	{
    		SwapBuffers(hDC) ;
    	}
     GLint MySetPixelFormat(HDC hdc)
        {
            PIXELFORMATDESCRIPTOR pfd = { 
                sizeof(PIXELFORMATDESCRIPTOR),    // size of this pfd 
    
                1,                                // version number 
    
                PFD_DRAW_TO_WINDOW |              // support window 
    
                PFD_SUPPORT_OPENGL |              // support OpenGL 
    
               PFD_DOUBLEBUFFER,                 // single or double buffered
    
                PFD_TYPE_RGBA,                    // RGBA type 
    
                24,                               // 24-bit color depth 
    
                0, 0, 0, 0, 0, 0,                 // color bits ignored 
    
                0,                                // no alpha buffer 
    
                0,                                // shift bit ignored 
    
                0,                                // no accumulation buffer 
    
                0, 0, 0, 0,                       // accum bits ignored 
    
                32,                               // 32-bit z-buffer     
    
                0,                                // no stencil buffer 
    
                0,                                // no auxiliary buffer 
    
                PFD_MAIN_PLANE,                   // main layer 
    
                0,                                // reserved 
    
                0, 0, 0                           // layer masks ignored 
    
            }; 
    
            GLint  iPixelFormat; 
    
            // get the device context's best, available pixel format match 
    
            if((iPixelFormat = ChoosePixelFormat(hdc, &pfd)) == 0)
            {
                MessageBox::Show("ChoosePixelFormat Failed");
                return 0;
            }
    
            // make that match the device context's current pixel format 
    
            if(SetPixelFormat(hdc, iPixelFormat, &pfd) == FALSE)
            {
                MessageBox::Show("SetPixelFormat Failed");
                return 0;
            }
    
            if((hRC = wglCreateContext(hDC)) == NULL)
            {
                MessageBox::Show("wglCreateContext Failed");
                return 0;
            }
    
            if((wglMakeCurrent(hDC, hRC)) == NULL)
            {
                MessageBox::Show("wglMakeCurrent Failed");
                return 0;
            }
    
            return 1;
        }
    
    #pragma endregion
    	private: System::Void Perspective_Load(System::Object^  sender, System::EventArgs^  e) {
    				 hDC = GetDC(hWnd);
    				if(hDC)
                MySetPixelFormat(hDC);
    
    		hRC = wglCreateContext(hDC);
    			wglMakeCurrent(hDC, hRC);
    			SetupRC();
    			 }
    	private: System::Void Perspective_Paint(System::Object^  sender, System::Windows::Forms::PaintEventArgs^  e) {
    				 //UNREFERENCED_PARAMETER(sender);
    				 //UNREFERENCED_PARAMETER(e);
    				 this->Render();
    				 if(buffer::Double){this->SwapBuffer();}
    				 else{glFlush();}
    
    				// glDisable(GL_LIGHTING);
    				 //if(EnabledProperties::BackFaceCulling)
    				//	glDisable(GL_CULL_FACE);
    			 }
    	private: System::Void Perspective_SizeChanged(System::Object^  sender, System::EventArgs^  e) {
    				  this->ChangeSize(this->ClientSize.Width, this->ClientSize.Height, this);
    				  this->Invalidate();
    			 }
    	};
    

    also im Endeffekt ganz normal. Im HauptForm werden diese 4 dann so eingebunden:

    private: System::Void MainWindow_Load(System::Object^  sender, System::EventArgs^  e) {
    				//NXG::Log::Protocole<nxgLog>::WriteEntry(nxgEMPTY_STD_STRING,1,1,0);
    				this->Ortho = gcnew ViewWindow(this->UpperLittleSplitter->Panel1->Width,
    																	 this->UpperLittleSplitter->Panel1->Height, this, 1);
    				this->Ortho2 = gcnew ViewWindow(this->UpperLittleSplitter->Panel1->Width,
    															this->UpperLittleSplitter->Panel1->Height, this, 2);
    				this->Ortho3 = gcnew ViewWindow(this->LowerLittleSplitter->Panel1->Width,
    															this->LowerLittleSplitter->Panel1->Height, this, 3);
    				this->PerspectiveView = gcnew Perspective(this->LowerLittleSplitter->Panel2->Width,
    															this->LowerLittleSplitter->Panel2->Height, this);
    				this->UpperLittleSplitter->Panel1->Controls->Add(Ortho);
    				this->Ortho->Dock = DockStyle::Fill;
    				Ortho->Show();
    				this->UpperLittleSplitter->Panel2->Controls->Add(Ortho2);
    				this->Ortho2->Dock = DockStyle::Fill;
    				Ortho2->Show();
    				this->LowerLittleSplitter->Panel1->Controls->Add(Ortho3);
    				this->Ortho3->Dock = DockStyle::Fill;
    				Ortho3->Show();
    				this->LowerLittleSplitter->Panel2->Controls->Add(PerspectiveView);
    				this->PerspectiveView->Dock = DockStyle::Fill;
    				PerspectiveView->Show();
                 }
    

    Das Problem ist jetzt das die ganzen Fenster flackern, wenn ich sie neu zeichne. Und das liegt nicht an der performance, selbst wenn ich
    nichts zeichne, sondern nur das Fenster neu aufsetzte, flackert es. Wüsstest du da was?



  • if(PerspectiveProperties::Lighting)
        {glEnable(GL_LIGHTING);
        glLightModelfv(GL_LIGHT_MODEL_AMBIENT, PerspectiveProperties::GeneralAmbientLight);
        glEnable(GL_COLOR_MATERIAL);
    

    Könnte eventuell daran liegen. Man muss den Status eigentlich nur 1x einschalten und nicht jeden Frame. Frag doch mal den Status von Lightning ab und aktiviere nur wenn nötig. Ansonsten frag doch mal am ENDE jedes Frames den Error-Code ab und lass dir den ausgeben über Visual Studio. Das hilft oft ne Menge. So mach ich das:

    u32 err = glGetError();
            while (err != GL_NO_ERROR && err != m_prevGLError)
            {
                m_prevGLError = err;
                std::stringstream ss;
                ss << "Error No:" << this->getGLErrorString(err) << "!";
                NLTrace(ss.str().c_str());
                err = glGetError();
            }
    

    Zu den Texturen:
    Wenn man eine Textur nicht mit BGRA lädt und diese keinen Alpha-Kanal hat, sollte das so nicht funktionieren, aber das ist von hier aus schlecht zu sagen.
    Ich benutze halt eine Image-Library und frage das Format des Bildes ab und erzeuge danach die Textur mit dem korrekten Parameter:

    NLITexture* NLTextureLoader::getTexture(const char* name, const char* filename, const bool repeat)
    {
        if ( !glIsEnabled(GL_TEXTURE_2D) ) {
            glEnable(GL_TEXTURE_2D);
        }
    
        // Load Texture
        corona::Image* img = NULL;
        img = corona::OpenImage(filename, corona::PF_R8G8B8A8);
        if (!img)
        {
            NLError(std::string("Cannot load Image '") + name + std::string("'."));
            return NULL;
        }
        u32 id = this->makeGLTexture(img->getPixels(), img->getWidth(), img->getHeight(), getColorsFromFormat(img->getFormat()), repeat);    
        delete img;
    
        // Add to collection
        NLTexture *handle 
            = new NLTexture(name, id);      
        return handle;
    }
    
    u32 NLTextureLoader::makeGLTexture(void* data, const u32 width, const u32 height, const u32 numcolor, const bool repeat)
    {
        GLuint glImage = 0;
        GLint oldTexture = 0;
        u32 mode = GL_TEXTURE_2D; // GL_EXT_texture_rectangle
    
        glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTexture);
        glGenTextures(1, &glImage);
        glBindTexture(mode, glImage);
    
        if ( numcolor == 3 )
        {
            glTexImage2D(mode, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);    
        }
        else if ( numcolor == 4)
        {
            glTexImage2D(mode, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
        }
    
        if ( repeat == true )
        {
            glTexParameteri(mode, GL_TEXTURE_WRAP_S, GL_REPEAT);
            glTexParameteri(mode, GL_TEXTURE_WRAP_T, GL_REPEAT);
        }    
        else
        {
            glTexParameteri(mode, GL_TEXTURE_WRAP_S, GL_CLAMP);
            glTexParameteri(mode, GL_TEXTURE_WRAP_T, GL_CLAMP);
        }
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
        glTexParameteri(mode, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(mode, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    
        glBindTexture(GL_TEXTURE_2D, oldTexture);
        return glImage;
    }
    
    u32 NLTextureLoader::getColorsFromFormat(u32 value)
    {
        switch(value)
        {
        case corona::PF_R8G8B8:
            return 3;
        case corona::PF_B8G8R8:
            return 3;
        case corona::PF_B8G8R8A8:
            return 4;
        case corona::PF_R8G8B8A8:
            return 4;
        default:
            return 3;
        }
    }
    

    HTH.
    rya.


Anmelden zum Antworten