Sign in to follow this  
Nene

Abstraction in game engines

Recommended Posts

Hi!! In most game engine books, abstraction of the graphics API and other subsystems is one of the main concerns. This supposes the use of interfaces and DLLs, as well as having to implement our own subsystems from scratch, such as a mathematics system. But in some cases it means reinventing the wheel (DirectX already offers its Extended Library). Now my question... If we decide to use DirectX as the core technology -like many games do-, is that abstraction actually used in commercial games? For instance, many console games are platform-specific, and some PC titles like Crysis support only DirectX. However, although Crysis does not support OpenGL, I'd like to know how they manage to support DirectX 9 and 10 at the same time. CryEngine3 is being ported to consoles, so I suppose every commercial game use these abstraction layers. In that case, does it mean D3DX is not used commercial games? I'd really appreciate some clarification. Thank you guys

Share this post


Link to post
Share on other sites
I don't know for sure, but I suspect the abstraction layers will still exist. Even if the rendering library is the same, the requirements and practices surrounding it might change based on the platform it's running on.

Share this post


Link to post
Share on other sites
Quote:
Original post by Nene
In most game engine books, abstraction of the graphics API and other subsystems is one of the main concerns.
True.
Quote:
This supposes the use of interfaces and DLLs

Hell, no! Practical abstraction of graphics interfaces is targeted towards multiplatform development. That means a windows build, an XBox build, a Linux build (heh), etc. In other words, abstraction is compile-time, not runtime; no need for anything but a statically chosen graphics layer going into the executable. Choosing between DirectX and OpenGL at runtime, IMNSHO, is useless, timewasting gimmickry.

Quote:
If we decide to use DirectX as the core technology -like many games do-, is that abstraction actually used in commercial games?
Yes, for the reasons of multiplatform capability I mentioned. But you've changed your question in the middle there. The concerns of 150-man development teams with a $60M budget are considerably different from the concerns of a five-man team with a fuckall budget. If you decide to use DirectX as the core technology, you probably do not need an all-singing all-dancing abstraction layer.

Share this post


Link to post
Share on other sites
Thanks! Although there is no point in switching between DirectX and OpenGL at run-time using DLLs, switching between D3D9 and D3D10 might be different. In Crysis, for example, there is only one executable and you switch from D3D10 to D3D9 passing -dx9 as a parameter. That means the corresponding DLL is loaded at initialization time, right? Or maybe embedding the two implementations in the same build is a better option, what do you think?

If I decide to use DirectX 9.0c as the core technology, how can I switch to DirectX 10, 11, etc. in a future? I see exactly the same problem as if we wanted to support OpenGL and DirectX, so an API-independent layer is still required although our game is DirectX-based after all, right?

Also, the D3DX library changes as well on each iteration of DirectX. Although some structures and functions remain the same, some of them do not. For example:


HRESULT D3DX10CreateTextureFromFile( // D3DX10
ID3D10Device *pDevice,
LPCTSTR pSrcFile,
D3DX10_IMAGE_LOAD_INFO *pLoadInfo,
ID3DX10ThreadPump *pPump,
ID3D10Resource **ppTexture,
HRESULT *pHResult
);

HRESULT D3DXCreateTextureFromFile( // D3DX9
LPDIRECT3DDEVICE9 pDevice,
LPCTSTR pSrcFile,
LPDIRECT3DTEXTURE9 * ppTexture
);




Do you know what solutions use professional developers?

I appreciate your answers

