Hello Guest

Basic LWJGL/GLFW/OpenVR Example

  • 7 Replies
  • 1206 Views
Basic LWJGL/GLFW/OpenVR Example
« on: April 19, 2018, 12:19:58 »
Can someone give me a super basic example of how to render some images to a HTC Vive using LWJGL, GLFW and OpenVR?

I get the VRCompositor to show me the default-grid with the controllers and basestations, but i'm not able to add anything to it.

I found an example, where the GLFW window is rendered to the Vive. He used
Code: [Select]
GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices(); to identify the HTC Vive as a monitor.
In a comment he wrote, that LWJGL3 doesn't support this anymore :-[. So i tried to identify the Vive with the GLFW method
Code: [Select]
glfwGetMonitors();The result is an array of size 1 though (so he only finds the Default Monitor attached to the computer).  :'(


In a C++ OpenVR example i found this:
Code: [Select]
vr::Texture_t leftEyeTexture = {(void*)leftEyeTex, vr::API_OpenGL, colorSpace};
vr::Texture_t rightEyeTexture = {(void*)rightEyeTex, vr::API_OpenGL, colorSpace};

vr::VRCompositor()->Submit(vr::Eye_Left, &leftEyeTexture);
vr::VRCompositor()->Submit(vr::Eye_Right, &rightEyeTexture);
leftEyeTex and rightEyeTex where created using openGL.
So i tried to do this in Java:
Code: [Select]
Texture texture = Texture.create();
texture.set(modelTexture.getID(), ETextureType_TextureType_OpenGL, EColorSpace_ColorSpace_Auto);

VRCompositor.VRCompositor_Submit(EVREye_Eye_Left, texture, null, VR.EVRSubmitFlags_Submit_GlRenderBuffer);
VRCompositor.VRCompositor_Submit(EVREye_Eye_Right, texture, null, VR.EVRSubmitFlags_Submit_GlRenderBuffer);
texture is an OpenVR Texture, modelTexture was created with OpenGL.
This didnt work either  :'(

Thanks in advance!
« Last Edit: April 19, 2018, 12:43:15 by MKutschin »

*

Offline spasi

  • *****
  • 2052
    • WebHotelier
Re: Basic LWJGL/GLFW/OpenVR Example
« Reply #1 on: April 19, 2018, 16:45:46 »
You don't need to discover the HMD as a monitor afaik.

I can't help you much without seeing more code, but here are a couple of samples that you may find useful:

Minimal OpenVR + GLFW
OpenGL sample (from the OpenVR repository, uses SDL which is similar to GLFW)

Re: Basic LWJGL/GLFW/OpenVR Example
« Reply #2 on: April 20, 2018, 09:00:41 »
Thanks for the quick answer!

I already looked through the "Minimal OpenVr + GLFW" example. Actually the C++ code i posted was from there ;)

What part of my code would you need?

*

Offline spasi

  • *****
  • 2052
    • WebHotelier
Re: Basic LWJGL/GLFW/OpenVR Example
« Reply #3 on: April 20, 2018, 09:48:59 »
As much of it as possible I guess. There are no hints to what may be wrong in what you posted above.

Before you post though, make sure there are no issues that are trivially discovered with the available tools:

- Run your application with -Dorg.lwjgl.util.Debug=true
- Create a debug OpenGL context and register a debug callback (glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE) and GLUtil.setupDebugMessageCallback())
- Try LWJGLX/debug

Re: Basic LWJGL/GLFW/OpenVR Example
« Reply #4 on: April 24, 2018, 10:50:38 »
Debugging:
-Dorg.lwjgl.util.Debug=true:
unusual things:
Code: [Select]
[LWJGL] opengl32.dll not found in org.lwjgl.librarypath
[LWJGL] Loaded from system paths

and:
Code: [Select]
[LWJGL] [GL] GL_ARB_shader_subroutine was reported as available but an entry point is missing.

the other dll's were loaded normally.


