La 3D sous XNA Campus-Booster ID : **XXXXX Copyright © SUPINFO. All rights reserved La 3D sous...

Post on 04-Apr-2015

113 views 1 download

Transcript of La 3D sous XNA Campus-Booster ID : **XXXXX Copyright © SUPINFO. All rights reserved La 3D sous...

La 3D sous XNACampus-Booster ID : **XXXXX

www.supinfo.com

Copyright © SUPINFO. All rights reserved

La 3D sous XNA

Objectifs de ce module

Découvir la 3D. Que faut il connaître pour faire de la 3D ?

Afficher votre objet en 3D. Afficher un simple triangle puis un modèle en 3D.

Comprendre et utiliser les transformations. Modifier la position, l’orientation et la taille d’objets 3D.

En suivant ce module vous allez :

La 3D sous XNA

Plan du module

Introduction à la 3D. coordonnées, caméra, vertex…

Affichage d’un triangle. Comment afficher un simple triangle ?

Transformations. Modifications de l’état de nos objets 3D.

Affichage d’un modèle 3D. Utilisation de modèles 3D.

Billboarding. De la 2D en 3D.

Lumière. Gestion de l’éclairage

Optimisations. Optimiser l’affichage.

Voici les parties que nous allons aborder :

La 3D sous XNA

Introduction à la 3D

coordonnées, caméra, vertex…

La 3D sous XNA

Plan de la partie

Le système de coordonnées.

La Caméra.

Le vertex.

Voici les chapitres que nous allons aborder :

Introduction à la 3D

Le monde de jeu se situe dans un repère 3D orthonormé.

Chaque objet sera positionné dans le monde suivant ses coordonnées X, Y et Z.

Il s’agit d’un repère « main droite »

Introduction à la 3D

Système de coordonnées

La caméra est caractérisée par :

Une position X,Y,Z

Un champ de vision :

Cette méthode permet d’obtenir la projection matrix

Une direction :

Cette méthode permet d’obtenir la view Matrix

Afin d’observer le monde la caméra est nécessaire

Introduction à la 3D

Camera

Matrix.CreatePerspectiveFieldOfView(float fieldOfView,float aspectRatio,float nearPlaneDistance,float farPlaneDistance)

Matrix.CreateLookAt(Vector3 cameraPosition, ref Vector3 cameraTarget,ref Vector3 cameraUpVector);

Un vertex est un point auquel on associe différentes propriétés comme :

Une couleur

Des coordonnées de texture

Une normale

Une tangente

Etc…

Au pluriel : Vertices

Un vertex = un point, un sommet

Introduction à la 3D

Vertex

Affichage d’un triangle

Comment afficher un simple triangle ?

La 3D sous XNA

Plan de la partie

Pourquoi un triangle ?

Création du VertexBuffer

Affichage du VertexBuffer

Effets

BackFace culling

Application d’une texture

Affichez votre premier triangle pas à pas

Voici les chapitres que nous allons aborder :

Affichage d’un triangle

Tout objet 3D est composé essentiellement de triangles :

Affichage d’un triangle

Pourquoi un triangle ?

Il est donc essentiel de savoir dessiner un triangle

Créer un tableau de vertices :

VertexBuffer = zone mémoire pour vertices

Affichage d’un triangle

Création du VertexBuffer

VertexPositionColor[] vertices = new VertexPositionColor[3];

Affectation des positions :vertices[0] = new VertexPositionColor(new Vector3(-0.5f, 0.5f, 0), new Color(10, 120, 200, 255));vertices[1] = new VertexPositionColor(new Vector3(-0.5f, 0, 0), new Color(10, 120, 200, 255));vertices[2] = new VertexPositionColor(new Vector3(0, 0, 0), new Color(10, 120, 200, 255));

Assignation au VertexBuffer :

vertexBuffer = new VertexBuffer(this.graphics.GraphicsDevice, VertexPositionColor.SizeInBytes * 3, ResourceUsage.WriteOnly);vertexBuffer.SetData(vertices);

Spécifier le type de Vertex utilisé:

Etapes de l’affichage :

Affichage d’un triangle

Affichage du VertexBuffer

graphics.GraphicsDevice.VertexDeclaration = new VertexDeclaration( graphics.GraphicsDevice, VertexPositionColor.VertexElements);

