flareteam / flare-engine

Free/Libre Action Roleplaying Engine (engine only)
http://flarerpg.org/
GNU General Public License v3.0
1.11k stars 187 forks source link

OpenGL rendering #757

Closed rinnert closed 10 years ago

rinnert commented 11 years ago

Hello,

I have a fork of the engine over here at 'rinnert/flare-engine'. I have moved all the code related to rendering to the screen to a rendering backend interface I introduced. I also changed some code I wasn't forced to for improved performance. The majority of the engine source files was touched (uh-oh).

As of now, I merged all upstream changes that appeared after I forked. I'll try to continue to do so in order to make an eventual merge (should it ever happen) as painless as possible for everyone else.

Right now there is a SDL_BLitSurface and an OpenGL rendering implementation. As far as I can tell both are fully functional. But you guys probably have many more save games and such for testing. It would be nice if you could give this a try and give me some feedback.

I have only tested this on Linux (Xubuntu 12.04 LTS) with fairly decent NVIDIA GPU and proprietary drivers. However, I don't use any extensions in the OpenGL backend. So I expect this to be portable. I observe ~50% less CPU usage in play state with OpenGL. It's also nice to have vertical sync! (In fullscreen only. As I said, no extensions.)

To try it out, you can either clone the whole thing or just get the 'glflare-rc1.0' tag.

To build with OpenGL support you have to do 'WITH_OPENGL=yes cmake'. Then you can enable OpenGL rendering with 'opengl=1' in settings.txt. With 'opengl=0' (default) the same build will run with the SDL_BlitSurface rendering backend.

There is a minor bug in the flare-game assets which causes a rendering artifact with OpenGL rendering. You should set the the height of the XP bar to 10 instead of 18 in fantasycore/menus/xp.txt to make it look right. (I opened an issue in flare-game about this. But no-one cares as they can't see it -- yet.)

I did this for my own education. No big deal if you don't like it. It would be very nice, though, if some of you could give it a try and provide some feedback.

I, for one, enjoy the game more with this engine. :)

cheers,

Kurt

P.S. I really like the game. My compliments to everyone, especially the content creators!

dorkster commented 11 years ago

(I've submitted a PR to fix the XP menu here: https://github.com/clintbellanger/flare-game/pull/347)

First off, let me say wow, this is some dedication. Unfortunately, I'm not sure we want to go with a straight-up OpenGL implementation. I believe @igorko has done some work moving the engine to use SDL2, which abstracts the usage of OpenGL rendering. That implementation is more in line with our current usage of SDL. It's also nice because I believe SDL2 will auto-magically fall back to SDLBlitSurface when OpenGL doesn't work, instead of having it be an engine setting on our side.

Does anyone know any advantages/possible issues when using plain OpenGL as opposed to SDL2's abstraction of OpenGL?

rinnert commented 11 years ago

Hey, that's interesting. Will SDL2 really just let you SDL_BlitSurface to 'screen' and do everything else auto-magically? I'm asking because this distinction was the major part of my work (everything going to 'screen' is a Renderable, handled by the RenderDevice interface). The actual OpenGL code is not very much. @igorko, maybe you can comment on this?

Bertram25 commented 11 years ago

Hi, IMHO, the concept of using render devices should be at least considered.

Best regards,

Bertram25 commented 11 years ago

@rinnert Hi :) Btw, did you consider trying to port th gl code to the 3+ norm? This could actually help about performance and avoid using legacy code, if I'm correct.

Best regards,

rinnert commented 11 years ago

@Bertram25 Hello,

yes, you are absolutely right! :) Getting rid of immediate mode is the way forward. I'm planning to move to retained mode/buffer objects. I think that's what you mean by '3+ norm'?

I just wanted to achieve correctness before complicating the back-end code. There are still some glitches I have to iron out...

cheers, Kurt

P.S. In that context (no pun intended), I don't think it's possible that any abstraction in SDL2 can do that. The very concept of blitting to the screen is an immediate mode paradigm.

Bertram25 commented 11 years ago

Hey :)

I think that's what you mean by '3+ norm'?

Yeah, indeed, I meant the OpenGL 3+ specs and the removal of quads glBegin()/End() mostly.

P.S. In that context (no pun intended), I don't think it's possible that any abstraction in SDL2 can do that. The very concept of blitting to the screen is an immediate mode paradigm.