the OpenGL debug context gave me lot of:
Code: [Select]
[LWJGL] OpenGL debug message
ID: 0x20071
Source: API
Type: OTHER
Severity: NOTIFICATION
Message: Buffer detailed info: Buffer object 104 (bound to GL_ELEMENT_ARRAY_BUFFER_ARB, usage hint is GL_STATIC_DRAW) will use VIDEO memory as the source for buffer object operations.

and a few of:
Code: [Select]
[LWJGL] OpenGL debug message
ID: 0x502
Source: API
Type: ERROR
Severity: HIGH
Message: GL_INVALID_OPERATION error generated. No active program.

I dont think these messages are generated by my code, because there's a game running, which was implemented by other students.


I removed all the try-blocks from the code.

Setting up VR:
Code: [Select]
System.out.println("VR_IsRuntimeInstalled() = " + VR_IsRuntimeInstalled());
System.out.println("VR_RuntimePath() = " + VR.VR_RuntimePath());
System.out.println("VR_IsHmdPresent() = " + VR_IsHmdPresent());

IntBuffer peError = stack.mallocInt(1);
int token = VR_InitInternal(peError, VR.EVRApplicationType_VRApplication_Scene);
if (peError.get(0) == 0) {
OpenVR.create(token);

System.out.println("Model Number : " + VRSystem_GetStringTrackedDeviceProperty(
k_unTrackedDeviceIndex_Hmd, ETrackedDeviceProperty_Prop_ModelNumber_String, peError));
System.out.println("Serial Number: " + VRSystem_GetStringTrackedDeviceProperty(
k_unTrackedDeviceIndex_Hmd, ETrackedDeviceProperty_Prop_SerialNumber_String, peError));

IntBuffer w = stack.mallocInt(1);
IntBuffer h = stack.mallocInt(1);
VRSystem_GetRecommendedRenderTargetSize(w, h);
System.out.println("Recommended width : " + w.get(0));
System.out.println("Recommended height: " + h.get(0));

} else {
System.out.println("INIT ERROR SYMBOL: " + VR_GetVRInitErrorAsSymbol(peError.get(0)));
System.out.println("INIT ERROR  DESCR: " + VR_GetVRInitErrorAsEnglishDescription(peError.get(0)));
System.exit(-1);
}

i tried to follow the implementation of Minimal OpenVR + GLFW Example as strictly as possible, so the comments in the code mark the methods of the example.
Code: [Select]
// the following comments reference: https://gist.github.com/VirtuosoChris/272f803966e62796b83dce2a597adcc7#file-helloopenvr_glfw-cpp-L284
// main:
int tex = GL11.glGenTextures();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, tex);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0,GL11.GL_RGBA, 1024, 768, 0,GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, 0);

// constructor of BasicRenderTarget
int fbo = GL30.glGenFramebuffers();
int rbo = GL30.glGenRenderbuffers();
GL30.glRenderbufferStorage(rbo, GL11.GL_RGBA, 1024, 768);
GL30.glBindRenderbuffer(GL30.GL_DEPTH_ATTACHMENT, fbo);
GL11.glViewport(0, 0, 1024, 768);

// BasicRenderTarget.prime
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, fbo);
GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, GL11.GL_TEXTURE_2D, tex, 0);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);

// main
GL11.glClearColor(1f, 0f, 0f, 1f);
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, fbo);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);


VREvent vrEvent = new VREvent(bb);

// Process SteamVR events
while (VRSystem_PollNextEvent(vrEvent)) {
processVREvent(vrEvent);
}

TrackedDevicePose.Buffer tdpb = TrackedDevicePose.create(k_unMaxTrackedDeviceCount);
TrackedDevicePose.Buffer tdpb2 = TrackedDevicePose.create(k_unMaxTrackedDeviceCount);

VRCompositor.VRCompositor_WaitGetPoses(tdpb, tdpb2);


Texture texture = Texture.create();
texture.set(tex, ETextureType_TextureType_OpenGL, EColorSpace_ColorSpace_Auto);

VRCompositor.VRCompositor_Submit(EVREye_Eye_Left, texture, null, VR.EVRSubmitFlags_Submit_GlRenderBuffer);
VRCompositor.VRCompositor_Submit(EVREye_Eye_Right, texture, null, VR.EVRSubmitFlags_Submit_GlRenderBuffer);

