Comment puis-je utiliser le pipeline graphique pour rendre des données volumétriques basées sur une fonction de densité?

12

Les deux API graphiques (OpenGL et DirectX) conçoivent un pipeline bien défini dans lequel plusieurs étapes sont programmables. Ces étapes programmables nécessitent de prendre une quantité minimale fixe de données et sont censées effectuer une gamme bien définie d'opérations sur celle-ci, et produire une sortie minimale définie, afin que les données puissent être transmises correctement à l'étape suivante. Il semble que ces pipelines soient conçus pour fonctionner avec une quantité limitée de types de données géométriques, qui dans le cas de D3D et OGL sont des données de sommet et des coordonnées de texture.

Mais, si on me donne un cas où l'application que je prévois de faire n'utilise pas de sommets (ou même de voxels) pour représenter ses données géométriques et ne fait pas exactement de transformations ou de projections ou de pixellisation ou d'interpolation ou quelque chose comme ça, de telles limitations des API ou le pipeline rend les choses difficiles.

Alors, existe-t-il un moyen de modifier le pipeline graphique de manière à ce que la fonctionnalité de ce que chaque étape fait aux données et le type de données qui sont produites à chaque étape soient modifiées à mon avantage? Sinon, existe-t-il un moyen par lequel je peux utiliser les fonctions API «brutes» pour construire mon propre pipeline? Sinon, veuillez indiquer pourquoi ce n'est pas possible.

EDIT : Mon application utilise des fonctions de densité pour représenter la géométrie. La fonction a une valeur à chaque point de l'espace. Je divise le tronc de l'appareil photo en une grille 3D, chaque bloc peut être projeté en pixel. Sur chaque bloc, j'intègre la fonction densité et vérifie si sa valeur est supérieure à une valeur requise. Si oui, alors il est supposé que quelque chose existe dans ce bloc et que le pixel correspondant à ce bloc est rendu. donc, maintenant dans mon moteur de rendu, je veux passer la fonction (que je représente avec une chaîne) au matériel graphique au lieu des données de sommet dans les tampons de sommet. cela implique également que le vertex shader n'aura pas de vertices à transformer en espace de clip homogeniouse et le fragment shader n'obtient pas d'informations sur les pixels. à la place, la plupart des recherches et évaluations se font désormais par pixel.

The Light Spark
la source
La «fonction de densité de fonction» est-elle une tautologie?
Pharap
@Pharap, c'était une faute de frappe. son simplement "funity functon" qui représente la présence de "matière" dans l'espace.
The Light Spark
2
Il semble que vous vouliez simplement construire une isosurface, ce qui est un problème bien étudié. Avez-vous vu http.developer.nvidia.com/GPUGems3/gpugems3_ch07.html ou effectué une recherche sur Metaballs, visualisation de nuages ​​de points, extraction d'isosurface ou rendu de volume? De plus, quel type de performances avez-vous besoin, cela fera une énorme différence dans le choix de la technique que vous recherchez lorsqu'elle est combinée à la complexité de vos calculs. Je pense que vous constaterez également que le pixel provoquera un scintillement lorsque la caméra se déplacera et qu'un sous-pixel sera nécessaire.
Patrick Hughes

Réponses:

18

Vous pouvez absolument utiliser le GPU pour restituer des données volumétriques.

Puisque vous souhaitez évaluer un ensemble de fonctions par pixel sur l'écran, une approche simple consiste à rendre un triangle plein écran. Ce n'est qu'un seul triangle qui couvre tout l'écran (en fait, il couvre plus que l'écran, car l'écran n'est pas triangulaire, mais les parties hors écran sont rejetées par le GPU). Vous pouvez ensuite utiliser le pixel shader (qui reçoit les coordonnées d'écran du pixel qu'il ombrage) pour construire un rayon à travers votre volume, évaluer les fonctions, tout ce que vous devez faire.

(Contrairement aux autres réponses, je ne recommande pas un shader de calcul car il semble que vous souhaitiez effectuer des opérations par pixel, et un shader triangle + pixel plein écran est généralement plus efficace pour cela qu'un shader de calcul, bien que les shaders de calcul fonctionneront certainement aussi.)

La méthode du triangle plein écran est très courante dans les graphiques en temps réel pour les opérations de post-traitement, vous pouvez donc probablement y trouver toutes les informations dont vous avez besoin avec un peu de recherche.

BTW, il peut vous intéresser de lire Rendering Worlds with Two Triangles par Iñigo Quílez, un exposé qui décrit comment rendre des scènes 3D composées à l'aide de fonctions mathématiques (en particulier, les champs de distance) en utilisant la technique de pixel shader plein écran.

Nathan Reed
la source
Le pixel shader accepte-t-il des entrées arbitraires (comme des chaînes ou d'autres types d'objets définis par l'utilisateur) pour que je puisse transmettre mes fonctions?
The Light Spark
Je doute que vous souhaitiez essayer d'exécuter un analyseur et / ou un langage sur des chaînes de fonctions arbitraires sur GPU, ce serait gênant car les GPU ne sont pas vraiment à usage général. Vous souhaiterez probablement créer le shader lui-même de manière dynamique dans votre code principal, puis laisser le système graphique compiler et exécuter le shader résultant.
Patrick Hughes
@TheLightSpark À droite, vous ne passeriez pas de chaînes au shader (les langages d'ombrage n'ont même pas de type de chaîne), vous voudriez générer et compiler du code de shader pour les fonctions souhaitées. Cela peut être fait au moment de l'exécution si nécessaire.
Nathan Reed
J'ai commencé à lire votre réponse, j'ai imaginé un moniteur en forme de triangle;) At-il l'avantage de n'utiliser qu'un seul triangle au lieu de deux qui couvrent l'écran sans éliminer les pixels?
danijar
@danijar Oui, cela a un léger avantage sur l'utilisation d'un quad, car certains pixels le long de la diagonale seront ombrés deux fois si vous utilisez un quad en plein écran. D'un autre côté, la suppression des pixels hors écran est gratuite car le rasterizer ne générera pas ces pixels pour commencer.
Nathan Reed
6

Le traçage de rayons et d'autres techniques sont couramment effectués avec Compute Shaders, pris en charge par Direct3D depuis la sortie de D3D11 et OpenGL depuis 4.3 (et plus via l'utilisation d'OpenCL et de certaines contorsions).

Sean Middleditch
la source
5

Il semble que vous souhaitiez utiliser un shader de calcul GPU ou utiliser un objet "Shader Storage Buffer" pour aider à étendre le pipeline en fonction de vos besoins. Les mathématiciens, les scientifiques et d'autres personnes qui se tournent vers le GPU pour calculer des choses qui ne se traduisent pas exactement en graphiques standard utilisent ce genre de chose.

Bien que le pipeline graphique contemporain soit très flexible, les développeurs ont toujours tendance à tomber sur certaines restrictions. Cependant, la fonction de calcul des shaders nous facilite la vie pour ne pas penser aux étapes du pipeline car nous sommes habitués à penser au sommet et au fragment. Nous ne sommes plus limités par les entrées et sorties de certaines étapes du pipeline. La fonctionnalité Shader Storage Buffer Object (SSBO), par exemple, a été introduite avec les shaders de calcul et offre des possibilités supplémentaires d'échanger des données entre les étapes du pipeline, tout en étant une entrée et une sortie flexibles pour les shaders de calcul.

http://community.arm.com/groups/arm-mali-graphics/blog/2014/04/17/get-started-with-compute-shaders

Si cela ne vous oriente pas dans la bonne direction, cela vous dérangerait-il d'étendre le concept de la vôtre qui ne correspond pas au paradigme sommet / fragment?

AAorris
la source
J'ai modifié ma réponse pour inclure ce que je fais. le calcul shader semble être les réponses, mais dites-moi simplement s'il y a autre chose que je peux faire.
The Light Spark