OpenGL着色器编译问题 - 意外的EOF

rja*_*cks 9 opengl shader jogl

所以我决定尝试使用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;
}
Run Code Online (Sandbox Code Playgroud)

片段着色器也很简单,所以除非有人要求,否则我不会打扰它.当我检查日志时,我收到以下错误(对于两个着色器):

(0) : error C0000: syntax error, unexpected $end at token "<EOF>"
Run Code Online (Sandbox Code Playgroud)

我不确定这是否相关......但我正在使用Java在Linux(Ubuntu 11.04)上进行开发.我使用的唯一库是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<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;
    }
Run Code Online (Sandbox Code Playgroud)

顺便说一句,我检查glGetError()的if语句实际上并不是捕获错误的地方,直到执行返回到调用函数并且我检查着色器日志时才会发生.可能是相关的,但我可能也会漫无目的.

Nic*_*las 14

好的,现在我看到了问题.您的加载代码不起作用.但别担心; 很多人在看到glShaderSource采用字符串数组时会感到困惑.我猜你看到有人用C/C++写这样的着色器:

const char *myShader[] = {
    "#version 330\n",
    "\n",
    "in vec3 in_position;\n",
    ...
};
Run Code Online (Sandbox Code Playgroud)

他们上传了着色器, 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;...
Run Code Online (Sandbox Code Playgroud)

您的整个着色器被视为一个重要的单行注释.因此意外的EOF:OpenGL从来没有看到任何东西要编译;)

你不应该逐行阅读文件.只需将整个内容加载到一个字符串中即可.然后将其传递给OpenGL.或者,您可以查看以前关于JOGL的答案 ; 它应该告诉你如何正确地执行它(虽然我希望BufferedReader有一些方法可以将整个文件作为字符串而不是逐行读取.