You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 19:23:14