| Autor |
Beitrag |
Simon Joker
      
Beiträge: 236
Erhaltene Danke: 1
|
Verfasst: Mo 11.08.03 11:20
Hi Leute
ich habe ein Problem mit transparenten Flächen, die sich gegenseitig durchdringen. Dabei kommt es zu unschönen Fragmenten, durch den ZBuffer der Flächen.
Hat jemand eine Idee wie ich das beseitigen kann?
Danke
|
|
Logiqu
      
Beiträge: 43
Win XP
Delphi 2006 Pro
|
Verfasst: Mo 11.08.03 15:08
wenn alle objekte transparent sind, kannst du den zbuffer abschalten:glDisable(GL_DEPTH_TEST)
du musst aber aufpassen, wann du den test einsetzt und wann nicht. eine weitere lösung wäre, die objekte von hinten nach vorn zu rendern (die hinteren zuerst und die vorderen zum schluss)
p.s.: das ist die lösung für reines opengl, ich weiß nicht, ob man das so auch bei glscene anwenden kann...
_________________ Logiqu. Just feel it...
|
|
Simon Joker 
      
Beiträge: 236
Erhaltene Danke: 1
|
Verfasst: Mo 11.08.03 15:37
Hi Logiqu
den Tiefentest ganz abschalten geht nicht, es sind nicht alle Objekte Transparent sondern nur die Effekte. Die Reihenfolge wird schon beachtet. Das Problem ist einfach, daß der Tiefentest auf die gesammte Fläche angewendet wird und nicht nur auf die wirklich sichtbaren Teile.
|
|
Aya
      
Beiträge: 1964
Erhaltene Danke: 15
MacOSX 10.6.7
Xcode / C++
|
Verfasst: Mo 11.08.03 19:41
Hi,
ich weiß net ob es bei GLScene auch so machbar ist.. aber bei einfachem OpenGL macht man es so:
Delphi-Quelltext 1: 2: 3:
| glDepthMask(False); glDepthMask(True); |
Au'revoir,
Aya~
_________________ Aya
I aim for my endless dreams and I know they will come true!
|
|
Simon Joker 
      
Beiträge: 236
Erhaltene Danke: 1
|
Verfasst: Di 12.08.03 10:34
Hi Aya
erstmal: Ja, es ist machbar! Nur leider bringt mich das nicht weiter. Das Ergebnis ist identisch mit dem Vorschlag von Logiqu.
ich wünsche mir aber ein solches Ergebnis (Fake mit zwei Objekten):
vieleicht ist es ja aber gar nicht machbar. 
|
|
Aya
      
Beiträge: 1964
Erhaltene Danke: 15
MacOSX 10.6.7
Xcode / C++
|
Verfasst: Di 12.08.03 15:10
*schaut verwirrt* Hä??
Erklär mal genauer was du vorhast und was genau nicht klappt.
Au'revoir,
Aya~
_________________ Aya
I aim for my endless dreams and I know they will come true!
|
|
Simon Joker 
      
Beiträge: 236
Erhaltene Danke: 1
|
Verfasst: Mi 13.08.03 11:53
Hi Aya
Das Ziel ist eigentlich recht primitiv.
Situation:
Das Programmmodul soll eine Raumschlacht für ein Strategiespiel werden. Die Scenen werden dynamisch generiert. Raumschiffmodelle, Skyboxes und Planeten werden geladen, verteilt und korrekt dargestellt. Soweit kein Problem. Für die Schlacht soll natürlich auch etwas Feuerwerk existieren! und diese Waffeneffekte sind der Hänger, den ich habe.
Problem:
Die reinen Waffeneffekte sind zumeist einfache Planes. Diese sind so prositioniert, das sie von der Waffe zum Ziel ausgerichtet sind. Dabei wird die Fläche zur Kamera orientiert.
Die Treffereffekte oder andere Waffen haben natürlich andere Ausrichtungen. Deshalb durchdringen sich die transparenten Flächen! und das ist der Kern des Problems siehe Bild 1. Schalte ich den ZBuffer ab oder verwende deine Vorschlag geht die Tiefenwirkung verloren bild 2.
Was ich erreichen will ist Bild 3 korrekt geblendete Objekte mit Tiefenwirkung.
Noch zur Erklärung: die beiden transparenten Objekte sind 30° gegeneinander gedreht und haben die selbe Position.
Ich hoffen ich habe Klarheiten beseitigt und Unklarheiten erzeugt oder so ähnlich. 
|
|
Aya
      
