#ifndef RENDER_SYSTEM #define RENDER_SYSTEM #include #include #include #include #include "Structures.h" const float skyboxVertices[] = { -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f }; class Camera; class Shader; class FBO; class VBO; class VAO; class Cubemap; class Lighting; class Renderable { public: enum ShaderType { RigShader, MeshShader, ImageBoxShader, BoxShader, TextShader, ParticleShader }; ShaderType shadertype = ShaderType::MeshShader; bool opaque = true; bool castshadow = false; Renderable(); ~Renderable(); void BindToRenderSystem(); virtual void Render(Shader& ShaderProgram) {} virtual glm::vec3 GetWorldPosition() const { return glm::vec3(0.0f); } // A world space box around everything this draws. Without one it's never culled. virtual bool GetWorldBounds(BoundingBox& bounds) const { return false; } // Occlusion culling state, only the render system touches these unsigned int occlusionQuery = 0; bool occlusionPending = false; // a query was sent and hasn't been read back yet bool occluded = false; // the last answered query saw none of it }; struct GraphicsSettings { bool bloom = true; bool shadows = true; // the sun's shadow map bool lightShadows = true; // spot and point light shadows bool vsync = true; bool culling = true; // frustum and occlusion culling for opaque meshes and characters }; struct HitboxDebugLine { glm::mat4 transform; glm::vec3 color; }; class RenderSystem { public: Lighting* lighting = nullptr; GraphicsSettings graphics; FBO* screenfbo = nullptr; FBO* shadowdepthmapfbo = nullptr; FBO* gBuffer = nullptr; unsigned int gPosition = 0; unsigned int gNormal = 0; unsigned int gAlbedo = 0; unsigned int gMaterial = 0; unsigned int gDepth = 0; unsigned int shadowDebugSampler = 0; FBO* localShadowFBO = nullptr; unsigned int localShadowAtlas = 0; FBO* bloomFBO[2] = { nullptr, nullptr }; unsigned int bloomTextures[2] = { 0, 0 }; int bloomWidth = 0; int bloomHeight = 0; int debugView = 0; // 0 = final image, otherwise a debugMode in gbuffer_debug.frag unsigned int depthMaptexture = 0; unsigned int textureColorbuffer = 0; unsigned int rbo = 0; unsigned int SHADOW_RESOLUTION = 0; VAO* quadVAO = nullptr; VBO* quadVBO = nullptr; VAO* skyboxVAO = nullptr; VBO* skyboxVBO = nullptr; Shader* MeshShadowShader = nullptr; Shader* RigShadowShader = nullptr; Shader* SkyboxShader = nullptr; Shader* ScreenShader = nullptr; Shader* RigShader = nullptr; Shader* MeshShader = nullptr; Shader* GeometryShader = nullptr; Shader* GeometryRigShader = nullptr; Shader* DeferredLightingShader = nullptr; Shader* GBufferDebugShader = nullptr; Shader* BloomExtractShader = nullptr; Shader* BloomBlurShader = nullptr; Shader* ImageBoxShader = nullptr; Shader* BoxShader = nullptr; Shader* Text2DShader = nullptr; Shader* ParticleShader = nullptr; Shader* HitboxShader = nullptr; Cubemap* skybox = nullptr; unsigned int hitboxVAO = 0; unsigned int hitboxVBO = 0; std::vector hitboxDebugLines; RenderSystem() {} void Initialize(); void Resize(int width, int height); void Render(Camera& camera); void CycleDebugView(); void SetHitboxDebugLines(const std::vector& lines) { hitboxDebugLines = lines; } void AddRenderable(Renderable* r) { renderables.push_back(r); } void RemoveRenderable(Renderable* r) { for (int i = 0; i < (int)renderables.size(); i++) { if (renderables[i] == r) { renderables.erase(renderables.begin() + i); return; } } std::cout << "didn't find renderable to remove\n"; } void RenderRenderable(Renderable* renderable, Camera& camera); std::vector renderables; private: void PrepareRigShader(Camera& camera); void PrepareMeshShader(Camera& camera); void PrepareParticleShader(Camera& camera); void PrepareBoxShader(Camera& camera); void PrepareImageBoxShader(Camera& camera); void PrepareTextShader(Camera& camera); void RenderTranslucent(Camera& camera, const glm::mat4& lightSpaceMatrix, const glm::vec3& camPos); void RenderHitboxDebug(Camera& camera); void AllocateGBuffer(int width, int height); void AllocateBloom(int width, int height); void RenderBloom(); void RenderShadowCasters(const glm::mat4& lightSpaceMatrix); void RenderLocalShadows(); void BindGBufferTextures(Shader* shader); void RenderGeometryPass(const glm::mat4& proj, const glm::mat4& view, const glm::vec3& camPos); bool IsVisible(Renderable* r, const glm::vec4 (&frustum)[6], const glm::vec3& camPos); void IssueOcclusionQueries(const glm::mat4& proj, const glm::mat4& view); std::vector occlusionCandidates; // drawn into the queries after the geometry pass void RenderLightingPass(const glm::vec3& camPos, const glm::mat4& lightSpaceMatrix); void RenderDebugView(); }; #endif