Entwickler-Ecke

Multimedia / Grafik - Texturen verblassen, ausblenden


Gausi - Sa 01.05.10 11:21
Titel: Texturen verblassen, ausblenden
Ich geb ja zu, dass ich von OpenGL praktisch keine Ahnung habe. Für meinen Coverflow nutze ich eine Unit "unitFlyingCow", die auf dglOpenGL aufsetzt. Ein paar Punkte habe ich da schon anpassen können, aber hier komme ich nicht weiter.

Was ich rausgefunden habe ist, dass mit glClearColor(0.00.00.00.0); die "Löschfarbe" eingestellt wird. Da ich nur lose Objekte im Raum zeichne, ist das quasi die Farbe meines Raumes, hier also schwarz. Die möchte ich gerne variabel gestalten, z.B. clBtnFace statt schwarz. Eigentlich kein Problem.

Dann bekomme ich aber bei den Objekten selbst Probleme. Die render-Methode sieht (gekürzt) so aus:

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:
procedure TRenderThread.RenderPass;
var
  modelMatrix, projMatrix : TGLMatrixd4;
  viewport : TGLVectori4;
  i : Integer;
  w, h : Single;
begin
    glGetDoublev (GL_MODELVIEW_MATRIX, @modelMatrix);
    glGetDoublev (GL_PROJECTION_MATRIX, @projMatrix);
    glGetIntegerv (GL_VIEWPORT, @viewport);
    For i := 0 To High(fItem) do
    begin
        // Item preview
        glEnable (GL_TEXTURE_2D);
        glBindTexture (GL_TEXTURE_2D, fItem[i].texture.handle);
       
        w := fItem[i].texture.w;
        h := fItem[i].texture.h;
        
        // for transparent Object
        glEnable (GL_BLEND);

        // reflexion 
        // Items, die weiter außen liegen, werden hierdurch dunkler 
        glColor3f (0.85-Abs(fItem[i].x)/7.0*1.5,
                   0.85-Abs(fItem[i].x)/7.0*1.5,
                   0.85-Abs(fItem[i].x)/7.0*1.5);

        glBegin (GL_QUADS);
          glTexCoord2f (fItem[i].texture.su, fItem[i].texture.tv);
          glVertex3f (fItem[i].x-w*Cos(fItem[i].r), -0.75-h*2, -w*Sin(fItem[i].r)-w+Abs(w*Sin(fItem[i].r))-2.0+3.0*fItem[i].z);
          // weitere Koordinaten
        glEnd;

        // item itsself
        glColor3f (1.0-Abs(fItem[i].x)/7.0,
                   1.0-Abs(fItem[i].x)/7.0,
                   1.0-Abs(fItem[i].x)/7.0);
        glBegin (GL_QUADS);
          glTexCoord2f (fItem[i].texture.tu, fItem[i].texture.sv);
          glVertex3f (fItem[i].x+w*Cos(fItem[i].r), -0.75, w*Sin(fItem[i].r)-w+Abs(w*Sin(fItem[i].r))-2.0+3.0*fItem[i].z);
          // ...
        glEnd;
    end;
end;


In einem schwarzen Raum sieht das ganz gut aus. D.h. das Item in der Mitte sieht man voll, die anderen erscheinen dunkler, die Reflexion noch etwas dunkler. In einem hellen Raum sieht das ziemlich verkehrt aus, und ich schaffe es nicht, das anzupassen.
Der gewollte Effekt ist, dass die hinteren Items in einem passend farbigen Nebel verblassen. Wie muss ich das anpassen?


Martok - Sa 01.05.10 11:43

user profile iconGausi hat folgendes geschrieben Zum zitierten Posting springen:
Für meinen Coverflow nutze ich eine Unit "unitFlyingCow"

Eine Unit FlyingSpaghettiMonster wäre irgendwie cooler... 8)


user profile iconGausi hat folgendes geschrieben Zum zitierten Posting springen:
Da ich nur lose Objekte im Raum zeichne, ist das quasi die Farbe meines Raumes, hier also schwarz. Die möchte ich gerne variabel gestalten, z.B. clBtnFace statt schwarz. Eigentlich kein Problem.

Stimmt, musst nur die Zerlegung richtig machen... clBtnFace ist keine klassische Farbe, sondern eine Systemfarbe...da könnte man mit Get(R|G|B)Value etc Probleme kriegen.

