CameraComponent, SceneCamera

- Added CameraComponent
- Added SceneCamera
- Renamed the previous Camera to OrthographicCamera
- Added Camera
- Renderer now takes a Camera* for projection and mat4& for view
- Scene::OnRender now takes in an optional Framebuffer to render to
- Minor tidying
This commit is contained in:
Light 2021-07-30 14:40:34 +04:30
parent 98184d358f
commit aab0c7b958
18 changed files with 277 additions and 119 deletions

View file

@ -1,43 +1,7 @@
#include "ltpch.h"
#include "Camera.h"
#include <glm/matrix.hpp>
#include <glm/gtc/matrix_transform.hpp>
namespace Light {
Camera::Camera(const glm::vec2& position, float aspectRatio, float zoomLevel, const glm::vec4& clearColor /* = glm::vec4(0.1f, 0.3f, 0.7f, 1.0f) */)
: m_Up(0.0f, 1.0f, 0.0f),
m_Position(position),
m_AspectRatio(aspectRatio),
m_ZoomLevel(zoomLevel),
m_ClearColor(clearColor)
{
}
void Camera::CalculateView()
{
m_View = glm::lookAt(glm::vec3(m_Position, 100.0f), glm::vec3(m_Position, 0.0f), m_Up);
}
void Camera::CalculateProjection()
{
m_Projection = glm::ortho(-m_ZoomLevel * m_AspectRatio,
+m_ZoomLevel * m_AspectRatio,
-m_ZoomLevel,
+m_ZoomLevel,
FLT_MAX, FLT_MIN);
}
void Camera::OnResize(const glm::vec2& size)
{
m_AspectRatio = size.x / size.y;
CalculateProjection();
}
void Camera::Move(const glm::vec2& position)
{
m_Position += position;
}
}

View file

@ -9,33 +9,17 @@ namespace Light {
class Camera
{
private:
glm::vec2 m_Position;
float m_AspectRatio;
float m_ZoomLevel;
const glm::vec3 m_Up;
glm::vec4 m_BackgroundColor = glm::vec4(1.0f, 0.0f, 0.0f, 1.0f);
protected:
glm::mat4 m_Projection;
glm::mat4 m_View;
glm::vec4 m_ClearColor;
public:
Camera(const glm::vec2& position, float aspectRatio, float zoomLevel, const glm::vec4& clearColor = glm::vec4(0.1f, 0.3f, 0.7f, 1.0f));
Camera() = default;
// CAMERA //
void CalculateView();
void CalculateProjection();
const glm::mat4& GetProjection() const { return m_Projection; }
void OnResize(const glm::vec2& size);
inline const glm::mat4& GetView() const { return m_View; }
inline const glm::mat4& GetProjection() const { return m_Projection; }
inline const glm::vec4& GetClearColor() const { return m_ClearColor; }
// CAMERA_CONTROLLER //
void Move(const glm::vec2& position);
const glm::vec4& GetBackgroundColor() const { return m_BackgroundColor; }
};
}

View file

@ -0,0 +1,43 @@
#include "ltpch.h"
#include "OrthographicCamera.h"
#include <glm/matrix.hpp>
#include <glm/gtc/matrix_transform.hpp>
namespace Light {
OrthographicCamera::OrthographicCamera(const glm::vec2& position, float aspectRatio, float zoomLevel, const glm::vec4& clearColor /* = glm::vec4(0.1f, 0.3f, 0.7f, 1.0f) */)
: m_Up(0.0f, 1.0f, 0.0f),
m_Position(position),
m_AspectRatio(aspectRatio),
m_ZoomLevel(zoomLevel),
m_ClearColor(clearColor)
{
}
void OrthographicCamera::CalculateView()
{
m_View = glm::lookAt(glm::vec3(m_Position, 100.0f), glm::vec3(m_Position, 0.0f), m_Up);
}
void OrthographicCamera::CalculateProjection()
{
m_Projection = glm::ortho(-m_ZoomLevel * m_AspectRatio,
+m_ZoomLevel * m_AspectRatio,
-m_ZoomLevel,
+m_ZoomLevel,
FLT_MAX, FLT_MIN);
}
void OrthographicCamera::OnResize(const glm::vec2& size)
{
m_AspectRatio = size.x / size.y;
CalculateProjection();
}
void OrthographicCamera::Move(const glm::vec2& position)
{
m_Position += position;
}
}

