0

0

LWJGL 3 渲染失败的根源:缺少着色器程序(Shader Program)

霞舞

霞舞

发布时间:2026-01-29 11:16:21

|

576人浏览过

|

来源于php中文网

原创

LWJGL 3 渲染失败的根源:缺少着色器程序(Shader Program)

lwjgl 3 使用 opengl core profile 时必须显式编写并绑定顶点/片元着色器,否则即使 vao/vbo 正确创建,gpu 也无法执行任何渲染指令——这是导致“窗口可见但画面全黑”的最常见原因。

在你的代码中,ModelLoader 和 Renderer 虽然正确完成了 VAO/VBO 的创建、绑定与数据上传,也调用了 glDrawArrays,但整个渲染管线缺失最关键的一环:着色器程序(Shader Program)。OpenGL Core Profile(你通过 GLFW_OPENGL_CORE_PROFILE 启用)已完全移除了固定功能管线(Fixed-Function Pipeline),不再支持 glBegin/glEnd 或默认的顶点变换与颜色输出逻辑。所有顶点处理和像素生成都必须由用户提供的 GLSL 着色器控制。

✅ 必须补充的核心组件

你需要添加以下三部分:

1. 着色器源码(建议存为 vertex.glsl 和 fragment.glsl)

vertex.glsl

#version 150 core

in vec3 position;

void main() {
    gl_Position = vec4(position, 1.0);
}

fragment.glsl

知了zKnown
知了zKnown

知了zKnown:致力于信息降噪 / 阅读提效的个人知识助手。

下载
#version 150 core

out vec4 outColor;

void main() {
    outColor = vec4(1.0, 0.0, 0.0, 1.0); // 红色三角形
}
⚠️ 注意:#version 150 core 必须与你请求的 OpenGL 上下文版本(3.2)兼容;LWJGL 3.2+ 默认支持 GLSL 150(对应 OpenGL 3.2)。

