GLSL #version语法错误求助(M2 Mac+LWJGL+OpenGL2.1)
OpenGL 2.1下GLSL着色器编译报错:syntax error: #version
环境信息
- Java版本:11
- 开发库:LWJGL
- 设备:M2 Mac
- OpenGL版本:2.1 Metal - 83.1
错误信息
编译GLSL着色器时触发如下错误:
Error compiling Shader code: ERROR: 0:1: '' : syntax error: #version
相关代码
Java着色器编译类
public class Shader { private int shaderProgramID; private boolean beingUsed = false; private String vertexSource; public Shader (int type, String path) { shaderProgramID = glCreateProgram(); StringBuilder builder = new StringBuilder(); try (InputStream in = new FileInputStream(path); BufferedReader reader = new BufferedReader(new InputStreamReader(in))) { String line; while ((line = reader.readLine()) != null) { builder.append(line).append("\n"); } } catch (IOException ex) { throw new RuntimeException("Failed to load a shader file!" + System.lineSeparator() + ex.getMessage()); } vertexSource = builder.toString(); } public void compile() { // ============================================================ // Compile and link shaders // ============================================================ int vertexID, fragmentID; // First load and compile the vertex shader int shaderId = glCreateShader(GL_VERTEX_SHADER); glShaderSource(shaderId, vertexSource); System.out.println(vertexSource); glCompileShader(shaderId); if (glGetShaderi(shaderId, GL_COMPILE_STATUS) == 0) { System.out.println("Error compiling Shader code: " + glGetShaderInfoLog(shaderId, 1024)); } glAttachShader(shaderProgramID, shaderId); glLinkProgram(shaderProgramID); if (glGetProgrami(shaderProgramID, GL_LINK_STATUS) == 0) { System.out.println("Error linking shader program: " + glGetProgramInfoLog(shaderProgramID)); } } public void use() { if (!beingUsed) { // Bind shader program glUseProgram(shaderProgramID); beingUsed = true; } } public int getAttributeLocation(CharSequence name) { return glGetAttribLocation(shaderProgramID, name); } public void detach() { glUseProgram(0); beingUsed = false; } }
GLSL顶点着色器代码
#version 120 core void main(){ realpos.x = (1920 / 2) + 40 * aPosition.x; realpos.y = (1000 / 2) + 40 * aPosition.y; }
问题说明
OpenGL 2.1对应GLSL版本120,尝试修改版本号会触发版本不兼容错误。该错误曾莫名消失后重现,已排查数小时未解决。
解决方案
1. 修正#version指令格式
GLSL 120(对应OpenGL 2.1)不支持core profile,将着色器第一行改为:
#version 120
core是GLSL 130(OpenGL 3.0)才引入的语法,旧版本编译器会把core识别为非法内容,导致版本指令解析失败。
2. 修复着色器未定义变量
当前着色器中的realpos和aPosition均未声明,且顶点着色器必须设置内置变量gl_Position,修正后的示例代码:
#version 120 // 声明顶点输入属性 attribute vec2 aPosition; void main(){ vec2 realpos = vec2(0.0); // 使用浮点运算避免整数除法问题 realpos.x = (1920.0 / 2.0) + 40.0 * aPosition.x; realpos.y = (1000.0 / 2.0) + 40.0 * aPosition.y; // 转换为OpenGL标准化设备坐标(NDC) gl_Position = vec4(realpos / vec2(1920.0, 1000.0) * 2.0 - 1.0, 0.0, 1.0); }
3. 检查文件编码与换行符
M2 Mac上的文件可能带有UTF-8 BOM编码,导致编译器读取着色器时第一行开头出现不可见字符,解析#version失败。用文本编辑器将着色器文件保存为UTF-8无BOM格式,同时确保换行符为LF(Unix风格)。
4. 修正Java着色器逻辑
当前Shader类混淆了单个着色器对象与program的创建逻辑,构造函数传入的type参数未被使用,调整后的代码示例:
public class Shader { private int shaderID; // 单个着色器ID private String shaderSource; // type为GL_VERTEX_SHADER或GL_FRAGMENT_SHADER public Shader(int type, String path) { shaderID = glCreateShader(type); StringBuilder builder = new StringBuilder(); try (InputStream in = new FileInputStream(path); BufferedReader reader = new BufferedReader(new InputStreamReader(in))) { String line; while ((line = reader.readLine()) != null) { builder.append(line).append("\n"); } } catch (IOException ex) { throw new RuntimeException("Failed to load shader file!\n" + ex.getMessage()); } shaderSource = builder.toString(); } public void compile() { glShaderSource(shaderID, shaderSource); glCompileShader(shaderID); if (glGetShaderi(shaderID, GL_COMPILE_STATUS) == 0) { System.err.println("Shader compile error: " + glGetShaderInfoLog(shaderID, 1024)); glDeleteShader(shaderID); throw new RuntimeException("Shader compilation failed"); } } // 单独创建program并链接多个着色器 public static int createProgram(Shader vertexShader, Shader fragmentShader) { int programID = glCreateProgram(); glAttachShader(programID, vertexShader.shaderID); glAttachShader(programID, fragmentShader.shaderID); glLinkProgram(programID); if (glGetProgrami(programID, GL_LINK_STATUS) == 0) { System.err.println("Program link error: " + glGetProgramInfoLog(programID)); glDeleteProgram(programID); throw new RuntimeException("Program linking failed"); } // 链接成功后删除临时着色器对象 glDeleteShader(vertexShader.shaderID); glDeleteShader(fragmentShader.shaderID); return programID; } // 其他方法调整为使用programID public static void use(int programID) { glUseProgram(programID); } public static int getAttributeLocation(int programID, CharSequence name) { return glGetAttribLocation(programID, name); } public static void detach() { glUseProgram(0); } }
该逻辑符合OpenGL标准工作流程,避免因对象混淆导致的编译/链接错误。
内容的提问来源于stack exchange,提问作者Owen Griffiths
相关产品推荐
相关产品推荐

