OpenGL: Render2Texture
Übersicht

![]() |
Fetze |
![]() Antworten mit Zitat ![]() |
---|---|---|
Mir einer Kombination aus deinem Beispiel und diesem Dokument habe ich mich nun mal dran versucht.. aber ich erhalte ab der Zeile mit dem Befehl immer einen "FRAMEBUFFER_UNSUPPORTED_EXT"-Status.. woraus ich schlussfolgere, dass da mit meiner Textur etwas nicht stimmt.
Da ich das ganze in C# ausprobiere und nicht in BlitzMax (Ja, ich bin mir im Klaren darüber, dass das hier der BLitzMax-Bereich ist - aber hier geht es ja schließlich auch um OpenGL, oder? Und genau darauf bezieht sich ja meine Fragestellung.), musste ich die Textur selbst initialisieren, vielleicht liegt dort das Problem. Hier mal ein paar Zeilen (gekürzter, auf OpenGL beschränkter, aber nach Ablauf geordneter) Code: Code: [AUSKLAPPEN] Gl.glGenTextures(1, out this.textureID); <...> <Hier erstelle ich den Frame- udn Renderbuffer> int oglWidth; int oglHeight; GetOGLTexSize(this.width, this.height, out oglWidth, out oglHeight); Gl.glGenFramebuffersEXT(1, out this.framebufferID); Gl.glGenRenderbuffersEXT(1, out this.renderbufferID); Gl.glBindTexture(Gl.GL_TEXTURE_2D, this.textureID); Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGBA, oglWidth, oglHeight, 0, Gl.GL_RGBA, Gl.GL_UNSIGNED_INT, null); Gl.glBindFramebufferEXT(Gl.GL_FRAMEBUFFER_EXT, this.framebufferID); Gl.glFramebufferTexture2DEXT(Gl.GL_FRAMEBUFFER_EXT, Gl.GL_COLOR_ATTACHMENT0_EXT, Gl.GL_TEXTURE_2D, this.textureID, 0); Gl.glBindRenderbufferEXT(Gl.GL_RENDERBUFFER_EXT, this.renderbufferID); Gl.glRenderbufferStorageEXT(Gl.GL_RENDERBUFFER_EXT, Gl.GL_DEPTH_COMPONENT24, oglWidth, oglHeight); Gl.glFramebufferRenderbufferEXT(Gl.GL_FRAMEBUFFER_EXT, Gl.GL_DEPTH_ATTACHMENT_EXT, Gl.GL_RENDERBUFFER_EXT, this.renderbufferID); Gl.glBindFramebufferEXT(Gl.GL_FRAMEBUFFER_EXT, 0); Gl.glBindTexture(Gl.GL_TEXTURE_2D, 0); <...> <Hier "bind"e ich ihn> Gl.glBindFramebufferEXT(Gl.GL_FRAMEBUFFER_EXT, this.framebufferID); <...> <Hier "unbind"e ich ihn> Gl.glBindFramebufferEXT(Gl.GL_FRAMEBUFFER_EXT, 0); Es ist klar, dass ich mit "FRAMEBUFFER_UNSUPPORTED_EXT"-Status keinen Gebrauch vom Framebuffer machen kann.. aber wieso kriege ichdiesen Fehler überhaupt? Das Texturformat aus Gl.glTexImage2D habe ich erfolgreich im GrabImage-Ansatz getestet, daran wirds also wohl eher nicht liegen.. was sind weitere mögliche Fehlerquellen? |
||
![]() |
Fetze |
![]() Antworten mit Zitat ![]() |
---|---|---|
So, ich habs jetzt doch zum Laufen bekommen - muss mir mal eienr sagen, dass die Textur vorher eindeutige Filterzuweiseungen für MIN und MAG braucht ![]() Wie dem auch sei: Jetzt gibts ein Problem mit den MipMaps, die nämlich nur Datensalat ergeben (wahllos weisse Pixel über die Textur verstreut? Aber auch das nur manchmal), wenn ich sie per "Gl.glGenerateMipmapEXT(Gl.GL_TEXTURE_2D);" generieren lassen will. So wie ich das verstanden habe, muss ich den Befehl nur einmal bei der Texturdefinition aufrufen? Oder muss er genau dann aufgerufen werden, wenn die Mimaps erzeugt werden sollen? Ein weiteres Problem, das ich bisher umgangen habe, ist, dass meine Einstellungen für glOrtho plötzlich "weg" sind, oder wenigstens teilweise ignoriert. Wenn ich zuvor die Koordinate [X,Y] hatte, muss ich im Framebuffer für dieselbe (relativ zur oberen linken Ecke gemessenen) Position [X,Y-Windowsize.y+Textur.h] angeben. Ergo: Ich muss meine Ortho umstellen, damit ich bei [X,Y] bleiben kann, was aber wiederum insofern müll ist, dass mein SetOrtho-Befehl innerhalb der Textur nur noch dann funktioniert, wenn man die entsprechende Verschiebung bei den Parametern berücksichtigt. Kann ich da OpenGL-Seitig irgendwas tun? |
||
Dreamora |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Resetest du die Transformationen während du drin bist? Sprich erst aktuelle Transformationen speichern (pushen) und dann die Transformationen resetten indem du die Identität lädst?
Bin mir net sicher ob du FBOs mipmappen kannst, RenderTargets sind davon meist auch nicht so Fans |
||
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen. |
![]() |
Fetze |
![]() Antworten mit Zitat ![]() |
---|---|---|
Nun, die Transformationen setze ich einmal bei der Initialisierung des Grafikframeworks - danach lasse ich die Finger davon. Muss ich die im Framebuffer nochmal neu setzen? Was genau muss ich neu setzen, was wird übernommen?
Wegen den Mipmaps: Das sollte an sich schon gehen - dieser Befehl wird extra vom NVidia-Paper empfohlen, das zum Release der FBO-Extension herausgegeben wurde. Insofern sollte die Textur MipMap-Fähig sein. Ist ja an sich auch eine Textur wie jede andere auch, denke ich. |
||
![]() |
Fetze |
![]() Antworten mit Zitat ![]() |
---|---|---|
So, beide Probleme gelöst. Das Transformationsproblem habe ich nun mit einem "glPushMatrix + glTransform" bei "SetBuffer" und einem "glPopMatrix" bei "SetBuffer(null)" gelöst.. danke Dreamora für deinen Hinweis, hatte da irgendwie ei nBrett vorm Kopf ![]() Was das Mipmapping betrifft: Habe herausgefunden, dass ich diesen MipMap-Befehl sowohl einmal bei der Texturkonfiguration bei merstellen des FBO aufrufen muss als auch jedesmal, wenn die MipMap tatsächlich generiert werden soll. Also automatisch bei "SetBuffer(null)". Muss aber alle nachahmer warnen, diese automatische MipMap-Generierung frisst übelst an der performance.. nichts für Echtzeitrenderings! (Von 100 FPS - da liefen noch einige Demosachen im Hintergrund, ohne Render2Texture mit FBO sind es vllt 5 FPS mehr - auf 30!) |
||
Dreamora |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Die MipMap Generierung ist der Grund warum Textur laden in Blitz3D schon so lange ging ...
Würds auch nicht raten mit Echtzeit Update. Ist eigentlich auch nicht nötig. Es verbraucht mehr VRAM und das ohne dass es einen sinn macht. Denn wer FBO nutzen kann wird auch noch Aniso Filtering 2,4 oder 8 machen können ohne probleme |
||
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen. |
![]() |
Fetze |
![]() Antworten mit Zitat ![]() |
---|---|---|
Was ist denn Aniso-Filtering? | ||
Dreamora |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Anisotropes Filtering ist eine Texturfiltermethode welche auf allen einigermassen aktuellen Grafikkarten selbst auf höchster Stufe nahezu ohne Performanceverlust genutzt werden kann (bei meiner 8800GTS sinds auch auf 1680x1050 sinds << 1% Unterschied), das aber dafür sorgt, dass die Texturen nicht direkt so grausig verwaschen aussehen wie zb in Blitz3D | ||
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen. |
![]() |
Fetze |
![]() Antworten mit Zitat ![]() |
---|---|---|
AchSO. Anisotropische Filterung. Stand aufdem Schlauch ^^
Nun, abgesehen vom Mipmapping-Ersatz macht das bei einem 2D-Framework aber wohl eher keinen Sinn, oder? Nichtsdestotrotz: Muss ich das selbst implementieren oder kann ich das in OpenGL eifnach per Extension aktivieren? Dann könnte ich MipMapping vielleicht generell deaktivieren und hätte höhere Qualität bei niedrigerem Speicherbedarf. |
||
![]() |
Fetze |
![]() Antworten mit Zitat ![]() |
---|---|---|
Okay, hat sich erledigt - das ist wohl mit die am einfachsten zu verwendende OpenGL-Extension auf Welt:
http://steinsoft.net/index.php...cfiltering Fertig. Und funktioniert sogar direkt! Muss aber sagen, im rein zweidimensionalen Bereich kommt Mipmapping manchmal besser, weil es bei - um ein Beispiel zu nennen - ein Pixel breiten Linien auf der gedrehten und verkleinerten Textur einfach doch manchmal besser aussieht, wenn die Textur ein wenig verwaschen ist. |
||
Dreamora |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Wenn du es verkleinerst stimmt das natürlich im reinen 2D Sektor.
Aber im reinen 2D Sektor würd ich auch nicht umbedingt mit FBO auffahren sondern mit pBuffern, rein weil FBO doch eine höhere Funktionalität sind die bei "2D Liebhabern" nicht umbedingt vorhanden sind oder effizient genug arbeiten. Denn du kannst nicht wie mit SetBuffer auf unzähligen Texturen rumholzen jedes Frame wie unter B3D, sonst geht die Performance an den Render Surface Switches zugrunde. |
||
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen. |
![]() |
Fetze |
![]() Antworten mit Zitat ![]() |
---|---|---|
Naja, sagen wir's so: Ich hab mir das NVidia-Paper angesehen udn der dort vorhandene Direktvergleich zwischen FBO und pBuffer hat mich überzeugt, dass das ganze auch für den 2D-Bereich sinnvoll ist. | ||
Dreamora |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
ja, wenn du es auf ATI und NVIDIA user beschränken willst schon.
In den Papern von ATI und NVIDIA stehen viele coole Dinge. Die haben aber immer 2 Probleme: 1. Häufig gelten sie nur für den macher von dem sie kommen. ATI oder NVIDIA 2. So gut wie nie gelten sie für den grossteil aller user, nämlich die, die garkein ATI und NVIDIA haben und das sind 60%+ aller Systeme |
||
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen. |
![]() |
Fetze |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ach, es gibt sicherlich genug "große" Spiele, die sowas nutzen und bei denen hat sich auch niemand beschwert - also warum dann wegen einem belanglosen kleinen 2D-Spielchen einen Aufstand machen? ^^
Solange es nicht "gar nicht" läuft, sollte das kein allzu riesiges Problem sein - schneller als die GrabImageFast-methodik ist es allemal und selbst die lässt sich in begrenztem Maß auch noch in Echtzeit einsetzen. |
||
![]() |
mahe |
![]() Antworten mit Zitat ![]() |
---|---|---|
Wahrscheinlich spielen von diesem 60%+ Nichtgrafikkartenbesitzer 90% eh nur Solitaire.
Die wenigsten davon werden sich grafisch aufwendige Spiele herunterladen. |
||
ʇɹǝıdɯnɹɹoʞ ɹnʇɐuƃıs - ǝpoɥʇǝɯ-ɹoɹɹıɯ ɹǝp uı ,ɹoɹɹǝ, |
![]() |
Fetze |
![]() Antworten mit Zitat ![]() |
---|---|---|
So, da bin ich wieder und ich habe ein Problem mitgebracht. Die Framebuffer habe ich ja nun zum Laufen bekommen, so weit so gut. Allerdings habe ich festgestellt, dass es bei Framebufferobjekten üblich zu sein scheint, grundsätzlich deckend zu zeichnen.. das Blending funktioniert vorne und hinten nicht. Hier, ein Beispiel aufbauend auf dem Code von klepto2:
Code: [AUSKLAPPEN] SuperStrict Type TKLGUI Global Container:TList = New TList Function RegisterITEM(Item:TKLITEM) TKLGUI.Container.Addlast(Item) End Function Function Sort() End Function Function Update() End Function End Type Type TKLITEM Abstract End Type Type TKLEVENT End Type Type TImageBuffer Field Image:TImage Field rb:Int[1] Field fb:Int[1] Field Imageframe:TGLImageframe Field Frame:Int = 0 Field OrigX:Int Field OrigY:Int Field OrigW:Int Field OrigH:Int Function SetBuffer:TImageBuffer(Image:TImage,Frame:Int = 0 ) Local IB:TImageBuffer = New TImageBuffer IB.Image = Image IB.Frame = Frame IB.GenerateFBO() IB.BindBuffer() Return IB End Function Method GenerateFBO() ImageFrame = TGLImageFrame(Image.frame(Frame) ) imageframe.v0 = imageframe.v1 imageframe.v1 = 0.0 Local W:Int = Image.width Local H:Int = Image.Height AdjustTexSize(W , H) glGenFramebuffersEXT(1, fb ) glGenRenderbuffersEXT(1 , rb) glBindTexture(GL_TEXTURE_2D, Imageframe.name); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , fb[0]) ; ' 'glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, W, H, 0, GL_RGBA, GL_UNSIGNED_INT, Null); 'glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); 'glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); ' glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, Imageframe.name, 0); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rb[0]); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, W, H); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT , GL_DEPTH_ATTACHMENT_EXT , GL_RENDERBUFFER_EXT , rb[0]) Local status:Int = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) Select status Case GL_FRAMEBUFFER_COMPLETE_EXT DebugLog ("all right" + " : " + Status) Case GL_FRAMEBUFFER_UNSUPPORTED_EXT DebugLog ("choose different formats") Default DebugLog status End EndSelect End Method Method BindBuffer(Fullscreen:Byte = False) GetViewport(OrigX,OrigY,OrigW,OrigH) glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , fb[0]) 'If Fullscreen = True Then 'glViewport(0 , 0 , -Image.Width , -Image.Height) ; 'EndIf glViewport(0 , 0 , Image.Width , Image.Height) 'SetScale 1,-1 'SetOrigin 0 , Float(Image.Height) * (GraphicsHeight() / 600.0) 'Print (Image.Height * (GraphicsHeight()/600.0)) End Method Method UnBindBuffer() glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , 0) glViewport(OrigX , OrigY , OrigW , OrigH) SetOrigin 0 , 0 SetScale 1,1 End Method Method Cls() glClearColor 0.0,0.0,0.0,0.0 glClear GL_COLOR_BUFFER_BIT End Method End Type Function AdjustTexSize( width:Int Var,height:Int Var ) 'calc texture size width=Pow2Size( width ) height=Pow2Size( height ) Repeat Local t:Int glTexImage2D GL_PROXY_TEXTURE_2D,0,4,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,Null glGetTexLevelParameteriv GL_PROXY_TEXTURE_2D,0,GL_TEXTURE_WIDTH,Varptr t If t Return If width=1 And height=1 RuntimeError "Unable to calculate tex size" If width>1 width:/2 If height>1 height:/2 Forever End Function Function Pow2Size:Int( n:Int ) Local t:Int=1 While t<n t:*2 Wend Return t End Function SetGraphicsDriver GLMax2DDriver() Graphics 800 , 600 , 0, - 1 glewinit() Global iFPSCounter:Int Global iFPSLastCheck:Int Global iFPS:Int Global TextImg:TImage = LoadImage("Charset1.png") SetMaskColor 255,0,255 Global Img:TImage = CreateImage(400, 300) Local IB:TImageBuffer = TImageBuffer.SetBuffer(Img) Local x:Float = 0 Local Speed:Float = 0.01 Local OX:Float = 200 Local OY:Float = 150 UpdateImage(IB,OX,OY) While Not KeyHit(Key_Escape) SetClsColor 0 , 0 , 255 Cls SetColor 255,255,255 DrawRect 256,256,256,256 SetBlend ALPHABLEND SetAlpha 1.0 SetColor 255,255,255 SetRotation 360 * Sin(X/10.0) DrawImage Img , 200 + X ,150 SetRotation 0 SetAlpha 1.0 x:+ Speed If x > 800 -400 Then Speed = - 0.01 If x < 0 Then Speed = 0.01 If KeyDown(KEY_RIGHT) OX:+0.1 UpdateImage(IB , OX , OY) EndIf If KeyDown(KEY_LEFT) OX:-0.1 UpdateImage(IB , OX , OY) EndIf If KeyDown(KEY_UP) OY:-0.1 UpdateImage(IB , OX , OY) EndIf If KeyDown(KEY_DOWN) OY:+0.1 UpdateImage(IB , OX , OY) EndIf CalcFPS() DrawText OX + " : " + OY ,20,20 DrawText iFPS ,20,30 Flip Wend Function CalcFPS:Byte() iFPSCounter:+1 If iFPSLastCheck = 0 Then iFPSLastCheck = MilliSecs() If (MilliSecs() - iFPSLastCheck) >= 1000 Then iFPS = iFPSCounter iFPSCounter = 0 iFPSLastCheck = MilliSecs() End If Return True End Function Function UpdateImage(IB:TImageBuffer , X:Float , Y:Float) IB.BindBuffer() IB.Cls() SetLineWidth 4 DrawLine 0 , 0 , 800 , 0 DrawLine 798 , 0 , 798 , 600 DrawLine 800 , 598 , 0 , 598 DrawLine 0 , 600 , 0 , 0 SetColor 255, 0 , 0 SetScale 5,5 DrawText "Hello World" , GraphicsWidth()/2-(TextWidth("Hello World")*5)/2 , GraphicsHeight()/2 SetScale 1,1 DrawOval X , Y , 20 , 20 SetColor 255 , 255 , 255 SetBlend ALPHABLEND SetAlpha 1.0 DrawRect 600, 50, 100, 100 SetAlpha 0.5 DrawRect 620, 70, 40, 40 IB.UnBindBuffer() End Function Die Sache ist die: Ich zeichne ein weißes Rechteck in den Framebuffer, ohne Transparenz. Dann zeichne ich darüber - chronologisch danach ohne jegliche Z-Buffer-Verwendung ein mit 50% Alphageblendetes weißes Rechteck darüber. Was passiert? Es wird einfach draufgezeichnet als wäre SolidBlend aktiv gewesen. Zu allem Überfluss wird sogar der neue Alphawert einfach übernommen, sodass ich nun eine halbtransparente Lücke im zuvor völlig soliden weißen Rechteck habe. Was soll das denn nun? oO Das mag ja hin und wieder mal ganz nützlich sein, aber es beraubt die FBO's dem Großteil ihres Nutzens. Ein weiteres Problem, die beiden werden wohl zusammenhängen: Anders als im Backbuffer wird die Farbe von halbtransparenten Pixeln nicht entsprechend geändert, wenn man eine Textur zeichnet. Angenommen, ich habe einen Buchstaben mit stellenweise halbtransparentem Rand. Zeichne ich diese direkt auf den Backbuffer wird korrekt geblendet und ich habe kein Problem. Zeichne ich diese jedoch auf einen FBO, dann nehmen die halbtransparenten Randpixel die Hintergrundfarbe / ClearColor des FBOs an anstatt die in der Textur definierte Farbe zu behalten. Ebenso dämlich, weil so all meine BitmapFonts einen ekligen Rand bekommen, sobald ich sie auf eine Textur rendere. Ganz zu schweigen davon, dass zuvor ausgefüllte Pixel am Rand der einzelnen Buchstaben wieder halbtransparent werden. ![]() Was kann ich tun? |
||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group