OpenGLシェーダーコンパイルの問題-予期しないEOF

jogl opengl shader
OpenGLシェーダーコンパイルの問題-予期しないEOF

そこで、私はJavaを使用して簡単なOpenGLアプリを作成することを決めました。他の取り組みと比較して、シェーダーがコンパイルを拒否する問題に直面しています。 彼らは本当に簡単にすることができませんでした、ここに私の意味を示すための私の頂点シェーダーがあります:

//Minimal vertex shader

#version 330

in vec3 in_Position;
in vec3 in_Color;
out vec3 var_Color;

void main(void)
{
    gl_Position = vec4(in_Position, 1.0);
    var_Color = in_Color;
}

フラグメントシェーダーも同様に単純なので、誰かがそれを求めない限り、それを投稿することはありません。 ログを確認すると、次のエラーが返されます(両方のシェーダーに対して):

(0) : error C0000: syntax error, unexpected $end at token ""

これが関連するかどうかはわかりません…​ しかし、私はJava(Ubuntu 11.04)でJavaを使用して開発しています。 私が使用しているライブラリは、JOGL(openGLバインディング用)と標準Javaライブラリ(それも重要な場合)です。私のグラフィックカードはNvidia GeForce 9600M GSであり、拡張機能をチェックし、 OpenGL 3.3。

Stack Overflowを手伝ってください、あなたは私の唯一の希望です。

編集:

要求に応じて、シェーダーソースのロードとコンパイルを行う関数を次に示します。 また、GLSLに関して言えば、私はスーパーn00bなので、OpenGL用に適切にフォーマットされていることを確認する限り、何を探すべきか本当に分かりません。 最近の(つまり、 OpenGL 3.xを扱う)このテーマに関するチュートリアルをいただければ幸いです。

private int CreateCompiledShader(File source, int shader, GL3 gl){
        int shaderloc = gl.glCreateShader(shader);

        BufferedReader input = null;
        ArrayList lines = new ArrayList();
        ArrayList lengths = new ArrayList();
        try{
            input = new BufferedReader(new FileReader(source));
            String buffer;

            while(input.ready()){
                buffer = input.readLine();
                lines.add(buffer);
                lengths.add(buffer.length());
            }
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            if(input != null){
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        int[] iLengths = new int[lengths.size()];
        for(int i = 0; i < lengths.size(); i++){
        iLengths[i] = lengths.get(i).intValue();
        }

        gl.glShaderSource(shaderloc, lines.size(), lines.toArray(new String[0]), iLengths, 0);
        gl.glCompileShader(shaderloc);

        int error = gl.glGetError();
        if(error != GL3.GL_NO_ERROR){
            Logger.log(new GLU().gluErrorString(error), Logger.ERROR, "Shader compilation");
        }

        return shaderloc;
    }

余談ですが、glGetError()をチェックする最後のifステートメントは、実際にエラーがキャッチされる場所であり、実行が呼び出し元の関数に戻り、シェーダーログをチェックするまで発生しません。 関連する可能性がありますが、再び私はとりとめのないこともできます。

  9  4


ベストアンサー

OK、問題が発生しました。 読み込みコードが機能しません。 しかし、心配しないでください。 glShaderSourceが文字列の配列を受け取っていることに気付くと、多くの人が混乱します。 私はあなたが誰かがこのようなC / C ++でシェーダーを書くのを見たと推測しています:

const char *myShader[] = {
    "#version 330\n",
    "\n",
    "in vec3 in_position;\n",
    ...
};

そして、「glShaderSource(shader、ARRAY_COUNT(myShader)、myShader、NULL、0);」でシェーダーをアップロードしました

これは合法ですが、実際には機能の目的ではありません。 GLSLには#includeメカニズムがないため、glShaderSourceは複数の文字列を取ることができます。 各文字列は、_シェーダーファイル_であることが意図されています。 シェーダーコンパイラーは、#includeがコンパイルする前に行うように、文字列を効果的に連結します。

これにより、各行を個別の文字列として使用できます。 ただし、そのC / C ++コードを振り返ってください。 各行の末尾にあるものを参照してください? その ‘\ n’文字。

これが、ロードする行の最後に「ない」ことです。 BufferedReader.readlineが行末文字を保持しないことは確かだからです。 したがって、シェーダーは次のようになります。

//Minimal vertex shader#version 330in vec3 in_Position;in vec3 in_Color;out vec3 var_Color;...

シェーダー全体は、1つの大きな単一行コメントとして表示されます。 したがって、予期しないEOF:OpenGLはコンパイルするものを見ませんでした;)

行ごとにファイルを読むべきではありません。 すべてを単一の文字列にロードするだけです。 次に、OpenGLに渡します。 または、JOGLについてhttps://stackoverflow.com/questions/428225/jogl-shader-programming [この前の回答]をご覧ください。それを正しく行う方法を示す必要があります(ただし、BufferedReaderがファイル全体を行ごとではなく文字列として読み取る方法があることを願っています。

13


答えはすでに提供され受け入れられていますが、私はここで私がそれを好む方法を書きます:

// Create shader from one or multiple source files
private int CreateCompiledShader(File[] source_files, int shader, GL3 gl){
    int shaderloc = gl.glCreateShader(shader);
    int nSources = source_files.size();

    // the number of shader sources it known from the beginning
    // so we can allocate the arrays right here
    String[] sources = new String[nSources];
    int[] sources_lengths = new int[nSources];
    for(int i = 0; i < nSources; i++) {
        // We don't need a buffered reader as we're reading the file as a whole
        FileReader input = new FileReader(source_file[i]);
        String buffer;

        buffer = input.read();
        sources[i] = buffer;
        sources_lengths[i] = buffer.length();

        if(input != null){
            input.close();
        }
    }

    // Frankly I really don't understand why you have to pass sources_lengths here
    // It would take only 3 LOC in the binding's code
    // to extract that from the sources array, Oh, well...
    gl.glShaderSource(shaderloc, nSources, sources, sources_lengths, 0);
    gl.glCompileShader(shaderloc);

    // Actually if glGetError() returns an error you must call it in a loop
    // as OpenGL errors can accumulate, and you have to pop them all from the list.
    int error = gl.glGetError();
    if(error != GL3.GL_NO_ERROR){
        Logger.log(new GLU().gluErrorString(error), Logger.ERROR, "Shader compilation");
    }

    return shaderloc;
}

少し置き違いがあったため、すべてのtry / catch / finallyブロックを削除するために自由を取りました。ソースファイルの読み取りに失敗すると、シェーダーの読み込みが完了できません。 これに対処する適切な方法は、この周辺の大きなtry / catchブロックで、シェーダーコンパイルのOpenGLオブジェクトをクリーンアップしないことです。

3


#version宣言の後にコメントを移動してみてください。 問題ではありませんが、ドライバーのバグが存在する可能性があります。

また、ファイルの最後に余分な空行を入れてみてください。 繰り返しますが、念のためです。

最後に、実際に文字列を適切にロードしていることを確認してください。 デバッガで確認してください。 そして、OpenGLに文字列を正しく渡していることを確認してください。 そのコードはどのように見えますか?

1


タイトルとURLをコピーしました