为什么我使用此 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_LINEARGL_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);