CatinaCupGames / Dissonance-Prototype

A prototype for an action RPG game named Dissonance
2 stars 0 forks source link

Render Engine Rewrite Discussion #107

Open ecp4224 opened 10 years ago

ecp4224 commented 10 years ago

So me and @roboman2444 were talking about how the Dissonance render engine should be moved out of OpenGL 1 spec and upgrade to OpenGL 3 spec. And I think this would be the perfect opportunity to rewrite the main Render Engine.

This issue is made to discuss the rewrite that will take place after the release of the demo (June 4th).

My current thoughts:

_Allow for multiple implementations of a renderer:_ We will have an interface name Renderer that will have the following methods exposed:

void start()
void render()
void terminate()

void fadeToBlack(speed)
void fadeFromBlack(speed)
void fadeToAlpha(speed, alpha)
void waitForFade()
void removeScale()
void resetScale()
void provideData(object, type)
World getCurrentDrawingWorld()

The RenderService class will still be a Service class, however, the way it behaves will be slightly different.

First, onUpdate will not do anything until a Renderer object is provided using the provideData method. Once one is present, it will invoke the start() method in it, then onUpdate will invoke render() on it until the Service is terminated.

To prevent breaking changes, all RenderService's method will remain intake and will simply be marked as deprecated. However, they will continue to work by invoking the equivalent method in the Renderer object.

_Planned Renderers:_

OpenGL1Render - This is the current implementation of the renderer engine and will remain in the engine incase of old hardware
OpenGL3Render - This will be the new implementation of the renderer engine and will be the default in the engine

_Prevent breaking of Sprites:_ Sprites are a big part of the engine, so if we add breaking changes to the Drawable interface, UpdatableDrawable interface, Sprite class, or the AnimatedSprite class, then all hell will break loose.

We need to prevent this from happening, while at the same time changing how they render. Luckily, there are 2 simple ways to go about this.

  1. Simply change the render() method in Sprite and AnimatedSprite. Since most children of the Sprite and AnimatedSprite class do not change the render method (and if they do, they still invoke the super's method), we can change this method without breaking anything. However, this means that the sprite either needs to be aware of what Renderer is being used (OpenGL1 or OpenGL3), or it must only use one.
  2. Create Render Jobs. All sprites do the same thing, draw a quad and apply a texture to it. We could have the current Renderer return a Render Job for the sprite everytime one is added to the World, so that sprite will not have to be aware how it's rendering the sprites. This also makes implementing opengl 3 batch jobs easier. If a Drawable is being added to the World that is not a sprite, then it can implement a Render Job and handle rendering itself.

The down side to number 1 is messy code, but the upside is easy coding The down side to number 2 is complex code, but the upside is the ability to extend the API.

I personally would like to go with number 2, but number 1 would also work.

_Is OpenGL3 really needed?_ Remember, this is an ARPG game. Is the performance increase we will get when we upgrade to OpenGL3 really worth the hardware requirement we add? I'm not sure how common OpenGL3 is among graphic cards and what kind of users we will be kicking out with this requirement, but hopefully the implementation idea suggested above will allow those people not on OpenGL3 to enjoy Dissonance with a different Renderer.

roboman2444 commented 10 years ago

Render Jobs is the better way to do it. The api wouldn't be too hard to do, just have something that is addSpriteToRenderJob(shader s, texture t, sprite data); and then order it by a tree. This would minimize shader switching firstly, and texture switching secondly, and could easily be used to batch the sprites. Of course, you would have other functions for adding in world tiles to the render batch system, but all functions would end up adding data to one batch.

ecp4224 commented 10 years ago

One thing I have a concern with about batching is, how do we sort the Sprites? I know depth testing and alpha blending don't mix well (and we _do_ need alpha blending), so how do we combat this? Or will sorting not be affected..?

Again, I'm not familiar with OpenGL 3 spec, so I have no clue.

roboman2444 commented 10 years ago

We can always either have multiple batches, one for transparent stuff and one for alpha tested/opaque stuff. Alpha tested stuff will probably use the same shaders as opaque stuff, just a different permutation. It wont need separate paths in the pipeline.

Before rendering the second batch, we will set blending and depth testing modes. The stuff in the transparent batch would be sorted by depth of course. Batching where it needs to be sorted isn't as useful, because it has to be drawn in the order of depth. We can always do some smart algorithms that try to group things together or not sort them if they don't overlap eachother, in order to batch more efficiently.

Also, the alpha blended stuff WILL also be alpha tested. If the a pixel is completely transparent on the sprite, there is no need to try and write it.