问题描述
因此,我决定尝试使用Java编写一个简单的OpenGL应用程序,以了解它与我的其他工作相比如何,而且我遇到了着色器拒绝编译的问题.它们真的无法简单得多,这是我的顶点着色器,用于演示我的意思:
So I decided to try writing a simple OpenGL app using Java, just to see how it compared to my other efforts, and I'm running into an issue where my shaders refuse to compile. They really couldn't get much simpler, here's my vertex shader to demonstrate what I mean:
//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;
}
片段着色器非常简单,因此除非有人要求,否则我不会费心发布它.当我检查日志时,我得到以下错误(对于两个着色器):
The fragment shader is just as simple, so I won't bother posting it unless someone asks for it. When I check the logs, I get back the following error (for both shaders):
(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.
I'm not sure this is relevant... but I'm developing on Linux (Ubuntu 11.04) using Java. The only libraries I'm using are JOGL (for the openGL bindings) and the standard Java library (if that even counts...) My graphics card is a Nvidia GeForce 9600M GS, and I checked the extensions and it has full support for OpenGL 3.3.
帮我堆栈溢出,您是我唯一的希望.
Help me Stack Overflow, you're my only hope.
根据要求,这里是负责加载和编译着色器源的函数.另外,在GLSL方面,我是超级n00b,所以我真的不知道要查找的内容,只要确保为OpenGL正确格式化即可.链接到有关该主题的最新(即处理OpenGL 3.x)教程的链接.
As requested, here is the function that is responsible for loading and compiling the shader source. Also, when it comes to GLSL I'm a super n00b, so I really don't know what to look for as far as making sure things are formatted properly for OpenGL. A link to a recent (i.e. dealing with OpenGL 3.x) tutorial on the subject would be appreciated.
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语句实际上不是捕获错误的位置,直到执行返回到调用函数并且我检查着色器日志.可能是相关的,但话又说回来,我也可能漫步.
As an aside, the if statement towards the end where I check glGetError() isn't actually where the error gets caught, that doesn't happen until execution returns to the calling function and I check the shader logs. Could be relevant, but then again I could also be rambling.
推荐答案
好的,现在我看到了问题.您的加载代码无效.但是不用担心;当很多人看到glShaderSource需要一个字符串数组时,就会感到困惑.我猜想您看到有人用C/C ++这样编写着色器:
OK, now I see the problem. Your loading code doesn't work. But don't worry; a lot of people get confused when they see that glShaderSource takes an array of strings. I'm guessing that you saw someone write their shaders in C/C++ like this:
const char *myShader[] = {
"#version 330\n",
"\n",
"in vec3 in_position;\n",
...
};
然后他们用glShaderSource(shader, ARRAY_COUNT(myShader), myShader, NULL, 0);
虽然这是合法的,但实际上并不是该功能的目的.由于GLSL没有#include机制,因此glShaderSource可以采用多个字符串.每个字符串均应为着色器文件.然后,着色器编译器像在编译之前#include一样有效地将字符串连接在一起.
While this is legal, that's not really what the feature is for. Because GLSL does not have a #include mechanism, glShaderSource can take multiple strings. Each string is intended to be a shader file. The shader compiler then effectively concatenates the strings together like #include does before compiling.
现在,由于这个原因,您可以将每一行作为单独的字符串.但是,请回顾该C/C ++代码.看看每一行的末尾是什么?那个'\ n'字符.
Now, because of this, you can have each line as a separate string. However, look back that that C/C++ code. See what is at the end of each line? That '\n' character.
这就是您正在加载的行末尾的 not .因为我很确定BufferedReader.readline不会不保留行尾字符.所以您的着色器看起来像:
That's what is not at the end of the lines you are loading. Because I'm pretty sure BufferedReader.readline does not keep the end-of-line character. So your shader looks like:
//Minimal vertex shader#version 330in vec3 in_Position;in vec3 in_Color;out vec3 var_Color;...
您的整个着色器被视为一个大的单行注释.因此出现了意外的EOF:OpenGL从来没有看到过要编译的东西;)
Your entire shader is seen as one big single-line comment. Hence the unexpected EOF: OpenGL never saw anything to compile ;)
您不应该逐行读取文件.只需将整个内容加载到单个字符串中即可.然后将其传递给OpenGL.或者,您可以查看关于JOGL的此先前答案;它应该显示如何正确执行操作(尽管我希望BufferedReader可以通过某种方式将整个文件读取为字符串,而不是逐行读取.
You shouldn't be reading the file line by line. Just load the whole thing up into a single string. Then pass it to OpenGL. Alternatively, you can look at this previous answer about JOGL; it should show you how to do it correctly (though I would hope that BufferedReader would have some way to read the whole file as a string rather than line-by-line.
这篇关于OpenGL Shader编译问题-意外的EOF的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!