是否可以使用 LWJGL 将 C++ OpenGL 代码与 Java 混合?
Posted
技术标签:
【中文标题】是否可以使用 LWJGL 将 C++ OpenGL 代码与 Java 混合?【英文标题】:Is it possible to mix C++ OpenGL code with Java using LWJGL? 【发布时间】:2018-12-10 03:19:39 【问题描述】:我想制作 Java 应用程序。使用 CEF3 库。 CEF 是在任何应用程序中嵌入 Google Chrome 浏览器的库。 而 LWJGL 用于用 Java 编写 GL 代码。 但在使用 CEF 之前,基本的问题是如何混合 C++ 和 Java。
Java main 将 C++ 部分调用为 DLL
C++部分创建窗口并设置GL上下文
在消息循环中,C++ 再次回调 Java 部分做一些 GL 在 Java 中工作。
以下测试代码失败并显示消息:
本机方法中的致命错误:线程 [main,5,main]:没有上下文 当前或在当前上下文中不可用的功能是 叫。 JVM 将中止执行。 在 org.lwjgl.opengl.GL11.glColor3f(本机方法) 在 Main.run(Main.java:18) 在 Main.cppmain(本机方法) 在 Main.main(Main.java:10)
可能是因为Java部分不知道 关于 C++ 部分创建的 GL 上下文。 我的问题是如何设置 GL 上下文 这样 C++ 和 Java 都可以调用 GL 函数?
Main.java
import org.lwjgl.opengl.GL11;
public class Main implements Runnable
System.loadLibrary("cppgl");
public static void main(String[] args)
Main me = new Main();
me.cppmain(me);
private native void cppmain(Runnable callback);
@Override
public void run()
// callback from cpp
GL11.glColor3f(1.0f, 0.0f, 1.0f);
cppgl.cpp
#pragma comment(lib, "OpenGL32.lib")
#include <windows.h>
#include <tchar.h>
#include <functional>
#include <gl/gl.h>
#include <jni.h>
#pragma comment(lib, "jvm.lib")
LRESULT CALLBACK WndProc(HWND hWnd, UINT mes, WPARAM wParam, LPARAM lParam)
if (mes == WM_DESTROY || mes == WM_CLOSE) PostQuitMessage(0); return 0;
return DefWindowProc(hWnd, mes, wParam, lParam);
extern "C" JNIEXPORT void JNICALL Java_Main_cppmain
(JNIEnv *env, jobject, jobject callback)
LPCTSTR title = L"gl test";
// prepare JNI call
jclass cls = env->FindClass("Ljava/lang/Runnable;");
jmethodID mid = env->GetMethodID(cls, "run", "()V");
// window class
HINSTANCE hInstance = ::GetModuleHandle(NULL);
WNDCLASSEX wcex;
ZeroMemory(&wcex, sizeof(wcex));
wcex.cbSize = sizeof(wcex);
wcex.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.hInstance = hInstance;
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszClassName = title;
if (!RegisterClassEx(&wcex)) return;
// window
RECT R = 0, 0, 640, 480 ;
AdjustWindowRect(&R, WS_OVERLAPPEDWINDOW, FALSE);
HWND hWnd = CreateWindow(title, title, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, R.right - R.left, R.bottom - R.top,
NULL, NULL, hInstance, NULL);
if (!hWnd) return;
// GL context
PIXELFORMATDESCRIPTOR pfd;
ZeroMemory(&pfd, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 24;
pfd.iLayerType = PFD_MAIN_PLANE;
HDC dc = GetDC(hWnd);
int format = ChoosePixelFormat(dc, &pfd);
SetPixelFormat(dc, format, &pfd);
HGLRC glRC = wglCreateContext(dc);
if (!wglMakeCurrent(dc, glRC)) return;
// message loop
ShowWindow(hWnd, SW_SHOW);
MSG msg;
do
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
TranslateMessage(&msg);
DispatchMessage(&msg);
else
wglMakeCurrent(dc, glRC);
glClearColor(0.0f, 0.5f, 1.0f, 1.0f);
// call Java and change clear color here
env->CallVoidMethod(callback, mid);
glClear(GL_COLOR_BUFFER_BIT);
glRectf(-0.5f, -0.5f, 0.5f, 0.5f);
glFlush();
SwapBuffers(dc);
wglMakeCurrent(NULL, NULL);
while (msg.message != WM_QUIT);
// clean up
wglMakeCurrent(NULL, NULL);
wglDeleteContext(glRC);
ReleaseDC(hWnd, dc);
【问题讨论】:
【参考方案1】:在从 java 进行任何渲染之前,您应该在开始时调用一次。
// This line is critical for LWJGL's interoperation with GLFW's
// OpenGL context, or any context that is managed externally.
// LWJGL detects the context that is current in the current thread,
// creates the GLCapabilities instance and makes the OpenGL
// bindings available for use.
GL.createCapabilities();
【讨论】:
@AkihiroYoshikawa 不,您不应该编辑问题,但您应该接受答案(答案左侧的复选标记)。请注意,其他人应该能够理解问题中的问题并阅读答案中的解决方案。以上是关于是否可以使用 LWJGL 将 C++ OpenGL 代码与 Java 混合?的主要内容,如果未能解决你的问题,请参考以下文章
使用 OpenGL / LWJGL 绘制纹理四边形使用旧纹理