Skip to content

Instantly share code, notes, and snippets.

@Jjagg
Last active September 12, 2020 09:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jjagg/096c5218d21c5e2944a88dbc1b6947b3 to your computer and use it in GitHub Desktop.
Save Jjagg/096c5218d21c5e2944a88dbc1b6947b3 to your computer and use it in GitHub Desktop.
Explaining a possible solution to the sampler/texture/effectparameter problems in MonoGame

This first part would go in the docs:


Effect samplers and textures

Because of the changed syntax for declaring and using samplers since Direct3D10 the MonoGame Team recommends handling samplers and textures in one of the following three ways. This ensures that your shaders will work the same as in XNA and that they'll work when they are automatically translated to GLSL. With the first two options you have explicit textures and should set them via the EffectParameters of your effect. E.g. myEffect.Parameters["MyTexture"].SetValue(myTexture). With the third option you can only set textures on the GraphicsDevice by their texture slot i.e. graphicsDevice.Textures[myTextureSlot] = myTexture.

Using the old sampler syntax

Bind the Texture to a sampler using the sampler_state syntax. This guarantees you'll have an EffectParameter in your Effect for your Texture with the name of the texture. If you do not specify the texture name in a sampler_state declaration explicitly but rely on the texture register matching the sampler register, we cannot identify the name of the texture due to effect compiler limitations and no EffectParameter will be available. Therefore this is not recommended.

Example: In HLSL

Texture2D MyTexture;

sampler MySampler = sampler_state
{
   Texture = (MyTexture);
    ... // optional other sampler state
};

In C# game code

myEffect.Parameters["MyTexture"].SetValue(myTexture);

Using the new sampler syntax

Since D3D10 the bound Texture is no longer part of the sampler state. It allows to use one sampler to sample different textures in a shader. There are no restrictions when using this syntax. It is recommended however to not mix the new and old syntax for samplers.

Example: In HLSL

Texture2D MyTexture;
sampler MySampler = sampler_state // sampler_state is optional
{
   ... // sampler state here
}

In C# game code

myEffect.Parameters["MyTexture"].SetValue(myTexture);

Do not declare textures explicitly

You do not have to declare textures. If you bind your sampler to a register, you can set the corresponding texture through the API by specifying the texture slot instead of a name.

Example: In HLSL

sampler MySampler : register(s3);

In C# game code

graphicsDevice.Textures[3] = myTexture;

[NOT IN THE DOCS]

How we can actually achieve this: only generate a texture parameter if the sampler state has a texture bound!

if (sampler state has texture bound)

[generate texture parameter with the texture name]

else if (sampler register is not explicitly set)

[Optionally, we can generate texture parameter with sampler name so the user can reliably set the sampler texture] // I think it's better if we don't do this, users shouldn't only declare a sampler and not explicitly set its register... // Also this will probably cause issues when users use the new sampler syntax option above without setting a register. // EDIT: We definitely shouldn't do this! // If we do this we'll also have to generate EffectParameters with the sampler name when people use the // new syntax because we cannot differentiate between the samplers in the two cases!

else

[Don't generate a texture parameter, if users only declare a sampler and explicitly set the register they intend to bind textures to the corresponding registers, not use EffectParameter syntax!]

Notes:

  • Textures used with the new syntax will get a parameter because we can find their name and slot through reflection
  • EffectParameters will behave like in XNA except in the following case
Texture2D MyTexture : register(t0);
sampler MySampler : register(s0);

which is why it is explicitly advised against.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment