为什么我使用此 opengl 应用程序会出现黑屏?
Why am I getting a black screen with this opengl application?
我一定是遗漏了一些非常简单的东西,过去一个小时我一直盯着我的代码看,就是看不到它。代码应该只创建一个具有随机纯色或纯黑色像素的纹理,然后将其绘制到屏幕上。现在虽然只是黑屏...
我猜它与我的顶点或 uv 位置有关。
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
const char TITLE[] = "GL TEST";
const int WIDTH = 800;
const int HEIGHT = 600;
const char BASIC_VERT_SHADER[] =
"#version 330\n"
"in vec2 vs_position;"
"in vec2 vs_uvCoord;"
"out vec2 fs_uvCoord;"
"void main()"
"{"
"fs_uvCoord = vs_uvCoord;"
"gl_Position = vec4(vs_position, 1.f, 1.f);"
"}";
const char BASIC_FRAG_SHADER[] =
"#version 330\n"
"uniform sampler2D texture;"
"in vec2 fs_uvCoord;"
"out vec4 frag_color;"
"void main()"
"{"
"frag_color = texture2D(texture, fs_uvCoord);"
"}";
const float TEXTURE_UV[] =
{
0.f, 0.f,
1.f, 0.f,
1.f, 1.f,
0.f, 1.f
};
const float VERT_POS[] =
{
-1.f, -1.f,
1.f, -1.f,
1.f, 1.f,
-1.f, 1.f
};
GLFWwindow* setupGraphics()
{
GLFWwindow* window;
if ( !glfwInit() )
{
fputs("failed to initialize glfw!\n", stderr);
exit(1);
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // opengl 3.x
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // opengl 3.3
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // needed for osx
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow(WIDTH, HEIGHT, TITLE, NULL, NULL);
if (!window)
{
fputs("failed to create window!\n", stderr);
exit(1);
}
glfwMakeContextCurrent(window);
glewExperimental = true;
if ( glewInit() != GLEW_OK )
{
fputs("failed to initialize glew!\n", stderr);
exit(1);
}
if ( !GLEW_VERSION_3_3 )
{
fputs("opengl 3.3 support is required!\n", stderr);
exit(1);
}
return window;
};
unsigned int compileShader(const char* shaderSource, GLenum type)
{
unsigned int shaderID = glCreateShader(type);
glShaderSource(shaderID, 1, &shaderSource , NULL);
glCompileShader(shaderID);
int status;
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &status);
if ( status == GL_FALSE )
{
int errorLength;
glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &errorLength);
char errorString[errorLength+1];
glGetShaderInfoLog(shaderID, errorLength, NULL, errorString);
fprintf(stderr, "glsl compile error: %s", errorString);
exit(1);
}
return shaderID;
}
unsigned int compileShaderProgram(const char* vsSource, const char* fsSource)
{
unsigned int programID = glCreateProgram();
unsigned int vsID = compileShader(vsSource, GL_VERTEX_SHADER);
unsigned int fsID = compileShader(fsSource, GL_FRAGMENT_SHADER);
glAttachShader(programID, vsID);
glAttachShader(programID, fsID);
glLinkProgram(programID);
int status;
glGetProgramiv(programID, GL_LINK_STATUS, &status);
if ( status == GL_FALSE )
{
int errorLength;
glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &errorLength);
char errorString[errorLength+1];
glGetProgramInfoLog(programID, errorLength, NULL, errorString);
fprintf(stderr, "glsl linking error: %s", errorString);
exit(1);
}
glDetachShader(programID, vsID);
glDetachShader(programID, fsID);
glDeleteShader(vsID);
glDeleteShader(fsID);
return programID;
}
unsigned int randomTexture(int width, int height)
{
unsigned int textureID;
int size = width * height;
unsigned char* buffer = malloc( size * sizeof(unsigned char) );
for (int i = 0; i < size; i++)
{
if ( rand() & 1 )
{
buffer[i] = 0x00;
}
else
{
buffer[i] = 0xFF;
}
}
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(
GL_TEXTURE_2D, 0, GL_R8,
width, height, 0, GL_RED,
GL_UNSIGNED_BYTE, buffer
);
free(buffer);
return textureID;
}
int main()
{
GLenum glError;
GLFWwindow* window;
unsigned int shader;
unsigned int texture;
unsigned int vertPosBuffer;
unsigned int uvCoordBuffer;
unsigned int vertexArray;
int textureUniform;
int vertPosAttribute;
int uvCoordAttribute;
srand( time(NULL) );
window = setupGraphics();
shader = compileShaderProgram(BASIC_VERT_SHADER, BASIC_FRAG_SHADER);
textureUniform = glGetUniformLocation(shader, "texture");
vertPosAttribute = glGetAttribLocation(shader, "vs_position");
uvCoordAttribute = glGetAttribLocation(shader, "vs_uvCoord");
texture = randomTexture(WIDTH, HEIGHT);
glGenVertexArrays(1, &vertexArray);
glBindVertexArray(vertexArray);
glGenBuffers(1, &vertPosBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertPosBuffer);
glBufferData(GL_ARRAY_BUFFER, 8*sizeof(float), VERT_POS, GL_STATIC_DRAW);
glVertexAttribPointer(vertPosAttribute, 2, GL_FLOAT, GL_FALSE, 0, 0);
glGenBuffers(1, &uvCoordBuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvCoordBuffer);
glBufferData(GL_ARRAY_BUFFER, 8*sizeof(float), TEXTURE_UV, GL_STATIC_DRAW);
glVertexAttribPointer(uvCoordAttribute, 2, GL_FLOAT, GL_FALSE, 0, 0);
while ( !glfwWindowShouldClose(window) )
{
glClear( GL_COLOR_BUFFER_BIT );
glClearColor(0.f, 0.f, 0.f, 1.f);
glUseProgram(shader);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(textureUniform, 0);
glBindVertexArray(vertexArray);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glfwSwapBuffers(window);
glfwPollEvents();
while((glError = glGetError()) != GL_NO_ERROR)
{
fprintf(stderr, "gl error: %d\n", glError);
exit(1);
}
}
glDeleteVertexArrays(1, &vertexArray);
glDeleteBuffers(1, &vertPosBuffer);
glDeleteBuffers(1, &uvCoordBuffer);
glDeleteTextures(1, &texture);
glDeleteProgram(shader);
return 0;
}
主要问题是您忘记启用通用顶点属性数组。参见 glEnableVertexAttribArray
glGenBuffers(1, &vertPosBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertPosBuffer);
glBufferData(GL_ARRAY_BUFFER, 8*sizeof(float), VERT_POS, GL_STATIC_DRAW);
glVertexAttribPointer(vertPosAttribute, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray( vertPosAttribute ); // <-----------------
glGenBuffers(1, &uvCoordBuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvCoordBuffer);
glBufferData(GL_ARRAY_BUFFER, 8*sizeof(float), TEXTURE_UV, GL_STATIC_DRAW);
glVertexAttribPointer(uvCoordAttribute, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray( uvCoordAttribute ); // <-----------------
如您问题的评论中所述,您应该将文本缩小过滤器设置为 GL_LINEAR
或 GL_NEAREST
,因为您不使用 mipmaps:
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(
GL_TEXTURE_2D, 0, GL_R8,
width, height, 0, GL_RED,
GL_UNSIGNED_BYTE, buffer.data()
);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
创建四边形的三角形条纹设置如下:
const float TEXTURE_UV[] =
{
0.f, 0.f,
1.f, 0.f,
0.f, 1.f,
1.f, 1.f
};
const float VERT_POS[] =
{
-1.f, -1.f,
1.f, -1.f,
-1.f, 1.f,
1.f, 1.f
};
但是你可以画一个三角形的扇子:
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
我一定是遗漏了一些非常简单的东西,过去一个小时我一直盯着我的代码看,就是看不到它。代码应该只创建一个具有随机纯色或纯黑色像素的纹理,然后将其绘制到屏幕上。现在虽然只是黑屏...
我猜它与我的顶点或 uv 位置有关。
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
const char TITLE[] = "GL TEST";
const int WIDTH = 800;
const int HEIGHT = 600;
const char BASIC_VERT_SHADER[] =
"#version 330\n"
"in vec2 vs_position;"
"in vec2 vs_uvCoord;"
"out vec2 fs_uvCoord;"
"void main()"
"{"
"fs_uvCoord = vs_uvCoord;"
"gl_Position = vec4(vs_position, 1.f, 1.f);"
"}";
const char BASIC_FRAG_SHADER[] =
"#version 330\n"
"uniform sampler2D texture;"
"in vec2 fs_uvCoord;"
"out vec4 frag_color;"
"void main()"
"{"
"frag_color = texture2D(texture, fs_uvCoord);"
"}";
const float TEXTURE_UV[] =
{
0.f, 0.f,
1.f, 0.f,
1.f, 1.f,
0.f, 1.f
};
const float VERT_POS[] =
{
-1.f, -1.f,
1.f, -1.f,
1.f, 1.f,
-1.f, 1.f
};
GLFWwindow* setupGraphics()
{
GLFWwindow* window;
if ( !glfwInit() )
{
fputs("failed to initialize glfw!\n", stderr);
exit(1);
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // opengl 3.x
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // opengl 3.3
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // needed for osx
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow(WIDTH, HEIGHT, TITLE, NULL, NULL);
if (!window)
{
fputs("failed to create window!\n", stderr);
exit(1);
}
glfwMakeContextCurrent(window);
glewExperimental = true;
if ( glewInit() != GLEW_OK )
{
fputs("failed to initialize glew!\n", stderr);
exit(1);
}
if ( !GLEW_VERSION_3_3 )
{
fputs("opengl 3.3 support is required!\n", stderr);
exit(1);
}
return window;
};
unsigned int compileShader(const char* shaderSource, GLenum type)
{
unsigned int shaderID = glCreateShader(type);
glShaderSource(shaderID, 1, &shaderSource , NULL);
glCompileShader(shaderID);
int status;
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &status);
if ( status == GL_FALSE )
{
int errorLength;
glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &errorLength);
char errorString[errorLength+1];
glGetShaderInfoLog(shaderID, errorLength, NULL, errorString);
fprintf(stderr, "glsl compile error: %s", errorString);
exit(1);
}
return shaderID;
}
unsigned int compileShaderProgram(const char* vsSource, const char* fsSource)
{
unsigned int programID = glCreateProgram();
unsigned int vsID = compileShader(vsSource, GL_VERTEX_SHADER);
unsigned int fsID = compileShader(fsSource, GL_FRAGMENT_SHADER);
glAttachShader(programID, vsID);
glAttachShader(programID, fsID);
glLinkProgram(programID);
int status;
glGetProgramiv(programID, GL_LINK_STATUS, &status);
if ( status == GL_FALSE )
{
int errorLength;
glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &errorLength);
char errorString[errorLength+1];
glGetProgramInfoLog(programID, errorLength, NULL, errorString);
fprintf(stderr, "glsl linking error: %s", errorString);
exit(1);
}
glDetachShader(programID, vsID);
glDetachShader(programID, fsID);
glDeleteShader(vsID);
glDeleteShader(fsID);
return programID;
}
unsigned int randomTexture(int width, int height)
{
unsigned int textureID;
int size = width * height;
unsigned char* buffer = malloc( size * sizeof(unsigned char) );
for (int i = 0; i < size; i++)
{
if ( rand() & 1 )
{
buffer[i] = 0x00;
}
else
{
buffer[i] = 0xFF;
}
}
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(
GL_TEXTURE_2D, 0, GL_R8,
width, height, 0, GL_RED,
GL_UNSIGNED_BYTE, buffer
);
free(buffer);
return textureID;
}
int main()
{
GLenum glError;
GLFWwindow* window;
unsigned int shader;
unsigned int texture;
unsigned int vertPosBuffer;
unsigned int uvCoordBuffer;
unsigned int vertexArray;
int textureUniform;
int vertPosAttribute;
int uvCoordAttribute;
srand( time(NULL) );
window = setupGraphics();
shader = compileShaderProgram(BASIC_VERT_SHADER, BASIC_FRAG_SHADER);
textureUniform = glGetUniformLocation(shader, "texture");
vertPosAttribute = glGetAttribLocation(shader, "vs_position");
uvCoordAttribute = glGetAttribLocation(shader, "vs_uvCoord");
texture = randomTexture(WIDTH, HEIGHT);
glGenVertexArrays(1, &vertexArray);
glBindVertexArray(vertexArray);
glGenBuffers(1, &vertPosBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertPosBuffer);
glBufferData(GL_ARRAY_BUFFER, 8*sizeof(float), VERT_POS, GL_STATIC_DRAW);
glVertexAttribPointer(vertPosAttribute, 2, GL_FLOAT, GL_FALSE, 0, 0);
glGenBuffers(1, &uvCoordBuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvCoordBuffer);
glBufferData(GL_ARRAY_BUFFER, 8*sizeof(float), TEXTURE_UV, GL_STATIC_DRAW);
glVertexAttribPointer(uvCoordAttribute, 2, GL_FLOAT, GL_FALSE, 0, 0);
while ( !glfwWindowShouldClose(window) )
{
glClear( GL_COLOR_BUFFER_BIT );
glClearColor(0.f, 0.f, 0.f, 1.f);
glUseProgram(shader);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(textureUniform, 0);
glBindVertexArray(vertexArray);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glfwSwapBuffers(window);
glfwPollEvents();
while((glError = glGetError()) != GL_NO_ERROR)
{
fprintf(stderr, "gl error: %d\n", glError);
exit(1);
}
}
glDeleteVertexArrays(1, &vertexArray);
glDeleteBuffers(1, &vertPosBuffer);
glDeleteBuffers(1, &uvCoordBuffer);
glDeleteTextures(1, &texture);
glDeleteProgram(shader);
return 0;
}
主要问题是您忘记启用通用顶点属性数组。参见 glEnableVertexAttribArray
glGenBuffers(1, &vertPosBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertPosBuffer);
glBufferData(GL_ARRAY_BUFFER, 8*sizeof(float), VERT_POS, GL_STATIC_DRAW);
glVertexAttribPointer(vertPosAttribute, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray( vertPosAttribute ); // <-----------------
glGenBuffers(1, &uvCoordBuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvCoordBuffer);
glBufferData(GL_ARRAY_BUFFER, 8*sizeof(float), TEXTURE_UV, GL_STATIC_DRAW);
glVertexAttribPointer(uvCoordAttribute, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray( uvCoordAttribute ); // <-----------------
如您问题的评论中所述,您应该将文本缩小过滤器设置为 GL_LINEAR
或 GL_NEAREST
,因为您不使用 mipmaps:
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(
GL_TEXTURE_2D, 0, GL_R8,
width, height, 0, GL_RED,
GL_UNSIGNED_BYTE, buffer.data()
);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
创建四边形的三角形条纹设置如下:
const float TEXTURE_UV[] =
{
0.f, 0.f,
1.f, 0.f,
0.f, 1.f,
1.f, 1.f
};
const float VERT_POS[] =
{
-1.f, -1.f,
1.f, -1.f,
-1.f, 1.f,
1.f, 1.f
};
但是你可以画一个三角形的扇子:
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);