Beiträge: 1964
Erhaltene Danke: 15
MacOSX 10.6.7
Xcode / C++
|
Verfasst: Mi 13.08.03 12:56
*schaut leicht verwirrt*
So ganz kapiert hab ich's immernochnet wie das Bild oben denn nu wirklich aussehen soll... *schaut verlegen*
Aber nochmal als kleinen Tip... schalt den Tiefentest mal aus (so wie ich es sagte) und zeichne deine Transparenten dinge ganz zum schluss als aller letztes erst
Au'revoir,
Aya~
PS: Versuch doch mal nen Bild zu machen (mit GrafikProg oder sonstwas), wo du zeigst wie das aussehen soll 
_________________ Aya
I aim for my endless dreams and I know they will come true!
|
|
Logiqu
      
Beiträge: 43
Win XP
Delphi 2006 Pro
|
Verfasst: Mi 13.08.03 13:31
ganz abschalten geht nicht. aus folgendem grund: wenn erst alle soliden objekte gezeichnet werden und dann ein transparentes, welches zwischen zwei soliden liegt (alle objekte direkt hintereinander), so wird das transparente einfach gezeichnet, ohne dass geprüft wird, ob sich noch ein objekt davor befindet.
mein vorschlag: erst alle soliden objekte zeichnen, dann alle transparenten objekte von hinten nach vorn sortieren und dan die transparenten objekte zeichnen... ist ein bisschen rechenaufwendig bei vielen partikeln, aber zur zeit habe ich auch keinen besseren vorschlag
p.s.: alle transparenten objekte müssen so gerichtet werden, dass die camera immer senkrecht darauf schaut!
_________________ Logiqu. Just feel it...
|
|
Aya
      
Beiträge: 1964
Erhaltene Danke: 15
MacOSX 10.6.7
Xcode / C++
|
Verfasst: Mi 13.08.03 13:33
Hi,
du sollst ja nicht den kompletten Tiefentest abschalten, sondern nur das schreiben in den Tiefenbuffer!
Delphi-Quelltext 1: 2: 3:
| glDepthMask(False); glDepthMask(True); |
Das machst du ganz am ende, also nachdem du deine anderen Objekte zeichnest.. sollte eigentlich gehen..
Au'revoir,
Aya~
_________________ Aya
I aim for my endless dreams and I know they will come true!
|
|
Simon Joker 
      
Beiträge: 236
Erhaltene Danke: 1
|
Verfasst: Mi 13.08.03 14:25
Hi
zur Geometrie:
Die Anordnug der Objekte ist so:
Aussehen soll das Ergebnis wie Bild 3 (siehe oben), aber das ist ein Fake mit drei Objekten in der richtigen Reihenfolge.
Bei zwei objekten kommt es je nach Renderreihenfolge zu Fehlern wie in Bild 1.
Wenn ich das Schreiben in den ZBuffer abschalte ist der optische Eindruck der Geometrie zerstört. (rechte Seite des längeren Objekts muß über dem runden liegen!) Bild 2.
@Logiqu
Warum sollen alle transparenten Objekte senkrecht zur Kamera liegen? Sicher würde das das Problem beseitigen, aber dann wäre die ganze Sache sinnlos. Weil dann das 3D Eindruck weg wäre.
Es muß gehen, denn die Profi-Spiel-Programmieren schaffen es ja auch.
Dein Vorschlag mit der Tiefensortierung der Objekte für die Renderreihenfolge ist schon GLScene integriert. Solange sich die Objekte nicht überschneiden gibts auch kein Problem.
@Aya
Dein Vorschlag funktioniert, aber leider halt auf Kosten der geometrischen Korrektheit.
|
|
Aya
      
