2017-04-15 7 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のバージョンでのNvidia GTX 1070を使用しています
  • のx64のUbuntu 16.10を使用していますが、あるlibsdl2-devからインストールしたものとそれぞれlibglew-devパッケージ。私はリンクするためにpkg-configを使用しています。

このエラーを解決するための私の研究では、私は主にさまざまなフォーラムやStackOverflowの投稿を見て、他の人のコードで特定のエラーを見つけました。これらのどれも私のコードには当てはまりません。このエラーを見つけた後、コードをthisのコードと比較しました。この例もコンパイルされ、コンピュータ上で正常に動作します。

は¹:glGetProgramInfoLoginfoLog配列は、その最初のアドレスにNULL終止符文字で割り当てられることが起こったことを外部の影響で何もしないとされていることは不可能であるために設定されていてもglGetProgramInfoLog 0を返すのサイズリターンglGetProgramInfoLogの前に異なる値が呼び出されます。

答えて

0

loadShader()メソッドでreturn文が見つからないという問題が見つかりました。しかし、これを解決しようとしたときに経験したように、これは役に立たなかった。このように、私はあなたがしようとしているものと似たような何かを行い、徐々にあなたのコードの小さな部分をあなたのものにコピー/貼り付けている実例(すなわち、this)逆もあります)、あなたのエラーを見つけるための一種のバイナリ検索を行います。

+0

'-Wall -Wextra'で警告が有効になっていました。 – HolyBlackCat

関連する問題