使用SDL2& Glew,尝试在OpenGL中绘制一个简单的白色方块。刚搞黑屏

时间:2014-09-06 05:38:51

标签: 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;
}

1 个答案:

答案 0 :(得分:3)

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

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核心配置文件。根据{{​​3}},现在可能发生以下情况:

  

如果请求版本3.1,则返回的上下文可以实现任何一个   以下版本:

     
      
  • 版本3.1。 GL_ARB_compatibility扩展可能会也可能不会实现,具体取决于实现。
  •   
  • 版本3.2或更高版本的核心配置文件。
  •   

所以你很有可能获得一些没有兼容性功能的现代环境,这带来了第二个缺陷:你没有使用WGL_ARB_create_context_specification。这些是现代OpenGL中的强制。您使用的教程可能会在GL实现返回带有兼容性扩展的GL 3.1上下文的几台机器上偶然使用,但绝不保证可以正常工作。

我建议您使用更准确的教程,例如Vertex Array Objects (VAOs)Learning Modern 3D Graphics Programming。后者也有一个 open.gl,尽管使用的窗口和上下文创建库对于学习OpenGL并不是很重要。