Le week-end prochain est arrivé, vous devez écrire quelques dizaines de lignes de code et dessiner une image, mais aucune n'est meilleure. Donc, le week-end dernier avant-dernier, j'ai montré comment
faire le ray tracing et même
tout exploser. C'est surprenant pour beaucoup, mais l'infographie est une chose très simple, quelques centaines de lignes de C ++ nues suffisent pour créer des images intéressantes.
Le sujet de la conversation d'aujourd'hui est la vision binoculaire, et aujourd'hui nous ne pouvons même pas atteindre cent lignes de code. Être capable de rendre des scènes en trois dimensions, il serait stupide de passer des paires de stéréos, aujourd'hui nous allons dessiner quelque chose comme ceci:

La folie des développeurs de
Magic Carpet me hante. Pour ceux qui ne l'ont pas trouvé, ce jeu a permis de faire du rendu 3D à la fois en anaglyphe et en stéréogrammes
dans les paramètres principaux, juste disponible dans le menu! Ce cerveau a explosé précisément.
Parallax
Commençons donc. Pour commencer, pourquoi notre appareil visuel nous permet-il de percevoir la profondeur? Il y a un mot si intelligent "parallaxe". Si sur les doigts, concentrons-nous sur l'écran. Tout ce qui se trouve dans le plan de l'écran de notre cerveau existe en un seul exemplaire. Mais si tout à coup une mouche vole devant l'écran, alors (si nous ne changeons pas nos yeux!) Notre cerveau l'enregistrera en double. Et en même temps, l'araignée sur le mur derrière l'écran bifurque également, et la direction de la bifurcation dépend de si l'objet est devant le point focal ou derrière:

Notre cerveau est une machine très efficace pour analyser des images légèrement différentes. Il utilise la
disparité pour obtenir des informations de profondeur à partir d'images rétiniennes bidimensionnelles pour la
stéréopsie . Eh bien, Dieu les bénisse, avec les mots, faisons mieux de dessiner des images!
Supposons que notre écran soit une fenêtre sur le monde virtuel :)

Notre tâche est de dessiner deux images avec ce qui sera visible à travers cette «fenêtre». Il y aura deux images, une pour chaque œil, dans le schéma ci-dessus que je leur ai montré avec un "sandwich" rouge et bleu. Ne nous occupons pas encore de la façon dont nous alimentons exactement ces images dans l'appareil visuel, nous avons juste besoin d'enregistrer deux fichiers. Je suis particulièrement intéressé par la façon dont ces images peuvent être obtenues en utilisant
notre traceur de rayons .
Eh bien, supposons que la direction du regard ne change pas, c'est un vecteur (0,0, -1). Supposons que nous puissions déplacer la position de la caméra de la distance interoculaire, quoi d'autre? Il y a une petite subtilité: le cône de vue à travers notre «fenêtre» est asymétrique. Et notre traceur de rayons ne peut rendre qu'un cône de regard symétrique:

Que faire? Lire :)
En fait, nous pouvons rendre les images plus larges que ce dont nous avons besoin et simplement recadrer l'excédent:

Anaglyphe
Avec le mécanisme de rendu général, il devrait être clair, il est maintenant temps de nous interroger sur la livraison de l'image à notre cerveau. L'une des options les plus simples est les lunettes rouge-bleu:

Nous faisons juste les deux pré-rendus non pas en noir mais en blanc, écrivons l'image de gauche dans le canal rouge et l'image de droite en bleu. Vous obtenez l'image suivante:

Le verre rouge coupera un canal et le verre bleu en coupera un autre, de sorte que chaque œil recevra sa propre image et nous pourrons regarder le monde en 3D. Voici les
modifications apportées au commit principal du premier article , qui montrent à la fois les paramètres de la caméra pour les deux yeux et l'assemblage du canal.
Les rendus anaglyphiques sont l'une des plus anciennes façons de visualiser (ordinateur!) Des images stéréo. Ils présentent de nombreuses lacunes, par exemple un mauvais rendu des couleurs (au fait, essayez d'enregistrer le canal vert de l'œil droit dans le canal vert de l'image finale). Un avantage - ces verres sont facilement fabriqués à partir de matériaux improvisés.
Stéréoscope
Avec la prolifération des smartphones, nous nous sommes souvenus de ce que sont les stéréoscopes (qui, pour une seconde, ont été inventés au 19ème siècle)! Il y a quelques années,
Google a suggéré d' utiliser deux lentilles penny (malheureusement, elles ne sont pas faites sur le genou), du carton (traînant partout) et un smartphone (couché dans votre poche) pour obtenir des lunettes de réalité virtuelle tout à fait tolérables:

