Bonjour
J'aimerais pousser un peu plus loin ce que j'ai l'habitude de faire niveau 3D (je travaille, que ce soit au boulot ou chez moi, avec JOGL principalement).
Je possède chez moi une TV LED 3D 140cm, du coup j'aimerais tester la programmation d'un rendu 3D mais en relief sur mon écran (technologie avec lunettes passives). Je parle donc d'un système de rendu polarisé.
Problème actuel : je ne trouve pas comment faire
Quelqu'un aurait-il déjà essayé ? Ou aurait-il déjà trouvé un exemple de code montrant comment réaliser ce type de rendu ?
Niveau programmation JOGL, je sais déjà qu'il faut générer 2 rendus d'un point de vue légèrement décalé l'un de l'autre, mais comment utiliser ces 2 images pour les envoyer à un écran supportant la 3D relief ?
J'ai entendu parler du setStereo(...) d'OpenGL, est-ce une partie de la réponse ?
Faut-il détecter le support 3D de l'écran visé un peu à la manière du full screen ? Est-ce un simple paramétrage d'OpenGL ?
Si quiconque possède des informations correspondant à mon "problème", je serai ravi des les lire
Merci d'avance ![]()
Désolé du titre, j'ai un peu oublié de préciser que ça concerne un rendu 3D relief...
Toutes mes excuses.
Je ne sait pas comment se gère les écran 3D mais a mon avis tu doit faire 2 rendus dans 2 viewports avec 2 cameras cote à cote que tu configure (de façon à créer le relief), puis tu affecte à chaque viewport un "moniteur"
Oui, la gestion des 2 rendus est un élément essentiel, mais je n'ai aucun problème à la gérer, au contraire c'est la seule chose que je sais très bien faire pour ce rendu relief ^^
C'est la suite, c'est-à-dire comment envoyer l'information de relief à la télé, qui coince ![]()
en premier lieu tu aura besoin de sa http://www.seereal.com/download/drivers/NVidia_OpenGLStereo_EN.pdf
ensuite on initialise le relief avec
glutInit(&argc,argv);
if (!stereo)
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
else
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_STEREO);
ici il y a tout ce qu'il faut (mais il faut glut) : http://www.tav.net/3d/3d_stereo.htm
Merci beaucoup pour ces infos
Je regarderai ça dès que possible
Si tu as d'autres infos n'hésite pas je suis preneur ![]()
Je travaille en ce moment sur de la stéréo passive et ce que je fais pour transmettre les informations c'est du size by side : si je fais du full HD (1920 x 1080), alors il me suffit de rendre une image de taille (3840 x 1080) avec dans la moitié gauche la vision de l'oeil gauche et dans la moitié droite la vision de l'oeil droit.
Par contre avec cette méthode, il n'y a besoin que de deux buffers et non quatre (comme pour un rendu 3D classique). Et techniquement il n'y a pas non plus besoin d'activer le rendu stéréo via Glut.
Après il faut que le périphérique de sortie soit capable de prendre en entrée ce genre d'image et de le rendre. Il sera peut-être nécessaire de faire certains réglages.
Merci beaucoup pour ces réponses
Par curiosité, le size by side, c'est quoi exactement ?
Sinon je me demandais surtout : comment savoir (dans le code) si un périphérique telle ma télé est capable de rendre ce genre d'image ? Est-ce qu'il y a une valeur à récupérer, un peu comme quand on veut vérifier que le full screen est supporté ?
"Par curiosité, le size by side, c'est quoi exactement ? "
Le side by side ce sont les images de l'oeil gauche et de l'oeil droite côte à côte sur une seule même image qui est transmise à la sortie vidéo.
http://www.lcd-compare.com/definition-de-side-by-side.htm
"comment savoir (dans le code) si un périphérique telle ma télé est capable de rendre ce genre d'image ? Est-ce qu'il y a une valeur à récupérer, un peu comme quand on veut vérifier que le full screen est supporté ?"
Ça je ne sais pas, mais j'en doute.
"alors il me suffit de rendre une image de taille (3840 x 1080) avec dans la moitié gauche la vision de l'oeil gauche et dans la moitié droite la vision de l'oeil droit. "
Au final tu fais ça comment ? Tu utilises glDrawBuffer(GL_BACK_RIGHT) et glDrawBuffer(GL_BACK_LEFT) ? (J'ai tenté et le résultat a l'air bon, sauf que ma télé ne polarise pas les 2 images différemment et le relief n'apparaît pas).
Tu joues sur le viewport ? (ne donne rien pour ma part).
Autre ?
"Tu utilises glDrawBuffer(GL_BACK_RIGHT) et glDrawBuffer(GL_BACK_LEFT) ?"
Non je n'ai pas besoin d'utiliser ces buffers avec ma méthode. Mais à vrai dire je n'utilise pas OpenGL donc je peux me tromper, mais je jouerais plutôt avec la fonction glViewport pour faire le rendu de l'oeil gauche dans la première moitié de l'écran et le rendu de l'oeil droit dans la deuxième moitié.
Je suis un peu rouillé avec OpenGL mais je crois que ça fonctionne un peu comme ça :
glViewport(0, 0, w, h);
// définition de tes matrices de projections et modelview de l'oeil gauche
// affichage de la scène
glViewport(w, 0, 2*w, h);
// définition de tes matrices de projections et modelview de l'oeil droit
// affichage de la scène
Ta surface de rendu (ton écran du point de vue d'OpenGL) doit évidemment être de taille 2 * w où w peut être 1920 pour de la full HD, mais pas sûr qu'un câble HDMI 1.4 soit capable de transmettre une telle définition.
J'ai tenté sur un viewport 2 fois plus large, mais ça ne donne rien.
Déjà je pense que mon GPU n'est pas capable de gérer la 3D. Il n'a pas l'option Stereo 3D dans les settings.
J'ai tenté d'installer des drivers mais sans succès :/
Shao, de ce que j'ai compris des rendus 3D, n'importe quel carte graphique peut les generer. En fonction de l'equipement d'affichage, les rendu 3d se font soit avec une image deux fois plus grande et l'oeil gauche est afficher sur la premiere moitie et l'oeil droit sur la deuxieme moitie. Soit les deux images sont entrelace. Soit tu envois deux images et le FPS est divise par deux.
Je ne pense pas qu'il soit imperatif d'avoir du support dans la carte graphique pour generer de la 3D.
"J'ai tenté sur un viewport 2 fois plus large, mais ça ne donne rien. "
Arrive-tu déjà à afficher les images de deux caméra différentes sur l'écran ?
N'importe quel GPU peut le faire sans problème (c'est le principe utilité pour faire une vue splittée pour deux joueurs sur un seul écran). Après il faut adapter le code pour mettre les images des deux caméras côte à côte, mais ça ça ne devrait plus poser de problèmes si tu arrives à rendre les images des deux caméras.
N'hésites pas à montrer un peu ton code si tu veux qu'on t'aide mieux. Et donne voir aussi le modèle de la TV 3D : peut-être qu'elle ne gère pas le side by side mais le top & bottom ? Ou peut-être un format entrelacé ?
"Déjà je pense que mon GPU n'est pas capable de gérer la 3D. Il n'a pas l'option Stereo 3D dans les settings. "
Normalement tu peux faire de la stéréo passive sans problème. D'ailleurs pour la stéréo passive tu n'as normalement rien besoin d'activer du côté du PC. Pour la stéréo active ça se peut que ça ne soit pas possible puisqu'il faut un double-buffer pour l'oeil gauche et un autre pour l'oeil droit, et il y a aussi un mécanisme de synchronisation nécessaire pour synchroniser lunettes et écran.
"Arrive-tu déjà à afficher les images de deux caméra différentes sur l'écran ? "
Oui. Voici ce que j'ai à l'écran : http://desmond.imageshack.us/Himg808/scaled.php?server=808&filename=screen3dj.png&res=landing
(à noter qu'en mode non stereo la ligne rouge se trouve sur le plan x=0 et parait une ligne du même point de vue que ce screen).
"N'hésites pas à montrer un peu ton code si tu veux qu'on t'aide mieux."
Ca va être difficile, j'ai une centaine de classes donc c'est assez fragmenté. A la limite je peux fournir le code dans lequel je construis les 2 points de vue. Le voici :
if (stereo) {
//# (0) ##################
Matrix4d invViewMatrix = new Matrix4d(viewMatrix);
invViewMatrix.invert();
Vector4d viewPosWorldSpace = new Vector4d(0.0, 0.0, 0.0, 1.0);
Vector4d viewDirWorldSpace = new Vector4d(0.0, 0.0, -1.0, 0.0);
invViewMatrix.transform(viewPosWorldSpace);
invViewMatrix.transform(viewDirWorldSpace);
double viewZ =
Math.abs(viewPosWorldSpace.dot(viewDirWorldSpace))
;
//# (1) ##################
int reso =
ShaoEngineFrameManager.INSTANCE.getRenderingFrame(
).getToolkit().getScreenResolution();
//# (2) ##################
Matrix4d mat = graphicsContext.getInverseModelMatrix();
double distanceOfTheScreenInPixels = (3000.0 / 25.4) * reso;
Point3d pt = new Point3d(distanceOfTheScreenInPixels, 0.0, 0.0);
mat.transform(pt, pt);
double distanceOfTheScreenInModel = pt.getX();
//# (3) ##################
double intervalEyesInPixels = (45.0 / 25.4) * reso;
Point3d pt2 = new Point3d(intervalEyesInPixels, 0.0, 0.0);
mat.transform(pt2, pt2);
double intervalEyesInModel = pt2.getX();
//# (4) ##################
double ratio = width / (double) height;
double totalLength = viewZ + distanceOfTheScreenInModel;
double leftRIGHT = -ratio * near - intervalEyesInModel * (near / totalLength) * 0.5;
double rightRIGHT = ratio * near - intervalEyesInModel * (near / totalLength) * 0.5;
leftRIGHT /= rightRIGHT;
rightRIGHT /= rightRIGHT;
double leftLEFT = -ratio * near + intervalEyesInModel * (near / totalLength) * 0.5;
double rightLEFT = ratio * near + intervalEyesInModel * (near / totalLength) * 0.5;
leftLEFT /= rightLEFT;
rightLEFT /= rightLEFT;
//================
graphicsContext.clear(SHAOGL.GL_COLOR_BUFFER_BIT | SHAOGL.GL_DEPTH_BUFFER_BIT | SHAOGL.GL_STENCIL_BUFFER_BIT | SHAOGL.GL_STEREO);
graphicsContext.setProjectionMatrix(leftRIGHT, rightRIGHT, -ratio, ratio, near, far, true);
graphicsContext.drawBuffer(SHAOGL.GL_BACK_RIGHT);
viewMatrix.setM03(- intervalEyesInModel / 4.0);
graphicsContext.setViewModelMatrix(modelMatrix, viewMatrix, true);
graphicsContext.setViewport(0, 0, width, height);
// Traverse scene graph
if (rootNode != null) rootNode.traverse(rv);
graphicsContext.setProjectionMatrix(leftLEFT, rightLEFT, -ratio, ratio, near, far, true);
graphicsContext.drawBuffer(SHAOGL.GL_BACK_LEFT);
viewMatrix.setM03(intervalEyesInModel / 4.0);
graphicsContext.setViewModelMatrix(modelMatrix, viewMatrix, true);
// Traverse scene graph
if (rootNode != null) rootNode.traverse(rv);
graphicsContext.flush();
}
Bon il y a pas mal de choses à améliorer, notamment des calculs à simplifier, mais j'ai tellement tenté de choses que mon code en est là pour l'instant. Peut-être que certaines choses ne sont pas très justes, après tout sans rendu stéréoscopique je peux difficilement m'en rendre compte ^^
"Et donne voir aussi le modèle de la TV 3D"
J'ai une LG LED 3D 139cm, lunettes passives, achetée en Décembre.
Concernant le GPU j'ai lu de tout, donc j'avoue ne pas savoir si je peux avoir ce rendu stéréoscopique...
Ah et pour info, je ne crois pas l'avoir précisé, mais c'est un pc portable muni d'une carte NVidia GeForce 9600M GT 512 MB ![]()
"Oui. Voici ce que j'ai à l'écran : http://desmond.imageshack.us/Himg808/scaled.php?server=808&filename=screen3dj.png&res=landing
(à noter qu'en mode non stereo la ligne rouge se trouve sur le plan x=0 et parait une ligne du même point de vue que ce screen)."
J'avoue que je ne vois pas grand chose sur cette image : qu'est-ce qu'est sensé voir l'oeil gauche et qu'est-ce qu'est sensé voir l'oeil droit ? La ligne rouge devrait-elle marquer la séparation entre les images destinés à chaque oeil ?
L'image qu'on doit s'attendre à voir avec du side by side est une image de ce type :
http://www.hdfever.fr/wp-content/uploads/2010/03/sidebyside01.jpg
Avec l'image oeil gauche et l'image oeil droit clairement côte à côte.
Concernant le code :
"graphicsContext.clear(SHAOGL.GL_COLOR_BUFFER_BIT | SHAOGL.GL_DEPTH_BUFFER_BIT | SHAOGL.GL_STENCIL_BUFFER_BIT | SHAOGL.GL_STEREO); "
Pour de la stéréo passive, je ne pense pas qu'il faille passer GL_STEREO en paramètre, mais à vérifier.
"graphicsContext.drawBuffer(SHAOGL.GL_BACK_RIGHT);
"
Si je comprends bien, ici tu dessines dans le buffer GL_BACK_RIGHT ? Ça ne doit pas être nécessaire pour de la stéréo passive : tu n'as besoin que d'un seul buffer dans lequel écrire les données de chacun des yeux, comme un rendu OpenGL classique sans stéréoscopie. A mon avis les deux lignes :
graphicsContext.drawBuffer(SHAOGL.GL_BACK_RIGHT);
graphicsContext.drawBuffer(SHAOGL.GL_BACK_LEFT);
Peuvent être commentées sans problème.
Enfin concernant la fonction rootNode.traverse(rv), si cette fonction est celle qui te permet de faire le rendu de ta scène, elle devrait être précédée par un appel à glViewport te permettant de spécifier dans quelle partie de l'écran le rendu devrait être fait.
C'est-à-dire que l'appel à cette fonction doit être précédé de :
graphicsContext.setViewport(0, 0, width / 2, height); pour l'oeil gauche
graphicsContext.setViewport(width / 2, 0, width, height); pour l'oeil droit
"J'ai une LG LED 3D 139cm, lunettes passives, achetée en Décembre. "
Tu n'aurais pas le nom exact du modèle par hasard ?
Quoique normalement ça devrait fonctionner avec ta TV, apparemment les chaînes de TV 3D diffusent en side by side donc ça devrait marcher.
"Ah et pour info, je ne crois pas l'avoir précisé, mais c'est un pc portable muni d'une carte NVidia GeForce 9600M GT 512 MB
"
Ah quand même, c'est pas du tout neuf ![]()
Pour la stéréo active c'est mort, et pour la stéréo passive faudra pas trop monter en résolution mais ça devrait marcher : la résolution max par oeil sera 1280 x 800 en 16:10 ou 1280x720 en 16:9. Sur un écran aussi grand ça peut être gênant, faudra éviter de se mettre trop prêt.
N'hésites pas à montrer un peu ton code si tu veux qu'on t'aide mieux.
Ca va être difficile, j'ai une centaine de classes donc c'est
assez fragmenté. A la limite je peux fournir le code dans lequel je
construis les 2 points de vue.
Personnellement, si j'avais un projet comme celui la. Je commenderais par essayer d'afficher un teapot en 3D stereoscopique avant de brancher le tout dans mon programme complexe.
"J'avoue que je ne vois pas grand chose sur cette image : qu'est-ce qu'est sensé voir l'oeil gauche et qu'est-ce qu'est sensé voir l'oeil droit ? La ligne rouge devrait-elle marquer la séparation entre les images destinés à chaque oeil ? "
En fait les deux images sont dessinées sur la même avec les 2 buffers. Disons que ça ressemblait un peu à la duplication des éléments quand on regarde une scène 3D stéréoscopique sans les lunettes, mais je ne savais pas du coup comment avoir un tel rendu, que je vois presque tous les jours avec mes jeux PS3.
Concernant le viewport, il suffit de rajouter le second set avant le rendu de la seconde scène (la méthode traverse()). Si je comprends bien tu me dis de laisser tomber le coup du stereo et des 2 buffers, donc le code que j'ai mis ne correspond pas.
Ceci dit quand je tentais avec le viewport je ne faisait pas du "width / 2", faudra que je tente demain (un peu tard là ^^).
Et en faisant ça tu penses que la télé retranscrirait ça à l'écran tout seul ?
Pour ce qui est du modèle de ma télé : C'est la LG 55LW4500 LED 3D 139cm
"Personnellement, si j'avais un projet comme celui la. Je commenderais par essayer d'afficher un teapot en 3D stereoscopique avant de brancher le tout dans mon programme complexe. "
Remarque pertinente. J'ai tendance à me compliquer la tâche !