#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 : %sn", 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, "%sn", &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 : %sn", 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, "%sn", &FragmentShaderErrorMessage[0]);
}
//Link the program
fprintf(stdout, "Linking programn");
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, "%sn", &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;
}
I want to draw a 3D cube with the above code, 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, i’ll so thanks to you if you tell me there are else problems in my code.
I’m a total beginner, and to be honest, I don’t fully understand the graphics pipeline. But I’d really appreciate your help with my assignment.
kkk is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.