Ogólny zarys:
Utwórz mapę głębi swojej sceny bez tarczy. Możesz uzyskać to skutecznie za darmo, ponieważ obiekty przezroczyste są często renderowane w późniejszym przebiegu. W przeciwnym razie możesz utworzyć mapę głębokości, renderując scenę bez osłony na RTT z shaderem głębokości.
Renderuj scenę normalnie, przekaż mapę głębi do shadera tarcz.
W module cieniującym oblicz różnicę głębokości sceny od głębokości fragmentu osłony i użyj tej różnicy, aby zmodyfikować kolor fragmentu.
Próbny
Napisałem prostą wersję demo tego WebGL.
Linia po linii
Omówmy szczegółowo kod modułu do cieniowania fragmentów:
float solidsDepth = texture2D(depthMap, gl_FragCoord.xy / dims).r;
Próbkuj mapę głębokości dla każdego fragmentu. Pamiętaj, aby podzielić przez wymiary rzutni, aby przekonwertować fragment z przestrzeni ekranu [0, szerokość / wysokość] na znormalizowane współrzędne [0,0, 1,0]. W tym momencie, jeśli po prostu ustawisz kolor fragmentu na próbkowany piksel mapy głębi, wyglądałoby to tak:
Mapa głębokości jest w skali szarości, więc możesz uzyskać wartość z dowolnego kanału (użyłem r
tutaj).
float solidsDiff = 1.0 - smoothstep(
zNear,
zFar,
gl_FragCoord.z / gl_FragCoord.w
) - solidsDepth;
Następnie możesz użyć tej próbki głębokości, aby znaleźć różnicę między głębokością sceny a głębokością fragmentu tarczy. Pamiętaj również o normalizacji głębi, aby przenieść ją z [zNear, zFar] (bliskie i dalekie płaszczyzny aparatu) do [0,0, 1,0]. smoothstep
robi to ładnie. Ma 1.0 -
to na celu odwrócenie wartości, która solidsDiff
wynosi 1,0, gdy różnica jest wartością maksymalną (zFar - zNear), a wartością minimalną 0,0 (0,0).
Zauważ, że założyłem, że solidsDepth
został już znormalizowany w module cieniującym, który utworzył mapę głębokości.
float alpha = 0.3 + max(0.0, 1.0 - log(100.0 * (solidsDiff - 0.005) + 1.0));
Następnie możesz zmodyfikować kanał alfa swojej tarczy w zależności od różnicy głębokości. Tutaj zaczynamy od minimalnej wartości alfa 0.3
, a następnie tworzymy ładny gwałtowny wzrost alfa, gdy zbliżamy się do 0.0
różnicy.
- 0.005
Przesunięcie tylko dodaje biały margines, aby „skrzyżowanie” grubsze. Spróbuj to zmodyfikować!
gl_FragColor = vec4(vec3(1.0), alpha);
Na koniec zastosuj tę alfa do koloru fragmentu.
Ulepszenia
Możesz zrobić zakrzywioną tarczę, dodać plazmę, aby uzyskać wygląd „tarczy energetycznej” (demo) lub eksplorować efekty za pomocą tylko pokazanych skrzyżowań (demo) .
Niebo Twoja karta graficzna to limit!