Direct3D vs OpenGL
Which API is the best choice for a 3D engine, OpenGL or Direct3D ?
Pros and cons of both API
Here are the drawbacks and advantages of both interfaces :
- + Easier to use to start. More intricate after.
- + Portable on several platforms, including Linux
- - Switching render target (for shadows, secondary cameras...) awkward on old 3d cards
- - Shitty drivers on small 3d card manufacturers (Intel, Via, Sis, S3 & co).
- - Drivers very hard to develop as the user have too much freedom of action
- + Easier to use for advanced features
- + Better rendertarget switching
- + Better drivers on slow/old cards (Intel, Sis, Via, S3...)
- + Much better debugging tools: Pix360, NvPerfhud, Pix Windows, D3D-debug...
- + Portable quite easily on XBox and 360
- - Performance problem when displaying lots of different objects
The main OpenGL drawbacks are rendertarget switching and shity drivers on low end 3D cards. The first problem disappear when we want to render modern shadows: the cards that do not support FBO (FrameBuffer Objets) are also unable to run modern shaders.
But if our product also targets old/slow 3D cards (Geforce <= 4, maybe some slow Geforce FX, Radeons 8500 and under, Intel, Sis, S3...), then these problems become huge negative points. Programming with the ugly PBO and fighting drivers bugs will get really annoying.
Direct3D has a major design problem. It has been developed and optimized at a time when games were displaying few objects, and still today it cannot render a big amount of objects quickly. Each primitive rendering makes the CPU switch from protected mode 3 (applications) to level 0 (Os kernel), which causes a stall.
If in a fps or in 3dmark, that's no problem (as they are few objects, each object having many triangles), it gets very painful in RTS (many units) or in a 3D SimCity-like (many different buildings which may be animated).
To fix that, an extension has been provided in Direct3D 9 : instancing, which make it possible to display several times the same object at different positions. But this is useful only when an object is repeated often and when all instances are exactly at the same moment of its animation. Plus it does not work on older cards.
The only solution is to animate vertexes on the CPU, and to generate each frame a meta-object that contains all the small objects using the same texture/shader.
D3D10 and above actually fix that.
Is the perfect solution to use OpenGL-ES, which is "OpenGL light" containing only the main most useful features and which is far easier to implement on 3D cards?
Update on October 2008
An interesting link: OpenGL 3 & DirectX 11: The War Is Over on tomshardware.com.
Also, debugging tools make the balance lean heavily toward D3D.
Side note - quick comparison of PC vs concoles
Today's PC are quite more powerful than Gen3 consoles.
But consoles have some advantage on features that helps programming:
- the depth buffer can be read ; no need for a depth prepass with rendering in a color buffer that will be later used as a readable depth buffer on PC.
- antialiasing quite simpler to set up, particularly when rendering off the screen buffer (and risks of drivers bugs, as we found on my latest game - confirmed by the maker which fixed that in his latest driver).
- on consoles, all game's shaders can be loaded quickly when starting the game, which will speed up level streaming later ; even (tens of) thousands of shaders. On PC, a blue screen of the death will appear after a given number of shaders (this number depending on their complexity) ; the limit seems to be related to a fixed size Kernel memory block allocated to the graphic driver.