Dair
Dair

Reputation: 16240

Problems displaying cube in OpenGL

I am currently trying to follow this tutorial. There are some problems though, for starters because I am on a Mac the GLSL language maxes out at 1.5 (I decided to use 1.1) and the tutorial expects 3.3, also the tutorial uses a different windowing system (I am using GLUT they are using GLFW see here for the complete source code of all the site's tutorials). I have currently rearranged the code as such to get it running no my computer:

//OpenGL and GLEW
#include <GL/glew.h>
//Include GLUT
#ifdef __APPLE__
# include <GLUT/glut.h>
#else
# include <GL/glut.h>
#endif
//Some standard libraries
#include <vector>
#include <string>
#include <stdio.h>
#include <fstream>
#include <math.h>
//For transofmations.
#include "glm.hpp"
#include "transform.hpp"
//max macro for my Mac.
#define max( a, b ) ( ((a) > (b)) ? (a) : (b) )

//Vertex data for cube. Direct copy and paste for the coordinates from the website.
static const GLfloat g_vertex_buffer_data[] = { 
        -1.0f,-1.0f,-1.0f,
        -1.0f,-1.0f, 1.0f,
        -1.0f, 1.0f, 1.0f,
        1.0f, 1.0f,-1.0f,
        -1.0f,-1.0f,-1.0f,
        -1.0f, 1.0f,-1.0f,
        1.0f,-1.0f, 1.0f,
        -1.0f,-1.0f,-1.0f,
        1.0f,-1.0f,-1.0f,
        1.0f, 1.0f,-1.0f,
        1.0f,-1.0f,-1.0f,
        -1.0f,-1.0f,-1.0f,
        -1.0f,-1.0f,-1.0f,
        -1.0f, 1.0f, 1.0f,
        -1.0f, 1.0f,-1.0f,
        1.0f,-1.0f, 1.0f,
        -1.0f,-1.0f, 1.0f,
        -1.0f,-1.0f,-1.0f,
        -1.0f, 1.0f, 1.0f,
        -1.0f,-1.0f, 1.0f,
        1.0f,-1.0f, 1.0f,
        1.0f, 1.0f, 1.0f,
        1.0f,-1.0f,-1.0f,
        1.0f, 1.0f,-1.0f,
        1.0f,-1.0f,-1.0f,
        1.0f, 1.0f, 1.0f,
        1.0f,-1.0f, 1.0f,
        1.0f, 1.0f, 1.0f,
        1.0f, 1.0f,-1.0f,
        -1.0f, 1.0f,-1.0f,
        1.0f, 1.0f, 1.0f,
        -1.0f, 1.0f,-1.0f,
        -1.0f, 1.0f, 1.0f,
        1.0f, 1.0f, 1.0f,
        -1.0f, 1.0f, 1.0f,
        1.0f,-1.0f, 1.0f
};

//Color data for cube. Direct copy and paste from the site.
static const GLfloat g_color_buffer_data[] = {
    0.583f,  0.771f,  0.014f,
    0.609f,  0.115f,  0.436f,
    0.327f,  0.483f,  0.844f,
    0.822f,  0.569f,  0.201f,
    0.435f,  0.602f,  0.223f,
    0.310f,  0.747f,  0.185f,
    0.597f,  0.770f,  0.761f,
    0.559f,  0.436f,  0.730f,
    0.359f,  0.583f,  0.152f,
    0.483f,  0.596f,  0.789f,
    0.559f,  0.861f,  0.639f,
    0.195f,  0.548f,  0.859f,
    0.014f,  0.184f,  0.576f,
    0.771f,  0.328f,  0.970f,
    0.406f,  0.615f,  0.116f,
    0.676f,  0.977f,  0.133f,
    0.971f,  0.572f,  0.833f,
    0.140f,  0.616f,  0.489f,
    0.997f,  0.513f,  0.064f,
    0.945f,  0.719f,  0.592f,
    0.543f,  0.021f,  0.978f,
    0.279f,  0.317f,  0.505f,
    0.167f,  0.620f,  0.077f,
    0.347f,  0.857f,  0.137f,
    0.055f,  0.953f,  0.042f,
    0.714f,  0.505f,  0.345f,
    0.783f,  0.290f,  0.734f,
    0.722f,  0.645f,  0.174f,
    0.302f,  0.455f,  0.848f,
    0.225f,  0.587f,  0.040f,
    0.517f,  0.713f,  0.338f,
    0.053f,  0.959f,  0.120f,
    0.393f,  0.621f,  0.362f,
    0.673f,  0.211f,  0.457f,
    0.820f,  0.883f,  0.371f,
    0.982f,  0.099f,  0.879f
};

//Used to check if shaders are working. (http://content.gpwiki.org/index.php/OpenGL:Codes:Simple_GLSL_example is where I got this from)
void printLog(GLuint obj)
{
    int infologLength = 0;
    int maxLength;

    if(glIsShader(obj))
        glGetShaderiv(obj,GL_INFO_LOG_LENGTH,&maxLength);
    else
        glGetProgramiv(obj,GL_INFO_LOG_LENGTH,&maxLength);

    char infoLog[maxLength];

    if (glIsShader(obj))
        glGetShaderInfoLog(obj, maxLength, &infologLength, infoLog);
    else
        glGetProgramInfoLog(obj, maxLength, &infologLength, infoLog);

    if (infologLength > 0)
        printf("%s\n",infoLog);
}

//Loads the vertex and fragment shader.
GLuint LoadShaders(const char * vertex_file_path,const char * fragment_file_path){

    // Create the shaders
    GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
    GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);

    // Read the Vertex Shader code from the file
    std::string VertexShaderCode;
    std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
    if(VertexShaderStream.is_open())
    {
        std::string Line = "";
        while(getline(VertexShaderStream, Line))
            VertexShaderCode += "\n" + Line;
        VertexShaderStream.close();
    }

    // Read the Fragment Shader code from the file
    std::string FragmentShaderCode;
    std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
    if(FragmentShaderStream.is_open()){
        std::string Line = "";
        while(getline(FragmentShaderStream, Line))
            FragmentShaderCode += "\n" + Line;
        FragmentShaderStream.close();
    }

    GLint Result = GL_FALSE;
    int InfoLogLength;

    // Compile Vertex Shader
    printf("Compiling shader : %s\n", vertex_file_path);
    char const * VertexSourcePointer = VertexShaderCode.c_str();
    glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
    glCompileShader(VertexShaderID);
    printLog(VertexShaderID);

    // Compile Fragment Shader
    printf("Compiling shader : %s\n", fragment_file_path);
    char const * FragmentSourcePointer = FragmentShaderCode.c_str();
    glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
    glCompileShader(FragmentShaderID);
    printLog(FragmentShaderID);

    // Link the program
    fprintf(stdout, "Linking program\n");
    GLuint ProgramID = glCreateProgram();
    glAttachShader(ProgramID, VertexShaderID);
    glAttachShader(ProgramID, FragmentShaderID);
    glLinkProgram(ProgramID);

    // Check the program
    glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
    glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    std::vector<char> ProgramErrorMessage( max(InfoLogLength, int(1)) );
    glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
    fprintf(stdout, "%s\n", &ProgramErrorMessage[0]);

    //Clean up.
    glDeleteShader(VertexShaderID);
    glDeleteShader(FragmentShaderID);

    return ProgramID;
}

