in managed directx, Materials are black if I create more than one mesh

I'm using the cool example from the managed directx wiki.
http://pluralsight.com/wiki/default.aspx/Craig.DirectX/MeshBasicsTutorial.html

I created an object that took the mesh name and the device as arguments and have their own render methods. It works perfectly if I only make and render one Mesh but if I render two the materials seem to disapear, every surface of the mesh is totally black except for where there are textures, those parts render fine. What gives

Here's the bit of the constructor which has to do with the mesh:

ExtendedMaterial[] exMaterials;
mesh = Mesh.FromFile(Path.Combine(artPath, name), MeshFlags.SystemMemory,
device, out exMaterials);

if (textures != null)
{
DisposeTextures();
}

textures = new Texture[exMaterials.Length];
materials = new Material[exMaterials.Length];
for (int i = 0; i < exMaterials.Length; ++i)
{
if (exMaterials[ i ].TextureFilename != null)
{
string texturePath = Path.Combine(artPath,
exMaterials[ i ].TextureFilename);
textures[ i ] = TextureLoader.FromFile(device, texturePath);
}
materials[ i ] = exMaterials[ i ].Material3D;
materials[ i ].Ambient = materials[ i ].Diffuse;
}

and here's the render method:

public void RenderMesh()
{
for (int i = 0; i < materials.Length; ++i)
{
if (textures[ i ] != null)
{
someDevice.SetTexture(0, textures[ i ]);
}


device.Material = materials[ i ];


mesh.DrawSubset(i);
}
}


Answer this question

in managed directx, Materials are black if I create more than one mesh

  • fawkes

    Renderstates are the current state of the rendering process - think of them as global varaibles that the GPU understands. e.g from now on draw in wireframe, from now on use this material, from now on blend textures like this. Notice they are always 'from now on'.

    So in your previous code sample, if you unroll the loops and calls to 'render' you get this:

    if (tX !=null) settexture tX
    drawsubset mX
    if (tY != null) settexture tY
    drawsubset mY
    if (tZ != null) settexture tZ
    drawsubset mZ
    etc many times.

    if tY== null then you do not call set texture. Therefore mY gets drawn with the texture that was last set i.e. setTexture tX. But mY was never expected to be drawn with a texture so its texture coordiates are wrong/undefined/not set/zeroed (one or more I don't know). By taking away the if statement you called setTexture null, which says 'from this point forward don't bother looking up the texture coordinates'.

    Does that make better sense




  • MonkWebs

    No becuase SetTexture (..., null) is the way to render something without a texture. 

    By checking for null before running that line of code you were not turning the texture 'off' for the parts of the mesh that didn't have textures. If a mesh subset is texture free, odds are its texture coordinates are not set (i.e. they are 0) so the texture lookup ends up sampling some odd bit of your texture for every vertex..... black bits on the mesh.

    SetTexture is like any renderstate, it stays in effect from that point on until you cahnge or disable it.


  • bvrkchowdary

    Problem solved. But I'm not sure why this makes a difference. I take out the if (texturesIdea != null) statement and always execute device.SetTexture(0, texturesIdea); I can render as many meshes as I like. But I think this means that there would be problems if I wanted to render a mesh without a texture.
  • IanMixxxqqq

    I understood that up until "so the texture lookup ends up sampling some odd bit of your texture for every vertex..... black bits on the mesh.". If there is no texture in the mesh, how can sampling of a texture occur

    What exactly is a renderstate You can point me to an article about it if you like.

  • Tall Dude

    Makes me think you are copying a reference at some point. So when the constructor is called for the 2nd object it overwrites the first one.

    Mail me your project (no binaries) zman@thezbuffer.com, I can't see anything obvious in your code and its always easier in the debugger anyway.


  • djdekker

    So the places that were black were black because setTexture null had not been called
  • Chen_mcc

    Yes, well thats my guess based on the evidence and your code. If there is no texture you *have* to set it to null otherwise it just keeps using whatever the last thing you set.

  • FA65

    Okay, here's an update on my progress. I used the example code in for materials in the directx wiki. Then I try to encapsulate this into an object so all I have to do is transform and then render the primitive. If I make the SetUpMaterials method a method of this new object and call it durning the constructor like so:

    public GameObject(string color, Device device)
    {
       gameVertices = CreateVertexBuffer(device);
       SetupMaterials(color, device);
    }

    both primitives have the same material. Which material it chooses seems to depend on which object is instatiated last.


    link to article in question.
    http://pluralsight.com/wiki/default.aspx/Craig.DirectX/MaterialsBasicsTutorial.html

  • in managed directx, Materials are black if I create more than one mesh