2011-06-19 29 views
9

私はJavaを使って単純なOpenGLアプリケーションを書くことにしました。これは私の他の取り組みとどのように比較されているのか分かりませんし、シェイダーがコンパイルを拒否する問題に遭遇しています。OpenGLシェーダのコンパイルの問題 - 予期しないEOF

//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 "<EOF>" 

私はこれが関連しているかわからない...しかし、私は、Javaを使用してLinux(Ubuntuの11.04)上で開発しています。私が使用している唯一のライブラリはJOGL(OpenGLバインディング用)と標準のJavaライブラリです(それが重要であれば...)私のグラフィックスカードはNvidia GeForce 9600M GSで、拡張機能をチェックしました。 OpenGL 3.3。

私がスタックオーバーフローを助けてください、あなたは私の唯一の希望です。

EDIT:

要求されたとして、ここではロードとシェーダのソースをコンパイルするための責任がある関数です。また、GLSLに関しては、私はスーパーn00bだから、OpenGLのために適切に書式が設定されているかどうかを確認するのは本当にわかりません。このテーマに関する最近の(すなわち、OpenGL 3.xを扱う)チュートリアルへのリンクが評価されます。余談として

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

     BufferedReader input = null; 
     ArrayList<String> lines = new ArrayList<String>(); 
     ArrayList<Integer> lengths = new ArrayList<Integer>(); 
     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文)は、エラーが呼び出し元の関数に実行戻るまで起こると私は確認されませんので、引っ掛かり実際にどこではありませんシェーダーログ。関連性があるかもしれませんが、再び私は散歩することもできます。

+0

最後の括弧の後に空行を追加してみてください。 – Kromster

+0

これは私が試した最初のものの1つでしたが、コードを投稿したときには表示されませんでした。 – rjacks

答えて

13

[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つの大きな1行コメントとみなされます。したがって、予期しないEOF:OpenGLは何もコンパイルすることを見なかった;)

ファイルを1行ずつ読むべきではない。全体を単一の文字列にロードするだけです。その後、OpenGLに渡します。あるいは、JOGLについてthis previous answerを見ることができます。 (これは、BufferedReaderがファイル全体を行単位ではなく文字列として読み取ることを望むでしょうが)、

+0

Aha!それは理にかなっている。私はこのプロジェクトをC/C++で前に行っています。この関数がString []を受け取ったことをJavadocで見たとき、何とかchar * == String [](これは明らかに正しくありません)と仮定しました。役に立つ答えをありがとう。 – rjacks

1

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

また、ファイルの最後に余分な空白行を入れてみてください。再び、確かに。

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

+1

また、ファイルの先頭にBOMがないことを確認することもできます。 (ほとんどのエディタがあなたから隠してくれる3バイトのことですが、それはラテン文字だけを使用していても、ファイル内のUnicodeエンコーディングを定義します) – Kromster

3

回答は既に提供されていますが、私はちょうど私がそれを好む方法をここに書きます:

// 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ブロックarroundにして、シェーダのOpenGLオブジェクトをクリーンアップすることはできません。

+0

もしあなたがJavaでプログラミングしていないが、ポインタ(C、C++、D、Go)を持つ言語で書かれているのであれば、もう一つの実行可能な方法はファイルをバッファに読み込むのではなくメモリマップすることです。 – datenwolf

+0

このコードは*より良い... です。もう一度、ありがとう。 – rjacks

関連する問題