Beiträge: 1964
Erhaltene Danke: 15
MacOSX 10.6.7
Xcode / C++
|
Verfasst: Do 14.08.03 02:51
Hi,
also um es so zu machen wie du es auf dem Bild beschreibst, mußt du das schreiben in den DepthBuffer deaktivieren und das Transparente als allerletztes Zeichnen...
Dann ist das was hinter der wand ist nicht sichtbar...
Oder versteh ich das immernoch falsch???
Au'revoir,
Aya~
PS: Mach mal nen Screenshot von der Variante wie ich es vorschlage und zeige mal an diesem wie du es haben willst.
_________________ Aya
I aim for my endless dreams and I know they will come true!
|
|
Simon Joker 
      
Beiträge: 236
Erhaltene Danke: 1
|
Verfasst: Do 14.08.03 14:52
Hi Aya
ich habe jetzt nochmal eine Dummyscene gemacht. Diesmal mit echten Texturen und einer realen Ansicht.
Erstmal das Bild zum Problem:
So siehts aus wenn ich ganz normal rendere. Der blaue Laser ist hinter der Eplosionswolke positioniert. Alle Objekte sind transparent.
So siehts aus wenn ich das Schreiben in den ZBuffen abschalte.
Es ist nicht mehr zusehen, das sich die beiden Flächen schneiden.
Und so hätte ich es gern:
Leider ist das nur ein Fake mit 3 Objekten.
|
|
Aya
      
Beiträge: 1964
Erhaltene Danke: 15
MacOSX 10.6.7
Xcode / C++
|
Verfasst: Do 14.08.03 16:51
Hi,
zeig mal bitte den Source von Bild2..
Also wie du das da genau machst.. (wie/wann du den Laser zeichnest etc)
Au'revoir,
Aya~
_________________ Aya
I aim for my endless dreams and I know they will come true!
|
|
Simon Joker 
      
Beiträge: 236
Erhaltene Danke: 1
|
Verfasst: Fr 15.08.03 09:53
Hi Aya,
das mit dem Code ist etwas schwirig, da das ja alles Komponenten sind. Und diese natürlich jeweils ihre eigenen Methoden besitzen, um sich zu rendern.
Deshalb erstmal die Hierarschie der Objekte:
Alle Effekttransparenzen sind in einer Gruppe zusammengefasst:
Effects : TDummyCube
|_ Laser : TPlane
|_ Explosion : TSprite;
|_ -usw.-
Die Einstellung des DummyCubs sind so, daß die untergeordneten Objekte nach der Entfernung sortiert werden. Also FarestFirst.
TSprite und TPlane haben die Eigenschaft noZWrite. Bei TPlain habe ich die Eigenschaft selbst hinzugefügt, falls die jemand bei sich vermisst.
Die Renderprozedure vom TSprite:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45:
| procedure TSprite.BuildList(var rci : TRenderContextInfo); var vx, vy, vx1, vy1 : TAffineVector; i : Integer; w, h, c, s : Single; mat : TMatrix; begin if FAlphaChannel<>1 then SetGLMaterialAlphaChannel(GL_FRONT, FAlphaChannel); if NoZWrite then glDepthMask(False); glGetFloatv(GL_MODELVIEW_MATRIX, @mat); glBegin(GL_QUADS); w:=FWidth*0.5; h:=FHeight*0.5; vx[0]:=mat[0][0]; vy[0]:=mat[0][1]; vx[1]:=mat[1][0]; vy[1]:=mat[1][1]; vx[2]:=mat[2][0]; vy[2]:=mat[2][1]; ScaleVector(vx, w/VectorLength(vx)); ScaleVector(vy, h/VectorLength(vy)); if FRotation=0 then begin xglTexCoord2f(1, 1); glVertex3f( vx[0]+vy[0], vx[1]+vy[1], vx[2]+vy[2]); xglTexCoord2f(0, 1); glVertex3f(-vx[0]+vy[0],-vx[1]+vy[1],-vx[2]+vy[2]); xglTexCoord2f(0, 0); glVertex3f(-vx[0]-vy[0],-vx[1]-vy[1],-vx[2]-vy[2]); xglTexCoord2f(1, 0); glVertex3f( vx[0]-vy[0], vx[1]-vy[1], vx[2]-vy[2]); end else begin SinCos(FRotation*cPIdiv180, s, c); for i:=0 to 2 do begin vx1[i]:=vx[i]+vy[i]; vy1[i]:=vy[i]-vx[i]; end; xglTexCoord2f(1, 1); glVertex3f( c*vx1[0]+s*vy1[0], c*vx1[1]+s*vy1[1], c*vx1[2]+s*vy1[2]); xglTexCoord2f(0, 1); glVertex3f(-s*vx1[0]+c*vy1[0],-s*vx1[1]+c*vy1[1],-s*vx1[2]+c*vy1[2]); xglTexCoord2f(0, 0); glVertex3f(-c*vx1[0]-s*vy1[0],-c*vx1[1]-s*vy1[1],-c*vx1[2]-s*vy1[2]); xglTexCoord2f(1, 0); glVertex3f( s*vx1[0]-c*vy1[0], s*vx1[1]-c*vy1[1], s*vx1[2]-c*vy1[2]); end; glEnd; if NoZWrite then glDepthMask(True); end; |
und die vom TPlain:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74:
| procedure TPlane.BuildList(var rci : TRenderContextInfo); var hw, hh, posXFact, posYFact, pX, pY0, pY1 : TGLFloat; tx0, tx1, ty0, ty1, texSFact, texTFact : TGLFloat; texS, texT0, texT1 : TGLFloat; x, y : Integer; begin hw:=FWidth*0.5; hh:=FHeight*0.5; glNormal3fv(@ZVector); if psTileTexture in FStyle then begin tx0:=FXOffset; tx1:=FXTiles+FXOffset; ty0:=FYOffset; ty1:=FYTiles+FYOffset; end else begin tx0:=0; ty0:=tx0; tx1:=1; ty1:=tx1; end; if psSingleQuad in FStyle then begin if NoZWrite then glDepthMask(False); glBegin(GL_QUADS); xglTexCoord2f(tx1, ty1); glVertex2f( hw, hh); xglTexCoord2f(tx0, ty1); glVertex2f(-hw, hh); xglTexCoord2f(tx0, ty0); glVertex2f(-hw, -hh); xglTexCoord2f(tx1, ty0); glVertex2f( hw, -hh); glEnd; if NoZWrite then glDepthMask(true); end else begin texSFact:=(tx1-tx0)/FXTiles; texTFact:=(ty1-ty0)/FYTiles; posXFact:=FWidth/FXTiles; posYFact:=FHeight/FYTiles; texT0:=0; pY0:=-hh; for y:=0 to FYTiles-1 do begin texT1:=(y+1)*texTFact; pY1:=(y+1)*posYFact-hh; if NoZWrite then glDepthMask(False); glBegin(GL_TRIANGLE_STRIP); for x:=0 to FXTiles do begin texS:=tx0+x*texSFact; pX:=x*posXFact-hw; xglTexCoord2f(texS, texT1); glVertex2f(pX, pY1); xglTexCoord2f(texS, texT0); glVertex2f(pX, pY0); end; glEnd; if NoZWrite then glDepthMask(true); texT0:=texT1; pY0:=pY1; end; end; end; |
Die Render Reihenfolge habe ich überprüft. Die Sortiereung der Objekte verläuft auf die gewünschte Weise.
|
|
|