在 OpenGL 中显示立方体的问题
Posted
技术标签:
【中文标题】在 OpenGL 中显示立方体的问题【英文标题】:Problems displaying cube in OpenGL 【发布时间】:2012-07-05 23:55:45 【问题描述】:我目前正在尝试关注this tutorial。但是有一些问题,对于初学者来说,因为我在 Mac 上,GLSL 语言的最大值为 1.5(我决定使用 1.1)并且本教程需要 3.3,本教程也使用不同的窗口系统(我正在使用他们正在使用的 GLUT GLFW 请参阅here 以获取所有站点教程的完整源代码)。我目前已经重新安排了代码,让它在我的电脑上运行:
//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;
顶点着色器代码:
#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);
片段着色器代码:
#version 110
varying vec4 fragmentColor;
void main()
gl_FragColor = fragmentColor;
目前我的立方体是这样的:
着色器编译良好,没有错误消息。
很抱歉,如果这看起来代码太多或什么的,但我真的不知道要删减什么,如果你有什么要我特别指出的,请询问。
更新
感谢蒂姆的建议,但我仍然遇到一些问题(尽管看起来更好)。我在显示函数中更改了以下代码行,因此我不假设哪个属性是哪个:
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
);
除了创建一个全局变量program
,它将假定programID
的值,这样我就可以在我的显示函数中使用它。现在看起来像这样:
大家还有什么建议吗?
【问题讨论】:
您是否注意到我的第二个建议,即 2d 与 3d 不匹配?如果是,请更新代码。 @Tim 这种 2d-3d 的不匹配肯定会导致他的立方体变成正方形。 +1 给你,-1 给只阅读一半答案然后寻求进一步帮助的人。 @Tim:好的,我认为这只是一个建议,例如:您应该这样做以获得更好的实践,但这不是必需的(我当时只是想让它工作),这有帮助。谢谢!再次。 【参考方案1】:一方面,假设属性的位置是不好的。您任意假设“顶点”是属性 0,而“颜色”是属性 1。这是一个危险的假设。您想调用glGetAttribLocation
来获取他们的真实位置,或者在链接之前调用glBindAttribLocation
将变量分配给一个位置。
您的混乱结果看起来几乎就像您提供顶点作为颜色,反之亦然。
此外,您正在着色器中读取 2d 顶点,同时提供 3d 顶点信息。您可能希望保持一致。
【讨论】:
嗯,在更改了位置中的一些变量之后,您似乎对颜色是正确的,是给定的顶点...给我一点,看看我是否可以使用您的建议修复它。谢谢。 如果您愿意查看我更新的问题,感谢您迄今为止的帮助!以上是关于在 OpenGL 中显示立方体的问题的主要内容,如果未能解决你的问题,请参考以下文章
我的 opengl 代码应该显示多个立方体,但只显示一个正方形