所以我决定尝试使用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 "<EOF>"
我不确定这是否相关......但我正在使用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;
}
顺便说一下,我检查glGetError()的结尾的if语句实际上不是错误被捕获的地方,直到执行返回到调用函数并且我才发生检查着色器日志。可能是相关的,但话又说回来,我也可能是漫无边际的。
答案 0 :(得分:13)
好的,现在我看到了问题。您的加载代码不起作用。但别担心;很多人在看到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;...
您的整个着色器被视为一个重要的单行注释。因此意外的EOF:OpenGL从未见过任何可编译的内容;)
您不应该逐行阅读文件。只需将整个内容加载到一个字符串中即可。然后将其传递给OpenGL。或者,您可以查看有关JOGL的this previous answer;它应该告诉你如何正确地执行它(虽然我希望BufferedReader有一些方法可以将整个文件作为字符串而不是逐行读取。
答案 1 :(得分: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块来清理着色器编译的OpenGL对象。
答案 2 :(得分:1)
尝试在#version声明之后移动注释。这应该没关系,但可能存在驱动程序错误。
另外,尝试在文件末尾添加一个空行。再次,只是为了确定。
最后,请确保您实际上正确加载了字符串。在调试器中检查它。并确保您正确地将字符串传递给OpenGL。那段代码是什么样的?