#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;
}
我想用上面的代码绘制一个 3D 立方体,但我得到一个白色的窗口。如何在窗口上显示 3D 立方体? 如果我对 VBO 和 IBO 使用像“VBOs”这样的数组,如上面的代码所示,会出现问题吗?
另外,你能告诉我如何绘制多个立方体吗? 最后,如果您告诉我我的代码中还有其他问题,我将非常感谢您。
我是一个完全的初学者,说实话,我并不完全理解图形管道。但我真的很感谢你对我的作业的帮助。
type
的参数glDrawElements
为整数1。
您已将索引定义为实数数组:
GLfloat cubeIndices[] = {
// front
0, 1, 2,
因此,当
glDrawElements
工作并读取 cubeIndices
的内存时,它会遇到一些巨大的值(例如,整数值 1 作为浮点数为 0x3f80'0000)。您定义的索引完全不在顶点属性数组确定的范围内。