Sur aliexpress, c'étaient des tas, cent roubles par pièce. Par rapport à l'anaglyphe, vous n'avez rien à faire du tout, prenez simplement deux photos et composez-les côte à côte,
voici le commit .

À strictement parler, en fonction de l'objectif, une
correction de la distorsion de l' objectif peut être nécessaire, mais je n'ai pas pris la peine du tout, et ça a l'air bien sur mes lunettes. Mais si vous avez vraiment besoin d'appliquer une pré-distorsion en forme de tonneau qui compense la distorsion de l'objectif, voici à quoi cela ressemble pour mon smartphone et mes lunettes:

Stéréogrammes
Mais que faire si vous ne souhaitez pas utiliser d'appareils supplémentaires? Ensuite, il n'y a qu'une seule option - engourdir. De manière générale, l'image précédente suffit pour regarder en stéréo, utilisez simplement l'astuce pour regarder en stéréo. Il existe deux principes pour visualiser les stéréogrammes: bougez vos yeux ou écartez vos yeux. J'ai donc dessiné un diagramme dans lequel je montre comment vous pouvez regarder l'image précédente. L'image précédente est double, deux barres rouges sur le diagramme montrent deux images sur la rétine gauche, deux bleues sur la droite.

Si nous concentrons nos yeux sur l'écran, alors sur quatre images, nous en obtenons deux. Si nous louchons nos yeux vers le nez, il est tout à fait possible de montrer au cerveau «trois» images. Et vice versa, si vous ouvrez les yeux, vous pouvez également obtenir "trois" images. La superposition d'images centrales donnera au cerveau un effet stéréo.
Ces méthodes sont données à différentes personnes de différentes manières, par exemple, je ne sais pas du tout bouger mes yeux, mais je me reproduis facilement. Il est important que le stéréogramme construit pour une méthode soit vu de la même manière, sinon une carte de profondeur inversée est obtenue (voir parallaxe négative et positive). Le problème avec cette méthode de visualisation stéréo est qu'il est très difficile
de bouger
fortement les yeux par rapport à l'état normal, vous devez donc vous contenter de petites images. Et si vous en voulez de gros? Sacrifions complètement la couleur et ne voulons qu'une perception de la profondeur. Pour l'avenir, voici l'image que nous obtenons à la fin de cette partie:

Ce stéréogramme est conçu pour «diluer» les yeux (stéréogramme aux yeux muraux). Pour ceux qui préfèrent la vision inverse,
prenez une photo ici . Si vous n'êtes pas habitué aux stéréogrammes, essayez différentes conditions: une image plein écran, une petite image, une lumière vive, l'obscurité. La tâche consiste à ouvrir les yeux afin que les deux bandes vorticales adjacentes coïncident. La façon la plus simple de se concentrer sur le coin supérieur gauche est elle est plate. Par exemple, je suis entouré par l'environnement de l'hubr, j'ouvre l'image en plein écran. N'oubliez pas d'en retirer la souris!
Ne vous contentez pas de l'effet 3D défectueux. Si vous n'êtes que vaguement conscient des formes arrondies au milieu de points aléatoires ainsi que de faibles effets 3D, c'est certainement une illusion incomplète! Si vous regardez correctement, les boules doivent clairement sortir du plan de l'écran pour le spectateur, l'effet doit être stable et maintenu en raison de l'étude constante et détaillée de chaque partie de l'image, à la fois au premier plan et à l'arrière-plan. La stéréopsie a une hystérésis: dès que vous obtenez une image stable, elle devient plus claire plus vous regardez longtemps. Plus l'écran est éloigné des yeux, plus l'effet de profondeur est important.
Ce stéréogramme a été dessiné selon la méthode proposée il y a un quart de siècle par Thimbleby et al. Dans leur article «
Affichage d'images 3D: algorithmes pour les stéréogrammes à points aléatoires à image unique ».
Point de départ
Le point de départ du rendu des stéréogrammes est une carte de profondeur (nous avons oublié la couleur).
Voici un commit qui rend une telle image:

