2016-09-13 9 views
-1

シェイダーを使用してプログラムを作成していて、ビルド済みのexeを実行しているときに何らかのエラーが発生しています。GLSLシェーダのリンカエラー?

シェーダプログラムは、フラグメントシェーダは、様々な色を使用しますが、以前のシェーダがそれに書き込まない

をリンクに失敗しました。

リソース不足エラー。

これは私のコードです:

example.cpp:

// Two-Dimensional Sierpinski Gasket  
// Generated using randomly selected vertices and bisection 

#include "Angel.h" 

const int NumTimesToSubdivide = 5; 
const int NumTetraeder = 1024; 
const int NumVertices = 9 * NumTetraeder; 

vec4 points[NumVertices]; 
int Index = 0; 

int fps = 20; 
float angle_param = 0.5; 

float etime; 
GLint time_loc; 

//---------------------------------------------------------------------------- 


void triangle(const vec4& a, const vec4& b, const vec4& c) 
{ 
    points[Index++] = a; 
    points[Index++] = b; 
    points[Index++] = c; 
} 

void divide_tetraeder(const vec4& a, const vec4& b, const vec4& c, const vec4& d, int count) 
{ 
    if(count > 0) 
    { 
     //compute midpoints 
     vec4 ab = (a + b)/2.0; 
     vec4 ac = (a + c)/2.0; 
     vec4 ad = (a + d)/2.0; 

     vec4 bc = (b + c)/2.0; 
     vec4 bd = (b + d)/2.0; 

     vec4 cd = (c + d)/2.0; 

     divide_tetraeder(a, ab, ac, ad, count -1); 
     divide_tetraeder(ab, b, bc, bd, count -1); 
     divide_tetraeder(ad, bd, cd, d, count -1); 
     divide_tetraeder(ac, bc, c, cd, count -1);   

    } 
    else 
    { 
     triangle(a,b,c); 
     triangle(b,d,c); 
     triangle(d,a,c); 
    } 
} 

void 
init(void) 
{ 
    // Specifiy the vertices for the initial tetraeder 

    vec4 vertices[4] = { 
     vec4( 0.0, -1.0, -1.0, 1.0), 
     vec4( 0.866, -1.0, 0.5, 1.0), 
     vec4( 0.0, 1.0, 0.0, 1.0), 
     vec4(-0.866, -1.0, 0.5, 1.0) 
    }; 


    divide_tetraeder(vertices[0], vertices[1], vertices[2], vertices[3], NumTimesToSubdivide); 

    // Create a vertex array object 
    GLuint vao; 
    glGenVertexArrays(1, &vao); 
    glBindVertexArray(vao); 

    // Create and initialize a buffer object 
    GLuint buffer; 
    glGenBuffers(1, &buffer); 
    glBindBuffer(GL_ARRAY_BUFFER, buffer); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW); 

    // Load shaders and use the resulting shader program 
    GLuint program = InitShader("../shader/vshader_03.glsl", "../shader/fshader_03.glsl"); 
    glUseProgram(program); 

    // Initialize the vertex position attribute from the vertex shader 
    GLuint loc = glGetAttribLocation(program, "vPosition"); 
    glEnableVertexAttribArray(loc); 
    glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0)); 

    //Initialize the time parameter 
    time_loc = glGetUniformLocation(program, "time"); 

    glClearColor(1.0, 1.0, 1.0, 1.0); // white background 
} 

//---------------------------------------------------------------------------- 

void 
display(void) 
{ 

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the window  
    glDrawArrays(GL_TRIANGLES, 0, NumVertices); // draw the points 
    glutSwapBuffers(); 
} 

//---------------------------------------------------------------------------- 

void 
keyboard(unsigned char key, int x, int y) 
{ 
    switch (key) { 
    case 033: 
     exit(EXIT_SUCCESS); 
     break; 
    } 
} 

void specialKeys(int key, int x, int y) 
{ 
    switch (key) { 
    case GLUT_KEY_UP: 
     fps += 1; 
     std::cout << "fps: " << fps << std::endl; 
     break; 

    case GLUT_KEY_DOWN: 
     if(fps > 1) fps -= 1; 
     std::cout << "fps: " << fps << std::endl; 
     break; 

    case GLUT_KEY_LEFT: 
     angle_param -= 0.05; 
     std::cout << "angle_param: " << angle_param << std::endl; 
     break; 

    case GLUT_KEY_RIGHT: 
     angle_param += 0.05; 
     std::cout << "angle_param: " << angle_param << std::endl; 
     break; 
    default: 
     break; 
    } 
} 

//---------------------------------------------------------------------------- 


void timer(int value){ 

    static float currentangle = 0.0f; 
    currentangle += angle_param; 

    float angle = currentangle*DegreesToRadians; // small angle in radians 

    //************************************************************** 
    //Füge hier deinen code ein, der die Punkte um die z-Achse dreht und neu zur Grafikkarte hochlädt 

    //Benutze die Funktion RotateY um eine 4x4 Rotationsmatrix zu erzeugen 
    mat4 rotMat = RotateY(angle); 

    //Berechne die rotierten Vertices auf der CPU durch Multiplikation mit der Matrix 
    for(int i = 0; i < NumVertices; i++) { 
     points[i] = rotMat * points[i]; 
    } 

    //Anzahl der Sekunden seit dem letzten Aufruf 
    //http://www.opengl.org/documentation/specs/glut/spec3/node70.html 
    etime = 0.001 * glutGet(GLUT_ELAPSED_TIME); 

    //Schicke diesen Wert zum Vertex Shader 
    glUniform1f(time_loc, etime); 

    //Sende alle Vertices erneut an die GPU 
    glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW); 

    //*******************************************************************/ 

    glutPostRedisplay(); 
    int delay = ceil(1000.0f/fps); 
    glutTimerFunc(delay,timer,0); 
} 

int 
main(int argc, char **argv) 
{ 

    glutInit(&argc, argv); 
    glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE); 
    //glEnable(GL_DEPTH_TEST); 
    glutInitWindowSize(512, 512); 

    // If you are using freeglut, the next two lines will check if 
    // the code is truly 3.2. Otherwise, comment them out 
    //glutInitContextVersion(3, 1); 
    //glutInitContextProfile(GLUT_CORE_PROFILE); 

    glutCreateWindow("Sierpinski Gasket"); 

    glewInit(); 

    init(); 

    glutDisplayFunc(display); 
    glutKeyboardFunc(keyboard); 
    glutSpecialFunc(specialKeys); 

    int delay = ceil(1000.0f/fps); 
    glutTimerFunc(delay,timer,0); 


    glutMainLoop(); 
    return 0; 
} 

InitShader.cpp:

#include "Angel.h" 

char vSource[] = "#version 130\n in vec4 vPosition;\nvoid main() {\n gl_Position = vPosition;\n}\n"; 
char fsource[] = "#version 130\n out vec4 color;\n void main() {\n color = vec4(1.0, 0.0, 0.0, 1.0);\n}\n"; 

