Export (0) Print
Expand All

How To: Draw Point Sprites

Demonstrates how to create and draw point sprites.

The Complete Sample

The code in this topic shows you the technique. You can download a complete code sample for this topic, including full source code and any additional supporting files required by the sample.

Using Point Sprites

To create a point sprite shader

  • Verify that the shader for point sprites has a pixel shader that accepts a texture coordinate.

    On Xbox 360, these are specified by the special SPRITETEXCOORD semantic. On Windows-based computers, any texture coordinate such as TEXCOORD0 will work. The pixel shader returns the color of the texel at the coordinate in the texture that is used to draw the sprite.

    uniform extern texture SpriteTexture;
    struct PS_INPUT
    {
        #ifdef XBOX
            float2 TexCoord : SPRITETEXCOORD;
        #else
            float2 TexCoord : TEXCOORD0;
        #endif
        
    };
    sampler Sampler = sampler_state
    {
        Texture = <SpriteTexture>;
    };                        
    float4 PixelShader(PS_INPUT input) : COLOR0
    {
        float2 texCoord;
    
        texCoord = input.TexCoord.xy;
    
        return tex2D(Sampler, texCoord);
    }
    

    A vertex shader for point sprites only needs to return a POSITION0 for the vertex, transformed by the world-view-projection matrix.

    uniform extern float4x4 WVPMatrix;
    float4 VertexShader(float4 pos : POSITION0) : POSITION0
    {
        return mul(pos, WVPMatrix);
    }
    

To draw a group of point sprites

  1. In LoadContent, load an Effect object for your point sprites, and set the texture the point sprites will draw.

    This example also creates a random set of point sprites to draw, using an array of VertexPositionColor elements.

    Effect pointSpritesEffect;
    VertexPositionColor[] spriteArray;
    VertexDeclaration vertexPosColDecl;
    Random rand;
    protected override void LoadContent()
    {
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);
        pointSpritesEffect = Content.Load<Effect>("pointsprites");
        pointSpritesEffect.Parameters["SpriteTexture"].SetValue(
            Content.Load<Texture2D>("fire"));
        spriteArray = new VertexPositionColor[200];
        vertexPosColDecl = new VertexDeclaration(graphics.GraphicsDevice,
            VertexPositionColor.VertexElements); 
        rand = new Random();
        for (int i = 0; i < spriteArray.Length; i++)
        {
            spriteArray[i].Position = new Vector3(rand.Next(100) / 10f,
               rand.Next(100) / 10f, rand.Next(100) / 10f);
            spriteArray[i].Color = Color.WhiteSmoke;
        }
    
  2. In Draw, set the proper render states on the GraphicsDevice.

  3. Set PointSpriteEnable to true and DepthBufferWriteEnable to false.

  4. If your shader does not set the PSIZE semantic itself, set a PointSize here.

    The PointSize is the width of the point sprite on screen, in pixels. Setting the PSIZE semantic in the shader allows the shader to vary the size of each point. Using the PointSize render state instead will cause each point to be rendered as the same size.

  5. Set up additive blending by setting AlphaBlendEnable to true, and the SourceBlend and DestinationBlend to Blend.One.

                graphics.GraphicsDevice.RenderState.PointSpriteEnable = true;
                graphics.GraphicsDevice.RenderState.PointSize = 64.0f;
                graphics.GraphicsDevice.RenderState.AlphaBlendEnable = true;
                graphics.GraphicsDevice.RenderState.SourceBlend = Blend.SourceAlpha;
                graphics.GraphicsDevice.RenderState.DestinationBlend = Blend.One;
                graphics.GraphicsDevice.RenderState.DepthBufferWriteEnable = false;
    
                graphics.GraphicsDevice.VertexDeclaration
                    = vertexPosColDecl;
                Matrix WVPMatrix = Matrix.Identity * viewMatrix * projectionMatrix;
                pointSpritesEffect.Parameters["WVPMatrix"].SetValue(WVPMatrix);
    
                pointSpritesEffect.Begin();
                foreach (EffectPass pass in pointSpritesEffect.CurrentTechnique.Passes)
                {
                    pass.Begin();
                    graphics.GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.PointList,
                        spriteArray, 0, spriteArray.Length);
                    pass.End();
                }
                pointSpritesEffect.End();
    
                graphics.GraphicsDevice.RenderState.PointSpriteEnable = false;
                graphics.GraphicsDevice.RenderState.DepthBufferWriteEnable = true;
                graphics.GraphicsDevice.RenderState.SourceBlend = Blend.SourceAlpha;
                graphics.GraphicsDevice.RenderState.DestinationBlend =
                    Blend.InverseSourceAlpha;
    
                base.Draw(gameTime);
            }
        }
    }
    #region File Description
    //-----------------------------------------------------------------------------
    // Program.cs
    //
    // Microsoft XNA Community Game Platform
    // Copyright (C) Microsoft Corporation. All rights reserved.
    //-----------------------------------------------------------------------------
    #endregion
    
    using System;
    
    namespace PointSprites
    {
        static class Program
        {
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            static void Main(string[] args)
            {
                using (Game1 game = new Game1())
                {
                    game.Run();
                }
            }
        }
    }
    
  6. Set the VertexDeclaration on the GraphicsDevice to the type of vertex you will be drawing (in this case, VertexPositionColor).

    graphics.GraphicsDevice.VertexDeclaration
        = vertexPosColDecl;
    
  7. Call SetValue for any draw-time parameters to your Effect, such as the world-view-projection matrix.

    Matrix WVPMatrix = Matrix.Identity * viewMatrix * projectionMatrix;
    pointSpritesEffect.Parameters["WVPMatrix"].SetValue(WVPMatrix);
    
  8. Call Begin on your Effect, and for each pass in the effect, call DrawUserPrimitives for the point sprites.

    pointSpritesEffect.Begin();
    foreach (EffectPass pass in pointSpritesEffect.CurrentTechnique.Passes)
    {
        pass.Begin();
        graphics.GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.PointList,
            spriteArray, 0, spriteArray.Length);
        pass.End();
    }
    pointSpritesEffect.End();
    
  9. Reset your render states for drawing any subsequent objects.

    graphics.GraphicsDevice.RenderState.PointSpriteEnable = false;
    graphics.GraphicsDevice.RenderState.DepthBufferWriteEnable = true;
    graphics.GraphicsDevice.RenderState.SourceBlend = Blend.SourceAlpha;
    graphics.GraphicsDevice.RenderState.DestinationBlend =
        Blend.InverseSourceAlpha;
    

Community Additions

ADD
Show:
© 2014 Microsoft