IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

OpenGL Discussion :

Des ombres dynamiques dans un monde en voxel [OpenGL 3.x]


Sujet :

OpenGL

  1. #1
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2009
    Messages : 91
    Points : 65
    Points
    65
    Par défaut Des ombres dynamiques dans un monde en voxel
    Bonjour à tous.

    Aujourd'hui je viens solliciter votre aide car j'aurais besoin de conseils. En effet, j'aimerais implanter les ombres (dynamiques) dans un monde composé de cubes.
    J'ai commencé à me renseigner, et j'ai notamment trouvé la technique du shadow mapping.
    D'après ce que j'ai vu, le principe serait (si j'ai bien compris) d'afficher un objet dans une texture (par exemple l'objet en noir, sur un fond blanc) avec un framebuffer, et ensuite de projeter cette texture sur la surface où on veut les ombres.

    Pour une scène "classique", je vois le principe, mais pour un monde composé de cubes, donc avec beaucoup d'objets et beaucoup de surfaces sur lesquelles je peux afficher les ombres, j'ai vraiment du mal à voir comment faire pour ce type de scène.

    Pourriez-vous m'aider, en m'expliquant comment je pourrais procéder, ou encore en me proposant une technique plus pratique dans mon cas ?
    Merci d'avance.

  2. #2
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 859
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 859
    Points : 218 580
    Points
    218 580
    Billets dans le blog
    120
    Par défaut
    Bonjour,

    Vous ne semblez pas avoir exactement saisi le principe.
    Pour le shadow mapping de base, vous devez :
    - faire le rendu de votre scène, à la position de la lumière. Ce rendu va ainsi compléter un tampon de profondeur que l'on sauvegardera dans une texture (voir les FBO).
    - faire le rendu de votre scène, à la position de la caméra. Durant ce rendu, pour chaque pixel (donc, dans le pixel shader), vous allez comparer la profondeur du pixel actuel avec la profondeur correspondant, de la texture de profondeur du rendu précédent. Si la profondeur actuelle est supérieure à celle indiquée dans la texture, alors le pixel doit être ombré.

    Voilà. Dans le pixel shader, il y a quelques astuces, notamment pour déterminer quel pixel correspond à quel pixel dans la texture. Il y aura encore quelques autres trucs, mais là, vous avez le principe de base.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  3. #3
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2009
    Messages : 91
    Points : 65
    Points
    65
    Par défaut
    Ah d'accord, merci pour l'explication

    Je pense avoir réussi à générer ma shadow map.
    Maintenant il faut que je teste chaque pixel. Et là, je vois pas comment transformer mes coordonnées 3d en coordonnées 2D correspondant à la texture.
    Mes matrices concernant la depth map sont les suivantes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    glm::mat4 matriceProjection(glm::ortho(-(float)800 / 600 * ratio, (float)800 / 600 * ratio, -(float)800 / 600 * ratio, (float)800 / 600 * ratio, 0.1f, 10000.0f));
    glm::mat4 matriceVue(glm::lookAt(glm::vec3(0, 0, 500), glm::vec3(1, 1, 498), glm::vec3(0, 0, 1)));
    Comment puis-je récupérer les coordonnées de la shadow map pour chaque pixel ?
    Merci d'avance.

  4. #4
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 859
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 859
    Points : 218 580
    Points
    218 580
    Billets dans le blog
    120
    Par défaut
    J'ai enfin le plaisir de vous annoncé que vous allez trouver l'explication de cette transformation dans ce tutoriel, en français !
    Désolé du retard que j'ai pris à répondre.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  5. #5
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2009
    Messages : 91
    Points : 65
    Points
    65
    Par défaut
    Désolé moi aussi de répondre si tard, ces derniers temps j'ai pas trop pu retoucher à mon jeu.
    Merci beaucoup pour ce tutoriel qui est très bien expliqué (j'avais du croiser le même en anglais, mais j'avais pas tout compris)

    Bon, malheureusement, j'ai pas réussi à afficher mes ombres correctement car j'ai du faire une erreur quelque part.
    J'ai réussi à cerner un peu l'erreur, elle vient de la texture de profondeur qui reste tout simplement vide, mais incapable de trouver d'où ça vient.

    Je génère la texture avec cette fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    void Terrain::creerShadowMap()
    {
    	glm::mat4 matriceProjection = glm::ortho<float>(-25 * 10, 25 * 10, -25 * 10, 25 * 10, -25 * 10, 25 * 10);
    	glm::mat4 matriceVue = glm::lookAt(glm::vec3(25 * 5, 25 * 5, 25 * 5), glm::vec3(0, 0, 1000), glm::vec3(0, 0, 1));
     
     
    	glUseProgram(m_shaderProfondeur.identifiant());
    	glBindFramebuffer(GL_FRAMEBUFFER, m_frameBufferProfondeur.identifiant());
     
    	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
    	for (int x = 0; x < m_tailleTerrain; ++x)
    	{
    		for (int y = 0; y < m_tailleTerrain; ++y)
    		{
    			for (int z = 0; z < m_tailleTerrain; ++z)
    				m_regions[x][y][z]->afficher(m_shaderProfondeur, matriceProjection * matriceVue);
    		}
    	}
     
    	glBindFramebuffer(GL_FRAMEBUFFER, 0);
    	glUseProgram(0);
    }
    Les matrices d'affichage et de projection semblent bonnes, je les avait testés directement en temps que caméra de la scène. Et la fonction de la ligne 17 fonctionne aussi correctement.

    J'ai donc pensé que ça pouvait venir du framebuffer, ou de la texture en elle même.
    Le framebuffer est initialisé comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    glGenFramebuffers(1, &m_identifiant);
     
    	glBindFramebuffer(GL_FRAMEBUFFER, m_identifiant);
    	Texture colorBuffer;
    	colorBuffer.charger(m_taille);
    	m_colorBuffers.push_back(colorBuffer);
     
    	if (glIsRenderbuffer(m_identifiantDepthBuffer) == GL_TRUE)
    		glDeleteRenderbuffers(1, &m_identifiantDepthBuffer);
    	glGenRenderbuffers(1, &m_identifiantDepthBuffer);
     
    	glBindRenderbuffer(GL_RENDERBUFFER, m_identifiantDepthBuffer);
    	glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, m_taille.x, m_taille.y);
    	glBindRenderbuffer(GL_RENDERBUFFER, 0);
     
    	glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_colorBuffers[0].identifiant(), 0);
    	glFramebufferRenderbuffer(GL_FRAMEBUFFER, (m_utiliserStencilBuffer ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT), GL_RENDERBUFFER, m_identifiantDepthBuffer);
    	glDrawBuffer(GL_NONE);
     
    	if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
    	{
    		glDeleteFramebuffers(1, &m_identifiant);
    		glDeleteRenderbuffers(1, &m_identifiantDepthBuffer);
    		m_colorBuffers.clear();
     
    		std::cout << "[ERREUR] Initialisation du Frame Buffer" << std::endl;
    		return false;
    	}
     
    	glBindFramebuffer(GL_FRAMEBUFFER, 0);
    Et la texture :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    if (glIsTexture(m_identifiant) == GL_TRUE)
    		glDeleteTextures(1, &m_identifiant);
    	glGenTextures(1, &m_identifiant);
     
    	glBindTexture(GL_TEXTURE_2D, m_identifiant);
    	glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, m_tailleTexture.x, m_tailleTexture.y, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
    	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    	glBindTexture(GL_TEXTURE_2D, 0);
    L'erreur viendrait-il d'un des deux derniers bouts de code ?
    Si jamais y a besoin je peux fournir le projet complet pour que ce soit plus "simple" (même si c'est pas forcement bien commenté).

    Merci d'avance.

  6. #6
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2009
    Messages : 91
    Points : 65
    Points
    65
    Par défaut
    Bon j'ai passé pas mal d'heure à chercher la petite bête, en modifiant tout un tas de chose. J'ai notamment recodé tout le framebuffer+texture de manière "simplifiée", et fais des tests à coup de glReadPixels.
    Le glReadPixels m'indique au final que la texture est correctement créée, le problème vient donc de la lecture de celle-ci lors de l'affichage final.

    Méthode d'affichage :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    glUseProgram(m_shaderOmbres.identifiant());
    	glBindTexture(GL_TEXTURE_2D, m_frameBufferProfondeur.identifiantTexture());
     
    	glm::mat4 matriceProjection = glm::ortho<float>(-25 * 10, 25 * 10, -25 * 10, 25 * 10, -25 * 10, 25 * 10);
    	glm::mat4 matriceVue = glm::lookAt(glm::vec3(25 * 5, 25 * 5, 25 * 5), glm::vec3(0, 0, 1000), glm::vec3(0, 0, 1));
     
    	glUniform1f(glGetUniformLocation(m_shaderOmbres.identifiant(), "luminositeAmbiante"), glm::abs(m_luminositeAmbiante));
    	glUniformMatrix4fv(glGetUniformLocation(m_shaderOmbres.identifiant(), "matriceAffichageOmbres"), 1, GL_FALSE, glm::value_ptr(matriceProjection * matriceVue));
     
    	for (int x = 0; x < m_tailleTerrain; ++x)
    	{
    		for (int y = 0; y < m_tailleTerrain; ++y)
    		{
    			for (int z = 0; z < m_tailleTerrain; ++z)
    				m_regions[x][y][z]->afficher(m_shaderOmbres, matriceAffichage);
    		}
    	}
     
    	glBindTexture(GL_TEXTURE_2D, 0);
    	glUseProgram(0);
    La fonction afficher() des régions :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    void Region::afficher(const Shader& shader, const glm::mat4& matriceAffichage)
    {
    	if (m_nombreCubesAffiches != 0)
    	{
    		glBindVertexArray(m_identifiantVAOAffichage);
     
    		glUniformMatrix4fv(glGetUniformLocation(shader.identifiant(), "matriceAffichage"), 1, GL_FALSE, glm::value_ptr(matriceAffichage));
    		glUniform3fv(glGetUniformLocation(shader.identifiant(), "coordonneesRegion"), 1, glm::value_ptr(m_coordonnees));
    		glDrawArrays(GL_POINTS, 0, m_nombreCubesAffiches);
     
    		glBindVertexArray(0);
    	}
    }
    Voici le fragment shader :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #version 330 compatibility
     
    in vec4 coordonneesOmbres;
     
    uniform sampler2D textures;
     
    out vec4 out_couleurs;
     
    void main()
    {
    	if (texture2D( textures, coordonneesOmbres.xy).z == 1)    // Condition toujours vraie, pourtant ma texture n'est pas vide
    		out_couleurs = vec4(0, 0, 0, 0.5);
    	else
    		out_couleurs = vec4(0, 0, 0, 0);
    }
    Voyez-vous où est l'erreur ?
    Merci d'avance.

    EDIT :
    C'est bon, il semblerait que j'arrive à lire la texture maintenant (par contre je sais pas comment, à force de bidouiller...).
    Bon par contre j'ai toujours pas le bon résultat quand je fait mon fragment shader comme dans le tuto :
    http://hpics.li/ac82eb4

    Le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #version 330 compatibility
     
    in vec4 coordonneesOmbres;
     
    uniform sampler2D textures;
     
    out vec4 out_couleurs;
     
    void main()
    {
    	if (texture2D( textures, coordonneesOmbres.xy).z < coordonneesOmbres.z)
    		out_couleurs = vec4(0, 0, 0, 0.5);
    	else
    		out_couleurs = vec4(0, 0, 0, 0);
    }
    EDIT 2 : en faite c'est bon, j'ai réussi à corriger le bug. C'est que ma caméra était dans la direction opposée, du coup les ombres étaient pas projetés sur les bonnes faces.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Problème]Nombre et nom des champs dynamiques dans un form
    Par julienOriano dans le forum Struts 1
    Réponses: 17
    Dernier message: 10/04/2007, 15h32
  2. Réponses: 5
    Dernier message: 19/02/2007, 15h44
  3. Creér des Clip dynamiquement dans la scène
    Par jpboogie dans le forum Flash
    Réponses: 2
    Dernier message: 04/10/2006, 16h47
  4. Réponses: 4
    Dernier message: 19/05/2006, 14h30
  5. Réponses: 5
    Dernier message: 22/08/2005, 16h48

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo