toxicTom: That's what I meant - frameworks take care of that - at the cost of optimisation for a specific platform. And the PC platform is extremely difficult in itself with its wide range of hardware combinations, drivers and OS's.
dtgreene: C + OpenGL ES should be portable to any modern syatem that supports OpenGL ES or full OpenGL. In particular, the same code should run on both a desktop and a Raspberry Pi. (For Android or iOS, you might need to write some code in another language to bootstrap it, but you should still be able to reuse most of the C code.)
Also, don't forget things like SDL.
(Note that these things are libraries that abstract out OS/hardware differences, not frameworks that do everything for you, so it should still be good enough to get good speed. After all, many emulators (of 8/16-bit systems, not for modern consoles like the PS5) use SDL and still run well on lower-end systems.)
The problem is the productivity. C and its dialects are for techies, let's be honest here. And there's simply not enough of those to create the masses of games in all their variety we have today.
I mean, I tip my head to anyone capable to complete complex project this way and thus produce a performant product - game or not, but those people are rare specialists.
SDL is pretty impressive though.
I think it's actually the mobile market that still drives the need for optimisation. There's money in making things work on those tiny and often outdated machines. Often through garbage business practices, but money no less. Without this, the situation would be even worse.
toxicTom: Shader languages are - in my understanding - a perpetuation of the principle. You can either go native and implement your own optimised code for every platform, or you can rely on frameworks like D3D, Vulcan or OpenGL to do the work for you. Correct me if I'm wrong, the stuff I do is all boring business stuff with no use for shaders :-)
dtgreene: In modern graphics APIs, you really can't get any lower in level than the likes of GLSL or similar. (Well, you might be able to write SPIR-V by hand, but even that is abstracted away from the actual instruction set used by the hardware.)
D3D (from DirectX 11 or earlier) and OpenGL (3.0 and up) are libraries that handle some lower level details for you, but are still at a pretty low level, much like in C. It can still be quite tedious to write even simple examples with these APIs, particularly since you need both a vertex shader and a fragment shader just to draw a triangle (the hello world of 3d graphics programming). I would compare this to writing in C.
Vulkan (and DX12/Metal) is lower level, to the point where I'd compare it to writing assembly. Even the triangle example I mentioned above takes many hundreds of lines to set everything up. (Looking online, I find an example that's over 1,000 lines of code, but note that many of them are comments meant for those learning Vulkan, so that number is inflated somewhat.) It's bad enough to the point where there exists libraries like V-EZ and vk-bootstrap that exist solely to reduce the amount of boilerplate code needed for Vulkan.
(Older OpenGL versions use the fixed function pipeline, which is less work for simple examples (since you don't have to write shaders), but less flexible (since you can't write custom shaders, though it appears that 2.x has the beginnings of that.)
Thanks for the explanation. Yeah I've seen Vulcan code (without being able to read it) and it reminded me of Assembly. I thought it was a mistake actually, that someone posted intermediate language instead of the real code... I'd have thunk Vulcan more abstracted.
Explains why it's not as successful while having a good reputation in terms of performance.