#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 static GLuint g_VAO = 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_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 filenameBuffer 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; } } Render* g_pRender = nullptr; Render::Render() : m_pWindow(nullptr), m_pGLContext(nullptr), m_pStretchedPicVBuf(nullptr), m_sceneModel(nullptr), m_bUsingVAO(false) { m_ViewMatrix = glm::identity(); m_ProjectionMatrix = glm::identity(); } Render::~Render() { } void Render::Init(SDL_Window* pWindow) { m_pWindow = pWindow; SDL_assert(m_pWindow); // 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_bUsingVAO = 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("Context created with OpenGL version %d.%d", GLVersion.major, GLVersion.minor); // Reset OpenGL error stack glGetError(); // 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); } // Create render device g_pRenderDevice = new RenderDevice(); // Create texture manager g_pTexturesManager = new TexturesManager(); g_pTexturesManager->Init(); // Create shader system g_pShaderSystem = new ShaderSystem(); g_pShaderSystem->Init(); // Create model system g_pModelSystem = new ModelSystem(); // Create debug render g_pDebugRender = new DebugRender(); g_pDebugRender->Initialize(); // Create stretched picture filenameBuffer m_pStretchedPicVBuf = g_pRenderDevice->CreateVertexBuffer(nullptr, MAX_STRETCH_VX, true); // Core profile require Vertex Array Object to render if (m_bUsingVAO) { // Create global vertex array glGenVertexArrays(1, &g_VAO); glBindVertexArray(g_VAO); } } void Render::Shutdown() { if (m_bUsingVAO) { glBindVertexArray(0); glDeleteVertexArrays(1, &g_VAO); } delete m_pStretchedPicVBuf; m_pStretchedPicVBuf = nullptr; g_pDebugRender->Shutdown(); delete g_pDebugRender; g_pDebugRender = nullptr; g_pModelSystem->Shutdown(); delete g_pModelSystem; g_pModelSystem = nullptr; g_pShaderSystem->Shutdown(); delete g_pShaderSystem; g_pShaderSystem = nullptr; g_pTexturesManager->Shutdown(); delete g_pTexturesManager; g_pTexturesManager = nullptr; delete g_pRenderDevice; g_pRenderDevice = nullptr; // Destroy OpenGL context SDL_GL_MakeCurrent(nullptr, nullptr); SDL_GL_DestroyContext(m_pGLContext); m_pGLContext = nullptr; } void Render::RenderScene() { if (m_sceneModel) { static glm::mat4 s_identity = glm::mat4(1.0f); m_sceneModel->Draw(s_identity); } g_pDebugRender->RenderFrame(); } void Render::Present(bool vsync) { SDL_GL_SwapWindow(m_pWindow); } void Render::ResetStates() { g_pRenderDevice->SetDepthTest(true); g_pRenderDevice->SetDepthWrite(true); g_pRenderDevice->SetStencilTest(false); g_pRenderDevice->SetScissorTest(false); g_pRenderDevice->SetCullFace(false); g_pRenderDevice->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) { char filenameBuffer[kMaxPathLength]; snprintf(filenameBuffer, kMaxPathLength, "data/levels/%s/%s.xml", filename, filename); FileHandle_t file = GetFileSystem()->OpenFile(filenameBuffer, "rb"); SDL_assert_always(file != kInvalidFileHandleValue); size_t length = GetFileSystem()->GetFileLength(file); char* filedata = new char[length + 1]; GetFileSystem()->ReadFile(file, filedata, length); filedata[length] = '\0'; GetFileSystem()->CloseFile(file); pugi::xml_document doc; pugi::xml_parse_result result = doc.load_buffer(filedata, length); delete[] filedata; if (!result) { Core::Error("Render::LoadSceneXML: Error while reading level description file '%s'\nError: %s:%i", filenameBuffer, result.description(), result.offset); } pugi::xml_node root = doc.document_element(); const char* scenefilename = root.child("SceneFile").attribute("filename").value(); sprintf(filenameBuffer, "data/levels/%s/%s", filename, scenefilename); if (!GetFileSystem()->IsExist(filenameBuffer)) { Core::Error("SceneManager::LoadScene: scene file '%s' doesnt exist", scenefilename); } m_sceneFilename = filenameBuffer; m_sceneModel = g_pModelSystem->LoadModel(m_sceneFilename.c_str()); } //IRender* GetRender() //{ // return g_pRender; //}