user profile iconGausi hat folgendes geschrieben Zum zitierten Posting springen:
In einem schwarzen Raum sieht das ganz gut aus. D.h. das Item in der Mitte sieht man voll, die anderen erscheinen dunkler, die Reflexion noch etwas dunkler. In einem hellen Raum sieht das ziemlich verkehrt aus, und ich schaffe es nicht, das anzupassen.
Der gewollte Effekt ist, dass die hinteren Items in einem passend farbigen Nebel verblassen. Wie muss ich das anpassen?

Blending abschalten müsste doch eigentlich schon reichen, oder?
Ich bau auch mal ein Testprogramm...


Gausi - Sa 01.05.10 12:01

Ich häng mal das Originalprojekt an, dann kannst du dir das drumherum sparen. ;-)


Martok - Sa 01.05.10 12:44

So geht das auch ;)

Was wir also brauchen, ist ein Ausdruck für "Wenn vorn, dann weiß, sonst Fade to $Hintergrundfarbe".

Ich hab das mal auf Papier hergeleitet, bei manchen Kombinationen sieht es so aus, als ob die Spiegelung eine andere Farbe hätte.

Folgender Ansatz, für den Rot-Kanal:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
c=Berechnete Farbe
r=HintergrundRot
u=GewählteFarbe

u = c+(1-c)*r;
//da c komplizierter ist und ich mir die im Code sparen will, ausklammern ;)

u = c+r-cr = c-cr+r

u = c(1-r) + r
--------------

Analog für die anderen beiden.

Damit wäre das dann:

Delphi-Quelltext
1:
2:
3:
        glColor3f ((0.5-Abs(fItem[i].x)/7.0*0.5)*(1-r)+r,
                   (0.5-Abs(fItem[i].x)/7.0*0.5)*(1-g)+g,
                   (0.5-Abs(fItem[i].x)/7.0*0.5)*(1-b)+b);

Bzw.

Delphi-Quelltext
1:
2:
3:
        glColor3f ((1.0-Abs(fItem[i].x)/7.0)*(1-r)+r,
                   (1.0-Abs(fItem[i].x)/7.0)*(1-g)+g,
                   (1.0-Abs(fItem[i].x)/7.0)*(1-b)+b);


Passendes glClearColor noch irgendwo einzubauen, und dann das ganze mal noch "in schön", mit Properties und so.

Was bei der Unit etwas schwierig wird: den Text färben. Das ist da etwas hässlich gelöst; da muss in unitGLText procedure gltDrawText noch ein paar mehr Parameter kriegen.


BenBE - Sa 01.05.10 13:49

Was du machen könntest ist die Nutzung von glColor4f, wobei der letzte Parameter die Transparenz angibt. glEnable(GL_BLEND); muss dafür aktiv sein.

Bzgl. clBtnFace: Es gibt in der RTL\VCL ne Funktion, die einem die Systemfarben in RGB konvertiert; unabhängig ob Systemfarbe oder RGB-Wert. Siehe ColorToRGB bzw. GetSysColor (Nur das LSB übergeben).


Gausi - Sa 01.05.10 14:00

Ok, mit der Modifikation sieht das schon etwas besser aus. Aber wenn die Raumfarbe weiß ist (r=g=b=1), dann liefert die Rechnung immer weiß, und es passiert "nichts".

Ich vermute, dass man da auch noch an dem glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); in der Methode DrawScene drehen muss, die das Renderpass aufruft - aber da stochere ich auch komplett im Dunkeln. :nixweiss:

Das mit dem Text habe ich bei mir eh anders gelöst. Unicode in OpenGL habe ich irgendwie gar nicht hinbekommen...


BenBE - Sa 01.05.10 14:08

user profile iconGausi hat folgendes geschrieben Zum zitierten Posting springen:
Ok, mit der Modifikation sieht das schon etwas besser aus. Aber wenn die Raumfarbe weiß ist (r=g=b=1), dann liefert die Rechnung immer weiß, und es passiert "nichts".

Ich vermute, dass man da auch noch an dem glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); in der Methode DrawScene drehen muss, die das Renderpass aufruft - aber da stochere ich auch komplett im Dunkeln. :nixweiss:

mom, ich such mal kurz etwas JOGL-Code raus, der transparent was zeichnet mit Blending. Der ist recht Straight-Forward:


