We have made a few significant refactors of our low-level OpenGL(ES) code, to support better both modern GPUs, ancient GPUs and mobile GPUs. Everybody wins! 🙂
Modern GPUs
We have now much better support of new OpenGL features. If we have shaders, we know we have shaders from “core”, and we initialize them with the same code everywhere. Same for FBO (Framebuffer Object). Most new GPUs support now OpenGL 4.x. So for many things, we can just assume that modern OpenGL will have them in “core”.
So we have implemented a code path using 100% “core profile” OpenGL 3.3 context (using deprecated stuff is prohibited). To force using it, set TGLFeatures.RequestCapabilities
to rcForceModern
. Or pass command-line option --capabilities=force-modern
. Or in CGE editor click “Run -> Run Parameters -> Force Modern Rendering Context (–capabilities=force-modern)”.
Our upgraded renderer:
- Automatically converts quads to triangles as modern OpenGL(ES) API don’t support quads.
-
Uses image formats without luminance, instead we use texture swizzle.
-
Creates and uses Vertex Array Buffer.
-
Queries OpenGL(ES) extensions in new way
-
Uses shadow samplers following OpenGL(ES) core
The default is a smart choice. We create a “compatibility” context, and
- if it has a new OpenGL version — we will actually use only the new API , just like from “core” profile. As mentioned above, OpenGL >= 2 implies a lot of things (VBO, shaders) and we will use them. Later versions also imply some nice things, e.g. OpenGL >= 3 implies FBO.
-
However, if the provided OpenGL version will be low (< 2), we will automatically set
GLFeatures.EnableFixedFunction
totrue
, and follow ancient fixed-function rendering path.
This makes the approach “automatic”, and it is indicated by (default) TGLFeatures.RequestCapabilities
value of rcAutomatic
.
Our treatment of old GPUs is now simpler
If you don’t have OpenGL 2, then we assume you also don’t have a lot of other things (we will not even try to use them through old extensions). Without OpenGL 2, we assume you never have shaders or even VBO. To be precise, GLFeatures.Shaders
is now always a simple negation of GLFeatures.EnableFixedFunction
, same for GLFeatures.VertexObjectBuffer
.
This makes things actually better for these ancient GPUs: it means that their support is more reliable. It is easier to write and test one simple “ancient fixed-function” code path when it doesn’t have so many variations. And you can test it easily: just set TGLFeatures.RequestCapabilities
to rcForceFixedFunction
from code. Or pass command-line option --capabilities=force-fixed-function
. Or in CGE editor click “Run -> Run Parameters -> Force Ancient Rendering Context (–capabilities=force-fixed-function)”, then run as usual (F9 or click the button).
Rendering on such old systems supports unlit or Phong lighting. Some modern rendering features are not available (like PBR or shadow maps), but simple games will manage.
The renderer was really tested with actual OpenGL 1.1 implementation available on some Windows 2016 servers 🙂
Switching between modern and ancient OpenGL
We have a new command-line option --capabilities=automatic
(or
--capabilities=force-fixed-function
or --capabilities=force-modern
). It is available in all CGE applications (TCastleApplication.ParseStandardParameters
handles it, and it is called from CastleAutoGenerated
unit).
We also have a new menu items in CGE editor to easily set it “Run -> Run Parameters -> …”.
view3dscene and the CGE editor itself also support these options. So you can test how does editor behave on ancient OpenGL implementations, just run it like this: castle-editor --capabilities=force-fixed-function
.
Mobile
Finally, the end result is also good for OpenGLES (usually on mobile, though it also works on desktop if you want). It is more consistent now with desktop OpenGL, bringing many rendering improvements to OpenGLES and simplifying the code in the process too. E.g. shadow maps now just depend on OpenGL ES 3, and use almost the same code as on desktop OpenGL, with shadow samplers in GLSL.
I wrote more about mobile improvements in this post.
Testing
I have also added a test application examples/research_special_rendering_methods/test_rendering_opengl_capabilities/. It exercises all rendering methods:
-
TCastleScene
(unlit, Phong, PBR, also textured versions of them). -
TCastleRenderUnlitMesh
-
TDrawableImage
I have also extended default OpenGL 1-line report to contain vendor name and “modern rendering” (not GLFeatures.EnableFixedFunction
), since they are important information about your GPU. It looks like this now:
Rendering Initialized: OpenGL 4.6 (Nvidia) (modern rendering: True) (for more info: LogGLInformationVerbose:=true)
The verbose report (the one you see if you enable LogGLInformationVerbose
, you also can see it in CGE editor, use “Help -> System Information”) is also improved in many ways — more relevant stuff reported, better order.
Also our GLSL usage in now more modern
We advise you to not declare any #version
in your GLSL code, and internally we will add a modern #version
and also define a few macros that turn lowest-supported GLSL versions into modern versions. See CastleGLShaders
unit for more comments.
We also automatically define precision for OpenGLES
fragment shader, if you didn’t do it automatically.
Debugging
You can use OpengGL debug context feature. Just set TGLFeatures.Debug
.