Default values for samplers

Right now in our engine we use a scheme like this to name texture samplers in a shader:

uniform sampler2D texture0;//diffuse map
uniform sampler2D texture1;//normal map
uniform sampler2D texture2;//specular map
uniform sampler2D texture3;//emissive map

The engine automatically sets the uniforms texture0…texturen to 0,1,2, etc., and each material has slots 0 to maxtexture-1 where textures can be assigned:

Material::SetTexture( Texture* texture, int index )

This works well, but people are complaining about having to use these names for texture sampler variables in the shader. I propose the following solution.

An integer can be used as a default value for sampler uniforms:

uniform sampler2D diffusemap=0;
uniform sampler2D normalmap=1;
uniform sampler2D specularmap=2;
uniform sampler2D emissivemap=3;

I think it would perhaps be better to use they existing layout qualifier stuff?

layout(unit = 0) uniform sampler2D diffusemap;

I another thread I also discussed something similar for uniform block bindings.

I would still like to see separate texture and sampler units exposed to GLSL given that they exist now in the C API.

I think it would perhaps be better to use they existing layout qualifier stuff?

Better in what way? If you’re going to do it, I’d prefer it be done in a way that adds only 4 characters to a definition instead of 16. Also, samplers cannot be given initializers, so it wouldn’t break anything to define sampler initializers to mean, well, initializing them to a sampler in GL.

I would still like to see separate texture and sampler units exposed to GLSL given that they exist now in the C API.

That’s not what sampler_objects does. It doesn’t create “sampler units”; it simply allows you to separate the state that a texture is sampled with from the texture object itself. You still bind sampler objects to texture units.

It would be consistent with the way shader’s intputs/outputs are explicitly connected to attributes/draw buffers.
Now as far as im concerned they could go ’ = 7’ for all these instead of more verbose ‘layout(location = 7)’, but its kinda too late.

Now as far as im concerned they could go ’ = 7’ for all these instead of more verbose ‘layout(location = 7)’, but its kinda too late.

Here’s why they did it that way.

You can initialize uniform and constant variables:


uniform vec3 myUniform = vec3(1.0, 0.0, 0.0);

For uniforms, this is the behavioral equivalent of calling glLinkProgram, immediately getting the uniform location for ‘myUniform’, and setting its value with glUniform3f.

If you were to then have this:


in vec3 myAttrib = 0;

This looks like an initializer. But it isn’t; it’s specifying the attribute index. Therefore, it is overloading the initializer syntax for something that isn’t really initializing the variable to a value.

Allowing sampler uniforms to be initialized with a texture unit is initialization. It’s exactly analogous to initializing uniform values. After glLinkProgram, you get the uniform location and use glUniform1i to set its value. It’s the same thing as other uniform initialization.

The only inconsistency that this would cause is that you are not normally allowed to set values to a sampler in GLSL. But this is a pretty minor issue compared to the way it perfectly works with the rest of GLSL.

An integer can be used as a default value for sampler uniforms:

uniform sampler2D diffusemap=0;
uniform sampler2D normalmap=1;
uniform sampler2D specularmap=2;
uniform sampler2D emissivemap=3;

I’d like to initialize sampler uniforms this way as well.

With the old method, I already got a schizophrenic linker warning on ATI cards, if I used cubemaps and 2d textures in the same shader; something like “two or more samplers of different types bound to unit 0”. The driver obviously used default value 0 for all samplers internally and then moaned about it… with me never having had a chance to assign sane values before the very first link.

I follow that request! Simple but clever idea!

[quote]
An integer can be used as a default value for sampler uniforms:

uniform sampler2D diffusemap=0;
uniform sampler2D normalmap=1;
uniform sampler2D specularmap=2;
uniform sampler2D emissivemap=3;

I’d like to initialize sampler uniforms this way as well.
[/QUOTE]

Ditto and definitely the above syntax as it is consistent (you are setting what texture unit the sampler takes data from, which is the value set via glUniform1i).

Yup, disregard my previous post - for some reason i confused sampler ‘value’ with its location. Dont know what was i thinking.

You got that on linking?
For me, it would link fine but glValidate would fail.

Also, we have documented that message here
http://www.opengl.org/wiki/GLSL_:_common_mistakes#Binding_A_Texture

Output from shader Fragment shader(s) linked, vertex shader(s) linked.
Validation failed - samplers of different types are bound to the same texture image unit.