2016-10-13 7 views
-1

Qt OpenGLアプリケーションの作成を開始します。そして、私はLearnopenglからチュートリアルに従いました。このチュートリアルでは、頂点とフラグメントのシェーダーに対応する静的なC-Stringを提供します。アプリケーションに静的C文字列シェーダを渡すと、エラーはなく、三角形が画面に表示されます。ファイルからglslコードを読み取ることができません

しかし、私は別々のファイルにすべてのシェーダコードを処理しようとすると、私のようながgl_Positionここ

に書き込む必要がありますglLinkProgramコマンド中にエラーが発生している私のC++コードです:

#include "widget.h" 

Widget::Widget(QOpenGLWidget *parent) 
: QOpenGLWidget(parent) 
{ 
    this->setWindowTitle("Learning OpenGL"); 
    QString pathV="shaders/main.vert"; 
    QString pathF="shaders/main.frag"; 
    vertexShaderSource=loadShader(pathV); 
    fragmentShaderSource=loadShader(pathF); 
} 

Widget::~Widget() 
{ 

} 
void Widget::initializeGL() 
{ 
    this->initializeOpenGLFunctions(); 
    qDebug()<<"Vous travaillez sur une OpenGL version:"<<QString((char*)glGetString(GL_VERSION)); 
    compileShaders(); 
    glClearColor(0.0,0.0,0.0,1.0); 
    glClear(GL_COLOR_BUFFER_BIT); 

} 
void Widget::paintGL() 
{ 

    GLfloat vertices[] = { 
    -0.5f, -0.5f, 0.0f, 
    0.5f, -0.5f, 0.0f, 
    0.0f, 1.0f, 0.0f 
    }; 
    GLuint VBO,VAO; 
    glGenVertexArrays(1, &VAO); 
    glGenBuffers(1, &VBO); 
    // Bind the Vertex Array Object first, then bind and set vertex buffer(s) and attribute pointer(s). 
    glBindVertexArray(VAO); 

    glBindBuffer(GL_ARRAY_BUFFER, VBO); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); 
    glEnableVertexAttribArray(0); 

    glBindBuffer(GL_ARRAY_BUFFER, 0); // Note that this is allowed, the call to glVertexAttribPointer registered VBO as the currently bound vertex buffer object so afterwards we can safely unbind 

    glBindVertexArray(0); // Unbind VAO (it's always a good thing to unbind any buffer/array to prevent strange bugs) 
    // Draw our first triangle 
    glUseProgram(shaderProgram); 
    glBindVertexArray(VAO); 
    glDrawArrays(GL_TRIANGLES, 0, 3); 
    glBindVertexArray(0); 

} 
QString Widget::loadShader(QString &path) 
{ 
    QFile file(path); 
    file.open(QIODevice::ReadOnly); 
    QTextStream stream(&file); 
    QString lines; 
    while(!stream.atEnd()) 
    { 
     lines.append(stream.readLine()+"\n"); 
    } 
    //lines.append('\0'); 
    file.close(); 
    return lines; 
} 
void Widget::compileShaders() 
{ 

    /* //Static shaders 
    // Shaders 
    vs = "#version 330 core\n" 
     "layout (location = 0) in vec3 position;\n" 
     "void main()\n" 
     "{\n" 
     "gl_Position = vec4(position.x, position.y, position.z, 1.0);\n" 
     "}\0"; 
    fs = "#version 330 core\n" 
    "out vec4 color;\n" 
    "void main()\n" 
    "{\n" 
    "color = vec4(0.0f, 1.0f, 0.0f, 1.0f);\n" 
    "}\n\0"; 

    //*/ 
    //Vertex shader 
    GLuint vertexShader; 
    vertexShader = glCreateShader(GL_VERTEX_SHADER); 
    vs=vertexShaderSource.toStdString().c_str(); 
    glShaderSource(vertexShader, 1,(const GLchar **) &vs, 0); 
    glCompileShader(vertexShader); 
    //check if any error during compilation 
    GLint success; 
    GLchar infoLog[512]; 
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); 
    if(!success) 
    { 
     glGetShaderInfoLog(vertexShader, 512, NULL, infoLog); 
     qDebug()<< "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog ; 
    } 
    else qDebug()<<"compile vertex ok"; 
    //Fragment shader 
    GLuint fragmentShader; 
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); 
    fs=fragmentShaderSource.toStdString().c_str(); 
    glShaderSource(fragmentShader, 1,(const GLchar **) &fs, 0); 
    glCompileShader(fragmentShader); 
    //Check if any error during compilation 
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); 
    if(!success) 
    { 
     glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog); 
     qDebug()<< "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog ; 
    } 
    else qDebug()<<"compile fragment ok"; 

    shaderProgram = glCreateProgram(); 
    glAttachShader(shaderProgram, vertexShader); 
    glAttachShader(shaderProgram, fragmentShader); 
    glLinkProgram(shaderProgram); 
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); 
    if(!success) { 
     glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog); 
     qDebug()<< "Linkage error\n" << infoLog; 
    } 

} 
は、

シェーダファイルから読み込んだデータをコンソールに表示すると、スタティックC-Stringシェーダコードと同じになります。

シェーダファイルが壊れている理由はわかりません。

+0

ファイルを1行ずつ読み込むのは、ファイルを一度に読み込むよりも遅いでしょうか? 'QTextStream'は' readAll'と呼ばれる便利な機能を持っています。 –

答えて

0

このコード:文字列の一時的なコピーで

fragmentShaderSource.toStdString() 

結果、このような何かを試してみてください。その一時的なものは、それを生成する式の後に破棄されます。したがって、その文字列にc_str()を呼び出すと、削除しようとしているメモリへのポインタが表示されます。

代わりにfragmentShaderSourceなどの頂点シェーダタイプは、それ自体がstd::stringである必要があります。そのため、loadShaderは、std::stringを返します(linesの代わりにlines.toStdString()を返します)。

完了したら、fragmentShaderSource.c_str()を自由にOpenGLに渡すことができます。

+0

はい、あなたは正しいです。ありがとう –

0

シェーダーのソースが空であるか無効であるようです。おそらくそのあなたが/対FS変数に一時コピーバッファを割り当てているという事実によるもの:、これらのポインタは、おそらく、これらの行の後に無効と右になります

vs=vertexShaderSource.toStdString().c_str(); 
fs=fragmentShaderSource.toStdString().c_str(); 

のでglShaderSource関数に渡すことではないかもしれません最高のアイデア。

バッファの内容をコピーする必要があります。

char* vs = new char[vertexShaderSource.size() + 1]; 
strcpy(vs, vertexShaderSource.toStdString().c_str()); 
+0

あなたの診断は正しいです。解決策はありません。 –

関連する問題