c - 使用 SDL2 & Glew,尝试在 OpenGL 中绘制一个简单的白色正方形。只会黑屏

标签 c opengl sdl-2

基于这里的教程:http://lazyfoo.net/tutorials/SDL/51_SDL_and_modern_opengl/index.php

但运气不佳。有任何想法吗?继承人的代码:

#include <stdio.h>
#include <SDL2/SDL.h>
#include "glew.h"
//#include <GL/glut.h>
#include <SDL2/SDL_opengl.h>
#include <stdbool.h>

void close(GLuint gProgramID, SDL_Window *window);
bool initGL(GLuint *gProgramID, GLint *gVertexPos2DLocation, GLuint *gVBO, GLuint *gIBO);
void printProgramLog(GLuint program);
void printShaderLog(GLuint shader);
void render(GLuint *gProgramID, GLint *gVertexPos2DLocation, GLuint *gVBO, GLuint *gIBO);


void close(GLuint gProgramID, SDL_Window *window) {
  //Deallocate program
  glDeleteProgram( gProgramID );

  //Destroy window  
  SDL_DestroyWindow( window );
  window = NULL;

  //Quit SDL subsystems
  SDL_Quit();
}

bool initGL(GLuint *gProgramID, GLint *gVertexPos2DLocation, GLuint *gVBO, GLuint *gIBO) {
  *gProgramID = glCreateProgram();

  GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);

  const GLchar *vertexShaderSource[] =
  {
    "#version 140\nin vec2 LVertexPos2D; void main() { gl_Position = vec4( LVertexPos2D.x, LVertexPos2D.y, 0, 1 ); }"
  };

  glShaderSource(vertexShader, 1, vertexShaderSource, NULL);

  glCompileShader(vertexShader);

  GLint vShaderCompiled = GL_FALSE;
  glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &vShaderCompiled);

  if (vShaderCompiled != GL_TRUE) {
    printf("Unable to compile shader %d", &vShaderCompiled);
    printShaderLog(vertexShader);

    return false;
  }
  else {
    glAttachShader(*gProgramID, vertexShader);
    GLuint fragmentShader = glCreateShader( GL_FRAGMENT_SHADER );

    const GLchar *fragmentShaderSource[] =
    {
        "#version 140\nout vec4 LFragment; void main() { LFragment = vec4( 1.0, 1.0, 1.0, 1.0 );}"
    };

    glShaderSource(fragmentShader, 1, fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);

    GLint fShaderCompiled = GL_FALSE;
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &fShaderCompiled);
    if(fShaderCompiled != GL_TRUE) {
        printf("Unable to compile fragment shader %d!\n", fragmentShader);
        printShaderLog(fragmentShader);
        return false;
    }
    else {
      glAttachShader(*gProgramID, fragmentShader);

      glLinkProgram(*gProgramID);

      GLint programSuccess = GL_TRUE;
      glGetProgramiv(*gProgramID, GL_LINK_STATUS, &programSuccess);
      if (programSuccess != GL_TRUE) {
        printf("Error linking program %d!\n", *gProgramID);
        printProgramLog(*gProgramID);
        return false;
      }
      else {
        *gVertexPos2DLocation = glGetAttribLocation(*gProgramID, "LVertexPos2D");

        if (*gVertexPos2DLocation == -1) {
          printf("LVertexPos2D is not a valid glsl program variable!\n");
          return false;
        }
        else {
          glClearColor(0.f, 0.f, 0.f, 1.f);

          GLfloat vertexData[] = {
            -0.5f, -0.5f,
            0.5f, -0.5f,
            0.5f, 0.5f,
            -0.5f, 0.5f
          };

          GLuint indexData[] = { 0, 1, 2, 3 };

          glGenBuffers(1, gVBO);
          glBindBuffer(GL_ARRAY_BUFFER, *gVBO);
          glBufferData(GL_ARRAY_BUFFER, 2 * 4 * sizeof(GLfloat), vertexData, GL_STATIC_DRAW);

          glGenBuffers(1, gIBO);
          glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *gIBO);
          glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4 * sizeof(GLuint), indexData, GL_STATIC_DRAW);
          return true;
        }
      }
    }
  }
}

void printProgramLog(GLuint program) {
  if (glIsProgram(program)) {

    int infoLogLength = 0;
    int maxLength = infoLogLength;

    glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);

    char* infoLog = malloc(sizeof(char) * maxLength);

    glGetProgramInfoLog(program, maxLength, &infoLogLength, infoLog);
    if (infoLogLength > 0) {
      printf("%s\n", infoLog);
    }

    free(infoLog);
  }
  else {
    printf( "Name %d is not a program\n", program );
  }
}

