2013-11-26 5 views
9

Ich arbeite an einem WebGL-Programm, das Shadow-Mapping implementiert. Nach Berechnung der Tiefenwerte an jedem Fragment habe ich am Ende eine if-Anweisung, die die Beleuchtung basierend darauf berechnet, ob das Fragment in einem Schatten ist oder nicht.WebGL-Fragment-Shader, der bei if-Anweisung nicht korrekt verzweigt

gl_FragColor = vec4(calcLighting(light0, eye_dir, eye_dir_norm, normal), 1); 
if (light_tex_coord.z - depth <= 0.0) { 
    gl_FragColor += vec4 
     (calcLighting(light1, eye_dir, eye_dir_norm, normal) 
     , 0.0 
    ); 
} 

Shadows not being correctly computed, branch never taken

wo depth die Tiefe der Schattenkarte und light_tex_coord ist die Position des Fragments in der Szene Raum light1. light1 ist ein Punktlicht, das um das Modell rotiert, und light0 ist ein Punktlicht, das statisch an der Kamera positioniert ist.

Das Problem hier ist, dass der if-Zweig nie genommen wird, so dass die Szene nur light0 angewendet hat. Ich habe überprüft, dass depth, light_tex_coord und calculateLighting korrekt funktionieren.

Hier ist das Merkwürdige, obwohl, die oben mit dem folgenden Code ersetzen:

if (light_tex_coord.z - depth <= 0.0) { 
    gl_FragColor = vec4(0,1,0,1); 
} else { 
    gl_FragColor = vec4(1,0,0,1); 
} 

Shadowed fragments correctly computed and drawn as red and green

Ursachen Schattenzonen richtig in rot gezeichnet werden, und unshadowed in grün gezeichnet werden. Das heißt, die Verzweigung wird korrekt ausgewertet. Ersetzen es mit diesem:

gl_FragColor = vec4(calcLighting(light0, eye_dir, eye_dir_norm, normal), 1); 
gl_FragColor += vec4 
    (calcLighting(light1, eye_dir, eye_dir_norm, normal) 
    , 0.0 
    ); 

Lighting computed without shadows

Ursachen Beleuchtung korrekt berechnet (ohne Schatten, obwohl) werden. Es scheint, dass wenn ich die teurere Funktion calcLighting in der if-Anweisung anrufe, es nicht einmal die Mühe macht, sie zu nehmen.

Außerdem habe ich versucht, die Beleuchtung auf verschiedene Arten einschließlich der Verwendung der clamp Funktion anzuwenden; immer die Addition und die Verwendung eines terinären Operators, um den zweiten calcLighting Aufruf mit 1 oder 0 zu multiplizieren und meine if-Anweisung auf verschiedene Arten anzuordnen. Nichts scheint zu funktionieren.

Gibt es etwas, was mir fehlt, wie Verzweigung in Webgl funktioniert?

+0

Haben Sie versucht, die Farbe auf eine separate 'vec4'-Variable zu akkumulieren und ** nur ** den Wert dieser anderen Variablen einmal '' gl_FragColor'' zuzuweisen. Das mehrfache Schreiben in 'gl_FragColor' in einem Shader soll unterstützt werden, ebenso wie das Lesen des Wertes davon (was notwendig ist, um' + = 'zu implementieren), aber bei allen Accounts scheint dieses Problem mit einer oder beiden dieser Aktionen zusammenzuhängen gegeben Ihren Kontrollfluss. –

+0

Ich habe versucht, alle Instanzen von 'gl_FragColor' in den obigen Snippets durch einen Akkumulator' vec4 acc; 'zu ersetzen. Ich habe am Ende des Shaders nur 'gl_FragColor = acc;' zugewiesen. Keine Änderung in einem der obigen Fälle. – Cookyt

+0

Können Sie den gesamten fs-Code angeben? Würde es auch einen Unterschied machen, wenn Sie den Code in 'gl_FragColor + = vec4 (calcLight (..), 1.0)' ändern? [Anmerkung 1.0 Alpha-Wert] –

Antwort

0

Vielleicht unterstützt der WebGl-Kontext keine Tiefe. Ausdrücke, die es verwenden, werden ignoriert.

Sie können dies mit getContextAttributes()

+0

In meinem JavaScript-Code überprüfe ich die Tiefenerweiterung, und wenn es nicht existiert, schreibe ich die Tiefenwerte in den Farbpuffer. In jedem Fall unterstützen die Browser, auf denen ich dies getestet habe, die Tiefenerweiterung. – Cookyt

0

Statt der Branche, haben Sie etwas wirklich radikal wie dies in Betracht gezogen:

gl_FragColor += vec4 (
    calcLighting(light1, eye_dir, eye_dir_norm, normal) 
    , 0.0 
    ) * abs (min (sign (light_tex_coord.z - depth), 0.0)); 

Es ist nicht die schönste Lösung in der Welt, aber es einfach Vielleicht bekommst du etwas mehr nach dem, was du suchst. Es dauert im Allgemeinen Ihren light_tex_coord.z - depth <= 0.0 bedingten Ausdruck und macht es zu einem schönen Gleitkommazahlen 0.0 oder 1,0, dass Sie die Beleuchtung vermehren können entweder halten oder Verwerfungs das Verzweigungsergebnis. Art der Art und Weise Shader verwendet zu arbeiten, bevor dynamische Flusskontrolle eingeführt wurde.

+0

Es ist eine nette Idee, aber leider scheint es keine Wirkung zu haben, wenn ich es benutze. – Cookyt

0

Das Thema ist 2 Jahre alt, aber hier ist mein 2 Cent:

Ich hatte ein ähnliches Problem und fand eine Seite im Internet mit einer Diskussion des folgenden Satz enthält:

[... ] (es sei denn, du verrücktes Zeug wie Bild schreibt innerhalb bedingten Blöcke). [...]

Also habe ich versucht

vec4 col; 

lokal für main() die Pixelfarbe in einer temporären Variablen zu setzen, in der "if" Anweisungen ich nur col ändern, und ich gesetzt Die Pixelfarbe nur am Ende:

gl_FragColor = col; 

Das löste mein Problem. Natürlich kann es lästige zusätzliche Programmierung erfordern, damit der Fluss in jeder Situation die letzte Zeile erreicht.