367 lines
8.9 KiB
C++
367 lines
8.9 KiB
C++
#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<glm::mat4>();
|
|
m_projectionMatrix = glm::identity<glm::mat4>();
|
|
}
|
|
|
|
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;
|
|
//}
|