Spécifier le VertexBuffer à afficher :graphics.GraphicsDevice.Vertices[0].SetSource(vertexBuffer, 0, VertexPositionColor.SizeInBytes);

Afficher le vertexbuffer:

graphics.GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);

Un effet permet de spécifier à la carte graphique comment afficher les triangles en appliquant des modifications d’affichage telles que :

Eclairer l’objet

Modifier la couleur des pixels

Appliquer un effet de Bump mapping

Etc…

Un effet est normalement issu d’un fichier .fx programmé en HLSL

Le framework XNA met à disposition un effet simple qui ne nécessite pas de fichier .fx : le BasicEffect

Tout affichage en XNA doit utiliser un effet

Affichage d’un triangle

Effets

Initialisation :

Propriétés de l’effet :

Affichage du triangle à l’aide de l’effet :

BasicEffect

Affichage d’un triangle

Effets

effect = new BasicEffect(graphics.GraphicsDevice, null);

effect.VertexColorEnabled = true;

effect.Begin();foreach (EffectPass pass in effect.CurrentTechnique.Passes){ pass.Begin();

effect.View = mViewMatrix; effect.Projection = mProjectionMatrix;

graphics.GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);

pass.End();}effect.End();

Affichage d’un triangle

Back Face culling

Il faut spécifier les points dans le sens trigonométrique par rapport à la camérasinon le triangle ne sera pas visible.

Par défaut une seule face du triangle est dessinée pour des raisons de performance

Ce comportement peut être modifié en changeant le culling mode :

graphics.GraphicsDevice.RenderState.CullMode = CullMode.None;

Une texture ?

Affichage d’un triangle

Texturer un triangle

Une texture est tout simplement une image appliquée à un triangle.

XNA gère par défaut les formats PNG, TGA, JPEG, DDS et BMP.

Il n’y a pas de différence de performance suivant le format utilisé : la texture est convertie en format interne à Direct3D et sa taille adaptée à une puissance de 2

Cependant plus la résolution de la texture est élevée plus son affichage sera gourmand en temps.

Affectation de la texture :

Affichage d’un triangle

Texturer un triangle

Afin de texturer un triangle il suffit de donner les coordonnées de la texture au vertex 

Mise en place de la texture :

Utilisation de VertexPositionTexture comme type de vertex

Chargement de la texture :

Assignation de la texture à l’effet :mTexture = content.Load<Texture2D>( "Glass" );

basicEffect .TextureEnabled = true;basicEffect .Texture = texture;

Créez votre projet et ouvrez le fichier Game1.cs

Ajoutez les champs suivants à votre classe :

Dans la méthode Initialize, initialisez la caméra :

Création du projet et initialisation de la caméra

Affichage d’un triangle

Pas à pas

Matrix viewMatrix;Matrix projection;VertexBuffer vertexBuffer;BasicEffect effect;

viewMatrix = Matrix.CreateLookAt(new Vector3(0, 0, 1), new Vector3(0, 0, 0), Vector3.Up);projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver2, (float)graphics.GraphicsDevice.Viewport.Width / (float)graphics.GraphicsDevice.Viewport.Height, 1.0f, 100.0f);

Dans la méthode LoadGraphicsContent déclarez vos vertices et assignez les au vertexBuffer :

A la suite, initialisez votre effet :

Vertices et effet

Affichage d’un triangle

Pas à pas

VertexPositionColor[] vertices = new VertexPositionColor[3];vertices[0] = new VertexPositionColor(new Vector3(0,0,0),Color.Blue);vertices[1] = new VertexPositionColor(new Vector3(0.5f,0.5f,0),Color.Red);vertices[2] = new VertexPositionColor(new Vector3(0.5f,0,0),Color.Green);

vertexBuffer = new VertexBuffer(graphics, VertexPositionColor.SizeInBytes * 3, ResourceUsage.WriteOnly);vertexBuffer.SetData<VertexPositionColor>(vertices);

effect = new BasicEffect(graphics, null);effect.VertexColorEnabled = true;

Dans la méthode Draw affichez votre triangle :

Affichage

Affichage d’un triangle

Pas à pas

graphics.GraphicsDevice.VertexDeclaration = new VertexDeclaration(graphics.GraphicsDevice, VertexPositionColor.VertexElements);graphics.GraphicsDevice.Vertices[0].SetSource(vertexBuffer, 0, VertexPositionColor.SizeInBytes);

