Skip to content

无缝连接 Java AWT 与 OpenGL 的高性能桥梁 --- A high-performance bridge that seamlessly connects Java AWT with OpenGL

License

Notifications You must be signed in to change notification settings

tzdwindows/GLAwt

Repository files navigation

GLAwt: 无缝桥接 Java AWT 与 OpenGL 的高性能渲染库 🚀

MPL-2.0 License PRs Welcome Java Version Platform Build Status

厌倦了为在 Java AWT 应用中添加一点 3D 功能而引入庞大的图形框架? GLAwt 是你的完美解决方案!这是一个轻量级、跨平台的 JNI 库,让你能在标准的 AWT/Swing 窗口中零配置启动 OpenGL 渲染上下文,无缝集成高性能 3D 渲染。

核心价值:在现有 Java 桌面应用中,以最小的侵入性添加 OpenGL 渲染能力。


📋 目录


✨ 为什么选择 GLAwt?

现有方案的问题

方案 优点 缺点
LWJGL/JOGL 功能全面,社区活跃 体积庞大,学习曲线陡峭
手动 JNI 完全控制,无额外依赖 跨平台困难,维护成本高
混合框架 可以利用现有组件 集成复杂,性能开销大

GLAwt 的独特优势

场景一:企业应用中的 3D 可视化

你有一个成熟的 Java Swing 数据管理系统,现在需要在地图面板中添加 3D 地形预览。使用 GLAwt,你只需将现有的 JPanel 替换为 OpenGL 画布,无需重写整个界面。

场景二:科学计算的可视化

你的科研软件用 Java Swing 开发,需要实时显示 3D 分子模型或流体模拟。GLAwt 让你能在现有窗口中直接渲染 OpenGL 内容。

场景三:教育演示工具

创建交互式的 3D 几何教学演示,学生可以旋转、缩放模型。GLAwt 的低门槛让你专注于教学内容,而不是图形编程。

GLAwt 的核心哲学:为已有 Java 桌面应用提供最简单、最直接的 OpenGL 集成方案。


🎯 核心特性

✅ 已完成

  • 跨平台支持:Windows (WGL)、Linux (GLX)、macOS (CGL)
  • 零外部依赖:仅需 JNI 和系统 OpenGL 驱动
  • 线程安全设计:明确的上下文管理策略
  • 完整的资源生命周期管理:自动清理原生资源
  • 详细的错误处理:跨平台的错误信息反馈

🚀 快速开始

基础示例:渲染彩色三角形

import org.tzd.awt.ContextHandle;
import java.awt.Canvas;
import java.awt.Frame;

import static org.lwjgl.opengl.GL11.*;

public class OpenGLExample {
   public static void main(String[] args) {
      // 1. 创建 AWT 窗口
      Frame frame = new Frame("OpenGL with ContextHandle Example");
      frame.setSize(800, 600);

      // 2. 创建 OpenGL 画布
      Canvas canvas = new Canvas();
      canvas.setSize(800, 600);
      frame.add(canvas);

      frame.setVisible(true);

      // 3. 使用 ContextHandle(try-with-resources 自动管理资源)
      try (ContextHandle ctx = new ContextHandle(canvas)) {
         // 激活上下文
         ctx.makeCurrent();

         // 4. 设置 OpenGL 状态(这里使用 LWJGL 作为示例)
         org.lwjgl.opengl.GL.createCapabilities();
         glClearColor(0.2f, 0.3f, 0.3f, 1.0f);

         // 5. 简单渲染循环
         while (!Thread.currentThread().isInterrupted()) {
            glClear(GL_COLOR_BUFFER_BIT);

            // 渲染一个彩色三角形(使用立即模式,仅用于示例)
            glBegin(GL_TRIANGLES);
            glColor3f(1.0f, 0.0f, 0.0f);   // 红色
            glVertex2f(-0.5f, -0.5f);
            glColor3f(0.0f, 1.0f, 0.0f);   // 绿色
            glVertex2f(0.5f, -0.5f);
            glColor3f(0.0f, 0.0f, 1.0f);   // 蓝色
            glVertex2f(0.0f, 0.5f);
            glEnd();

            // 交换缓冲区
            ctx.swapBuffers();

            // 简单的帧率控制(60 FPS)
            Thread.sleep(16);
         }
      } catch (Exception e) {
         e.printStackTrace();
      } finally {
         frame.dispose();
      }
   }
}

📖 详细使用指南

1. 上下文管理最佳实践

手动管理上下文

long context = GLAwt.init(canvas);
try {
    GLAwt.makeCurrent(context);
    // OpenGL 渲染...
    GLAwt.swapBuffers(context);
} finally {
    GLAwt.destroy(context); // 必须调用!
}

2. 多线程渲染

public class MultiThreadRender {
    private volatile boolean running = true;
    private long context;
    
