OpenGL MSAA funktioniert nicht



  • Hallo,

    ich habe versucht MSAA zu implementieren, was leider bislang nicht funktioniert hat. Multisampling ist verfügbar und ich kann auch einen Kontext mit einem 8x Sampleformat erstellen, jedoch gibt mir glGetIntegerv hinterher nur 1 Sample und 1 Buffer an, obwohl ich 8 Samples und Doublebuffering anforder.

    Zuerst suche ich mir einen geeigneten Kontext, nachdem ich mir per Preload einen dummykontext erzeugt habe und die extensions gebunden habe.

    void Preload(void* ptr) //<- dummy handle
    	{
    		void* tmp = handle;
    		handle = ptr;
    
    		setupContext();
    		LoadExtensions();
    		Dispose();
    
    		handle = tmp;
    	}
    
    void setupContext()
    	{
    		if((device = GetDC(handle)))
    		{
    			SwapBuffers(device);
    			int rt;
    			if((rt = ChoosePixelFormat(device, &format)))
    			{
    				if (SetPixelFormat(device, rt, &format))
    				if(profile.MajorVersion <= 0)
    				{
    					if((context = CreateContext(device)))
    						MakeCurrent(device,context);
    				}
    				else
    				{
    					int* ptr = profile.CreateList();
    					if((context = CreateContextAttribs(device, profile.SharedHandle, ptr)))
    						MakeCurrent(device,context);
    				}
    			}
    		}
    	}
    
    void Dispose()
    	{
    		if(handle)
    		{
    			MakeCurrent(0, 0);
    		        DeleteContext(context);
    			ReleaseDC(handle, device);
    
    			context = 0;
    			device = 0;
    			handle = 0;
    		}
    	}
    

    dann setze ich das format auf den letzten Eintrag in der Liste, die ich wie folgt erzeuge

    std::vector<MultisamplePixelFormat> SupportedFormats()
    			{
    				if(!device)
    					if(!(device = PlatformCore::GetDC(handle)))
    						return std::vector<MultisamplePixelFormat>();
    
    				std::vector<MultisamplePixelFormat> formats = std::vector<MultisamplePixelFormat>();
    
    				int attribs[] = 
                    {
                        (int)MultisamplePixelFormatType::AccelerationArb,
    
                        (int)MultisamplePixelFormatType::RedBitsArb,
                        (int)MultisamplePixelFormatType::GreenBitsArb,
                        (int)MultisamplePixelFormatType::BlueBitsArb,
                        (int)MultisamplePixelFormatType::AlphaBitsArb,
                        (int)MultisamplePixelFormatType::ColorBitsArb,
    
                        (int)MultisamplePixelFormatType::DepthBitsArb,
                        (int)MultisamplePixelFormatType::StencilBitsArb,
    
                        (int)MultisampleType::SampleBuffersArb,
                        (int)MultisampleType::SamplesArb,
    
                        (int)MultisamplePixelFormatType::AccumRedBitsArb,
                        (int)MultisamplePixelFormatType::AccumGreenBitsArb,
                        (int)MultisamplePixelFormatType::AccumBlueBitsArb,
                        (int)MultisamplePixelFormatType::AccumAlphaBitsArb,
                        (int)MultisamplePixelFormatType::AccumBitsArb,
    
                        (int)MultisamplePixelFormatType::DoubleBufferArb,
                        (int)MultisamplePixelFormatType::StereoArb,
    
                        0
                    };
    
    			int values[17] = { 0 };
                int attribs_values[] =
                    {
                        (int)MultisamplePixelFormatType::AccelerationArb,
                        (int)MultisamplePixelFormatType::FullAccelerationArb,
                        (int)MultisamplePixelFormatType::SupportOpenglArb, 1,
                        (int)MultisamplePixelFormatType::DrawToWindowArb, 1,
                        0, 0
                    };
    
                int piFormats;
                uint numFormats;
    
                    if (ChoosePixelFormatARB(device, attribs_values, 0, 0, 0, &numFormats))
                    {
    					std::vector<int> pixel = std::vector<int>(numFormats);
                        if (ChoosePixelFormatARB(device, attribs_values, 0, numFormats, &pixel[0], &numFormats))
                        {
    						for(int p = 0; p < numFormats; p++)
                                if (GetPixelFormatAttribivARB(device, pixel[p], 0, 17, attribs, values))
                                {
                                    MultisamplePixelFormat pfd = MultisamplePixelFormat();
                                    pfd.Version = p;
                                    pfd.ColorBits = (byte)(values[1] + values[2] + values[3] + values[4]);
                                    pfd.DepthBits = (byte)values[6];
                                    pfd.Stencil = (byte)values[7];
                                    pfd.Samples = ((values[8] != 0) ? values[9] : 0);
                                    pfd.Accum = (byte)(values[10] + values[11] + values[12] + values[13]);
                                    pfd.Buffers = ((values[15] == 1) ? 2 : 1);
                                    pfd.Stereo = (values[16] == 1);
    
                                    formats.push_back(pfd);
                                }
    					   }
                    }
    
                return formats;
            }
    
    //pixelformat
    		Size	40	short
    		Version	1	short
    		Flags	37	int
    		PixelType	0	unsigned char
    		ColorBits	24 ''	unsigned char
    		RedBits	0	unsigned char
    		RedShift	0	unsigned char
    		GreenBits	0	unsigned char
    		GreenShift	0	unsigned char
    		BlueBits	0	unsigned char
    		BlueShift	0	unsigned char
    		AlphaBits	0	unsigned char
    		AlphaShift	0	unsigned char
    		AccumBits	0	unsigned char
    		AccumRedBits	0	unsigned char
    		AccumGreenBits	0	unsigned char
    		AccumBlueBits	0	unsigned char
    		AccumAlphaBits	0	unsigned char
    		DepthBits	16 ''	unsigned char
    		StencilBits	0	unsigned char
    		AuxBuffers	0	unsigned char
    		LayerType	0	unsigned char
    		Reserved	0	unsigned char
    		LayerMask	0	int
    		VisibleMask	0	int
    		DamageMask	0	int
    
    //multisample format
    		Size	24	short
    		Version	33	int
    		Accum	64 '@'	unsigned char
    		ColorBits	32 ' '	unsigned char
    		DepthBits	24 ''	unsigned char
    		Stencil	8 ''	unsigned char
    		Samples	8	int
    		Buffers	2	int
    		Stereo	false	bool
    

    anschließend erzeuge ich den richtigen Kontext mit dem angegebenen Format

    void setupMultisample()
    	{
    		if(device || (device = GetDC(handle)))
    		{
    			SwapBuffers(device);
    
    			int rt;
    			if((rt = DescribePixelFormat(device, multisample.Version, format.Size, &format)))
    			{
    				if (SetPixelFormat(device, multisample.Version, &format))
    				if(profile.MajorVersion <= 0)
    				{
    					if((context = CreateContext(device)))
    						MakeCurrent(device,context);
    				}
    				else
    				{
    					int* ptr = profile.CreateList();
    					if((context = CreateContextAttribs(device, profile.SharedHandle, ptr)))
    						MakeCurrent(device,context);
    				}
    			}
    		}
    	}
    
    //pixelformat after call
    		Size	40	short
    		Version	1	short
    		Flags	4	int
    		PixelType	0	unsigned char
    		ColorBits	32 ' '	unsigned char
    		RedBits	8 ''	unsigned char
    		RedShift	16 ''	unsigned char
    		GreenBits	8 ''	unsigned char
    		GreenShift	8 ''	unsigned char
    		BlueBits	8 ''	unsigned char
    		BlueShift	0	unsigned char
    		AlphaBits	8 ''	unsigned char
    		AlphaShift	24 ''	unsigned char
    		AccumBits	64 '@'	unsigned char
    		AccumRedBits	16 ''	unsigned char
    		AccumGreenBits	16 ''	unsigned char
    		AccumBlueBits	16 ''	unsigned char
    		AccumAlphaBits	16 ''	unsigned char
    		DepthBits	24 ''	unsigned char
    		StencilBits	8 ''	unsigned char
    		AuxBuffers	0	unsigned char
    		LayerType	0	unsigned char
    		Reserved	0	unsigned char
    		LayerMask	0	int
    		VisibleMask	0	int
    		DamageMask	0	int
    

    und wenn ich jetzt glGetIntegerv für Buffer und Samples aufrufe bekomme ich jeweils nur 1 Buffer und 1 Sample angezeigt und die Scene ist immer noch ziemlich Fragmentbelastet an den Kanten.

    Es spielt übrigens keine Rolle ob ich 8 oder 4 Samples anfordere, es klappt nicht!

    Das Fenster ist gerade ein ganz rudimentäres Fenster welches ich mir von Nehe geholt habe, jedoch ohne den gl kram, da ich das ja selbst mache.

    Hat jemand eine Ahnung woran das liegen kann?

    Nachtrag: GetLastError schmeißt an keiner Stelle eine Fehlermeldung, von daher vermute ich mal, dass alles so OK ist



  • klappt es auch fullscreen nicht?



  • hallo,

    nein habe ich nicht, da ich bislang immer eher im fenster gearbeitet habe, werde ich aber in zukunft nochmal probieren.

    Ich werde es auch nochmal über einen wrapper mit einem .net form ausprobieren, da ich das in der c# variante damals erfolgreich implementieren konnte und sichd er code eigentlich nicht gravierend unterscheidet.

    Aber kann es tatsächlich daran bzw. am Fenster liegen?



  • Soweit ich mich richtig erinnere musste nicht nur der Rendercontext sondern auch das HWND geloescht und neu erzeugt werden.
    Das ist aber bei einem von .Net vorgegebenen Fenster wohl nicht ohne Weiteres drin.
    Du kannst Dir aber doch einfach ein Framebuffer Object mit Multisampling erzeugen und das am Ende in Dein Fenster blitten.



  • hellihjb schrieb:

    Du kannst Dir aber doch einfach ein Framebuffer Object mit Multisampling erzeugen und das am Ende in Dein Fenster blitten.

    Da würde aber imho die Performance stark drunter leiden.



  • So schlimm ist ein Hardwareblit nun auch wieder nicht. Allerdings nur als letzte Notlösung zu sehen imo.



  • Also ich habe in meiner C++ test anwendung zwei fenster erzeugt. Von einem habe ich das handle also das HWND an die display-klasse übergeben, das ist mein hauptfenster. Darüberhinaus habe ich den kontext für das vorhergehende laden von den erweiterungsmethoden aber über das andere fenster per preload() und dessen handle erzeugt und danach erst den msaa kontext für mein hauptfenster, daran kannes also nicht liegen weil es zwei getrennte objekte mit unterschiedlichem handle sind.

    Übrigens funktioniert das in .Net ganz einfach über

    Preload(new System.Windows.Forms.Form().Handle);
    


  • So, ich habe das Problem teilweise gelöst. Das Problem ist wohl, dass Pixelformate zurückgegeben werden, die vom Fenster nicht unterstützt werden und deshalb wird auch kein Multisampling durchgeführt.

    Das äußert sich beispielsweise darin, wenn ich Format nr. 33 nehme, welches genau die gleichen Parameter hat wie Format 32, dieses nicht klappt, Format 32 aber 8x MSAA durchführt.

    Da steckt wohl irgendein Parameter drin, den ich mit wglChoosePixelFormatARB noch abfragen müsste, den ich aber aktuell nicht kenne, der aber dafür sorgt oder den Indikator dafür gibt, dass MSAA unterstützt wird oder eben nicht.

    Kennt sich jemand so gut damit aus, dass er mir sagen könnte welches attribut das sein könnte?


Anmelden zum Antworten