Comment mélanger deux caméras lorsque vous traversez un portail dans Unity3D

18

Avant d'arriver à ma question, je sais que la solution la plus évidente serait d'utiliser le port de vue normalisé rect, mais j'ai besoin de formes plus complexes qu'un rectangle, et j'ai cherché à utiliser le port de vue rect et il semble que non être ma solution.

EDIT: Certaines personnes étaient confuses par ma question, permettez-moi d'entrer dans un peu plus de détails. entrez la description de l'image ici Ce qui se passe, c'est que lorsque le joueur se déplace vers un portail, je crée un contrôleur FPS clone et le déplace de l'autre. Cela me donne deux caméras et la vue que vous voyez à droite ci-dessus. Il montre juste une caméra et coupe le portail. Ce que je veux, c'est quelque chose de similaire à çaoù les caméras se fondent pour créer l'illusion d'une transition en douceur. Ce que je veux faire, c'est tout supprimer de l'image du vérificateur vert à gauche dans l'image ci-dessous et la remplacer par l'autre appareil photo. De cette façon, vous obtenez la partie de la vue de la caméra A qui culmine hors du portail, mélangée avec la partie de la vue de la caméra B qui culmine hors de l'autre portail, pour obtenir une image complète. Et lorsque vous vous déplacez à travers le portail, la coupe change de manière appropriée.

J'ai conçu un système de portail, j'ai tout en bas, y compris faire en sorte que le joueur se déplace en douceur à travers le portail. Mon principal problème est maintenant d'obtenir l'effet de mélange de caméras que Valve fait. J'ai besoin de deux caméras pour se fondre parfaitement, comme si vous passiez la tête à travers le portail. Et ce ne peut pas être juste un rectangle, il doit correspondre, mais le joueur regarde à travers le portail.

Ma meilleure idée à ce sujet en ce moment est de projeter éventuellement un masque de profondeur derrière chaque portail, puis de faire de la caméra du portail que vous voyagez uniquement en profondeur. Mélangez ensuite les deux caméras. Mon problème principal est de savoir exactement comment je ferais cela, comment faire en sorte que la deuxième caméra ne rende que ce qui est en dehors du portail, et que le reste par défaut soit la caméra 1 pour obtenir une projection en plein écran.

Si vous pouviez me donner des idées ou expliquer comment je peux le faire avec le shader de masque de profondeur, ce serait d'une aide précieuse. Je continuerai à travailler sur cela et à mettre à jour pendant que je fais des percées.

Timothy Williams
la source
5
Pouvez-vous expliquer en quoi consiste «l'effet de mélange de caméra que Valve fait»? J'ai compris que dans le rendu de portail, une seule caméra suffit. Dans les jeux à la première personne, il est attaché au joueur et est automatiquement transformé au nouvel emplacement lors de la traversée du portail avec le joueur. Pour rendre l'effet portail, une copie transformée de la scène est rendue. Cela peut également être réalisé avec un deuxième appareil photo, mais il ne devrait pas être nécessaire de mélanger entre ces appareils photo.
msell
1
J'ai déjà parfaitement les effets visuels. Ce que j'essaie de faire, c'est de trouver comment obtenir l'effet de marcher à travers le portail. J'ai déjà tous les graphismes des personnages et ces mouvements en douceur, j'en ai juste besoin pour être lisse du point de vue de la première personne.
Timothy Williams
1
Je suis sûr que beaucoup de gens aimeraient vous aider avec le problème s'ils comprenaient ce que c'était. Vous devez vraiment mieux expliquer le problème, peut-être ajouter des photos ou même une vidéo montrant ce qui ne va pas.
msell
2
Pourriez-vous ajouter un lien vers un exemple de vidéo de l'effet?
Mike Baxter
2
Et si vous n'utilisiez qu'une seule caméra / contrôleur FPS? Lorsque la caméra se déplace à travers le portail, vous pouvez la transformer au nouvel emplacement et à la nouvelle orientation. Si le rendu du portail est correct, la transition doit être transparente et aucun mélange n'est nécessaire.
msell