Les profondeurs de notre rendu sont coupées par les plans proche et éloigné, c'est-à-dire que le point le plus éloigné de ma carte a une profondeur de 0, la plus proche.
Principe de base
Que nos yeux soient à une distance d de l'écran. Placez le plan éloigné (imaginaire) (z = 0) à la même distance derrière l'écran. On choisit une constante μ, qui détermine la position du plan proche (z = 0): elle sera à une distance μd de la plus éloignée. J'ai choisi μ = 1/3 dans mon code. Au total, notre monde entier vit à une distance de d-μd à d derrière l'écran. Ayons une distance e définie entre les yeux (en pixels, dans mon code j'ai choisi 400 pixels).

Si nous regardons le point de notre objet marqué en rouge sur le diagramme, alors deux pixels marqués en vert devraient avoir la même couleur dans le stéréogramme. Comment trouver la distance entre ces pixels? Très simple. Si le point projeté actuel a une profondeur de z, alors le rapport de parallaxe à la distance entre les yeux est égal au rapport des profondeurs correspondantes: p / e = (d-dμz) / (2d-dμz). Soit dit en passant, d diminue et n'est impliqué nulle part ailleurs! Autrement dit, p / e = (1-μz) / (2-μz), ce qui signifie que la parallaxe est égale à p = e * (1-μz) / (2-μz) pixels.
Autrement dit, le principe de base de la construction d'un stéréogramme: nous parcourons toute la carte de profondeur, pour chaque valeur de profondeur, nous déterminons quels pixels doivent avoir la même couleur, et écrivons cela dans notre système de restrictions. Ensuite, nous partons d'une image arbitraire et essayons de respecter toutes les restrictions précédemment imposées.
Préparez l'image originale
À ce stade, nous préparerons une image sur laquelle nous imposerons plus tard des restrictions de parallaxe.
Ici, engagez-vous , il dessine cette image:

Notez qu'en général les couleurs sont juste aléatoires, sauf que je mets rand () * sin dans le canal rouge pour fournir des ondes périodiques. Ces ondes sont faites avec une distance de 200 pixels, ceci (avec μ = 1/3 et e = 400 sélectionnés) est la valeur maximale de parallaxe dans notre monde, c'est aussi un plan éloigné. Ces ondes sont facultatives, mais elles faciliteront la concentration nécessaire de la vision.
Rendu stéréogramme
En fait, le code complet lié au stéréogramme ressemble à ceci:
int parallax(const float z) { const float eye_separation = 400.;
Si quoi que ce soit, alors
engagez-vous ici . La fonction int parallaxe (const float z) donne la distance entre les pixels de la même couleur pour la valeur de profondeur actuelle. Nous rendons le stéréogramme ligne par ligne, car les lignes sont indépendantes les unes des autres (nous n'avons pas de parallaxe verticale). Par conséquent, la boucle principale traverse simplement toutes les lignes; pour chacun d'eux, nous commençons par un ensemble illimité complet de pixels, sur lequel nous imposerons ensuite des restrictions d'égalité par paire, et à la fin nous aurons un certain nombre de clusters de pixels (déconnectés) de la même couleur. Par exemple, un pixel avec un index à gauche et un pixel avec un index à droite devraient finir par être les mêmes.
Comment stocker cet ensemble de restrictions? La réponse la plus simple est
la structure de données union-find . Je ne vais pas le décrire, ce ne sont que trois lignes de code, vous pouvez le lire sur Wikipedia. L'idée principale est que pour chaque cluster, nous en aurons un certain «responsable», c'est aussi un pixel racine, nous lui laisserons la même couleur que dans l'image d'origine, et nous repeindrons tous les autres pixels du cluster:
for (size_t i=0; i<width; i++) {
Conclusion
Eh bien, en fait, c'est tout. Vingt lignes de code - et notre stéréogramme est prêt, cassez vos yeux et vos têtes, dessinez des images! Soit dit en passant, juste des couleurs aléatoires dans un stéréogramme est généralement un luxe, en principe, si vous essayez, vous pouvez également transmettre partiellement la couleur de notre image.
D'autres systèmes de visionnage stéréo, par exemple,
liés à la polarisation , ont été retirés de la discussion, car ils dépassent le budget de cent roubles. Si vous manquez quelque chose, ajoutez et corrigez!