Using a Basic Effect with Texturing
Demonstrates how to create and draw a simple quad—two triangles that form a rectangle or square—using DrawUserIndexedPrimitives.
This sample introduces the Quad
class, which is used to construct a quad with a list of vertices and indices suitable for drawing with DrawUserIndexedPrimitives. The sample also demonstrates how to use BasicEffect to render the quad and to apply a texture to the primitive. For more information about BasicEffect, see Creating a Basic Effect.
Complete Sample
The code in the topic shows you the technique for creating and drawing a quad. You can download a complete code sample for this topic, including full source code and any additional supporting files required by the sample.
Download TexturedQuad_Sample.zip.
Textured Quad
To create a quad
Determine the location of each of the four vertices in the quad.
The
Quad
constructor calculates the four corners given the origin, width, height, and facing information supplied by the caller.public Quad( Vector3 origin, Vector3 normal, Vector3 up, float width, float height ) { Vertices = new VertexPositionNormalTexture[4]; Indexes = new short[6]; Origin = origin; Normal = normal; Up = up; // Calculate the quad corners Left = Vector3.Cross( normal, Up ); Vector3 uppercenter = (Up * height / 2) + origin; UpperLeft = uppercenter + (Left * width / 2); UpperRight = uppercenter - (Left * width / 2); LowerLeft = UpperLeft - (Up * height); LowerRight = UpperRight - (Up * height); FillVertices(); }
Determine the UV coordinates for the texture you want to apply to the quad.
Note
UV coordinates are derived from texture coordinates that are mapped into values along a u-axis and a v-axis. The u represents width, and v represents height.
The
Quad
constructor callsFillVertices
, which assigns UV coordinates ranging from (0,0) to (1,1), and makes the entire texture appear on the quad.private void FillVertices() { // Fill in texture coordinates to display full texture // on quad Vector2 textureUpperLeft = new Vector2( 0.0f, 0.0f ); Vector2 textureUpperRight = new Vector2( 1.0f, 0.0f ); Vector2 textureLowerLeft = new Vector2( 0.0f, 1.0f ); Vector2 textureLowerRight = new Vector2( 1.0f, 1.0f );
Determine the normals for your vertices.
FillVertices
copies the normal vector you provide to each vertex.// Provide a normal for each vertex for (int i = 0; i < Vertices.Length; i++) { Vertices[i].Normal = Normal; }
Copy the position and texture coordinate data to your vertex array.
// Set the position and texture coordinate for each // vertex Vertices[0].Position = LowerLeft; Vertices[0].TextureCoordinate = textureLowerLeft; Vertices[1].Position = UpperLeft; Vertices[1].TextureCoordinate = textureUpperLeft; Vertices[2].Position = LowerRight; Vertices[2].TextureCoordinate = textureLowerRight; Vertices[3].Position = UpperRight; Vertices[3].TextureCoordinate = textureUpperRight;
Fill out the index buffer to determine what order your vertices are drawn by the graphics hardware.
Drawing two triangles requires four vertices, but six index entries if you are using a PrimitiveType.TriangleList. The indices are specified in clockwise order. XNA is a right-handed coordinate system so triangles drawn in counter-clockwise order are assumed to be facing away from the camera which causes them to be culled.
// Set the index buffer for each vertex, using // clockwise winding Indexes[0] = 0; Indexes[1] = 1; Indexes[2] = 2; Indexes[3] = 2; Indexes[4] = 1; Indexes[5] = 3; }
To draw a quad
In your game's Initialize method, create a new
Quad
object specifying the location, the normal (the direction the quad faces), theUp
vector, and the width and height of the quad.You can also create a view and projection matrix to use when rendering.
Quad quad; VertexDeclaration vertexDeclaration; Matrix View, Projection; protected override void Initialize() { quad = new Quad(Vector3.Zero, Vector3.Backward, Vector3.Up, 1, 1); View = Matrix.CreateLookAt(new Vector3(0, 0, 2), Vector3.Zero, Vector3.Up); Projection = Matrix.CreatePerspectiveFieldOfView( MathHelper.PiOver4, 4.0f / 3.0f, 1, 500); base.Initialize(); }
In your game's LoadContent method, load the texture you want to apply to the quad using the ContentManager.
Create and initialize a new BasicEffect object.
Set TextureEnabled to true, and assign the texture to draw to the Texture property.
Texture2D texture; BasicEffect quadEffect; protected override void LoadContent() { // Create a new SpriteBatch, which can be used to draw textures. spriteBatch = new SpriteBatch(GraphicsDevice); texture = Content.Load<Texture2D>("Glass"); quadEffect = new BasicEffect(graphics.GraphicsDevice); quadEffect.EnableDefaultLighting(); quadEffect.World = Matrix.Identity; quadEffect.View = View; quadEffect.Projection = Projection; quadEffect.TextureEnabled = true; quadEffect.Texture = texture;
In LoadContent, create a VertexDeclaration for the vertex type used to define the quad, which included position, normal and texture coordinates.
vertexDeclaration = new VertexDeclaration(new VertexElement[] { new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0), new VertexElement(12, VertexElementFormat.Vector3, VertexElementUsage.Normal, 0), new VertexElement(24, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0) } );
Use DrawUserIndexedPrimitives in each EffectPass to draw the quad.
Use the Vertices and Indices properties on the Quad structure to supply the primitive data, and specify two triangles to draw.
GraphicsDevice.Clear(Color.CornflowerBlue); foreach (EffectPass pass in quadEffect.CurrentTechnique.Passes) { pass.Apply(); GraphicsDevice.DrawUserIndexedPrimitives <VertexPositionNormalTexture>( PrimitiveType.TriangleList, quad.Vertices, 0, 4, quad.Indexes, 0, 2); }