Reputation: 23
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
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