Java-Code:
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:
75:
76:
77:
78:
79:
80:
    private void drawCoordSys() {
      gl.glEnable(GL.GL_DEPTH_TEST);

      gl.glEnable(GL.GL_BLEND);
      gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_DST_ALPHA);

      gl.glLineWidth(1.0f);

      gl.glBegin(GL.GL_LINES);
        gl.glColor4f(lineColor[0], lineColor[1], lineColor[2], ALPHA_BLENDING);
        for (int i = -100; i <= 100; i += 10) {
          gl.glVertex3f(i, -100.0f, +0.0f);
          gl.glVertex3f(i, +100.0f, +0.0f);

          gl.glVertex3f(-100.0f, i, +0.0f);
          gl.glVertex3f(+100.0f, i, +0.0f);

          gl.glVertex3f(i, 0.0f, -1.0f);
          gl.glVertex3f(i, 0.0f, +1.0f);

          gl.glVertex3f(+0.0f, i, -1.0f);
          gl.glVertex3f(+0.0f, i, +1.0f);

          gl.glVertex3f(-1.0f, +0.0f, i);
          gl.glVertex3f(+1.0f, +0.0f, i);

          gl.glVertex3f(+0.0f, -1.0f, i);
          gl.glVertex3f(+0.0f, +1.0f, i);
        }
        gl.glVertex3f(0.0f0.0f, -100.0f);
        gl.glVertex3f(0.0f0.0f, +100.0f);
      gl.glEnd();

      gl.glLineWidth(3.0f);
      gl.glBegin(GL.GL_LINES);
        gl.glColor4f(lineColor[0], 00, ALPHA_BLENDING);
        gl.glVertex3f(-100.0f, +0.0f, +0.0f);
        gl.glVertex3f(+100.0f, +0.0f, +0.0f);

        gl.glColor4f(0, lineColor[1], 0, ALPHA_BLENDING);
        gl.glVertex3f(+0.0f, -100.0f, +0.0f);
        gl.glVertex3f(+0.0f, +100.0f, +0.0f);

        gl.glColor4f(00, lineColor[2], ALPHA_BLENDING);
        gl.glVertex3f(+0.0f, +0.0f, -100.0f);
        gl.glVertex3f(+0.0f, +0.0f, +100.0f);
      gl.glEnd();

      gl.glEnable(GL.GL_DEPTH_TEST);
      gl.glBegin(GL.GL_QUADS);
        gl.glColor4f(lineColor[0], lineColor[1], lineColor[2], ALPHA_BLENDING / 4f);
        gl.glVertex3f(-100.0f, -100.0f, +0.0f);
        gl.glVertex3f(-100.0f, +100.0f, +0.0f);
        gl.glVertex3f(+100.0f, +100.0f, +0.0f);
        gl.glVertex3f(+100.0f, -100.0f, +0.0f);
      gl.glEnd();

      gl.glPushMatrix();
      try {
        gl.glDisable(GL.GL_DEPTH_TEST);
        gl.glScalef(50f50f10f);
        gl.glBegin(GL.GL_TRIANGLE_FAN);
          gl.glColor4f(1.0f1.0f1.0f0.250f);
          gl.glVertex3f(+0.0f, +0.0f, +0.0f);
          gl.glColor4f(1.0f0.0f0.0f0.125f);
          gl.glVertex3f(+1.0f, +0.0f, +0.0f);
          gl.glColor4f(1.0f1.0f0.0f0.125f);
          gl.glVertex3f(+0.0f, +1.0f, +0.0f);
          gl.glColor4f(0.0f1.0f0.0f0.125f);
          gl.glVertex3f(-1.0f, +0.0f, +0.0f);
          gl.glColor4f(0.0f0.0f1.0f0.125f);
          gl.glVertex3f(+0.0f, -1.0f, +0.0f);
          gl.glColor4f(1.0f0.0f0.0f0.125f);
          gl.glVertex3f(+1.0f, +0.0f, +0.0f);
        gl.glEnd();
      } finally {
        gl.glPopMatrix();
      }
      gl.glEnable(GL.GL_DEPTH_TEST);
    }


user profile iconGausi hat folgendes geschrieben Zum zitierten Posting springen:
Das mit dem Text habe ich bei mir eh anders gelöst. Unicode in OpenGL habe ich irgendwie gar nicht hinbekommen...

Text in OGL mit Unicode ist auch etwas Interessantes, weil die Textausgabe (zumindest für Vector-Fonts) darauf basiert, dass man sich über Display-Listen die Vektor-Daten der Zeichen im Vorfeld hold und dann die Display-Listen zum Schreiben verwendet. Dafür habsch aber leider keinen Source @Hand, wie man die Unicode-Zeichen vektorisiert bekommt, da die API dafür glaube nur ANSI versteht (AFAIK) ...

Provozieren wir doch einfach mal einen Stack-Overflow [http://stackoverflow.com/questions/7737/how-to-display-unicode-text-in-opengl] ;-)