Registriert: Di Apr 29, 2008 18:56 Beiträge: 1213
Programmiersprache: Delphi/FPC
Hey,
ich bin grad dabei meine Proggi etwas zu verbessern und hab n Problem beim Supersampling. Ich Render die komplette Szene in ein FBO, das 2x größer is als der Bildschirm. Das funktioniert auch wunderbar, wenn ich jetzt aber noch ein Tick am Rädchen drehen will und das Supersampling auf 4x stelle schmiert die Anwendung ab, weil die maximale Texturgröße überschirrten wurde. Hat jmd ne Idee wie ich trotzdem 4x (evtl sogar 8x) Supersampling hin bekommen kann? €: am Hardware AA hab ich mich noch nich probiert, werd ich aber demnächst mal versuchen wenn ich Zeit finde.
Nun, du könntest die Szene mehrfach rendern. Also du für 4x renderst du insgesamt vier deiner 2x-FBOs. Die Kunst ist eigentlich nur die View/Projection-Matrix korrekt hin zu bekommen. (*) Idealerweise sollten sich die FBOs leicht überschneiden, anderenfalls könnte es sichtbare Artefakte beim zusammenfügen geben.
Das das nicht sonderlich schnell wird wenn du die Szene 4 oder gar 16 mal renderst sollte klar sein.
(*) Auf den ersten Blick klingt das schwer, soooo schwer ist es aber nicht. Am Ende deiner ModelViewProjectionMatrix landest du im Raum [-1...1]^3. Du musst nur noch eine Skalierung+Translation für die X&Y-Achse hinter die Projektion hängen damit zu [-1...0]x[-1...0]x[-1...1] bzw. [0...1]x[-1...0]x[-1...1] usw. kommst.
Edit: Hardware AA ist natürlich dem ganzen vor zu ziehen. Allerdings hab ich keine Ahnung wie man das macht.
Registriert: Di Apr 29, 2008 18:56 Beiträge: 1213
Programmiersprache: Delphi/FPC
Hey,
die Ide hatte ich auch schon, aber die hab ich erstmal verworfen, weil ich dachte es gibt was besseres. Das es dann ar***lahm wird is klar ^^ Zum Hardware AA gabs ja schonma n Thread, ich les mir das ma durch un probier mich ma dran, wenn ich Erfolge erziehlt haben sollte wäre das ja auch was fürs Wiki, weil da gibts ja auch noch nix so weit ich weiß...
Hardware AntiAliasing ist im prinzip sehr simpel... du mußt nur nen Context mit entsprechendem Setup erstellen und dann via glEnable, bzw glDisable mit GL_MULTISAMPLE das AntiAliasing aktivieren oder deaktivieren.
Das einzig schwere ist eben den Context zu erstellen.. dafür braucht es unter Windows erstmal einen Context ohne AntiAliasing um die extension zu laden etc, dann kannst den wieder wegwerfen und deinen richtigen Context mit den richtigen Sample-Einstellungen erstellen.
Wie es unter Linux geht weiß ich nicht.. unter MacOSX kann man direkt beim ersten Context sagen wieviel Multisampling man haben möchte.
Aya
PS: Soweit ich das hier mitbekommen habe unterstützt doch sogar der DGL-Header die geschichte mit dem Multisample-Context.. also der übernimmt dann den Part mit dem Temporären-Context.
Registriert: Di Okt 03, 2006 14:07 Beiträge: 1277 Wohnort: Wien
Bergmann89 hat geschrieben:
wäre das ja auch was fürs Wiki, weil da gibts ja auch noch nix so weit ich weiß...
Doch, es gibt schon etwas, nur ist es sehr gut versteckt.
Gib mal im Wiki das Stichwort "wglChoosePixelFormatARB" ein.
Ich habe das Multisampling für Windows bei mir implementiert und dazu einen Artikel ins Wiki geschrieben. Der Code ist derzeit zwar stillgelegt, aber er hat damals einwandfrei funktioniert. Ich habe keinen Sourcecode dazugegegeben, weil mein Artikel so ein "Spezifikations"-Artikel war, da darf kein Sourcecode rein. Aber Du bist schon der X-te, der danach fragt.... So langsam wär es Zeit Sourcecode ins Wiki zu schreiben. Ich kann jetzt aber im Augenblick leider nicht. Aber den SourceCode könnte ich Dir schon geben (Pascal).
Wie es in Linux geht, würde mich auch interessieren. Viele Grüße, Traude
Registriert: Di Okt 13, 2009 17:25 Beiträge: 365
Programmiersprache: C++
@Aya und Traude: Ihr redet beide von Multisampling. Ich dachte, Bergmann wollte sich am Supersampling versuchen? Oder geht es allgemein um Antialiasing?
Gruß mrtrain
Zuletzt geändert von mrtrain am Mi Aug 31, 2011 19:16, insgesamt 1-mal geändert.
Registriert: Di Okt 03, 2006 14:07 Beiträge: 1277 Wohnort: Wien
Nun, er hat eigentlich beide erwähnt. Und er hat davon gesprochen, es selber machen zu wollen. Das sei natürlich jedem gegönnt, ein wenig auf der Grafikkarte in der Pixelsuppe umzurühren.
Nevertheless, just my 2 cents: dem Multisampling per Pixelformat sollte der Vorzug gegeben werden. Ich denke, schneller ist es allemal. Vor allem initialisiert man es *einmal*, und dann muss man sich nicht mehr drum kümmern.
Registriert: Di Apr 29, 2008 18:56 Beiträge: 1213
Programmiersprache: Delphi/FPC
Hey,
@mrtrain: am Ende is ega wie es geglättet wird, hauptsache die Treppen sind weg^^ @Traude: also komplett selber wollt ich das ding auch net schreiben, ich meinte schon die Sache mit dem Pixelformat. Das hab ich in dem anderen Topic schonmal gelesen, aber woe gesagt noch nicht ausprobiert. Mach ich aber sobald ich Zeit hab, jetzt stehn erstma Prüfungen an erster stelle ( leider -.- )
Registriert: Do Sep 25, 2003 15:56 Beiträge: 7810 Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Es darf beispielcode ins Wiki. Falls es in den Spec Artikel nicht wirklich rein passt, kannst du auch einen extra Artikel machen und den dann von der Spec aus verlinken. Da sind wir sehr tollerant.
_________________ Blog: kevin-fleischer.de und fbaingermany.com
Registriert: Di Okt 03, 2006 14:07 Beiträge: 1277 Wohnort: Wien
@Flash: Dachte ich mir, dass das an mir hängenbleibt.
Aber jetzt im Augenblick gehts nicht, wenn ich so etwas bastel dann will ich es testen auch. Und das kann ich im Augenblick nicht, weil meine ganze Zeichen-Maschinerie im Umbau begriffen ist und noch nicht wieder ordentlich zusammenarbeiten kann: Ich stelle grade auf Shader & OpenGL3/4-Kompatibilität um. Dauert also noch ein bisschen, bis ich wieder einsatzfähig bin. Aber ich habs vorgemerkt.
Registriert: Di Apr 29, 2008 18:56 Beiträge: 1213
Programmiersprache: Delphi/FPC
Hey,
wenns bei mir so gut weitergeht wie bisher kann ich dir die Arbeit abnehmen^^ Ich hab diesen Code von LordHorazont gefunden, der hat mir weiter geholfen. Ich hab zur Zeit noch 2 Probleme/Fragen: 1: er findet ja mehrere Pixelformate. Gibt es da zwischen denen einen Unterschied bezogen auf das Multisampling (mal abgesehen von der SampleRate)? 2: ich hab noch n paar Probleme mit dem Neuerzeugen des Fensters, weil ja das Pixelformat schon gesetzt wurde. Kann man das auch iwie anders lösen, wenn ja wie? Ich hab das Neuerzeugen mit DestroyWnd und CreateWnd probiert und trotzdem gibt mir SetPixelFormat false zurück, wenn ich das AAPixelformat setzen will. Außerdem kann man die Sache dann nicht in eine unabhängige Unit auslagern, da man ja direkt auf Form1 zugreifen muss, weil die Methoden nicht public sind.
Registriert: Di Okt 03, 2006 14:07 Beiträge: 1277 Wohnort: Wien
Bergmann89 hat geschrieben:
wenns bei mir so gut weitergeht wie bisher kann ich dir die Arbeit abnehmen^^
SUPER! Hab's immer gern wenn mir jemand eine Arbeit abnimmt.
Bergmann89 hat geschrieben:
Ich hab diesen Code von LordHorazont gefunden, der hat mir weiter geholfen.
Ja, den hab ich damals auch benutzt.
Bergmann89 hat geschrieben:
1: er findet ja mehrere Pixelformate. Gibt es da zwischen denen einen Unterschied bezogen auf das Multisampling (mal abgesehen von der SampleRate)?
Ich *glaube* nicht. Ich habe ihn auf Basis der Sample Rate ausgesucht. Das ist so ein Abwägen zwischen Augenschmaus und Performance.
Bergmann89 hat geschrieben:
2: ich hab noch n paar Probleme mit dem Neuerzeugen des Fensters, weil ja das Pixelformat schon gesetzt wurde. Kann man das auch iwie anders lösen, wenn ja wie?
Soweit ich weiß, kann man das nicht anders lösen.
Bergmann89 hat geschrieben:
Ich hab das Neuerzeugen mit DestroyWnd und CreateWnd probiert und trotzdem gibt mir SetPixelFormat false zurück, wenn ich das AAPixelformat setzen will
Jetzt steh ich auf der Leitung. Sind das Delphi-Funktionen? Die Window-Erzeugungs-Funktion heißt "CreateWindowEx(A/W)".
Bergmann89 hat geschrieben:
Außerdem kann man die Sache dann nicht in eine unabhängige Unit auslagern, da man ja direkt auf Form1 zugreifen muss, weil die Methoden nicht public sind.
Warum? Das ist ja kein hochoffizielles Fenster, das man da erzeugt, sondern nur ein Probefensterchen, eine Totgeburt sozusagen. Dazu bestimmt, gleich wieder gelöscht zu werden. Das ist alles internes Zeugs und geht daher niemanden etwas an. Kein Mensch kriegt dieses Fenster je zu sehen. Ich mach das in meiner internen Prozedur "osGetPixelFormatInfo", und zwar BEVOR das endgültige Fenster erzeugt wird.
Ich hänge Dir in diesen Beitrag den Windows-Teil meiner OSSupport-Unit rein, da ist auch "osGetPixelFormatInfo" (in der OSSupportWin32.inc) drin, samt Fenstererzeugung. Ich habe zwar nicht viele Erklärungen dabei, aber wenn Du Dich schon ein bisschen eingelesen hast, sollte Dir das etwas sagen können. Die Prozeduren da drinnen sind nicht nach Alphabet sondern nach Funktionsbereichen sortiert (Initialize,Clock,...,RenderingContext,...Windows). Es ist eine einfache prozedurale Unit.
Den Code fürs Multisampling habe ich vor längerer Zeit stillgelegt, weil er mir beim Vergleich Linux/Windows ganz schöne Probleme bereitet hat: Ich dachte auf Grund der FPS, dass Windows langsamer ist als Linux; ich hatte längst vergessen, dass Windows mittels eingebautem Multisampling ein viel aufwendigeres Renderverfahren hat. Um daher immer einen guten Vergleich zu haben, ist der Code auf Eis gelegt.
Viele Grüße Traude
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
Registriert: Di Apr 29, 2008 18:56 Beiträge: 1213
Programmiersprache: Delphi/FPC
Hey,
hab noch gar ne daran gedacht mir ein extra Fenster zu erstellen. Ich hatte alles auf dem Fenster gemacht, was die Anwendung schon hat. Hab mir deinen Code auch grad ma kurz angeguckt und damit sollte das ganze kein Problem mehr sein. Ich guck mir das zu späterer Stunde nochma genauer an. Wenn ich dann fertig bin oder sich noch Fragen ergeben meld ich mich nochma.
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Du übergibst den Rückgabewert von der Funktion (diese hier meine ich) direkt an SetPixelFormat. Als allererstes. Das erzeugen eines temporären Fensters etc. wird von der Funktion erledigt. So setzt du gleich einen Multisample-Kontext, wenn du einen bekommen kannst.
greetings
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Registriert: Di Apr 29, 2008 18:56 Beiträge: 1213
Programmiersprache: Delphi/FPC
Hey,
die Funktion hab ich noch gar nich gesehen^^ aber ich hab mir schon selbst eine gebastelt, es war nur das Problem, das Fenster zu erzeugen, aber das hab ich jetzt genau wie du einfach mit ner TForm gemacht. Hier die Resultate:
Code:
//Kapselt die Daten für einen RenderContext TgluRenderContext = packed record DC: HDC; RC: HGLRC; Handle: HWND; end;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //ermittelt die SampleRate des MultiSampling eines PixelFormats //@PixelFormat: PixelFormat, dessen SampleRate ermittelt werden soll; //@result: SampleRate des PixelFormats (wenn 0 wird kein MultiSampling unterstüzt); function gluGetSampleRate(const PixelFormat: Integer): Integer; var Form: TForm; QueryAtrib, ResultAtrib, PF: Integer; multiARBSup, multiEXTSup: Boolean; RC: TgluRenderContext; procedure FreeAll; begin gluFreeRenderContext(RC); Form.Free; end; begin result := 0; Form := TForm.Create(nil); try PF := gluGetPixelFormat(Form.Handle, [opDoubleBuffered], 32, 24, 0, 0, 0, 0); RC := gluCreateRenderContext(Form.Handle, PF); except FreeAll; exit; end;
if not wglMakeCurrent(RC.DC, RC.RC) then begin FreeAll; exit; end; ReadImplementationProperties; ReadExtensions;
multiARBSup := false; multiEXTSup := false; if WGL_ARB_extensions_string and WGL_ARB_pixel_format and (WGL_ARB_MULTISAMPLE or GL_ARB_MULTISAMPLE) then multiARBSup := true; if WGL_EXT_extensions_string and WGL_EXT_pixel_format and (WGL_EXT_MULTISAMPLE or GL_EXT_MULTISAMPLE) then multiEXTSup := true; if not (multiARBSup or multiEXTSup) then begin FreeAll; exit; end; if multiARBSup then Read_WGL_ARB_pixel_format else if multiEXTSup then Read_WGL_EXT_pixel_format; QueryAtrib := WGL_SAMPLES_ARB; ResultAtrib := 0; if multiARBSup then wglGetPixelFormatAttribivARB(RC.DC, PixelFormat, 0, 1, @QueryAtrib, @ResultAtrib) else if multiARBSup then wglGetPixelFormatAttribivEXT(RC.DC, PixelFormat, 0, 1, @QueryAtrib, @ResultAtrib); result := ResultAtrib;
FreeAll; end;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //ermittelt ein passendes Pixelformat //@Handle: Handle des Objekts, dür das das Pixelformat bestimmt werden soll; //@Options: opDoubleBuffered, opGDI oder opStereo; //@ColorBits: Anzahl der Bits zu Darstellung der Farbe; //@DepthBits: Anzahl der Bits für den TiefenBuffer; //@StencilBits: Anzahl der Bits für den StencilBuffer; //@AccumBits: Anzahl der Bits für den AccumBuffer; //@AuxBuffers: Anzahl der Bits für den AuxBuffer; function gluGetPixelFormat(const Handle: HWND; const Options: TRCOptions; const ColorBits, DepthBits, StencilBits, AccumBits, AuxBuffers, Layer: Integer): Integer; const MemoryDCs = [OBJ_MEMDC, OBJ_METADC, OBJ_ENHMETADC]; var //DeviceContext DC: HDC; //Objekttyp des DCs AType: DWord; //Beschreibung zum passenden Pixelformat PFDescriptor: TPixelFormatDescriptor; begin DC := GetDC(Handle); if DC = 0 then raise Exception.Create('gluGetPixelFormat: Getting Device Context failed!'); with PFDescriptor do begin nSize := SizeOf(PFDescriptor); nVersion := 1; dwFlags := PFD_SUPPORT_OPENGL; AType := GetObjectType(DC); if AType = 0 then raise Exception.Create('gluGetPixelFormat: Getting Object Type failed!'); if opDoubleBuffered in Options then dwFlags := dwFlags or PFD_DOUBLEBUFFER; if opGDI in Options then dwFlags := dwFlags or PFD_SUPPORT_GDI; if opStereo in Options then dwFlags := dwFlags or PFD_STEREO; if AType in MemoryDCs then dwFlags := dwFlags or PFD_DRAW_TO_BITMAP else dwFlags := dwFlags or PFD_DRAW_TO_WINDOW;
if Layer = 0 then iLayerType := PFD_MAIN_PLANE else if Layer > 0 then iLayerType := PFD_OVERLAY_PLANE else iLayerType := Byte(PFD_UNDERLAY_PLANE); end; result := ChoosePixelFormat(DC, @PFDescriptor); end;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //ermittelt alle möglichen PixelForamte, die AntiAliasing unterstützen und fügt sie zur Liste hinzu //@List: Liste in die die Samplerates geschrieben werden; procedure gluGetAntiAliasingPixelFormats(const List: Pointer; const MaxCount: Integer); var //temporäres Fenster zum erzeugen des RC Form: TForm; //ARB_Erweiterung vorhanden //| EXT_Erweiterung vorhanden MultiARBSup, MultiEXTSup: Boolean; //Liste der Integer Attribute IAtrib: array[0..18] of Integer; //Liste der Float Attribute (nur 0, da kein Wert) FAtrib: GLFloat; //temp. PixelFormat //| Nummer der ausgelesenen PixelFormate mit AntiAliasing PF, numPFs: Integer; //temp. RenderKontext RC: TgluRenderContext;
//gibt die benutzen Variablen/Objekte frei procedure FreeAll; begin gluFreeRenderContext(RC); Form.Free; end; begin //temp. Fenster und RenderContext erstellen Form := TForm.Create(nil); try PF := gluGetPixelFormat(Form.Handle, [opDoubleBuffered], 32, 24, 0, 0, 0, 0); RC := gluCreateRenderContext(Form.Handle, PF); except FreeAll; raise Exception.Create('gluAntiAliasingPixelFormats: Create Rendering Context failed!'); end; if not wglMakeCurrent(RC.DC, RC.RC) then begin FreeAll; raise Exception.Create('gluAntiAliasingPixelFormats: Activating Rendering Context failed!'); end; ReadImplementationProperties; ReadExtensions;
//Pixelformate mit AA auslesen MultiARBSup := false; MultiEXTSup := false; if WGL_ARB_extensions_string and WGL_ARB_pixel_format and (WGL_ARB_MULTISAMPLE or GL_ARB_MULTISAMPLE) then multiARBSup := true; if WGL_EXT_extensions_string and WGL_EXT_pixel_format and (WGL_EXT_MULTISAMPLE or GL_EXT_MULTISAMPLE) then multiEXTSup := true;
if multiARBSup then Read_WGL_ARB_pixel_format else if multiEXTSup then Read_WGL_EXT_pixel_format;
FAtrib := 0; if not (MultiARBSup or MultiEXTSup) then begin FreeAll; raise Exception.Create('gluAntiAliasingPixelFormats: AntiAliasing is not supported!'); end;
if multiARBSup then wglChoosePixelFormatARB(RC.DC, @IAtrib, @FAtrib, MaxCount, List, @numPFs) else if multiEXTSup then wglChoosePixelFormatEXT(RC.DC, @IAtrib, @FAtrib, MaxCount, List, @numPFs); if numPFs = 0 then begin FreeAll; raise Exception.Create('gluAntiAliasingPixelFormats: No PixelFormat Found!'); end;
FreeAll; end;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //erstellt einen RenderContext mit dem übergebenen PixelFormat. Wenn das angegebene //AntiAliasing Pixelformat nicht unterstützt wird der 0 ist, erfolgt automatisch //ein FallBack auf das normale PixelFormat //@Handle: Handle für das der RenderContext erzeugt werden soll; //@PixelFormat: FallBack-PixelFormat falls AAPixelFormat 0 oder nicht gültig; //@AAPixelFormat: Pixelformat mit aktiviertem AntiAliasing; //@result: Device- und erzeugter RenderContext, für das übergebene Handle; function gluCreateRenderContext(const Handle: HWND; const PixelFormat: Integer): TgluRenderContext; begin result.DC := 0; result.RC := 0; result.Handle := 0;
if GL_LibHandle = nil then if not InitOpenGL then raise Exception.Create('gluCreateRenderContext: Initializing OpenGL failed!');
if PixelFormat = 0 then raise Exception.Create('gluCreateRenderContext: Unknown Pixelformat (' + IntToStr(PixelFormat) + ')');
result.Handle := Handle; result.DC := GetDC(Handle); if result.DC = 0 then raise Exception.Create('gluCreateRenderContext: Getting Device Context failed!'); if not SetPixelFormat(result.DC, PixelFormat, nil) then begin ReleaseDC(result.Handle, result.DC); raise Exception.Create('gluCreateRenderContext: Setting Pixelformat failed!'); end;
result.RC := wglCreateContext(result.DC); if result.RC = 0 then begin ReleaseDC(result.Handle, result.DC); raise Exception.Create('gluCreateRenderContext: Creating Rendering Context faild!'); end; end;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //gibt den RenderContext frei //@RC: RenderContext der freigegeben werden soll; procedure gluFreeRenderContext(RC: TgluRenderContext); begin try DeactivateRenderingContext; except end; if RC.RC <> 0 then DestroyRenderingContext(RC.RC); if RC.DC <> 0 then ReleaseDC(RC.Handle, RC.DC); end;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TForm1.CreateRenderContext; var PF: Integer; AAList: array[0..15] of Integer;
function GetAAPixelFormat(const SampleRate: Byte): Integer; var i: Integer; begin result := 0; for i := 0 to 15 do begin if SampleRate = gluGetSampleRate(AAList[i]) then begin result := AAList[i]; exit; end; end; end;
Is auch nochma als Datei im Anhang. Sin aber noch paar andere Sachen dabei, neben dem AntiAliasing. Wenn der Code so in Ordnung is, un niemand Verbesserungsvorschläge hat würd ich den dann so ins Wiki stellen...
MfG Bergmann
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
Mitglieder in diesem Forum: 0 Mitglieder und 6 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.