Sampling a texture in a custom shader

Hello,

I have experience with graphics programming, but for the love of god I can’t manage to perform a simple texture sample in a custom shader.

Has anyone already managed to perform a texture sample (with a most recent version of Xenko) ?

There seem to be a few posts about it already on this forum but between now and 2015 it seems that Xenko had major rendering changes…

Below is my code, I would like to precise that I managed to get it working passing a simple color value from CPU instead of sampling a texture.

Also, I have check the texture dimensions in the shader for debug and I always get 0…

**** Please only answer if you managed yourself to sample a texture in a recent version of Xenko****

Thanks in advance.

//***** Material creation *****//

var material = Material.New(m_graphicsDevice, new MaterialDescriptor
{
	Attributes =
	{
		Emissive = new MaterialEmissiveMapFeature(new SiliconStudio.Xenko.Rendering.Materials.ComputeColors.ComputeShaderClassColor() { MixinReference = "SimpleTexture"  }),
	}
});

...

material.Parameters.Set(SimpleTextureKeys.MyTexture, myTexture);

modelComponent.Model.Materials.Add(material);


//***** Shader code *****//

shader SimpleTexture: ComputeColor
{
    stage stream float2 TexCoord : TEXCOORD0;

    SamplerState MySampler
    {
        Filter = ANISOTROPIC;
        AddressU = Wrap;
        AddressV = Wrap;
        MaxAnisotropy = 16;
    };
	
	// Tried with and without cbuffer
	//Texture2D MyTexture;

    cbuffer PerMaterial
    {
        Texture2D MyTexture;
    }

    override float4 Compute()
    {
		// Tried reading the tex dimensions for debug... always return null
		//float w;
        //float h;
        //MyTexture.GetDimensions(w, h);
        //if(w == 0) discard;
	
        return MyTexture.Sample(MySampler, streams.TexCoord);
    }
};

Yep… Looks like a bug in Xenko. I tried several ways and spended several hours but looks like its impossible for now…

You must disable Stream property on Texture in GameStudio, than it will load correctly.

Hi,

I don’t understand shader and its system but this seems to work.

// MyCustomShader.xksl
    shader MyCustomShader : ComputeColor
    {
        rgroup PerMaterial
        {
            stage Texture2D MyTexture;
        }

        stage stream float2 TexCoord : TEXCOORD0;

        SamplerState MySampler
        {
            Filter = ANISOTROPIC;
            AddressU = Wrap;
            AddressV = Wrap;
            MaxAnisotropy = 16;
        };

        override float4 Compute()
        {
            return MyTexture.Sample(MySampler, streams.TexCoord);
        }
    };

// TestScript.cs
    public class TestScript : StartupScript
    {
        public Texture Texture;
        public override void Start()
        {
            var material = Material.New(GraphicsDevice, new MaterialDescriptor
            {
                Attributes = new MaterialAttributes
                {
                    DiffuseModel = new MaterialDiffuseLambertModelFeature(),
                    Diffuse = new MaterialDiffuseMapFeature
                    {
                        DiffuseMap = new ComputeShaderClassColor { MixinReference = "MyCustomShader" },
                    },
                },
            });

            material.Passes[0].Parameters.Set(MyCustomShaderKeys.MyTexture, Texture);

            var entity = new Entity(new Vector3(0f, 1.5f, 0f));
            entity.GetOrCreate<ModelComponent>().Model = new Model
            {
                    new Mesh
                    {
                        Draw = GeometricPrimitive.Sphere.New(GraphicsDevice).ToMeshDraw(),
                    },
                    material
            };

            Entity.Scene.Entities.Add(entity);
        }
    }
1 Like

That worked for me, thanks mate

If you wish to create a shader where you can set a texture in the game studio, the following code should work:

shader TextureShader: ComputeColor
    {
        //Not necessarily a texture, it can also be a different shader, a color, etc.
        compose ComputeColor MatrixTexture; 

        override float4 Compute()
        {
            return MatrixTexture.Compute();
        }
    };