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

DirectX Discussion :

[c#] Normal map, heigthmap et multitexturing


Sujet :

DirectX

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 134
    Points : 75
    Points
    75
    Par défaut [c#] Normal map, heigthmap et multitexturing
    Bonjour,

    Je me penche actuellement sur la génération d'un terrain basé sur une heigthmap. Cependant je souhaite utiliser la technique du normal mapping en multitexturing. Pour schématiser, je souhaite utiliser 4 stages par couche (type de terrain : herbe, terre, roche etc). Le premier stage est celui de mon alphamap, le deuxième la normal map, le troisième la texture et le quatrième la texture de détail pour réhausser le niveau graphique, pour l'instant, sans envisager la gestion des Pixel/vertex shader. Voici une partie du 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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    //texture stage : 0 : alpha map
                /////////////////////
                this.app.device.TextureState[0].ColorOperation = TextureOperation.SelectArg1;
                this.app.device.TextureState[0].ColorArgument1 = TextureArgument.TextureColor;
                this.app.device.TextureState[0].AlphaOperation = TextureOperation.SelectArg1;
                this.app.device.TextureState[0].AlphaArgument1 = TextureArgument.TextureColor;
                this.app.device.TextureState[0].ResultArgument = TextureArgument.Current;
     
                //texture stage : 1 : normal map
                /////////////////////
                this.app.device.TextureState[1].ColorOperation = TextureOperation.Modulate;
                this.app.device.TextureState[1].ColorArgument1 = TextureArgument.TextureColor;
                this.app.device.TextureState[1].ColorArgument2 = TextureArgument.Current;
                this.app.device.TextureState[1].AlphaOperation = TextureOperation.Disable;
                this.app.device.TextureState[1].ResultArgument = TextureArgument.Current;
     
     
                //texture stage : 2 : texture
                /////////////////////
                this.app.device.TextureState[2].ColorOperation = TextureOperation.DotProduct3;
                this.app.device.TextureState[2].ColorArgument1 = TextureArgument.TFactor;
                this.app.device.TextureState[2].ColorArgument2 = TextureArgument.Current;
                this.app.device.TextureState[2].AlphaOperation = TextureOperation.Disable;
                this.app.device.TextureState[2].ResultArgument = TextureArgument.Current;
     
                //texture stage : 3 : texture
                /////////////////////
                this.app.device.TextureState[3].ColorOperation = TextureOperation.Modulate;
                this.app.device.TextureState[3].ColorArgument1 = TextureArgument.Current;
                this.app.device.TextureState[3].ColorArgument2 = TextureArgument.TextureColor;
                this.app.device.TextureState[3].AlphaOperation = TextureOperation.Disable;
                this.app.device.TextureState[3].ResultArgument = TextureArgument.Current;
    Evidemment, je ne vous chache pas que ça ne donne pas le résultat escompté... j'en suis proche mais ce n'est pas ça. La superposition des couches grâce à mes alphamaps occupent toute la map pour chaque couche (ex : la couche d'herbe affichée en premier sera entièrement recouverte par la deuxième couche et ainsi de suite jusqu'à la dernière).

    Auriez-vous une idée de ce qui cloche et est ce bien réalisable sans les pixel/vertex shaders ? merci

  2. #2
    Membre actif
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    267
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 267
    Points : 275
    Points
    275
    Par défaut
    'Alut.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this.app.device.TextureState[0].AlphaArgument1 = TextureArgument.TextureColor;
    OK tu modules la couleur présente par l'alpha de ta alphamap.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this.app.device.TextureState[1].AlphaOperation = TextureOperation.Disable;
    Ah non, on ne doit pas désactiver l'alpha quand une opération sur les couleurs est effectué.
    Il te faut AlphaOp = SelectArg1 et AlphaArg1 = Current sur tous les étages après ton alpha map.
    Et tout à la fin :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    this.app.device.TextureState[4].ColorOperation = TextureOperation.Disable
    this.app.device.TextureState[4].AlphaOperation = TextureOperation.Disable
    En gros:
    1ere couche (herbe par exemple):
    pas d'alpha
    2eme couche et les autres:
    alpha sur toutes tes maps

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 134
    Points : 75
    Points
    75
    Par défaut
    J'ai essayé ceci avec tes conseils mais ça ne fonctionne pas :

    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
     
     //texture stage : 0 : alpha map  /////////////////////  
                this.app.device.TextureState[0].ColorOperation = TextureOperation.SelectArg1; 
                this.app.device.TextureState[0].ColorArgument1 = TextureArgument.TextureColor; 
                this.app.device.TextureState[0].AlphaOperation = TextureOperation.SelectArg1; 
                this.app.device.TextureState[0].AlphaArgument1 = TextureArgument.TextureColor; 
                this.app.device.TextureState[0].ResultArgument = TextureArgument.Current;   
                //texture stage : 1 : normal map  /////////////////////  
                this.app.device.TextureState[1].ColorOperation = TextureOperation.Modulate; 
                this.app.device.TextureState[1].ColorArgument1 = TextureArgument.TextureColor; 
                this.app.device.TextureState[1].ColorArgument2 = TextureArgument.Current;
                this.app.device.TextureState[1].AlphaOperation = TextureOperation.SelectArg1;
                this.app.device.TextureState[1].AlphaArgument1 = TextureArgument.Current; 
                this.app.device.TextureState[1].ResultArgument = TextureArgument.Current;     
                //texture stage : 2 : texture  /////////////////////  
                this.app.device.TextureState[2].ColorOperation = TextureOperation.DotProduct3; 
                this.app.device.TextureState[2].ColorArgument1 = TextureArgument.TFactor; 
                this.app.device.TextureState[2].ColorArgument2 = TextureArgument.Current;
                this.app.device.TextureState[2].AlphaOperation = TextureOperation.SelectArg1;
                this.app.device.TextureState[2].AlphaArgument1 = TextureArgument.Current; 
                this.app.device.TextureState[2].ResultArgument = TextureArgument.Current;   
                //texture stage : 3 : texture  /////////////////////  
                this.app.device.TextureState[3].ColorOperation = TextureOperation.Modulate; 
                this.app.device.TextureState[3].ColorArgument1 = TextureArgument.Current; 
                this.app.device.TextureState[3].ColorArgument2 = TextureArgument.TextureColor;
                this.app.device.TextureState[3].AlphaOperation = TextureOperation.SelectArg1;
                this.app.device.TextureState[3].AlphaArgument1 = TextureArgument.Current; 
                this.app.device.TextureState[3].ResultArgument = TextureArgument.Current;
    Puis voici la boucle où j'affiche chaque couche "de vertex", ça sera plus explicite :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    for ( i = this.alphaMap.Length - 1 ; i > -1; i--)          
              {
                this.app.device.SetTexture(0, this.alphaMap[k]);
                this.app.device.SetTexture(1, this.texNormalMap[k]);
                this.app.device.SetTexture(2, this.texMap[k]);
                this.app.device.SetTexture(3, this.texDetail[k]);    
     
                this.app.device.Transform.World = Matrix.Translation(new Vector3(0f, this.coefLayer * i, 0) + this.app.Camera.position);            
                this.app.device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, this.nbSommet, 0, this.nbPrimitives);
              }

  4. #4
    Membre actif
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    267
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 267
    Points : 275
    Points
    275
    Par défaut
    J'ai un peu du mal avec ta normal map et la mainère dont tu la lies à la couche alpha... Perso, je mettrais:
    1: alphamap
    2: la texture (couleurs = texture et alpha = alpha étage précédent)
    3: la texture2 (couleurs = modulation et alpha = alpha étage précédent)
    4: normal map (couleurs = transformation et alpha = alpha étage précédent)


    Sinon, voici une partie de la boucle de rendu de mon terrain (c++). Je me suis fortement inspiré du projet http://jeux.developpez.com/sources/d...NIQUES_terrain. Il y a 3 couches. Les normales sont inclues dans les vertex buffer.

    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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    IRenderer::Instance().SetMaterial(&m_DefaultMaterial);
    
    // Initialisation
    //    Melange avec l'alpha
    //    Utilisation de la couleur fournie par le matériel
    //    Wrap des textures
    IRenderer::Instance().SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
    IRenderer::Instance().SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
    IRenderer::Instance().SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
    IRenderer::Instance().SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
    IRenderer::Instance().SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
    IRenderer::Instance().SetSamplerState(0, D3DSAMP_ADDRESSU,  D3DTADDRESS_WRAP);
    IRenderer::Instance().SetSamplerState(0, D3DSAMP_ADDRESSV,  D3DTADDRESS_WRAP);
    IRenderer::Instance().SetSamplerState(1, D3DSAMP_ADDRESSU,  D3DTADDRESS_WRAP);
    IRenderer::Instance().SetSamplerState(1, D3DSAMP_ADDRESSV,  D3DTADDRESS_WRAP);
    
    // Rendu de la permière couche du terrain : herbe
    // Pas de mélange alpha
    // Stage 0 : Texture
    IRenderer::Instance().SetTextureStageState (0, D3DTSS_COLOROP,   D3DTOP_MODULATE);
    IRenderer::Instance().SetTextureStageState (0, D3DTSS_COLORARG2, D3DTA_TEXTURE);
    IRenderer::Instance().SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE );
    IRenderer::Instance().SetTextureStageState (0, D3DTSS_ALPHAOP,   D3DTOP_DISABLE);
    IRenderer::Instance().SetTextureStageState (1, D3DTSS_COLOROP,   D3DTOP_DISABLE);
    IRenderer::Instance().SetTextureStageState (1, D3DTSS_ALPHAOP,   D3DTOP_DISABLE);
    // On change l'index des coordonnées de textures
    IRenderer::Instance().SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 1);
    IRenderer::Instance().SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
    IRenderer::Instance().SetTexture(0, m_Texture[0]);
    
    ...Rendu des primitives
    
    // Rendu des autres couches (mélange alpha)
    // Stage 0 : alpha
    // Stage 1 :texture
    IRenderer::Instance().SetTextureStageState (0, D3DTSS_COLOROP,   D3DTOP_SELECTARG1);
    IRenderer::Instance().SetTextureStageState (0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
    IRenderer::Instance().SetTextureStageState (0, D3DTSS_ALPHAOP,   D3DTOP_SELECTARG1);
    IRenderer::Instance().SetTextureStageState (0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
    IRenderer::Instance().SetTextureStageState (1, D3DTSS_COLOROP,   D3DTOP_MODULATE);
    IRenderer::Instance().SetTextureStageState (1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
    IRenderer::Instance().SetTextureStageState (1, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
    IRenderer::Instance().SetTextureStageState (1, D3DTSS_ALPHAOP,   D3DTOP_SELECTARG1);
    IRenderer::Instance().SetTextureStageState (1, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
    IRenderer::Instance().SetTextureStageState (2, D3DTSS_COLOROP,   D3DTOP_DISABLE);
    IRenderer::Instance().SetTextureStageState (2, D3DTSS_ALPHAOP,   D3DTOP_DISABLE);
    
    IRenderer::Instance().SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
    IRenderer::Instance().SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
    
    IRenderer::Instance().SetTexture(1, m_Texture[1]);
    IRenderer::Instance().SetTexture(0, m_DensityTexture[0]);
    ...Rendu des primitives
    
    IRenderer::Instance().SetTexture(1, m_Texture[2]);
    IRenderer::Instance().SetTexture(0, m_DensityTexture[1]);
    ...Rendu des primitives
    
    //Fin du rendu
    IRenderer::Instance().SetTexture(0, NULL);
    IRenderer::Instance().SetTexture(1, NULL);
    Enfin, je te conseille de commencer tout d'abord uniquement avec une texture et l'alpha Tu rajouteras par la suite la normal map et la deuxieme texture. Vérifie aussi les paramètres d'initialisation pour le mélange alpha (la partie en gras dans mon code). Désolé mais je ne connais pas leur équivalent c#.

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 134
    Points : 75
    Points
    75
    Par défaut
    voici où j'en suis :

    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
     // normal map
                this.app.device.SetTextureStageState(0, TextureStageStates.ColorOperation, (int)TextureOperation.DotProduct3);
                this.app.device.SetTextureStageState(0, TextureStageStates.ColorArgument1, (int)TextureArgument.TextureColor);
                this.app.device.SetTextureStageState(0, TextureStageStates.ColorArgument2, (int)TextureArgument.TFactor);
                this.app.device.SetTextureStageState(0, TextureStageStates.AlphaOperation, (int)TextureOperation.Disable);            
     
                // texture
                this.app.device.SetTextureStageState(1, TextureStageStates.ColorOperation, (int)TextureOperation.Modulate);
                this.app.device.SetTextureStageState(1, TextureStageStates.ColorArgument1, (int)TextureArgument.TextureColor);
                this.app.device.SetTextureStageState(1, TextureStageStates.ColorArgument2, (int)TextureArgument.Current);
                this.app.device.SetTextureStageState(1, TextureStageStates.AlphaOperation, (int)TextureOperation.Disable);            
     
                // détail
                this.app.device.SetTextureStageState(2, TextureStageStates.ColorOperation, (int)TextureOperation.Modulate);            
                this.app.device.SetTextureStageState(2, TextureStageStates.ColorArgument1, (int)TextureArgument.TextureColor);
                this.app.device.SetTextureStageState(2, TextureStageStates.ColorArgument2, (int)TextureArgument.Current);
                this.app.device.SetTextureStageState(2, TextureStageStates.AlphaOperation, (int)TextureOperation.Disable);                 
     
                // alpha map
                this.app.device.SetTextureStageState(3, TextureStageStates.ColorOperation, (int)TextureOperation.Modulate);
                this.app.device.SetTextureStageState(3, TextureStageStates.ColorArgument1, (int)TextureArgument.Current);
                this.app.device.SetTextureStageState(3, TextureStageStates.ColorArgument2, (int)TextureArgument.TextureColor);            
                this.app.device.SetTextureStageState(3, TextureStageStates.AlphaOperation, (int)TextureOperation.Modulate);
                this.app.device.SetTextureStageState(3, TextureStageStates.AlphaArgument1, (int)TextureArgument.TextureColor);
                this.app.device.SetTextureStageState(3, TextureStageStates.AlphaArgument2, (int)TextureArgument.Current);
    Cependant l'effet souhaité n'est pas vraiment celui que j'attendais (cf miniature jointe). Je ne vois pas trop ce que je peux faire...
    Images attachées Images attachées  

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 134
    Points : 75
    Points
    75
    Par défaut
    une autre image plus explicite mais très étrange... Le normalmap fonctionne uniquement en haut à droite de l'écran si je mets à plus de 8f les valeurs suivantes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    verts[i].Tu2 = (float)x / 16f;
    verts[i].Tv2 = (float)y / 16f;
    Images attachées Images attachées  

  7. #7
    Membre actif
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    267
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 267
    Points : 275
    Points
    275
    Par défaut
    une autre image plus explicite mais très étrange... Le normalmap fonctionne uniquement en haut à droite de l'écran
    Il s'agit d'un mauvais adressage des textures. Dans ton coin en haut à droite, Tu2 et Tv2 sont compris entre 0 et 1, tout va bien. Ailleurs Tu2 et Tv2 sont supérieures à 1. Tu peux activer le wrapping qui va répéter la texture ( en C++: SetSamplerState(idSampler, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP) ou bien moduler tes coordonnées de textures pour avoir des valeurs comprises entre 0 et 1.

  8. #8
    Membre actif
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    267
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 267
    Points : 275
    Points
    275
    Par défaut
    En ce qui concerne la premiere image, j'ai l'impression que ton fond d'écran est aussi pris en compte pour le mélange alpha. N'oublies pas de désactiver l'alpha lors du rendu de la premiere couche.

    La premiere couche doit être affichée partout. Il n'y a pas de mélange alpha. Ce sont les couches suivantes qui viendront se superposer (avec l'alpha) à la première.

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 134
    Points : 75
    Points
    75
    Par défaut
    ça fonctionne déjà bien mieux grâce à tes conseils ! merci beaucoup

    cependant, l'effet est statique, ie que lorsqu'on tourne la caméra l'effet normalmap ne se recalcule pas. C'est comme si l'effet était précalculé (sous photoshop par exemple) donc y a pas l'aspect bluffant du normal mapping... encore un problème à résoudre.

    voici une image du résultat en miniature.
    Images attachées Images attachées  

Discussions similaires

  1. OGRE et le normal mapping
    Par supermael dans le forum Ogre
    Réponses: 4
    Dernier message: 05/10/2010, 10h39
  2. Deferred shading: comment faire du normal mapping
    Par zenux dans le forum API graphiques
    Réponses: 6
    Dernier message: 02/07/2010, 03h45
  3. [OpenGL/GLSL] Utilisation Normal Map
    Par AuraHxC dans le forum OpenGL
    Réponses: 3
    Dernier message: 31/01/2010, 11h45
  4. Création d'une "Normal map"
    Par Jérôme.O[76] dans le forum PureBasic
    Réponses: 0
    Dernier message: 23/12/2008, 00h02

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