#include "core.h" #include "log.h" #include "render.h" #include "renderdevice.h" #include "texturesmanager.h" #include "shadersystem.h" #include "modelsystem.h" #include "debugrender.h" #include "ifilesystem.h" #include "camera.h" #include "imguimanager.h" #include "scenemanager.h" #include "gpu_buffer.h" static GLuint g_VAO = 0; int g_NumModels = 0; // TEMP glm::vec3 g_viewOrigin; glm::vec3 g_viewOrient; #ifdef GL_DEBUG_OUTPUT #define GL_DEBUG_OUTPUT 0x92E0 #endif // GL_DEBUG_OUTPUT #ifndef GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB #define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242 #endif // !GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB #ifndef GL_DEBUG_TYPE_ERROR_ARB #define GL_DEBUG_TYPE_ERROR_ARB 0x824C #endif // !GL_DEBUG_TYPE_ERROR_ARB #ifndef GL_DEBUG_OUTPUT #define GL_DEBUG_OUTPUT 0x92E0 #endif // !GL_DEBUG_OUTPUT #ifndef GL_ARB_debug_output #define GL_ARB_debug_output 1 typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLARBPROC)(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled); PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB; typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTARBPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* buf); PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsertARB; typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKARBPROC)(GLDEBUGPROCARB callback, const void* userParam); PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARB; typedef GLuint(APIENTRYP PFNGLGETDEBUGMESSAGELOGARBPROC)(GLuint count, GLsizei bufSize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, GLchar* messageLog); PFNGLGETDEBUGMESSAGELOGARBPROC glGetDebugMessageLogARB; #endif void APIENTRY GL_DebugOutput(GLenum source, GLenum type, unsigned int id, GLenum severity, GLsizei length, const char* message, const void* userParam) { // Nvidia spam too much about buffer mapping if (type == 0x8251) return; Msg("OpenGL: %stype = 0x%x, severity = 0x%x, message = %s\n", (type == GL_DEBUG_TYPE_ERROR_ARB ? "** GL ERROR ** " : ""), type, severity, message); if (type == GL_DEBUG_TYPE_ERROR_ARB) { bool debug = true; //__debugbreak(); } } Render* g_render = nullptr; Render::Render() : m_pWindow(nullptr), m_pGLContext(nullptr), m_pStretchedPicVBuf(nullptr), m_usingVAO(false), m_showStats(false) { m_viewMatrix = glm::identity(); m_projectionMatrix = glm::identity(); } Render::~Render() { } void Render::Init(SDL_Window* pWindow) { m_pWindow = pWindow; SDL_assert(m_pWindow); Msg("Initializing renderer ..."); // Create OpenGL context m_pGLContext = SDL_GL_CreateContext(m_pWindow); SDL_GL_MakeCurrent(m_pWindow, m_pGLContext); gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress); if (GLVersion.major == 0 || GLVersion.minor == 0) { Core::Error("Failed to load OpenGL"); } // Core profile probably, should use VAO if (GLVersion.major >= 3 && GLVersion.minor >= 1) m_usingVAO = true; Msg("%s", (const char*)glGetString(GL_VENDOR)); Msg("%s", (const char*)glGetString(GL_RENDERER)); Msg("OpenGL ver. %s", (const char*)glGetString(GL_VERSION)); Msg("Initializing OpenGL extensions..."); InitGLExtensions(); // Reset OpenGL error stack glGetError(); // Create render device g_renderDevice = new RenderDevice(); // Create texture manager g_texturesManager = new TexturesManager(); g_texturesManager->Init(); // Create shader system g_shaderSystem = new ShaderSystem(); g_shaderSystem->Init(); // Create model system g_modelSystem = new ModelSystem(); g_modelSystem->Init(); // Create scene manager g_sceneManager = new SceneManager(); // Create debug render g_debugRender = new DebugRender(); g_debugRender->Initialize(); // Create imgui manager g_ImGuiManager.Init(); // Create stretched picture filenameBuffer m_pStretchedPicVBuf = g_renderDevice->CreateVertexBuffer(nullptr, MAX_STRETCH_VX, true); // Core profile require Vertex Array Object to render if (m_usingVAO) { // Create global vertex array glGenVertexArrays(1, &g_VAO); glBindVertexArray(g_VAO); } } void Render::InitGLExtensions() { //// Load extension //glDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC)SDL_GL_GetProcAddress("glDebugMessageCallbackARB"); //// Enable debug output //if (glDebugMessageCallbackARB) //{ // Msg("...found GL_ARB_debug_output"); // //glEnable(GL_DEBUG_OUTPUT); // glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); // glDebugMessageCallbackARB(GL_DebugOutput, NULL); //} //bool found_WGL_EXT_swap_control = false; bool found_GL_ARB_debug_output = false; // Load extensions char* extensions = (char*)glGetString(GL_EXTENSIONS); // OpenGL Error: GL_INVALID_ENUM at D:\projects\old\pke\src\render\shadersystem.cpp:169 if (extensions) { char* extension = strtok(extensions, " "); while (extension) { //if (strcmp(extension, "WGL_EXT_swap_control") == 0) // found_WGL_EXT_swap_control = true; if (strcmp(extension, "GL_ARB_debug_output") == 0) found_GL_ARB_debug_output = true; extension = strtok(NULL, " "); } } else // core profile { int NumberOfExtensions; glGetIntegerv(GL_NUM_EXTENSIONS, &NumberOfExtensions); for (int i = 0; i < NumberOfExtensions; i++) { char* extension = (char*)glGetStringi(GL_EXTENSIONS, i); //if (strcmp(extension, "WGL_EXT_swap_control") == 0) // found_WGL_EXT_swap_control = true; if (strcmp(extension, "GL_ARB_debug_output") == 0) found_GL_ARB_debug_output = true; } } // Enable debug output if (found_GL_ARB_debug_output) { Msg("...found GL_ARB_debug_output"); glDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC)SDL_GL_GetProcAddress("glDebugMessageCallbackARB"); glEnable(GL_DEBUG_OUTPUT); glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); glDebugMessageCallbackARB(GL_DebugOutput, NULL); } else { Msg("...not found GL_ARB_debug_output"); } } void Render::Shutdown() { if (m_usingVAO) { glBindVertexArray(0); glDeleteVertexArrays(1, &g_VAO); } delete m_pStretchedPicVBuf; m_pStretchedPicVBuf = nullptr; g_ImGuiManager.Shutdown(); g_debugRender->Shutdown(); delete g_debugRender; g_debugRender = nullptr; delete g_sceneManager; g_sceneManager = nullptr; g_modelSystem->Shutdown(); delete g_modelSystem; g_modelSystem = nullptr; g_shaderSystem->Shutdown(); delete g_shaderSystem; g_shaderSystem = nullptr; g_texturesManager->Shutdown(); delete g_texturesManager; g_texturesManager = nullptr; delete g_renderDevice; g_renderDevice = nullptr; // Destroy OpenGL context SDL_GL_MakeCurrent(nullptr, nullptr); SDL_GL_DestroyContext(m_pGLContext); m_pGLContext = nullptr; } void Render::RenderScene() { //if (m_sceneModel) { // Camera* camera = g_cameraManager.GetActiveCamera(); // if (camera) { // glm::mat4 viewProj = m_projectionMatrix * m_viewMatrix; // viewProj = glm::transpose(viewProj); // camera->GetFrustum().Build(viewProj); // if (camera->GetFrustum().CullBoundingBox(m_sceneModel->GetBoundingBox())) // return; // } // static glm::mat4 s_identity = glm::mat4(1.0f); // m_sceneModel->Draw(s_identity); // g_NumModels++; // // g_debugRender->DrawBoundingBox(m_sceneModel->GetBoundingBox(), glm::vec3(1.0f)); //} static glm::mat4 s_identity = glm::mat4(1.0f); if (g_sceneManager->isSceneLoaded()) g_sceneManager->renderScene(s_identity); g_debugRender->RenderFrame(); } void Render::RenderStats() { if (!m_showStats) return; char buffer[256]; snprintf(buffer, sizeof(buffer), "FPS: %.1f", ImGui::GetIO().Framerate); ImGui::GetForegroundDrawList()->AddText(ImVec2(0.0f, 0.0f), 0xffffffff, buffer); snprintf(buffer, sizeof(buffer), "Scene: %s", g_sceneManager->getSceneName()); ImGui::GetForegroundDrawList()->AddText(ImVec2(0.0f, 15.0f), 0xffffffff, buffer); snprintf(buffer, sizeof(buffer), "numModels: %d", g_NumModels); ImGui::GetForegroundDrawList()->AddText(ImVec2(0.0f, 30.0f), 0xffffffff, buffer); Camera* camera = g_cameraManager.GetActiveCamera(); if (camera) { snprintf(buffer, sizeof(buffer), "cam pos: %.2f %.2f %.2f", camera->GetPosition().x, camera->GetPosition().y, camera->GetPosition().z); ImGui::GetForegroundDrawList()->AddText(ImVec2(0.0f, 45.0f), 0xffffffff, buffer); } } void Render::Present(bool vsync) { SDL_GL_SetSwapInterval(vsync); SDL_GL_SwapWindow(m_pWindow); // reset stats ResetStates(); g_NumModels = 0; } void Render::ResetStates() { g_renderDevice->SetDepthTest(true); g_renderDevice->SetDepthWrite(true); g_renderDevice->SetStencilTest(false); g_renderDevice->SetScissorTest(false); g_renderDevice->SetCullFace(false); g_renderDevice->SetBlending(false); } void Render::SetViewMatrix(const glm::mat4& matView) { m_viewMatrix = matView; } void Render::SetProjectionMatrix(const glm::mat4& matProjection) { m_projectionMatrix = matProjection; } void Render::LoadSceneXML(const char* filename) { g_sceneManager->loadScene(filename); } void Render::ToggleShowStats() { m_showStats = !m_showStats; } //IRender* GetRender() //{ // return g_render; //}