GenuinePlaceholder
GenuinePlaceholder

Reputation: 695

If Else statement causes strage behaviour GLSL

So my vertex shader goes something like this

String vertexshader = "#version 330 core"
        + System.getProperty("line.separator")
        + "in vec4 vertexin;"
        + "in vec2 textcoords;"
        + "in int texture;"
        + "uniform mat4 orthogonal;"
        + "out vec2 supertextcoords;"
        + "out int textureoi;"
        + "void main(){"
        + "gl_Position = orthogonal * vertexin ;"
        + "supertextcoords = textcoords;"
        + "textureoi=texture;"
        + "}";

And my fragment shader goes something like this

String fragmentshader="#version 330 core"
        + System.getProperty("line.separator")
        +"out vec4 outcolor;"
        + "in int textureoi;"
        +"in vec2 supertextcoords;"
        +"uniform sampler2D texture1;"
        +"uniform sampler2D texture2;"
        + "vec4 texturedecode();"
        + "vec4 texturedecode() {"
        + "vec4 color;"
        + "if(textureoi==0) {"
        + "color= texture2D(texture1, supertextcoords); return color; }"
        + "else if(textureoi==1) {"
        + " color= texture2D(texture2, supertextcoords); return color;"
        + "} else {"
        + " color= texture2D(texture2, supertextcoords); return color;}"
        + "}"
        +"void main(){"         
        +" outcolor =texturedecode();"      
        +"}";

The problem is that when I glUseProgram() I get error 1282. The problem only happens if I use the function texturedecode(). It does not matter if I use it on the outcolor variable or on its own declaring some unused variable. It crashes opengl.

The way I send the variables is as follows.

glActiveTexture(GL_TEXTURE0); 
glBindTexture(GL_TEXTURE_2D, TextureInit.loadTexture(io.getSubimage(0,0, 32, 32), 4));
int loc1 = glGetUniformLocation(program, "texture1");
glUniform1i(loc1, 0);
glActiveTexture(GL_TEXTURE1); 
glBindTexture(GL_TEXTURE_2D, TextureInit.loadTexture(io.getSubimage(32,0, 32, 32), 4));
int loc2 = glGetUniformLocation(program, "texture2");
glUniform1i(loc2, 0);
int orthographicloc=glGetUniformLocation(program,"orthogonal");
glUniformMatrix4(orthographicloc,false, orthographicBuffer);
glBindAttribLocation(program, 0, "vertexin");
glBindAttribLocation(program, 1, "textcoords");  
glLinkProgram(program);


glVertexAttribPointer(0, 4, GL_FLOAT,false,0,0);
glVertexAttribPointer(1,2,GL_FLOAT,false,0,vertices.length*datasize);
glVertexAttribIPointer(2,1,GL_INT,0,vertices.length*datasize+textcoord.length*4);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glDrawArrays(GL_TRIANGLES, 0, vertices.length/4);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);

Upvotes: 0

Views: 594

Answers (2)

GenuinePlaceholder
GenuinePlaceholder

Reputation: 695

There we go! The problem was that the integer was not "flat". What does this mean? I have no idea. But the way to solve this is to write

flat out int textureoi;

and

flat in int textureoi;

Upvotes: 0

Colonel Thirty Two
Colonel Thirty Two

Reputation: 26599

From the OpenGL wiki:

In fragment shaders, there is one other circumstance that can cause all of your non-"Lod" or "Grad" texture accesses to become undefined: non-uniform flow control.

Uniform flow control for a particular location in code means that, no matter how a shader is executed, the shader will follow the same path to get to that location of code. Consider the following GLSL code for a fragment shader:

void main()
{
  vec4 firstData = texture(someSampler, textureCoords);

  if(parameterValue < 20)
  {
      firstData += texture(someOtherSampler, otherTexCoords);
  }

  vec4 moreData = texture(thirdSampler, thirdTexCoords);
}

The first texture access happens in uniform flow control. Thus, the texture access produces definite results. However, the next texture access is not in uniform flow. If the accessed texture uses mipmapping or anisotropic filtering of any kind, then any texture function that is not "Lod" or "Grad" will retrieve undefined results. The last texture access happens in uniform flow control again and will produce definite results.

Note: The GLSL compiler will not give you an error for this. It is perfectly legal GLSL code. It only becomes undefined when certain texture state is set on those textures. Specifically, if mipmap or anisotropic filtering is used.

To mitigate this, you can either sample both textures and use the if/else to return the appropriate color value, or use textureGrad manually.

Upvotes: 1

Related Questions