/** * ========================================================================= * File : Renderer.h * Project : 0 A.D. * Description : higher level interface on top of OpenGL to render basic * objects: terrain, models, sprites, particles etc. * ========================================================================= */ #ifndef INCLUDED_RENDERER #define INCLUDED_RENDERER #include "graphics/Camera.h" #include "lib/ogl.h" #include "lib/res/handle.h" #include "ps/Singleton.h" #include "scripting/ScriptableObject.h" #include "renderer/Scene.h" // necessary declarations class CPatch; class CMaterial; class CModel; class CLightEnv; class CTexture; class RenderPathVertexShader; class WaterManager; class SkyManager; // rendering modes enum ERenderMode { WIREFRAME, SOLID, EDGED_FACES }; // stream flags #define STREAM_POS 0x01 #define STREAM_NORMAL 0x02 #define STREAM_COLOR 0x04 #define STREAM_UV0 0x08 #define STREAM_UV1 0x10 #define STREAM_UV2 0x20 #define STREAM_UV3 0x40 #define STREAM_POSTOUV0 0x80 #define STREAM_TEXGENTOUV1 0x100 ////////////////////////////////////////////////////////////////////////////////////////// // SVertex3D: simple 3D vertex declaration struct SVertex3D { float m_Position[3]; float m_TexCoords[2]; unsigned int m_Color; }; ////////////////////////////////////////////////////////////////////////////////////////// // SVertex2D: simple 2D vertex declaration struct SVertex2D { float m_Position[2]; float m_TexCoords[2]; unsigned int m_Color; }; // access to sole renderer object #define g_Renderer CRenderer::GetSingleton() /////////////////////////////////////////////////////////////////////////////////////////// // CRenderer: base renderer class - primary interface to the rendering engine struct CRendererInternals; class CRenderer : public Singleton, public CJSObject, private SceneCollector { public: // various enumerations and renderer related constants enum { NumAlphaMaps=14 }; enum { MaxTextureUnits=16 }; enum Option { OPT_NOVBO, OPT_NOFRAMEBUFFEROBJECT, OPT_SHADOWS, OPT_FANCYWATER, OPT_LODBIAS }; enum RenderPath { // If no rendering path is configured explicitly, the renderer // will choose the path when Open() is called. RP_DEFAULT, // Classic fixed function. RP_FIXED, // Use (GL 2.0) vertex shaders for T&L when possible. RP_VERTEXSHADER }; // stats class - per frame counts of number of draw calls, poly counts etc struct Stats { // set all stats to zero void Reset() { memset(this,0,sizeof(*this)); } // add given stats to this stats Stats& operator+=(const Stats& rhs) { m_Counter++; m_DrawCalls+=rhs.m_DrawCalls; m_TerrainTris+=rhs.m_TerrainTris; m_ModelTris+=rhs.m_ModelTris; m_BlendSplats+=rhs.m_BlendSplats; return *this; } // count of the number of stats added together size_t m_Counter; // number of draw calls per frame - total DrawElements + Begin/End immediate mode loops size_t m_DrawCalls; // number of terrain triangles drawn size_t m_TerrainTris; // number of (non-transparent) model triangles drawn size_t m_ModelTris; // number of splat passes for alphamapping size_t m_BlendSplats; }; // renderer options struct Options { bool m_NoVBO; bool m_NoFramebufferObject; bool m_Shadows; bool m_FancyWater; float m_LodBias; RenderPath m_RenderPath; } m_Options; struct Caps { bool m_VBO; bool m_TextureBorderClamp; bool m_GenerateMipmaps; bool m_VertexShader; bool m_DepthTextureShadows; bool m_FramebufferObject; }; public: // constructor, destructor CRenderer(); ~CRenderer(); // open up the renderer: performs any necessary initialisation bool Open(int width,int height,int depth); // resize renderer view void Resize(int width,int height); // set/get boolean renderer option void SetOptionBool(enum Option opt,bool value); bool GetOptionBool(enum Option opt) const; // set/get RGBA color renderer option // void SetOptionColor(enum Option opt,const RGBAColor& value); void SetOptionFloat(enum Option opt, float val); // const RGBAColor& GetOptionColor(enum Option opt) const; void SetRenderPath(RenderPath rp); RenderPath GetRenderPath() const { return m_Options.m_RenderPath; } static CStr GetRenderPathName(RenderPath rp); static RenderPath GetRenderPathByName(const CStr& name); // return view width int GetWidth() const { return m_Width; } // return view height int GetHeight() const { return m_Height; } // return view aspect ratio float GetAspect() const { return float(m_Width)/float(m_Height); } // signal frame start void BeginFrame(); // signal frame end void EndFrame(); // set color used to clear screen in BeginFrame() void SetClearColor(u32 color); // return current frame counter int GetFrameCounter() const { return m_FrameCounter; } /** * Set up the camera used for rendering the next scene; this includes * setting OpenGL state like viewport, projection and modelview matrices. * * @param viewCamera this camera determines the eye position for rendering * @param cullCamera this camera determines the frustum for culling in the renderer and * for shadow calculations */ void SetSceneCamera(const CCamera& viewCamera, const CCamera& cullCamera); // set the viewport void SetViewport(const SViewPort &); /** * Render the given scene immediately. * @param scene a Scene object describing what should be rendered. */ void RenderScene(Scene* scene); // basic primitive rendering operations in 2 and 3D; handy for debugging stuff, but also useful in // editor tools (eg for highlighting specific terrain patches) // note: // * all 3D vertices specified in world space // * primitive operations rendered immediatedly, never batched // * primitives rendered in current material (set via SetMaterial) // void RenderLine(const SVertex2D* vertices); // void RenderLineLoop(int len,const SVertex2D* vertices); // void RenderTri(const SVertex2D* vertices); // void RenderQuad(const SVertex2D* vertices); // void RenderLine(const SVertex3D* vertices); // void RenderLineLoop(int len,const SVertex3D* vertices); // void RenderTri(const SVertex3D* vertices); // void RenderQuad(const SVertex3D* vertices); // set the current lighting environment; (note: the passed pointer is just copied to a variable within the renderer, // so the lightenv passed must be scoped such that it is not destructed until after the renderer is no longer rendering) void SetLightEnv(CLightEnv* lightenv) { m_LightEnv=lightenv; } // set the mode to render subsequent terrain patches void SetTerrainRenderMode(ERenderMode mode) { m_TerrainRenderMode=mode; } // get the mode to render subsequent terrain patches ERenderMode GetTerrainRenderMode() const { return m_TerrainRenderMode; } // set the mode to render subsequent models void SetModelRenderMode(ERenderMode mode) { m_ModelRenderMode=mode; } // get the mode to render subsequent models ERenderMode GetModelRenderMode() const { return m_ModelRenderMode; } // try and load the given texture bool LoadTexture(CTexture* texture,int wrapflags); // set the given unit to reference the given texture; pass a null texture to disable texturing on any unit; // active texture unit always set to given unit on exit void SetTexture(int unit,CTexture* texture); // bind a GL texture object to active unit void BindTexture(int unit,GLuint tex); // query transparency of given texture bool IsTextureTransparent(CTexture* texture); // load the default set of alphamaps. // return a negative error code if anything along the way fails. // called via delay-load mechanism. int LoadAlphaMaps(); void UnloadAlphaMaps(); // return stats accumulated for current frame const Stats& GetStats() { return m_Stats; } // return the current light environment const CLightEnv &GetLightEnv() { return *m_LightEnv; } // return the current view camera const CCamera& GetViewCamera() const { return m_ViewCamera; } // return the current cull camera const CCamera& GetCullCamera() const { return m_CullCamera; } // get the current OpenGL model-view-projection matrix into the given float[] CMatrix3D GetModelViewProjectionMatrix(); /** * GetWaterManager: Return the renderer's water manager. * * @return the WaterManager object used by the renderer */ WaterManager* GetWaterManager() { return m_WaterManager; } /** * GetSkyManager: Return the renderer's sky manager. * * @return the SkyManager object used by the renderer */ SkyManager* GetSkyManager() { return m_SkyManager; } /** * SetFastPlayerColor: Tell the renderer which path to take for * player colored models. Both paths should provide the same visual * quality, however the slow path runs on older hardware using multi-pass. * * @param fast true if the fast path should be used from now on. If fast * is true but the OpenGL implementation does not support it, a warning * is printed and the slow path is used instead. */ void SetFastPlayerColor(bool fast); /** * GetCapabilities: Return which OpenGL capabilities are available and enabled. * * @return capabilities structure */ const Caps& GetCapabilities() const { return m_Caps; } bool GetDisableCopyShadow() const { return m_DisableCopyShadow; } static void ScriptingInit(); protected: friend struct CRendererInternals; friend class CVertexBuffer; friend class CPatchRData; friend class FixedFunctionModelRenderer; friend class ModelRenderer; friend class PolygonSortModelRenderer; friend class SortModelRenderer; friend class RenderPathVertexShader; friend class HWLightingModelRenderer; friend class InstancingModelRenderer; friend class TerrainRenderer; // scripting // TODO: Perhaps we could have a version of AddLocalProperty for function-driven // properties? Then we could hide these function in the private implementation class. jsval JSI_GetFastPlayerColor(JSContext*); void JSI_SetFastPlayerColor(JSContext* ctx, jsval newval); jsval JSI_GetRenderPath(JSContext*); void JSI_SetRenderPath(JSContext* ctx, jsval newval); jsval JSI_GetUseDepthTexture(JSContext*); void JSI_SetUseDepthTexture(JSContext* ctx, jsval newval); jsval JSI_GetDepthTextureBits(JSContext*); void JSI_SetDepthTextureBits(JSContext* ctx, jsval newval); jsval JSI_GetSky(JSContext*); void JSI_SetSky(JSContext* ctx, jsval newval); //BEGIN: Implementation of SceneCollector void Submit(CPatch* patch); void SubmitNonRecursive(CModel* model); //END: Implementation of SceneCollector // render any batched objects void RenderSubmissions(); // patch rendering stuff void RenderPatches(); // model rendering stuff void RenderModels(); void RenderTransparentModels(); // shadow rendering stuff void RenderShadowMap(); // render water reflection and refraction textures void RenderReflections(); void RenderRefractions(); // debugging void DisplayFrustum(); // enable oblique frustum clipping with the given clip plane void SetObliqueFrustumClipping(const CVector4D& clipPlane, int sign); // RENDERER DATA: /// Private data that is not needed by inline functions CRendererInternals* m; // view width int m_Width; // view height int m_Height; // view depth (bpp) int m_Depth; // frame counter int m_FrameCounter; // current terrain rendering mode ERenderMode m_TerrainRenderMode; // current model rendering mode ERenderMode m_ModelRenderMode; /** * m_ViewCamera: determines the eye position for rendering * * @see CGameView::m_ViewCamera */ CCamera m_ViewCamera; /** * m_CullCamera: determines the frustum for culling and shadowmap calculations * * @see CGameView::m_ViewCamera */ CCamera m_CullCamera; // color used to clear screen in BeginFrame float m_ClearColor[4]; // current lighting setup CLightEnv* m_LightEnv; // ogl_tex handle of composite alpha map (all the alpha maps packed into one texture) Handle m_hCompositeAlphaMap; // coordinates of each (untransformed) alpha map within the packed texture struct { float u0,u1,v0,v1; } m_AlphaMapCoords[NumAlphaMaps]; // card capabilities Caps m_Caps; // build card cap bits void EnumCaps(); // per-frame renderer stats Stats m_Stats; // active textures on each unit GLuint m_ActiveTextures[MaxTextureUnits]; // Additional state that is only available when the vertex shader // render path is used (according to m_Options.m_RenderPath) RenderPathVertexShader* m_VertexShader; /// If false, use a multipass fallback for player colors. bool m_FastPlayerColor; /** * m_WaterManager: the WaterManager object used for water textures and settings * (e.g. water color, water height) */ WaterManager* m_WaterManager; /** * m_SkyManager: the SkyManager object used for sky textures and settings */ SkyManager* m_SkyManager; /** * m_SortAllTransparent: If true, all transparent models are * rendered using the TransparencyRenderer which performs sorting. * * Otherwise, transparent models are rendered using the faster * batching renderer when possible. */ bool m_SortAllTransparent; /** * m_DisplayFrustum: Render the cull frustum and other data that may be interesting * to evaluate culling and shadow map calculations * * Can be controlled from JS via renderer.displayFrustum */ bool m_DisplayFrustum; /** * m_DisableCopyShadow: For debugging purpose: * Disable copying of shadow data into the shadow texture (when EXT_fbo is not available) */ bool m_DisableCopyShadow; public: /** * m_ShadowZBias: Z bias used when rendering shadows into a depth texture. * This can be used to control shadowing artifacts. * * Can be accessed via JS as renderer.shadowZBias * ShadowMap uses this for matrix calculation. */ float m_ShadowZBias; /** * m_ShadowMapSize: Size of shadow map, or 0 for default. Typically slow but useful * for high-quality rendering. Changes don't take effect until the shadow map * is regenerated. * * Can be accessed via JS as renderer.shadowMapSize */ int m_ShadowMapSize; /** * m_SkipSubmit: Disable the actual submission of rendering commands to OpenGL. * All state setup is still performed as usual. * * Can be accessed via JS as renderer.skipSubmit */ bool m_SkipSubmit; /** * m_RenderTerritories: * Turn territory boundary rendering on or off. */ bool m_RenderTerritories; }; #endif