namespace Angel { 

// Create a NULL-terminated string by reading the provided file 
static char* 
readShaderSource(const char* shaderFile) 
{ 
    //öffne die Datei 
    FILE* fp = fopen(shaderFile, "r"); 

    //wenn das nicht klappt, hör sofort auf 
    if (fp == NULL) { return NULL; } 

    //finde heraus wie groß in bytes die datei ist 
    //1. gehe zum ende der datei 
    fseek(fp, 0L, SEEK_END); 
    //2. frage nach der Größe 
    long size = ftell(fp); 

    //mache einen speicherbereich für den shadertext von ausreichender Größe 
    char* buf = new char[size + 1]; 

    //gehe zum Anfang der datei 
    fseek(fp, 0L, SEEK_SET); 

    //lies das erste Zeichen 
    char c; 
    c = fgetc(fp); 

    //initialisiere den index für den buffer 
    int i = 0; 

    //Solange das Ende der Datei nicht erreicht ist 
    while(c != EOF) 
    { 
     //Zeichen abspeichern 
     buf[i] = c; 
     //Nächstes Zeichen lesen 
     c = fgetc(fp); 
     //index für den Puffer inkrementieren 
     i++; 
    }  

    //Am Ende den Puffer mit 0 terminieren 
    buf[i] = '\0'; 

    //Datei schließen 
    fclose(fp); 

    //printf("buf is: %s",buf); 
    return buf; 
} 


// Create a GLSL program object from vertex and fragment shader files 
GLuint 
InitShader(const char* vShaderFile, const char* fShaderFile) 
{ 
    struct Shader { 
    const char* filename; 
    GLenum  type; 
    GLchar*  source; 
    } shaders[2] = { 
    { vShaderFile, GL_VERTEX_SHADER, NULL }, 
    { fShaderFile, GL_FRAGMENT_SHADER, NULL } 
    }; 

    GLuint program = glCreateProgram(); 


    for (int i = 0; i < 2; ++i) { 
     Shader& s = shaders[i]; 

     s.source = readShaderSource(s.filename); 
     if (shaders[i].source == NULL) { 
      std::cerr << "Failed to read " << s.filename << std::endl; 
      exit(EXIT_FAILURE); 
     } 

     /* 
     if(i==0) s.source = vSource; 
     else s.source = fsource; 
     */ 

     GLuint shader = glCreateShader(s.type); 

     glShaderSource(shader, 1, (const GLchar**) &s.source, NULL); 
     glCompileShader(shader); 

     GLint compiled; 
     glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); 
     if (!compiled) { 
      std::cerr << s.filename << " failed to compile:" << std::endl; 
      GLint logSize; 
      glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logSize); 
      char* logMsg = new char[logSize]; 
      glGetShaderInfoLog(shader, logSize, NULL, logMsg); 
      std::cerr << logMsg << std::endl; 
      delete [] logMsg; 

      exit(EXIT_FAILURE); 
     } 

     //delete [] s.source; 

     glAttachShader(program, shader); 
    } 

    /* link and error check */ 
    glLinkProgram(program); 

    GLint linked; 
    glGetProgramiv(program, GL_LINK_STATUS, &linked); 
    if (!linked) { 
    std::cerr << "Shader program failed to link" << std::endl; 
    GLint logSize; 
    glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logSize); 
    char* logMsg = new char[logSize]; 
    glGetProgramInfoLog(program, logSize, NULL, logMsg); 
    std::cerr << logMsg << std::endl; 
    delete [] logMsg; 

    exit(EXIT_FAILURE); 
    } 

    /* use program object */ 
    glUseProgram(program); 

    return program; 
} 

} // Close namespace Angel block 

vshader_03.glsl:

#version 130 

uniform float time; 
in vec4 vPosition; 
void main() 
{ 

    vec4 temp = vPosition; 
    temp.x *= (1+sin(time)); 
    gl_Position = temp; 
} 

fshader_03.glsl:

#version 130 
in vec4 color; 

void main() 
{ 
    gl_FragColor = color; 
} 
+3

シェーダの内容は何ですか?あなたのコードを簡単に見て、私はそれが文字列vSourceとfSourceだと思ったが、そうではないようだ。 – pleluron

+0

@pleluronがシェーダの内容を追加しました – herrh

答えて

6

あなたフラグメントシェーダは、様々な変数in vec4 colorを有しているが、先行シェーダステージのいずれも(あなたのケースで頂点シェーダ)が変化する出力out vec4 colorを定義しません。これはまた、エラーメッセージがあなたに語ったものです。解決策:あなたの頂点シェーダはout vec4 colorを定義し、そこに書き込む必要があります。

+0

うまく動作します。ありがとう! – herrh

関連する問題