Joan P.S
Joan P.S

Reputation: 1573

Wrong texture rendering in OpenGL 3.0 ES

I'm trying to render a simple square with a texture using C++ in Android but I'm having some troubles while using the texture.

Here is the code that prepare OpenGL ES

// set up vertex data (and buffer(s)) and configure vertex attributes
// ------------------------------------------------------------------
float vertices[] = {
        // positions          // colors           // texture coords
        0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f, // top right
        0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f, // bottom right
        -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f, // bottom left
        -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f  // top left
};
unsigned int indices[] = {
        0, 1, 3, // first triangle
        1, 2, 3  // second triangle
};

glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);

glBindVertexArray(VAO);

glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

// position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// texture coord attribute
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);

And here the vertex shader:

attribute vec4 vertexPosition;
attribute vec2 vertexTexCoord;

varying vec2 texCoord;

void main()
{
   gl_Position = vec4(vertexPosition.x, vertexPosition.y, vertexPosition.z, 1.0);
   texCoord = vertexTexCoord;
}

And the fragment shader:

precision mediump float;
uniform sampler2D texSampler2D;
varying vec2 texCoord;
void main()
{
    gl_FragColor = texture2D(texSampler2D, texCoord);
}

But when I run this code on Android the texture is not placed properly.

Error using the texture

And the original texture looks like this:

Original texture

What am I doing wrong?

Upvotes: 1

Views: 715

Answers (2)

Rabbid76
Rabbid76

Reputation: 210878

In your shader code you do not have any color attribute. You have only vertex positions and texture coordinates:

attribute vec4 vertexPosition;
attribute vec2 vertexTexCoord;

But in the c++ code you define and enable the generic vertex attribute arrays with the indices 0, 1 and 2. Especially the association of the texture coordinates to the attribute index 2 may not work.

Use glGetAttribLocation to get the attribute index of an attribute (after glLinkProgram):

GLuint prog .....;   

GLint vert_loc = glGetAttribLocation(prog , "vertexPosition");
GLint texc_loc = glGetAttribLocation(prog , "texCoord");

And change your code somehaow like this:

glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);

glBindVertexArray(VAO);

glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

// position attribute
glVertexAttribPointer(vert_loc, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(vert_loc);

// texture coord attribute
glVertexAttribPointer(texc_loc, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(texc_loc);


If you use a vertex shader which has a vertex coordinate, a color attributes and a texture coordinates, you code may work:

attribute vec3 aPos;
attribute vec3 aColor;
attribute vec2 aTexCoord;

varying vec3 ourColor;
varying vec2 texCoord;

void main()
{
   gl_Position = vec4(aPos.xyz, 1.0);
   ourColor = aColor;
   texCoord = aTexCoord;
}

But, there is no guarantee, that the attribute indices for aPos, aColor and aTexCoord are consecutifly 0, 1, 2. This depends on the hardware and OpenGL dirver. Because of that you should use glGetAttribLocation to get the attribute indices.
Further you have to use all the attributes in the shader code. An attribute which is not used becomes not active. This means it is not added to the resources and gets no attribute index.


See OpenGL ES 2 Specifications - 2.10.4 Shader Variables - p. 32:

A generic attribute variable is considered active if it is determined by the compiler and linker that the attribute may be accessed when the shader is executed. Attribute variables that are declared in a vertex shader but never used are not considered active. In cases where the compiler and linker cannot make a conclusive determination, an attribute will be considered active.

.....

To determine the set of active vertex attributes used by a program, and to determine their types, use the command:

void GetActiveAttrib( uint program, uint index, sizei bufSize, sizei *length, int *size, enum *type, char *name );

.....

After a program object has been linked successfully, the bindings of attribute variable names to indices can be queried. The command

int GetAttribLocation( uint program, const char *name );

Upvotes: 2

Joan P.S
Joan P.S

Reputation: 1573

The shaders where the problem. I've changed the shaders as follows:

attribute vec3 aPos;
attribute vec3 aColor;
attribute vec2 aTexCoord;

varying vec3 ourColor;
varying vec2 texCoord;

void main()
{
   gl_Position = vec4(aPos.xyz, 1.0);
   ourColor = aColor;
   texCoord = aTexCoord;
}

and the fragment:

precision mediump float;

varying vec3 ourColor;
varying vec2 texCoord;

uniform sampler2D texSampler2D;

void main()
{
    gl_FragColor = texture2D(texSampler2D, texCoord);
}

but there are 2 things I don't understand:

  1. If I remove the line ourColor = aColor; from the vector shader I have the same problem, why?
  2. The texture now is upside down, why? screenshot

Upvotes: 0

Related Questions