Logo
programming4us
programming4us
programming4us
programming4us
Home
programming4us
XP
programming4us
Windows Vista
programming4us
Windows 7
programming4us
Windows Azure
programming4us
Windows Server
programming4us
Windows Phone
 
Windows Phone

Developing for Windows Phone and Xbox Live : Device States (part 2) - DepthStencilState

- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019
6/9/2011 5:06:39 PM

DepthStencilState

Next up on the list is the depth stencil state. This state has all of the settings and properties required to control the depth and stencil buffers. The previous example is a little dry with just blending the colors, so start a new game project now. Add the depthmodel.fbx model to your content project, and add a few variables to the game, too:

Model model;
Matrix proj;
Matrix view;

Load the model and create the matrices, which you can do in your LoadContent overload:

proj = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4,
GraphicsDevice.Viewport.AspectRatio, 1.0f, 100.0f);
view = Matrix.CreateLookAt(new Vector3(0, 3, 20), Vector3.Zero, Vector3.Up);

model = Content.Load<Model>("depthmodel");
foreach (ModelMesh mm in model.Meshes)
{
foreach (Effect e in mm.Effects)
{
IEffectLights iel = e as IEffectLights;
if (iel != null)
{
iel.EnableDefaultLighting();
}
}
}

Here, set up a basic camera, load the model, and turn on the lights on the model (because it would look boring and flat otherwise). To draw the model, replace your Draw overload with the following:
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
float time = (float)gameTime.TotalGameTime.TotalSeconds;
Matrix rotation = Matrix.CreateRotationZ(time) *
Matrix.CreateRotationY(time / 4.0f);
Matrix scale = Matrix.CreateScale(0.5f);
Matrix transLeft = Matrix.CreateTranslation(-6, 0, 0);
model.Draw(scale * rotation * transLeft, view, proj);
}

This code renders the model to the left of the screen with it slowly rotating around. Notice that the model is a donut-shaped object with four spheres spinning around with it along its outside border. You also should see that at the beginning of the method, you set the DepthStencilState property on the device, although you just set it to Default. In this particular case, it doesn’t matter if you don’t make this call. When you draw this model again to the right, it will matter.

What exactly is a depth buffer? Well, it’s a buffer to hold depth, of course. If you render a scene with the depth buffer enabled (which is the case by default), for every pixel that is rendered, the depth of that pixel is also stored. You can think of the depth as the distance from the camera. Something near the camera has a depth close to 0.0f, and objects far away have a depth close to 1.0f (the depth runs from 0.0f to 1.0f).

Each time a new pixel is rendered, the system checks whether a depth is written for the position already. If it is, it compares the depth of the current pixel with the one that is already stored, and depending on the function of the depth buffer (which is discussed later), it decides what to do with it. If, for example, the function is CompareFunction.LessEqual, it looks at the current pixel’s depth. If it is less than or equal to the stored pixel’s depth, it writes the new pixel to the buffer; otherwise, it discards it. This enables you to render scenes in 3D, with objects appearing behind (and occluded) by other objects.

To give you an idea of why having the depth buffer is so valuable in a 3D application, add the following code at the end of your Draw overload:

Matrix transRight = Matrix.CreateTranslation(6, 0, 0);
GraphicsDevice.DepthStencilState = DepthStencilState.None;
model.Draw(scale * rotation * transRight, view, proj);

This turns the depth buffer completely off, and then draws the same model again to the right side of the screen, much like you see in Figure 2.

Figure 2. Rendering a scene with and without depth

Notice that the model on the right looks odd. You can see the small spheres whether they’re in front of the torus or not. You can even see some of the inside of the torus through the other portions of itself. With no depth buffer, the last pixel drawn at a particular depth wins.

In the case of this model, it is composed of five different meshes (the torus, and each sphere is its own mesh). The torus is drawn first, and the spheres next, so the spheres always appear on top of the torus, as they’re drawn later. Depending on how the torus itself is drawn (and which angle it is at), certain pixels in the center of the torus might be drawn after pixels that would normally block it, so you can also get an odd visual with the center.

Before moving on to the specific properties of the DepthStencilState object, let’s take a look at the last static member. You used Default (which turns the depth buffer on) and None (which turns it off). The last one is DepthRead, which reads from the depth buffer, but doesn’t write to it. What does that exactly mean?

It means that it does the same operation as the default depth buffer state—it rejects pixels that don’t pass the depth test, but when it finds a new pixel that does pass the depth test, it doesn’t write the pixel’s depth to the buffer. For example, add the following variable to your game:

Texture2D grey;

Then, create and initialize it in your LoadContent method:

grey = new Texture2D(GraphicsDevice, 1, 1);
grey.SetData<Color>(new Color[] { Color.Gray });

Next, make one change to your current Draw overload, namely deleting the line that sets the graphics device to DepthStencilState.None before adding this code to the end of the method:

GraphicsDevice.Clear(ClearOptions.Target, Color.CornflowerBlue, 1.0f, 0);
model.Draw(scale * rotation, view, proj);
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend,
SamplerState.LinearClamp, DepthStencilState.Default,
RasterizerState.CullCounterClockwise);
spriteBatch.Draw(grey, GraphicsDevice.Viewport.Bounds, null, Color.White,
0.0f, Vector2.Zero, SpriteEffects.None, 1.0f);
spriteBatch.End();

