2017-04-15 6 views
1

현재 OpenGl 및 C++를 사용하여 기본 그래픽 엔진을 작성하려고합니다. 그렇게함으로써, OpenGl은 명백한 설명없이 매우 이상한 방식으로 행동합니다. 그것은 셰이더가 컴파일에 실패했지만, 그 이유를 설명하는 어떤 종류의 오류도주지 않기를 요구합니다. 특히 glGetProgramiv을 호출하면 반환 값은 0이지만 glGetProgramInfoLog은 빈 문자열을 제공합니다 .¹.glGetProgramIv는 셰이더 연결이 실패했지만 glGetProgramInfoLog가 비어 있다고 주장합니다.

#include <SDL2/SDL.h> 
#include <GL/glew.h> 
#include <sstream> 
#include <stdexcept> 
#include <fstream> 

GLuint loadShader(const std::string &path, GLenum type); 

int main(int argc, char *argv[]){ 
    //show window & other housekeeping 
    SDL_Init(SDL_INIT_EVERYTHING); 
    SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); 
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); 
    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); 
    SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); 
    SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32); 
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); 
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); 
    SDL_Window *window = SDL_CreateWindow("test window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); 
    SDL_GLContext glContext = SDL_GL_CreateContext(window); 
    SDL_GL_MakeCurrent(window, glContext); 
    GLenum c = glewInit(); 
    if(c != GLEW_OK){ 
     std::ostringstream sout; 
     sout << "Failed to initialize OpenGl: " << glewGetErrorString(c); 
     throw std::runtime_error(sout.str()); 
    } 

    //**** -- BEGIN IMPORTANT BIT -- ****// 
    //This is where the shaders are loaded 

    //load shaders 
    GLuint vertexShader = loadShader("shader.vert", GL_VERTEX_SHADER); 
    GLuint fragmentShader = loadShader("shader.frag", GL_FRAGMENT_SHADER); 

    //create & link program 
    GLuint program = glCreateProgram(); 
    glAttachShader(program, vertexShader); 
    glAttachShader(program, fragmentShader); 
    glLinkProgram(program); 

    //check for errors 
    GLint success; 
    glGetProgramiv(program, GL_LINK_STATUS, &success); 
    if(!success){ 
     GLchar infoLog[512]; 
     GLint size; //gives 0 when checked in debugger 
     glGetProgramInfoLog(program, 512, &size, infoLog); 
     throw std::runtime_error(std::string("Failed to link shader program: ") + infoLog); 
    } 

    //cleanup 
    glDeleteShader(vertexShader); 
    glDeleteShader(fragmentShader); 

    //**** -- END IMPORTANT BIT -- ****// 

    //update loop 
    bool isClosed = false; 
    while(!isClosed){ 
     SDL_GL_SwapWindow(window); 

     SDL_Event e; 
     while(SDL_PollEvent(&e)){ 
      switch(e.type){ 
       case SDL_QUIT: 
        isClosed = true; 
        break; 
      } 
     } 
    } 
} 

GLuint loadShader(const std::string &path, GLenum type){ 
    //load file 
    std::ifstream fin(path); 
    std::string line, total = ""; 

    while(std::getline(fin, line)){ 
     total += (line + "\n"); 
    } 

    //reformat source into OpenGl's ridiculous format 
    const char *cArray = total.c_str(); 
    const char **pointerToCArray = &cArray; 

    //create shader 
    GLuint shader = glCreateShader(type); 
    glShaderSource(shader, 1, pointerToCArray, nullptr); 
    glCompileShader(shader); 

    //check for erros 
    GLint success; 
    glGetShaderiv(shader, GL_COMPILE_STATUS, &success); 
    if(!success){ 
     GLchar infoLog[512]; 
     glGetShaderInfoLog(shader, 512, nullptr, infoLog); 
     throw std::runtime_error(std::string("Failed to compile shader: ") + infoLog); 
    } 
} 

MCVE의 testshader.vert :

#version 330 core 

layout (location = 0) in vec3 position; 

void main() 
{ 
    gl_Position = vec4(position.x, position.y, position.z, 1.0); 
} 

MCVE의 testshader.frag : 여기

는 최소한의 완전하고 검증 예입니다 내가 이것을 실행하면

#version 330 core 

out vec4 color; 

void main() 
{ 
    color = vec4(1.0f, 0.5f, 0.2f, 1.0f); 
} 

내가 얻을 다음과 같은 출력은 창을 잠깐 깜박이는 것 외에도

terminate called after throwing an instance of 'std::runtime_error' 
    what(): Failed to link shader program: 
Aborted (core dumped) 

추가 참고 :

  • 내가 드라이버 버전 375.39
  • SDL과 glew 버전으로 엔비디아의 GTX 1070을 사용하고
  • 64 우분투 16.10를 사용하고는있는 libsdl2-dev에서 설치 그와 libglew-dev 개의 패키지가 있습니다. 링크를 위해 pkg-config를 사용하고 있습니다.

이 오류를 해결하기 위해 다른 사람들의 코드에서 특정 오류를 발견 한 다양한 포럼과 StackOverflow 게시물을 발견했습니다. 이들 중 아무 것도 내 코드에 적용되지 않으며이 오류를 발견 한 후 코드를 this과 비교했을 것입니다. 또한이 예제는 컴퓨터에서 올바르게 컴파일되고 실행되므로 모든 종류의 구성 오류가 발생하지 않습니다.

는 ¹ : glGetProgramInfoLoginfoLog 배열의 첫 번째 주소에 널 (NULL) 종료 문자로 할당 할 수 있었던 것을 외부 결과와 아무것도하지 않고 것이 가능하지 않다 때문에로 설정 한 경우에도 glGetProgramInfoLog 0을 반환의 크기 반환 glGetProgramInfoLog 전에 다른 값이 호출됩니다.

답변

0

loadShader() 메서드에서 return 문이 누락되었습니다. 그러나이 문제를 해결하려고 시도했을 때 경험했던 것처럼 이것은 도움이되지 못했습니다. 따라서 앞으로 어떤 사람이 시도하고있는 것과 비슷한 작업을 수행하고 점진적으로 코드의 작은 부분을 자신의 것으로 복사하거나 붙여 넣는 작업 예제 (예 : this)를 읽는 것이 좋습니다. 그 반대의 경우) 이진 검색을 수행하여 오류를 찾습니다.

+0

'-Wall -Wextra '로 경고를 사용하면 도움이되었습니다. – HolyBlackCat