2. 着色器加载与编译工具类(例如 ShaderProgram.java

package core;

import org.lwjgl.system.MemoryUtil;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import static org.lwjgl.opengl.GL20.*;

public class ShaderProgram {
    private final int programID;

    public ShaderProgram(String vertexPath, String fragmentPath) {
        int vertexShader = compileShader(GL_VERTEX_SHADER, readFile(vertexPath));
        int fragmentShader = compileShader(GL_FRAGMENT_SHADER, readFile(fragmentPath));

        programID = glCreateProgram();
        glAttachShader(programID, vertexShader);
        glAttachShader(programID, fragmentShader);
        glLinkProgram(programID);

        if (glGetProgrami(programID, GL_LINK_STATUS) == GL_FALSE) {
            throw new RuntimeException("Shader linking failed: " + glGetProgramInfoLog(programID));
        }

        glDeleteShader(vertexShader);
        glDeleteShader(fragmentShader);
    }

    private int compileShader(int type, String source) {
        int shader = glCreateShader(type);
        glShaderSource(shader, source);
        glCompileShader(shader);

        if (glGetShaderi(shader, GL_COMPILE_STATUS) == GL_FALSE) {
            throw new RuntimeException("Shader compilation failed: " + glGetShaderInfoLog(shader));
        }
        return shader;
    }

    private String readFile(String path) {
        try {
            return Files.readString(Paths.get(path));
        } catch (IOException e) {
            throw new RuntimeException("Failed to read shader file: " + path, e);
        }
    }

    public void bind() {
        glUseProgram(programID);
    }

    public void unbind() {
        glUseProgram(0);
    }

    public void cleanup() {
        glDeleteProgram(programID);
    }
}

3. 在渲染循环中绑定着色器

修改 LWJGLTutorial.run() 中的渲染部分:

// 在初始化阶段(glfwMakeContextCurrent 之后、渲染循环之前)创建着色器
ShaderProgram shader = new ShaderProgram("src/main/resources/vertex.glsl", "src/main/resources/fragment.glsl");

// 在渲染循环中:
while (!glfwWindowShouldClose(window)) {
    glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    shader.bind(); // ← 关键:启用着色器程序
    Renderer.render(model);
    shader.unbind(); // ← 可选,但推荐显式解绑

    glfwSwapBuffers(window);
    glfwPollEvents();
}

// 渲染结束后清理
shader.cleanup();

同时,更新 Renderer.render() 以确保状态安全(可选增强):

public static void render(RawModel model) {
    glBindVertexArray(model.getVAO());
    glDrawArrays(GL_TRIANGLES, 0, model.getVertexCount());
    glBindVertexArray(0); // 好习惯:解绑 VAO
}

? 其他潜在风险点(检查清单)

  • OpenGL 上下文是否已正确创建? → 你已调用 GL.createCapabilities(),没问题。
  • VAO 是否在正确的上下文中创建? → 是,在 glfwMakeContextCurrent(window) 之后,正确。
  • 顶点属性指针索引是否匹配着色器 in 变量? → 你使用 glVertexAttribPointer(0, ...),着色器中 in vec3 position 绑定到 location 0,匹配。
  • 是否启用了 GL_DEPTH_TEST 却未写入深度值? → 当前着色器无深度操作,建议暂时注释 glEnable(GL_DEPTH_TEST),避免因深度测试失败导致片段被丢弃(尤其当清除深度缓冲未初始化或 Z 值冲突时)。

✅ 总结

问题现象 根本原因 解决方案
窗口正常但无任何图形 缺少着色器程序(Shader Program) 编写 GLSL 着色器 + 编译链接 + 渲染时 glUseProgram()

没有着色器,OpenGL 就像一台没有安装操作系统电脑——硬件就绪,却不知如何执行任务。补上着色器后,你的红色矩形将立即呈现。务必确保 .glsl 文件路径正确,并在构建时将其复制到 classpath(如 src/main/resources/)。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
function是什么
function是什么

function是函数的意思,是一段具有特定功能的可重复使用的代码块,是程序的基本组成单元之一,可以接受输入参数,执行特定的操作,并返回结果。本专题为大家提供function是什么的相关的文章、下载、课程内容,供大家免费下载体验。

483

2023.08.04

js函数function用法
js函数function用法

js函数function用法有:1、声明函数;2、调用函数;3、函数参数;4、函数返回值;5、匿名函数;6、函数作为参数;7、函数作用域;8、递归函数。本专题提供js函数function用法的相关文章内容,大家可以免费阅读。

163

2023.10.07

location.assign
location.assign

在前端开发中,我们经常需要使用JavaScript来控制页面的跳转和数据的传递。location.assign就是JavaScript中常用的一个跳转方法。通过location.assign,我们可以在当前窗口或者iframe中加载一个新的URL地址,并且可以保存旧页面的历史记录。php中文网为大家带来了location.assign的相关知识、以及相关文章等内容,供大家免费下载使用。

226

2023.06.27

CSS position定位有几种方式
CSS position定位有几种方式

有4种,分别是静态定位、相对定位、绝对定位和固定定位。更多关于CSS position定位有几种方式的内容,可以访问下面的文章。

81

2023.11.23

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

386

2026.01.28

包子漫画在线官方入口大全
包子漫画在线官方入口大全

本合集汇总了包子漫画2026最新官方在线观看入口,涵盖备用域名、正版无广告链接及多端适配地址,助你畅享12700+高清漫画资源。阅读专题下面的文章了解更多详细内容。

135

2026.01.28

ao3中文版官网地址大全
ao3中文版官网地址大全

AO3最新中文版官网入口合集,汇总2026年主站及国内优化镜像链接,支持简体中文界面、无广告阅读与多设备同步。阅读专题下面的文章了解更多详细内容。

233

2026.01.28

php怎么写接口教程
php怎么写接口教程

本合集涵盖PHP接口开发基础、RESTful API设计、数据交互与安全处理等实用教程,助你快速掌握PHP接口编写技巧。阅读专题下面的文章了解更多详细内容。

8

2026.01.28

php中文乱码如何解决
php中文乱码如何解决

本文整理了php中文乱码如何解决及解决方法,阅读节专题下面的文章了解更多详细内容。

13

2026.01.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 3万人学习

C# 教程
C# 教程

共94课时 | 7.9万人学习

Java 教程
Java 教程

共578课时 | 52.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号