Rendering multiple 2D textures

Hello everybody,

I am trying to write a little toy engine for myself. But I am experiencing difficulty rendering more than one texture. I have gone over the tutorials from open.gl and I can get everything to work with one texture. But as soon as I try to make it two or more everything breaks down. I’ll paste the code below of my third iteration that still doesn’t work. I am using a core profile for OpenGL 3.2. And I am using SDL for window management.

I have been reading a lot and as I understand it you should be able to use VAOs to make two different things render to the screen. So that has been my approach so far, basically I generate a VAO for the first texture, get some vertices set up and load the texture. Then I do the same with a second texture. When rendering I use GLSL shaders. Which is where the first problem seems to be at the moment. My game/engine receives a SIGSEGV when enabling a vertex attribute.


void Main::initShaders() {
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexSource, NULL);
    glCompileShader(vertexShader);
    checkShaderCompilerStatus(vertexShader);

    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
    glCompileShader(fragmentShader);
    checkShaderCompilerStatus(fragmentShader);

    GLuint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glBindFragDataLocation(shaderProgram, 0, "outColor");
    glLinkProgram(shaderProgram);
    glUseProgram(shaderProgram);

    // This works fine
    GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
    glEnableVertexAttribArray(posAttrib);
    glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 7 * sizeof(GLfloat), 0);
    checkGLError2(__LINE__, __FILE__);

    // This results in error 1282(should be GL_INVALID_VALUE) that is caught in the checkGLError2 function below
    GLint colAttrib = glGetAttribLocation(shaderProgram, "color");
    glEnableVertexAttribArray(colAttrib);
    glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(GLfloat), (void*)(2 * sizeof(GLfloat)));
    checkGLError2(__LINE__, __FILE__);

    // This does the same.
    GLint texAttrib = glGetAttribLocation(shaderProgram, "texcoord");
    glEnableVertexAttribArray(texAttrib);
    glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 7 * sizeof(GLfloat), (void*)(5 * sizeof(GLfloat)));
    checkGLError2(__LINE__, __FILE__);
}

And the shaders I use:
vertex:


    #version 150 core
    in vec2 position;
    in vec3 color;
    in vec2 texcoord;

    out vec3 Color;
    out vec2 Texcoord;

    void main() {
       Color = color;
       Texcoord = texcoord;

       gl_Position = vec4(position, 0.0, 1.0);
    }

fragment:


    #version 150 core
    in vec3 Color;
    in vec2 Texcoord;

    out vec4 outColor;

    uniform sampler2D tex;

    void main() {
       outColor = texture(tex, Texcoord) * vec4(Color, 0.0);
    }

As far as I know that shouldn’t result in an error. Because the color and texcoord attributes are both there.

I won’t paste the whole source here because that’s too much for one forum post. But here it is.

Here is some info about my system:
Kernel: Linux aristotle 3.18.3-1-ck #1 SMP PREEMPT Fri Jan 16 15:02:43 EST 2015 x86_64 GNU/Linux
GL version: 3.3.0 NVIDIA 340.65
GL vendor: NVIDIA Corporation
GL renderer: GeForce 8400M GS/PCIe/SSE2

Any advice about how to render multiple textures would be a nice addition :slight_smile:

Thanks in advance,
Peter

You’re missing the binding of the buffer that contains the data in initShaders():


glBindBuffer(GL_ARRAY_BUFFER, vertex_data_buffer_id);

before the calls to the glVertexAttribPointer(). Pull all the glVertexAttribPointer() calls out of the initShaders() function and move them to initVertices1/2(), because the attribute location storage is not stored with the shader program, but instead in a VAO.

After fixing that, note that textures are not bound to VAOs, only buffers are. You’ll need to bind each texture before the draw calls:

glBindVertexArray(vao1);
glBindTexture(GL_TEXTURE_2D, tex1);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
  // glBindVertexArray(0);  - no need to unbind vao1 when you immediately bind vao2

glBindVertexArray(vao2); 
glBindTexture(GL_TEXTURE_2D, tex2);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); glBindVertexArray(0); 

…which means you’ll need to hold onto those texture ids that glGenTextures() produces. Right now, you’re creating a texture and then losing the handle to it, effectively leaking it.

I’m not sure I understand the first part.

Do I need to bind the vbo from each initVertices function when initializing the shaders?

It has nothing to do with shaders. It’s how Vertex Specification works. To say that attribute X gets its vertex array data from a particular buffer, you must bind the buffer to GL_ARRAY_BUFFER, then call glVertexAttribPointer.

Thanks guys, it’s working now. :slight_smile: