kkk
kkk

Reputation: 23

draw cubes with index buffer in openGL

I want to draw a 3D cube:

#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

#include <GL/glew.h>
#include <GL/glut.h>

#include <GL/glm/glm.hpp>
#include <GL/glm/gtx/transform.hpp> // rotate(), scale(), translate()
#include <GL/glm/gtc/quaternion.hpp>
#include <GL/glm/gtc/type_ptr.hpp>

using namespace std;

GLuint VertexArrayID;
GLuint programID;
float sx = 0;
float sy = 0;
bool projMode = true; // true: perspective, false: ortho

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);

    GLint Result = GL_FALSE;
    int InfoLogLength;

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

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

    //Check Vertex Shader
    glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    if (InfoLogLength > 0) {
        vector<char> VertexShaderErrorMessage(InfoLogLength);
        glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
        fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]);
    }

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

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

    //Check Fragment Shader
    glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    if (InfoLogLength > 0) {
        vector<char> FragmentShaderErrorMessage(InfoLogLength);
        glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
        fprintf(stdout, "%s\n", &FragmentShaderErrorMessage[0]);
    }

    //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);
    vector<char> ProgramErrorMessage(max(InfoLogLength, int(1)));
    glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
    fprintf(stdout, "%s\n", &ProgramErrorMessage[0]);

    glDeleteShader(VertexShaderID);
    glDeleteShader(FragmentShaderID);

    return ProgramID;
}

void renderScene(void)
{
    //Clear all pixels
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //Let's draw something here

    glBindVertexArray(VertexArrayID);
    //define the size of point and draw a point.
    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
    
    //Double buffer
    glutSwapBuffers();
}

void mouse(int button, int state, int x, int y) {
    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
        projMode = !projMode;
    }
}

void init()
{
    //initilize the glew and check the errors.
    GLenum res = glewInit();
    if (res != GLEW_OK)
    {
        fprintf(stderr, "Error: '%s' \n", glewGetErrorString(res));
    }

    //select the background color
    glClearColor(1.0, 1.0, 1.0, 1.0);
    glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
    glEnable(GL_DEPTH_TEST);

    glDepthFunc(GL_LESS);
    glDepthRange(0.0f, 1.0f);
}

GLfloat cubeVertices[] = {
    // front
   -0.1f, 0.1f, 0.1f,
   -0.1f,-0.1f, 0.1f,
   0.1f,-0.1f, 0.1f,
   0.1f, 0.1f, 0.1f,
   -0.1f, 0.1f, 0.1f,
   0.1f,-0.1f, 0.1f,

    // back
    0.1f, 0.1f,-0.1f,
    -0.1f,-0.1f,-0.1f,
    -0.1f, 0.1f,-0.1f,
    0.1f, 0.1f,-0.1f,
    0.1f,-0.1f,-0.1f,
    -0.1f,-0.1f,-0.1f,

    // left
    -0.1f,-0.1f,-0.1f,
    -0.1f,-0.1f, 0.1f,
    -0.1f, 0.1f, 0.1f,
    -0.1f,-0.1f,-0.1f,
    -0.1f, 0.1f, 0.1f,
    -0.1f, 0.1f,-0.1f,

   

    // right
    0.1f, 0.1f, 0.1f,
    0.1f,-0.1f,-0.1f,
    0.1f, 0.1f,-0.1f,
    0.1f,-0.1f,-0.1f,
    0.1f, 0.1f, 0.1f,
    0.1f,-0.1f, 0.1f,

    // bottom
    0.1f,-0.1f, 0.1f,
    -0.1f,-0.1f,-0.1f,
    0.1f,-0.1f,-0.1f,
    0.1f,-0.1f, 0.1f,
    -0.1f,-0.1f, 0.1f,
    -0.1f,-0.1f,-0.1f,

    // top
    1.1f, 0.1f, 0.1f,
    0.1f, 0.1f,-0.1f,
    -0.1f, 0.1f,-0.1f,
    0.1f, 0.1f, 0.1f,
    -0.1f, 0.1f,-0.1f,
    -0.1f, 0.1f, 0.1f,
};

GLfloat cubeColors[] = {
    // red
    1.0, 0.0, 0.0, 1.0,
    1.0, 0.0, 0.0, 1.0,
    1.0, 0.0, 0.0, 1.0,
    1.0, 0.0, 0.0, 1.0,
    1.0, 0.0, 0.0, 1.0,
    1.0, 0.0, 0.0, 1.0,

    // green
    0.0, 1.0, 0.0, 1.0,
    0.0, 1.0, 0.0, 1.0,
    0.0, 1.0, 0.0, 1.0,
    0.0, 1.0, 0.0, 1.0,
    0.0, 1.0, 0.0, 1.0,
    0.0, 1.0, 0.0, 1.0,

    // blue
    0.0, 0.0, 1.0, 1.0,
    0.0, 0.0, 1.0, 1.0,
    0.0, 0.0, 1.0, 1.0,
    0.0, 0.0, 1.0, 1.0,
    0.0, 0.0, 1.0, 1.0,
    0.0, 0.0, 1.0, 1.0,

    // yellow
    1.0, 1.0, 0.0, 1.0,
    1.0, 1.0, 0.0, 1.0,
    1.0, 1.0, 0.0, 1.0,
    1.0, 1.0, 0.0, 1.0,
    1.0, 1.0, 0.0, 1.0,
    1.0, 1.0, 0.0, 1.0,

    // cyan
    1.0, 0.0, 1.0, 1.0,
    1.0, 0.0, 1.0, 1.0,
    1.0, 0.0, 1.0, 1.0,
    1.0, 0.0, 1.0, 1.0,
    1.0, 0.0, 1.0, 1.0,
    1.0, 0.0, 1.0, 1.0,

    // magenta
    0.0, 1.0, 1.0, 1.0,
    0.0, 1.0, 1.0, 1.0,
    0.0, 1.0, 1.0, 1.0,
    0.0, 1.0, 1.0, 1.0,
    0.0, 1.0, 1.0, 1.0,
    0.0, 1.0, 1.0, 1.0,
};
/* idx | coord:
0 | (1,1,1)
1 | (-1, 1, 1)
2 | (-1,-1,1)
3 | (1, -1, 1)
4 | (1, -1, -1)
5 | (1, 1, -1)
6 | (-1, 1, -1)
7 | (-1, -1, -1) */
GLfloat cubeIndices[] = {
    // front
    0, 1, 2,
    0, 1, 3,

    // back
    5, 6, 7,
    5, 6, 4,
    
    // left
    1, 2, 6,
    1, 2, 7,

    // right
    0, 3, 4,
    0, 4, 5,

    // top
    0, 1, 5,
    0, 1, 6,

    // bottom
    2, 3, 4,
    2, 4, 7,
};

int main(int argc, char** argv)
{
    //init GLUT and create Window
    //initialize the GLUT
    glutInit(&argc, argv);
    //GLUT_DOUBLE enables double buffering (drawing to a background buffer while the other buffer is displayed)
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);

    //These two functions are used to define the position and size of the window. 
    glutInitWindowPosition(200, 200);
    glutInitWindowSize(480, 480);
    //This is used to define the name of the window.
    glutCreateWindow("Simple OpenGL Window");

    //call initization function
    init();
    //0.
    programID = LoadShaders("VertexShader.txt", "FragmentShader.txt");
    glUseProgram(programID);

    /**************************************************/
    // model matrix
    glm::mat4 model = glm::mat4(1.0f); 
    float rotateAngle = 45.0f; 
    glm::vec3 rotateAxis(0.0f, 1.0f, 0.0f); 
    model = glm::rotate(model, glm::radians(rotateAngle), rotateAxis);

    glm::vec3 scaleVec(5.0f, 5.0f, 5.0f); 
    model = glm::scale(model, scaleVec);

    glm::vec3 translateVec(0.0f, 0.0f, 0.0f);
    model = glm::translate(model, translateVec);

    // view matrix
    glm::mat4 view = glm::lookAt(glm::vec3(5.0f, -5.0f, -5.0f),
        glm::vec3(0.0f, 0.0f, 0.0f), 
        glm::vec3(0.0f, 1.0f, 0.0f)); 

    // proj matrix
    glm::mat4 proj;
    int width = glutGet(GLUT_WINDOW_WIDTH);
    int height = glutGet(GLUT_WINDOW_HEIGHT);
    if (projMode) {
        float aspectRatio = float(width) / height; 
        proj = glm::perspective(glm::radians(45.0f), aspectRatio, 0.1f, 100.0f); 
    }
    else {
        float orthoSize = 5.0f;
        proj = glm::ortho(-orthoSize, orthoSize, -orthoSize, orthoSize, 0.1f, 0.6f);
    }

    // model, view, proj matrix to shader
    GLint modelLoc = glGetUniformLocation(programID, "model");
    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));

    GLint viewLoc = glGetUniformLocation(programID, "view");
    glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));

    GLint projLoc = glGetUniformLocation(programID, "proj");
    glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(proj));

    /**************************************************/
    glGenVertexArrays(1, &VertexArrayID);
    glBindVertexArray(VertexArrayID);

    float vtxs[] = { -0.5, 0.0, 0.0, 0.5, 0.3, 0.0 };
    GLuint VBOs[3];
    glGenBuffers(3, VBOs);

    glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * 3 * 2 * 6, cubeVertices, GL_STATIC_DRAW);
    GLuint posAttribLoc = glGetAttribLocation(programID, "inPos");
    glVertexAttribPointer(posAttribLoc, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(0));
    glEnableVertexAttribArray(posAttribLoc);     
    
    glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 4 * 3 * 2 * 6, cubeColors, GL_STATIC_DRAW); 
    GLuint colAttribLoc = glGetAttribLocation(programID, "color");
    glVertexAttribPointer(colAttribLoc, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(0));
    glEnableVertexAttribArray(colAttribLoc);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VBOs[2]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(float) * 6 * 6, cubeIndices, GL_STATIC_DRAW);
    GLuint idxAttribLoc = glGetAttribLocation(programID, "index");
    glVertexAttribPointer(idxAttribLoc, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(0));
    glEnableVertexAttribArray(idxAttribLoc);

    glutDisplayFunc(renderScene);
    glutMouseFunc(mouse);

    //enter GLUT event processing cycle
    glutMainLoop();

    glDeleteVertexArrays(1, &VertexArrayID);

    return 1;
}

...but I'm getting a white window.

How can I display a 3D cube on the window?

Is there a problem if I use an array like 'VBOs' for both VBOs and IBO, as shown in the above code?

Also, could you tell me how to draw multiple cubes?

Finally, tell me if there are other problems in my code.

Upvotes: -1

Views: 42

Answers (1)

rafix07
rafix07

Reputation: 20949

Parameter type of glDrawElements is integer one.

You have defined the array with indices as real numbers:

GLfloat cubeIndices[] = {
    // front
    0, 1, 2,

so when glDrawElements works and reads the memory of cubeIndices it hits some huge values (for example integer value of 1 as float is 0x3f80'0000). Indices you defined completely don't lie in the range determined by vertex attribute arrays.

Because you pass GL_UNSIGNED_INT to glDrawElements type of array should be GLuint:

GLuint cubeIndices[] = {
    // front
    0, 1, 2,

Upvotes: 0

Related Questions