Не могу изменить цвет фона в OpenGL

Я только начал экспериментировать с OpenGL (используя freeglut и GLEW). Я могу заставить окно всплывать, но ничего не рисуется, я даже не могу заставить его изменить цвет фона.

Вот как выглядит основная функция:

int
main(int argc, char **argv)
{ 
  GLenum err;

  /* Initialize GLUT library */
  glutInit(&argc, argv);

  /* Set window mode */
  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);

  /* Choose OpenGL version */
  glutInitContextVersion(3, 3);

  /* Choose OpenGL profile */
  glutInitContextFlags(GLUT_CORE_PROFILE);

  /* Create a GLUT window */
  glutCreateWindow("OpenGL 2D");

  /* Initialize GLEW library */
  glewExperimental = GL_TRUE;
  err = glewInit();
  if(err != GLEW_OK) {
    printf("Cannot initialize GLEW: %s\n",
       glewGetErrorString(err));
    return 1;
  }

  /* WORKAROUND: Ignore all GLEW errors */
  while(glGetError() != GL_NO_ERROR)
    ;

  (void) printf("OpenGL vendor: \"%s\"\n"
        "       renderer: \"%s\"\n"
        "       version: \"%s\"\n"
        "       SL version: \"%s\"\n",
        glGetString(GL_VENDOR),
        glGetString(GL_RENDERER),
        glGetString(GL_VERSION),
        glGetString(GL_SHADING_LANGUAGE_VERSION));

  /* Set up callback function for "reshape" event */
  printf("Setting callback functions\n");
  glutReshapeFunc(canvas_reshape);

  /* Set up callback function for "display" event */
  glutDisplayFunc(canvas_display);

  /* Set up callback function for "keyboard" event */
  glutKeyboardFunc(canvas_keyboard);

  /* Set up callback function for "timer" event */
  glutTimerFunc(30, canvas_timer, 0);

  /* Initialize OpenGL */
  init();

  /* Choose the window's position */
  glutPositionWindow(100, 100);

  /* Choose the window's size */
  glutReshapeWindow(800, 600);

  /* Start main loop */
  printf("Entering main loop\n");
  glutMainLoop();

  return 0;
}

Вот как выглядит инициализация:

init()
{
  const GLchar *vertex_shader_source[] = {
    "#version 330 core\n",
    "\n",
    "layout(location=0) in vec4 position;\n",
    "out vec4 color;\n",
    "uniform mat4 viewtrans;\n",
    "\n",
    "void\n",
    "main()\n",
    "{\n",
    "  gl_Position = viewtrans * position;\n"
    "  color =  vec4(1.0, 1.0, 1.0, 1.0);\n"
    "}\n" };
  const GLchar *fragment_shader_source[] = {
    "#version 330 core\n",
    "in vec4 color;\n",
    "layout(location=0) out vec4 fcolor;\n",
    "void\n",
    "main()\n",
    "{\n",
    "  fcolor = color;\n",
    "}\n" };
  char compiler_log[LOGSIZE];

  /* Obtain an unused name for our vertex array */
  printf("Creating vertex array\n");
  glGenVertexArrays(1, &vertex_array);
  check_error("glGenVertexArrays");

  /* Tell OpenGL to use the new vertex array */
  glBindVertexArray(vertex_array);
  check_error("glBindVertexArray");

  /* Obtain an unused name for our vertex buffer */
  printf("Creating vertex buffer\n");
  glGenBuffers(1, &vertex_buffer);
  check_error("glGenBuffers");

  /* Tell OpenGL to use the new vertex buffer as the
   * vertex array */
  glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
  check_error("glBindBuffer");

  /* We want to get two coordinates from the vertex buffer and
   * feed them as the first parameter to the vertex shader */
  glEnableVertexAttribArray(0);
  glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 2, 0);

  /* Create vertex shader */
  printf("Creating vertex shader\n");
  vertex_shader = glCreateShader(GL_VERTEX_SHADER);
  check_error("glCreateShader");

  /* Assign vertex shader source code */
  glShaderSource(vertex_shader, sizeof(vertex_shader_source) / sizeof(GLchar *),
         vertex_shader_source, 0);
  check_error("glShaderSource");

  /* Compile vertex shader */
  glCompileShader(vertex_shader);
  check_error("glCompileShader");

  /* Get compiler log *//* Set up callback function for "timer" event */
  glGetShaderInfoLog(vertex_shader, LOGSIZE, 0, compiler_log);
  printf("  Compiler log: \"%s\"\n", compiler_log);

  /* Create fragment shader */
  printf("Creating fragment shader\n");
  fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
  check_error("glCreateShader");

  /* Assign fragment shader source code */
  glShaderSource(fragment_shader, sizeof(fragment_shader_source) / sizeof(GLchar *),
         fragment_shader_source, 0);
  check_error("glShaderSource");

  /* Compile fragment shader */
  glCompileShader(fragment_shader);
  check_error("glCompileShader");

  /* Get compiler log */
  glGetShaderInfoLog(fragment_shader, LOGSIZE, 0, compiler_log);
  printf("  Compiler log: \"%s\"\n", compiler_log);

  /* Create shader program */
  printf("Creating shader program\n");
  shader_program = glCreateProgram();
  check_error("glCreateProgram");

  /* Attach vertex shader */
  glAttachShader(shader_program, vertex_shader);
  check_error("glAttachShader");

  /* Attach fragment shader */
  glAttachShader(shader_program, fragment_shader);
  check_error("glAttachShader");

  /* Link shader program */
  glLinkProgram(shader_program);
  check_error("glLinkProgram");

  /* Get linker log */
  glGetProgramInfoLog(shader_program, LOGSIZE, 0, compiler_log);
  printf("  Linker log: \"%s\"\n", compiler_log);

  /* Get location of "viewtrans" matrix */
  viewtrans = glGetUniformLocation(shader_program, "viewtrans");
  check_error("glGetUniformLocation");

  /* Tell OpenGL to use the new shader program */
  glUseProgram(shader_program);

  /* Choose background color */
  glClearColor(1.0, 0.0, 1.0, 0.0);
}

