[FIXED] LWJGL3: Whither NV_path_rendering?

Started by princec, July 17, 2015, 09:11:07

Previous topic - Next topic

princec

Got latest nightly here... can't seem to find NV_path_rendering. NVPathRenderingSharedEdge is there... but not NV_path_rendering. Have I just missed something?

Cas :)

Kai

I second this (feature request)! Definitely an awesome extension! Should be implemented.
Wanted to play/work with this extension to render svg, but it has not yet been implemented/ported to Kotlin. :(

spasi

On it, will let you know when it's up.

princec

Phew, thought I was just being stupid  ::)

I actually have a work use case for it! Turns out JavaFX is riddled with bugs, and the icing on the cake is that if you do anything remotely clever with path rendering, it's just totally slow. My plan is to render paths in OpenGL and then blit the results out to JavaFX and hopefully achieve 60fps...

Cas :)

spasi

Meh, I pushed the extension but the Linux builds are failing: can't download UPX from Sourceforge, looks like it's down for disaster recovery.

spasi

The latest nightly has NV_path_rendering. Sourceforge is still in recovery and upx.sourceforge.net is down, but I changed the build to download upx from s3.

Kai

Very nice! Thanks for adding that extension.

princec

Thanks Spasi, it's working well.

The reason I'm using LWJGL3 btw is that the NV_path_rendering extension in LWJGL2 has been implemented completely wrong and won't work.

Of course, this means that my previously nice and simple code using Pbuffers was no longer valid! So I've had to develop a sort of "Pbuffer"-alike class that does something similar using an invisible GLFW window context and FBOs. Much more fiddly and took most of an afternoon to get it all working!

Context handing in LWJGL3 is a bit ... undocumented. I have it all working but I'm not sure I'm following best practices.

Cas :)

spasi

Quote from: princec on July 26, 2015, 22:20:47The reason I'm using LWJGL3 btw is that the NV_path_rendering extension in LWJGL2 has been implemented completely wrong and won't work.

There is a good chance that the LWJGL 3 implementation is also wrong. I have not tested it and NV_path_rendering is significantly more complex than the average OpenGL extension. Could you share a code sample that breaks on LWJGL 2 (or 3)?

Just had a look and the methods that accept ByteBuffers (vs a typed buffer) seem to have wrong checks. I'll try to fix those today. I'll also convert the PathCommand tokens to byte constants, they currently require casts to use, right?

Quote from: princec on July 26, 2015, 22:20:47Of course, this means that my previously nice and simple code using Pbuffers was no longer valid! So I've had to develop a sort of "Pbuffer"-alike class that does something similar using an invisible GLFW window context and FBOs. Much more fiddly and took most of an afternoon to get it all working!

You're doing it right. Using a hidden GLFW window is the recommended way to do offscreen rendering. You could also use the context's framebuffer and avoid the FBO complexity.

LWJGL 3 has bindings to the pbuffer APIs, but it doesn't have a cross-platform wrapper (like org.lwjgl.opengl.Pbuffer in 2) to discourage their use. You could of course roll your own if you don't want to use GLFW.

Quote from: princec on July 26, 2015, 22:20:47Context handing in LWJGL3 is a bit ... undocumented. I have it all working but I'm not sure I'm following best practices.

Feel free to post any code or questions you might have. But there's not much to it. LWJGL 3 does not have code to create contexts (except the WGL/GLX/etc bindings, if you use those directly) and assumes all contexts are created and managed "externally" (e.g. via GLFW and that has plenty documentation). So GLContext.createFromCurrent() is all you really need in the common case.

princec

The LWJG3 APIs seem to be doing it right. The LWJGL2 APIs have their problem in glPathCommandsNV, which takes a buffer of coordinates but calculates the number of coordinates incorrectly as it doesn't take into account the data type of the coords in the buffer:
public static void glPathCommandsNV(int path, ByteBuffer commands, int coordType, ByteBuffer coords) {
		ContextCapabilities caps = GLContext.getCapabilities();
		long function_pointer = caps.glPathCommandsNV;
		BufferChecks.checkFunctionAddress(function_pointer);
		BufferChecks.checkDirect(commands);
		BufferChecks.checkDirect(coords);
		nglPathCommandsNV(path, commands.remaining(), MemoryUtil.getAddress(commands), coords.remaining(), coordType, MemoryUtil.getAddress(coords), function_pointer);
	}

instead just passing in coords.remaining() into nglPathCommandsNV. Doh! To fix it it'd need to have an overload for each sort of buffer type.

Cas :)

spasi

Yes, LWJGL 3 has the same problem, which I'll fix today. The typed versions work correctly.

princec

Nice one :)

LWJGL3 seems to be nice enough to use in production so far. Haven't seen results with Retina displays yet though.

Cas :)

spasi

The latest build (3.0.0b #6) has the fixes. The changes are here and here, please let me know if anything else needs fixing.

Quote from: princec on July 27, 2015, 10:39:32Haven't seen results with Retina displays yet though.

Works great on my MBP. GLFW has separate callbacks for the window and the framebuffer size, make sure to handle the framebuffer one to get the Retina resolution (e.g. to call glViewport).

princec

Haven't looked at callbacks yet... still only using invisible windows for pbuffer emulation!

Cas :)

spasi

Build #8 has more fixes. I think I've gone through all the functions now, but do let me know if you find any bugs. Also promoted the build to stable, the NV_path_rendering fixes helped me find similar bugs in other classes.