• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

webgl gl_FragColor

m1au

New member
Hallo :)

Ich schaffe es leider nicht zu verstehen, wie webgl bei den Farben mit der alpha-Komponente umgeht.

Mein Fragment-Shader schaut folgendermaßen aus:

Code:
<script id="shader-fs" type="x-shader/x-fragment">
   precision highp float;
   void main(void)
   {
      float c = 0.5;
      float a = 0.7;
      if(gl_FragCoord.x < 320.0) // linke canvas-Hälfte
         gl_FragColor = vec4(c, c, c, a);
      else gl_FragColor = vec4(c / a, c / a, c / a, 1.0);
   }
</script>
Das canvas ist 640 Pixel breit. Ich rendere einen Würfel, den ich von schräg oben betrachte.

Eigentlich hätte ich erwartet, dass der Würfel in einer einzigen Farbe angezeigt wird. Das ist aber nicht der Fall. Das Ergebnis schaut folgendermaßen aus:

Unbenannt.png

Ich habe hier also 2 unterschiedliche Farben. Woran liegt das?

- - - Aktualisiert - - -

Zu Beginn mache ich übrigens (wie üblich):
Code:
gl.clearColor(0.0, 0.0, 0.0, 1.0); 
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

Getestet mit dem Google Chrome Browser. Im Firefox habe ich scheinbar das gleiche Problem
 
Zuletzt bearbeitet:
Ja, da scheinst du auch wirklich Recht zu haben ... ganz offensichtlich, das sieht man ja am Ergebnis (sofern man davon ausgeht, dass das nicht ein Bug im webgl ist) :)

Aber wie müsste ich beim zweiten gl_FragColor-Befehl (dort ist der alpha-Komponente fix der Wert 1.0 zugewiesen) das a in r, g und b einbauen, damit ich dann die gleiche Farbe bekomme wie beim ersten gl_FragColor-Befehl?
 
Zuletzt bearbeitet:
wie willst du denn durch transparenz eine farbe wie eine andere aussehen lassen? das geht ja maximal über eine hintergrundfarbe?
 
Das ist momentan auch gar nicht mein Ziel, irgendetwas transparent zu machen. Ich versuche nur zu verstehen, wie die Grafikkarte dann mit dem alpha-Wert weiter umgeht. Denn irgendwie berücksichtigt die Grafikkarte den Wert dann.

Code:
<script id="shader-fs" type="x-shader/x-fragment">
   precision highp float;
   void main(void)
   {
      float c = 0.5;
      float a = 0.7;
      if(gl_FragCoord.x < 310.0) // links
         gl_FragColor = vec4(c, c, c, 1.0);
      else if(gl_FragCoord.x > 330.0) // rechts
         gl_FragColor = vec4(c, c, c, a);
      else gl_FragColor = vec4(c / a, c / a, c / a, 1.0); // mitte
   }
</script>
Hier bekommt man 3 unterschiedliche Farben:

Unbenannt.png

Und ich will den letzten gl_FragColor-Befehl irgendwie so hinbiegen, dass die gleiche Farbe angezeigt wird wie beim zweiten gl_FragColor-Befehl.

Diese 3 Farben kann man sich auch auf http://www.mathematik.uni-marburg.d.../code/WebGLShaderLightMat/ShaderLightMat.html ansehen. Einfach meine GLSL-Programmierung in das "Fragment shader:"-Feld reinkopieren und dann den Button "Reload Shader Code" anklicken.
 
Zuletzt bearbeitet:
Das ist momentan auch gar nicht mein Ziel, irgendetwas transparent zu machen. Ich versuche nur zu verstehen, wie die Grafikkarte dann mit dem alpha-Wert weiter umgeht. Denn irgendwie berücksichtigt die Grafikkarte den Wert dann.
ja, natürlich, durch die transparez hast du eine überlagerung von farben, deine farbe besteht zu a% aus deinem farbanteil und zu 1-a%(ok, (1-a)*100) aus dem farbanteil des hintergrundes, liegt zw. hintergrund und deinem objekt noch ein anderes, ist das auch zu berücksichtigen (im günstigsten fall hat dieses keine transparez und ist somit dein hintergrund)

Und ich will den letzten gl_FragColor-Befehl irgendwie so hinbiegen, dass die gleiche Farbe angezeigt wird wie beim zweiten gl_FragColor-Befehl.
wozu?
 
Ich glaube nicht, dass meine Würfel-Farben irgendwie von der Hintergrundfarbe abhängen.

Ich habe nun die clearColor geändert auf:

Code:
gl.clearColor(1.0, 1.0, 1.0, 1.0);

Und die Würfel-Farben sind unverändert:

Unbenannt2.png

Ich will mich als nächstes mit Blending beschäftigen. Aber zuvor will ich das hier mal verstanden haben.

