0
votes

I am having some strange behavior when trying to draw a texture in OpenGL. Currently all this program does for me is draw the background color with no indication of a texture being drawn. I have just moved from Visual Studio (where this code produces the correct output) to compiling in the command prompt. This code should color the background and draw one texture in the center of the screen.

I am concerned that I may have supplied the incorrect libraries for compilation since as far as I am concerned everything I am doing is the same. Different libraries, however, always said that they were incompatible.

Main code:

#define GLEW_STATIC
#include <GL/glew.h> // window management library
#include <GL/glfw3.h>
#include <GL/glm.hpp>
#include <GL/gtc/matrix_transform.hpp> //

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

int main(int argc, char** argv){

    //Initialize GLFW and GLEW...
    //Setup and combine shaders...

    GLint vertex_att = glGetAttribLocation(program, "vertex");
    glVertexAttribPointer(vertex_att, 2, GL_FLOAT, GL_FALSE, 7*sizeof(GLfloat), 0);
    glEnableVertexAttribArray(vertex_att);

    GLint color_att = glGetAttribLocation(program, "color");
    glVertexAttribPointer(color_att, 3, GL_FLOAT, GL_FALSE, 7*sizeof(GLfloat), (void *) (2 *sizeof(GLfloat)));
    glEnableVertexAttribArray(color_att);

    GLint tex_att = glGetAttribLocation(program, "uv");
    glVertexAttribPointer(tex_att, 2, GL_FLOAT, GL_FALSE, 7*sizeof(GLfloat), (void *) (5 *sizeof(GLfloat)));
    glEnableVertexAttribArray(tex_att);

    glUseProgram(program);

    GLuint texture;
    glGenTextures(1, &texture);
    setthisTexture(texture, "./black.png");

    // Create geometry of the square
    int size = CreateSquare();

    while (!glfwWindowShouldClose(window)){
        // Clear background
        glClearColor(viewport_background_color_g[0], 
                     viewport_background_color_g[1],
                     viewport_background_color_g[2], 0.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        //set displacement - 'program' being the shader program
        int matrixLocation = glGetUniformLocation(program, "x");

        glm::mat4 translate = glm::mat4();
        translate = glm::translate(translate, glm::vec3(0.0f, 0.0f, 0.0f));

        glUniformMatrix4fv(matrixLocation, 1, GL_FALSE, &translate[0][0]);
        glBindTexture(GL_TEXTURE_2D, texture);
        glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);

        glfwPollEvents();

        glfwSwapBuffers(window);
    }
}

Vertex Shader:

#version 130

in vec2 vertex;
in vec3 color;
in vec2 uv;
out vec2 uv_interp;

// Uniform (global) buffer
uniform mat4 x;

// Attributes forwarded to the fragment shader
out vec4 color_interp;

void main(){
    vec4 t;
    t = vec4(vertex, 0.0, 1.0);
    gl_Position = x*t;

    color_interp = vec4(color, 1.0);
    uv_interp = uv;
}

Fragment Shader:

#version 130

in vec4 color_interp;
in vec2 uv_interp;

uniform sampler2D onetex;

void main(){
    vec4 color = texture2D(onetex, uv_interp);
    gl_FragColor = vec4(color.r,color.g,color.b,color.a);
    if(gl_FragColor.a < 0.9){
        discard;
    }
}

setthisTexture:

void setthisTexture(GLuint w, const char *fname)
{
    glBindTexture(GL_TEXTURE_2D, w);

    int width, height, nrChannels;
    unsigned char* image = stbi_load(fname, &width, &height, &nrChannels, 0);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
    stbi_image_free(image);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}

CreateSquare:

int CreateSquare(void) {

    // The face of the square is defined by four vertices and two triangles

    // Number of attributes for vertices and faces
    //  const int vertex_att = 7;  // 7 attributes per vertex: 2D (or 3D) position (2), RGB color (3), 2D texture coordinates (2)
    //  const int face_att = 3; // Vertex indices (3)

    GLfloat vertex[]  = {
        //  square (two triangles)
        //  Position     Color                  Texcoords
        -0.5f, 0.5f,     1.0f, 0.0f, 0.0f,      0.0f, 0.0f, // Top-left
        0.5f, 0.5f,      0.0f, 1.0f, 0.0f,      1.0f, 0.0f, // Top-right
        0.5f, -0.5f,     0.0f, 0.0f, 1.0f,      1.0f, 1.0f, // Bottom-right
        -0.5f, -0.5f,    1.0f, 1.0f, 1.0f,      0.0f, 1.0f  // Bottom-left
    };

    GLuint face[] = {
        0, 1, 2, // t1
        2, 3, 0  //t2
    };

    GLuint vbo, ebo;

    // Create buffer for vertices
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertex), vertex, GL_STATIC_DRAW);

    // Create buffer for faces (index buffer)
    glGenBuffers(1, &ebo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(face), face, GL_STATIC_DRAW);

    // Return number of elements in array buffer
    return sizeof(face);
}
1
Have you checked the return value of setthisTexture(texture, "./black.png");? If all you changed was the development environment, I'd say that it's probably just a matter of what root directory you're using.Martin Véronneau

1 Answers

1
votes

For the use of glVertexAttribPointer either a named GL_ARRAY_BUFFER buffer object has to be bound or a pointer to the vertex data has to be passed.

In your case this means, that

int size = CreateSquare();

has to be done before

GLint vertex_att = glGetAttribLocation(program, "vertex");
glVertexAttribPointer(vertex_att, 2, GL_FLOAT, GL_FALSE, 7*sizeof(GLfloat), 0);
glEnableVertexAttribArray(vertex_att);

.....


Note in the function CreateSquare, the named buffer object vbo is bound:

glBindBuffer(GL_ARRAY_BUFFER, vbo);

which is used by the glVertexAttribPointer calls.


See OpenGL 4.6 API Compatibility Profile Specification; 10.3.9 Vertex Arrays in Buffer Objects; page 409:

A buffer object binding point is added to the client state associated with each vertex array type and index. The commands that specify the locations and organizations of vertex arrays copy the buffer object name that is bound to ARRAY_- BUFFER to the binding point corresponding to the vertex array type or index being specified. For example, the VertexAttribPointer command copies the value of ARRAY_BUFFER_BINDING (the queriable name of the buffer binding corresponding to the target ARRAY_BUFFER) to the client state variable VERTEX_ATTRIB_- ARRAY_BUFFER_BINDING for the specified index.