Learn from Irrlicht the API Mapping Between OpenGL and Direct3D

Published May 10, 2012 by Issam Lahlali, posted by IssamLahlali
Do you see issues with this article? Let us know.
Advertisement

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. In some cases the development team could decide to move from OpenGL to Direct3D, or from Direct3D to OpenGL or even provides a multirendering solution. And to make the task easy we need a good documentation about the API mapping between the two API. Another solution could be to discover the API mapping from an existing source code. Irrlicht 3D engine is a good candidate for this purpose. it 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. CppDepend and CQLinq will be used to help us to identify some code elements from the source code. 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.

irrelicht8.png

Both DirectX and OpnGL renders are implemented. the COpenGLSLMaterialRenderer, COpenGLShaderMaterialRenderer, CD3D9ShaderMaterialRenderer and CD3D9MaterialRenderer are the base classes for all the other rendering classes. OpenGL renders Let's search for all classes inheriting from COpenGLSLMaterialRenderer and COpenGLShaderMaterialRenderer directly or indirectly:

irrelicht3.png

DirectX renders Let's search for all classes inheriting from CD3D9ShaderMaterialRenderer and CD3D9MaterialRenderer directly or indirectly:

irrelicht4.png

How Irrlicht could help us for the mapping? Let's suppose that you need to migrate a code from OpenGL to Direct3D implementation. And in our code the function glTexEnvi is used and we want to know the equivalent in Direct3D. First Step: Search where in Irrlicht the function is used.

Irrlicht5.png

Choose one method using it. Let's take as example OnSetMaterial in COpenGLMaterialRenderer_SOLID. Here' its 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); 
	} 
} 

Second step: Find the equivalent in Direct3D Irrlicht implements both OpenGL and Direct3D, and for each rendering class from Direct3D, there's an equivalent for OpenGL. The equivalent of COpenGLMaterialRenderer_SOLID class is CD3D9MaterialRenderer_SOLID. Here's the implementation of OnSetMaterial from the Direct3D render:

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); 
} 

Discover all the OpenGL and Direct3D functions used in Irrlicht

Fortunatly Irrlicht uses many functions from both APIs, and you will certainly find most of your Direct3D or OpenGL functions used in your code. Let's take as example irr::video::CD3D9Driver and search for the Direct3D functions used:

irrelicht5.png

And we can do the same with the irr::video::COpenGLDriver class

irrelicht6.png

Conclusion

Irrlicht is a good candidate to discover how to map functions between the two APIs. This 3D engine is mature and very well implemented. You can easily search for an API function and find how it's implemented for the other one.

Cancel Save
0 Likes 7 Comments

Comments

Krohm

I have used OpenGL for years and I consider myself fairly well versed in some Direc3D versions as well. I don't understand how those evaluations can be relevant. The reported snippets are engine-dependent and don't map to any operation I recognize.

I find this cutting it short.

October 16, 2014 07:02 AM
AgentC

Indeed, the problem is that it should be comparing Direct3D API calls vs OpenGL API calls, instead of any calls to the engine's internal helper functions.

When I look at my own engine's (D3D9 and OGL2) graphics code I actually find that the raw code size is less for the OpenGL renderer. However analyzing just code size doesn't necessarily capture the complexity of the logic required to implement same operations, and it doesn't tell whether the programmer is using the API in the most optimal way.

My personal experience is that Direct3D usually gives a well-defined way of doing some thing, and you don't have to doubt whether it's the fastest way or not. While OpenGL, due to its history, will give multiple ways, and in the worst case you just have to guess the "fast path".

One example I can give where OpenGL code can end up significantly more complex is rendertarget switching: on Direct3D it's just a few calls (set rendertarget, set depth stencil). On OpenGL you will have to implement somewhat complex logic of creating several framebuffer objects (for example sorted by texture size and format) then assigning the color and depth attachments to them. If you just use simply one FBO to which you attach everything, you will encounter performance loss on some OSes and driver versions. In this case the total code size (API calls + your internal logic) can easily end up 10 times larger for the OpenGL version.

Then, an opposite example: investigating a compiled shader's uniforms. On OpenGL it's a few straightforward function calls, while on Direct3D the API itself deals with just precompiled shader byte blobs, so instead you will have to use the shader compiler library reflection facilities, which results in more verbose code. Also, if we talk of WinRT Metro style applications published to the store, they are not allowed to link to the shader compiler DLL (even just for reflection) so you would basically end up implementing your own shader reflection data structures.

These are of course extreme examples: in operations related to just drawing the API call ratio is much closer to 1 : 1.

October 16, 2014 07:36 AM
IssamLahlali

I have used OpenGL for years and I consider myself fairly well versed in some Direc3D versions as well. I don't understand how those evaluations can be relevant. The reported snippets are engine-dependent and don't map to any operation I recognize.

I find this cutting it short.

What's interesting is to know how many Lines of code I need to do the same thing. In the case of Irrlicht the OpenGL implementation of their renders has more line than the DirectX one.

As you say the reported snippet is engine dependent, for this reason in the conclusion I said that the verbosity is more dependent to the engine implementation choices and not to OpenGL or DirectX APIs.

October 16, 2014 08:59 AM
SeanMiddleditch
There's also the question of forward-compatibility. Which versions of OpenGL does Irrlicht support? Does it support GLES? Is it ready for D3D12/Mantle/Metal?
November 26, 2014 09:03 PM
Radikalizm

Irrlicht definitely isn't the right environment to do these kind of API comparisons in. It's not up to date with the most recent version of either API (as far as I know there's no support for any DX version after 9) and its general design is just not really that great.

If you really want to do a comparison of equivalent functionality in both OpenGL and DirectX just do a proper analysis of the APIs themselves instead of giving a shallow overview of an outdated - the last major release was over 2 years ago, and the last bugfix release over a year - and irrelevant engine.

November 26, 2014 11:13 PM
ongamex92
Also, if we talk of WinRT Metro style applications published to the store, they are not allowed to link to the shader compiler DLL (even just for reflection) so you would basically end up implementing your own shader reflection data structures.

This is no longer true. The D3DCompiler*.dll is available since Windows Phone 8.1

November 27, 2014 08:47 AM
fafase

So mainly, what this does is search and find methods.

Alt+F12 in Visual Studio.

November 27, 2014 08:45 PM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!

Discover from the Irrlicht source code, how to map functions between OpenGL and Direct3D.

Advertisement

Other Tutorials by IssamLahlali

Advertisement