Weird Behavior with GLSL int

Started by fiendfan1, June 02, 2013, 00:15:32

Previous topic - Next topic

fiendfan1

I am rendering multi-textured models using shaders and in order to do so, I am passing in a varying int that tells each vertex which texture ID to use. (I am using VBOs)

First, I give each vertex a texture ID (-1 if nothing, 0 if texture0, 1 if texture1 in this case)

Then I send info to the vertex shader as an attribute int.

The vertex shader passes the attribute int to the frag shader as a varying int

The frag shader handles changes to gl_FragColor

And when I did some testing, I found that all the ID's are either 0 (which is correct), about -13000000 or some huge negative number like that (Should be -1), or about 13000000 or some huge positive number like that (should be 1).

Could it be something about the way I pass the attribute to the shaders? or the conversion from attribute to varying?

Heres the Java Code:
int texIDVar = glGetAttribLocation(m.shader, "textureID");

glBindBuffer(GL_ARRAY_BUFFER, vboTexIDHandle);
glVertexAttribPointer(texIDVar, 1, GL_INT, false, 0, 0);


//Then I enable that Attrib, call the VBO, then disable it


And the parts of the shaders involved:
/// VERTEX SHADER START ///
varying int texID;

attribute int textureID;

void main() 
{
	texID = textureID;
        
        // I am testing with just 2 textures right now
        gl_TexCoord[0] = gl_MultiTexCoord0;
	gl_TexCoord[1] = gl_MultiTexCoord1;
}
/// VERTEX SHADER END ///
/// FRAG SHADER START ///

varying int texID;

void main() 
{
        //NOTE: TEXTURED POINTS ARE 0 texID
	if(texID < 0)
	{	
		gl_FragColor = vec4(ambColor, 1.0) + vec4(diffColor + specColor, 1.0);
		//gl_FragColor = vec4(1, 0, 0, 1);
	}
	else
	{
		vec3 textureColor = vec3(texture(textures[texID], gl_TexCoord[texID].st));
		gl_FragColor = vec4(ambColor, 1.0) + vec4(diffColor * textureColor + specColor, 1.0);
	}
}

fiendfan1

So I found out that the big number was 1065353215, which is float-format for 1.

What I had to do is instead of

glVertexAttribPointer(texIDVar, 1, GL_INT, false, 0, 0);

I used

glVertexAttribPointer(texIDVar, 1, GL_FLOAT, false, 0, 0);

I have no idea why and it makes no sense, because I was passing an int to an int, but it works.

Fool Running

Maybe because you're saying it's a varying? Maybe try changing it to a uniform. I don't know if you can do that because of your texId being defined in a VBO, but if you can, that might solve it.  :P
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

quew8

This is from the OpenGL specs:
Quote
type
Specifies the data type of each component in the array. The symbolic constants GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, and GL_UNSIGNED_INT are accepted by glVertexAttribPointer and glVertexAttribIPointer. Additionally GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE, GL_FIXED, GL_INT_2_10_10_10_REV, and GL_UNSIGNED_INT_2_10_10_10_REV are accepted by glVertexAttribPointer. GL_DOUBLE is also accepted by glVertexAttribLPointer and is the only token accepted by the type parameter for that function. The initial value is GL_FLOAT.
That last bit seems odd but perhaps has something to do with it. I didn't know method parameters could have initial values but hey.

quew8

Also I recommend using texture sheets and messing around with texture coordinates rather than your current solution.

Also if statements in shaders tend to be very inefficient (shaders run on several vertices simultaneously so they are obliged to run both all clauses for every vertex) so I would recommend having two or more separate shaders for the different tasks. As long as you do all of the first shaders work before binding the next shader (as in render all solid colour primitives, then all texture1 primitives, then all texture2) then the overhead from binding the different shaders should be minuscule.

fiendfan1

Quote from: quew8 on June 03, 2013, 21:29:22
Also I recommend using texture sheets and messing around with texture coordinates rather than your current solution.

Yeah, but I tried making a program that would make that possible with .OBJ/.MTL files (with multiple textures), and it turns out to be fairly difficult. I will at some point, but not now.

Quote from: quew8 on June 03, 2013, 21:29:22
Also if statements in shaders tend to be very inefficient. As long as you do all of the first shaders work before binding the next shader (as in render all solid colour primitives, then all texture1 primitives, then all texture2) then the overhead from binding the different shaders should be minuscule.

That is a good idea. I think I will try to implement it. Thanks again!