我的简单OpenGL应用程序无法在女友的机器上工作,这使我感到非常奇怪。起初,我想到了代码的各种问题,但最终可以将其分解为该代码不起作用(不起作用意味着:三角形绘制正确,但是黑色绘制,即没有正确的颜色):
#include <stdio.h>
#include <stdlib.h>
#include <string>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
#include "../common/shader.h"
const GLfloat reticle_vertices[] =
{
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f
};
glm::mat4 MVP;
glm::mat4 vp;
const char *vertexSource =
"#version 150\n"
"layout(location = 0) in vec3 position;"
"layout(location = 1) in vec3 color;"
"out vec3 fragColor;"
"uniform mat4 MVP;"
"void main() {"
"gl_Position = MVP * vec4(position, 1.0);"
"fragColor = color;"
"}";
const char *fragmentSource =
"#version 150\n"
"in vec3 fragColor;"
"out vec4 outColor;"
"void main() {"
"outColor = vec4(fragColor, 1.0);"
"}";
// Key callback: exit on ESCAPE
static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
// Initialize and return a window with GLFW
GLFWwindow *initGLWindow(int width, int height, int samples, const char *title, GLFWkeyfun keycb)
{
if (!glfwInit())
{
fprintf(stderr, "Failed to initialize GLFW\n");
return NULL;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_SAMPLES, samples);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow *w = glfwCreateWindow(width, height, title, NULL, NULL);
if (!w)
{
glfwTerminate();
return NULL;
}
glfwMakeContextCurrent(w);
glfwSetKeyCallback(w, keycb);
glewExperimental = true;
if (glewInit() != GLEW_OK)
{
fprintf(stderr, "Failed to initialize GLEW\n");
return NULL;
}
return w;
}
int main()
{
// Initialize the OpenGL window
GLFWwindow *window = initGLWindow(1024, 768, 2, "Schnuff", key_callback);
// Load and use the shaders
GLuint programID = LoadShaders(vertexSource, fragmentSource);
glUseProgram(programID);
// Get the attribute locations
GLuint posAttrib = glGetAttribLocation(programID, "position");
printf("posAttrib = %d\n", posAttrib);
GLuint colAttrib = glGetAttribLocation(programID, "color");
printf("colAttrib = %d\n", colAttrib);
//GLint normAttrib = glGetAttribLocation(programID, "normal");
//printf("normAttrib = %d\n", normAttrib);
GLuint mvpID = glGetUniformLocation(programID, "MVP");
// Vertex array object
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Vertex buffer object
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(reticle_vertices), reticle_vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
// Hide the cursor
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_CULL_FACE);
glClearColor(0.0f, 0.0f, 0.2f, 1.0f);
glm::mat4 m = glm::mat4(1.0f);
// Main loop
do
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUniformMatrix4fv(mvpID, 1, GL_FALSE, &m[0][0]);
glVertexAttrib3f(colAttrib, 1.0f, 0.0f, 0.0f);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
glfwPollEvents();
}
while (!glfwWindowShouldClose(window));
glDeleteProgram(programID);
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
据我所知,问题仅出现是由于以下原因:在她的机器上
posAttrib = 1, colAttrib = 0
,而在我的机器上则相反。我尝试使用layout(location = 0) in vec3 position;
layout(location = 1) in vec3 color;
然后就可以了!尽管一旦我交换了这些数字(我还没有用其他值和
#version 330 core\n
对其进行测试,但是她的笔记本电脑目前处于离线状态),它仍然无法工作...我什至发现了以下悬而未决的问题here on SO,它似乎密切相关。
你们中是否有人遇到过类似的行为,或者知道如何在不使用
layout(location = x)
的情况下解决整个问题?因为我认为在一个较大的项目中,手动设置每个位置可能是乏味的或不想要的(如果我错了,请纠正我,这实际上是首选的方法!)。尚未测试:0或1以外的其他值,以及
#version
的东西,因为在我的机器上,我什至不能在没有layout(location = x)
的情况下使用#version 330 core
(这又很奇怪,因为它显然在她的机器上做了某些事情使其正常工作)。我是OpenGL的新手,因此在这里完全感到困惑! :-)
最佳答案
看起来像我的AMD卡上的driver bug。
将VBO用于颜色阵列的工作原理是:
#include <vector>
#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
// GLSL shader program loader
struct Program
{
static GLuint Load( const char* vert, const char* geom, const char* frag )
{
GLuint prog = glCreateProgram();
if( vert ) AttachShader( prog, GL_VERTEX_SHADER, vert );
if( geom ) AttachShader( prog, GL_GEOMETRY_SHADER, geom );
if( frag ) AttachShader( prog, GL_FRAGMENT_SHADER, frag );
glLinkProgram( prog );
CheckStatus( prog );
return prog;
}
private:
static void CheckStatus( GLuint obj )
{
GLint status = GL_FALSE, len = 10;
if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
if( status == GL_TRUE ) return;
if( glIsShader(obj) ) glGetShaderiv( obj, GL_INFO_LOG_LENGTH, &len );
if( glIsProgram(obj) ) glGetProgramiv( obj, GL_INFO_LOG_LENGTH, &len );
std::vector< char > log( len, 'X' );
if( glIsShader(obj) ) glGetShaderInfoLog( obj, len, NULL, &log[0] );
if( glIsProgram(obj) ) glGetProgramInfoLog( obj, len, NULL, &log[0] );
std::cerr << &log[0] << std::endl;
exit( -1 );
}
static void AttachShader( GLuint program, GLenum type, const char* src )
{
GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader );
glAttachShader( program, shader );
glDeleteShader( shader );
}
};
#define GLSL(version, shader) "#version " #version "\n" #shader
const char* vert = GLSL
(
150 core,
in vec3 position;
in vec3 color;
out vec3 fragColor;
uniform mat4 MVP;
void main()
{
fragColor = color;
gl_Position = MVP * vec4(position, 1.0);
}
);
const char* frag = GLSL
(
150 core,
in vec3 fragColor;
out vec4 outColor;
void main()
{
outColor = vec4(1.0);
}
);
const GLfloat reticle_vertices[] =
{
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f
};
const GLfloat colors[] =
{
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f
};
// Key callback: exit on ESCAPE
static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
// Initialize and return a window with GLFW
GLFWwindow *initGLWindow(int width, int height, int samples, const char *title, GLFWkeyfun keycb)
{
if (!glfwInit())
{
fprintf(stderr, "Failed to initialize GLFW\n");
return NULL;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_SAMPLES, samples);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow *w = glfwCreateWindow(width, height, title, NULL, NULL);
if (!w)
{
glfwTerminate();
return NULL;
}
glfwMakeContextCurrent(w);
glfwSetKeyCallback(w, keycb);
glewExperimental = true;
if (glewInit() != GLEW_OK)
{
fprintf(stderr, "Failed to initialize GLEW\n");
return NULL;
}
while( glGetError() != GL_NO_ERROR ) {}
return w;
}
int main()
{
// Initialize the OpenGL window
GLFWwindow *window = initGLWindow(1024, 768, 2, "Schnuff", key_callback);
// Hide the cursor
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
// Load and use the shaders
GLuint programID = Program::Load( vert, NULL, frag );
glUseProgram(programID);
// Vertex array object
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Vertex buffer object
GLuint posVbo;
glGenBuffers(1, &posVbo);
glBindBuffer(GL_ARRAY_BUFFER, posVbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(reticle_vertices), reticle_vertices, GL_STATIC_DRAW);
GLuint colorVbo;
glGenBuffers(1, &colorVbo);
glBindBuffer(GL_ARRAY_BUFFER, colorVbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_CULL_FACE);
// Main loop
while( !glfwWindowShouldClose(window) )
{
glClearColor(0.0f, 0.0f, 0.2f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 m = glm::mat4(1.0f);
GLuint mvpID = glGetUniformLocation(programID, "MVP");
glUniformMatrix4fv(mvpID, 1, GL_FALSE, &m[0][0]);
GLuint posPos = glGetAttribLocation( programID, "position" );
glEnableVertexAttribArray( posPos );
glBindBuffer(GL_ARRAY_BUFFER, posVbo);
glVertexAttribPointer( posPos, 3, GL_FLOAT, GL_FALSE, 0, (void*)0 );
GLuint colorPos = glGetAttribLocation( programID, "color" );
// broken
//glDisableVertexAttribArray( colorPos );
//glVertexAttrib3f( colorPos, 1.0f, 0.0f, 0.0f );
// works
glEnableVertexAttribArray( colorPos );
glBindBuffer(GL_ARRAY_BUFFER, colorVbo);
glVertexAttribPointer( colorPos, 3, GL_FLOAT, GL_FALSE, 0, (void*)0 );
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteProgram(programID);
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}