effect.Begin();foreach (EffectPass pass in effect.CurrentTechnique.Passes){ pass.Begin();

effect.View = viewMatrix; effect.Projection = projectionMatrix;

graphics.GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);

pass.End();}effect.End();

Résultat :

Affichage d’un triangle

Pas à pas

Transformations

Modifications de l’état de nos objets 3D

La 3D sous XNA

Plan de la partie

Matrices

Rotation

Homothétie

Translation

Voici les chapitres que nous allons aborder :

Transformations

Pourquoi utiliser des matrices ?

Transformations

Matrices

Les objets ne sont pas affichés « tel quel » ils peuvent être :

Orientés

Agrandis / Réduis

Déplacés

Ces transformations sont effectuées à l’aide de matrices

Qu’est-ce qu’une matrice ?

Transformations

Matrices

Une matrice est un outil représenté par un tableau à 2 dimensions permettant d’effectuer les transformations

Il suffira de multiplier les coordonnées d’un point par une matrice de translation pour le faire déplacer.

Les matrices peuvent être associées (une matrice peut à la fois effectuer une rotation, une translation et un redimensionnement)

Transformations

Matrices

La multiplication des matrices n’est pas une opération commutative : effectuer une rotation suivie d’une translation ne donne pas le même résultat qu’effectuer une translation puis une rotation.

Les méthodes de la classe matrice permettent :

Transformations

Rotation

D’obtenir une rotation à partir d’un axe du repère :

D’obtenir une rotation à partir d’un axe quelconque

D’obtenir une rotation à partir d’un angle de Yaw/Pitch/Roll :

Matrix.CreateRotationX(float radians)

Matrix.CreateFromAxisAngle(Vector3 axis, float angle)

Pour effectuer un redimensionnement :

Transformations

Homothétie

Utilisation de la méthode CreateScale :

Possibilité d’un redimensionnement non homogène grâce aux surcharges 

Matrix.CreateScale(float scale)

Matrix.CreateScale(float xScale,float yScale, float zScale) 

Pour déplacer un objet :

Transformations

Translation

Utilisation de la méthode CreateTranslation :

Contenu de la Matrice de translation (1,2,3)

Matrix.CreateTranslation(float xPosition, float yPosition , float zPosition )

1 0 0 0

0 1 0 0

0 0 1 0

1 2 3 1

Effectuer une translation sur un objet :

Effectuer un redimensionnement et une rotation :

La matrice world définit la transformation qui sera effectuée sur l’objet.

Effectuer une rotation sur le triangle dessiné précédemment, placez ce code après l’affectation de la view et de la projection Matrix:

Transformations

Exemples

effect.World = Matrix.CreateTranslation( 1, 0 , 0);

effect.World = Matrix.CreateScale(2) * Matrix.CreateRotationX(MathHelper.PiOver4);

effect.World = Matrix.CreateRotationX(-MathHelper.PiOver4);

Affichage d’un model 3D

Utilisation de modèles 3D

La 3D sous XNA

Plan de la partie

Qu’est-ce qu’un modèle 3D ?

Affichage d’un modèle 3D.

Voici les chapitres que nous allons aborder :

Affichage d’un model 3D

Un modèle 3D c’est simplement un ensemble de vertices stockés dans un fichier sous un format prédéfinit.

La création d’un modèle triangle par triangle est fastidieuse c’est pourquoi des logiciels de modélisation existent.

Ils permettent d’exporter dans les formats .X et .FBX que XNA peut lire par défaut.

Affichage d’un model 3D

Qu’est-ce qu’un modèle 3D ?

Affichage d’un model 3D

Affichage d’un modèle 3D

Chargement du modèle :

Affichage d’un modèle :

Model model = content.Load<Model>( "media\\ship" )

foreach (ModelMesh mesh in model.Meshes){ foreach (BasicEffect effect in mesh.Effects) { effect.View = mViewMatrix; effect.Projection = mProjectionMatrix; effect.EnableDefaultLighting(); } mesh.Draw();}

Billboarding

De la 2D en 3D

La 3D sous XNA

Plan de la partie

Pourquoi ?

Comment ?

Voici les chapitres que nous allons aborder :

Billboarding

Billboarding

Pourquoi ? Il est parfois nécessaire d’afficher un objet 2D dans une

scène 3D sans que le joueur s’en aperçoive il faut donc orienter un carré vers la camera : il s’agit de billboarding.