I do think you're right. Yet, I'd need to know more about SDL2 to make sure they aren't using other methods to get things done.

Good luck on your way toward all that and best regards,

pennomi commented 11 years ago

As big a fan as I am of OpenGL, I suppose the biggest concern is code portability. Right now Flare can run on an astonishing number of devices; it would be a pity if we lost some of them.

For instance, technically Flare can run on Android and iOS, so any OpenGL implementation would also have to be supported by OpenGL ES.

stefanbeller commented 11 years ago

One way to handle that would be a bunch of #ifdefs to select opengl or sdl1 at compiletime. This would make it theoretically available on /more/ platforms, but you'd be forced to do more configuring at compile time (set the option whether to use opengl or sdl).

pennomi commented 11 years ago

Plus, with two implementations, if the rendering algorithm changed, it'd have to be maintained in two places.

rinnert commented 11 years ago

@pennomi @stefanbeller Hello,

I fully agree! :)

Just to be clear: I did not get rid of the SDL blit rendering. In fact I did exactly what Stefan suggested. :) If the engine is build with OpenGL support you have a choice at run time (more specifically at start up). Also, you can build without depending on OpenGL at all. The latter is actually the default if you just run 'cmake'. It's a high priority not to ruin it for anyone.

That's also why the concept of a rendering device is useful: you can enable/disable any of them at run and/or compile time. :) And the rendering is done through the same interface. So changes in the game state logic are entirely independent of the rendering back-end. I'm usually more in the 'abstraction is selective ignorance' camp. However this is one clear example where it is really useful.

There are still too many #ifdefs scattered around in the code (not that many, but still). I'll try to abstract these away after fixing some other stuff...

cheers, Kurt

clintbellanger commented 11 years ago

I'll decline having explicit OpenGL code in Flare 1.0. I don't think the added complexity is worth it for our very simple 2D games.

I don't mind migrating to SDL 2.0 at some point, if it gets us OpenGL hardware acceleration "for free". Similarly I'd be open to migrating to SFML later, if SDL 2 doesn't pan out for whatever reason.

I much prefer we use simple, standard blit calls and let the media layer do any heavy lifting for us. This approach works in every language and every 2D graphics framework. Makes the code easy to translate and port when we keep it simple.

Flare 2.0 is a different story. Whatever you guys agree on is completely fine for the future of Flare. But 1.0 will be simple and stable and maintained for a long time.

(Also, as always, I'm open to being wrong about this and accepting OpenGL!)

rinnert commented 11 years ago

@clintbellanger Hello Clint,

I wasn't even remotely suggesting to include anything like this in any upcoming release. :)

Just thought people might be interested in having look and maybe give me some suggestions. Which is what happened, so thank you all very much! Espcially you, Clint, for creating this great project in the first place!

cheers, Kurt

clintbellanger commented 11 years ago

@rinnert No sweat! When I get some time this week I want to clone your repo and poke around. Even if I don't plan to make 3D-heavy games in the near future it'll be good for me to learn some of that.

pennomi commented 11 years ago

I'm probably shooting at the moon here, but since Flare has all 3D assets anyway, it would be possible to do something fancy like real 3D with nice lightning for Flare 2.0... I'm actually learning the relevant OpenGL stuff right now and once you get past the initial shock, it's not so bad. Of course, this would probably cripple games like Polymorphable, et al.

rinnert commented 11 years ago

@clintbellanger Incidentally, 'No sweat!' is a nice one -- it's very hot where I am and I have no AC. :) If you get around to look at the code, keep in mind that using OpenGL immediate mode is considered bad style (as discussed above). I plan to keep improving things to make it as simple, efficient and good style as possible. Just for fun.

To be honest, if you want to learn about how to do things properly in OpenGL, the current state of my fork is probably not the best place to start... I hope it will be in the not too distant future.

There are other changes not related to how things are ultimately rendered you might find interesting, though.

Thanks again and have fun!

Kurt

rinnert commented 11 years ago

@pennomi It might sound funny, after all I started this thread. But I actually like the way the game looks very much! I find the 2D isometric style and the way the art is done very appealing. Also the idea of having a simple engine and asset interface, making it easier to create content (for which I unfortunately have no skills whatsoever :( ).

I stumbled on this project when looking for a game that would run without problems on my -- less than powerful -- Linux netbook. After a short time the lack of VSync annoyed me. So I thought 'use the source'. :)

There are also a lot of things you can do in 2D to make things look more lively. For instance animated tiles for water and trees. But that's on the asset side.

Of course, using shaders for some lighting and other effects in the OpenGL back-end also came to my mind. :) That doesn't need 3D, though.