[Edited by - Nene on June 23, 2009 12:50:39 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Nene
If I decide to use DirectX 9.0c as the core technology, how can I switch to DirectX 10, 11, etc. in a future?
By changing your code. Writing an abstraction layer that abstracts out everything you think could possibly change between graphics systems will be both overkill and futile.

Share this post


Link to post
Share on other sites
If I read correctly, directx 11 will handle if dx 10 or 9 will be used depending on whether the graphic card supports dx 10...

http://www.softwaretipspalace.com/blog/?p=455

This means that all we got to do is learn dx 11 for those going directx, and programming dx 11 on xp should not be a problem. Correct me if I'm wrong. ><

Share this post


Link to post
Share on other sites
Quote:
Original post by Twinblad3r
If I read correctly, directx 11 will handle if dx 10 or 9 will be used depending on whether the graphic card supports dx 10...

http://www.softwaretipspalace.com/blog/?p=455

This means that all we got to do is learn dx 11 for those going directx, and programming dx 11 on xp should not be a problem. Correct me if I'm wrong. ><

No, not on Windows XP. Direct3D 11 will run on Windows Vista, Windows 7, and all future Windows operating systems.

Share this post


Link to post
Share on other sites
Quote:
Original post by Nene
Also, the D3DX library changes as well on each iteration of DirectX. Although some structures and functions remain the same, some of them do not. For example:

*** Source Snippet Removed ***

Do you know what solutions use professional developers?

I appreciate your answers


Well, I can give you my solution: I created an ITexture interface that offers anything that is needed by the application in a simpler manner. Getting the width, height, aquiring a surface, etc...
This ITexture can be created by IVideoDevice which is implemented for a specific subsystem (as is the ITexture ofcourse). This may not be the best solution, as every call invokes a vtable lookup, however I'm a hobby developer and I really like this approach.

Another way would be to use the pimpl idom, so you only have a pointer in your ITexture interface, that points to the right implementation:


//ITexture.h
class ITexture
{
private:

class pimpl *d;

public:

int width() const; // notice the "non-virtual" here
};

//ItextureDX9Impl.cpp
class ITexture::pimpl
{
// Here's the actual implementation
};



You would simple switch the cpp files to use the DX9 or DX10/11 implementation. Maybe this can even be done better, but this is one approach.

Abstracting in general is very important, as I really hate to deal with those ugly DirectX functions in my application. I have to look up the documentation about all those parameters and do the FAILED check, which results in 10 lines of code, at least. Abstracting this stuff is really helpful:
I no have an IStaticMesh and IDynamicMesh interface that both offer all the functions I need in a much simpler manner (I only need to pass my favourite vector of choice with the vertices & indices: no more dealing with pointers).
But be careful and really think what is important and what not, my "engine" underwent several changes because I invented stupid interfaces, or didn't separate enough.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
Quote:
Original post by Nene
If I decide to use DirectX 9.0c as the core technology, how can I switch to DirectX 10, 11, etc. in a future?
By changing your code. Writing an abstraction layer that abstracts out everything you think could possibly change between graphics systems will be both overkill and futile.


Also, programming a D3D10 app as you would a D3D9 app isn't going to gain you anything. D3D10 (and D3D11) really comes into play when you design your rendering backend to take advantages of their strengths and the API properly.

Just naively converting function calls without reconsidering your rendering path isn't going to do you any favours.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
By changing your code. Writing an abstraction layer that abstracts out everything you think could possibly change between graphics systems will be both overkill and futile.


But commercial games cannot allow being re-written for D3D9, D3D10, etc. They must work with its own rendering interface. I suppose that engines like CryEngine 2/3 have this abstraction layer, but with a rendering pipeline already set up to support full D3D10 capabilities. I guess they thought in D3D10 from the beginning of the engine design, and then added D3D9 support for compatibility purposes. When a new API iteration is released, the engine might be fully revised or rewritten. Is that what you mean?


What happens with D3DX?

Share this post


Link to post
Share on other sites
This is one case where I also advocate adding a wrapper for abstraction. What you're aiming for may be less of having it work on multiple platforms, but instead actually avoiding the dreaded vendor lock-in. The problem is that in today's requirements, DirectX may be the way you're going, but you simply can't visualize three years ahead with certainty and know that that will always be the plan. The moment the plan changes, management will on you assuming it's an easy task to switch and wondering why you coded things so poorly that transitioning to a different system can't be done. On some teams, management will begrudgingly accept the difficulty of the task and on some they will start looking for a new team.

In the case of DirectX or OpenGL as a whole, anyway, I find the APIs are written too low level to be used directly and so naturally I am writing higher level classes around them as I'm working through, so the overhead of making these classes API-independent becomes further reduced.

Of course you have to weigh the trade-offs, and sometimes getting it done now 10% more quickly is more valuable than having to spend 50-100% effort to refactor/rewrite later (Caveat: I find that this is less often the case than most people perceive, however).

Share this post


Link to post
Share on other sites
Quote:
Original post by SneftelBy changing your code. Writing an abstraction layer that abstracts out everything you think could possibly change between graphics systems will be both overkill and futile.

So basically you're calling the work on Unreal Engine 3, Ogre, and Irrlicht both overkill and futile? That's simply rediculous.

Share this post


Link to post
Share on other sites
Quote:
Original post by Halifax2
Quote:
Original post by SneftelBy changing your code. Writing an abstraction layer that abstracts out everything you think could possibly change between graphics systems will be both overkill and futile.

So basically you're calling the work on Unreal Engine 3, Ogre, and Irrlicht both overkill and futile? That's simply rediculous.


just because they do, doesn't mean you should.
after all, they have development teams .


Share this post


Link to post
Share on other sites
Quote:
Original post by Matt_D
just because they do, doesn't mean you should.
after all, they have development teams .

Exactly my point. You shouldn't even be making a game engine in the first place, but rather picking up an existing one that has been made by a development team already and helping to improve it. Thus gaining your desired experience.

At any rate, I find that just "changing your code" is highly inefficient. By abstracting away to a higher level you have the advantage of possibly enlisting future developers to work in tandem with another API.

Share this post


Link to post
Share on other sites
Quote:
Original post by Halifax2
Exactly my point. You shouldn't even be making a game engine in the first place, but rather picking up an existing one that has been made by a development team already and helping to improve it. Thus gaining your desired experience.

well, in some cases, there isnt an engine out there which fits your purpose, or perhaps you want to write an engine. An off the shelf option isnt always viable in all cases.

Quote:

At any rate, I find that just "changing your code" is highly inefficient. By abstracting away to a higher level you have the advantage of possibly enlisting future developers to work in tandem with another API.

[/quote]
in realistic terms, its more about the frequency of change. Graphics API's tend to change rather infrequently, and unless your really trying to target disparate platforms or your intending on bolting your engine on top of someone elses (to use as a UI engine for example, and thus will need to use someone else's renderer) its really not worth wrapping the entire lot.

