我最近开始学习OpenGL并编写了一些代码来在SDL窗口中绘制一个简单的白色三角形。我已经阅读并重新阅读了我的代码,并且已经根据几个opengl教程中提出的内容进行了检查,但我无法使其工作。我知道opengl正确绑定到SDL,因为我可以使用glClearColor更改窗口背景颜色,但我无法显示该darn三角形。
我很乐意提供更多信息,但说实话,我不知道问题的确切来源,所以这里是我写的代码:
int init()
{
if(SDL_Init(SDL_INIT_VIDEO) < 0)
{
fprintf(stderr, "SDL error : %s\n", SDL_GetError());
SDL_Quit();
return -1;
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
gWindow = SDL_CreateWindow("Test OpenGL", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINWIDTH, WINHEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
if (gWindow == NULL)
{
fprintf(stderr, "Failed to create window. SDL error : %s\n", SDL_GetError());
SDL_Quit();
return -1;
}
gGLContext = SDL_GL_CreateContext(gWindow);
if (gGLContext == 0)
{
fprintf(stderr, "Failed to create OpenGL context. SDL error : %s\n", SDL_GetError());
SDL_DestroyWindow(gWindow);
SDL_Quit();
return -1;
}
GLenum glewInitResult = glewInit();
if (glewInitResult != GLEW_OK)
{
fprintf(stderr, "Failed to initialize glew. Glew error : %s\n", glewGetErrorString(glewInitResult));
SDL_GL_DeleteContext(gGLContext);
SDL_DestroyWindow(gWindow);
SDL_Quit();
return -1;
}
glEnable(GL_DEPTH_TEST);
return 0;
}
int loadShader(char *filename, GLint *shader)
{
long sz;
const GLchar *code;
FILE *fp = fopen(filename, "rb");
if( !fp ) perror(filename),exit(1);
fseek( fp , 0L , SEEK_END);
sz = ftell( fp );
rewind( fp );
code = calloc( 1, sz+1 );
if( !code ) fclose(fp),fputs("memory alloc fails",stderr),exit(1);
if( 1!=fread( code , sz, 1 , fp) )
fclose(fp),free(code),fputs("entire read fails",stderr),exit(1);
fclose(fp);
char *dot = strrchr(filename, '.');
GLenum type;
if (dot)
type = !strcmp(dot, ".vs") ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER;
*shader = glCreateShader(type);
glShaderSource(*shader, 1, &code, NULL);
glCompileShader(*shader);
GLint status;
glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
char buffer[512];
glGetShaderInfoLog(*shader, sizeof(buffer), NULL, buffer);
fprintf(stderr, buffer);
if (status != GL_TRUE)
return -1;
return 0;
}
void printError(char *message)
{
#define TEST(ERR) case ERR: fprintf(stderr, "%s : " #ERR "\n", message); break;
int error;
if ((error = glGetError()))
switch (error)
{
TEST(GL_INVALID_ENUM)
TEST(GL_INVALID_VALUE)
TEST(GL_INVALID_OPERATION)
TEST(GL_STACK_OVERFLOW)
TEST(GL_STACK_UNDERFLOW)
TEST(GL_OUT_OF_MEMORY)
TEST(GL_INVALID_FRAMEBUFFER_OPERATION)
TEST(GL_TABLE_TOO_LARGE)
default:
fprintf(stderr, "Unknown error\n");
}
#undef TEST
}
int main(int argc, char *argv[])
{
if (init() != 0)
return -1;
float vertices[] = {0.0, 0.5,
0.5, -0.5,
-.5, -0.5};
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
GLuint vShader;
GLuint fShader;
if (loadShader("plain_2d.vs", &vShader) < 0)
return -1;
if (loadShader("plain_2d.fs", &fShader) < 0)
return -1;
GLint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vShader);
glAttachShader(shaderProgram, fShader);
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);
printError("Before entering the loop");
SDL_Event e;
int quit = 0;
while (!quit)
{
printError("In the loop");
while (SDL_PollEvent(&e))
{
switch (e.type)
{
case SDL_QUIT:
quit = 1;
}
}
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
SDL_GL_SwapWindow(gWindow);
}
return 0;
}
printError和loadShader是我写的辅助函数,我确信它们完美无缺。这是顶点和片段着色器的代码,这是基本的,我没有看到有什么错误来自那里:
VERTEX SHADER
#version 150
in vec2 position;
void main()
{
gl_Position = vec4(position, 0.0, 1.0);
}
FRAGMENT SHADER
#version 150
out vec4 outColor;
void main()
{
outColor = vec4(1.0, 1.0, 1.0, 1.0);
}
我很抱歉这是模糊的,但是我做了我的研究,并且在我的代码中找不到任何错误,所以我希望更有经验的人能够找到问题。
提前致谢!
答案 0 :(得分:5)
您尚未生成和绑定顶点数组对象,只是顶点缓冲区。基本上你已经创建了一个数据源(VBO),但数据无处可去,所以当你调用glEnableVertexAttribArray(posAttrib);
在生成并绑定缓冲区之前添加以下内容:
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
编辑:启用兼容性配置文件时,3.1和更新的 中有默认的VAO - 核心配置文件要求您手动执行。
另外,请显示loadShader()
答案 1 :(得分:1)
通常,在创建着色器时,必须指定着色器类型:
GLuint vertexShader, fragmentShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
我的代码中没有看到任何内容。 loadShader是否根据扩展名进行此检测?如果没有,这将是最可能的问题。
答案 2 :(得分:1)
我对你的代码进行了一些检查。一些错误的事情:
以下是使用上下文的差异(来自修改后的版本,因为您没有包含标题或定义):
@@ -22,6 +22,7 @@
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
@@ -43,6 +44,7 @@
return -1;
}
+ glewExperimental = GL_TRUE;
GLenum glewInitResult = glewInit();
if (glewInitResult != GLEW_OK)
{
@@ -69,10 +71,10 @@
rewind( fp );
code = calloc( 1, sz+1 );
- if( !code ) fclose(fp),fputs("memory alloc fails",stderr),exit(1);
+ if( !code ) {fclose(fp);fputs("memory alloc fails",stderr);exit(1);}
if( 1!=fread( code , sz, 1 , fp) )
- fclose(fp),free(code),fputs("entire read fails",stderr),exit(1);
+ {fclose(fp);free(code);fputs("entire read fails",stderr);exit(1);}
fclose(fp);
char *dot = strrchr(filename, '.');
@@ -122,6 +124,10 @@
float vertices[] = {0.0, 0.5,
0.5, -0.5,
-.5, -0.5};
+ GLuint vao;
+ glGenVertexArrays(1, &vao);
+ glBindVertexArray(vao);
+
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
@@ -160,7 +166,7 @@
}
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);