View file

@ -0,0 +1,41 @@
#pragma once
#include "Base/Base.h"
#include <glm/glm.hpp>
namespace Light {
class OrthographicCamera
{
private:
glm::vec2 m_Position;
float m_AspectRatio;
float m_ZoomLevel;
const glm::vec3 m_Up;
glm::mat4 m_Projection;
glm::mat4 m_View;
glm::vec4 m_ClearColor;
public:
OrthographicCamera(const glm::vec2& position, float aspectRatio, float zoomLevel, const glm::vec4& clearColor = glm::vec4(0.1f, 0.3f, 0.7f, 1.0f));
// CAMERA //
void CalculateView();
void CalculateProjection();
void OnResize(const glm::vec2& size);
inline const glm::mat4& GetView() const { return m_View; }
inline const glm::mat4& GetProjection() const { return m_Projection; }
inline const glm::vec4& GetClearColor() const { return m_ClearColor; }
// CAMERA_CONTROLLER //
void Move(const glm::vec2& position);
};
}

View file

@ -0,0 +1,33 @@
#include "ltpch.h"
#include "SceneCamera.h"
#include <glm/gtc/matrix_transform.hpp>
namespace Light {
SceneCamera::SceneCamera()
: m_OrthoSize(1000.0f),
m_OrthoNearPlane(-1.0f),
m_OrthoFarPlane(1.0f),
m_AspectRatio(16.0f / 9.0f)
{
CalculateProjection();
}
void SceneCamera::SetViewportSize(unsigned int width, unsigned int height)
{
m_AspectRatio = width / (float)height;
CalculateProjection();
}
void SceneCamera::CalculateProjection()
{
m_Projection = glm::ortho(-m_OrthoSize * 0.5f * m_AspectRatio,
m_OrthoSize * 0.5f * m_AspectRatio,
-m_OrthoSize * 0.5f,
m_OrthoSize * 0.5f,
m_OrthoFarPlane,
m_OrthoNearPlane);
}
}

View file

@ -0,0 +1,26 @@
#pragma once
#include "Camera.h"
#include "Base/Base.h"
namespace Light {
class SceneCamera : public Camera
{
private:
float m_OrthoSize;
float m_OrthoNearPlane, m_OrthoFarPlane;
float m_AspectRatio;
public:
SceneCamera();
void SetViewportSize(unsigned int width, unsigned int height);
private:
void CalculateProjection();
};
}

View file

@ -7,7 +7,7 @@
#include "RenderCommand.h"
#include "Texture.h"
#include "Camera/Camera.h"
#include "Camera/SceneCamera.h"
#include "Events/WindowEvents.h"
@ -51,20 +51,20 @@ namespace Light {
/* tint */
void Renderer::DrawQuadImpl(const glm::vec3& position, const glm::vec2& size, const glm::vec4& tint)
{
DrawQuadFinal(glm::translate(glm::mat4(1.0f), position) * glm::scale(glm::mat4(1.0f), { size.x, size.y, 1.0f }),
DrawQuad(glm::translate(glm::mat4(1.0f), position) * glm::scale(glm::mat4(1.0f), { size.x, size.y, 1.0f }),
tint);
}
/* texture */
void Renderer::DrawQuadImpl(const glm::vec3& position, const glm::vec2& size, Ref<Texture> texture)
{
DrawQuadFinal(glm::translate(glm::mat4(1.0f), position) * glm::scale(glm::mat4(1.0f), { size.x, size.y, 1.0f }),
DrawQuad(glm::translate(glm::mat4(1.0f), position) * glm::scale(glm::mat4(1.0f), { size.x, size.y, 1.0f }),
texture);
}
//======================================== DRAW_QUAD ========================================//
//==================== DRAW_QUAD_TINT ====================//
void Renderer::DrawQuadFinal(const glm::mat4& transform, const glm::vec4& tint)
void Renderer::DrawQuadImpl(const glm::mat4& transform, const glm::vec4& tint)
{
// locals
QuadRendererProgram::QuadVertexData* bufferMap = m_QuadRenderer.GetMapCurrent();
@ -95,7 +95,7 @@ namespace Light {
//==================== DRAW_QUAD_TINT ====================//
//==================== DRAW_QUAD_TEXTURE ====================//
void Renderer::DrawQuadFinal(const glm::mat4& transform, Ref<Texture> texture)
void Renderer::DrawQuadImpl(const glm::mat4& transform, Ref<Texture> texture)
{
// #todo: implement a proper binding
texture->Bind();
@ -136,10 +136,10 @@ namespace Light {
void Renderer::EndFrame()
{
m_RenderCommand->SwapBuffers();
m_RenderCommand->ClearBackBuffer(m_Camera->GetClearColor());
m_RenderCommand->ClearBackBuffer(m_Camera->GetBackgroundColor());
}
void Renderer::BeginSceneImpl(const Ref<Camera>& camera, const Ref<Framebuffer>& targetFrameBuffer /* = nullptr */)
void Renderer::BeginSceneImpl(Camera* camera, const glm::mat4& cameraTransform, const Ref<Framebuffer>& targetFrameBuffer /* = nullptr */)
{
// determine the target frame buffer
m_TargetFramebuffer = targetFrameBuffer;
@ -152,7 +152,7 @@ namespace Light {
// update view projection buffer
m_Camera = camera;
glm::mat4* map = (glm::mat4*)m_ViewProjectionBuffer->Map();
map[0] = m_Camera->GetProjection() * m_Camera->GetView();
map[0] = m_Camera->GetProjection() * glm::inverse(cameraTransform);
m_ViewProjectionBuffer->UnMap();
// map renderers

View file

@ -39,7 +39,7 @@ namespace Light {
Scope<RenderCommand> m_RenderCommand;
Scope<Blender> m_Blender;
Ref<Camera> m_Camera;
Camera* m_Camera;
Ref<Framebuffer> m_TargetFramebuffer;
public:
@ -48,7 +48,10 @@ namespace Light {
static inline void DrawQuad(const glm::vec3& position, const glm::vec2& size, const glm::vec4& tint) { s_Context->DrawQuadImpl(position, size, tint); }
static inline void DrawQuad(const glm::vec3& position, const glm::vec2& size, Ref<Texture> texture) { s_Context->DrawQuadImpl(position, size, texture); }
static inline void BeginScene(const Ref<Camera>& camera, const Ref<Framebuffer>& targetFrameBuffer = nullptr) { s_Context->BeginSceneImpl(camera, targetFrameBuffer); }
static void DrawQuad(const glm::mat4& transform, const glm::vec4& tint) { s_Context->DrawQuadImpl(transform, tint); }
static void DrawQuad(const glm::mat4& transform, Ref<Texture> texture) { s_Context->DrawQuadImpl(transform, texture); }
static inline void BeginScene(Camera* camera, const glm::mat4& cameraTransform, const Ref<Framebuffer>& targetFrameBuffer = nullptr) { s_Context->BeginSceneImpl(camera, cameraTransform, targetFrameBuffer); }
static inline void EndScene() { s_Context->EndSceneImpl(); }
void OnWindowResize(const WindowResizedEvent& event);
@ -62,10 +65,10 @@ namespace Light {
void DrawQuadImpl(const glm::vec3& position, const glm::vec2& size, const glm::vec4& tint);
void DrawQuadImpl(const glm::vec3& position, const glm::vec2& size, Ref<Texture> texture);
void DrawQuadFinal(const glm::mat4& transform, const glm::vec4& tint);
void DrawQuadFinal(const glm::mat4& transform, Ref<Texture> texture);
void DrawQuadImpl(const glm::mat4& transform, const glm::vec4& tint);
void DrawQuadImpl(const glm::mat4& transform, Ref<Texture> texture);
void BeginSceneImpl(const Ref<Camera>& camera, const Ref<Framebuffer>& targetFrameBuffer = nullptr);
void BeginSceneImpl(Camera* camera, const glm::mat4& cameraTransform, const Ref<Framebuffer>& targetFrameBuffer = nullptr);
void FlushScene();
void EndSceneImpl();
};

View file

@ -13,7 +13,7 @@ namespace Light {
class IndexBuffer;
class VertexLayout;
class Camera;
class OrthographicCamera;
class SharedContext;

View file

@ -4,7 +4,7 @@
namespace Light {
class Camera;
class OrthographicCamera;
class RendererProgram
{

View file

@ -13,7 +13,7 @@ namespace Light {
class IndexBuffer;
class VertexLayout;
class Camera;
class OrthographicCamera;
class SharedContext;

View file

@ -0,0 +1,28 @@
#pragma once
#include "Base/Base.h"
#include "Camera/SceneCamera.h"
#include <glm/glm.hpp>
namespace Light {
struct CameraComponent
{
SceneCamera camera;
bool isPrimary;
CameraComponent() = default;
CameraComponent(const CameraComponent&) = default;
CameraComponent(SceneCamera _camera, bool _isPrimary = false)
: camera(_camera),
isPrimary(_isPrimary)
{
}
operator SceneCamera() { return camera; }
};
}

View file

@ -2,8 +2,6 @@
#include "Base/Base.h"
#include <glm/glm.hpp>
namespace Light {
class Texture;
@ -14,7 +12,11 @@ namespace Light {
SpriteRendererComponent() = default;
SpriteRendererComponent(const SpriteRendererComponent&) = default;
SpriteRendererComponent(Ref<Texture> _texture) : texture(_texture) {}
SpriteRendererComponent(Ref<Texture> _texture)
: texture(_texture)
{
}
operator Ref<Texture>() { return texture; }
};

View file

@ -8,16 +8,18 @@ namespace Light {
struct TransformComponent
{
glm::vec2 position, size;
// glm::mat4 transform{ 1.0f };
glm::mat4 transform;
TransformComponent() = default;
TransformComponent(const TransformComponent&) = default;
TransformComponent(const glm::vec2& _position, const glm::vec2& _size) : position(_position), size(_size) {}
// operator glm::mat4&() { return transform; }
// operator const glm::mat4& () const { return transform; }
TransformComponent(const glm::mat4& _transform)
: transform(_transform)
{
}
operator glm::mat4&() { return transform; }
operator const glm::mat4& () const { return transform; }
};
}

View file

@ -23,6 +23,12 @@ namespace Light {
{
return m_Scene->m_Registry.emplace<T>(m_Handle, std::forward<Args>(args)...);
}
template<typename T>
T& GetComponent()
{
return m_Scene->m_Registry.get<T>(m_Handle);
}
};
}

View file

@ -19,19 +19,52 @@ namespace Light {
{
}
void Scene::OnRender()
void Scene::OnRender(const Ref<Framebuffer>& targetFrameBuffer /* = nullptr */)
{
auto group = m_Registry.group(entt::get<TransformComponent, SpriteRendererComponent>);
Camera* sceneCamera = nullptr;
glm::mat4* sceneCameraTransform;
group.each([](auto& transform, auto& sprite) {
Renderer::DrawQuad(glm::vec3(transform.position, 0.0f), transform.size, sprite.texture);
});
/* scene camera */
{
auto group = m_Registry.group(entt::get<TransformComponent, CameraComponent>);
for (auto& entity : group)
{
auto& [transformComp, cameraComp] = group.get<TransformComponent, CameraComponent>(entity);
if (cameraComp.isPrimary)
{
sceneCamera = &cameraComp.camera;
sceneCameraTransform = &transformComp.transform;
}
}
}
/* draw quads */
{
if (sceneCamera)
{
Renderer::BeginScene(sceneCamera, *sceneCameraTransform, targetFrameBuffer);
auto group = m_Registry.group(entt::get<TransformComponent, SpriteRendererComponent>);
for (auto& entity : group)
{
auto& [transformComp, spriteRendererComp] = group.get<TransformComponent, SpriteRendererComponent>(entity);
Renderer::DrawQuad(transformComp.transform, spriteRendererComp.texture);
}
Renderer::EndScene();
}
}
}
Entity Scene::CreateEntity(const std::string& name, const glm::vec2& position, const glm::vec2& size)
Entity Scene::CreateEntity(const std::string& name, const glm::mat4& transform)
{
Entity entity { m_Registry.create(), this } ;
entity.AddComponent<TransformComponent>(position, size);
entity.AddComponent<TransformComponent>(transform);
return entity;
}

View file

@ -10,6 +10,8 @@ namespace Light {
class Entity;
class Framebuffer;
class Scene
{
private:
@ -20,9 +22,9 @@ namespace Light {
Scene();
~Scene();
void OnRender();
void OnRender(const Ref<Framebuffer>& targetFrameBuffer = nullptr);
Entity CreateEntity(const std::string& name, const glm::vec2& position, const glm::vec2& size);
Entity CreateEntity(const std::string& name, const glm::mat4& transform);
};
}

View file

@ -1,67 +1,54 @@
#include <LightEngine.h>
#include <glm/gtc/matrix_transform.hpp>
namespace Light {
class MirrorLayer : public Layer
{
private:
std::shared_ptr<Texture> m_AwesomefaceTexture;
std::vector<glm::vec3> positions;
std::vector<glm::vec2> sizes;
Ref<Texture> m_AwesomefaceTexture;
glm::vec2 m_Direction;
float m_Speed = 1000.0f;
Ref<Camera> m_Camera;
Ref<Framebuffer> m_Framebuffer;
Scene m_Scene;
Entity m_TestEntity;
bool m_GameSceneEvents = false;
Entity m_CameraEntity;
public:
MirrorLayer(const std::string& name)
: Layer(name), m_Direction(glm::vec2(0.0f, 0.0f))
{
m_Camera = std::make_shared<Camera>(glm::vec2(500.0f), NULL, 1000.0f);
ResourceManager::LoadTexture("awesomeface", "res/Textures/awesomeface.png");
m_AwesomefaceTexture = ResourceManager::GetTexture("awesomeface");
m_Framebuffer = std::shared_ptr<Framebuffer>(Framebuffer::Create({ 800u, 600u, 1, glm::vec4(1.0f, 0.0f, 0.0f, 1.0f) }, GraphicsContext::GetSharedContext()));
m_CameraEntity = m_Scene.CreateEntity("camera", glm::mat4(1.0f));
m_CameraEntity.AddComponent<CameraComponent>(SceneCamera(), true);
for (int i = 0; i < 250; i++)
{
glm::vec3 position = glm::vec3(rand() % 3000 - 1400.0f, rand() % 3000 - 1400.0f, 0.0f);
glm::vec2 size = glm::vec2(250.0f, 250.0f);
positions.push_back(position);
sizes.push_back(size);
m_Scene.CreateEntity("quad", position, size).AddComponent<SpriteRendererComponent>(m_AwesomefaceTexture);
m_Scene.CreateEntity("quad", glm::translate(glm::mat4(1.0f), { position.x, position.y, 0.0f }) *
glm::scale(glm::mat4(1.0f), { size.x, size.y, 1.0f})).AddComponent<SpriteRendererComponent>(m_AwesomefaceTexture);
}
}
void OnRender() override
{
m_Camera->CalculateProjection();
m_Camera->CalculateView();
Renderer::BeginScene(m_Camera, m_Framebuffer);
m_Scene.OnRender();
Renderer::EndScene();
m_Scene.OnRender(m_Framebuffer);
}
void OnUserInterfaceUpdate()
{
if (ImGui::Begin("GameView"))
{
// #todo: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Input::ReceiveGameEvents(ImGui::IsWindowFocused());
static ImVec2 regionAvailPrev = { 0, 0 };
@ -70,7 +57,10 @@ namespace Light {
if (regionAvail.x != regionAvailPrev.x || regionAvail.y != regionAvailPrev.y)
{
m_Framebuffer->Resize({ regionAvail.x, regionAvail.y });
m_Camera->OnResize({ regionAvail.x, regionAvail.y });
auto& cameraComp = m_CameraEntity.GetComponent<CameraComponent>();
cameraComp.camera.SetViewportSize(regionAvail.x, regionAvail.y);
regionAvailPrev = regionAvail;
}
@ -99,7 +89,8 @@ namespace Light {
else
m_Direction.y = 0.0f;
m_Camera->Move(m_Direction * m_Speed * deltaTime);
auto& transform = m_CameraEntity.GetComponent<TransformComponent>();
transform = glm::translate(transform.transform, glm::vec3(m_Direction * m_Speed * deltaTime, 0.0));
}
};