1
\$\begingroup\$

I'm trying to write a shader which renders a multitextured geometry wihout rerendering the geometry with each texture.

In my test I'm not using textures, I just convert the texture index to a color (0: red, 1: blue, 2: green). I'm rendering 3 planes with 3 different "texture index" attributes. The vertex shader just passes that float to the fragment shader where I convert it to an integer (and use this interger as an array indexer in the main shader).

So a vertex consists 4 floats (0-2: position, 3: texture index). Everything is fine until I'm trying to use that "texture index".

Here's the VertexShader:

#version 130
uniform mat4 proj;
uniform mat4 view;
uniform mat4 world;

in vec3 in_position;
in float in_fl;

smooth out float FL;

void main(void)
{
    FL = in_fl;

    gl_Position = proj * view * world * vec4(in_position, 1);
}

FragmentShader:

#version 130

out vec4 out_frag_color;
smooth in float FL;

void main(void)
{
    int i = int(FL);

    if(i == 0)
        out_frag_color = vec4(1,0,0,1);
    else if(i == 1)
        out_frag_color = vec4(0,0,1,1);
    else if(i == 2)
        out_frag_color = vec4(0,1,0,1);
    else   
        out_frag_color = vec4(1,1,1,1);
}

And the result (the numbers are the "texture index" of the plane): Problems, problems... Tested on an Intel HD 4000 GPU and an nVidia GTS 250, same result. As you can see 0 is OK, but 2.0 is sometimes 2 (green), sometimes 1 (blue), why? If I pass that "i" to a sampler2D array, nothing shows up on the screen, because "i" is out of the array bounds.

The rendering is done using OpenGL 3.0, with a VAO, an ArrayBuffer and an ElementArrayBuffer.

This is how I setup the attrib pointers:

GL.EnableVertexAttribArray(0); //pos
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, true, sizeof(float) * 4, 0);

GL.EnableVertexAttribArray(1); //tetxure index
GL.VertexAttribPointer(1, 1, VertexAttribPointerType.Float, true, sizeof(float) * 4, sizeof(float) * 3);

I've tried using VertexAttribPointerType.Int and int attributes, Also I've tried setting the "FL" varaible in the vertex shader, with 0, the result is red which is good, but if I use 1 or 2 the result is again a mess.

So what do you think? It's a rounding problem? Or how should I render the geometry with multiple textures wihout rerendering the geometry with each texture?

\$\endgroup\$
7
  • \$\begingroup\$ I'm trying to write a shader which renders a multitextured geometry without rerendering the geometry with each texture What are you trying to achieve, did you look into multitexturing ? you only render the geometry once with multiple textures. Explaining what are you trying to achieve is better than describing your solution \$\endgroup\$
    – concept3d
    Oct 11, 2014 at 20:05
  • \$\begingroup\$ Sorry, I tried to explain what I'm trying to achieve, I just don't know how.. (English is not my native language, but I think you already know it) So I'm trying to render a model with multiple textures (each vertex has an attribute which is the texture index) but I don't want to re render the whole model with each texture. \$\endgroup\$
    – robot9706
    Oct 11, 2014 at 20:10
  • \$\begingroup\$ Well, it's ok english isn't my native language either. Anyway for multitexturing you need to pass multiple textures and then blend them, rather than giving each vertex an index attribute. \$\endgroup\$
    – concept3d
    Oct 11, 2014 at 20:18
  • \$\begingroup\$ I know what multitexturing does, but I don't want to blend the textures. Every polygon has it's own texture and I'm trying to render the model with one draw call. \$\endgroup\$
    – robot9706
    Oct 11, 2014 at 20:22
  • 2
    \$\begingroup\$ Visually, it looks like z-fighting... it looks like the "2.0" diamond is being drawn twice with same coordinates and depth, and randomly either the blue or green gets drawn first and wins. \$\endgroup\$ Oct 11, 2014 at 20:48

1 Answer 1

3
\$\begingroup\$

I managed to find out what my problem was. The "smooth" keyword.

Vertex shader:

...
in float in_fl;

flat out int FL;

void main(void)
{
    FL = int(in_fl);
...

Fragment shader:

...
    flat in int FL;
...

So now I have a red, a blue and a green square, as I wanted.

Anyway thanks for any help.

\$\endgroup\$
1
  • \$\begingroup\$ This seems surprising. opengl.org/wiki/Type_Qualifier_(GLSL) says "SMOOTH: ​ The value will be interpolated in a perspective-correct fashion. This is the default if no qualifier is present." \$\endgroup\$ Oct 13, 2014 at 4:14

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .