OpenGL/GLSL texture coordinates.
category: general [glöplog]
Hi alll.
I'm not quite sure what I experience is a but or correct behaviour, because I use an scenegraph library, so I'm asking around here.
I have an application that uses textures in units 0-3 in a GLSL shader. I always use texture coordinates from unit 0 ("gl_TexCoord[0] = gl_MultiTexCoord0;" in the vertex shader) for all samplers. Then in the fragment shader I do "vec2 texCoord = gl_TexCoord[0].st;" and work with that (vec4 color = texture2D(bla, texCoord);). Now, if I have NO texture in unit 0 (but still some in 1-3) the texture coordinates in unit 0 are always (1.0, 0.0).
Is this specified OpenGL behaviour or is it the library screwing up here?
I'm not quite sure what I experience is a but or correct behaviour, because I use an scenegraph library, so I'm asking around here.
I have an application that uses textures in units 0-3 in a GLSL shader. I always use texture coordinates from unit 0 ("gl_TexCoord[0] = gl_MultiTexCoord0;" in the vertex shader) for all samplers. Then in the fragment shader I do "vec2 texCoord = gl_TexCoord[0].st;" and work with that (vec4 color = texture2D(bla, texCoord);). Now, if I have NO texture in unit 0 (but still some in 1-3) the texture coordinates in unit 0 are always (1.0, 0.0).
Is this specified OpenGL behaviour or is it the library screwing up here?
Sorry for the typos. Example code:
Vertex shader
Fragment shader
Again: If there's a texture in unit 0 everything's fine. If no texture in unit 0 texture coordinates are always (1.0, 0.0).
Vertex shader
Code:
varying vec3 lightVec;
varying vec3 halfVector;
varying vec2 texCoord;
void main(void)
{
gl_Position = ftransform();
texCoord = gl_MultiTexCoord0.xy;
vec3 normal = normalize(gl_NormalMatrix * gl_Normal);
mat3 trans = transpose(gl_NormalMatrix);
vec3 tangent = normalize(gl_NormalMatrix * trans[0]);
vec3 binormal = normalize(gl_NormalMatrix * trans[1]);
vec3 vVertex = vec3(gl_ModelViewMatrix * gl_Vertex);
vec3 tmpVec = gl_LightSource[0].position.xyz - vVertex;
lightVec.x = dot(tmpVec, tangent);
lightVec.y = dot(tmpVec, binormal);
lightVec.z = dot(tmpVec, normal);
halfVector = reflect(-tmpVec, gl_Normal);
halfVector.x = dot(tmpVec, tangent);
halfVector.y = dot(tmpVec, binormal);
halfVector.z = dot(tmpVec, normal);
}
Fragment shader
Code:
uniform sampler2D colorMap;
uniform sampler2D normalMap;
uniform sampler2D heightMap;
uniform float strength;
uniform float scale;
uniform float bias;
uniform int parallax;
uniform int isTexUnit0Used;
varying vec3 lightVec;
varying vec3 halfVector;
varying vec2 texCoord;
void main (void)
{
vec3 h = normalize(halfVector);
if (parallax == 1) {
float height = texture2D(heightMap, texCoord).r;
height = height * scale + bias;
texCoord = texCoord + (height * h.xy);
}
vec3 n = normalize(texture2D(normalMap, texCoord).rgb * 2.0 - 1.0);
vec3 l = normalize(lightVec);
float nDotL = max(0.0, dot(n, l));
float nDotH = max(0.0, dot(n, h));
float power = (nDotL == 0.0) ? 0.0 : pow(nDotH, gl_FrontMaterial.shininess);
vec4 ambient = gl_LightSource[0].ambient;
vec4 diffuse = gl_LightSource[0].diffuse * gl_FrontMaterial.diffuse * nDotL;
vec4 specular = gl_LightSource[0].specular * gl_FrontMaterial.specular * power * strength;
vec4 color = gl_FrontLightModelProduct.sceneColor + ambient + diffuse + specular;
if (isTexUnit0Used == 0) {
gl_FragColor = color;
}
else {
gl_FragColor = color * texture2D(colorMap, texCoord);
}
}
Again: If there's a texture in unit 0 everything's fine. If no texture in unit 0 texture coordinates are always (1.0, 0.0).
Is it (1.0, 0.0) in all cases or just the test case you've tried? I can't be bothered digging in the spec but I would guess that that value is undefined.
Haven't tried it in OpenGL. I use a scenegraph library called Coin3D.
Do you mean that the value MEANS it is undefined or the value must be undefined in this case? I read through the GL specs a bit, but didn't get any useful information.
Do you mean that the value MEANS it is undefined or the value must be undefined in this case? I read through the GL specs a bit, but didn't get any useful information.
I also tried adding a
to the vertex shader which seems to help in some cases.
Code:
if (isTexUnit0Used == 0) {
texCoord = gl_MultiTexCoord1.xy;
}
else {
texCoord = gl_MultiTexCoord0.xy;
}
to the vertex shader which seems to help in some cases.
Well unless I've misunderstood, what you basically have is an uninitialized variable and so the value would be undefined and possibly vary on different implementations.
Ifs in a shader?
The question is: IS gl_MultiTexCoord0 uninitialized by definition if the texture unit 0 is not being used?! That is what I'm asking.
If it should NOT be uninitialized (imo, because the application is still passing the texture coordinate values) then the scene graph library screws up somewhere and does not pass the coordinates.
If it should NOT be uninitialized (imo, because the application is still passing the texture coordinate values) then the scene graph library screws up somewhere and does not pass the coordinates.
Or: IS gl_MultiTexCoord0 uninitialized by the OpenGL specs definition if the texture unit 0 is not being used?
maybe the engine has some code like this (found in a Maya Hardware Shader example):
Code:
glClientActiveTexture(GL_TEXTURE0 + coord);
if (coord < texCoordCount && texCoordArrays[coord]) {
//this set exists
glTexCoordPointer(2, GL_FLOAT, 0, texCoordArrays[coord]);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
} else {
//the set does not exist
glMultiTexCoord2f(GL_TEXTURE0 + coord, 1.0f, 0.0f);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
xernobyl, welcome to 2004! \o/
I don't think texture coordinates and texture units have anything to do with each other here. And gl_multitexcoord0 should probably have the last set value (immediate mode or as part of (maybe previous) vertex buffer).
But if the library doesn't use the unit and only uses the tcoord0 for the texture I guess it's fair enough that it's not spending time sending the values..
But if the library doesn't use the unit and only uses the tcoord0 for the texture I guess it's fair enough that it's not spending time sending the values..
well. if it is like this, it pretty much fucks up my hole concept... :(
Quote:
it pretty much fucks up my hole concept
I couldn't find a better name for accessing non-existing data :)
Rare[etc], if you can modify shaders, can't you just trick the scenegraph library by enabling a texture on unit 0? I assume all you're trying to do is index another texture with the coordinates in unit 0...?
thanks for answering, people. The library disabled texture coordinates when there's no texture in the unit, as bartman and psycho pointed out.
I put in a dummy texture now, which works to some extent. coordinates are still wrong though, but that is a problem in the scene graph...
I put in a dummy texture now, which works to some extent. coordinates are still wrong though, but that is a problem in the scene graph...