/* * Renderer.cpp * * Created on: 4 nov. 2020 * Author: simon */ #include "render/Renderer.h" #include "render/GL.h" #include #include "misc/Time.h" #include "misc/Easing.h" #include "misc/Maths.h" #include #include namespace td { namespace render { Renderer::Renderer() : m_BackgroundColor(0, 0, 0) { } Renderer::~Renderer() { } void Renderer::InitShaders() { m_WorldShader = std::make_unique(); m_WorldShader->LoadShader(); m_EntityShader = std::make_unique(); m_EntityShader->LoadShader(); } // TODO : change loader check bool Renderer::Init() { #if __has_include() glbinding::initialize(); #elif __has_include() glewInit(); #elif __has_include() gladLoadGL(); #elif __has_include() gl3wInit(); #elif __has_include() 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(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(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(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(m_WindowSize.x) / 2.0f - mov.x, static_cast(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