6 ms·
Good answer. I would add that, despite all of them being low-level, Metal is quite easier than the other two, and DirectX 12 is also easier than Vulkan, despite
by whstl 3y ago
Good answer. I would add that, despite all of them being low-level, Metal is quite easier than the other two, and DirectX 12 is also easier than Vulkan, despite having very similar concepts and ideas. This is in part due to API decisions and differences in verbosity, in part due to the "easier" ones having less flexibility. If your ultimate goal is to master Vulkan, starting with another can help. Also: OpenGL and DirectX are easier than those 3.
If I were learning those APIs today, I would personally start with either OpenGL, Metal or DirectX 11 (or 12 if you're slightly braver). They can give someone lots of insights that one can use when learning Vulkan.
Like other people mentioned, WebGPU or WebGL are also more straightforward and a good starting point.
- alexarnesen 3y agoIf you are looking to dig into Metal, this site and book might be useful. I have no graphics background and found it accessible. Metal By Example https://metalbyexample.com/ https://metalbyexample.com/
- pjmlp 3y agoA better one with Swift, https://www.amazon.com/Metal-Programming-Guide-Tutorial-Reference/dp/0134668944 https://www.amazon.com/Metal-Programming-Guide-Tutorial-Refe...
- flohofwoe 3y agoThe big advantage of not using OpenGL is that D3D11, D3D12 and Metal all have excellent validation layers which tell you exactly what's wrong when you mess something up. In OpenGL you're pretty much left alone, staring at that black screen. Xcode and Visual Studio also have builtin graphics debuggers for Metal and D3D11 (not sure if the VS debugger also supports D3D12 though).
- reactordev 3y agoBecause you forget to call glGetError and do the error check on your previous call. In a world where we are driven by exceptions, not excepting and requiring you to check is actually a good thing, you wouldn’t want a shader param exception from panicking your game in the middle of a gun fight.
- flohofwoe 3y agoglGetError() is useless unfortunately for getting any information about what went wrong, because it only has 8 error codes: https://registry.khronos.org/OpenGL-Refpages/gl4/html/glGetError.xhtml https://registry.khronos.org/OpenGL-Refpages/gl4/html/glGetE... There's a debug output extension (or core feature since 4.3) that's slightly more verbose, but not universally supported (e.g. AFAIK not on macOS).
- CyborgCabbage 3y agoWhat about Debug Output? https://www.khronos.org/opengl/wiki/Debug_Output https://www.khronos.org/opengl/wiki/Debug_Output
- whstl 3y agoThat's a fantastic point. As much as I managed to do stuff in OpenGL for decades, it was definitely left behind DX and Metal in terms of API ergonomics.
- drawkbox 3y ago> WebGPU or WebGL are also more straightforward and a good starting point. WebGL and WebGPU also show some of the difference in how rendering libraries have evolved. They used to be all "stateful" global state like OpenGL/OpenGL ES. WebGL followed that model as it was simple and needed for the time, but could have bugs if correct flags weren't set. WebGPU and other newer rendering libraries (Vulkan, Metal, and Direct3D 12) are more "modern" in that they have almost no global state. They are also more raw and lower level and take a bit more to grok. This is one of the best overviews of the differences between WebGL/WebGPU but also is similar to how OpenGL to Vulkan, Metal, and Direct3D 12 evolved. https://webgpufundamentals.org/webgpu/lessons/webgpu-from-webgl.html https://webgpufundamentals.org/webgpu/lessons/webgpu-from-we... > The biggest difference is WebGL is a stateful API and WebGPU is not. By that I mean in WebGL there is a bunch of global state. Which textures are currently bound, which buffers are currently bound, what the current program is, what the blending, depth, and stencil settings are. You set those states by calling various API functions like `gl.bindBuffer`, `gl.enable`, `gl.blendFunc`, etc…, and they stay what you set them globally until you change them to something else. > By contrast, In WebGPU there is almost no global state. Instead, there are the concepts of a pipeline or render pipeline and a render pass which together effectively contain most of the state that was global in WebGL. Which textures, which attributes, which buffers, and all the various other settings. Any settings you don’t set have default values. You can’t modify a pipeline. Instead, you create them and after that they are immutable. If you want different settings you need to create another pipeline. render passes do have some state, but that state is local to the render pass. > The second-biggest difference is that WebGPU is lower level than WebGL. In WebGL many things connect by names. For example, you declare a uniform in GLSL and you look up its location > `loc = gl.getUniformLocation(program, 'nameOfUniform')`; > Another example is varyings, in a vertex shader you use `varying vec2 v_texcoord` or `out vec2 v_texcoord` and in the fragment shader you declare the corresponding varying naming it `v_texcoord`. The good part of this is if you mistype the name you’ll get an error. > WebGPU, on the other hand, everything is entirely connected by index or byte offset. You don’t create individual uniforms like WebGL, instead you declare uniform blocks (a structure that declares your uniforms). It’s then up to you to make sure you manually organize the data you pass to the shader to match that structure. > Note: WebGL2 has the same concept, known as Uniform Blocks, but WebGL2 also had the concept of uniforms by name. And, even though individual fields in a WebGL2 Uniform Block needed to be set via byte offsets, (a) you could query WebGL2 for those offsets and (b) you could still look up the block locations themselves by name. > In WebGPU on the other hand EVERYTHING is by byte offset or index (often called ‘location’) and there is no API to query them. That means it’s entirely up to you to keep those locations in sync and to manually compute byte offsets. For a time, supporting four rendering engines did cause lots of work for game engines, much more integration and abstraction. As OpenGL support fades at least one will drop off. I will miss it as I do still love OpenGL/WebGL. OpenGL and OpenGL ES / WebGL in particular opened up mobile/web gaming in ways never before possible. Prior to that you had Director (3D), Flash (Papervision/Away3D/etc), Silverlight and more recently `<canvas>`. Canvas is great for smaller games but you need raw power for rendering 3d and WebGL (almost a direct port of OpenGL ES) brought that and engines like three.js use that well. Mobile gaming became the biggest gaming market due to OpenGL ES and web games took a leap on WebGL, also apps, interactives and tools became faster rendered. With GL, in many cases the global state is more simple, but to take advantage of GPUs and rendering lower level the innovations were needed. The naming to index/position based for instance is lower level and can also end up in bugs just as the global state in GL could. The benefit is performance and cleaner global state. It is probably a good idea to learn OpenGL/WebGL as some of the concept in WebGPU/newer engines will be more clear, much of it was simpler with naming.
- WCSTombs 3y agoOf those three, Vulkan is the only one that is cross platform, and the only one that natively targets Linux.
- slimsag 3y agoVulkan requires a heavy-weight emulation layer on macOS. Consoles also don't really support it (some do, but not as a first class API) If you only care about Windows and Linux, you can also just use DirectX and require users make use of Proton.
- vetinari 3y ago> Vulkan requires a heavy-weight emulation layer on macOS. That's pretty much self-inflicted issue. > If you only care about Windows and Linux, you can also just use DirectX and require users make use of Proton. Proton drags in Wine, so it is even more heavy-weight than MoltenVK.
- ho_schi 3y agoPlease no! Don’t use Proton as API. It is a compatibility layer trying to implement what Microsoft’s implementation probably does. Use Vulkan or OpenGL if you can. Proprietary APIs? In 2023 we shall all know to avoid them. It is not 1998. The unfortunate move from Apple is Metal instead of going all in for Vulkan. And now they struggle and need foster native ports. They shall support itself Vulkan and improve it - and therefore improve support of Linux and MacOS.
- shortrounddev2 3y agoOpenGL straight up sucks to work with. DirectX 11 is a much nicer API that doesn't require you to write your own allocator for views in the GPU like the lower level APIs. Linux isn't a major platform I personally care about so I use DirectX 11
- iforgotpassword 3y agoPlease yes! ... At least for commercial, closed source stuff. I'm exclusively on Linux, a casual gamer, and native ports suck. They probably can be done better, but you still run into the problem that some Linux game released 5 years ago doesn't even launch anymore on current distros. I've tried to play the native port of lis2 only to be greeted with a "hey this game needs an AMD or Nvidia GPU" warning, which I could click past only to have the whole system freeze in the main menu. That was literally the first ever crash of that machine ever (about 14 months old at that point). Luckily steam allows you to force using the windows version of a game even if a native port is available and guess what, no warning about GPU, game worked flawlessly. And it very likely still will a decade from now. How many native games released today will? Morale of the story: win32 is the only stable userspace API on Linux. Develop for win32 and test on Linux, boom you got your multi-platform game.
- omoikane 3y agoNote that DirectX is left-handed, while OpenGL, Metal, and Vulkan are all right-handed. Other things that use right-handed coordinate system include Blender, Godot, and my physics textbook, so left-handed coordinate systems is something of a minor annoyance for me. But then, Unreal Engine is left-handed, so maybe some people prefer that.
- cmovq 3y agoThis really doesn’t matter. It’s only something you need to care about in your rendering backend. The rest of your engine can use whatever coordinate system you want, and you do the conversion as part of your transforms.
- flohofwoe 3y ago> Note that DirectX is left-handed, while OpenGL, Metal, and Vulkan are all right-handed. This was only relevant in the past when 3D APIs implemented fixed function vertex processing. Today this is just a contract between your CPU-side code and your shader code. There are other other subtle coordinate system differences though, like the framebuffer and/or texture origin being in the top-left vs bottom-left, or clip space z ranging from -1.0 to +1.0 or 0.0 to +1.0.