Вот чем я рисую:

static void
canvas_display()
{
  glClearColor(0.0, 0.0, 0.0, 0.0);

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

Все это основано на учебнике. На самом деле происходит что-то вроде белого окна размером 300 x 300, которое преобразуется в черное окно размером 800 x 600, НО с белым квадратом 300 x 300 посередине или в углу, чьи пиксели (частично) становятся черными, когда изменение размера окна таким образом, что (часть) квадрата исчезает (либо вручную, либо с помощью кода). Я также написал код для рисования треугольников, но он тоже не работает, как и следовало ожидать. Но вот код для этого в любом случае:

static void
canvas_display()
{
    glClearColor(0.0, 0.0, 0.0, 0.0);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    GLfloat vertices[] =
    { 0.0, 0.0,
      0.5, 0.5,
      0.5, 0.0 };

    glGenVertexArrays(1, &vertex_array);
    glBindVertexArray(vertex_array);

    glGenBuffers(1, &vertex_buffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GL_FLOAT) * 2, vertices);

    glDrawArrays(GL_TRIANGLES, 0, 3);
}

person sanik98    schedule 28.05.2020    source источник
comment
Всего несколько замечаний. Во-первых, вы всегда указываете альфа-значение 0.0 при вызове glClearColor, который требует, чтобы фон был полностью прозрачным - вместо этого попробуйте 1.0. Во-вторых, насколько я вижу, вы никогда не устанавливали значение униформы viewtrans.   -  person G.M.    schedule 28.05.2020
comment
Спасибо, поменял, все равно. Неудивительно, поскольку, как я уже сказал, я не могу рисовать ни одной вещи, и кажется, что ни одна вещь не рисуется с момента создания и изменения формы окна. viewtrans сбрасывается в canvas_reshape для обеспечения однородных пропорций с помощью glUniformMatrix4fv и матрицы с соответствующим масштабированием первых двух векторов-столбцов.   -  person sanik98    schedule 28.05.2020
comment
проверьте свои ошибки opengl в цикле рендеринга   -  person Erwan Daniel    schedule 28.05.2020


Ответы (1)


Не указывайте постоянно новые объекты массива вершин. Создайте 1 объект массива вершин при инициализации. Массив вершин содержится в объекте Vertex Buffer. Когда объект именованного буфера привязан к цели ARRAY_BUFFER, последний параметр glVertexAttribPointer рассматривается как смещение в байтах в хранилище данных объекта буфера. Таким образом, смещение должно быть NULL:

void init()
{
    // [...]

    GLfloat vertices[] =
    { 0.0, 0.0,
      0.5, 0.5,
      0.5, 0.0 };

    glGenVertexArrays(1, &vertex_array);
    glBindVertexArray(vertex_array);

    glGenBuffers(1, &vertex_buffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GL_FLOAT) * 2, NULL);
}

Убедитесь, что программа установлена ​​и VAO привязан при рисовании геометрии. По умолчанию значения юниформ инициализируются нулем. По крайней мере, вы должны установить идентификационную матрицу, а затем матрицу uniform viewtrans.
Поскольку вы используете двойная буферизация (GLUT_DOUBLE), вы должны поменять местами буферы текущего окна после отрисовки всей геометрии с помощью glutSwapBuffers

void canvas_display()
{
    glClearColor(1.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glUseProgram(shader_program);
    GLfloat identity_mat[] = { 1,0,0,0,  0,1,0,0, 0,0,1,0, 0,0,0,1 };
    glUniformMatrix4fv(viewtrans, 1, GL_FALSE, identity_mat);

    glBindVertexArray(vertex_array);
    glDrawArrays(GL_TRIANGLES, 0, 3);

    glutSwapBuffers();
    glutPostRedisplay();
}
person Rabbid76    schedule 28.05.2020
comment
Хорошо, большое спасибо, отсутствующий вызов glutSwapBuffers оказался ключевой проблемой, и я взял ее оттуда, хотя ваше объяснение в целом также очень помогло. - person sanik98; 28.05.2020
comment
@sanik98 Спасибо. Пожалуйста. Ключевой проблемой является glutSwapBuffers и смещение к glVertexAttribPointer. - person Rabbid76; 28.05.2020
comment
О, вы правы, но я думаю, что это была моя оплошность, и я не заметил этого во второй раз (я просто закомментировал все, что связано с рисованием, и попробовал снова). - person sanik98; 28.05.2020