Context
I’ve been working with using OpenXR (aka modern Virtual reality etc) with JMonkeyEngine. I’ve found a bug but I’m unsure if it’s in my code or JMonkeyEngine. The basic process I’m doing is setting up 2 cameras, moving them in an AppStates update method depending on where OpenXR says they should be then in the postRender I’m copying their frame buffers into OpenXR
public class XrAppState extends BaseAppState{
@Override
protected void initialize(Application app){
Texture2D leftOffTex = new Texture2D(width, height, Image.Format.RGBA8);
leftOffTex.setMinFilter(Texture.MinFilter.BilinearNoMipMaps);
leftOffTex.setMagFilter(Texture.MagFilter.Bilinear);
leftEyeFrameBuffer = new FrameBuffer(width, height, 1);
leftEyeFrameBuffer.setDepthBuffer(Image.Format.Depth);
leftEyeFrameBuffer.setColorTexture(leftOffTex);
leftViewPort = app.getRenderManager().createPreView("Left Eye", leftCamera);
leftViewPort.setClearFlags(true, true, true);
leftViewPort.setOutputFrameBuffer(leftEyeFrameBuffer);
//same for right eye
}
@Override
public void update(float tpf){
leftCamera.setLocation(observer.localToWorld(inProgressXrRender.leftEye.eyePosition(), null));
}
public void postRender(){
xrSession.presentFrameBuffersToOpenXr(inProgressXrRender, leftEyeFrameBuffer, rightEyeFrameBuffer);
}
}
The bug
Sometimes (and it seems to depend on viewing angle) a geometry will go black (not culled, black)
“A” solution
The way I present these frame buffers to OpenXR (called within the postRender method) is like this:
private void renderWithJMEFrameBuffer(XrSwapchainImageOpenGLKHR swapchainImage, FrameBuffer targetBuffer){
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, targetBuffer.getId());
GL11.glBindTexture(GL11.GL_TEXTURE_2D, swapchainImage.image());
GL11.glCopyTexSubImage2D(
GL11.GL_TEXTURE_2D,
0,
0, 0,
0, 0,
swapchainWidth,
swapchainHeight
);
GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, 0); //clear framebuffer
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0); //clear texture
}
I.e. I bind the texture and the frame buffer and copy them across, then I set them both to zero as I’m done with them to release them
If I instead change it to this then the problems go away
private void renderWithJMEFrameBuffer(XrSwapchainImageOpenGLKHR swapchainImage, FrameBuffer targetBuffer){
IntBuffer intBuffer = BufferUtils.createIntBuffer(1);
GL11.glGetIntegerv(GL11.GL_TEXTURE_BINDING_2D, intBuffer);
int previouslyBoundTexture = intBuffer.get(0);
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, targetBuffer.getId());
GL11.glBindTexture(GL11.GL_TEXTURE_2D, swapchainImage.image());
GL11.glCopyTexSubImage2D(
GL11.GL_TEXTURE_2D,
0,
0, 0,
0, 0,
swapchainWidth,
swapchainHeight
);
GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, 0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, previouslyBoundTexture); //< -- put things back how I found them
}
So it seems like JMonkey already has a bound texture and doesn’t like me messing with it.
Question
So it seems like there are 3 possibilities
- JMonkey wants full control of the bound textures and I should put them back how I found them (my solution is correct, there was a bug in my code)
- JMonkey shouldn’t be relying on these bound textures not being reset but it is (bug in JMonkeyEngine, my solution is a work around)
- I shouldn’t be copying around frame buffers in the postRender method and should be doing it elsewhere
Does anyone know which of these 3 is true? (Or if it’s a 4th I haven’t considered).
I’m on the most recent JME; 3.6.1