Independent of that, a 3D version would certainly be a cool project to work on.

I'm rambling...

TL;DR I like it the way it looks and want to run it on my netbook. Otherwise 3D would be cool project.

igorko commented 11 years ago

Hi guys. Don't have much time now even to read this issue :) Please look into my branch at flare-game called SDL2_Textures. It's on experimenting stage, but game loads into map (while map is not rendered yet)

rinnert commented 11 years ago

@igorko Hello :) I didn't have a chance to look at your code yet because I was busy coding in my fork... You say you didn't read the thread, so just so you know: by now I have a fully functional OpenGL renderer (as well as old scool blitting). You might want to have a look; I did quite some refactoring that might benefit your efforts. You can find it at 'rinnert/flare-engine'.

hean01 commented 11 years ago

Nice work @rinnert , im looking into GL ES 2.0 for making flare 2.5D with lightning support using shaders and texture maps: diffuse+ao+spec, im definitly gonna take a look into your effort.

Here's the initial example:

screenshot from 2013-06-23 15 40 31 screenshot from 2013-06-23 10 29 40

There is no light falloff nor specular map yet.. i need to get my math around the lightsource placement.

I have played alot making flare lightningaware :), i have an older example of realtime shadows for the 2d SDL engine as you can see here: http://www.youtube.com/watch?v=Dfh4_jXCrO4

hean01 commented 11 years ago

@rinnert did you base your fork with the floating point changes ?

rinnert commented 11 years ago

@hean01 that looks very nice!

Before you get too excited: I'm not using 3D assets and have no plans to do so. I'm simply creating textures from the 2D assets plaster them on vertices in the x-y space.

However, I'm planning to implement another render device that conforms to GL 3 core specs (right now all is done with deprecated fixed function pipelines in immediate mode). I'm not planning to use GL 3 specific features, so I understand this is essentially the same as going in the GL ES direction? Once this is done is should be good starting point for anyone who wants to get more fancy. It will take a while, though, because I have to learn all this first. Help and ideas are certainly most welcome!

As for the floating point movement, I thought this is not yet ready? I have merged everything from the master branch of Clint's repository since I forked.

hean01 commented 11 years ago

@rinnert I think you got me all wrong, the lightning is done using plain 2D assets, composed from 3 texture maps mapped on quads. The texturemaps are rendered in 3 different ways, one diffus (no lightning just texture color), one AO (Ambient occlusion) and one normal map. From those 3 textures we can have dynamic lightning for the 2D assest and my current implementation is using shaders for rendering this.

The screenshots are a texturedmapped quad using shaders with the above mentioned 3 textures.

rinnert commented 11 years ago

@hean01 Great! In that case it will be not too hard to plug in once I have a shader-based render device. :)

igorko commented 11 years ago

Let me explain what I have done. You, guys, can use my work to go further because I have no time for developing currently. SDL2_support branch: rendering is done in the same way as before, all is rendered to surface(screen). Then surface is converted to texture, which is rendered to Renderer. This was bad effort because we don't get any profit from using SDL2 textures. SDL2_Textures branch: I have tried to load images directly to textures where possible. Then render textures to renderer. In most cases this is done in such way. The problem is in some places we still need to blit one image on another so we still should use surface. E.g. we want to draw button not on screen(renderer) but on scrollbox. So button should have function to be drawn on both screen(renderer) and surface(another widget). In my understandning button should have two overloaded rendering functions. And I dunno how to do this without a lot of IFs.

rinnert commented 11 years ago

@igorko sounds all very familiar to me. :) I essentially did what you did in your SDL2_Textures branch, albeit with a little more abstraction and, of course, with OpenGL textures. Everything going to the screen is a Renderable rendered by a render device. I solved the daughter widget problem by allowing the Renderables to have a local reference frame and let the render device deal with it. Right now, this is only used in the scroll box widget and in the NPC action menu. No rendering to temporary surfaces anymore (at least not per frame; the minimap is still pre-rendered to a surface on map change).

Having all this infrastructure already, it will be rather easy for me to implement an efficient SDL2 texture render device.

