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.
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'à:
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 exemple
point - 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 :).
la source