Direct3D and OpenGL are competing application programming interfaces (APIs) which can be used in applications to render 2D and 3D computer graphics. They are the two most popular graphics APIs utilized in game development.
Probably the most recurrent debate between the two APIs has to do with their relative performances, which concern more the end user. In this post we will discuss their verbosity, which impacts more the developers using them.
To compare the verbosity of the two APIs, let’s analyse with CppDepend the Irrlicht 3D engine source code which implements both DirectX and OpenGL renders.
The Irrlicht Engine is an open-source high-performance realtime 3D engine written in C++. It is completely cross-platform, using D3D, OpenGL and its own software renderers. The Irrlicht rendering logic is implemented in the irr::video namespace, and the base interface for material rendering is
irr::video::IMaterialRender.
Let’s search for all the classes implementing directly the irr::video::IMaterialRender interface.
Both DirectX and OpnGL renders are implemented. the COpenGLSLMaterialRenderer, COpenGLShaderMaterialRenderer, CD3D9ShaderMaterialRenderer and CD3D9MaterialRenderer are the base classes for all the other rendering classes.
Let's export the result of the previous query to the dependency graph:
In this graph the rectangle size is proportionel to the size of code, and as we can observe the OpenGL rendering base classes are bigger than the DirectX ones.
The fact that the OpenGL base classes are bigger does not mean that the OpenGL implementation is more verbose, but it could mean that the OpenGL rendering implementation has more common rendering code than DirectX. therefore we have to compare the implementation of all the renders inheriting from these base classes.
OpenGL renders
Let's search for all classes inheriting from COpenGLSLMaterialRenderer and COpenGLShaderMaterialRenderer directly or indirectly:
The OpenGL renders implementation has 548 lines of code.
DirectX renders
Let's search for all classes inheriting from CD3D9ShaderMaterialRenderer and CD3D9MaterialRenderer directly or indirectly:
The DirectX renders implementation has 296 lines of code.
Like the rendering base classes, the sum of the OpenGL implementation rendering classes is more than the DirectX ones.
To investigate more this difference let’s compare the implementation of the method OnSetMaterial in COpenGLMaterialRenderer_SOLID and CD3D9MaterialRenderer_SOLID classes:
DirectX implementation
OpenGL implementation
As we can observe, the logic of setting basic states for DirectX is centralized in one method, however for OpenGL we need 6 lines of code. But this difference could be due to the developers implementation choice. And maybe the setBasicRenderStates of Directx include the lines added in the OpenGL implementation.
Let's search for all setBasicRenderStates methods:
The COpenGLDriver::setBasicRenderStates method is more bigger than CD3D9Driver::setBasicRenderStates. which makes the OpenGL implementation more verbose.
Another more reliable indicator to check the verbosity concerns the number of calls to the external API library needed to do some treatments.
Let’s take as example the big classes irr::video::COpenGLDriver and irr::video::CD3D9Driver from the rendering logic and check how many calls they need.
Let's search for all the OpenGL functions called directly or indirectly from the COpenGLDriver class:
The OpenGL driver needs 72 calls to the OpenGL API.
And concerning the CD3D9Driver class:
The DirectX driver needs 66 calls to the DirectX API.
When searching the web for which of the two APIs is more verbose, more developers say that DirectX is the most verbose one, however it's not necessarily true, it depends more on the the developer's design and implemenation choices.
For example, in this case of the Irrlicht engine, the OpenGL implementation is more verbose than the DirectX one, and it could just as well be the inverse for other game engines.
Probably the most recurrent debate between the two APIs has to do with their relative performances, which concern more the end user. In this post we will discuss their verbosity, which impacts more the developers using them.
Comparing the DirectX and OpenGL
To compare the verbosity of the two APIs, let’s analyse with CppDepend the Irrlicht 3D engine source code which implements both DirectX and OpenGL renders.
The Irrlicht Engine is an open-source high-performance realtime 3D engine written in C++. It is completely cross-platform, using D3D, OpenGL and its own software renderers. The Irrlicht rendering logic is implemented in the irr::video namespace, and the base interface for material rendering is
irr::video::IMaterialRender.
Let’s search for all the classes implementing directly the irr::video::IMaterialRender interface.
Both DirectX and OpnGL renders are implemented. the COpenGLSLMaterialRenderer, COpenGLShaderMaterialRenderer, CD3D9ShaderMaterialRenderer and CD3D9MaterialRenderer are the base classes for all the other rendering classes.
Let's export the result of the previous query to the dependency graph:
In this graph the rectangle size is proportionel to the size of code, and as we can observe the OpenGL rendering base classes are bigger than the DirectX ones.
The fact that the OpenGL base classes are bigger does not mean that the OpenGL implementation is more verbose, but it could mean that the OpenGL rendering implementation has more common rendering code than DirectX. therefore we have to compare the implementation of all the renders inheriting from these base classes.
OpenGL renders
Let's search for all classes inheriting from COpenGLSLMaterialRenderer and COpenGLShaderMaterialRenderer directly or indirectly:
The OpenGL renders implementation has 548 lines of code.
DirectX renders
Let's search for all classes inheriting from CD3D9ShaderMaterialRenderer and CD3D9MaterialRenderer directly or indirectly:
The DirectX renders implementation has 296 lines of code.
Like the rendering base classes, the sum of the OpenGL implementation rendering classes is more than the DirectX ones.
To investigate more this difference let’s compare the implementation of the method OnSetMaterial in COpenGLMaterialRenderer_SOLID and CD3D9MaterialRenderer_SOLID classes:
DirectX implementation
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_
{
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
{
setTextureColorStage(pID3DDevice, 0,
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
}
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
}
OpenGL implementation
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
bool resetAllRenderstates, IMaterialRendererServices* services) _IRR_OVERRIDE_
{
if (Driver->getFixedPipelineState() == COpenGLDriver::EOFPS_DISABLE)
Driver->setFixedPipelineState(COpenGLDriver::EOFPS_DISABLE_TO_ENABLE);
else
Driver->setFixedPipelineState(COpenGLDriver::EOFPS_ENABLE);
Driver->disableTextures(1);
Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
if (resetAllRenderstates || (material.MaterialType != lastMaterial.MaterialType))
{
// thanks to Murphy, the following line removed some
// bugs with several OpenGL implementations.
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
}
As we can observe, the logic of setting basic states for DirectX is centralized in one method, however for OpenGL we need 6 lines of code. But this difference could be due to the developers implementation choice. And maybe the setBasicRenderStates of Directx include the lines added in the OpenGL implementation.
Let's search for all setBasicRenderStates methods:
The COpenGLDriver::setBasicRenderStates method is more bigger than CD3D9Driver::setBasicRenderStates. which makes the OpenGL implementation more verbose.
Number of calls needed to the OpenGL and DirectX APIs
Another more reliable indicator to check the verbosity concerns the number of calls to the external API library needed to do some treatments.
Let’s take as example the big classes irr::video::COpenGLDriver and irr::video::CD3D9Driver from the rendering logic and check how many calls they need.
Let's search for all the OpenGL functions called directly or indirectly from the COpenGLDriver class:
The OpenGL driver needs 72 calls to the OpenGL API.
And concerning the CD3D9Driver class:
The DirectX driver needs 66 calls to the DirectX API.
Conclusion
When searching the web for which of the two APIs is more verbose, more developers say that DirectX is the most verbose one, however it's not necessarily true, it depends more on the the developer's design and implemenation choices.
For example, in this case of the Irrlicht engine, the OpenGL implementation is more verbose than the DirectX one, and it could just as well be the inverse for other game engines.