Using SDL2 requires some changes independent of the rendering (like SDLKey -> SDL_KeyCode and such). I would harvest/merge these from your code.

One question: did you make any effort to support SDL 1.2 and SDL 2 in the same code branch and then decide at build and/or start up time what to use? This is actually a question to the community in general. Would you want that? Or would you prefer an SDL2-only branch that supports nothing else?

igorko commented 11 years ago

I have used ifdefs, so result depends on which SDL version you are using to build the game. How is better(ifdefs or separate branch) is really a question to community. But deciding on startup time imho is bad solution because this will require to have two sdl versions to build the game, and some platforms can lack sdl2 support.

igorko commented 10 years ago

@rinnert , @Bertram25 , @pennomi , @hean01 Me and @dorkster just have finished SDL2 port. You can find it here https://github.com/igorko/flare-engine/tree/SDL2port, If someone interested, you can try to add such nice features as day/night support, lights, shadows and weather. Enjoy!

hean01 commented 10 years ago

Nice... @rinnert hows the status of your opengl backend ?

Bertram25 commented 10 years ago

Yes, indeed, really nice! :) Flare 1.0 isn't out yet, and it seems Flare 2.0 isn't that far away. ;)

Is it planned to get it merged somehow?

igorko commented 10 years ago

@hean01, @rinnert doesn't respond already a lot of time. On his work was based our SDL2 approach.I think it would be better to continue work using SDL2 API instead of OpenGL. Two APIs will make the game harder to compile and add more dependencies. As we know SDL2 just wraps OpenGL so you should be able to use required functionality from SDL2 API without linking to OpenGL.

@Bertram25 SDL2 version will be in different branch but it's code is compatible now with 0.x master

Bertram25 commented 10 years ago

@igorko I, for one, try not to maintain more than the needed branches in a spare-time project. (Bet you see why. :]) What is preventing SDL2 to be used since the 1.0 version isn't out, and because 0.19 just went to release mode? Are you fearing unsolvable problems with SDL2? Or are there technical changes that don't fit to master according to @clintbellanger ?

igorko commented 10 years ago

AFAIK most devs decided to have SDL1 and SDL2 version as separate games with as more as possible compatibility. But this can be still discussed.

Bertram25 commented 10 years ago

Well, this is just my opinion of course, but would Flare 1.0 be released in something like 3-6 months, you would have the time to polish the two versions anyway.

Now I understand the point is to deliver the most stable engine. And, if it happens the engine stability is more or less the same between the two sdl versions at release (and I hope it will), I guess the most capable one in term of performance and features will win the heart of game makers. ;)

Now, maybe there are portability issues?

clintbellanger commented 10 years ago

Currently the plan is for Flare1 to be based on SDL1, and Flare2 to be SDL2.

SDL1 does enjoy much wider support on older devices, and we've worked on lots of features targeting such devices. I'd have to know that SDL2 works well on those platforms before I'd consider moving Flare1 to SDL2.

But Flare2 isn't simply "Flare with SDL2". It should come with many more features for game makers. E.g. real support for random item tables, dynamic lighting maybe, possibly random dungeon support, that kind of thing. Whatever people are actually wanting to use in their games should be considered for Flare2. Getting SDL2 support is just the first milestone towards making a Flare2.

Bertram25 commented 10 years ago

SDL1 does enjoy much wider support on older devices, and we've worked on lots of features targeting such devices. I'd have to know that SDL2 works well on those platforms before I'd consider moving Flare1 to SDL2.

Thanks for the answer. Now, i guess flare 1.0 will have to wait for its first story before release?

igorko commented 10 years ago

@hean01 If you will find out that using lights on pure SDL2 is slow or requires a lot more of code then openGL, we can link to openGL. Currently flare-engine depends on sdl_input, sdl_font and sdl_mixer alongside of "sdl_renderer" so we can't use pure openGL for flare. We still can replace all with SFML, which afaik supports dynamic lighting, but this will require another huge effort.

igorko commented 10 years ago

So we will not support openGL backend in flare 1.0. Closing this issue. @hean01 , as the main reason of making GLES2 backend is adding dynamic lighting, please post any info in flare-engine-next issue here https://github.com/dorkster/flare-engine-next/issues/9. Also it would be cool to see your progress in openGL backend (screenshots, videos)