void display() {
    //Enable depth.
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);
    //Clear screen.
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    //Create the vertexbuffer.
    GLuint vertexbuffer;
    glGenBuffers(1, &vertexbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data,  GL_STATIC_DRAW);

    //Create the color buffer.
    GLuint colorbuffer;
    glGenBuffers(1, &colorbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW);

    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glVertexAttribPointer(
                          0,
                          3,
                          GL_FLOAT,
                          GL_FALSE,
                          0,
                          (void*)0
                          );

    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
    glVertexAttribPointer(
                          1,
                          3,
                          GL_FLOAT,
                          GL_FALSE,
                          0,
                          (void*)0
                          );

    //Draw the cube. 12 triangles, 3 vertices per triangle thus 12*3.
    glDrawArrays(GL_TRIANGLES, 0, 12*3);

    //Clean Up.
    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);

    //Display on screen
    glutSwapBuffers();
}

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

    //Init stuff.
    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
    glutInitWindowSize(400, 300);
    glutCreateWindow("Triangle");

    GLenum err = glewInit();
    if (GLEW_OK != err)
    {
        /* Problem: glewInit failed, something is seriously wrong. */
        fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
    }
    fprintf(stdout, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));

    //Create the shaders.
    GLuint programID = LoadShaders("/Users/person/Programming/C++/OpenGL Cube/OpenGL Cube/v.vsh", "/Users/person/Programming/C++/OpenGL Cube/OpenGL Cube/f.fsh");

    glUseProgram(programID);

    //Set the camera and stuff.
    glm::mat4 Projection = glm::perspective(45.0f, 4.0f/3.0f, 0.1f, 100.0f);

    glm::mat4 View = glm::lookAt(
                                 glm::vec3(4.0f,3.0f,3.0f),
                                 glm::vec3(0.0f,0.0f,0.0f),
                                 glm::vec3(0.0f,1.0f,0.0f)
                                 );

    glm::mat4 Model = glm::mat4(1.0f);

    glm::mat4 MVP = Projection * View * Model;

    GLuint MatrixID = glGetUniformLocation(programID, "MVP");
    glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);

    //Get stuff to display.
    glutDisplayFunc(display);


    glutMainLoop();
    return 0;
}

