Autor Beitrag
Simon Joker
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 236
Erhaltene Danke: 1



BeitragVerfasst: 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.

user defined image

Hat jemand eine Idee wie ich das beseitigen kann?

Danke
Logiqu
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 43

Win XP
Delphi 2006 Pro
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 236
Erhaltene Danke: 1



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1964
Erhaltene Danke: 15

MacOSX 10.6.7
Xcode / C++
BeitragVerfasst: 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:

ausblenden Delphi-Quelltext
1:
2:
3:
  glDepthMask(False);
  //Transparente Objekte zeichnen
  glDepthMask(True);

Au'revoir,
Aya~

_________________
Aya
I aim for my endless dreams and I know they will come true!
Simon Joker Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 236
Erhaltene Danke: 1



BeitragVerfasst: 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.

user defined image

ich wünsche mir aber ein solches Ergebnis (Fake mit zwei Objekten):

user defined image

vieleicht ist es ja aber gar nicht machbar. :bawling:
Aya
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1964
Erhaltene Danke: 15

MacOSX 10.6.7
Xcode / C++
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 236
Erhaltene Danke: 1



BeitragVerfasst: Mi 13.08.03 11:53 
Hi Aya

Das Ziel ist eigentlich recht primitiv. :lol:

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. :wink:
Aya
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1964
Erhaltene Danke: 15

MacOSX 10.6.7
Xcode / C++
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 43

Win XP
Delphi 2006 Pro
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1964
Erhaltene Danke: 15

MacOSX 10.6.7
Xcode / C++
BeitragVerfasst: Mi 13.08.03 13:33 
Hi,

du sollst ja nicht den kompletten Tiefentest abschalten, sondern nur das schreiben in den Tiefenbuffer! :)

ausblenden Delphi-Quelltext
1:
2:
3:
  glDepthMask(False); 
  //Transparente Objekte zeichnen 
  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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 236
Erhaltene Danke: 1



BeitragVerfasst: Mi 13.08.03 14:25 
Hi

zur Geometrie:

Die Anordnug der Objekte ist so:
user defined image

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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1964
Erhaltene Danke: 15

MacOSX 10.6.7
Xcode / C++
BeitragVerfasst: 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??? :roll:

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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 236
Erhaltene Danke: 1



BeitragVerfasst: 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:
user defined image
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.
user defined image
Es ist nicht mehr zusehen, das sich die beiden Flächen schneiden.

Und so hätte ich es gern:
user defined image
Leider ist das nur ein Fake mit 3 Objekten.
Aya
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1964
Erhaltene Danke: 15

MacOSX 10.6.7
Xcode / C++
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 236
Erhaltene Danke: 1



BeitragVerfasst: 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:

ausblenden volle Höhe Delphi-Quelltext
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);
    // extraction of the "vecteurs directeurs de la matrice"
    // (dunno how they are named in english)
      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
         // no rotation, use fast, direct projection
       xglTexCoord2f(11);  glVertex3f( vx[0]+vy[0], vx[1]+vy[1], vx[2]+vy[2]);
       xglTexCoord2f(01);  glVertex3f(-vx[0]+vy[0],-vx[1]+vy[1],-vx[2]+vy[2]);
       xglTexCoord2f(00);  glVertex3f(-vx[0]-vy[0],-vx[1]-vy[1],-vx[2]-vy[2]);
       xglTexCoord2f(10);  glVertex3f( vx[0]-vy[0], vx[1]-vy[1], vx[2]-vy[2]);
      end else begin
         // we need to compose main vectors...
         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;
         // ...and apply rotation... way slower
       xglTexCoord2f(11);  glVertex3f( c*vx1[0]+s*vy1[0], c*vx1[1]+s*vy1[1], c*vx1[2]+s*vy1[2]);
       xglTexCoord2f(01);  glVertex3f(-s*vx1[0]+c*vy1[0],-s*vx1[1]+c*vy1[1],-s*vx1[2]+c*vy1[2]);
       xglTexCoord2f(00);  glVertex3f(-c*vx1[0]-s*vy1[0],-c*vx1[1]-s*vy1[1],-c*vx1[2]-s*vy1[2]);
       xglTexCoord2f(10);  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:

ausblenden volle Höhe Delphi-Quelltext
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);
   // determine tex coords extents
   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
      // single quad plane
      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
      // multi-quad plane (actually built from tri-strips)
      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.