XBox:Framework:Models

From MadoxLabs

Template:Downloads:XBox

Edit Downloads:XBox (http://www.madox.ca/mediawiki2/index.php?title=Template:Downloads:XBox&action=edit)

Started trying to put together a grand unified model renderer. The basic requirements for a model renderer are:

  • able to render instanced models
  • able to handle skinned models (bones and animations)
  • able to handle multi-pass, multi-technique
  • models can have multiple shaders on various parts
  • handles setting custom parameters seemlessly

Model Content Importer

I started by making my own model importer based on the XNA Skinning model (though it doesn't do skinning yet). The main reason for it was so that I can have a 'shader' parameter that is settable through Visual Studio properties. This lets me assign a shader to a model. If no shader is set, the model look for a shader named the same as the model. If that doesn't exist, it tries the name of the model part.

The importer loads the model and divides it up into model parts which contain the vertexes of the part combined with the material parameters, shader and texture. The importer sets HLSL variables 'Texture' and 'HasTexture' for you, so these have to exist in all shaders.

Model Rendering

The Model class is a typical renderer that loops over a model's ModelParts rendering each set of vertexes. It accepts a technique name and array of instance World matrixes. Model always assumes you are rendering many instances currently.

The Model sets some fields automatically so they must exist: InstanceTransforms, View, Projection, VertexCount. Eventually, the Model will also set all the material properties for proper lighting. In additions, you can pass in a set of RenderParameters for it to set.

RenderParameters are a set of named objects are set on the shader's Parameters. The parameters are set using GetParameterBySemantic() so every shader variable must have a matching sematic set. This is because later I will be adding a shader management system that mangles variable names.

Render States

An important part of the shader is the render state that it needs to be set. In XNA4, setting render states in HLSL has gotten a bit goofy and I found it hard to figure out what the available states are, which are depricated and what the XNA names are compared to the HLSL names.

Acting on some advice from the XNA forums, I added setting render states from Pass annotations. Each Pass can now say what RenderState it wants, and can also define what that RenderState is. A RenderState is an object that looks like:

public sealed class mxState
 {
   public BlendState mBlendState;
   public DepthStencilState mDepthState;
   public RasterizerState mRasterState;
   public string mName;
 } 

It represents a compelete set of states and attaches a name to them. A RenderStateManager stores all the RenderStates, and when a Pass requires a certain state, it is fetched and applied to the GraphicsDevice. An example of a Pass setting a state is:

technique PerPixel
{
  pass P0
  < string state = "Default"; >
  {
    VertexShader = compile vs_3_0 vPerPixel();
    PixelShader = compile ps_3_0 pPerPixel();
  } 
}

This pass wants a state called Default. Since it doesn't define Default, it gets the default which is:

 mBlendState = BlendState.Opaque;
 mDepthState = DepthStencilState.Default;
 mRasterState = RasterizerState.CullCounterClockwise;

This shader wants one of the predefined blend states:

technique XBox
{ 
  pass Pass1
  < string state = "UIShader"; 
    string blendstate = "AlphaBlend"; 
  >
  {  
    VertexShader = compile vs_3_0 VS();
    PixelShader = compile ps_3_0 PS();
  }
}

Other annotations include renderstate and depthstate.

You can also define you own custom state by manually setting any of the individual parameters that are defined on the state objects.

technique XBox
{ 
  pass Pass1
  < string state = "UIShader"; 
    string blendstate = "AlphaSourceBlend = InverseSourceAlpha; MultiSampleAntiAlias = false;"; 
    string renderstate = "FillMode = WireFrame;";
  >
  {  
    VertexShader = compile vs_3_0 VS();
    PixelShader = compile ps_3_0 PS();
  }
}

In this case, UIShader gets created with the states from the annotation and stored in the RenderStateManager for future use.

Personal tools
Toolbox