3 #include <core/Assertions.h>
4 #include <render/shader/UBO.h>
5 #include <utility/Types.h>
6 #include "component/AudioSpeechComponent.h"
7 #include "component/BillboardComponent.h"
8 #include "component/MeshComponent.h"
9 #include "component/MeshDynamicComponent.h"
10 #include "component/SkyboxComponent.h"
11 #include "component/TagComponents.h"
12 #include "component/TransformComponent.h"
13 #include "component/MeshSpriteComponent.h"
14 #include "component/LayerComponents.h"
16 using namespace chira;
18 Viewport::Viewport(glm::vec2i size_,
ColorRGB backgroundColor_,
bool linearFiltering_)
20 , backgroundColor(backgroundColor_)
21 , linearFiltering(linearFiltering_) {
22 this->recreateFrameBuffer();
25 Scene* Viewport::addScene() {
26 auto uuid = UUIDGenerator::getNewUUID();
27 return this->addScene(uuid);
30 Scene* Viewport::addScene(
const std::string& name) {
31 auto* scene = this->addScene();
32 scene->getRegistry().emplace<
NameComponent>(scene->getRawHandle(), name);
36 Scene* Viewport::addScene(uuids::uuid uuid) {
37 runtime_assert(!this->scenes.contains(uuid),
"Scene UUID is already present!");
38 this->scenes[uuid] = std::unique_ptr<Scene>(
new Scene{});
39 auto& scene = this->scenes.at(uuid);
40 scene->getRegistry().get<
UUIDComponent>(scene->getRawHandle()).uuid = uuid;
44 Scene* Viewport::addScene(uuids::uuid uuid,
const std::string& name) {
45 auto* scene = this->addScene(uuid);
46 scene->getRegistry().emplace<
NameComponent>(scene->getRawHandle(), name);
50 Scene* Viewport::getScene(uuids::uuid sceneID) {
51 if (this->hasScene(sceneID)) {
54 return this->scenes.at(sceneID).get();
57 bool Viewport::hasScene(uuids::uuid sceneID) {
58 return this->scenes.contains(sceneID);
61 void Viewport::removeScene(uuids::uuid sceneID) {
62 runtime_assert(this->hasScene(sceneID),
"Trying to remove a scene with a UUID that doesn't exist!");
63 this->scenes.erase(sceneID);
66 void Viewport::removeAllScenes() {
67 for (
const auto& [uuid, scene] : this->scenes) {
68 this->removeScene(uuid);
72 void Viewport::update() {
73 for (
const auto& [uuid, scene] : this->scenes) {
74 if (
auto* camera = this->getCamera()) {
77 for (
const auto [entity, billboardComponent] : billboardView.each()) {
78 if (billboardComponent.x)
79 billboardComponent.transform->
setPitch(camera->transform->getPitch());
80 if (billboardComponent.y)
81 billboardComponent.transform->setYaw(camera->transform->getYaw());
82 if (billboardComponent.z)
83 billboardComponent.transform->setRoll(camera->transform->getRoll());
89 auto angelScriptView = scene->getEntities<AngelScriptComponent>();
90 for (
const auto [entity, angelScriptComponent] : angelScriptView.each()) {
91 angelScriptComponent.update();
97 void Viewport::render() {
98 Renderer::setClearColor({this->backgroundColor, 1.f});
99 Renderer::pushFrameBuffer(this->frameBufferHandle);
103 int directionalLightsCount = 0;
105 int pointLightsCount = 0;
107 int spotLightsCount = 0;
109 for (
const auto& [uuid, scene] : this->scenes) {
111 for (
auto [entity, directionalLightComponent] : directionalLightsView.each()) {
112 if (directionalLightsCount < DIRECTIONAL_LIGHT_MAX) {
113 directionalLightComponentArray[directionalLightsCount] = &directionalLightComponent;
115 directionalLightsCount++;
119 for (
auto [entity, pointLightComponent] : pointLightsView.each()) {
120 if (pointLightsCount < POINT_LIGHT_MAX) {
121 pointLightComponentArray[pointLightsCount] = &pointLightComponent;
127 for (
auto [entity, spotLightComponent] : spotLightsView.each()) {
128 if (spotLightsCount < SPOT_LIGHT_MAX) {
129 spotLightComponentArray[spotLightsCount] = &spotLightComponent;
134 LightsUBO::get().update(directionalLightComponentArray, pointLightComponentArray, spotLightComponentArray,
135 {directionalLightsCount, pointLightsCount, spotLightsCount});
137 foreach(LAYER_COMPONENTS, [&](
auto layer) {
138 if (!(this->getCamera()->activeLayers & layer.index)) {
142 using CurrentLayer = decltype(layer);
143 for (
const auto& [uuid, scene] : this->scenes) {
144 auto& registry = scene->getRegistry();
147 scene->setupForRender(this->size);
149 auto meshView = scene->template getEntities<MeshComponent, CurrentLayer>(entt::exclude<NoRenderTagComponent>);
150 for (
auto entity : meshView) {
151 auto& transformComponent = registry.template get<TransformComponent>(entity);
152 auto& meshComponent = registry.template get<MeshComponent>(entity);
153 meshComponent.mesh->render(transformComponent.getMatrix());
157 auto meshDynamicView = scene->template getEntities<MeshDynamicComponent, CurrentLayer>(entt::exclude<NoRenderTagComponent>);
158 for (
auto entity : meshDynamicView) {
159 auto& transformComponent = registry.template get<TransformComponent>(entity);
160 auto& meshDynamicComponent = registry.template get<MeshDynamicComponent>(entity);
161 meshDynamicComponent.meshBuilder.render(transformComponent.getMatrix());
165 auto meshSpriteView = scene->template getEntities<MeshSpriteComponent, CurrentLayer>(entt::exclude<NoRenderTagComponent>);
166 for (
auto entity : meshSpriteView) {
167 auto& transformComponent = registry.template get<TransformComponent>(entity);
168 auto& meshSpriteComponent = registry.template get<MeshSpriteComponent>(entity);
169 meshSpriteComponent.sprite.render(transformComponent.getMatrix());
175 for (
const auto& [uuid, scene] : this->scenes) {
176 auto& registry = scene->getRegistry();
180 if (!skyboxView.empty()) {
181 auto& skyboxComponent = skyboxView.get<
SkyboxComponent>(skyboxView.front());
182 skyboxComponent.skybox.render(glm::identity<glm::mat4>());
185 Renderer::popFrameBuffer();
188 void Viewport::recreateFrameBuffer() {
189 if (this->frameBufferHandle) {
190 Renderer::destroyFrameBuffer(this->frameBufferHandle);
192 this->frameBufferHandle = Renderer::createFrameBuffer(this->size.x, this->size.y, WrapMode::REPEAT, WrapMode::REPEAT,
193 this->linearFiltering ? FilterMode::LINEAR : FilterMode::NEAREST,
true);