Ein allgemeiner Überblick:
Erstellen Sie eine Tiefenkarte Ihrer Szene ohne Schild. Sie können dies effektiv kostenlos erhalten, da transparente Objekte ohnehin oft in einem späteren Durchgang gerendert werden. Andernfalls können Sie die Tiefenkarte erstellen, indem Sie die Szene ohne Abschirmung auf einem RTT mit einem Tiefen-Shader rendern .
Rendern Sie Ihre Szene normal, übergeben Sie die Tiefenkarte an Ihren Shader.
Berechnen Sie im Shader den Unterschied in der Szenentiefe von der Tiefe des Schildfragments und verwenden Sie diesen Unterschied, um die Fragmentfarbe zu ändern.
Demo
Ich habe eine einfache WebGL-Demo dazu geschrieben.
Zeile für Zeile
Lassen Sie uns den Fragment-Shader-Code im Detail durchgehen:
float solidsDepth = texture2D(depthMap, gl_FragCoord.xy / dims).r;
Probieren Sie die Tiefenkarte bei jedem Fragment. Denken Sie daran, durch die Abmessungen Ihres Ansichtsfensters zu dividieren, um das Fragment vom Bildschirmbereich [0, Breite / Höhe] in normalisierte [0.0, 1.0] Koordinaten zu konvertieren. Wenn Sie zu diesem Zeitpunkt die Fragmentfarbe einfach auf das Pixel der abgetasteten Tiefenkarte einstellen, sieht dies folgendermaßen aus:
Die Tiefenkarte ist Graustufen, sodass Sie den Wert von jedem Kanal abrufen können (den ich r
hier verwendet habe).
float solidsDiff = 1.0 - smoothstep(
zNear,
zFar,
gl_FragCoord.z / gl_FragCoord.w
) - solidsDepth;
Mit diesem Tiefenmuster können Sie dann den Unterschied zwischen der Szenentiefe und der Tiefe des Schildfragments ermitteln. Denken Sie daran, auch Ihre Tiefe zu normalisieren, um sie von [zNear, zFar] (der nahen und der fernen Ebene Ihrer Kamera) auf [0.0, 1.0] zu bringen. smoothstep
macht das schön. Das 1.0 -
ist, um den Wert so zu invertieren, dass er solidsDiff
1,0 ist, wenn die Differenz das Maximum (zFar - zNear) und 0,0 das Minimum (0,0) ist.
Beachten Sie, dass ich davon ausgegangen bin, dass solidsDepth
der Tiefen-Shader, der die Tiefen-Map erstellt hat, bereits normalisiert wurde.
float alpha = 0.3 + max(0.0, 1.0 - log(100.0 * (solidsDiff - 0.005) + 1.0));
Sie können dann den Alphakanal Ihres Schilds in Abhängigkeit von der Tiefenunterschiede ändern. Hier beginnen wir mit einem Alpha-Minimum von 0.3
, und erzeugen dann einen schönen steilen Alpha- Anstieg, wenn wir uns der 0.0
Differenz nähern.
Der - 0.005
Versatz fügt nur einen weißen Rand hinzu, um den "Schnitt" dicker zu machen. Versuchen Sie es zu ändern!
gl_FragColor = vec4(vec3(1.0), alpha);
Und schließlich wenden Sie dieses Alpha auf Ihre Fragmentfarbe an.
Verbesserungen
Sie können einen gekrümmten Schild erstellen, Plasma hinzufügen, um einen "Energieschild" -Look zu erhalten (Demo), oder Effekte mit nur den angezeigten Schnittpunkten untersuchen (Demo) .
Der Himmel Ihre Grafikkarte ist das Limit!