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

XNA/Monogame Discussion :

Les shaders avec XNA


Sujet :

XNA/Monogame

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    117
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2005
    Messages : 117
    Points : 76
    Points
    76
    Par défaut Les shaders avec XNA
    Bonjour à tous,

    je développe actuellement un petit jeu en 3D et je voudrais commencer à créer quelques effets. Ceux-ci pourraient par exemple, simuler une forte intensité de lumière d'un coup, et donc saturer les couleurs de l'écran. Seulement voilà je me pose la question suivante : Y a-t-il un moyen d'appliquer l'effet a chaque pixel de l'écran directement, ou bien faut-il d'abord rendre la scène, puis appliquer l'effet l'image résultante et l'afficher ensuite ?

    Merci.

  2. #2
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Pour faire un post-effect il faut d'abord rendre la scène dans une texture.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    366
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 366
    Points : 440
    Points
    440
    Par défaut
    Ca va dependre de l effet ... tu peux faire un rendu sur l ecran si les operations de blending te suffisent pour combiner les pixels de l image normale et de l effet.

    Si par exemple, tu souhaites simplement ajouter une couleur blanche constante sur tout l ecran , un blending avec l operation ADD en rendant un screen-aligned rectangle suffit

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    117
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2005
    Messages : 117
    Points : 76
    Points
    76
    Par défaut
    Merci pour vos réponses .

    smashy : Pour l'instant, les opérations de blending me suffiraient sans doute, mais petit à petit je vais rendre les opérations plus complexes dont je pense qu'il vaut mieux que j'utilise directement la méthode pour le post effect.

    Alors j'ai cherché un petit peu, et en me basant sur l'exemple donné par microsoft, j'ai essayé d'appliquer un effet sur une texture simple d'abord, là tout fonctionne sans problème, par contre quand j'en arrive à la 3D y a quelque chose qui va pas. A partir du moment ou j'applique l'effet, rien ne va plus : les coordonnées des textures sont complètements faussées. Je croyais que c'était un problème dans le shader mais apparemment c'est pire, car quand j'enlève l'application de l'effet, et que je fais un rendu simple de la scène, l'effet persiste (aussi bien les textures, que ce que mon effet est sencé appliquer).



    Voici mon 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
    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
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    #region Using Statements
    using System;
    using System.Collections.Generic;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Audio;
    using Microsoft.Xna.Framework.Content;
    using Microsoft.Xna.Framework.Graphics;
    using Microsoft.Xna.Framework.Input;
    using Microsoft.Xna.Framework.Storage;
    #endregion
     
    namespace Underwater
    {
        public class Game1 : Microsoft.Xna.Framework.Game
        {
            GraphicsDeviceManager graphics;
            ContentManager content;
            Effect underwater;
            Model room;
            SpriteBatch sprite;
            RenderTarget2D renderTarget;
            Texture2D shaderTexture;
            Matrix view;
            Matrix projection;
            Matrix []transform;
     
            public Game1()
            {
                graphics = new GraphicsDeviceManager(this);
                content = new ContentManager(Services);
            }
     
            protected override void Initialize()
            {
                view = Matrix.CreateLookAt(new Vector3(-700, 200, 250), Vector3.Zero, Vector3.Up);
                projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, 4.0f / 3.0f, 1, 10000);
                sprite = new SpriteBatch(graphics.GraphicsDevice);
                base.Initialize();
            }
     
            protected override void LoadGraphicsContent(bool loadAllContent)
            {
                if (loadAllContent)
                {
                    underwater = content.Load<Effect>("underwater");
                    room = content.Load<Model>("piece");
                }
                renderTarget = new RenderTarget2D(graphics.GraphicsDevice, graphics.GraphicsDevice.PresentationParameters.BackBufferWidth, graphics.GraphicsDevice.PresentationParameters.BackBufferHeight, 1, graphics.GraphicsDevice.PresentationParameters.BackBufferFormat, graphics.GraphicsDevice.PresentationParameters.MultiSampleType, graphics.GraphicsDevice.PresentationParameters.MultiSampleQuality);
                shaderTexture = new Texture2D(graphics.GraphicsDevice, renderTarget.Width, renderTarget.Height, 1, ResourceUsage.ResolveTarget, renderTarget.Format, ResourceManagementMode.Manual);
            }
     
            protected override void UnloadGraphicsContent(bool unloadAllContent)
            {
                if (unloadAllContent)
                {
                    content.Unload();
                }
            }
     
            protected override void Update(GameTime gameTime)
            {
                base.Update(gameTime);
            }
     
            protected override void Draw(GameTime gameTime)
            {
                graphics.GraphicsDevice.SetRenderTarget(0, renderTarget);
                graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
                transform = new Matrix[room.Bones.Count];
                room.CopyAbsoluteBoneTransformsTo(transform);
                foreach (ModelMesh mesh in room.Meshes)
                {
                    foreach (BasicEffect effect in mesh.Effects)
                    {
                        effect.View = view;
                        effect.Projection = projection;
                        effect.World = transform[mesh.ParentBone.Index];
                    }
                    mesh.Draw();
                }
                graphics.GraphicsDevice.ResolveRenderTarget(0);
                shaderTexture = renderTarget.GetTexture();
                graphics.GraphicsDevice.SetRenderTarget(0, null);
                sprite.Begin(SpriteBlendMode.None, SpriteSortMode.Immediate, SaveStateMode.None);
                underwater.Begin();
                underwater.CurrentTechnique.Passes[0].Begin();
                sprite.Draw(shaderTexture, Vector2.Zero, Color.White);
                sprite.End();
                underwater.CurrentTechnique.Passes[0].End();
                underwater.End();
                base.Draw(gameTime);
            }
        }
    }
    ainsi que mon effet (au cas ou) :

    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
    uniform extern texture ScreenTexture;    
     
    sampler ScreenS = sampler_state
    {
        Texture = <ScreenTexture>;    
    };
     
    float4 PixelShader(float2 texCoord: TEXCOORD0) : COLOR
    {
        float4 color = tex2D(ScreenS, texCoord);
        color.z += 0.5f;         
        return color;
    }
     
    technique
    {
        pass P0
        {
            PixelShader = compile ps_2_0 PixelShader();
        }
    }
    Vous avez une idée d'où ça peut venir ?

    Merci.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    366
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 366
    Points : 440
    Points
    440
    Par défaut
    sans regarder ton code (ne connaissant pas le framework ...) la difference entre 2D et 3D se situant dans la matrice de projection , le probleme pourrait venir de la.

    Pour faire un rendu d un screen aligned rect,

    -soit tu t assure de bien positionne la matrice de projection a ortho, puis tu rends un rectangle type [-1 , + 1] ou [0 , +1] (a voir)
    -soit tu rend un rectangle type [-1 , + 1] ou [0 , +1] , mais tu t assurer que le format donnee a directX empeche l utilisation de la projection (format D3DF_XYZW je crois (de tete), pour lequel les vertex ne subissent pas de transformations)

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    117
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2005
    Messages : 117
    Points : 76
    Points
    76
    Par défaut
    En fait ce qui est étrange c'est que avant d'appliquer mon effet, j'avais donc rendu ma scène, je l'avais récupéré dans une Texture2D (c'est le type pour afficher du 2D tu t'en doute) et je l'affichais sans problème la texture du modèle était bien placée, le problème des coordonnées est apparu a partir du moment ou j'ai appliqué mon effet, ce qui est encore plus étrange c'est que si j'enlève le code qui applique l'effet, et si même j'enlève l'affichage de la Texture2D à la place de la scène, l'effet persiste (la coloration bleue, en fait mon effet est pour créer un watervolume) mais le problème aussi, hors l'effet ne devrait plus être appliqué puisque j'enlève les commandes qui l'exécute... ça doit être à mon avis un problème au niveau du backbuffer ou des RenderTarget.

  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
    Si je résume:

    1) tu rends dans une texture : OK
    2) tu rends dans une texture + effet : pas bon
    3) tu rends dans une texture sans effet : pas bon

    J'avoue que j'ai du mal à comprendre la différence entre 1 et 3.

    Soit j'ai mal compris (dans ce cas pourrais-tu réexpliquer), soit tu as commis une erreur **idiote** (dans ce cas réessaye de faire le cas 1).

    si j'enlève le code qui applique l'effet
    ...
    l'effet persiste
    Là y a un problème....

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    117
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2005
    Messages : 117
    Points : 76
    Points
    76
    Par défaut
    Lol ok je vais essayer de mieux m'expliquer.

    1)Quand je rend la scène simplement en 3D ça fonctionne bien.
    2)Quand je récupère la scène, que je la stocke dans une texture et que je l'affiche ça fonctionne bien (c'est un peu le même fonctionnement que de prendre une capture d'écran en gros).
    3)Quand j'applique un effet à cette texture que j'ai récupéré (donc qui est en fait ma scène 3D, mais que j'ai copié dans une image 2D, comme si je prenais une capture d'écran et que j'appliquais un effet a une image dans un logiciel de retouche de photo), là ça me fais des coordonnées de la texture appliquée au modèle 3D n'importe comment (voir l'image).
    4)Quand je retire à nouveau l'application de l'effet, c'est comme si je n'avais rien enlevé car l'effet est toujours là.

    Pour supprimer totalement l'effet, il faut que je supprime la ligne graphics.GraphicsDevice.SetRenderTarget(0, renderTarget); ce qui n'est pas normal, car elle ne fait que définir un nouveau RenderTarget, pas de rapport avec l'application de l'effet donc.

  9. #9
    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
    Essaye de rajouter un clear ici :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    graphics.GraphicsDevice.ResolveRenderTarget(0);
    shaderTexture = renderTarget.GetTexture();
    graphics.GraphicsDevice.SetRenderTarget(0, null);
    graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

Discussions similaires

  1. Réponses: 17
    Dernier message: 18/06/2012, 13h27
  2. Pimp my video : effets avec les shaders et QtMultimedia
    Par LittleWhite dans le forum Qt Quick
    Réponses: 0
    Dernier message: 08/05/2012, 20h18
  3. Réponses: 2
    Dernier message: 14/12/2007, 01h47
  4. Effets avec les shaders
    Par chonos dans le forum OpenGL
    Réponses: 4
    Dernier message: 11/01/2006, 16h58

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