4
votes

I'm looking for a way to access OpenGL states from a shader. The GLSL Quick Reference Guide, an awesome resource, couldn't really help me out on this one.

In the example I'm working on I have the two following shaders:

Vertex:

void    main()
{
    gl_FrontColor = gl_Color;
    gl_TexCoord[0] = gl_MultiTexCoord0;
    gl_Position = ftransform();
}

Fragment:

uniform sampler2D   tex;
uniform float   flattening;

void main( void ) 
{
    vec4    texel;
    texel = texture2D(tex, gl_TexCoord[0].st);
    texel.r *= gl_Color.r;
    texel.g *= gl_Color.g;
    texel.b *= gl_Color.b;
    texel.a *= gl_Color.a;
    gl_FragColor = texel;
}

When I'm rendering polygons that are not textured, their alpha values are correct, but they're assigned the color black.

1, What conditional check can I setup so that the variable 'texel' will be set a vec4(1.0, 1.0, 1.0, 1.0) rather than sampling from a texture when GL_TEXTURE_2D is disabled?

2, Would the processing be faster if I wrote different shaders for different texturing modes and switch between them where I would use glEnable/glDisable(GL_TEXTURE_2D)?

2
Short note: you could write texel *= gl_Color; as one vector op instead of 4 scalar ops.Macke
thanks, is it hardware accelerated? wouldn't it be one function call and 4 scalar ops vs 4 scalar ops?zyndor
It's accelerated (if you're not running all shaders in software, in which case you're int seconds-per-frame territory), but there's no additional function call. True, it will still be 4 scalar ops (on modern GPUs), I just think of it as a vector op, but it's also much easier to follow and debug the code that way. (GLSL compilers inline things very heavily to avoid function call overhead.)Macke
It's indeed a vector op (=all 4 multiplications are calculated in parallel) and you should always try to group scalar operations if possible. The GLSL compiler may optimize 4 seperate operations into one but I wouldn't count on it.Maurice Gilden

2 Answers

8
votes

Sorry, but you can't access that kind of state from GLSL, period.

In fact, in the future GLSL you have to send all unforms/attributes yourself, i.e. no automagic gl_ModelViewMatrix, gl_LightPosition, gl_Normal or the like. Only basic stuff like gl_Position and gl_FragColor will be available.

That sort of voids your second question, but you could always use #ifdef's to enable/disable parts in your shader if you find that more convenient than writing separate shaders for different texture modes.

Related, do note that branching is generally rather slow so if you have the need for speed do avoid it as much as possible. (This matters especially irregular dynamic branching, as fragments are processed in SIMD blocks and all fragments in a block must compute the same instructions, even if they only apply for one or a few fragments.)

3
votes

One method I've seen is to bind a 1x1 texture with a single texel of (1.0, 1.0, 1.0, 1.0) when rendering polygons that are not textured. A texture switch should be less expensive than a shader switch and a 1x1 texture will fit entirely inside the texture cache.