PDA

View Full Version : Multi Textures VBO shaders



raziza
02-06-2012, 03:24 AM
Hi,

I'm using 3rd party that provides 2d and 3d views.
In both of them i am doing my drawing in pure OpenGL commands.

And now the problem:
I'm drawing quads with textures, and i'm doing it using VBO and shaders.

In the data arrays I'm providing for every vertex an attribute which is the texture number,
and according to this number i'm fetching the right sampler2D in the fragment shader.
It is working very good in 2D.

Application code


glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, intTexID1);
glActiveTexture(GL_TEXTURE0 + 1);
glBindTexture(GL_TEXTURE_2D, intTexID2);

glActiveTexture(GL_TEXTURE0); // resetting the active texture back

glUniform1iv(UniformTextureLoc, new float[]{ 0, 1 });

Shader code


varying vec4 v_texture_color;
varying float v_texture_id; // The attribute from the vertex
uniform sampler2D u_textures[10];

void main(void)
{
gl_FragColor = v_texture_color * texture2D(u_textures[v_texture_id], gl_TexCoord[0].xy);
}


In 3D, it is working (after allot of fixes) but weird problem occurs.

I've attached a screen preview of the problem. There are 2 quads. each has different textures.

It's look like the second texture is acting weird (the green). every movement of the camera it's showing something else, but its mixing the textures - It's like he is using some of the first texture also sometimes.

I've had few problems with this 3rd party before, but I found my mistakes (like not setting back the active texture to GL_TEXTURE0, or reset the binned buffer glBindBuffer(GL_ARRAY_BUFFER, 0)).

The thing is that it is working on 2D. so the 3rd party must enable\disable something that i'm not familiar with.

Is it familiar to anyone ? any ideas ?

BionicBytes
02-06-2012, 10:35 AM
varying vec4 v_texture_color;
varying float v_texture_id; // The attribute from the vertex
uniform sampler2D u_textures[10];

void main(void)
{
gl_FragColor = v_texture_color * texture2D(u_textures[v_texture_id], gl_TexCoord[0].xy);
}



I can't way that this is the actual problem, but the sampler array is an array of integers. You have supplied a float and it is being interpolated by the fragment shader.

perhaps try setting:
varying float v_texture_id;
to:
flat varying float v_texture_id;
...in both the VS and FS

and in the FS

int lookup = int (v_texture_id); //cast as integer

gl_FragColor = v_texture_color * texture2D(u_textures[lookup], gl_TexCoord[0].xy);

raziza
02-07-2012, 12:53 AM
The float array was my mistake - I just wanted to simplify my code.. It is int array in real. my bad.

I've tried the flat modifier, but didn't quiet made it work. because it always threw compilation error.

I've Tried the int casting of the v_texture_id, and it didn't work.
although it gave me an angle to solve it. I've thought that maybe this varying is not an exact values like i sent it - such as 0 or 1 (maybe like 0.000001 and 0.999999) - so i just round the value.. and boom. works great.

still don't know why it is working like this (Do you ?) but what the hack. It works great now. It haven't harm the performances due to the round method. so.. great.

I've attached the result image just for fun.

Thanks very much for the help, and the new angle :)

Alfonse Reinheart
02-07-2012, 01:19 AM
Samplers are special types in OpenGL. Though they are technically uniforms and are treated as such by the API, you can't really treat them like any old uniform.

Arrays of samplers are highly restricted. In particular, unless you're on GLSL 4.10 hardware or better, the index you use to access an array of samplers must be a compile-time constant. A varying value isn't a compile-time constant. Even on 4.10+ hardware, it needs to be "dynamically uniform", which means the value must be the same for all primitives for any one triangle being rendered. Hence the need for `flat`.

If you're breaking these rules and it appears to work, appearances can be deceiving. Porting such rule violating code to other hardware may fail spectacularly.

BionicBytes
02-07-2012, 04:04 AM
I agree with Alfonso. Sampler arrays are an oddity in GLSL and you really do need to use the flat keyword for your varyings.
Perhaps the compile error is due to too low a version number for the GLSL shaders.
Have you tried adding the following to both the VS and FS:

#version 150 compatibility

See if that makes a difference (using GLSL 150 = GL 3.2) when you use the shader code I posted.

raziza
02-07-2012, 05:13 AM
It was the version indeed, few adjustments and it works like you said, without using round method.

About the arrays, let me get you guys straight. You're suggestion is not to use more then one texture in one draw Array ?

Is there any other way to do what i wishes ? without sampler array.

BionicBytes
02-07-2012, 05:38 AM
You're suggestion is not to use more then one texture in one draw Array
Definately not. Batch as much as you can, where you can.


Is there any other way to do what i wishes ? without sampler array
Perhaps try Sampler3D or sampler2DArray in your shader. If all the textures have the same dimension and bit depth, then either of these is good.
Note sampler2DArray is not the same thing as you had originally posted which was "uniform sampler2D u_textures[10];"
That is a uniform array of sampler2D - not the same thing.

Kopelrativ
02-07-2012, 05:48 AM
There is the technique of using a texture atlas. That is, you create one big texture with all your textures in it.

This can also be implemented using a GL_TEXTURE_2D_ARRAY (http://www.opengl.org/wiki/Array_Texture).

BionicBytes
02-07-2012, 05:55 AM
Just to be clear.
Sampler2DArray is from the extension GL_TEXTURE_2D_ARRAY.
To use the new sampler type you need to enable it in the shader:
#extension GL_EXT_texture_array : enable

You could use an atlas as suggested. For this you would need to provide different u,v texture coordinates per vertex to sample from the atlas texture. You don't need Sampler2DArray for this as just a single texture is required.

Kopelrativ
02-07-2012, 06:55 AM
Bionic: I started to type my answer before your had arrived, that is why I repeat what you said.

raziza
02-07-2012, 07:22 AM
I think I do use texture atlas. I think. I am generating in run time big image with all the letters from the font and sending the u,v as vertex attributes, but i don't know which font will draw with which in run time, so each font is generated to his own texture and not one huge texture.

About the Sampler2DArray\Sampler3D I will read about them and try it out.

As you saw in the pictures I'm using the textures for billboard quads. so Sampler3D is still helping here ?

Thanks for helping guys