Vertex Shader code:

#version 110

uniform mat4 MVP;
attribute vec2 position;
attribute vec3 vertexColor;

varying vec4 fragmentColor;

void main() {
    gl_Position = MVP * vec4(position, 0.0, 1.0);
    fragmentColor = vec4(vertexColor, 1.0);
}

Fragment Shader code:

#version 110

varying vec4 fragmentColor;

void main() {
    gl_FragColor = fragmentColor;
}

Currently my cube looks like this:

Awesome Cube

The shaders compile fine, with no error messages.

I'm sorry if this seems like too much code or something, but I really don't know what to trim down, if there is something you want me to point out specifically please ask.

Update

Thank you Tim for your advice but I am still having some problems (although it looks better). I have changed the following lines of code in my display function so I don't assume which attribute is which:

GLuint loc1;
loc1 = glGetAttribLocation(program, "position");
glEnableVertexAttribArray(loc1);
printf("%d\n", loc1);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
                      loc1,
                      3,
                      GL_FLOAT,
                      GL_FALSE,
                      0,
                      (void*)0
                      );

GLuint loc2 = glGetAttribLocation(program, "vertexColor");
glEnableVertexAttribArray(loc2);
printf("%d\n", loc2);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glVertexAttribPointer(
                      loc2,
                      3,
                      GL_FLOAT,
                      GL_FALSE,
                      0,
                      (void*)0
                      );

As well as creating a global variable program that will assume the value of programID so I can use it in my display function. It now looks like this:

enter image description here

Anyone have any further suggestions?

Upvotes: 1

Views: 1181

Answers (1)

Tim
Tim

Reputation: 35943

For one thing it's bad to assume the locations of your attributes. You're arbitrarily assuming that 'vertex' is attribute 0, and 'color' is attribute 1. That's a dangerous assumption. You want to either call glGetAttribLocation to get their real locations, or call glBindAttribLocation before linking to assign variables to a location.

Your jumbled result looks almost like you're supplying vertices as colors and vice versa.

Also, you're reading a 2d vertex in the shader, while supplying 3d vertex information. You might want to make this consistent.

Upvotes: 5

Related Questions