Réponses:

6

Comprendre le problème

D'après ce que je peux voir, le problème que vous décrivez est le résultat du plan proche de la caméra coupant le plan défini par le portail. Pendant que cette intersection se produit, vous pouvez voir derrière le mur le portail.

Ceci est similaire à un problème rencontré dans d'autres jeux lorsque le joueur passe simplement de l'eau au-dessus de l'eau. Si la caméra est juste au-dessus de l'eau, aucun effet de post-traitement n'est appliqué pour obscurcir la vue des joueurs (la rendre sombre et floue et bleue). Donc, si le fond de l'avion proche est juste sous l'eau, le joueur peut voir clairement sous l'eau.

Si je me trompe, vous pouvez le confirmer en modifiant la position de ce plan lors de la définition de la matrice de projection. À mesure que la distance entre l'origine de la caméra et le plan proche augmente, le problème devrait également augmenter.

La solution simple

Rendre l'avion proche très proche de la caméra devrait presque éliminer ce problème. Cette solution n'est pas complète, mais donnera un résultat assez bon dans la grande majorité des cas et elle est efficace.

La solution complète

Si le simple fait de rapprocher le plan proche de la caméra ne vous satisfait pas, vous pouvez créer un "masque" pour mélanger les images générées par le rendu de la scène du point de vue du joueur et du portail.

En supposant que vous autorisez uniquement les portails à être appliqués sur des surfaces planes, vous pouvez calculer la ligne d'intersection entre le plan proche de la caméra et le plan défini par le portail (ou le mur sur lequel il se trouve). Cette ligne divisera l'écran en deux parties. Déterminer de quel côté de la ligne se trouve un pixel d'écran vous permettra de savoir quelle image de rendu utiliser, l'image du portail ou l'image de la caméra du lecteur.

Gardez à l'esprit que si ce problème se produit, le tronc de la vue de la caméra doit être complètement à l'intérieur du portail afin que la ligne d'intersection soit toujours complètement coupée d'un bord d'écran à l'autre.

Ce lien devrait aider avec les mathématiques à trouver la ligne. Le code ci-dessous devrait être à peu près correct.

La ligne d'intersection est définie à l'aide d'un point sur la ligne et de la direction de la ligne. Au-dessous de la direction d'intersection est calculée en utilisant le produit croisé de la normale du portail et la direction de vue de la caméra (près du plan normal). Un point sur la ligne est donné en lançant un rayon d'un point sur le plan proche directement vers le plan de portail (le long de la normale de portail) et en trouvant le point d'intersection.

