All pastes #178421 Raw Edit

ScreenQuad

public text v1 · immutable
#178421 ·published 2006-09-21 09:05 UTC
rendered paste body
    /// <summary>
    /// Screen quad vertex struct.
    /// Contains a transformed position and texture coord.
    /// </summary>
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct ScreenQuadVertex
    {
        /// <summary>
        /// The position of the vertex.
        /// </summary>
        private Vector4 PositionInternal;

        /// <summary>
        /// The texcoord for the vertex.
        /// </summary>
        private Vector2 TexCoordInternal;

        /// <summary>
        /// Constructor for the ScreenQuadVertex.
        /// Takes a position (Vector3), and a texcoord (Vector2).
        /// </summary>
        /// <param name="X"></param>
        /// <param name="Y"></param>
        /// <param name="Z"></param>
        /// <param name="U"></param>
        /// <param name="V"></param>
        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);
        }

        /// <summary>
        /// Retieves the stride in bytes for ScreenQuadVertex.
        /// </summary>
        public static int StrideSize
        {
            get { return Marshal.SizeOf(typeof(ScreenQuadVertex)); }
        }
    }

    /// <summary>
    /// ScreenQuad class to render a full screen quad.
    /// </summary>
    public class ScreenQuad
    {
        /// <summary>
        /// ScreenQuad vertex declaration, matching the ScreenQuadVertex struct.
        /// </summary>
        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),
        };

        /// <summary>
        /// VertexDeclaration for the full screen quad (ScreenQuadVertex).
        /// </summary>
        private VertexDeclaration VertexDeclarationInternal = null;

        /// <summary>
        /// Vertex buffer to hold the 4 vertices of the screen quad.
        /// </summary>
        private VertexBuffer VertexBufferInternal = null;

        /// <summary>
        /// ScreenQuad constructor, takes a device.
        /// Creates the vertex declaration, and the vertex buffer.
        /// </summary>
        /// <param name="device"></param>
        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);
        }

        /// <summary>
        /// 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.
        /// </summary>
        /// <param name="device"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        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<ScreenQuadVertex>(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<ScreenQuadVertex>(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;
            }
        }

        /// <summary>
        /// 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.
        /// </summary>
        /// <param name="device"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="left"></param>
        /// <param name="top"></param>
        /// <param name="bottom"></param>
        /// <param name="right"></param>
        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<ScreenQuadVertex>(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<ScreenQuadVertex>(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;
            }
        }

        /// <summary>
        /// Dispose the components of the screen quad
        /// </summary>
        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;
            }
        }
    }