Jump to content
  • Advertisement
  • entries
  • comments
  • views

D3D11 with MS3D + D3D11 Programming Tip #1

Sign in to follow this  
Jason Z


D3D11 with MS3D

I spent some time updating my geometry classes to allow for all of the myriad primitive topologies that are allowed for in D3D11. Its a bit surprising to see, but there are 32 different types of control patch primitives for use with the new tessellation shader stages. I basically allow my index buffer classes to add individual indices and let the application take care of ensuring that there is an appropriate number of indices for a given number of primitives of a given type. One by-product of adding this functionality is that I needed to be able to determine how many primitives are going to be rendered when a user specifies the number of indices and the topology type. Have you ever tried to figure out how to do this with a triangle strip with adjacency? Here's an image to show you what I mean - can you figure out the formula???

It took me a good 15 minutes of thinking about it to get it straight [rolleyes]! Anyhow, after getting my geometry classes straightened out, I ported over my geometry loader. The bottom line is that I can now load in my MilkShape3D files again, letting me render the old standby (do you know who it is?):

D3D11 Programming Tip #1

I'm going to periodically post programming tips that I come across while working with D3D11, and this is going to be the first one. When building a renderer around D3D11, it is pretty commong to create a function that recieves an object description that creates a state of some sort, such as a BlendState, RasterizerState, or DepthStencilState. Typically these descriptions are an actual D3D11 struct, and they can be quite verbose and unsightly to type out. Here is an example of how it would look to do create a DepthStencil state in this manner:

State.DepthEnable = true;
State.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
State.DepthFunc = D3D11_COMPARISON_LESS;
State.StencilEnable = FALSE;
State.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
State.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;

State.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
State.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
State.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
State.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;

State.BackFace.StencilFunc = D3D11_COMPARISON_NEVER;
State.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
State.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
State.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;

Renderer.CreateDepthStencilState( State );

This isn't too bad for one or two states, but by the time you get to 5 or 10 it becomes a real mess. Instead, if you create a class to wrap the structure you can take away a couple of nice advantages:

1. The constructor can be used to initialize the description to a known set of values.
2. Requesting the state to be created by the renderer is still simple - just pass a pointer.
3. You can add methods for setting the description to particular common settings.

So, given a class header like this:

class DepthStencilStateConfigDX11
virtual ~DepthStencilStateConfigDX11();

void SetDefaults();

void SetDepthEnable( bool state );
void SetDepthWriteMask( D3D11_DEPTH_WRITE_MASK state );
void SetDepthComparisonFunction( D3D11_COMPARISON_FUNC state );
void SetStencilEnable( bool state );
void SetStencilReadMask( UINT8 state );
void SetStencilWriteMask( UINT8 state );
void SetFrontFace( D3D11_DEPTH_STENCILOP_DESC state );
void SetBackFace( D3D11_DEPTH_STENCILOP_DESC state );

D3D11_DEPTH_STENCIL_DESC GetDepthStencilDesc();


friend RendererDX11;

Now you can create the state object in the renderer like so:

DepthStencilStateConfigDX11 DepthStencilState;
Renderer.CreateDepthStencilState( &DepthStencilState );

I have implemented these configuration classes for each of the state objects, and I will be adding them into the texture, buffer, and resource view creation schemes. It is a nice and clean solution, plus you can use it to add sanity checks on all of the different configurations and make sure there are no invalid state combinations.
Sign in to follow this  


Recommended Comments

Not a cow - but it is a mammal...

If you want a hint: He's been prominently featured in my journal before, so you could peruse a bit and figure it out... It's surprising how much information you get from depth cues like shading, and how much it takes away when you don't have them...

Good guess though!

Share this comment

Link to comment
I tried rating you up, but I must have done that some time ago since it didn't move your score...

You'll have to settle for knowing that you were able to 'see in the dark'... I wonder what else I could render without shading to see if you can figure it out...

Share this comment

Link to comment
Original post by Ashkan
Regarding your tip, Richard [legalize] Thomson has also posted a somewhat sexier approach on his blog.

Just thought it might be of interest to you.
Thanks for the link - that is an interesting method for doing the configuration. However, the state setup methods have to guarantee that they don't overwrite one another on the subsequent calls, otherwise you could end up with some confusing results. I have continued to implement the config classes I mentioned above, and I am finding that if I have a single method to do a complete configuration then it works out well. You can do something along the lines of:

RasterizerConfig config; // sets defaults in constructor
config.SetWireframeDefaults(); // modified the needed wireframe parameters

I think it is quite clear what is going on, and if you always set the default in the constructor then you can easily allocate a configuration on the stack and use it as a basis for the more advanced configurations later on...

Share this comment

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!