/// /// Screen quad vertex struct. /// Contains a transformed position and texture coord. /// [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct ScreenQuadVertex { /// /// The position of the vertex. /// private Vector4 PositionInternal; /// /// The texcoord for the vertex. /// private Vector2 TexCoordInternal; /// /// Constructor for the ScreenQuadVertex. /// Takes a position (Vector3), and a texcoord (Vector2). /// /// /// /// /// /// public ScreenQuadVertex(Single X, Single Y, Single Z, Single U, Single V) { this.PositionInternal = new Vector4(X, Y, Z, 1.0f); this.TexCoordInternal = new Vector2(U, V); } /// /// Retieves the stride in bytes for ScreenQuadVertex. /// public static int StrideSize { get { return Marshal.SizeOf(typeof(ScreenQuadVertex)); } } } /// /// ScreenQuad class to render a full screen quad. /// public class ScreenQuad { /// /// ScreenQuad vertex declaration, matching the ScreenQuadVertex struct. /// private readonly VertexElement[] ScreenQuadVertexElementsInternal = new VertexElement[] { new VertexElement(0, 0, VertexElementFormat.Vector4, VertexElementMethod.Default, VertexElementUsage.PositionTransformed, 0), new VertexElement(0, 16, VertexElementFormat.Vector2, VertexElementMethod.Default, VertexElementUsage.TextureCoordinate, 0), }; /// /// VertexDeclaration for the full screen quad (ScreenQuadVertex). /// private VertexDeclaration VertexDeclarationInternal = null; /// /// Vertex buffer to hold the 4 vertices of the screen quad. /// private VertexBuffer VertexBufferInternal = null; /// /// ScreenQuad constructor, takes a device. /// Creates the vertex declaration, and the vertex buffer. /// /// public ScreenQuad(GraphicsDevice device) { //Create the vertex declaration using ScreenQuadVertexElements this.VertexDeclarationInternal = new VertexDeclaration(device, this.ScreenQuadVertexElementsInternal); //Create the vertex buffer, with 4 vertices this.VertexBufferInternal = new VertexBuffer(device, typeof(ScreenQuadVertex), 4, ResourceUsage.None, ResourcePool.Default); } /// /// Draw the full screen quad at the specified width and height. /// Texcoords default to 0,0 and 1,1. /// /// Vertex positions are offset by -0.5f. /// /// /// /// public void Draw(GraphicsDevice device, Single width, Single height) { //Right and bottom vertex position, offset for texel mapping. float pixelToTexelX = 0.5f / width; float pixelToTexelY = 0.5f / height; //Create 4 new vertices ScreenQuadVertex[] quadVerts = new ScreenQuadVertex[4]; //Lock the vertex buffer into quadVerts this.VertexBufferInternal.GetData(quadVerts); //Fill in the data for the 4 quad verts quadVerts[0] = new ScreenQuadVertex(width, height, 0.5f, 1.0f - pixelToTexelX, 1.0f - pixelToTexelY); quadVerts[1] = new ScreenQuadVertex(width, 0.0f, 0.5f, 1.0f - pixelToTexelX, -pixelToTexelY); quadVerts[2] = new ScreenQuadVertex(0.0f, height, 0.5f, -pixelToTexelX, 1.0f - pixelToTexelY); quadVerts[3] = new ScreenQuadVertex(0.0f, 0.0f, 0.5f, -pixelToTexelX, -pixelToTexelY); //Unlock the vertex buffer this.VertexBufferInternal.SetData(quadVerts); //Whether the depth buffer was enabled or not bool depthBufferEnabled = false; if (device.RenderState.DepthBufferEnable == true) { //Disabled the depth buffer for renderin the quad device.RenderState.DepthBufferEnable = false; //flag that we disabled the depth buffer, so we can reset it to true depthBufferEnabled = true; } //Whether the cull mode was changed bool cullModeChanged = false; CullMode cullMode = device.RenderState.CullMode; if (cullMode != CullMode.CullClockwiseFace) { device.RenderState.CullMode = CullMode.CullClockwiseFace; cullModeChanged = true; } //Set the vertex declaration device.VertexDeclaration = this.VertexDeclarationInternal; //Set the stream source to the quad vertex buffer with the correct stride. device.Vertices[0].SetSource(this.VertexBufferInternal, 0, ScreenQuadVertex.StrideSize); device.Vertices[0].VertexStride = ScreenQuadVertex.StrideSize; //No indices are needed to render the 4 quad verts device.Indices = null; //Render the screen quad as 2 trianglestrips device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2); //If the depth buffer was originally enabled, enable it again if (depthBufferEnabled == true) { //Enable the depth buffer device.RenderState.DepthBufferEnable = true; } //If the cullmode was changed, reset it if (cullModeChanged == true) { //Set the cullmode back to its original value device.RenderState.CullMode = cullMode; } } /// /// Draw the full screen quad at the specified width and height. /// The Single parameters set the texcoords for the quad vertices. /// /// Vertex positions are offset by -0.5f. /// /// /// /// /// /// /// /// public void Draw(GraphicsDevice device, Single width, Single height, Single left, Single top, Single bottom, Single right) { //Right and bottom vertex position, offset for texel mapping. float pixelToTexelX = 0.5f / width; float pixelToTexelY = 0.5f / height; //Create 4 new vertices ScreenQuadVertex[] quadVerts = new ScreenQuadVertex[4]; //Lock the vertex buffer into quadVerts this.VertexBufferInternal.GetData(quadVerts); //Fill in the data for the 4 quad verts quadVerts[0] = new ScreenQuadVertex(width, height, 0.5f, right - pixelToTexelX, bottom - pixelToTexelY); quadVerts[1] = new ScreenQuadVertex(width, 0.0f, 0.5f, right - pixelToTexelX, top - pixelToTexelY); quadVerts[2] = new ScreenQuadVertex(0.0f, height, 0.5f, left - pixelToTexelX, bottom - pixelToTexelY); quadVerts[3] = new ScreenQuadVertex(0.0f, 0.0f, 0.5f, left - pixelToTexelX, top - pixelToTexelY); //Unlock the vertex buffer this.VertexBufferInternal.SetData(quadVerts); //Whether the depth buffer was enabled or not bool depthBufferEnabled = false; if (device.RenderState.DepthBufferEnable == true) { //Disabled the depth buffer for renderin the quad device.RenderState.DepthBufferEnable = false; //flag that we disabled the depth buffer, so we can reset it to true depthBufferEnabled = true; } //Whether the cull mode was changed bool cullModeChanged = false; CullMode cullMode = device.RenderState.CullMode; if (cullMode != CullMode.CullClockwiseFace) { device.RenderState.CullMode = CullMode.CullClockwiseFace; cullModeChanged = true; } //Set the vertex declaration device.VertexDeclaration = this.VertexDeclarationInternal; //Set the stream source to the quad vertex buffer with the correct stride. device.Vertices[0].SetSource(this.VertexBufferInternal, 0, ScreenQuadVertex.StrideSize); device.Vertices[0].VertexStride = ScreenQuadVertex.StrideSize; //No indices are needed to render the 4 quad verts device.Indices = null; //Render the screen quad as 2 trianglestrips device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2); //If the depth buffer was originally enabled, enable it again if (depthBufferEnabled == true) { //Enable the depth buffer device.RenderState.DepthBufferEnable = true; } //If the cullmode was changed, reset it if (cullModeChanged == true) { //Set the cullmode back to its original value device.RenderState.CullMode = cullMode; } } /// /// Dispose the components of the screen quad /// public void Dispose() { //If the vertex declaration is not null, dispose it if (this.VertexDeclarationInternal != null) { this.VertexDeclarationInternal.Dispose(); this.VertexDeclarationInternal = null; } //If the the vertex buffer is not null, dispose it if (this.VertexBufferInternal != null) { this.VertexBufferInternal.Dispose(); this.VertexBufferInternal = null; } } }