Luomu / pioneer

space simulation adventure game
http://pioneerspacesim.net/
7 stars 1 forks source link

Renderer architecture #4

Closed Luomu closed 12 years ago

Luomu commented 12 years ago

Perhaps "renderer" is not quite the correct term, but try to have this easier to extend/replace. Think for example what a GLES port would require.

Luomu commented 12 years ago

Underway

Luomu commented 12 years ago

(Pasting what I have written so far here, don't have time right now to edit)

Branch here, explore the commits: https://github.com/Luomu/pioneer/tree/renderer

Comments & design help welcome, there's still a lot to be done

Goals: make it possible to port to OpenGL ES2 (or even DirectX if someone wants to) without going crazy get rid of immediate mode drawing remove and reduce opengl calls in general source code - glEverything() reduce code diversity/duplication (Now it's a mix of everything. there are only so many ways you want to draw a quad)

The current class definition is short enough to be pasted here (extra comments with XX):

// Renderer base, functions return false if
// failed/unsupported
class Renderer
{
public:
    Renderer(int width, int height);
    virtual ~Renderer();

    virtual const char* GetName() = 0;

    virtual bool BeginFrame() = 0;
    virtual bool EndFrame() = 0;
    //traditionally gui happens between endframe and swapbuffers
    virtual bool SwapBuffers() = 0;

    //render state functions
    //XX expand whenever sensible but this should be enough to demonstrate the idea
    virtual bool SetBlendMode(BlendMode type) { return false; }
    //virtual bool SetState(Z_WRITE, false) or
    //virtual bool SetZWrite(false) ?

    virtual bool SetLights(int numlights, const Light *l) { return false; }
    virtual bool SetAmbientColor(const Color &c) { return false; }

    //drawing functions
    //2d drawing is generally understood to be for gui use (unlit, ortho projection)
    //XX here I was still using specialized data structures
    //XX could also be an array of vector3fs and array of Colors - let me know if you care
    virtual bool DrawLines(int vertCount, const LineVertex *vertices, LineType type=LINE_SINGLE)  { return false; }
    virtual bool DrawLines2D(int vertCount, const LineVertex2D *vertices, LineType type=LINE_SINGLE)  { return false; }
    //unindexed triangle draw
    //XX here I started using a generic VertexArray because there are too many attribute combinations
    virtual bool DrawTriangles(const VertexArray *vertices, const Material *material=0, PrimitiveType type=TRIANGLES)  { return false; }
    virtual bool DrawTriangles2D(const VertexArray *vertices, const Material *material=0, PrimitiveType type=TRIANGLES)  { return false; }
    //indexed triangle draw (only triangles, no strips or fans)
    virtual bool DrawSurface(const Surface *surface) { return false; }
    virtual bool DrawSurface2D(const Surface *surface) { return false; }

    //virtual bool DrawPoints(...)
    //virtual bool DrawPointSprites(...) //high amount of textured quads for particles etc

    //XX for complex geometry - the data will be processed & cached into something the renderer prefers
    virtual bool DrawBufferThing(BufferThing *thing) { return false; }

protected:
    int m_width;
    int m_height;
};

Core concepts VertexArray: at first I used specialized data structures like ColoredVertex (see DrawLines for this style) but there are too many possible combinations of attributes. Material: holds info on, well, material properties. And textures. Surface: has one vertex array, one index array (for indexed triangle drawing) and a material. BufferThing: Complex, static geometry that is expected to be buffered. Can have multiple surfaces. This is not fully fleshed out and I ran out of names here :) Mesh? Solid? Model? I ported Backround to use this.

Renderer choice I have started two renderers (quickly put together - will be rewritten). RendererLegacy is the fixed-function AKA shaderless one. We can keep it around as long as someone wants to maintain it. RendererGL2 is the new OpenGL 2.0 or 2.1 one that aims to shed as much historical baggage as possible. From a player's point of view it will not be possible to swap between these without restarting (not impossible but I wouldn't bother).

Materials & Shaders It is desirable to let the renderer choose and manage the appropriate shaders, for example when drawing unlit 2D lines the GL2 renderer is expected to choose simpleShader or similar. If textures are needed, that can be determined using a Material. Texture binds can be removed. RenderShader related calls in the general code are to be minimized. It's not always straightforward, for example with the planet atmosphere it's not enouch to communicate the choice of shader but also a bunch of uniforms. Perhaps something called "Effect" that can store the appropriate parameters?

Unknown territory LMRModel is such a big blob of stuff I don't know how easy it is to make play nice with Renderer. Terrain is another special case. The geopatches are complex, need to be buffered and change sometimes but not every frame. The unbuffered vertex data is kept around for some reason. I'd expect to add something like DrawTerrain(Patch *p) that works somewhat like DrawBufferThing.

Transformations the classic matrix stack (pushMatrix, popMatrix) we rely on everywhere needs to be replaced somehow Also, projections

Render.cpp - this will be slowly erased. Post processing needs to go somewhere else. I have a branch related to this (see http://github.com/Luomu/pioneer/blob/filters/src/render/RenderPostControl.cpp) but it needs to be reconsidered wrt. Renderer.

Porting old code glBegin/glEnd: recurring cases should be replaced by DrawQuad style methods, not calling renderer directly vertex array drawing (glVertexPointer etc.): same as above Textures: remove texture binds and unbinds, commmunicate textures to renderer via a Material glEnable()/Disable: GL_BLEND? replace by SetBlendMode. GL_LIGHTING? Remove. Texture related? remove. etc. Lights: use SetLights

SDL or not, Would be nice if the Renderer could also create the context.

Luomu commented 12 years ago

"Mostly" done