OpenGL: Render2Texture

Übersicht BlitzMax, BlitzMax NG Allgemein

Gehe zu Seite Zurück  1, 2

Neue Antwort erstellen

Fetze

BeitragSa, Okt 06, 2007 12:51
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragMo, Okt 08, 2007 19:33
Antworten mit Zitat
Benutzer-Profile anzeigen
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 Rolling Eyes

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

BeitragMo, Okt 08, 2007 19:42
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragMo, Okt 08, 2007 19:49
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragDi, Okt 09, 2007 12:36
Antworten mit Zitat
Benutzer-Profile anzeigen
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 Rolling Eyes

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

BeitragDi, Okt 09, 2007 12:50
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragDi, Okt 09, 2007 12:59
Antworten mit Zitat
Benutzer-Profile anzeigen
Was ist denn Aniso-Filtering?
 

Dreamora

BeitragDi, Okt 09, 2007 13:06
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragDi, Okt 09, 2007 13:08
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragDi, Okt 09, 2007 13:41
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragDi, Okt 09, 2007 14:40
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragDi, Okt 09, 2007 14:50
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragDi, Okt 09, 2007 15:40
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragDi, Okt 09, 2007 15:59
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragDi, Okt 09, 2007 16:04
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragMi, Okt 24, 2007 18:40
Antworten mit Zitat
Benutzer-Profile anzeigen
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. Evil or Very Mad

Was kann ich tun?

Gehe zu Seite Zurück  1, 2

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group