there are advantages, but there is also cost, weigh the two up, do the one that has the most beneficial outcome.

Share this post


Link to post
Share on other sites
Thank you all for your piece of advice. I've been reading a little and skimming through some open-source game engines like WildMagic and Ogre. Most of them create wrapper classes and their own math system. I think the wisest option is to stick with DirectX at all. So much abstraction is useful if are in a professional team that plan to port its engine to other platforms. For a programmer like me, it makes no sense. I am very comfortable working with DirectX and Windows is the standard platform for gaming. It's always tempting to build your own game engine, but sometimes it might be more beneficial to put your efforts on improving your skills in graphics, AI, maths, physics, etc. rather than reinventing the wheel just for fun.

Share this post


Link to post
Share on other sites
Quote:
Original post by Nene
But commercial games cannot allow being re-written for D3D9, D3D10, etc.
They don't have to. A game written for DX9 will work fine on DX11 or DX12 or any other version for the forseeable future.

Share this post


Link to post
Share on other sites
Quote:
Original post by Halifax2
So basically you're calling the work on Unreal Engine 3, Ogre, and Irrlicht both overkill and futile?
No, you misread.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
Quote:
Original post by Halifax2
So basically you're calling the work on Unreal Engine 3, Ogre, and Irrlicht both overkill and futile?
No, you misread.

Yes, it does appear as though I misread. Sorry Sneftel.

Share this post


Link to post
Share on other sites
Quote:
Original post by Nene
Thank you all for your piece of advice. I've been reading a little and skimming through some open-source game engines like WildMagic and Ogre. Most of them create wrapper classes and their own math system. I think the wisest option is to stick with DirectX at all. So much abstraction is useful if are in a professional team that plan to port its engine to other platforms. For a programmer like me, it makes no sense. I am very comfortable working with DirectX and Windows is the standard platform for gaming. It's always tempting to build your own game engine, but sometimes it might be more beneficial to put your efforts on improving your skills in graphics, AI, maths, physics, etc. rather than reinventing the wheel just for fun.


What better way to learn those things then writing your own engine. Just because you are reinventing the wheel doesnt mean it will take all your time... a very simple forward renderer using DX is not that big of a deal to write with all the samples out there, and then you can work on other subsystems with it. I think there is a lot of value in writing your own engine, and an importance in understanding just what the heck a renderer is doing with your model or game object. Then again, what is your purpose? if your purpose is to write a 3d fps game in 2 months, then yeah, you might want to grab an engine. however if you are trying to expand your skills, then writing a simple renderer and implementing subsystems would work. Personally, i think expanding on an existing engine is cool and all, but can be frustrating and time consuming learning the code base. DX9/10, OpenGL, whatever. Those are APIs, in the end they should be somewhat invisible to the user and the experience (unfortunately isnt always the case, save for some/all? blizzard games)



Share this post


Link to post
Share on other sites
The reasons for abstracting may be many, but the most important one is to reduce the usage complexity of the code such as rendering. You abstract away the vertex buffer, frame buffer, loading, shaders, and all this code so that the user is not bothered with the details and can efficiently develop at a high level.

As long as the user uses these high level objects their interface is "guaranteed" to be the same regardless of the under-lieing implementation. If you needed to switch to d3d11 and all you did was support the your existing feature set, this would take place below the abstraction layer and all the user code would remain the same.

It's only when you want to take advantage of new features will your abstraction interface change.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this