    public void startRenderThread(Canvas canvas) {
        context = GLAwt.init(canvas);
        
        Thread renderThread = new Thread(() -> {
            GLAwt.makeCurrent(context);
            
            while (running) {
                // 渲染逻辑
                renderFrame();
                GLAwt.swapBuffers(context);
                
                // 垂直同步控制
                // GLAwt.setVSync(context, true);
            }
            
            // 清理
            GLAwt.makeCurrent(0); // 取消当前化
            GLAwt.destroy(context);
        });
        
        renderThread.start();
    }
    
    public void stop() {
        running = false;
    }
}

3. 处理窗口大小变化

canvas.addComponentListener(new ComponentAdapter() {
    @Override
    public void componentResized(ComponentEvent e) {
        // 在渲染线程中处理大小变化
        EventQueue.invokeLater(() -> {
            int width = canvas.getWidth();
            int height = canvas.getHeight();
            
            if (context != 0) {
                GLAwt.makeCurrent(context);
                glViewport(0, 0, width, height);
                // 更新投影矩阵等...
            }
        });
    }
});

🔧 API 参考

核心方法

方法 参数 返回值 描述
init(Object) AWT 组件 long 创建 OpenGL 上下文
makeCurrent(long) 上下文句柄 void 激活上下文
swapBuffers(long) 上下文句柄 boolean 交换前后缓冲区
destroy(long) 上下文句柄 void 销毁上下文
setVSync(long, boolean) 上下文句柄, 启用标志 void 控制垂直同步
getLastError() String 获取错误信息

错误处理

try {
    long ctx = GLAwt.init(canvas);
    if (ctx == 0) {
        String error = GLAwt.getLastError();
        System.err.println("初始化失败: " + error);
        return;
    }
} catch (Exception e) {
    // 处理异常
}

🏗️ 架构设计

系统架构图

┌─────────────────────────────────────────┐
│           Java 应用程序层                │
│  ┌─────────────────────────────────┐    │
│  │      GLAwt Java API             │    │
│  │  • ContextHandle (AutoCloseable)│    │
│  │  • 线程安全的上下文管理           │    │
│  └───────────────┬─────────────────┘    │
└──────────────────┼──────────────────────┘
                   │ JNI 调用
┌──────────────────┼──────────────────────┐
│        原生层(C++/系统 API)            │
│  ┌───────────────┼─────────────────┐    │
│  │   平台抽象层                      │    │
│  │   • Windows: WGL                │    │
│  │   • Linux: GLX + X11            │    │
│  │   • macOS: CGL                  │    │
│  └─────────────────────────────────┘    │
└─────────────────────────────────────────┘

上下文状态机

      ┌─────────────┐
      │  未初始化    │
      └──────┬──────┘
             │ init()
      ┌──────▼──────┐
      │  已创建     │◄──┐
      └──────┬──────┘   │
             │ makeCurrent()
      ┌──────▼──────┐   │
      │  当前化     │───┘
      └──────┬──────┘   │
             │ swapBuffers()
      ┌──────▼──────┐   │
      │  渲染就绪   │───┘
      └──────┬──────┘
             │ destroy()
      ┌──────▼──────┐
      │  已销毁     │
      └─────────────┘

📦 安装与部署

环境要求

组件 最低要求 推荐版本
Java JDK 11 JDK 17 LTS
OpenGL 2.1 3.3+
Windows Windows 7 Windows 10/11
Linux X11 + GLX X11 + GLX 1.4
macOS 10.13 (High Sierra) 11.0+ (Big Sur)

🛠️ 从源码构建

本项目采用 Gradle 构建 Java 部分(并自动生成 JNI 头文件),采用 CMake 构建 C++ 本地库。

前置要求

通用要求

  • JDK 11+ (推荐 JDK 17 或更高,需配置 JAVA_HOME 环境变量)
  • CMake 3.10+
  • C++ 编译器 (支持 C++17)

平台特定要求

  • Windows: Visual Studio 2019+ (推荐) 或 MinGW-w64
  • Linux: GCC/Clang, libx11-dev, libgl1-mesa-dev
  • macOS: Xcode Command Line Tools

快速构建 (推荐)

项目提供了自动构建脚本,可自动处理 Java 编译、头文件生成和 C++ 库编译。

Windows

直接运行根目录下的脚本:

build.bat

Linux / macOS / Git Bash

chmod +x build.sh gradlew
./build.sh

构建产物位置:

  • Java Jar: build/libs/
  • Native Lib: build/native/Release/ (Windows 为 DLL, Linux 为 .so, macOS 为 .dylib)

手动构建步骤

如果你希望手动逐步构建(或集成到 IDE 中),请遵循以下顺序:

1. 编译 Java 并生成 JNI 头文件

必须先运行 Gradle 构建,因为它会生成 C++ 编译所需的 org_tzd_awt_GLAwt.h 头文件。

# Windows
gradlew.bat clean build classes

# Linux/macOS
./gradlew clean build classes

2. 构建 C++ 本地库