Hat wer von euch einen Apple-Rechner? Erscheinen dort auch 3 Farben?
 
Zuletzt bearbeitet:
Meinst du damit, dass man nicht mit dem alpha-Parameter von gl_FragColor arbeiten darf, wenn das blending aus ist? Bekommt man in so einem Fall irgendwelche nicht vorhersehbaren, falsche Werte?
 
OMG, Ursache gefunden. Du hattest recht. Es hat mit dem Hintergrund zu tun. Ich war nur leider immer auf die Farbe fixiert, die man mit clearColor einstellt. Aber das ist ja eigentlich nicht die Hintergrundfarbe, sondern nur die Default-Farbe für den Renderer. Die wahre Hintergrundfarbe ist jene Farbe, die man im HTML definiert, also z. B.:

Code:
<body bgcolor="#FF0000">

Und damit interagiert dann meine Würfelfarbe, wenn alpha < 1 ist. (Unabhängig davon, ob ich im webgl das Blending aktiviert habe).

Problem gelöst. Danke, dass du dich mit meinem Problem beschäftigt hast :)
 
Ich habe mir heute vorgenommen, die nächste Zeil mal etwas mit Farben und Blending herumzuexperimentieren. Dann schreib ich hier noch ein bissl was rein :)
 
das "problem" scheint nichts mit opengl zu tun zu haben, wenn du schreibst es wird der HTML-backgroung genommen ist das die darstellung des canvas im browser.
sprich das "canvas-bild" welches der browser zeichnet hat dann transparente teile, die der browser mit seinem hintergrund auch nochmal verrechnet
 
Ja, vermutlich macht das dann der Browser.

Weil ich versprochen hatte, hier noch was reinzuschreiben, hier mein erstes AHA-Erlebnis:

Code:
<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8">
      <title>Title of the document</title>
      <script src="sylvester.js" type="text/javascript"></script>
      <script src="glUtils.js" type="text/javascript"></script>
      <script src="unschaerfe2.js"></script>
      <script id="shader-vs" type="x-shader/x-vertex">
         attribute vec3 aVertexPosition;

         uniform mat4 uMVMatrix;
         uniform mat4 uPMatrix;

         void main(void) {
           gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
         }
      </script>
      <script id="shader-fs" type="x-shader/x-fragment">
         precision highp float;
         void main(void) {
            float c = 0.1;
            float a = 0.7;
            if(gl_FragCoord.x < 320.0) // links
               gl_FragColor = vec4(c, c, c, 1.0);
            else  // rechts
               gl_FragColor = vec4(c, c, c, a); 
               // vec4Oben.rgb + vec3Unten * (1 - vec4Oben.a)
               // mit ff0000 als html-Hintergrundfarbe:
               //    r:    0.1 + 1.0 * (1 - 0.7) = 0.4 ... 102
               //    g, b: 0.1 + 0.0 * (1 - 0.7) = 0.1 ... 25.5 => abgerundet 25
            // Bei c = 1.0 und a = 0.5 sieht man einen hässlichen, dünnen Rahmen.
            // Beim Rahmen wird c rasch kleiner. Das a wirkt zu 100% auch in diesem Rahmen!
            // In der Fläche innerhalb des Rahmens hat man:
            //    r:    1.0 + 1.0 * (1 - 0.5) = 1.5 ... Maximalwert 255
            //    g, b: 1.0 + 0.0 * (1 - 0.5) = 1.0 ... 255
            // Das Ergebnis ist also die erwartete weiße Farbe.
            // Nimmt man beim Rahmen ein c = 0.5 an, erhält man:
            //    r:    0.5 + 1.0 * (1 - 0.5) = 1.0 ... 255
            //    g, b: 0.5 + 0.0 * (1 - 0.5) = 0.5 ... 127.5 => abgerundet 127
            // Bei diesem c hat der Rahmen also eine (leider sehr auffällige) hellrote Farbe.
         }
      </script>
   </head>
   <body onload="start()" bgcolor="#FF0000">
      <canvas id="glcanvas" width="640" height="480">
         Your browser doesn't appear to support the <code><canvas></code> element.
      </canvas>
   </body>
</html>

Wer das ausprobieren will, kann als Vorlage das Programm von https://developer.mozilla.org/de/do...ufügen_von_2D_Inhalten_in_einen_WebGL-Kontext runterladen.

Bei mir sind aber in der html-Datei die script-Dateinamen/-Pfadangaben anders. Die css-Datei habe ich rausgenommen. Die setzt nämlich noch extra zusätzlich für das canvas eine schwarze Hintergrundfarbe. Dann hat das mit den alpha-Werten keinen Effekt. Als HTML-Hintergrundfarbe bgcolor habe ich rot gewählt.

Das ist alles ohne blending.
 
Zuletzt bearbeitet:
Zurück
Oben