Un aperçu général:
Créez une carte de profondeur de votre scène sans le bouclier. Vous pouvez l'obtenir efficacement gratuitement, car les objets transparents sont souvent rendus dans un passage ultérieur de toute façon. Sinon, vous pouvez créer la carte de profondeur en rendant la scène sans bouclier sur un RTT avec un shader de profondeur.
Rendez votre scène normalement, passez la carte de profondeur à votre shader de bouclier.
Dans le shader, calculez la différence de profondeur de scène à partir de la profondeur du fragment de bouclier et utilisez cette différence pour modifier la couleur du fragment.
Démo
J'ai écrit une simple démonstration WebGL de cela.
Ligne par ligne
Passons en revue le code du fragment shader en détail:
float solidsDepth = texture2D(depthMap, gl_FragCoord.xy / dims).r;
Échantillonnez la carte de profondeur à chaque fragment. N'oubliez pas de diviser par les dimensions de votre fenêtre pour convertir votre fragment de l'espace d'écran [0, largeur / hauteur] en coordonnées normalisées [0,0, 1,0]. À ce stade, si vous définissez simplement la couleur du fragment sur le pixel de la carte de profondeur échantillonnée, cela ressemblerait à ceci:
La carte de profondeur est en niveaux de gris, vous pouvez donc obtenir la valeur de n'importe quel canal (j'ai utilisé r
ici).
float solidsDiff = 1.0 - smoothstep(
zNear,
zFar,
gl_FragCoord.z / gl_FragCoord.w
) - solidsDepth;
Vous pouvez ensuite utiliser cet échantillon de profondeur pour trouver la différence entre la profondeur de la scène et la profondeur du fragment de bouclier. N'oubliez pas de normaliser également votre profondeur, pour la faire passer de [zNear, zFar] (les plans proche et éloigné de votre appareil photo) à [0.0, 1.0]. smoothstep
le fait bien. Le 1.0 -
est d'inverser la valeur telle que solidsDiff
1,0 lorsque la différence est le maximum (zFar - zNear) et 0,0 au minimum (0,0).
Notez que j'ai supposé qu'il solidsDepth
était déjà normalisé dans le shader de profondeur qui a créé la carte de profondeur.
float alpha = 0.3 + max(0.0, 1.0 - log(100.0 * (solidsDiff - 0.005) + 1.0));
Vous pouvez ensuite modifier le canal alpha de votre bouclier en fonction de la différence de profondeur. Ici, nous commençons à un alpha minimum de 0.3
, puis créons une belle augmentation nette de l'alpha lorsque nous approchons de la 0.0
différence.
Le - 0.005
décalage ajoute juste une marge blanche pour rendre "l'intersection" plus épaisse. Essayez de le modifier!
gl_FragColor = vec4(vec3(1.0), alpha);
Et enfin, appliquez cet alpha à la couleur de votre fragment.
Améliorations
Vous pouvez créer un bouclier incurvé, ajouter du plasma pour un look "bouclier d'énergie" (démo) ou explorer les effets avec juste les intersections affichées (démo) .
Le ciel Votre carte graphique est la limite!