Skip to main content
gamedev.net
🔒 Locked

Using multiple renderers for an engine

Started by Poontardis Oct 13, 2000 at 8:42 AM 8 replies 300+ views
Original Post
Poontardis
Poontardis
Howdy, I''m currently in the planning stages of a project in which I hope to offer the user a choice of renderer (OpenGL or D3D). I''d like to implement this through a common interface (the code - not the choice ). For example something like: r_DrawPoint3f(0.3, 0.3, 8.1); which would point to the corresponding OpenGL or D3D code depending on the current renderer. What I''d like to know is what sort of level the interface needs to be at: e.g. high level - r_DrawQuad(v.x1, v.y1, v.x2, v.y2); lower level - r_BeginQuad; r_Vertex3f(... r_Vertex3f(... ... r_EndQuad; I have a lot more experience in OpenGL than in D3D (basically I know sod all about D3D) and so I''m unsure how to structure the interface. Ideally I''d go off and learn D3D and be able to come up with the ideal interface, however I am under tight time constraints and will have to learn D3D as I go along. Any help or pointers to existing source code of this type will be GREATLY appreciated. Cheers in advance for any replies.
havoc
havoc
Look into MESA library. It has driver, which wrap OpenGL calls to Direct3D calls
MK42
MK42
I haven''t looked at MESA for a long time, but MESA is an OpenGL-clone and it can do its drawing by using DirectDraw ... not D3D, if I''m correct. The last time I looked at it, a 3Dfx/Glide DLL was available, so it''s quite possible that a D3D driver exists. This is not what Poontardis asked for, though.

Here goes:

I think, the higher level you go, the easier will it be to implement functionality in BOTH APIs. For some low-level things of OpenGL (such as the glVertex-stuff), there is no equivalent in D3D. If you want something performant, then you wouldn''t use these functions anyways. Things get much simpler, if you lowest level call is a DrawTriangle(). Again, this would just be used for rapid-prototyped stuff and won''t be performant. Things get more interesting, if you batch process like 1,000 triangles. Then you can start thinking about vertex-arrays in OGL and VertexBuffers in D3D. So, the higher-level your interface is, the better performance you will get. Unfortunately, that will mean more (and sometimes duplicate) code in both renderers.

It''ll be very hard designing an interface which is flexible, as well as performant. If you just want functionality, then start with initialization, mode-setting (depth, alpha, blending, etc...) and DrawTriangle ... if you want some more performance, try a batch-interface.

Well, that''s my two cents worth,

MK42

crazy-vasey
crazy-vasey
How about using dll's? Have the GL funcs in one dll and the D3D funcs in another then just call the appropriate dll at runtime.

My Homepage

Edited by - crazy-vasey on October 13, 2000 5:42:43 PM
MK42
MK42
crazy-vasey:

I think that''s what he means to do in the end. But, in order to do this you have to find a good interface for your DLL ... that''s what the question is about.

- MK42
Poontardis
Poontardis
Correct, MK42. And thanks to you all for the replies.

MK42 - I need control down to drawing individual points, lines and polygons, along with texture mapping quads. The points, lines + polygons of various materials should be no problem if I use vertex buffers. Would it be possible to wrap the following commands to D3D so that they would work correctly?:

r_SetCurrentTexture(345) (gl equiv. = gl_BindTexture(GL_TEXTURE_2D, 345))
r_EnableTextures() (glEnable(GL_TEXTURE_2D))
r_DisableTexutes() (glDisable(GL_TEXTURE_2D))

etc...

If using the r_SetCurrentTexture() function with an integer to represent the sesired texture, then I think I should be able to do what I want. I hope

Cheers.
MK42
MK42
Sounds like it could work (the texture thing). I tried doing a similar thing a while back, but discontinued the project due to lack of time. I used an OO approach, so I had a Baseclass for textures, and derived a class for D3D and OGL. The ''engine'' class allocated a texture and returned it. Using something like Texture::Select(), I was able to select the texture, etc... but the enable/disable should go to the renderer class/interface. Sorry, I''m not thinking straight C here

Anyways, going down to the point/line level IS possible, but you won''t get the best performance, since it''s not a good programming practice in general. With todays hardware accelerators, it''s necessary to batch as many operations as possible.

I don''t think you should try to teach Direct3D the OpenGL begin/end rendering paradigm. So you should stick to something like r_DrawPoint() and r_DrawLine().

Good luck with this,

MK42
wazoo69
wazoo69
I''m doing *something* along the same lines, though it''s tough
to keep everything generic enough to seperate your graphics API from your game code..

for starters, I''ll define some a basic function in a .h file

BOOL (* initCard)(int width, int height, int bpp);
BOOL initCard_OGL(int width, int height, int bpp);
BOOL initCard_DX(int width, int height, int bpp);
BOOL initCard_GLIDE(int width, int height, int bpp);

obviously in each of the 3 separate init functions I drop in
my initialization code for each card respecively

Now, I have a base function that I call during program init

bool createCard(int id){
switch(id){
case OPENGL:
initCard = initCard_OGL;
//..any other functions here too
break;
case DIRECTX:
initCard = initCard_DX;
//..any other functions here too
break;
case GLIDE:
initCard = initCard_GLIDE;
//any other functions here too
break;
}

return TRUE;
}

now when I want to initialize my graphics hardware, in my
initialization area (after calling createCard of course), I
can just simply call..

initCard(640, 480, 16);

which will initialize our hardware to whatever we had passed
into our createCard function..

I think you can see where I''m heading with this...

If somebody has any better suggestions, please post as I''m
always looking for ways to improve this..

AND I first did this using virtual class library, which made
the code neater but I felt a C implementation would be faster
than a c++ overhead..

would putting this into separate DLL''s be better?? maybe..
assembly?? probably..

Wazoo

MK42
MK42
wazoo69:

Your way is a possibility of doing this, although I doubt that a C++ implementation is noticeably slower.

I mean, using virtual functions adds one indirection to your code. That''s nothing compared to the other parts of your code.

Also some things, which are ''better'' in a C++ implementation:

You don''t have that many global variables, the code is easier to maintain. Managing a class is much simpler, than managing a host of function pointers, etc...

Yours might be a tick faster than C++, but I don''t think it''s worth the effort.

Putting this in a DLL is nice, since you can then work on the renderers individually and change/update them without having to recompile your program. When doing that you should only have ONE exported function, which accepts a struct and passes all the necessary data there. You can do some pretty nifty things with DLLs

I also don''t see how assembly will make stuff like card initialization and API management any faster...

MK42
Poontardis
Poontardis
Wazoo,

Using a set of generic functions which are set to point to the functions for the current renderer at setup is exactly the way I was intending to go. (Christ that was a long and poorly constructed sentence )

Or I might create a base renderer class with virtual pure functions which the derived specific renderer code must fill in. This would work fine if I cast the specific class instance as the generic type.

MK42 is right, .dlls are a good way to go as you can use exactly the same interface for each one and you only need one line of code to select the appropriate .dll at startup. I don''t see the point of straight c over c++ either, any overhead from class/functionindirection would be minimal (not even 1 fps I shouldn''t think).

I''ve got no problem with this sort of stuff though anyway - the problem was gauging the level at which to pitch the interface. I''m still on the brink of scrapping the whole idea and just sticking with plain OpenGL as I just don''t have the time to learn D3D before starting the project.

Cheers for the suggestions. If I decide to go with the multiple renderer idea and I get it working, I''ll put the code on the web and post a link here (don''t hold your breath). If the code''s of an decent quality I could open it up as an open project for anyone to help improve on and use for their own games/apps. I''ve got a lot of planning to do before I start coding anyway, so this wouldn''t happen for a loooonnnngggggg time.

Laters.





Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.