I’m looking for ways to improve the content processor for meshes and my workflow for exporting .fbx files for XNA. Yesterday I figured out how to keep the correct texture filenames for the meshes and not have Blender assign “untitled” for the name. Remove any unwanted texture images in the UV/image editor by Shift-clicking the Unlink button, save the file and re-open it.
Now I can export a single mesh with multiple diffuse textures. I’m also looking to do the same to support multiple normal map textures for models, using this forum thread as a guide. This also works with specular maps, glow maps and just about any kind of texture data you want. Just give them different property names and have the content processor pick them up.
Although editing .fbx files is fine, I would rather have the files already prepared upon export, but Blender made a huge oversight with not supporting the inclusion of custom properties with their .fbx file exporter. So disappointed at the Blender team for that. Maybe someone has made a script to add that feature in?
Supporting multiple textures
I have tested texture layering on this awesome dwarf model I found on Open Game Art. The clothing, armor and body are different mesh objects in the blend file and in XNA.
Each mesh has its own diffuse, normal and specular texture loaded by the content processor. The GBuffer only writes to one channel for the spec map’s brightness, so the specular output is in monochrome. Color specular highlights would be something I would add later on. Most likely I will add support for multiple textures in meshes with a Dictionary to store the key names that map to effect parameters. Also, I will improve organization on reading paramters for rendering in custom effects. For instance, here is part of the rendering code for a mesh using a custom (non-GBuffer) effect:
if (instancedModel.animationPlayer != null) effect.Parameters["bones"].SetValue( instancedModel.animationPlayer.GetSkinTransforms()); effect.Parameters["Texture"].SetValue(instancedModel.Textures[mesh.Key]); effect.Parameters["World"].SetValue(world);
It looks fine at first. All meshes have a World transformation matrix, and if a texture is found for the current mesh, set that parameter to the texture sampler. Also, animated models have an animationPlayer, so we know that it has bone matrix transformations.
But there’s a problem, what if you have an effect to render models but it does not need the textures? I see two quick but not so great fixes for this: check if the Texture parameter exists in the rendering code, or add a sampler for Texture in the shader. The first one is not very scalable if you start needing to check for many shader parameters, and the second one is just wasteful.
Currently I am using that second option as a temporary workaround to draw a depth map of objects from the light’s perspective. It has to support both static and animated objects, but textures are not important for this shader. The only purpose adding a Texture parameter in it is just to keep the program from crashing, otherwise the renderer is going to search for a null parameter. If you choose a shader that was compiled with diffuseTex defined, and your mesh has nothing defined for that, the shader will try to sample from something that’s not bound to it. It’s hacky and I don’t want to keep doing things this way.
Adding more flexibility for different materials
My next objective is to add some form of multiple material support with custom shaders. At first it will check to see if an object has diffuse, normal and specular textures, and whether the shader needs them. Later on I want to really support a wide array of materials for different types of objects. So nearly anything from reflective objects to transparent objects, or objects that require special types of lighting.
Something along the lines of a data-driven renderer is probably what I am looking for. It would use a combination of material states/types to use the appropriate commands and shaders to render the object with. It’s most commonly done using a long or integer type as a bitmask, which is the way I’ll plan to do it. I will start with a small set of material and texture types to choose from, and then gradually add more as I figure out how to get different effects working in the renderer.