Files
Tower-Defense/src/render/Renderer.cpp
2023-06-06 17:59:48 +02:00

164 lines
4.5 KiB
C++

/*
* Renderer.cpp
*
* Created on: 4 nov. 2020
* Author: simon
*/
#include "render/Renderer.h"
#include "render/GL.h"
#include <stdio.h>
#include "misc/Time.h"
#include "misc/Easing.h"
#include "misc/Maths.h"
#include <misc/Log.h>
#include <misc/Format.h>
namespace td {
namespace render {
Renderer::Renderer() : m_BackgroundColor(0, 0, 0) {
}
Renderer::~Renderer() {
}
void Renderer::InitShaders() {
m_WorldShader = std::make_unique<shader::WorldShader>();
m_WorldShader->LoadShader();
m_EntityShader = std::make_unique<shader::EntityShader>();
m_EntityShader->LoadShader();
}
// TODO : change loader check
bool Renderer::Init() {
#if __has_include(<glbinding/glbinding.h>)
glbinding::initialize();
#elif __has_include(<GL/glew.h>)
glewInit();
#elif __has_include(<glad/glad.h>)
gladLoadGL();
#elif __has_include(<GL/gl3w.h>)
gl3wInit();
#elif __has_include(<glbinding/Binding.h>)
glbinding::Binding::initialize();
#endif
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
InitShaders();
return true;
}
void Renderer::RenderVAO(const GL::VertexArray& vao) {
m_WorldShader->Start();
vao.Bind();
glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(vao.GetVertexCount()));
vao.Unbind();
}
void Renderer::RenderModel(const Model& model) {
m_EntityShader->Start();
m_EntityShader->SetModelPos(model.positon);
m_EntityShader->SetColorEffect(model.color);
model.vao->Bind();
glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(model.vao->GetVertexCount()));
model.vao->Unbind();
}
void Renderer::Prepare() {
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(m_BackgroundColor.r, m_BackgroundColor.g, m_BackgroundColor.b, 0);
}
void Renderer::Resize(int width, int height) {
m_Camera.projectionMatrix = maths::Perspective(80.0f / 180.0f * PI, static_cast<float>(width) / height, 0.1f, 160.0f);
m_Camera.InvProjectionMatrix = maths::Inverse(m_Camera.projectionMatrix);
m_WorldShader->Start();
m_WorldShader->SetProjectionMatrix(m_Camera.projectionMatrix);
m_EntityShader->Start();
m_WorldShader->SetProjectionMatrix(m_Camera.projectionMatrix);
m_WindowSize = { width, height };
glViewport(0, 0, width, height);
}
void Renderer::SetZoom(float zoom) {
m_Camera.CamPos.y = std::max(1.0f, m_Camera.CamPos.y - zoom);
m_Camera.CamDistance = std::max(1.0f, m_Camera.CamDistance - zoom);
SetCamLook(m_Camera.CamLook);
}
void Renderer::SetCamAngularMovement(const Vec2f& mov) {
m_Camera.m_Pitch = std::clamp(m_Camera.m_Pitch - mov.y / m_MouseSensitivity, -PI / 2.0f + 0.0000001f, -PI / 12.0f);
m_Camera.m_Yaw += mov.x / m_MouseSensitivity;
SetCamLook(m_Camera.CamLook);
}
void Renderer::SetCamMovement(const Vec2f& mov) {
Vec2f cursor = { static_cast<float>(m_WindowSize.x) / 2.0f - mov.x, static_cast<float>(m_WindowSize.y) / 2.0f - mov.y };
Vec2f worldMovement = GetCursorWorldPos(cursor, m_WindowSize.x, m_WindowSize.y);
SetCamLook(worldMovement);
}
void Renderer::SetCamPos(const Vec3f& newPos) {
Vec3f front = {
std::cos(m_Camera.m_Yaw) * std::cos(m_Camera.m_Pitch),
std::sin(m_Camera.m_Pitch),
std::sin(m_Camera.m_Yaw) * std::cos(m_Camera.m_Pitch)
};
m_Camera.CamPos = newPos;
m_Camera.viewMatrix = maths::Look(m_Camera.CamPos, front, { 0, 1, 0 });
m_Camera.InvViewMatrix = maths::Transpose(maths::Inverse(m_Camera.viewMatrix)); // why transpose ? I don't know
m_WorldShader->Start();
m_WorldShader->SetViewMatrix(m_Camera.viewMatrix);
m_EntityShader->Start();
m_EntityShader->SetViewMatrix(m_Camera.viewMatrix);
}
void Renderer::SetCamLook(const Vec2f& worldPos) {
static const float WORLD_HEIGHT = 0;
m_Camera.CamLook = worldPos;
Vec3f front = {
std::cos(m_Camera.m_Yaw) * std::cos(m_Camera.m_Pitch),
std::sin(m_Camera.m_Pitch),
std::sin(m_Camera.m_Yaw) * std::cos(m_Camera.m_Pitch)
};
SetCamPos({
-m_Camera.CamDistance * front.x + m_Camera.CamLook.x,
-m_Camera.CamDistance * front.y + WORLD_HEIGHT,
-m_Camera.CamDistance * front.z + m_Camera.CamLook.y
});
}
Vec2f Renderer::GetCursorWorldPos(const Vec2f& cursorPos, float windowWidth, float windowHeight) {
float relativeX = (cursorPos.x / windowWidth * 2) - 1.0f;
float relativeY = 1.0f - (cursorPos.y / windowHeight * 2);
Vec4f rayClip{ relativeX, relativeY, -1.0f, 1.0f };
Vec4f rayEye = maths::Dot(m_Camera.InvProjectionMatrix, rayClip);
rayEye = { rayEye.x, rayEye.y, -1.0f, 0.0f };
Vec4f rayWorld = maths::Dot(m_Camera.InvViewMatrix, rayEye);
float lambda = -m_Camera.CamPos.y / rayWorld.y;
return { lambda * rayWorld.x + m_Camera.CamPos.x, lambda * rayWorld.z + m_Camera.CamPos.z };
}
} // namespace render
} // namespace td