Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Impossible to munge only core GL entries into single class. #154

Closed
hypernewbie opened this Issue Mar 21, 2016 · 17 comments

Comments

Projects
None yet
8 participants
@hypernewbie
Copy link

commented Mar 21, 2016

The GL bindings here are very, very, very annoying to use. Please apply sanity to these bindings.

I want a single static class munging all GL1.1 --> GL3.3 entries and defines. I DO NOT want to do GL15. and GL30.. Importing everything static is not a solution.

Please provide an accumulated GL3.3 entry or give users an easy way to accumulate. Having separate non-interfaced entries for each GL version when the entry is first introduced is just absolute madness, because there is no way to have a core profile not have the compability entries.

For example org.lwjgl.opengles.GL33 does not contain a GL33.GL_ARRAY_BUFFER define. you have to use GL15.GL_ARRAYBUFFER. However, importing GL15 imports all of the deprecated stuff in GL15 not in GL33 core. That is suboptimal.

@hypernewbie hypernewbie changed the title Impossible to munge all GL entries into single class. Impossible to munge core GL entries into single class. Mar 21, 2016

@hypernewbie hypernewbie changed the title Impossible to munge core GL entries into single class. Impossible to munge only core GL entries into single class. Mar 21, 2016

@ghost

This comment has been minimized.

Copy link

commented Mar 21, 2016

For example org.lwjgl.opengles.GL33 does not contain a GL33.GL_ARRAY_BUFFER define.

Thats probably because org.lwjgl.opengles.GL33 does not exist. In OpenGL, GL_ARRAY_BUFFER is available under org.lwjgl.opengl.GL33. In OpenGL ES (the package you imported), it is available under org.lwjgl.opengles.GLES20. The javadoc covers this fully.

@Spasi

This comment has been minimized.

Copy link
Member

commented Mar 21, 2016

The recommended way to use LWJGL is via static imports. If you need functionality from a particular OpenGL version, you must explicitly import it. This:

  • is not a big deal. All tokens/functions are one <ctrl+space> away in modern IDEs, without any imports present.
  • protects from unintentionally using functionality from a higher OpenGL version than intended.
  • is better for exploring such a massive API.

Best we could do is make GL12 extend GL11, GL13 extend GL12, and so on. Using inheritance for static functionality is not a Java best practice, but it compiles and works. This way you could do an import static org.lwjgl.opengl.GL33.* and all functionality up to that version will be available.

@hypernewbie

This comment has been minimized.

Copy link
Author

commented Mar 21, 2016

I disagree.

It is not a big deal for your use cases, but that doesn't make the bindings any less terrible. It's just terrible in a way that doesn't affect the way you're using it.

This protects from unintentionally using functionality from a higher OpenGL version, but does not protect from unintentionally using a deprecated function from lower OpenGL when creating a core context. glBegin() doesn't exist on a core 33 context, but importing GL11.* gets me glBegin() :(. Yet I can't not use GL11 if I want GL_ARRAY_BUFFER.

I argue we should at least have a org.lwjgl.opengl.GL33core.* and should have EXACTLY all the entries in core 3.3, nothing more nothing less. For a library that claims to bind OpenGL, is this too much to ask? :P

@SilverTiger

This comment has been minimized.

Copy link
Member

commented Mar 21, 2016

You can create a forward compatible context by calling GL.createCapabilities(true). This will prevent LWJGL from loading deprecated functions. You can read this in the JavaDoc.
Also calling a deprecated function with an OpenGL context >= 3.0 should not work when creating a forward-compatible context with GLFW. Have you requested a context like in the following code?

glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
@httpdigest

This comment has been minimized.

Copy link
Member

commented Mar 21, 2016

Are you actually planning to use LWJGL for a real project? Just asking, because the confronting tone in your posts so far make it apparent that you don't want to do anything real with LWJGL, but instead just tell how terrible you think everything is and to grind up on such minor things as the binding strategy used in LWJGL.
Why does it bother you to have glBegin when you import GL11 for GL_ARRAY_BUFFER?
In my opinion it does not make the binding terrible or hard to use in any way.
It's not like you use LWJGL to actually learn OpenGL and help you avoid its pitfalls. There is better documentation for learning OpenGL than the IDE's auto-complete on the LWJGL API.

@hypernewbie

This comment has been minimized.

Copy link
Author

commented Mar 21, 2016

Hi,

Thanks for the suggestions.

The forward compat would help by crashing on null funcptr. I don't see how LWJGL's bindings can not have these functions in the first place by exposing only the core profile.

I do not intend to sound confrontational. I apologise if I sounded like that. I do intend to use LWJGL, I am complaining because I hope to make LWJGL better. If I didn't care then I wouldn't even post here. I am not intending to learn OpenGL with LWJGL, and agree it's not the best doc to do that.

I'm running intro trouble because I'm trying to port an ES2 app over to GL without using desktop ES compatibility extension. ES2 should be mostly subset of GL3 (save a few things). The app calls GL using the Android GLES20.gl style.

I ended up manually plugging every ES2 entry to the equivalent GLxx., even though I would've liked to be able to just extend GL33core or something and called it a day. I couldn't extend multiple classes from Java, and the GL* bindings aren't interfaced. Guess I probably should've used a python script or something to do that, but ES2 wasn't that big.

The use case here can probably be made easier if I just did a bunch of find-replace operations across the app code itself. But the fact that there is no core GLX.X interface in LWJGL is still hardly a selling point, no matter how minor to most people.

Having an accumulative version of org.lwjgl.opengl.GLXX would help something like my use case. That would be pretty sweet. I argue Core profile version should exist regardless of what people's opinions are regarding accumulative version.

@httpdigest

This comment has been minimized.

Copy link
Member

commented Mar 22, 2016

Instead of trying to find ways to extend a LWJGL class to bring its GL methods into scope, why didn't you just search GLES20. in your OpenGL ES application sources and replaced it with the empty string and then just import static org.lwjgl.opengl.GLxx.* for every needed GLxx class.
That'd work too, I guess. No need to manually lookup the correct GLxx class for a given OpenGL function and use GLxx.gl....
I am not saying which way is best, just trying to plot a way for you to work with the current binding strategy.

@Spasi

This comment has been minimized.

Copy link
Member

commented Mar 22, 2016

I ended up manually plugging every ES2 entry to the equivalent GLxx., even though I would've liked to be able to just extend GL33core or something and called it a day. I couldn't extend multiple classes from Java, and the GL* bindings aren't interfaced. Guess I probably should've used a python script or something to do that, but ES2 wasn't that big.

The use case here can probably be made easier if I just did a bunch of find-replace operations across the app code itself. But the fact that there is no core GLX.X interface in LWJGL is still hardly a selling point, no matter how minor to most people.

Having interfaces implies having instances that implement those interfaces. This will never happen in LWJGL. You'll never see C bindings that look like gl.glBufferData(...). Many other libraries work like that, but the current style has been LWJGL's differentiating factor from day one.

Especially in LWJGL 3, we want the Java code to look as close to the native equivalent as possible. We want the code to feel natural to both Java developers and to developers coming from system languages. The problem of copy/pasting Android code and have it work immediately is far less important and doing the same with native code.

Do you have any input on my suggestion above? (having GL33 extend GL32, GL32 extend GL31, and so on)

On dropping deprecated functions: As @SilverTiger mentioned, a forward compatible context will not load deprecated function pointers. You do not risk crashing the JVM either, there are runtime checks for such functions (unless -Dorg.lwjgl.util.NoChecks=true is specified). If you do not want to see such functions at all (e.g. in IDE auto-complete lists), you can always clone LWJGL locally and change the code generator to exclude deprecated functions. It should be trivial, but let me know if you need help with that.

@dustContributor

This comment has been minimized.

Copy link

commented Mar 22, 2016

Having interfaces implies having instances that implement those interfaces. This will never happen in LWJGL.

Praise Spasi \o/

I agree, its not a big deal. And extending classes just to import static functions is plain fugly, and a bad practice as it is. I doubt anyone here wants to encourage that kind of usage.

It'd be nice to have a "import org.lwjgl.opengl.CoreGL33.*" and get all the stuff in core OpenGL 3.3 but its far from a dealbreaker.

@ShadowLordAlpha

This comment has been minimized.

Copy link

commented Mar 27, 2016

could make a class that only contains wrapper methods for the core functions.

@TheOnlySilverClaw

This comment has been minimized.

Copy link

commented Jun 7, 2016

I agree, its not a big deal. And extending classes just to import static functions is plain fugly, and a bad practice as it is. I doubt anyone here wants to encourage that kind of usage.

I was tempted to shout yes, since it would kind of make sense that newer versions extend older ones, but a @dustContributor mentioned, it's probably inappropriate for static methods.
I still don't thin static importing everything is the greatest of all ways to handle this, especially for people who do not know OpenGL that well and try to find out how the whole thing works together. On the other hand, there is probably no perfect solution to bind Java methods to native calls, to the best course would be to leave it alone and focus on more useful things.

@Spasi Spasi closed this Nov 19, 2017

@hypernewbie

This comment has been minimized.

Copy link
Author

commented Apr 29, 2018

I'm not asking for the incremental versions.

OpenGL 3.3 core is a very specific API. When you create a 3.3 core context you get this exact set of functions and definitions and nothing more, nothing less. Anything more is illegal without extensions. Calling GL2 functions will certainly break the spec. All I wanted is a binding to 3.3 core, nothing more, nothing less, and if there's a GL2 function that doesn't actually exist in the driver for 3.3 core, why should it exist as a function in my bindings?

LWJGL3 effectively models compatibility. It does not bind core context. It binds a superset of core context, but that's not binding the core context.

FWIW I worked for and with the OpenGL Khronos group as member and part of the vendor driver team, and my ex co-workers (some of whom designed OpenGL and implemented it) would probably agree that an OpenGL binding library should have the ability to bind core.

For example, glbinding can just #include <glbinding/gl32core/gl.h>, and get the functionality of the GL 3.2 core exactly, nothing more nothing less. glBegin() is not part of the GL 3.2 core and calling that is illegal even though it works in a subset of drivers.

@Spasi

This comment has been minimized.

Copy link
Member

commented May 31, 2018

glbinding can just #include <glbinding/gl32core/gl.h>, and get the functionality of the GL 3.2 core exactly, nothing more nothing less.

Java is not C/C++. There's no preprocessor that could accomplish what glbinding does. The only possibility so far has been to create a custom LWJGL build for your application.

Anyway, there are two enhancements being suggested here:

  1. Core versions of the existing GL bindings, without any compatibility profile features (functions & constants). This is applicable to OpenGL only.
  2. Being able to use all GL11 - GLXX features by statically importing only the GLXX class. This is important for OpenGL because it's old and has many versions, but it's equally applicable to AL, ALC, CL, EGL, GLX, GLES, VK.

I've been doing some experiments and it looks like we cannot easily have both 1 and 2 without breaking compatibility of the OpenGL bindings. The cleanest solution seems to be adding a separate class hierarchy GL11Core, GL12Core, ..., GL46Core and an LWJGL application uses either the existing classes or the core versions, but never both. Any other approach that I tried was either binary incompatible (apps compiled with 3.1.6 wouldn't work with 3.1.7) or source incompatible (javac is too sensitive about ambiguous static imports, even if all resolve to the same method/field in the same class).

If anyone has a better suggestion, please let me know. If a solution is clean enough that justifies breaking changes, we could defer it to LWJGL 3.2.0.

Having tried this in practice, I can see the value of having clean bindings for the core profile, as @hypernewbie suggested. There's a significant cleanup of the API, not only of deprecated functions, but also of constants. On the other hand, I still believe that being able to access all GL versions up to the version that has been statically imported is not terribly exciting. But if it helps new users, then why not.

So, I'm looking for feedback on the available options:

  1. Add the GL11Core, GL12Core, ..., GL46Core classes, with only core profile functionality and no hierarchy between them. Users will have to statically import each one separately.
  2. Option 1, but each core class extends the core class of the previous OpenGL version. Users statically import only the core class with the minimum required OpenGL version, which provides all functionality up to that version.
  3. Option 2, but do the same for the current, "compatibility profile" classes too (a separate hierarchy).
  4. Option 3, but make AL, ALC, CL, EGL, GLX, GLES, VK hierarchical too.
    X. Your idea here.
@Spasi

This comment has been minimized.

Copy link
Member

commented May 31, 2018

Btw, instead of starting with GL11Core, we could merge 11 to 31 and start with GL31Core, since that was the first version that dropped the deprecated functionality. Or even skip that and start with the more practical GL32Core.

@Spasi

This comment has been minimized.

Copy link
Member

commented May 31, 2018

Option 4 has been implemented in the glcore-154 branch. I ended up using GL11C, GL12C, ..., GL46C for the new classes. If you'd like to try it out, a build is available here: https://build.lwjgl.org/res/lwjgl-opengl-core.zip (sources, classes and Windows x64 natives).

@Spasi Spasi closed this in 689fc84 Jun 14, 2018

@Spasi

This comment has been minimized.

Copy link
Member

commented Jul 10, 2018

A binary incompatibility has been reported: kotlin-graphics/imgui#42. The library has been compiled with 3.1.7 snapshot but the application runs on an earlier version. The problem is that javac compiles:

import static org.opengl.GL33.*;
// ...
glGetInteger(...);

as GL33.glGetInteger(...) instead of GL11.glGetInteger(...).

There are workarounds if the library wants to support earlier LWJGL versions, but still, I'm considering bumping the next release from 3.1.7 to 3.2.0, to signal the potential for incompatibilities.

@jmaasing

This comment has been minimized.

Copy link

commented Aug 27, 2018

I know this is closed but I want to say that I started my project in 3.1.7 and ran into the same questions as OP. The new 4xC classes really made it easier. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.