Comment le Marched Rayon de champ à distance signée est-il implémenté dans un monde dynamique?


10

Je pense que je comprends les bases de la marche des rayons de champ à distance signée. Vous modélisez votre scène avec un tas de champs de distance (comme ceux-ci: http://iquilezles.org/www/articles/distfunctions/distfunctions.htm ), puis pour chaque pixel que vous lancez un rayon, commencez par le début du rayon , trouvez la distance à l'objet le plus proche à ce point et incrémentez le point de la distance la plus proche jusqu'à ce que vous touchiez quelque chose. J'ai réussi à faire un simple rendu, et c'est là que la plupart des descriptions de la technique s'arrêtent.

Cela me laisse avec quelques questions sur la façon dont SDF Ray Marching peut être utilisé dans un scénario réel:

Question 1: Dans un vrai jeu, la scène est généralement complexe et chargée sur le CPU, avec de nombreux objets dynamiques. Je comprends l'abattage d'occlusion de base (comme les octrees), et avec le rendu polygonal, je créerais une liste (sur le CPU) des éléments dans la vue frustrum à rendre.

Donc, imaginez que j'ai une scène très complexe avec de nombreux personnages et objets dynamiques se déplaçant sur l'écran, contrôlés par le CPU. Comment pourrais-je diffuser les objets que je veux rendre au GPU à chaque image? Chaque exemple a la scène codée en dur dans GLSL. Quelqu'un peut-il partager un exemple du niveau diffusé dynamiquement vers le shader?

Question 2: Comment les objets peuvent-ils avoir plusieurs couleurs? Les fonctions de distance ne renvoient qu'une distance, mais comment les implémentations transmettent-elles généralement la couleur? (Par exemple, vous frappez une sphère rouge et non un cube bleu.) S'il s'agissait d'une implémentation CPU, je pourrais appeler une fonction globale à l'intérieur de la fonction de distance quand c'est un coup pour terminer le rayon marcher, et qui pourrait également passer l'objet touché. texture / couleur. Mais comment renverriez-vous la couleur ou la texture de l'article dans GLSL?

Je vous remercie.

Réponses:


2

C'est une réponse minimale, mais je voulais partager les informations au cas où vous n'obtiendrez pas une meilleure réponse.

En ce qui concerne la façon dont les jeux réels utilisent la ray ray, ils ne le font généralement pas. Ce n'est qu'au cours des deux dernières années que les jeux ont commencé le raymarking du tampon de profondeur pour faire des réflexions sur l'espace à l'écran, mais aucun jeu que je connaisse n'utilise le ray marching comme vous le décrivez - pour le moment?

Pour l'autre question sur les couleurs et autres, les gens associent généralement les matériaux aux objets et utilisent des "coordonnées de texture" du point où le rayon frappe l'objet pour déterminer les propriétés du matériau à ce point de l'objet. Les matériaux courants incluent des éléments comme la couleur diffuse, l'intensité spéculaire, la couleur émissive et l'indice de transparence / réfraction.

J'espère que cela vous aidera au moins! Vous pouvez également obtenir de bonnes réponses sur le site d'échange de pile graphique.


2
"aucun jeu dont je suis conscient utilise Ray Marching dans la façon dont vous décrivez" Le prochain jeu Dreams de Media Molecule utilise des champs de distance signés pour la sculpture de contenu généré par l'utilisateur, mais si je comprends bien, les champs sont convertis en nuage de points pour le rendu au lieu de être raymarched directement. Cet article peut avoir quelques idées: dualshockers.com/2015/08/15/…
DMGregory

1
@DMGregory Nice, mais je pense que ce n'est pas strictement Ray Marching. Donc, le point est toujours valable, les jeux n'utilisent généralement pas de ray marching.
concept3d

1
Mise à jour de ce fil - le prochain jeu Claybook rendrait ses scènes en utilisant des rayons tirés directement à travers des champs de distance , plutôt que de les convertir d'abord en géométrie conventionnelle. Donc le "encore?" semble avoir été confirmée deux ans plus tard. :)
DMGregory

1

Je suis en train de développer un moteur de jeu qui utilise des champs de distance signés comme technique de rendu pour afficher une géométrie procédurale fluide (généré avec des primitives simples comme celles de votre lien pour l'instant, en vue d'implémenter des fractales Julia et IFS à l'avenir). Étant donné que mon moteur est axé sur la génération procédurale et doit définir les chiffres d'une manière qui les rend conviviaux pour les ray-marcheurs, je pense que je suis bien placé pour répondre à cette question: P.

En ce qui concerne le streaming, la solution simple consiste à utiliser une sorte de tampon typé et à le jeter sur le GPU lorsque vous voulez faire votre ray ray. Chaque élément du tampon est un type complexe (par exemple une structure en C / C ++), et chaque type contient des éléments définissant la fonction que vous devez utiliser pour le représenter, sa position, sa rotation, son échelle, etc., et une couleur moyenne. Le processus se simplifie alors jusqu'à:

  1. Éliminez votre scène dans un sous-ensemble gérable (notez que l'élimination des troncs et de l'élimination des occlusions est en partie effectuée automatiquement par l'algorithme de défilement des rayons)
  2. Passez le sous-ensemble dans votre tampon d'entrée de rendu
  3. Passez le tampon au GPU s'il n'est pas déjà là, puis restituez votre scène avec un ray-marching traditionnel. Vous devrez effectuer une sorte de recherche par étape pour évaluer quel élément du tampon d'entrée est le plus proche de chaque rayon pour chaque itération du ray-marcher, et vous devrez appliquer des transformations à l'un ou l'autre des rayons (dans ce cas vous devrez inverser les rotations des figures avant qu'elles n'atteignent le GPU) ou les fonctions de distance elles-mêmes (déplacement de l'origine de la fonction pour les changements de position, ajustement par exemple des longueurs des côtés cubiques pour les changements d'échelle, etc.) L'approche la plus simple consiste à simplement modifier les rayons avant vous les transmettez à la fonction de distance centrale réelle.

Concernant les couleurs des figures, n'oubliez pas que les shaders vous permettent de définir des types complexes ainsi que des primitives;). Cela vous permet de tout jeter dans une structure de style C, puis de renvoyer ces structures depuis votre fonction de distance.

Dans mon moteur, chaque structure contient une distance, une couleur et un ID qui la lie à la définition de chiffre correspondante dans le tampon d'entrée. Chaque ID est déduit du contexte environnant de la fonction de distance pertinente (puisque ma fonction de mappage parcourt le tampon d'entrée pour trouver la figure la plus proche de chaque rayon pour chaque étape, je peux traiter en toute sécurité la valeur du compteur de boucle lorsque chaque SDF est appelé comme l'ID de la figure pour cette fonction), tandis que les valeurs de distance sont définies à l'aide d'un noyau arbitraire SDF (par exemplepoint - figure.pos pour une sphère), et les couleurs sont définies soit à partir de la couleur moyenne de l'élément approprié dans le tampon de la figure (d'où la raison pour laquelle il est utile de conserver l'ID de la figure) soit à travers une couleur procédurale pondérée en fonction de la moyenne stockée (un exemple pourrait être de prendre un nombre d'itérations pour un certain point sur le Mandelbulb, mappant votre "couleur moyenne" de l'espace colorimétrique FP à l'espace colorimétrique entier, puis en utilisant la couleur mappée comme une palette en la xorant sur le nombre d'itérations).

Les textures procédurales sont une autre approche, mais je ne les ai jamais utilisées moi-même. iq a fait beaucoup de recherches dans ce domaine et a publié des démonstrations intéressantes sur Shadertoy, ce qui pourrait être un moyen de recueillir des informations supplémentaires.

Que votre couleur soit statique pour chaque figure, générée de manière procédurale ou échantillonnée par magie à partir d'une texture procédurale, la logique de base est la même: les figures abstraites dans une sorte de type complexe intermédiaire (par exemple une structure), stockent à la fois la distance locale et locale color dans une instance de ce type, puis passez le type complexe comme valeur de retour de votre fonction de distance. Selon votre implémentation, la couleur de sortie peut ensuite passer directement à l'écran ou suivre le point de collision dans votre code d'éclairage.

Je ne sais pas si ce qui précède était suffisamment clair ou non, alors ne vous inquiétez pas de demander si quelque chose n'a pas de sens. Je ne peux pas vraiment donner d'échantillons de code GLSL / pixel-shading car je travaille avec HLSL et calcule l'ombrage, mais je suis heureux d'essayer de passer en revue tout ce que je n'ai pas écrit correctement en premier lieu :).

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.