生成头文件后,使用 CMake 构建动态链接库。

mkdir -p build/native
cd build/native

# 配置 CMake (注意指向源码目录)
# Windows (Visual Studio)
cmake ../../src/main/Cpp/GLAwt -DCMAKE_BUILD_TYPE=Release

# Linux / macOS
cmake ../../src/main/Cpp/GLAwt -DCMAKE_BUILD_TYPE=Release

# 编译
cmake --build . --config Release

交叉编译 (高级)

注意:交叉编译前,请确保已在宿主机上运行过 Gradle 任务以生成 JNI 头文件。

# 在 Linux 上交叉编译 Windows 版本 (MinGW)
mkdir build-windows && cd build-windows
cmake ../../src/main/Cpp/GLAwt -DCMAKE_TOOLCHAIN_FILE=../../cmake/x86_64-w64-mingw32.cmake
cmake --build . --config Release

# 在 macOS 上编译通用二进制 (Intel + Apple Silicon)
mkdir build-universal && cd build-universal
cmake ../../src/main/Cpp/GLAwt -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"
cmake --build . --config Release

🧪 验证安装

public class VerifyInstallation {
    public static void main(String[] args) {
        System.out.println("GLAwt 版本: " + GLAwt.getVersion());
        System.out.println("支持平台: " + 
            String.join(", ", GLAwt.getSupportedPlatforms()));
        
        // 尝试创建虚拟窗口测试
        try {
            Frame frame = new Frame("测试窗口");
            Canvas canvas = new Canvas();
            frame.add(canvas);
            frame.setSize(100, 100);
            frame.setVisible(true);
            
            Thread.sleep(1000); // 等待窗口显示
            
            try (GLAwt.ContextHandle ctx = new GLAwt.ContextHandle(canvas)) {
                System.out.println("✅ OpenGL 上下文创建成功!");
                System.out.println("✅ 系统错误检查: " + GLAwt.getLastError());
            }
            
            frame.dispose();
        } catch (Exception e) {
            System.err.println("❌ 测试失败: " + e.getMessage());
        }
    }
}

🤝 如何贡献

贡献流程

  1. Fork 仓库

    # 点击 GitHub 上的 Fork 按钮
    git clone https://github.com/你的用户名/GLAwt.git
  2. 创建特性分支

    git checkout -b feature/amazing-feature
  3. 开发与测试

    # 运行现有测试
    ./scripts/run-tests.sh
    
    # 添加新测试
    # 在 test/ 目录下添加测试用例
  4. 提交代码

    git add .
    git commit -m "feat: 添加了某某功能"
    git push origin feature/amazing-feature
  5. 创建 Pull Request

    • 描述你的更改
    • 关联相关的 Issue
    • 确保 CI 测试通过

开发指南

  • 代码风格:遵循 Google Java 风格指南和 Google C++ 风格指南
  • 提交信息:使用 Conventional Commits 格式
  • 测试覆盖率:新功能需要包含单元测试
  • 文档更新:修改代码时同步更新文档

寻找贡献点

查看 Good First Issues 标签开始你的贡献!


📄 许可证

本项目采用 Mozilla Public License 2.0 (MPL-2.0)。这是一个宽松的开源许可证,允许:

商业使用:可用于闭源商业软件 ✅ 修改分发:可以修改代码并分发 ✅ 专利授权:包含明确的专利授权条款

唯一要求:如果你修改了本项目的源代码,必须将修改部分以 MPL-2.0 许可证开源。

版权所有 (c) 2025 tzdwindows 7

本源码的使用受 MPL-2.0 许可证约束。
完整许可证文本见: https://mozilla.org/MPL/2.0/

许可证兼容性

许可证 兼容性 说明
Apache 2.0 可以链接使用
MIT 可以链接使用
GPL 2.0/3.0 ⚠️ 注意 Copyleft 条款
LGPL 可以链接使用

🙏 致谢

特别感谢

  • Java 社区:提供了 JAWT (Java Abstract Window Toolkit) 接口
  • OpenGL 开发者:创建了这个强大的图形标准
  • 所有贡献者:你们的代码、反馈和问题报告让项目更好

相关项目

  • LWJGL - 全面的 Java OpenGL 绑定
  • JOGL - Java OpenGL 绑定库
  • GLFW - 跨平台窗口和输入库

⭐ 支持项目

如果 GLAwt 帮助了你的项目:

  1. 给项目点个 Star ⭐ - 这是最大的支持!
  2. 分享你的用例 - 在 Discussions 中分享
  3. 报告问题 - 帮助我们改进
  4. 考虑赞助 - 支持项目的持续发展

GLAwt - 让 Java 桌面应用的 3D 渲染变得简单 ✨

Star History Chart

About

无缝连接 Java AWT 与 OpenGL 的高性能桥梁 --- A high-performance bridge that seamlessly connects Java AWT with OpenGL

Resources

License

Stars

Watchers

Forks

Packages

No packages published