Effets spéciaux Pour des raisons de performance

Création d’un billboard :

Billboarding

Comment ?

Afin d’afficher un billboard il suffit d’utiliser la matrice adéquate sur un carré :

Matrix.CreateBillboard(Vector3 objectPosition, Vector3 cameraPosition, Vector3 cameraUpVector, Vector3? cameraForwardVector);

Lumière

Eclairez vos jeux

La 3D sous XNA

Plan de la partie

Fonctionnement

Mise en pratique

Voici les chapitres que nous allons aborder :

Affichage d’un model 3D

Fonctionnement

Lumière

Eclairage des surfaces

XNA peut gérer l’éclairage des surfaces automatiquement

Comment XNA sait-il qu’une surface doit être plus éclairée qu’une autre ?

Il est donc nécessaire pour chaque vertex de spécifier sa normale

On remarque que plus une surface est face au soleil plus elle est éclairée

Spécifier les normales

Lumière

Eclairage des surfaces

Afin de spécifier les normales il faut utiliser un type de vertex contenant les normales comme VertexPositionNormalTexture par exemple :

VertexPositionNormalTexture v = new VertexPositionNormalTexture(Position, Normal, textureCoordinate);

Mise en place de l’effet de lumière

Lumière

Eclairage des surfaces

Lors de l’affichage de l’objet avec un BasicEffect il suffit d’utiliser les méthodes et propriétés adéquates.

effect.LightingEnabled = true;effect.DirectionalLight0.Enabled = true;effect.DirectionalLight0.Direction = LightDirection;effect.DirectionalLight0.DiffuseColor = new Vector3(Red, Green, Blue);

effect.DirectionalLight0.SpecularColor = new Vector3(Red, Green, Blue);effect.SpecularPower = 10;

Optimisations de l’affichage

Soulagez votre GPU…

La 3D sous XNA

Plan de la partie

Indices

LOD

Frustum culling

QuadTree

Mipmapping

Voici les chapitres que nous allons aborder :

La 3D avancée sous XNA

Un vertex contient de nombreuses informations(position, coordonnées texture, normal, etc…)

Plus le nombre de vertices envoyés à la carte graphique est important, plus l’envoie à celle-ci prends de temps et moins l’affichage sera rapide.

Un carré est composé de 2 triangles soit 6 vertices : or il n’y a que 4 vertices différents.

Les indices vont nous permettre de n’utiliser que le nombre de vertices strictement nécessaire.

Ou comment réutiliser un même vertex…

Optimisation de l’affichage

Indices

Création de l’indexbuffer :

Les triangles ne seront plus formés dans le vertexbuffer : celui-ci ne contient que des vertices différents à la suite.

Formation des triangles grâce aux indices :

Affectation de l’indexBuffer :

Implémentation

Optimisation de l’affichage

Indices

indexBuffer = new IndexBuffer(graphics.GraphicsDevice, typeof(short), NumberOfIndices, ResourceUsage.WriteOnly, ResourceManagementMode.Automatic);

short[] indices = new short[TrianglesNumber * 3] { 0, 1, 2 , 1, 3, 2 … };indexBuffer SetData<short>(indices);

graphicDevice.Indices = indexBuffer;

Les points représentent les vertices crées :

Exemple

Optimisation de l’affichage

Indices

Avec les indices il faut former les triangles :

VertexPositionColor[] vertices = new VertexPositionColor[4];vertices[0] = new VertexPositionColor(new Vector3(-0.5f, 0.5f, 0f), Color.Black);vertices[1] = new VertexPositionColor(new Vector3( 0.5f, 0.5f, 0f), Color.Black);vertices[2] = new VertexPositionColor(new Vector3( 0.5f,-0.5f, 0f), Color.Black);vertices[3] = new VertexPositionColor(new Vector3(-0.5f,-0.5f, 0f), Color.Black);vertexBuffer.SetData<VertexPositionNormalTexture>(vertices);

Les points représentent les vertices crées :

Exemple

Optimisation de l’affichage

Indices

Avec les indices il faut former les triangles :

Indices du premier triangles : 0 , 1 , 3