void printShaderLog(GLuint shader) {
  //Make sure name is shader
  if(glIsShader( shader )) {
    //Shader log length
    int infoLogLength = 0;
    int maxLength = infoLogLength;

    //Get info string length
    glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);

    //Allocate string
    char* infoLog = malloc(sizeof(char) * maxLength);

    //Get info log
    glGetShaderInfoLog(shader, maxLength, &infoLogLength, infoLog);
    if(infoLogLength > 0) {
        printf( "%s\n", infoLog );
    }

    //Deallocate string
    free(infoLog);
  }
  else {
    printf("Name %d is not a shader\n", shader);
  }
}

void render(GLuint *gProgramID, GLint *gVertexPos2DLocation, GLuint *gVBO, GLuint *gIBO) {
  //Clear color buffer
  glClear(GL_COLOR_BUFFER_BIT);

  //Bind program
  glUseProgram(*gProgramID);

  //Enable vertex position
  glEnableVertexAttribArray(*gVertexPos2DLocation);

  //Set vertex data
  glBindBuffer(GL_ARRAY_BUFFER, *gVBO);
  glVertexAttribPointer(*gVertexPos2DLocation, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), NULL);

  //Set index data and render
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *gIBO);
  glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_INT, NULL);

  //Disable vertex position
  glDisableVertexAttribArray(*gVertexPos2DLocation);

  //Unbind program
  glUseProgram(NULL);
}

int main(int argc, char *argv[]) {
  if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
    printf("SDL_Init error: %s\n", SDL_GetError());
  }

  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_Window *window = SDL_CreateWindow("Pong", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_OPENGL);

  GLuint gProgramID = 0;
  GLint gVertexPos2DLocation = -1;
  GLuint gVBO = 0;
  GLuint gIBO = 0;

  SDL_GLContext *context = SDL_GL_CreateContext(window);

  if (context == NULL) {
    printf("OpenGL context could not be created! SDL Error: %s\n", SDL_GetError());
    return 1;
  }

  glewExperimental = GL_TRUE;
  GLenum glewError = glewInit();

  if (glewError != GLEW_OK) {
    printf("Error initializing glew! %s\n", glewGetErrorString(glewError));
    return 1;
  }

  if( SDL_GL_SetSwapInterval( 1 ) < 0 ) {
    printf( "Warning: Unable to set VSync! SDL Error: %s\n", SDL_GetError() );
  }

  //Initialize OpenGL
  if (!initGL(&gProgramID, &gVertexPos2DLocation, &gVBO, &gIBO)) {
    printf( "Unable to initialize OpenGL!\n" );
    return 1;
  }

  bool quit = false;

  SDL_Event e;

  while (!quit) {
    while (SDL_PollEvent(&e) != 0) {
      if (e.type == SDL_QUIT) {
        quit = true;
      }

      if (e.type == SDL_KEYDOWN) {
        SDL_Keycode keyPressed = e.key.keysym.sym;

        switch (keyPressed) {
          case SDLK_ESCAPE:
            quit = true;
            break;
        }
      }
    }

    render(&gProgramID, &gVertexPos2DLocation, &gVBO, &gIBO);

    SDL_GL_SwapWindow(window);
  }

  SDL_StopTextInput();
  close(gProgramID, window);

  return 0;
}

最佳答案

您使用的教程有一些奇怪的缺陷:

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);

这需要 OpenGL 3.1 核心配置文件上下文,这完全没有意义,因为配置文件是在 GL 3.2 中引入的。 没有 3.1 核心配置文件。根据WGL_ARB_create_context_specification ,现在可能会发生以下情况:

If version 3.1 is requested, the context returned may implement any of the following versions:

  • Version 3.1. The GL_ARB_compatibility extension may or may not be implemented, as determined by the implementation.
  • The core profile of version 3.2 or greater.

所以你很有可能获得一些没有兼容性功能的现代上下文,这给我们带来了第二个缺陷:你没有使用 Vertex Array Objects (VAOs) .这些在现代 OpenGL 中是强制性的。您使用的教程可能偶然在一些机器上工作,在这些机器上 GL 实现返回具有兼容性扩展的 GL 3.1 上下文,但绝不保证它可以工作。

我建议您使用更准确的教程,例如 Learning Modern 3D Graphics Programmingopen.gl .后者还有一个 section about using SDL2 , 尽管使用的窗口和上下文创建库对于学习 OpenGL 并不是很重要。

关于c - 使用 SDL2 & Glew,尝试在 OpenGL 中绘制一个简单的白色正方形。只会黑屏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25697203/

相关文章:

c++ - Antlr C 运行时示例中的 undefined reference

c++ - 将 cairo 表面直接渲染到 OpenGL 纹理

c++ - OpenGL 检查是否启用或禁用了某些东西

c++ - 纹理显示为纯黑色,除非我将无效值传递给纹理统一位置

c++ - SDL2 CreateRenderer 抛出无效窗口错误

c++ - 我如何使用中点圆算法去除在 SDL 中绘制的圆中的这些间隙?

c - 为什么 execl 会覆盖文件

c - 从一个 header 结构到另一个 header 中的结构体

c - IP cidr匹配功能

rust - 在 sdl2 0.31.0 中找不到函数 `get_platform`