Texture arrays in HLSL

Started by
1 comment, last by LemonBiscuit 9 years, 11 months ago

Hello,

So I'm trying to create a lighting system on my XNA game, and I found a great shader on the internet:

http://pastebin.com/Y3Lvuwwk

But the problem is that my models have multiple textures, and this shader accept only one texture, so my models are finally drawn with one model on all their meshes.

Here's how I apply the effect on my model:


        public void SetModelEffect(Effect effect, bool CopyEffect)
        {
            foreach (ModelMesh mesh in _model.Meshes)
                foreach (ModelMeshPart part in mesh.MeshParts)
                {
                    Effect toSet = effect;

                    // Copy the effect if necessary
                    if (CopyEffect)
                        toSet = effect.Clone();

                    MeshTag tag = ((MeshTag)part.Tag);

                    // If this ModelMeshPart has a texture, set it to the effect
                    if (tag.Texture != null)
                    {
                        setEffectParameter(toSet, "BasicTexture", tag.Texture);
                        setEffectParameter(toSet, "TextureEnabled", true);
                    }
                    else
                        setEffectParameter(toSet, "TextureEnabled", false);

                    // Set our remaining parameters to the effect
                    setEffectParameter(toSet, "DiffuseColor", tag.Color);
                    setEffectParameter(toSet, "SpecularPower", tag.SpecularPower);

                    part.Effect = toSet;
                }
        } 

And here is how I draw my models with all their textures when the effect is not applied:


            foreach (ModelMesh mesh in _model.Meshes)
            {
                Matrix localWorld = _modelTransforms[mesh.ParentBone.Index] * world;
                foreach (ModelMeshPart meshPart in mesh.MeshParts)
                {
                    Effect effect = meshPart.Effect;


                    if (effect is BasicEffect)
                    {
                        BasicEffect bEffect = (BasicEffect)effect;

                        bEffect.Texture = _textures[newName];


                        bEffect.World = localWorld;
                        bEffect.View = view;
                        bEffect.Projection = projection;
                         ...

So what I thought to do is, I send on SetModelEffect all my model textures to the shader which will be stored in a texture array, and then in the shader I just do a loop through all the textures and apply the light effect. But I don't know how to do that.

I'm quite a newbie with shaders so tell me if my idea is bad...

Thank you!

Advertisement

Either:

1) you need to have a different instance of your effect (you seem to have code that Clones an effect, so it sounds like you have some support for this already?) for every ModelMeshPart (ModelMeshPart.Effect), and you set the appropriate textures on that effect. Then draw with mesh.Draw(). Or,

2) you use a single instance of your effect, and loop through all the ModelMeshParts, For each ModelMeshPart, set the needed texture on your effect and draw the mesh part "manually" using DrawIndexedPrimitives (ModelMeshPart contains the VertexBuffer and IndexBuffer and all the needed information to pass to DrawIndexedPrimitives).

I took a second look on the code and indeed it should work, because different instances of the effect are applied on every meshparts.

I tried to debug it and it seems the problem is actually coming from the fact that when I generate tags, all ModelMeshPart have the same texture...

Here's my function generateTags, which create a MeshTag used by SetModelEffect:


private void generateTags()
        {
            foreach (ModelMesh mesh in _model.Meshes)
                foreach (ModelMeshPart part in mesh.MeshParts)
                    if (part.Effect is BasicEffect)
                    {
                        BasicEffect effect = (BasicEffect)part.Effect;
                        MeshTag tag = new MeshTag(effect.DiffuseColor,
                            effect.Texture, effect.SpecularPower);
                        part.Tag = tag;
                    }
        }

So on my LoadContent I added this:


foreach (ModelMesh mesh in _model.Meshes)
                    foreach (ModelMeshPart part in mesh.MeshParts)
                        if (part.Effect is BasicEffect)
                        {
                            BasicEffect effect = (BasicEffect)part.Effect;
                            string newName = mesh.Name.Split('_')[0];
                            effect.Texture = _textures[newName];
                        }

But it doesn't work; I don't get it...

EDIT:

So I got something working.

In my generateTags function, I had to reload tag.Texture with my texture dictionnary I've been using when loading the content. That works, but I still don't understand why does my tags are all the same... ?

Thx anyway for putting my on the correct way, once again!

This topic is closed to new replies.

Advertisement