short[] indices = new short[] { 0, 1, 2 ,

Les points représentent les vertices crées :

Exemple

Optimisation de l’affichage

Indices

Avec les indices il faut former les triangles :

Indices du premier triangles : 0 , 1 , 3

Indices du second triangle : 1 , 2 , 3

short[] indices = new short[] { 0, 1, 2 , 1, 2, 3 };indexBuffer.SetData<short>(indices);

Moins il y a de vertices affichées à l’écran mieux le GPU se porte

Plus un objet est éloigné moins l’on voit ses détails

Il est donc possible d’afficher un objet moins détaillé lorsque celui-ci est éloigné et afficher l’original lorsque la caméra est assez proche

Cette technique s’appelle Level Of Detail

Level Of Detail

Optimisation de l’affichage

LOD

Si vous appelez la méthode Draw et que l’objet n’est pas visible vous ferez tout de même appel à votre GPU et donc consommerez des ressources.

Il faut donc n’afficher que ce qui est dans le champ de vision de la caméra

Afficher uniquement ce qui est visible

Optimisation de l’affichage

Frustum culling

Il suffit de tester si notre objet se trouve entre ces 6 plans

Creation d’une sphère englobant l’objet

Creation de la sphère englobante de l’objet à partir du model :

Implémentation sous XNA

Optimisation de l’affichage

Frustum culling

BoundingSphere boundingSphere = new BoundingSphere();boundingSphere.Radius = radius;BoundingSphere.Center = new Vector3(x,y,z);

BoundingSphere boundingSphere = new BoundingSphere();

foreach (ModelMesh mesh in mShipModel.Meshes) { BoundingSphere sphere = mesh.BoundingSphere; BoundingSphere.CreateMerged(ref boundingSphere, ref sphere, out boundingSphere);}

boundingSphere.Center *= scale;boundingSphere.Radius *= scale;

Creation du Frustum de la caméra :

Teste si la sphère englobante est dans le frustum :

ContainmentType est une énumération :

Implémentation sous XNA

Optimisation de l’affichage

Frustum culling

BoundingFrustum frustum = new BoundingFrustum(viewMatrix * projectionMatrix);

ContainmentType containment = frustum.Contains(boundingSphere );

Schéma

Optimisation de l’affichage

QuadTree

N = 2

Une fois le découpage effectué il suffit de tester si le carré se trouve dans le frustum culling.

Si celui-ci se trouve complètement dans le frustum culling tous les éléments contenus dans le carré peuvent être dessinés

Si celui-ci ne se trouve pas dans le frustum culling aucun élément contenu dans le carré ne sera affiché.

Si celui-ci est en parti en dehors et dedans il faudra alors effectuer récursivement le même teste avec les 4 carrés contenus dans ce carré.

Découpage en zone

Optimisation de l’affichage

QuadTree

Plus la texture affichée est grande plus le GPU sera sollicité

Il est inutile d’afficher une texture plus grande que son affichage à l’écran : la conversion vers une texture plus petite sera couteuse en GPU et l’affichage approximatif.

Afin de résoudre de problème il est possible d’utiliser la technique du mipmapping

Pourquoi ?

Optimisation de l’affichage

Mipmapping

Exemple sans mipmapping

Optimisation de l’affichage

Mipmapping

Exemple avec mipmapping

Optimisation de l’affichage

Mipmapping

Afin d’utiliser le mipmapping il suffit de créer plusieurs fois la même texture à des tailles différentes : l’on divise à chaque fois la taille par 2.

XNA se chargera d’afficher la texture adaptée

Comment ?

Optimisation de l’affichage

Mipmapping

Les images .dds peuvent contenir les différents niveaux de mipmapping.

Comment ?

Optimisation de l’affichage

Mipmapping

Afin de les générer il est possible d’utiliser le DirectX Texture Tool issu du SDK.

TransformationsTransformations

Afficher un triangle

Afficher un triangle Introduction à

la 3DIntroduction à

la 3D

Les MatricesLes Matrices

Résumé du module

OptimisationsOptimisations

La 2D sous XNA

Pour aller plus loin…

Publications

Sites web

http://www.labo-dotnet.com/

Si vous voulez approfondir vos connaissances:

http://www.xna.com/

La 3D sous XNA

http://creators.xna.com/

XNA Game Studio Express: Developing Games for Windows and the Xbox 360 par Joseph B Hall

Professional XNA Game Programming: For Xbox 360 and Windows par Benjamin Nitschke

Félicitations

Vous avez suivi avec succès le module de cours n°02

La 3D sous XNA