Files
pke/src/render/render.cpp
2026-02-12 11:46:06 +03:00

266 lines
6.7 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 <pugixml.hpp>
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<glm::mat4>();
m_ProjectionMatrix = glm::identity<glm::mat4>();
}
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;
//}