GL11.glFlush();
VRCompositor.VRCompositor_PostPresentHandoff();

i am completely new to OpenGL so pls be gentle  ;)
« Last Edit: April 26, 2018, 12:01:54 by MKutschin »

*

Offline spasi

  • *****
  • 2052
    • WebHotelier
Re: Basic LWJGL/GLFW/OpenVR Example
« Reply #5 on: April 24, 2018, 11:08:08 »
You may ignore OpenGL notifications, but errors must be eliminated. One thing you could do is enable synchronous error reporting (see GL43.GL_DEBUG_OUTPUT_SYNCHRONOUS) and register a custom debug callback that throws a Java exception (or use a breakpoint while debugging). This will let you know exactly which OpenGL call causes the error.

*

Offline KaiHH

  • ***
  • 154
Re: Basic LWJGL/GLFW/OpenVR Example
« Reply #6 on: April 24, 2018, 18:05:37 »
As @Spasi already pointed out, you could/should use LWJGLX/debug. It will either print the cause of the error (if it can validate it itself) or it will display a callstack in the installed synchronous OpenGL debug callback with the first stack trace element being _exactly_ the erroneous OpenGL call.
You can obtain the jar of LWJGLX/debug on https://www.lwjgl.org/customize under "Addons".
Start the JVM with `-javaagent:/path/to/lwjglx-debug-1.0.0.jar`

Re: Basic LWJGL/GLFW/OpenVR Example
« Reply #7 on: April 26, 2018, 10:37:06 »
Sorry for my slow responses, but I have limited access to the HMD  :-\

I debuged the code using LWJGLX/debug, located and solved a lot of errors. some errors i cant solve are:
Code: [Select]
[error][1] OpenGL debug message
  ID: 0x502
  Source: API
  Type: ERROR
  Severity: HIGH
  Message: GL_INVALID_OPERATION error generated. Unknown buffer name.

[error][1] OpenGL debug message
  ID: 0x502
  Source: API
  Type: ERROR
  Severity: HIGH
  Message: GL_INVALID_OPERATION error generated. Invalid render buffer.

[error][1] OpenGL debug message
  ID: 0x506
  Source: API
  Type: ERROR
  Severity: HIGH
  Message: GL_INVALID_FRAMEBUFFER_OPERATION error generated. Framebuffer bindings are not framebuffer complete.

if i call
Code: [Select]
GL30.glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
I get "36053" as a result.
Acording to this post it means "GL_FRAMEBUFFER_COMPLETE".

I changed the creation of the texture, following this wiki (lines 119-137).

This is my code atm:
Code: [Select]
int tex = GL11.glGenTextures();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, tex);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0,GL11.GL_RGBA8, 1024, 768, 0,GL11.GL_RGBA, GL11.GL_INT, (java.nio.ByteBuffer) null);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);

int fbo = glGenFramebuffersEXT();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL11.GL_TEXTURE_2D, tex, 0);

int rbo = glGenRenderbuffersEXT();
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rbo);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL14.GL_DEPTH_COMPONENT24, 1024, 768);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rbo);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

GL11.glViewport(0, 0, 1024, 768);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
GL11.glClearColor(1f, 0f, 0f, 1f);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
GL11.glClearColor(0f, 1f, 0f, 1f);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, tex);
GL11.glViewport(0, 0, 1024, 768);

int result = GL30.glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);

// Handling VREvents and VRCompositors waitGetPoses

Texture texture = Texture.create();
texture.set(tex, ETextureType_TextureType_OpenGL, EColorSpace_ColorSpace_Auto);

VRCompositor.VRCompositor_Submit(EVREye_Eye_Left, texture, null, VR.EVRSubmitFlags_Submit_GlRenderBuffer); // this line throws the exceptions

if i dont call
Code: [Select]
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

i get the same result from the checkStatus call
« Last Edit: April 26, 2018, 12:05:32 by MKutschin »