Vector3 intersectionDir = Vector3.cross(portalNorm, viewDir);
Ray ray = new Ray(camPos + viewDir * camNearPlaneDist, portalNorm);
Vector3 intersectionPos = ray.intersects(new Plane(portalVert1, portalVert2, portalVert3);

Assurez-vous que viewDir est un vecteur unitaire. portalVert1, 2 et 3 ne sont que 3 des 4 sommets utilisés pour l'autocollant de portail ou la surface sur laquelle il se trouve. Il existe d'autres façons de définir le plan sur lequel se trouve le portail, mais je suppose que ce sont les informations les plus facilement disponibles.

Une fois que vous avez ces deux vecteurs pour définir la ligne d'intersection, multipliez chacun par la vue puis les matrices de projection pour les placer dans l'espace écran.

Vous pouvez ensuite utiliser un shader de post-traitement pour mélanger ces images. Vous sélectionnez l'image à utiliser pour chaque pixel en déterminant de quel côté de la ligne de division se trouve le pixel actuel. Cela se fait en prenant la position du pixel (qui est également la position que vous utilisez pour rechercher le texel cible de rendu) et en faisant;

float d = (pixelX - intersectionPos.X) * intersectionDir.Y - (pixelY - intersectionPos.Y) * intersectionDir.X;

Le côté est donné par si d est supérieur ou inférieur à 0. Si c'est exactement 0, alors vous êtes sur la ligne.

Pour référence sur les mathématiques ci-dessus, voir ceci .

Cette méthode peut également être utilisée lors de la création d'un masque de profondeur / tampon de gabarit à utiliser avant le rendu du point de vue du portail. Vous pouvez créer un quadruple plein écran et utiliser la ligne pour le découper.

OriginalDaemon
la source
Le plan proche du clip était une bonne idée, mais pas exactement ce que je cherchais. Cette deuxième partie est cependant une approche intéressante. Actuellement, j'utilise un shader de masque de profondeur sur tout ce qui se trouve derrière le plan de portail sortant, puis je règle les drapeaux clairs de la caméra sortante sur la profondeur uniquement. Cela fait en sorte que toute partie de la caméra sortante qui culmine hors du portail dessine sur l'écran, et la caméra entrante dessine sur le masque de profondeur, donc elle crée une image en mélangeant les parties de chaque caméra qui culmine hors de son portail respectif. Le seul problème est que je reçois des problèmes d'écrêtage mineurs et comme
Timothy Williams
légère secousse pendant que le joueur se déplace. Cette idée que vous avez évoquée semble assez prometteuse. Donc, essentiellement, ce que je dois faire est de calculer la ligne le long de l'écran sur laquelle la caméra près du plan et le plan du portail se croisent, la direction me donne la direction dans laquelle la ligne va et le point est les différents points de la ligne. Comment pourrais-je alors déterminer dans un shader / script de quel côté de la ligne de division se trouve un pixel?
Timothy Williams
J'ai un peu mis à jour la réponse pour donner du code de base. Assurez-vous d'essayer de changer la vue près de la distance du plan de détourage pour confirmer le problème. Faire cela aussi petit que possible peut également suffire. N'oubliez pas, faites-le fonctionner, faites-le fonctionner correctement, puis faites-le fonctionner rapidement.
OriginalDaemon
J'ai testé la modification de la distance du plan de coupe proche, cela a légèrement amélioré le problème, mais comme l'article publié par Mell indique qu'il ne résout pas le problème lors du mitraillage. J'ai toujours l'impression que la ligne d'intersection peut fonctionner, alors je vais l'essayer. J'examinerai également un peu plus cet article publié par Mell. En fin de compte, il s'agira de déterminer si un masque de profondeur est plus rapide ou si cette ligne d'intersection est plus rapide
Timothy Williams
3

Les réponses suggérées étaient très bonnes, mais j'ai fini par opter pour une technique différente en utilisant un masque de profondeur.

Ce que vous faites est de prendre CE script et ce shader, vous placez le script sur chaque objet avec un moteur de rendu dans votre scène et définissez la file d'attente de rendu sur 3020 (je publierai un script pour vous faciliter la tâche plus tard).

Ensuite, vous créez une boîte d'avions (tous tournés vers l'intérieur, dans l'image, vous ne pouvez pas voir le côté de la boîte le plus proche de vous, mais lorsque vous êtes à l'intérieur de la boîte, tout ce que vous devriez voir est gris) derrière LES DEUX de vos portails ainsi: entrez la description de l'image ici Et placez-les sur une couche spéciale qui leur est propre (j'ai choisi "DepthMask" pour la mienne), puis vous leur ajoutez un matériau avec le shader ci-dessus. entrez la description de l'image ici

Vous prenez ensuite la caméra principale et décochez votre couche spéciale de son masque d'élimination (j'ai décoché la couche DepthMask) et définissez sa profondeur sur 0. entrez la description de l'image ici

Ensuite, lorsque vous vous téléportez et clonez la caméra, définissez les drapeaux clairs de l'autre caméra sur "Profondeur uniquement" et sa profondeur sur 1. entrez la description de l'image ici

Vous obtenez alors un écran transparent mélangé entre les deux vues de caméra.

Timothy Williams
la source