Notice that you’re calling a version of Clear that you haven’t seen before. You’re clearing again because you want to erase the two models you just drew, because for this example, they were to write only depth into the depth buffer. However, you cannot use the prototype of Clear that you normally use, because it also clears the depth buffer. So instead, tell Clear to clear only the ClearOptions.Target (the color buffer) to the normal CornflowerBlue, and the rest of the parameters are ignored because they depend on other ClearOptions that you didn’t specify. You can use ClearOptions.DepthBuffer to clear the depth and ClearOptions.Stencil to clear the stencil, with the latter two properties as the values to clear each buffer to respectively.

Draw the model again in the center of the screen (this is where you see the effect of DepthRead in a few moments).

Next, you use one of the more complex spriteBatch.Begin overloads. Aside from the DepthStencilState.Default, the rest of the parameters are the defaults for sprite batches though, so you can ignore those for now. Render the texture to cover the entire screen at a layer depth of 1.0f (the last parameter). Specify the Default depth state because sprite batch (in its default) turns the depth off. Because you turned it on for this sprite, rendering the texture tests its depth (1.0f) against all the pixels in the depth buffer. Any pixels where the models were drawn have a lesser depth, so the pixels in the texture are discarded and not drawn. As you can see in Figure 3, this is exactly what happens because you see a gray screen with the outline of the model’s circling there with your extra model floating in between them.

Figure 3. Cutouts using depth

Notice that the middle (colored) model looks perfectly normal in the scene. It gets occluded by the cutouts sometimes (when they are behind it), but it shows up in front of the cutouts when it is closer to the camera. This is because it is writing its depth into the depth buffer. Add the following line of code directly after the second Clear call:

GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;

This is a different output than before. Because it is not writing its depth to the scene, the only places you actually see the rendered model are the portions inside the cutouts where it passed the depth test. So why does this happen?

Let’s trace the lifetime of a pixel through this scene. Imagine the pixel is one in which the colored model is drawn through the cutout and intersecting the left model. First, the scene is cleared; the pixel has the default color and a depth value of 1.0f. Next, the left model is drawn, so now the pixel has the left model color in it, and its depth, you can call it 0.1f to have a nice round number. The right model is drawn next, but it doesn’t affect the pixel, so now the clear call happens again. This time, the color is reset back to default, but the depth isn’t changed, so it’s still 0.1f. Now, the colored model is drawn, it has a depth of 0.09f and passes the pixel test, so the color is now updated, but you aren’t writing depth, so it is still 0.1f. Finally, the grey texture is drawn, and its depth of 1.0f doesn’t pass the depth test, so the colored model’s pixel stays there.

If you are looking at a pixel outside of the cutout, though, something else happens. First, the left and right model don’t intersect the pixel (otherwise, it would be in a cutout), so this pixel is cleared, has a depth of 1.0f, and then cleared again without modifying the depth. Next, the colored model is drawn; it passes the depth test, updates the pixel color, but hasn’t modified the depth, which is still 1.0f. When the sprite comes to render, its value of 1.0f passes the depth test, it overwrites the pixel color with its grey, and you get the scene you see when running this example.

There are only three properties on the DepthStencilState object that deal directly with the depth buffer, and they’re all basically covered by the static members you’ve used already. However, because you aren’t setting them directly, let’s take a look at what they are.

First, you have the DepthBufferEnable property, which enables (or disables) the depth buffer completely. The default value for this is true. You should note that everything in this state object is only meaningful if you actually have a depth buffer. If you don’t need a depth buffer (for example, a purely 2D game with no layered sprites), you can simply turn the depth buffer off for the entire game by changing your PreferredDepthStencilFormat type to DepthFormat.None (the default is DepthFormat.Depth24) in your constructor:

graphics.PreferredDepthStencilFormat = DepthFormat.None;

Next is DepthBufferWriteEnable, which is by default true. This sets whether the system will take pixels that pass the depth test and write them to the depth buffer. You’ve seen the behavior when the write is false in the previous example.

The last depth buffer specific property is DepthBufferFunction, which has a default of CompareFunction.LessEqual. This enables you to dictate how the depth buffer decides whether to allow the pixel or not. By default, the depth buffer is cleared to a value of 1.0f (this is the parameter of the Clear function called depth). Because this is the farthest away point in the depth buffer, anything within the viewing frustum passes the depth test at first. However, you can change this behavior with the various values of the CompareFunction enumeration.

The rest of the properties deal with the stencil portion of the depth buffer, but first, let’s take a bit of time to talk about render targets.

Other -----------------
- Developing for Windows Phone and Xbox Live : Using SkinnedEffect
- Developing for Windows Phone and Xbox Live : Using AlphaTestEffect & Using EnvironmentMapEffect
- Developing for Windows Phone and Xbox Live : Using the Effect Interfaces & Using DualTextureEffect
- Developing for Windows Phone and Xbox Live : Using BasicEffect (part 2) - Textures, Vertex Colors, and Fog
- Developing for Windows Phone and Xbox Live : Using BasicEffect (part 1) - Basic Lighting
- Developing for Windows Phone and Xbox Live : Camera Types & Models
- Developing for Windows Phone and Xbox Live : Projection Matrix
- Developing for Windows Phone and Xbox Live : View Matrix
- Programming Windows Phone 7 : Pivot and Panorama - The XNA Music Classes: MediaPlayer
- Programming Windows Phone 7 : Pivot and Panorama - Displaying the Albums
 
 
Top 10
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
 
programming4us
Windows Vista
programming4us
Windows 7
programming4us
Windows Azure
programming4us
Windows Server