diff --git a/README.md b/README.md
index 065dba77..b1b164a0 100644
--- a/README.md
+++ b/README.md
@@ -42,7 +42,7 @@ This engine started as a C++ training project, with hopes of being applied in my
| **Data** | - File formats:
- Meshes:
- GLTF 2.0 (using [fastgltf](https://github.com/spnda/fastgltf))
- OBJ (using ???)
- Images:
- PNG, JPEG, BMP, TGA, GIF (using [stb](https://github.com/nothings/stb))
- SVG (using [lunasvg](https://github.com/sammycage/lunasvg))
- WEBP (using [libwebp](https://github.com/webmproject/libwebp))
- WEBM (video only) (using [libwebm](https://github.com/webmproject/libwebm))
- Fonts:
- TTF (using [stb](https://github.com/nothings/stb))
- Audio (using [BASS](https://www.un4seen.com/)):
- OGG
- MP4
- MP3
- WAV
- Supports url audio
- JSON (using [glaze](https://github.com/stephenberry/glaze)) |
| **Math** | - Vectors, colors, matrices & quaternions support
- Bezier curve & easing
- Packing support (float16, etc) |
| **Physics** | - 3D multi-threaded physics (using [JoltPhysics](https://github.com/jrouwe/JoltPhysics))
- 2D physics support (using [Muli](https://github.com/Sopiro/Muli)) |
-| **Rendering** | - **Vulkan** & **DirectX 12** support using ([Diligent](https://github.com/DiligentGraphics/DiligentCore))
- Material system similar to unity
- Window & Input callbacks (using [GLFW](https://github.com/glfw/glfw))
- Clustered rendering :
- Decals (**WIP**)
- Lights (point / spot/ directional)
- Linux (**steamdeck**) support
- Bindless rendering
- Post-processing support
- 2D rendering
- Custom rendering plugins
- GPU Picking
- [IMGUI](https://github.com/ocornut/imgui) support
- GPU Particle system
|
+| **Rendering** | - **Vulkan** & **DirectX 12** support using ([Diligent](https://github.com/DiligentGraphics/DiligentCore))
- Material system similar to unity
- Window & Input callbacks (using [GLFW](https://github.com/glfw/glfw))
- Clustered rendering :
- Decals (**WIP**)
- Lights (point / spot/ directional)
- Linux (**steamdeck**) support
- Bindless rendering
- Post-processing support
- 2D rendering
- Custom rendering plugins
- Multiple camera support
- GPU Picking
- [IMGUI](https://github.com/ocornut/imgui) support
- GPU Particle system
|
| **Network** | - HTTP / HTTPS requests (using [libcpr](https://github.com/libcpr/cpr))
- Packet network implementation
- **NetVar** & **NetArray** support for [snapshot](https://gafferongames.com/post/snapshot_interpolation/) implementation
- Simple socket implementation |
| **Scripting** | - Scripting / modding support with LUAU (using [luabridge3](https://github.com/kunitoki/LuaBridge3) + [luau](https://github.com/luau-lang/luau)) |
| **Other** | - I18N (internationalization) support
- Settings support
- Steamworks support
- Custom UI
- DEV Console with support for custom commands & scripts
- Timer utils (based on [GMOD's](https://wiki.facepunch.com/gmod/timer) timers)
- File watcher implementation
- Threading utilities |
@@ -55,7 +55,7 @@ This engine started as a C++ training project, with hopes of being applied in my
| 007-particle-system
| 008-ui
| 009-gltf
|
| 010-bass-audio
| 011-physics-3D
| 012-physics-2D
|
| 013-webm
| 014-scripting
| 015-gpu-picking
|
-| 016-steamworks
| 017-imgui
| |
+| 016-steamworks
| 017-imgui
| 018-camera
|
# BUILDING
diff --git a/rawrbox.render/include/rawrbox/render/bindless.hpp b/rawrbox.render/include/rawrbox/render/bindless.hpp
index 1b9e80a6..065e0419 100644
--- a/rawrbox.render/include/rawrbox/render/bindless.hpp
+++ b/rawrbox.render/include/rawrbox/render/bindless.hpp
@@ -62,7 +62,6 @@ namespace rawrbox {
// SIGNATURES ------
static void createSignatures();
- static void bindSignatures();
// -----------------
static uint32_t internalRegister(Diligent::ITextureView* view, rawrbox::TEXTURE_TYPE type);
@@ -80,6 +79,10 @@ namespace rawrbox {
static void update();
+ // SIGNATURES
+ static void bindSignatures();
+ // ----------------
+
// TEXTURES -------
static void registerTexture(rawrbox::TextureBase& texture);
static void registerTexture(rawrbox::TextureRender& texture);
diff --git a/rawrbox.render/include/rawrbox/render/cameras/base.hpp b/rawrbox.render/include/rawrbox/render/cameras/base.hpp
index 4e746a12..81bafef6 100644
--- a/rawrbox.render/include/rawrbox/render/cameras/base.hpp
+++ b/rawrbox.render/include/rawrbox/render/cameras/base.hpp
@@ -3,6 +3,8 @@
#include
#include
#include
+#include
+#include
#include
#include
@@ -11,6 +13,9 @@
#include
+#define CREATE_FLAGS(name, value) \
+ const uint32_t name = 1 << value;
+
namespace rawrbox {
struct CameraStaticUniforms { // Uniforms that won't be updated that frequently
rawrbox::Matrix4x4 gProjection = {};
@@ -26,6 +31,12 @@ namespace rawrbox {
bool operator!=(const CameraStaticUniforms& other) const { return !operator==(other); }
};
+ namespace CameraLayers {
+ // USER DEFINED
+ RB_RENDER_CAMERA_LAYERS(CREATE_FLAGS)
+ // ------------
+ }; // namespace CameraLayers
+
struct CameraUniforms {
rawrbox::Matrix4x4 gView = {};
rawrbox::Matrix4x4 gViewInv = {};
@@ -47,6 +58,8 @@ namespace rawrbox {
class CameraBase {
protected:
+ bool _enabled = true;
+
rawrbox::Vector3f _pos = {};
rawrbox::Vector4f _angle = {};
@@ -55,12 +68,15 @@ namespace rawrbox {
rawrbox::Matrix4x4 _world = {};
+ uint32_t _layers = 0; // None by default, it's up to the user to use this or not
+
+ // Renderer ----
+ std::unique_ptr _renderTarget = nullptr;
+ // --------------------------
+
float _z_near = 0.01F;
float _z_far = 100.F;
- Diligent::RefCntAutoPtr _staticUniforms;
- Diligent::RefCntAutoPtr _uniforms;
-
// LOGGER ------
std::unique_ptr _logger = std::make_unique("RawrBox-Camera");
// -------------
@@ -69,13 +85,15 @@ namespace rawrbox {
virtual rawrbox::CameraStaticUniforms getStaticData();
public:
- virtual ~CameraBase();
+ static Diligent::RefCntAutoPtr staticUniforms;
+ static Diligent::RefCntAutoPtr uniforms;
- CameraBase() = default;
+ CameraBase(const rawrbox::Vector2u& renderSize, bool depth = true);
CameraBase(CameraBase&&) = default;
CameraBase& operator=(CameraBase&&) = default;
CameraBase(const CameraBase&) = delete;
CameraBase& operator=(const CameraBase&) = delete;
+ virtual ~CameraBase();
// UTILS -----
virtual void setPos(const rawrbox::Vector3f& pos);
@@ -100,12 +118,26 @@ namespace rawrbox {
[[nodiscard]] virtual rawrbox::Vector3f worldToScreen(const rawrbox::Vector3f& pos) const;
[[nodiscard]] virtual rawrbox::Vector3f screenToWorld(const rawrbox::Vector2f& screen_pos, const rawrbox::Vector3f& origin = {0, 0, 0}) const;
+
+ virtual bool isEnabled() const;
+ virtual void setEnabled(bool enabled);
+
+ virtual uint32_t getLayers() const;
+ virtual void setLayers(uint32_t layers);
+ virtual bool shouldRenderLayer(uint32_t layer) const;
// ----------------
- [[nodiscard]] virtual Diligent::IBuffer* uniforms() const;
- [[nodiscard]] virtual Diligent::IBuffer* staticUniforms() const;
+ // RENDER TARGET ----
+ virtual void begin();
+ virtual void end();
+
+ [[nodiscard]] virtual Diligent::ITextureView* getDepth() const;
+ [[nodiscard]] virtual Diligent::ITextureView* getColor(bool rt = false) const;
+ [[nodiscard]] virtual rawrbox::TextureRender* getRenderTarget() const;
+ // ------------
virtual void initialize();
+ virtual void upload();
virtual void updateBuffer();
virtual void update();
diff --git a/rawrbox.render/include/rawrbox/render/cameras/perspective.hpp b/rawrbox.render/include/rawrbox/render/cameras/perspective.hpp
index ecb5b05f..1c6489c1 100644
--- a/rawrbox.render/include/rawrbox/render/cameras/perspective.hpp
+++ b/rawrbox.render/include/rawrbox/render/cameras/perspective.hpp
@@ -8,9 +8,7 @@
namespace rawrbox {
class CameraPerspective : public rawrbox::CameraBase {
protected:
- rawrbox::Vector2u _winSize = {};
float _FOV = 60.F;
-
void updateMtx() override;
public:
@@ -20,7 +18,7 @@ namespace rawrbox {
CameraPerspective& operator=(CameraPerspective&&) = default;
~CameraPerspective() override = default;
- explicit CameraPerspective(const rawrbox::Vector2u& winSize, float FOV = 60.F, float near = 0.01F, float far = 100.F);
+ explicit CameraPerspective(const rawrbox::Vector2u& renderSize, float FOV = 60.F, float near = 0.01F, float far = 100.F, bool depth = true);
[[nodiscard]] rawrbox::Vector3f worldToScreen(const rawrbox::Vector3f& pos) const override;
[[nodiscard]] rawrbox::Vector3f screenToWorld(const rawrbox::Vector2f& screenPos, const rawrbox::Vector3f& origin = {0, 0, 0}) const override;
diff --git a/rawrbox.render/include/rawrbox/render/plugins/base.hpp b/rawrbox.render/include/rawrbox/render/plugins/base.hpp
index 96a7b7e1..a1912f53 100644
--- a/rawrbox.render/include/rawrbox/render/plugins/base.hpp
+++ b/rawrbox.render/include/rawrbox/render/plugins/base.hpp
@@ -1,6 +1,7 @@
#pragma once
#include
+#include
#include
#include
@@ -40,8 +41,8 @@ namespace rawrbox {
virtual void resize(const rawrbox::Vector2u& renderSize);
virtual void upload();
- virtual void preRender();
- virtual void postRender(rawrbox::TextureRender& renderTarget);
+ virtual void preRender(const rawrbox::CameraBase& camera);
+ virtual void postRender(const rawrbox::CameraBase& camera);
virtual void update();
diff --git a/rawrbox.render/include/rawrbox/render/plugins/clustered.hpp b/rawrbox.render/include/rawrbox/render/plugins/clustered.hpp
index bb537e7b..da8d8a5d 100644
--- a/rawrbox.render/include/rawrbox/render/plugins/clustered.hpp
+++ b/rawrbox.render/include/rawrbox/render/plugins/clustered.hpp
@@ -71,7 +71,7 @@ namespace rawrbox {
void signatures(std::vector& sig) override;
void bindStatic(Diligent::IPipelineResourceSignature& sig) override;
- void preRender() override;
+ void preRender(const rawrbox::CameraBase& camera) override;
std::string getID() override;
};
diff --git a/rawrbox.render/include/rawrbox/render/plugins/particle_engine.hpp b/rawrbox.render/include/rawrbox/render/plugins/particle_engine.hpp
index a757b800..fa38bab7 100644
--- a/rawrbox.render/include/rawrbox/render/plugins/particle_engine.hpp
+++ b/rawrbox.render/include/rawrbox/render/plugins/particle_engine.hpp
@@ -50,7 +50,7 @@ namespace rawrbox {
void signatures(std::vector& sig) override;
void bindStatic(Diligent::IPipelineResourceSignature& sig) override;
- void preRender() override;
+ void preRender(const rawrbox::CameraBase& camera) override;
[[nodiscard]] Diligent::IPipelineResourceSignature* getSignature(bool dynamic = true) const;
[[nodiscard]] Diligent::IShaderResourceBinding* getBind(bool dynamic = true) const;
diff --git a/rawrbox.render/include/rawrbox/render/plugins/post_process.hpp b/rawrbox.render/include/rawrbox/render/plugins/post_process.hpp
index 076ba70d..30aa4cb8 100644
--- a/rawrbox.render/include/rawrbox/render/plugins/post_process.hpp
+++ b/rawrbox.render/include/rawrbox/render/plugins/post_process.hpp
@@ -25,7 +25,7 @@ namespace rawrbox {
void signatures(std::vector& sig) override;
void bindStatic(Diligent::IPipelineResourceSignature& sig) override;
- void postRender(rawrbox::TextureRender& render) override;
+ void postRender(const rawrbox::CameraBase& camera) override;
// PLUGIN UTILS ----
template
diff --git a/rawrbox.render/include/rawrbox/render/render_config.hpp b/rawrbox.render/include/rawrbox/render/render_config.hpp
index a89e70bf..659f8803 100644
--- a/rawrbox.render/include/rawrbox/render/render_config.hpp
+++ b/rawrbox.render/include/rawrbox/render/render_config.hpp
@@ -40,3 +40,10 @@
#define RB_RENDER_THREAD_GROUP_SIZE (RB_RENDER_CLUSTERS_X_THREADS * RB_RENDER_CLUSTERS_Y_THREADS * RB_RENDER_CLUSTERS_Z_THREADS)
// ----------------
+
+// CAMERA -----
+// Add more layers if needed, you can then check if the camera should draw your model by checking if the layer is enabled
+#define RB_RENDER_CAMERA_LAYERS(flag) \
+ flag(LAYER_1, 1) \
+ flag(LAYER_2, 2)
+// ----------------
diff --git a/rawrbox.render/include/rawrbox/render/renderer.hpp b/rawrbox.render/include/rawrbox/render/renderer.hpp
index 39fe6e02..1367d842 100644
--- a/rawrbox.render/include/rawrbox/render/renderer.hpp
+++ b/rawrbox.render/include/rawrbox/render/renderer.hpp
@@ -43,10 +43,6 @@ namespace rawrbox {
std::map> _renderPlugins = {};
// --------------
- // Post process renderer ----
- std::unique_ptr _render = nullptr;
- // --------------------------
-
#ifdef _DEBUG
// QUERIES ---
std::unordered_map> _query = {};
@@ -64,8 +60,8 @@ namespace rawrbox {
std::map _introList = {{"./assets/textures/rawrbox.webp", {1.4F, false}}}; // rawrbox intro, always the first
//----
- std::function _drawCall = nullptr;
- std::function _tempRender = nullptr;
+ std::function _drawCall = nullptr;
+ std::function _tempRender = nullptr;
rawrbox::Colorf _clearColor = rawrbox::Colors::Black();
@@ -88,11 +84,14 @@ namespace rawrbox {
// OTHER HANDLES
std::unique_ptr _logger = std::make_unique("RawrBox-Renderer");
- std::unique_ptr _camera = nullptr;
std::unique_ptr _stencil = nullptr;
std::unique_ptr _GPUBlit = nullptr;
// -------------
+ // CAMERAS ---
+ std::vector> _cameras = {};
+ // ----------
+
// INTRO ------
virtual void playIntro();
virtual void introComplete();
@@ -151,7 +150,7 @@ namespace rawrbox {
[[nodiscard]] virtual const std::map>& getPlugins() const;
// -----------------------------------
- virtual void setDrawCall(std::function call);
+ virtual void setDrawCall(std::function call);
virtual void update();
virtual void render();
@@ -163,15 +162,17 @@ namespace rawrbox {
// CAMERA ------
template
- T* setupCamera(CallbackArgs&&... args) {
- this->_camera = std::make_unique(std::forward(args)...);
- this->setMainCamera(this->_camera.get());
+ T* createCamera(CallbackArgs&&... args) {
+ if (this->_initialized) CRITICAL_RAWRBOX("'createCamera' must be called before initializing the renderer!");
+ auto camera = std::make_unique(std::forward(args)...);
- return dynamic_cast(this->_camera.get());
+ auto cameraPtr = camera.get();
+ this->_cameras.push_back(std::move(camera));
+ return dynamic_cast(cameraPtr);
}
- virtual void setMainCamera(rawrbox::CameraBase* camera) const;
- [[nodiscard]] virtual rawrbox::CameraBase* camera() const;
+ virtual void setActiveCamera(rawrbox::CameraBase* camera) const;
+ [[nodiscard]] virtual rawrbox::CameraBase* getActiveCamera() const;
// ----------------
// Utils ----
@@ -184,9 +185,6 @@ namespace rawrbox {
// WARNING: NOT THREAD SAFE!!
[[nodiscard]] virtual Diligent::IRenderDevice* device() const;
- [[nodiscard]] virtual Diligent::ITextureView* getDepth() const;
- [[nodiscard]] virtual Diligent::ITextureView* getColor(bool rt = false) const;
-
[[nodiscard]] virtual std::filesystem::path getShadersDirectory() const;
[[nodiscard]] virtual const Diligent::RENDER_DEVICE_TYPE& getRenderType() const;
diff --git a/rawrbox.render/src/bindless.cpp b/rawrbox.render/src/bindless.cpp
index cc9c7b00..38d53630 100644
--- a/rawrbox.render/src/bindless.cpp
+++ b/rawrbox.render/src/bindless.cpp
@@ -85,11 +85,7 @@ namespace rawrbox {
// Create signatures ------
createSignatures();
- // -------------
-
- // Bind signatures ------
- bindSignatures();
- // -------------
+ // ------------
}
void BindlessManager::shutdown() {
@@ -111,8 +107,6 @@ namespace rawrbox {
// SIGNATURES ---------
void BindlessManager::createSignatures() {
auto* renderer = rawrbox::RENDERER;
-
- auto* camera = renderer->camera();
auto* device = renderer->device();
Diligent::PipelineResourceSignatureDesc PRSDesc;
@@ -127,12 +121,9 @@ namespace rawrbox {
{Diligent::SHADER_TYPE_PIXEL, "Constants", 1, Diligent::SHADER_RESOURCE_TYPE_CONSTANT_BUFFER, Diligent::SHADER_RESOURCE_VARIABLE_TYPE_STATIC},
{Diligent::SHADER_TYPE_PIXEL, "g_Textures", RB_RENDER_MAX_TEXTURES, Diligent::SHADER_RESOURCE_TYPE_TEXTURE_SRV, Diligent::SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, Diligent::PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY},
- };
- if (camera != nullptr) {
- resources.emplace_back(Diligent::SHADER_TYPE_VERTEX | Diligent::SHADER_TYPE_PIXEL | Diligent::SHADER_TYPE_GEOMETRY, "Camera", 1, Diligent::SHADER_RESOURCE_TYPE_CONSTANT_BUFFER, Diligent::SHADER_RESOURCE_VARIABLE_TYPE_STATIC, Diligent::PIPELINE_RESOURCE_FLAG_NO_DYNAMIC_BUFFERS);
- resources.emplace_back(Diligent::SHADER_TYPE_VERTEX | Diligent::SHADER_TYPE_PIXEL | Diligent::SHADER_TYPE_GEOMETRY, "SCamera", 1, Diligent::SHADER_RESOURCE_TYPE_CONSTANT_BUFFER, Diligent::SHADER_RESOURCE_VARIABLE_TYPE_STATIC, Diligent::PIPELINE_RESOURCE_FLAG_NO_DYNAMIC_BUFFERS);
- }
+ {Diligent::SHADER_TYPE_VERTEX | Diligent::SHADER_TYPE_PIXEL | Diligent::SHADER_TYPE_GEOMETRY, "Camera", 1, Diligent::SHADER_RESOURCE_TYPE_CONSTANT_BUFFER, Diligent::SHADER_RESOURCE_VARIABLE_TYPE_STATIC, Diligent::PIPELINE_RESOURCE_FLAG_NO_DYNAMIC_BUFFERS},
+ {Diligent::SHADER_TYPE_VERTEX | Diligent::SHADER_TYPE_PIXEL | Diligent::SHADER_TYPE_GEOMETRY, "SCamera", 1, Diligent::SHADER_RESOURCE_TYPE_CONSTANT_BUFFER, Diligent::SHADER_RESOURCE_VARIABLE_TYPE_STATIC, Diligent::PIPELINE_RESOURCE_FLAG_NO_DYNAMIC_BUFFERS}};
// Add extra signatures ----
for (const auto& plugin : renderer->getPlugins()) {
@@ -162,22 +153,17 @@ namespace rawrbox {
}
void BindlessManager::bindSignatures() {
- auto* renderer = rawrbox::RENDERER;
- auto* camera = renderer->camera();
-
// Setup graphic binds ---
signature->GetStaticVariableByName(Diligent::SHADER_TYPE_VERTEX, "Constants")->Set(signatureBufferVertex);
signature->GetStaticVariableByName(Diligent::SHADER_TYPE_VERTEX, "SkinnedConstants")->Set(signatureBufferVertexSkinned);
- if (camera != nullptr) {
- signature->GetStaticVariableByName(Diligent::SHADER_TYPE_VERTEX, "Camera")->Set(camera->uniforms());
- signature->GetStaticVariableByName(Diligent::SHADER_TYPE_PIXEL, "Camera")->Set(camera->uniforms());
- signature->GetStaticVariableByName(Diligent::SHADER_TYPE_GEOMETRY, "Camera")->Set(camera->uniforms());
+ signature->GetStaticVariableByName(Diligent::SHADER_TYPE_VERTEX, "Camera")->Set(rawrbox::CameraBase::uniforms);
+ signature->GetStaticVariableByName(Diligent::SHADER_TYPE_PIXEL, "Camera")->Set(rawrbox::CameraBase::uniforms);
+ signature->GetStaticVariableByName(Diligent::SHADER_TYPE_GEOMETRY, "Camera")->Set(rawrbox::CameraBase::uniforms);
- signature->GetStaticVariableByName(Diligent::SHADER_TYPE_VERTEX, "SCamera")->Set(camera->staticUniforms());
- signature->GetStaticVariableByName(Diligent::SHADER_TYPE_PIXEL, "SCamera")->Set(camera->staticUniforms());
- signature->GetStaticVariableByName(Diligent::SHADER_TYPE_GEOMETRY, "SCamera")->Set(camera->staticUniforms());
- }
+ signature->GetStaticVariableByName(Diligent::SHADER_TYPE_VERTEX, "SCamera")->Set(rawrbox::CameraBase::staticUniforms);
+ signature->GetStaticVariableByName(Diligent::SHADER_TYPE_PIXEL, "SCamera")->Set(rawrbox::CameraBase::staticUniforms);
+ signature->GetStaticVariableByName(Diligent::SHADER_TYPE_GEOMETRY, "SCamera")->Set(rawrbox::CameraBase::staticUniforms);
signature->GetStaticVariableByName(Diligent::SHADER_TYPE_PIXEL, "Constants")->Set(signatureBufferPixel);
// ------------
diff --git a/rawrbox.render/src/cameras/base.cpp b/rawrbox.render/src/cameras/base.cpp
index 3846f0b8..c9ad421b 100644
--- a/rawrbox.render/src/cameras/base.cpp
+++ b/rawrbox.render/src/cameras/base.cpp
@@ -5,45 +5,65 @@
#include
namespace rawrbox {
- CameraBase::~CameraBase() {
- RAWRBOX_DESTROY(this->_uniforms);
- RAWRBOX_DESTROY(this->_staticUniforms);
+ Diligent::RefCntAutoPtr CameraBase::staticUniforms;
+ Diligent::RefCntAutoPtr CameraBase::uniforms;
+
+ CameraBase::CameraBase(const rawrbox::Vector2u& renderSize, bool depth) {
+ this->_renderTarget = std::make_unique(renderSize, depth);
}
+ CameraBase::~CameraBase() { this->_renderTarget.reset(); }
+
void CameraBase::initialize() {
- if (this->_staticUniforms != nullptr) CRITICAL_RAWRBOX("Camera already initialized!");
- {
- auto staticData = this->getStaticData();
+ if (this->_renderTarget == nullptr) CRITICAL_RAWRBOX("Render target not initialized!");
+ this->_renderTarget->upload(Diligent::TEX_FORMAT_RGBA8_UNORM);
+
+ // ADD GPU PICKING TEXTURE
+ auto idIndex = this->_renderTarget->addTexture(Diligent::TEX_FORMAT_RGBA8_UNORM);
+ this->_renderTarget->addView(idIndex, Diligent::TEXTURE_VIEW_RENDER_TARGET);
+ // --------
+ }
+
+ void CameraBase::upload() {
+ if (rawrbox::RENDERER == nullptr) CRITICAL_RAWRBOX("Renderer not initialized!");
- Diligent::BufferDesc CBDesc;
- CBDesc.Name = "rawrbox::Camera::Static::Uniforms";
- CBDesc.Usage = Diligent::USAGE_IMMUTABLE;
- CBDesc.BindFlags = Diligent::BIND_UNIFORM_BUFFER;
- CBDesc.Size = sizeof(rawrbox::CameraStaticUniforms);
+ auto* device = rawrbox::RENDERER->device();
+ if (device == nullptr) CRITICAL_RAWRBOX("Device not initialized!");
- Diligent::BufferData bData;
- bData.DataSize = CBDesc.Size;
- bData.pData = &staticData;
+ // These are shared across all the cameras. For performance reasons, we won't support different cameras (for now)
+ if (staticUniforms != nullptr || uniforms != nullptr) CRITICAL_RAWRBOX("Camera buffers already initialized!");
+ auto staticData = this->getStaticData();
- rawrbox::RENDERER->device()->CreateBuffer(CBDesc, &bData, &this->_staticUniforms);
- }
+ // STATIC BUFFER ---
+ Diligent::BufferDesc StaticDesc;
+ StaticDesc.Name = "rawrbox::Camera::Static::Uniforms";
+ StaticDesc.Usage = Diligent::USAGE_IMMUTABLE;
+ StaticDesc.BindFlags = Diligent::BIND_UNIFORM_BUFFER;
+ StaticDesc.Size = sizeof(rawrbox::CameraStaticUniforms);
- {
- Diligent::BufferDesc CBDesc;
- CBDesc.Name = "rawrbox::Camera::Uniforms";
- CBDesc.Usage = Diligent::USAGE_DEFAULT;
- CBDesc.BindFlags = Diligent::BIND_UNIFORM_BUFFER;
- CBDesc.Size = sizeof(rawrbox::CameraUniforms);
+ Diligent::BufferData sData;
+ sData.DataSize = StaticDesc.Size;
+ sData.pData = &staticData;
- rawrbox::RENDERER->device()->CreateBuffer(CBDesc, nullptr, &this->_uniforms);
- }
+ device->CreateBuffer(StaticDesc, &sData, &staticUniforms);
+ // ------------
+
+ // DYNAMIC BUFFER ---
+ Diligent::BufferDesc CBDesc;
+ CBDesc.Name = "rawrbox::Camera::Uniforms";
+ CBDesc.Usage = Diligent::USAGE_DEFAULT;
+ CBDesc.BindFlags = Diligent::BIND_UNIFORM_BUFFER;
+ CBDesc.Size = sizeof(rawrbox::CameraUniforms);
+
+ device->CreateBuffer(CBDesc, nullptr, &uniforms);
+ // ------------
// BARRIER -----
- rawrbox::BarrierUtils::barrier({{this->_staticUniforms, Diligent::RESOURCE_STATE_UNKNOWN, Diligent::RESOURCE_STATE_CONSTANT_BUFFER, Diligent::STATE_TRANSITION_FLAG_UPDATE_STATE},
- {this->_uniforms, Diligent::RESOURCE_STATE_UNKNOWN, Diligent::RESOURCE_STATE_CONSTANT_BUFFER, Diligent::STATE_TRANSITION_FLAG_UPDATE_STATE}});
+ rawrbox::BarrierUtils::barrier({{staticUniforms, Diligent::RESOURCE_STATE_UNKNOWN, Diligent::RESOURCE_STATE_CONSTANT_BUFFER, Diligent::STATE_TRANSITION_FLAG_UPDATE_STATE},
+ {uniforms, Diligent::RESOURCE_STATE_UNKNOWN, Diligent::RESOURCE_STATE_CONSTANT_BUFFER, Diligent::STATE_TRANSITION_FLAG_UPDATE_STATE}});
// -----------
- this->_logger->info("Initializing camera");
+ this->_logger->info("Initializing camera buffers");
}
void CameraBase::updateMtx() { CRITICAL_RAWRBOX("Not implemented"); };
@@ -134,8 +154,41 @@ namespace rawrbox {
this->updateBuffer();
}
+ rawrbox::Vector3f CameraBase::worldToScreen(const rawrbox::Vector3f& /*pos*/) const {
+ CRITICAL_RAWRBOX("Not implemented");
+ }
+
+ rawrbox::Vector3f CameraBase::screenToWorld(const rawrbox::Vector2f& /*screen_pos*/, const rawrbox::Vector3f& /*origin*/) const {
+ CRITICAL_RAWRBOX("Not implemented");
+ }
+
+ bool CameraBase::isEnabled() const { return this->_enabled; }
+ void CameraBase::setEnabled(bool enabled) { this->_enabled = enabled; }
+
+ uint32_t CameraBase::getLayers() const { return this->_layers; }
+ void CameraBase::setLayers(uint32_t layers) { this->_layers = layers; }
+ bool CameraBase::shouldRenderLayer(uint32_t layer) const { return (this->_layers & layer) > 1; }
+ // -----------
+
+ // RENDER TARGET ----
+ void CameraBase::begin() {
+ if (this->_renderTarget == nullptr) CRITICAL_RAWRBOX("Render target not initialized!");
+ this->_renderTarget->startRecord();
+ }
+
+ void CameraBase::end() {
+ if (this->_renderTarget == nullptr) CRITICAL_RAWRBOX("Render target not initialized!");
+ this->_renderTarget->stopRecord();
+ }
+
+ Diligent::ITextureView* CameraBase::getDepth() const { return this->_renderTarget->getDepth(); }
+ Diligent::ITextureView* CameraBase::getColor(bool rt) const { return rt ? this->_renderTarget->getRT() : this->_renderTarget->getHandle(); }
+
+ rawrbox::TextureRender* CameraBase::getRenderTarget() const { return this->_renderTarget.get(); }
+ // ----------------
+
void CameraBase::updateBuffer() {
- if (this->_uniforms == nullptr) CRITICAL_RAWRBOX("Buffer not initialized! Did you call initialize?");
+ if (uniforms == nullptr) CRITICAL_RAWRBOX("Buffer not initialized! Did you call initialize?");
auto view = rawrbox::Matrix4x4::mtxTranspose(this->getViewMtx());
auto viewInv = rawrbox::Matrix4x4::mtxInverse(this->getViewMtx());
@@ -150,22 +203,12 @@ namespace rawrbox {
data.gPos = this->getPos();
data.gDeltaTime = rawrbox::DELTA_TIME;
- rawrbox::BarrierUtils::barrier({{this->_uniforms, Diligent::RESOURCE_STATE_CONSTANT_BUFFER, Diligent::RESOURCE_STATE_COPY_DEST, Diligent::STATE_TRANSITION_FLAG_UPDATE_STATE}});
- rawrbox::RENDERER->context()->UpdateBuffer(this->_uniforms, 0, sizeof(rawrbox::CameraUniforms), &data, Diligent::RESOURCE_STATE_TRANSITION_MODE_VERIFY);
- rawrbox::BarrierUtils::barrier({{this->_uniforms, Diligent::RESOURCE_STATE_COPY_DEST, Diligent::RESOURCE_STATE_CONSTANT_BUFFER, Diligent::STATE_TRANSITION_FLAG_UPDATE_STATE}});
+ rawrbox::BarrierUtils::barrier({{uniforms, Diligent::RESOURCE_STATE_CONSTANT_BUFFER, Diligent::RESOURCE_STATE_COPY_DEST, Diligent::STATE_TRANSITION_FLAG_UPDATE_STATE}});
+ rawrbox::RENDERER->context()->UpdateBuffer(uniforms, 0, sizeof(rawrbox::CameraUniforms), &data, Diligent::RESOURCE_STATE_TRANSITION_MODE_VERIFY);
+ rawrbox::BarrierUtils::barrier({{uniforms, Diligent::RESOURCE_STATE_COPY_DEST, Diligent::RESOURCE_STATE_CONSTANT_BUFFER, Diligent::STATE_TRANSITION_FLAG_UPDATE_STATE}});
}
void CameraBase::update() {}
-
- rawrbox::Vector3f CameraBase::worldToScreen(const rawrbox::Vector3f& /*pos*/) const {
- CRITICAL_RAWRBOX("Not implemented");
- }
-
- rawrbox::Vector3f CameraBase::screenToWorld(const rawrbox::Vector2f& /*screen_pos*/, const rawrbox::Vector3f& /*origin*/) const {
- CRITICAL_RAWRBOX("Not implemented");
- }
-
- Diligent::IBuffer* CameraBase::uniforms() const { return this->_uniforms; }
- Diligent::IBuffer* CameraBase::staticUniforms() const { return this->_staticUniforms; }
// ----------------
+
} // namespace rawrbox
diff --git a/rawrbox.render/src/cameras/perspective.cpp b/rawrbox.render/src/cameras/perspective.cpp
index cd3bbe04..ca708dc5 100644
--- a/rawrbox.render/src/cameras/perspective.cpp
+++ b/rawrbox.render/src/cameras/perspective.cpp
@@ -4,11 +4,11 @@
namespace rawrbox {
// NOLINTBEGIN(clang-analyzer-optin.cplusplus.VirtualCall)
- CameraPerspective::CameraPerspective(const rawrbox::Vector2u& winSize, float FOV, float near, float far) : _winSize(winSize), _FOV(FOV) {
+ CameraPerspective::CameraPerspective(const rawrbox::Vector2u& renderSize, float FOV, float near, float far, bool depth) : rawrbox::CameraBase(renderSize, depth), _FOV(FOV) {
this->_z_near = near;
this->_z_far = far;
- this->_projection = rawrbox::Matrix4x4::mtxProj(FOV, static_cast(winSize.x) / static_cast(winSize.y), this->_z_near, this->_z_far);
+ this->_projection = rawrbox::Matrix4x4::mtxProj(FOV, static_cast(renderSize.x) / static_cast(renderSize.y), this->_z_near, this->_z_far);
this->updateMtx();
}
// NOLINTEND(clang-analyzer-optin.cplusplus.VirtualCall)
@@ -23,18 +23,19 @@ namespace rawrbox {
}
rawrbox::Vector3f CameraPerspective::worldToScreen(const rawrbox::Vector3f& pos) const {
- return rawrbox::Matrix4x4::mtxProject(pos, this->_view, this->_projection, {0, 0, this->_winSize.x, this->_winSize.y});
+ const auto& size = this->_renderTarget->getSize();
+ return rawrbox::Matrix4x4::mtxProject(pos, this->_view, this->_projection, {0, 0, size.x, size.y});
}
rawrbox::Vector3f CameraPerspective::screenToWorld(const rawrbox::Vector2f& screenPos, const rawrbox::Vector3f& origin) const {
- rawrbox::Vector3f plane_normal = {0, 1, 0};
+ static constexpr rawrbox::Vector3f plane_normal = {0, 1, 0};
// get our pos and force aim downwards, the getForward() seems to behave odd when aiming full down
- auto campos = this->getPos();
+ const auto& campos = this->getPos();
+ const auto& size = this->_renderTarget->getSize();
rawrbox::Matrix4x4 viewproj_inv = this->getViewProjMtx().inverse();
- auto winPos = this->_winSize.cast();
-
+ auto winPos = size.cast();
float screenx_clip = 2.F * (screenPos.x / winPos.x) - 1.F;
float screeny_clip = 1.F - 2.F * (screenPos.y) / winPos.y;
diff --git a/rawrbox.render/src/plugins/base.cpp b/rawrbox.render/src/plugins/base.cpp
index fb48831f..3983b5dd 100644
--- a/rawrbox.render/src/plugins/base.cpp
+++ b/rawrbox.render/src/plugins/base.cpp
@@ -17,8 +17,8 @@ namespace rawrbox {
void RenderPlugin::resize(const rawrbox::Vector2u& /*renderSize*/) {}
void RenderPlugin::upload() {}
- void RenderPlugin::preRender() {}
- void RenderPlugin::postRender(rawrbox::TextureRender& /*renderTarget*/) {}
+ void RenderPlugin::preRender(const rawrbox::CameraBase& /*camera*/) {}
+ void RenderPlugin::postRender(const rawrbox::CameraBase& /*camera*/) {}
void RenderPlugin::update() {}
} // namespace rawrbox
diff --git a/rawrbox.render/src/plugins/clustered.cpp b/rawrbox.render/src/plugins/clustered.cpp
index a17c83b1..1168f58c 100644
--- a/rawrbox.render/src/plugins/clustered.cpp
+++ b/rawrbox.render/src/plugins/clustered.cpp
@@ -61,11 +61,31 @@ namespace rawrbox {
this->_dispatch.ThreadGroupCountY = rawrbox::MathUtils::divideRound(CLUSTERS_Y, RB_RENDER_CLUSTERS_Y_THREADS);
// ----------
+ // Re-build clusters ---
+ this->_oldProj = {};
// --------------------------
- this->_oldProj = {}; // Re-build clusters
}
void ClusteredPlugin::upload() {
+ if (this->_signature == nullptr) CRITICAL_RAWRBOX("Signature not initialized, did you call 'initialize'?");
+ if (rawrbox::MAIN_CAMERA == nullptr) CRITICAL_RAWRBOX("Main camera not initialized");
+
+ // Compute bind ---
+ this->_signature->GetStaticVariableByName(Diligent::SHADER_TYPE_COMPUTE, "Camera")->Set(rawrbox::CameraBase::uniforms);
+ this->_signature->GetStaticVariableByName(Diligent::SHADER_TYPE_COMPUTE, "SCamera")->Set(rawrbox::CameraBase::staticUniforms);
+
+ this->_signature->GetStaticVariableByName(Diligent::SHADER_TYPE_COMPUTE, "Clusters")->Set(this->getClustersBuffer(false));
+ this->_signature->GetStaticVariableByName(Diligent::SHADER_TYPE_COMPUTE, "ClusterDataGrid")->Set(this->getDataGridBuffer(false));
+
+ this->_signature->GetStaticVariableByName(Diligent::SHADER_TYPE_COMPUTE, "Lights")->Set(rawrbox::LIGHTS::getBuffer());
+ this->_signature->GetStaticVariableByName(Diligent::SHADER_TYPE_COMPUTE, "LightConstants")->Set(rawrbox::LIGHTS::uniforms);
+
+ this->_signature->GetStaticVariableByName(Diligent::SHADER_TYPE_COMPUTE, "Decals")->Set(rawrbox::DECALS::getBuffer());
+ this->_signature->GetStaticVariableByName(Diligent::SHADER_TYPE_COMPUTE, "DecalsConstants")->Set(rawrbox::DECALS::uniforms);
+
+ this->_signature->CreateShaderResourceBinding(&this->_signatureBind, true);
+ // ----------------
+
this->buildPipelines();
}
@@ -91,13 +111,12 @@ namespace rawrbox {
sig.GetStaticVariableByName(Diligent::SHADER_TYPE_PIXEL, "DecalsConstants")->Set(rawrbox::DECALS::uniforms);
}
- void ClusteredPlugin::preRender() {
+ void ClusteredPlugin::preRender(const rawrbox::CameraBase& camera) {
auto* renderer = rawrbox::RENDERER;
- auto* camera = renderer->camera();
- auto* context = renderer->context();
-
if (renderer == nullptr) CRITICAL_RAWRBOX("Renderer not initialized!");
- if (camera == nullptr) CRITICAL_RAWRBOX("Camera not initialized!");
+
+ auto* context = renderer->context();
+ if (context == nullptr) CRITICAL_RAWRBOX("Context not initialized!");
if (this->_clusterBuildingComputeProgram == nullptr || this->_cullingComputeProgram == nullptr || this->_cullingResetProgram == nullptr) CRITICAL_RAWRBOX("Compute pipelines not initialized, did you call 'initialize'");
@@ -118,7 +137,7 @@ namespace rawrbox {
// -----------------------
// Rebuild clusters ---
- auto proj = camera->getProjMtx();
+ auto proj = camera.getProjMtx();
if (this->_oldProj != proj) {
this->_oldProj = proj;
@@ -194,7 +213,6 @@ namespace rawrbox {
void ClusteredPlugin::buildSignatures() {
if (this->_signature != nullptr || this->_signatureBind != nullptr) CRITICAL_RAWRBOX("Signatures already bound!");
- if (rawrbox::MAIN_CAMERA == nullptr) CRITICAL_RAWRBOX("Clustered plugin requires at least one camera!");
std::vector resources = {
// CAMERA ------
@@ -231,26 +249,10 @@ namespace rawrbox {
rawrbox::RENDERER->device()->CreatePipelineResourceSignature(PRSDesc, &this->_signature);
// ----------------------
-
- // Compute bind ---
- this->_signature->GetStaticVariableByName(Diligent::SHADER_TYPE_COMPUTE, "Camera")->Set(rawrbox::MAIN_CAMERA->uniforms());
- this->_signature->GetStaticVariableByName(Diligent::SHADER_TYPE_COMPUTE, "SCamera")->Set(rawrbox::MAIN_CAMERA->staticUniforms());
-
- this->_signature->GetStaticVariableByName(Diligent::SHADER_TYPE_COMPUTE, "Clusters")->Set(this->getClustersBuffer(false));
- this->_signature->GetStaticVariableByName(Diligent::SHADER_TYPE_COMPUTE, "ClusterDataGrid")->Set(this->getDataGridBuffer(false));
-
- this->_signature->GetStaticVariableByName(Diligent::SHADER_TYPE_COMPUTE, "Lights")->Set(rawrbox::LIGHTS::getBuffer());
- this->_signature->GetStaticVariableByName(Diligent::SHADER_TYPE_COMPUTE, "LightConstants")->Set(rawrbox::LIGHTS::uniforms);
-
- this->_signature->GetStaticVariableByName(Diligent::SHADER_TYPE_COMPUTE, "Decals")->Set(rawrbox::DECALS::getBuffer());
- this->_signature->GetStaticVariableByName(Diligent::SHADER_TYPE_COMPUTE, "DecalsConstants")->Set(rawrbox::DECALS::uniforms);
-
- this->_signature->CreateShaderResourceBinding(&this->_signatureBind, true);
- // ----------------
}
void ClusteredPlugin::buildPipelines() {
- if (rawrbox::MAIN_CAMERA == nullptr) CRITICAL_RAWRBOX("Clustered plugin requires at least one camera!");
+ if (this->_signature == nullptr) CRITICAL_RAWRBOX("Signature not initialized, did you call 'initialize'");
rawrbox::PipeComputeSettings settings;
settings.macros = this->getClusterMacros();
diff --git a/rawrbox.render/src/plugins/particle_engine.cpp b/rawrbox.render/src/plugins/particle_engine.cpp
index b0173462..b2d94610 100644
--- a/rawrbox.render/src/plugins/particle_engine.cpp
+++ b/rawrbox.render/src/plugins/particle_engine.cpp
@@ -45,15 +45,6 @@ namespace rawrbox {
rawrbox::RENDERER->device()->CreatePipelineResourceSignature(PRSDesc, &this->_signature);
// ----------------------
- // Compute bind ---
- this->_signature->GetStaticVariableByName(Diligent::SHADER_TYPE_COMPUTE, "Camera")->Set(rawrbox::MAIN_CAMERA->uniforms());
- this->_signature->GetStaticVariableByName(Diligent::SHADER_TYPE_COMPUTE, "SCamera")->Set(rawrbox::MAIN_CAMERA->staticUniforms());
-
- this->_signature->GetStaticVariableByName(Diligent::SHADER_TYPE_COMPUTE, "EmitterConstants")->Set(this->_uniforms);
-
- this->_signature->CreateShaderResourceBinding(&this->_signatureBind, true);
- // ----------------
-
// Dynamic signature ---
PRSDesc.Name = "RawrBox::SIGNATURE::Particles::Dynamic";
PRSDesc.BindingIndex = 1;
@@ -66,7 +57,6 @@ namespace rawrbox {
PRSDesc.NumResources = static_cast(resources.size());
rawrbox::RENDERER->device()->CreatePipelineResourceSignature(PRSDesc, &this->_dynamicSignature);
- this->_dynamicSignature->CreateShaderResourceBinding(&this->_dynamicSignatureBind, true);
// ----------------
}
@@ -98,6 +88,18 @@ namespace rawrbox {
}
void ParticleEnginePlugin::upload() {
+ if (this->_signature == nullptr || this->_signatureBind == nullptr || this->_uniforms == nullptr) CRITICAL_RAWRBOX("Plugin not initialized!");
+
+ // Compute bind ---
+ this->_signature->GetStaticVariableByName(Diligent::SHADER_TYPE_COMPUTE, "Camera")->Set(rawrbox::CameraBase::uniforms);
+ this->_signature->GetStaticVariableByName(Diligent::SHADER_TYPE_COMPUTE, "SCamera")->Set(rawrbox::CameraBase::staticUniforms);
+
+ this->_signature->GetStaticVariableByName(Diligent::SHADER_TYPE_COMPUTE, "EmitterConstants")->Set(this->_uniforms);
+
+ this->_signature->CreateShaderResourceBinding(&this->_signatureBind, true);
+ this->_dynamicSignature->CreateShaderResourceBinding(&this->_dynamicSignatureBind, true);
+ // ----------------
+
this->createPipelines();
}
@@ -109,7 +111,7 @@ namespace rawrbox {
sig.GetStaticVariableByName(Diligent::SHADER_TYPE_GEOMETRY, "EmitterConstants")->Set(this->_uniforms);
}
- void ParticleEnginePlugin::preRender() {
+ void ParticleEnginePlugin::preRender(const rawrbox::CameraBase& /*camera*/) {
for (auto* emitter : this->_registeredEmitters) {
if (emitter == nullptr || !emitter->isEnabled()) continue;
diff --git a/rawrbox.render/src/plugins/post_process.cpp b/rawrbox.render/src/plugins/post_process.cpp
index 7b7e349a..df5811f9 100644
--- a/rawrbox.render/src/plugins/post_process.cpp
+++ b/rawrbox.render/src/plugins/post_process.cpp
@@ -1,5 +1,6 @@
#include
#include
+#include
namespace rawrbox {
PostProcessPlugin::~PostProcessPlugin() {
@@ -8,6 +9,8 @@ namespace rawrbox {
}
void PostProcessPlugin::initialize(const rawrbox::Vector2u& /*size*/) {
+ if (this->_buffer != nullptr) CRITICAL_RAWRBOX("Plugin already initialized!");
+
Diligent::BufferDesc BuffPixelDesc;
BuffPixelDesc.Name = "rawrbox::PostProcess";
BuffPixelDesc.Usage = Diligent::USAGE_DYNAMIC;
@@ -23,8 +26,8 @@ namespace rawrbox {
}
void PostProcessPlugin::upload() {
- for (const auto& _postProcess : this->_postProcesses) {
- _postProcess->init();
+ for (const auto& postProcess : this->_postProcesses) {
+ postProcess->init();
}
}
@@ -36,14 +39,20 @@ namespace rawrbox {
sig.GetStaticVariableByName(Diligent::SHADER_TYPE_PIXEL, "PostProcessConstants")->Set(this->_buffer);
}
- void PostProcessPlugin::postRender(rawrbox::TextureRender& renderTexture) {
+ void PostProcessPlugin::postRender(const rawrbox::CameraBase& camera) {
+ if (&camera != rawrbox::MAIN_CAMERA) return; // Only apply on the main camera
+
+ auto* renderTarget = camera.getRenderTarget();
+
+ // Apply post-processing ---
for (auto& process : this->_postProcesses) {
if (!process->isEnabled()) continue;
- renderTexture.startRecord(false, 1);
- process->applyEffect(renderTexture);
- renderTexture.stopRecord();
+ renderTarget->startRecord(false, 1);
+ process->applyEffect(*renderTarget);
+ renderTarget->stopRecord();
}
+ // ----------
}
// Post utils ----
diff --git a/rawrbox.render/src/renderer.cpp b/rawrbox.render/src/renderer.cpp
index c9bf3c9a..e755ef04 100644
--- a/rawrbox.render/src/renderer.cpp
+++ b/rawrbox.render/src/renderer.cpp
@@ -41,7 +41,6 @@
namespace rawrbox {
RendererBase::RendererBase(Diligent::RENDER_DEVICE_TYPE type, Diligent::NativeWindow window, const rawrbox::Vector2u& size, const rawrbox::Vector2u& monitorSize, const rawrbox::Colorf& clearColor) : _clearColor(clearColor), _size(size), _monitorSize(monitorSize), _window(window), _type(type) {}
RendererBase::~RendererBase() {
- this->_render.reset();
this->_stencil.reset();
this->_logger.reset();
this->_GPUBlit.reset();
@@ -241,11 +240,6 @@ namespace rawrbox {
// --------------
// ----------------------
- // Setup camera -----
- if (this->_camera == nullptr) CRITICAL_RAWRBOX("No camera found!");
- this->_camera->initialize();
- // ------------------
-
// Init plugins ---
for (auto& plugin : this->_renderPlugins) {
if (plugin.second == nullptr) continue;
@@ -258,6 +252,19 @@ namespace rawrbox {
rawrbox::BindlessManager::init();
// -----------------
+ // Init cameras ---
+ this->setActiveCamera(this->_cameras.front().get());
+ for (auto& camera : this->_cameras) {
+ camera->initialize();
+ }
+
+ rawrbox::MAIN_CAMERA->upload();
+ // -----------------
+
+ // Bind signatures ---
+ rawrbox::BindlessManager::bindSignatures();
+ // -------
+
// Init default textures ---
this->_logger->info("Initializing default textures");
@@ -335,15 +342,6 @@ namespace rawrbox {
this->_stencil->upload();
// ------------------
- // Setup renderer --
- this->_render = std::make_unique(this->_size); // TODO: RESCALE
- this->_render->upload(Diligent::TEX_FORMAT_RGBA8_UNORM);
-
- // GPU PICKING TEXTURE
- auto idIndex = this->_render->addTexture(Diligent::TEX_FORMAT_RGBA8_UNORM);
- this->_render->addView(idIndex, Diligent::TEXTURE_VIEW_RENDER_TARGET);
- // --------
-
this->playIntro();
this->_initialized = true;
}
@@ -370,7 +368,7 @@ namespace rawrbox {
const std::map>& RendererBase::getPlugins() const { return this->_renderPlugins; }
// -----------------------------------
- void RendererBase::setDrawCall(std::function call) { this->_drawCall = std::move(call); }
+ void RendererBase::setDrawCall(std::function call) { this->_drawCall = std::move(call); }
void RendererBase::update() {
if (this->_currentIntro != nullptr) {
@@ -389,7 +387,12 @@ namespace rawrbox {
return;
}
} else {
- if (this->_camera != nullptr) this->_camera->update();
+ // Update cameras ---
+ for (auto& camera : this->_cameras) {
+ if (!camera->isEnabled()) continue;
+ camera->update();
+ }
+ // -----------------------
// Update plugins --
for (auto& plugin : this->_renderPlugins) {
@@ -403,6 +406,7 @@ namespace rawrbox {
void RendererBase::render() {
if (this->_swapChain == nullptr || this->_context == nullptr || this->_device == nullptr) CRITICAL_RAWRBOX("Failed to bind swapChain / context / device! Did you call 'init' ?");
if (this->_drawCall == nullptr) CRITICAL_RAWRBOX("Missing draw call! Did you call 'setDrawCall' ?");
+ if (rawrbox::MAIN_CAMERA == nullptr || this->_cameras.empty()) CRITICAL_RAWRBOX("Missing cameras! Did you call 'createCamera' ?");
// Clear backbuffer ----
this->clear();
@@ -412,70 +416,46 @@ namespace rawrbox {
rawrbox::BindlessManager::update();
// --------------------
- // Update camera buffer --
- this->_camera->updateBuffer();
- // -----------
+ for (auto& camera : this->_cameras) {
+ if (!camera->isEnabled()) continue;
- // Perform pre-render --
- for (auto& plugin : this->_renderPlugins) {
- if (plugin.second == nullptr || !plugin.second->isEnabled()) continue;
-#ifdef _DEBUG
- // this->_context->BeginDebugGroup(plugin.first.c_str());
-#endif
- plugin.second->preRender();
-#ifdef _DEBUG
- // this->_context->EndDebugGroup();
-#endif
- }
- // -----------------------
+ // Update camera buffer --
+ camera->updateBuffer();
+ // -----------
- // Commit graphics signature --
- this->_context->CommitShaderResources(rawrbox::BindlessManager::signatureBind, Diligent::RESOURCE_STATE_TRANSITION_MODE_VERIFY);
- // -----------------------
+ // Perform pre-render --
+ for (auto& plugin : this->_renderPlugins) {
+ if (plugin.second == nullptr || !plugin.second->isEnabled()) continue;
+ plugin.second->preRender(*camera);
+ }
+ // -----------------------
- // Perform world --
-#ifdef _DEBUG
- // this->_context->BeginDebugGroup("OPAQUE");
- // this->beginQuery("OPAQUE");
-#endif
- this->_render->startRecord();
- this->_drawCall(rawrbox::DrawPass::PASS_WORLD);
- this->_render->stopRecord();
-#ifdef _DEBUG
- // this->endQuery("OPAQUE");
- // this->_context->EndDebugGroup();
-#endif
- // -----------------
+ // Commit graphics signature --
+ this->_context->CommitShaderResources(rawrbox::BindlessManager::signatureBind, Diligent::RESOURCE_STATE_TRANSITION_MODE_VERIFY);
+ // -----------------------
- // Perform post-render --
- for (auto& plugin : this->_renderPlugins) {
- if (plugin.second == nullptr || !plugin.second->isEnabled()) continue;
-#ifdef _DEBUG
- // this->_context->BeginDebugGroup(plugin.first.c_str());
-#endif
- plugin.second->postRender(*this->_render);
-#ifdef _DEBUG
- // this->_context->EndDebugGroup();
-#endif
+ // Perform world --
+ camera->begin();
+ this->_drawCall(*camera, rawrbox::DrawPass::PASS_WORLD);
+ camera->end();
+ // -----------------
+
+ // Perform post-render --
+ for (auto& plugin : this->_renderPlugins) {
+ if (plugin.second == nullptr || !plugin.second->isEnabled()) continue;
+ plugin.second->postRender(*camera);
+ }
+ // -----------------------
}
- // -----------------------
- // Render world ----
- rawrbox::RenderUtils::renderQUAD(*this->_render);
+ // Render main camera ----
+ rawrbox::RenderUtils::renderQUAD(*rawrbox::MAIN_CAMERA->getRenderTarget());
// ------------------
- // Perform overlay --
-#ifdef _DEBUG
- // this->_context->BeginDebugGroup("OVERLAY");
- // this->beginQuery("OVERLAY");
-#endif
- this->_drawCall(rawrbox::DrawPass::PASS_OVERLAY);
+ // Perform overlay, only MAIN camera does it --
+ this->_drawCall(*rawrbox::MAIN_CAMERA, rawrbox::DrawPass::PASS_OVERLAY);
if (this->_stencil != nullptr) this->_stencil->render();
-#ifdef _DEBUG
- // this->endQuery("OVERLAY");
- // this->_context->EndDebugGroup();
-#endif
- // ------------------
+ // ---------------------------------------------
// Submit ---
this->frame();
@@ -522,7 +502,7 @@ namespace rawrbox {
this->_tempRender = this->_drawCall;
// -------------
- this->_drawCall = [this](const rawrbox::DrawPass& pass) {
+ this->_drawCall = [this](const rawrbox::CameraBase& /*camera*/, const rawrbox::DrawPass& pass) {
if (pass != rawrbox::DrawPass::PASS_OVERLAY) return;
auto screenSize = this->_size.cast();
@@ -668,22 +648,15 @@ namespace rawrbox {
// ----------------
// Utils ----
- void RendererBase::setMainCamera(rawrbox::CameraBase* camera) const { rawrbox::MAIN_CAMERA = camera; }
- rawrbox::CameraBase* RendererBase::camera() const { return this->_camera.get(); }
+ void RendererBase::setActiveCamera(rawrbox::CameraBase* camera) const { rawrbox::MAIN_CAMERA = camera; }
+ rawrbox::CameraBase* RendererBase::getActiveCamera() const { return rawrbox::MAIN_CAMERA; }
+
rawrbox::Stencil* RendererBase::stencil() const { return this->_stencil.get(); }
Diligent::IDeviceContext* RendererBase::context() const { return this->_context; }
Diligent::ISwapChain* RendererBase::swapChain() const { return this->_swapChain; }
Diligent::IRenderDevice* RendererBase::device() const { return this->_device; }
- Diligent::ITextureView* RendererBase::getDepth() const {
- return this->_render->getDepth();
- }
-
- Diligent::ITextureView* RendererBase::getColor(bool rt) const {
- return rt ? this->_render->getRT() : this->_render->getHandle();
- }
-
std::filesystem::path RendererBase::getShadersDirectory() const {
return "./assets/shaders";
}
@@ -711,8 +684,8 @@ namespace rawrbox {
void RendererBase::setVSync(bool vsync) { this->_vsync = vsync; }
void RendererBase::gpuPick(const rawrbox::Vector2i& pos, const std::function& callback) {
- if (this->_render == nullptr) CRITICAL_RAWRBOX("Render target texture not initialized");
- if (callback == nullptr) CRITICAL_RAWRBOX("Render target texture not initialized");
+ if (rawrbox::MAIN_CAMERA == nullptr) CRITICAL_RAWRBOX("Main camera not initialized");
+ if (callback == nullptr) CRITICAL_RAWRBOX("Invalid callback");
auto size = this->_size.cast();
if (pos.x < 0 || pos.y < 0 || pos.x >= size.x || pos.y >= size.y) CRITICAL_RAWRBOX("Outside of window range");
@@ -723,7 +696,7 @@ namespace rawrbox {
MapRegion.MaxX = MapRegion.MinX + RB_RENDER_GPU_PICK_SAMPLE_SIZE;
MapRegion.MaxY = MapRegion.MinY + RB_RENDER_GPU_PICK_SAMPLE_SIZE;
- auto* tex = this->_render->getTexture(1); // GPU pick texture
+ auto* tex = rawrbox::MAIN_CAMERA->getRenderTarget()->getTexture(1); // GPU pick texture
this->_GPUBlit->copy(tex, &MapRegion, [this, callback]() {
this->_GPUBlit->blit(nullptr, [callback](const uint8_t* pixels, const uint64_t stride) {
uint32_t max = 0;
diff --git a/samples/001-stencil/src/game.cpp b/samples/001-stencil/src/game.cpp
index 12a37775..be9750eb 100644
--- a/samples/001-stencil/src/game.cpp
+++ b/samples/001-stencil/src/game.cpp
@@ -38,7 +38,7 @@ namespace stencil {
// Setup renderer
auto* render = window->createRenderer(rawrbox::Color::RGBAHex(0x443355FF));
render->onIntroCompleted = [this]() { this->loadContent(); };
- render->setDrawCall([this](const rawrbox::DrawPass& pass) {
+ render->setDrawCall([this](const rawrbox::CameraBase& /*camera*/, const rawrbox::DrawPass& pass) {
if (pass == rawrbox::DrawPass::PASS_OVERLAY) {
this->drawOverlay();
} else if (pass == rawrbox::DrawPass::PASS_WORLD) {
@@ -48,7 +48,7 @@ namespace stencil {
// ---------------
// Setup camera --
- auto* cam = render->setupCamera(render->getSize());
+ auto* cam = render->createCamera(render->getSize());
cam->setPos({-2.F, 5.F, -3.5F});
cam->setAngle({0.F, rawrbox::MathUtils::toRad(-45), 0.F, 0.F});
// ---------------
diff --git a/samples/002-generated-models/include/model/game.hpp b/samples/002-generated-models/include/model/game.hpp
index 2ef9c512..b8453193 100644
--- a/samples/002-generated-models/include/model/game.hpp
+++ b/samples/002-generated-models/include/model/game.hpp
@@ -21,12 +21,14 @@ namespace model {
bool _ready = false;
bool _bbox = true;
+ // Engine setup ---
void setupGLFW() override;
void init() override;
void onThreadShutdown(rawrbox::ENGINE_THREADS thread) override;
void pollEvents() override;
void update() override;
void draw() override;
+ // ----------------
void createModels();
void createSpline();
diff --git a/samples/002-generated-models/src/game.cpp b/samples/002-generated-models/src/game.cpp
index 06a2bfce..97e5277e 100644
--- a/samples/002-generated-models/src/game.cpp
+++ b/samples/002-generated-models/src/game.cpp
@@ -35,7 +35,7 @@ namespace model {
// Setup renderer
auto* render = window->createRenderer();
render->onIntroCompleted = [this]() { this->loadContent(); };
- render->setDrawCall([this](const rawrbox::DrawPass& pass) {
+ render->setDrawCall([this](const rawrbox::CameraBase& /*camera*/, const rawrbox::DrawPass& pass) {
if (pass == rawrbox::DrawPass::PASS_WORLD) {
this->drawWorld();
} else {
@@ -45,7 +45,7 @@ namespace model {
// ---------------
// Setup camera
- auto* cam = render->setupCamera(*window);
+ auto* cam = render->createCamera(*window);
cam->setPos({0.F, 6.F, -6.F});
cam->setAngle({0.F, rawrbox::MathUtils::toRad(-55), 0.F, 0.F});
cam->onMovementStart = []() { fmt::print("Camera start\n"); };
diff --git a/samples/003-light/src/game.cpp b/samples/003-light/src/game.cpp
index b07da3fb..506e73f1 100644
--- a/samples/003-light/src/game.cpp
+++ b/samples/003-light/src/game.cpp
@@ -38,7 +38,7 @@ namespace light {
auto* render = window->createRenderer();
render->addPlugin();
render->onIntroCompleted = [this]() { this->loadContent(); };
- render->setDrawCall([this](const rawrbox::DrawPass& pass) {
+ render->setDrawCall([this](const rawrbox::CameraBase& /*camera*/, const rawrbox::DrawPass& pass) {
if (pass == rawrbox::DrawPass::PASS_WORLD) {
this->drawWorld();
} else {
@@ -48,7 +48,7 @@ namespace light {
// ---------------
// Setup camera
- auto* cam = render->setupCamera(*window);
+ auto* cam = render->createCamera(*window);
cam->setPos({0.F, 5.F, -5.F});
cam->setAngle({0.F, rawrbox::MathUtils::toRad(-45), 0.F, 0.F});
// --------------
diff --git a/samples/004-instancing/src/game.cpp b/samples/004-instancing/src/game.cpp
index dc1c2d29..4f41b074 100644
--- a/samples/004-instancing/src/game.cpp
+++ b/samples/004-instancing/src/game.cpp
@@ -39,14 +39,14 @@ namespace instance_test {
// Setup renderer
auto* render = window->createRenderer();
render->onIntroCompleted = [this]() { this->loadContent(); };
- render->setDrawCall([this](const rawrbox::DrawPass& pass) {
+ render->setDrawCall([this](const rawrbox::CameraBase& /*camera*/, const rawrbox::DrawPass& pass) {
if (pass != rawrbox::DrawPass::PASS_WORLD) return;
this->drawWorld();
});
// ---------------
// Setup camera
- auto* cam = render->setupCamera(*window);
+ auto* cam = render->createCamera(*window);
cam->setPos({0.F, 5.F, -5.F});
cam->setAngle({0.F, rawrbox::MathUtils::toRad(-45), 0.F, 0.F});
// --------------
diff --git a/samples/005-post-process/src/game.cpp b/samples/005-post-process/src/game.cpp
index a864bed9..b0582516 100644
--- a/samples/005-post-process/src/game.cpp
+++ b/samples/005-post-process/src/game.cpp
@@ -48,7 +48,7 @@ namespace post_process {
this->_noise = postProcess->add(0.1F);
// -----------------------
- render->setDrawCall([this](const rawrbox::DrawPass& pass) {
+ render->setDrawCall([this](const rawrbox::CameraBase& /*camera*/, const rawrbox::DrawPass& pass) {
if (pass == rawrbox::DrawPass::PASS_WORLD) {
this->drawWorld();
} else {
@@ -61,7 +61,7 @@ namespace post_process {
// ---------------
// Setup camera
- auto* cam = render->setupCamera(*window);
+ auto* cam = render->createCamera(*window);
cam->setPos({0.F, 5.F, -5.F});
cam->setAngle({0.F, rawrbox::MathUtils::toRad(-45), 0.F, 0.F});
// --------------
diff --git a/samples/006-decals/src/game.cpp b/samples/006-decals/src/game.cpp
index 66a8c760..93a2070d 100644
--- a/samples/006-decals/src/game.cpp
+++ b/samples/006-decals/src/game.cpp
@@ -41,7 +41,7 @@ namespace decal_test {
auto* render = window->createRenderer();
render->addPlugin();
render->onIntroCompleted = [this]() { this->loadContent(); };
- render->setDrawCall([this](const rawrbox::DrawPass& pass) {
+ render->setDrawCall([this](const rawrbox::CameraBase& /*camera*/, const rawrbox::DrawPass& pass) {
if (pass == rawrbox::DrawPass::PASS_WORLD) {
this->drawWorld();
} else {
@@ -51,7 +51,7 @@ namespace decal_test {
// ---------------
// Setup camera
- auto* cam = render->setupCamera(*window);
+ auto* cam = render->createCamera(*window);
cam->setPos({0.F, 5.F, -5.F});
cam->setAngle({0.F, rawrbox::MathUtils::toRad(-45), 0.F, 0.F});
// --------------
diff --git a/samples/007-particle-system/src/game.cpp b/samples/007-particle-system/src/game.cpp
index 83065e84..bef48691 100644
--- a/samples/007-particle-system/src/game.cpp
+++ b/samples/007-particle-system/src/game.cpp
@@ -35,14 +35,14 @@ namespace particle_system {
auto* render = window->createRenderer();
render->addPlugin();
render->onIntroCompleted = [this]() { this->loadContent(); };
- render->setDrawCall([this](const rawrbox::DrawPass& pass) {
+ render->setDrawCall([this](const rawrbox::CameraBase& /*camera*/, const rawrbox::DrawPass& pass) {
if (pass != rawrbox::DrawPass::PASS_WORLD) return;
this->drawWorld();
});
// ---------------
// Setup camera
- auto* cam = render->setupCamera(*window);
+ auto* cam = render->createCamera(*window);
cam->setPos({0.F, 5.F, -5.F});
cam->setAngle({0.F, rawrbox::MathUtils::toRad(-45), 0.F, 0.F});
// --------------
diff --git a/samples/008-ui/src/game.cpp b/samples/008-ui/src/game.cpp
index 784207c9..e28350e9 100644
--- a/samples/008-ui/src/game.cpp
+++ b/samples/008-ui/src/game.cpp
@@ -50,14 +50,14 @@ namespace ui_test {
// Setup renderer
auto* render = window->createRenderer(rawrbox::Color::RGBAHex(0x443355FF));
render->onIntroCompleted = [this]() { this->loadContent(); };
- render->setDrawCall([this](const rawrbox::DrawPass& pass) {
+ render->setDrawCall([this](const rawrbox::CameraBase& /*camera*/, const rawrbox::DrawPass& pass) {
if (pass != rawrbox::DrawPass::PASS_OVERLAY) return;
this->_ROOT_UI->render();
});
// ---------------
// Setup camera --
- auto* cam = render->setupCamera(render->getSize());
+ auto* cam = render->createCamera(render->getSize());
cam->setPos({-2.F, 5.F, -3.5F});
cam->setAngle({0.F, rawrbox::MathUtils::toRad(-45), 0.F, 0.F});
// ---------------
diff --git a/samples/009-gltf/src/game.cpp b/samples/009-gltf/src/game.cpp
index 1d3b70cd..68bb81d6 100644
--- a/samples/009-gltf/src/game.cpp
+++ b/samples/009-gltf/src/game.cpp
@@ -36,14 +36,14 @@ namespace gltf {
auto* render = window->createRenderer();
render->onIntroCompleted = [this]() { this->loadContent(); };
render->addPlugin();
- render->setDrawCall([this](const rawrbox::DrawPass& pass) {
+ render->setDrawCall([this](const rawrbox::CameraBase& /*camera*/, const rawrbox::DrawPass& pass) {
if (pass != rawrbox::DrawPass::PASS_WORLD) return;
this->drawWorld();
});
// ---------------
// Setup camera
- auto* cam = render->setupCamera(*window);
+ auto* cam = render->createCamera(*window);
cam->setPos({0.F, 5.F, -5.F});
cam->setAngle({0.F, rawrbox::MathUtils::toRad(-45), 0.F, 0.F});
// --------------
diff --git a/samples/010-bass-audio/src/game.cpp b/samples/010-bass-audio/src/game.cpp
index 1fb6e03c..fa20f8c3 100644
--- a/samples/010-bass-audio/src/game.cpp
+++ b/samples/010-bass-audio/src/game.cpp
@@ -34,14 +34,14 @@ namespace bass_test {
// Setup renderer
auto* render = window->createRenderer();
render->onIntroCompleted = [this]() { this->loadContent(); };
- render->setDrawCall([this](const rawrbox::DrawPass& pass) {
+ render->setDrawCall([this](const rawrbox::CameraBase& /*camera*/, const rawrbox::DrawPass& pass) {
if (pass != rawrbox::DrawPass::PASS_WORLD) return;
this->drawWorld();
});
// ---------------
// Setup camera
- auto* cam = render->setupCamera(*window);
+ auto* cam = render->createCamera(*window);
cam->setPos({0.F, 5.F, -5.F});
cam->setAngle({0.F, rawrbox::MathUtils::toRad(-45), 0.F, 0.F});
// --------------
diff --git a/samples/011-physics-3D/src/game.cpp b/samples/011-physics-3D/src/game.cpp
index b1bc7750..28fbd2d0 100644
--- a/samples/011-physics-3D/src/game.cpp
+++ b/samples/011-physics-3D/src/game.cpp
@@ -34,7 +34,7 @@ namespace phys_3d_test {
// Setup renderer
auto* render = window->createRenderer();
render->onIntroCompleted = [this]() { this->loadContent(); };
- render->setDrawCall([this](const rawrbox::DrawPass& pass) {
+ render->setDrawCall([this](const rawrbox::CameraBase& /*camera*/, const rawrbox::DrawPass& pass) {
if (pass == rawrbox::DrawPass::PASS_WORLD) {
this->drawWorld();
} else {
@@ -44,7 +44,7 @@ namespace phys_3d_test {
// ---------------
// Setup camera
- auto* cam = render->setupCamera(*window);
+ auto* cam = render->createCamera(*window);
cam->setPos({0.F, 5.F, -5.F});
cam->setAngle({0.F, rawrbox::MathUtils::toRad(-45), 0.F, 0.F});
// --------------
diff --git a/samples/012-physics-2D/src/game.cpp b/samples/012-physics-2D/src/game.cpp
index efa96727..6fcd661b 100644
--- a/samples/012-physics-2D/src/game.cpp
+++ b/samples/012-physics-2D/src/game.cpp
@@ -35,7 +35,7 @@ namespace phys_2d_test {
// Setup renderer
auto* render = window->createRenderer();
render->onIntroCompleted = [this]() { this->loadContent(); };
- render->setDrawCall([this](const rawrbox::DrawPass& pass) {
+ render->setDrawCall([this](const rawrbox::CameraBase& /*camera*/, const rawrbox::DrawPass& pass) {
if (pass == rawrbox::DrawPass::PASS_WORLD) {
this->drawWorld();
} else {
@@ -45,7 +45,7 @@ namespace phys_2d_test {
// ---------------
// Setup camera
- auto* cam = render->setupCamera(*window);
+ auto* cam = render->createCamera(*window);
cam->setPos({0.F, 5.F, -5.F});
cam->setAngle({0.F, 0.F, 0.F, 0.F});
// --------------
diff --git a/samples/013-webm/src/game.cpp b/samples/013-webm/src/game.cpp
index 70df5a7c..5841b3a6 100644
--- a/samples/013-webm/src/game.cpp
+++ b/samples/013-webm/src/game.cpp
@@ -35,14 +35,14 @@ namespace webm_test {
// Setup renderer
auto* render = window->createRenderer();
render->onIntroCompleted = [this]() { this->loadContent(); };
- render->setDrawCall([this](const rawrbox::DrawPass& pass) {
+ render->setDrawCall([this](const rawrbox::CameraBase& /*camera*/, const rawrbox::DrawPass& pass) {
if (pass != rawrbox::DrawPass::PASS_WORLD) return;
this->drawWorld();
});
// ---------------
// Setup camera
- auto* cam = render->setupCamera(*window);
+ auto* cam = render->createCamera(*window);
cam->setPos({0.F, 5.F, -10.F});
cam->setAngle({0.F, 0.F, 0.F, 0.F});
// --------------
diff --git a/samples/014-scripting/src/game.cpp b/samples/014-scripting/src/game.cpp
index c47c87e9..e3115726 100644
--- a/samples/014-scripting/src/game.cpp
+++ b/samples/014-scripting/src/game.cpp
@@ -51,7 +51,7 @@ namespace scripting_test {
// Setup renderer
auto* render = window->createRenderer();
render->onIntroCompleted = [this]() { this->loadContent(); };
- render->setDrawCall([this](const rawrbox::DrawPass& pass) {
+ render->setDrawCall([this](const rawrbox::CameraBase& /*camera*/, const rawrbox::DrawPass& pass) {
if (pass == rawrbox::DrawPass::PASS_WORLD) {
this->drawWorld();
} else {
@@ -61,7 +61,7 @@ namespace scripting_test {
// ---------------
// Setup camera
- auto* cam = render->setupCamera(*window);
+ auto* cam = render->createCamera(*window);
cam->setPos({0.F, 5.F, -5.F});
cam->setAngle({0.F, rawrbox::MathUtils::toRad(-45), 0.F, 0.F});
// --------------
diff --git a/samples/015-gpu-picking/src/game.cpp b/samples/015-gpu-picking/src/game.cpp
index 589b2060..c29c70a1 100644
--- a/samples/015-gpu-picking/src/game.cpp
+++ b/samples/015-gpu-picking/src/game.cpp
@@ -31,14 +31,14 @@ namespace gpu {
// Setup renderer
auto* render = window->createRenderer();
render->onIntroCompleted = [this]() { this->loadContent(); };
- render->setDrawCall([this](const rawrbox::DrawPass& pass) {
+ render->setDrawCall([this](const rawrbox::CameraBase& /*camera*/, const rawrbox::DrawPass& pass) {
if (pass != rawrbox::DrawPass::PASS_WORLD) return;
this->drawWorld();
});
// ---------------
// Setup camera
- auto* cam = render->setupCamera(*window);
+ auto* cam = render->createCamera(*window);
cam->setPos({0.F, 5.F, -5.F});
cam->setAngle({0.F, rawrbox::MathUtils::toRad(-45), 0.F, 0.F});
// --------------
diff --git a/samples/016-steamworks/src/game.cpp b/samples/016-steamworks/src/game.cpp
index c254aca7..73f12856 100644
--- a/samples/016-steamworks/src/game.cpp
+++ b/samples/016-steamworks/src/game.cpp
@@ -33,7 +33,7 @@ namespace steamworks {
// Setup renderer
auto* render = window->createRenderer();
render->onIntroCompleted = [this]() { this->loadContent(); };
- render->setDrawCall([this](const rawrbox::DrawPass& pass) {
+ render->setDrawCall([this](const rawrbox::CameraBase& /*camera*/, const rawrbox::DrawPass& pass) {
if (pass == rawrbox::DrawPass::PASS_OVERLAY) {
this->drawOverlay();
} else {
@@ -43,7 +43,7 @@ namespace steamworks {
// ---------------
// Setup camera
- auto* cam = render->setupCamera(*window);
+ auto* cam = render->createCamera(*window);
cam->setPos({0.F, 5.F, -5.F});
cam->setAngle({0.F, rawrbox::MathUtils::toRad(-45), 0.F, 0.F});
// --------------
diff --git a/samples/017-imgui/src/game.cpp b/samples/017-imgui/src/game.cpp
index 83de2d45..a4f61928 100644
--- a/samples/017-imgui/src/game.cpp
+++ b/samples/017-imgui/src/game.cpp
@@ -34,14 +34,14 @@ namespace imgui {
// Setup renderer
auto* render = window->createRenderer();
render->onIntroCompleted = [this]() { this->loadContent(); };
- render->setDrawCall([this](const rawrbox::DrawPass& pass) {
+ render->setDrawCall([this](const rawrbox::CameraBase& /*camera*/, const rawrbox::DrawPass& pass) {
if (pass != rawrbox::DrawPass::PASS_OVERLAY) return;
this->drawOverlay();
});
// ---------------
// Setup camera --
- auto* cam = render->setupCamera(render->getSize());
+ auto* cam = render->createCamera(render->getSize());
cam->setPos({-2.F, 5.F, -3.5F});
cam->setAngle({0.F, rawrbox::MathUtils::toRad(-45), 0.F, 0.F});
// ---------------
@@ -82,6 +82,10 @@ namespace imgui {
}
void Game::onThreadShutdown(rawrbox::ENGINE_THREADS thread) {
+ if (thread == rawrbox::ENGINE_THREADS::THREAD_RENDER) {
+ rawrbox::RESOURCES::shutdown();
+ }
+
rawrbox::IMGUIManager::shutdown(thread);
rawrbox::Window::shutdown(thread);
}
diff --git a/samples/018-camera/CMakeLists.txt b/samples/018-camera/CMakeLists.txt
new file mode 100644
index 00000000..5c7df8bb
--- /dev/null
+++ b/samples/018-camera/CMakeLists.txt
@@ -0,0 +1,23 @@
+set(output_target 018-camera)
+project(${output_target})
+# --------------
+
+# Grab source files
+file(GLOB_RECURSE RAWRBOX_SAMPLE_SOURCES "include/*.hpp" "src/*.cpp")
+
+# Project setup
+add_executable(${output_target} ${RAWRBOX_SAMPLE_SOURCES})
+add_dependencies(${output_target} copy_resources_samples)
+target_include_directories(${output_target} PRIVATE "include")
+target_compile_features(${output_target} PRIVATE cxx_std_${CMAKE_CXX_STANDARD})
+target_link_libraries(${output_target} PRIVATE RAWRBOX.RENDER)
+target_compile_definitions(${output_target} PRIVATE NOMINMAX)
+
+set_lib_runtime_mt(${output_target})
+
+if(NOT WIN32)
+ set_target_properties(${output_target} PROPERTIES LINK_FLAGS -Wl,-rpath,'\$ORIGIN')
+else()
+
+ copy_required_dlls(${output_target}) # Required by diligent
+endif()
diff --git a/samples/018-camera/README.md b/samples/018-camera/README.md
new file mode 100644
index 00000000..fb7d5573
--- /dev/null
+++ b/samples/018-camera/README.md
@@ -0,0 +1,6 @@
+# 018-camera Sample
+
+> [!NOTE]
+> This sample demonstrates how to integrate multiple cameras and layer filtering
+
+![](https://i.rawr.dev/sample18-min.gif)
diff --git a/samples/018-camera/include/camera/game.hpp b/samples/018-camera/include/camera/game.hpp
new file mode 100644
index 00000000..141f3a95
--- /dev/null
+++ b/samples/018-camera/include/camera/game.hpp
@@ -0,0 +1,44 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+
+namespace camera {
+ class Game : public rawrbox::Engine {
+ std::unique_ptr> _model = std::make_unique>();
+ std::unique_ptr> _model2 = std::make_unique>();
+ std::unique_ptr> _bboxes = std::make_unique>();
+ std::unique_ptr> _text = std::make_unique>();
+
+ rawrbox::CameraPerspective* _camera = nullptr;
+
+ bool _ready = false;
+ bool _layers = true;
+
+ // Engine setup ---
+ void setupGLFW() override;
+ void init() override;
+ void onThreadShutdown(rawrbox::ENGINE_THREADS thread) override;
+ void pollEvents() override;
+ void update() override;
+ void draw() override;
+ // ----------------
+
+ public:
+ Game() = default;
+ Game(const Game&) = delete;
+ Game(Game&&) = delete;
+ Game& operator=(const Game&) = delete;
+ Game& operator=(Game&&) = delete;
+ ~Game() override = default;
+
+ void drawWorld(uint32_t layer);
+ void drawOverlay();
+
+ void loadContent();
+ void contentLoaded();
+ };
+} // namespace camera
diff --git a/samples/018-camera/src/game.cpp b/samples/018-camera/src/game.cpp
new file mode 100644
index 00000000..ad9ff821
--- /dev/null
+++ b/samples/018-camera/src/game.cpp
@@ -0,0 +1,178 @@
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+
+namespace camera {
+ void Game::setupGLFW() {
+#if defined(_DEBUG) && defined(RAWRBOX_SUPPORT_DX12)
+ auto* window = rawrbox::Window::createWindow(Diligent::RENDER_DEVICE_TYPE_D3D12); // DX12 is faster on DEBUG than Vulkan, due to vulkan having extra check steps to prevent you from doing bad things
+#else
+ auto* window = rawrbox::Window::createWindow();
+#endif
+ window->setMonitor(-1);
+ window->setTitle("CAMERA TEST");
+#ifdef _DEBUG
+ window->init(1600, 900, rawrbox::WindowFlags::Window::WINDOWED);
+#else
+ window->init(0, 0, rawrbox::WindowFlags::Window::BORDERLESS);
+#endif
+
+ window->onWindowClose += [this](auto& /*w*/) { this->shutdown(); };
+ }
+
+ void Game::init() {
+ auto* window = rawrbox::Window::getWindow();
+
+ // Setup renderer
+ auto* render = window->createRenderer();
+ render->onIntroCompleted = [this]() { this->loadContent(); };
+ render->setDrawCall([this](const rawrbox::CameraBase& camera, const rawrbox::DrawPass& pass) {
+ if (pass == rawrbox::DrawPass::PASS_OVERLAY) {
+ this->drawOverlay();
+ } else {
+ this->drawWorld(camera.getLayers());
+ }
+ });
+ // ---------------
+
+ // Setup main camera
+ auto* cam = render->createCamera(*window);
+ cam->setPos({0.F, 6.F, -6.F});
+ cam->setAngle({0.F, rawrbox::MathUtils::toRad(-55), 0.F, 0.F});
+ // --------------
+
+ // Setup camera 2
+ this->_camera = render->createCamera(rawrbox::Vector2u{256, 256});
+ this->_camera->setPos({0.F, 6.F, -6.F});
+ this->_camera->setAngle({0.F, rawrbox::MathUtils::toRad(-55), 0.F, 0.F});
+ this->_camera->setLayers(rawrbox::CameraLayers::LAYER_1); // Only draw objects on layer 1 (the name can be changed on the render_config.hpp file)
+ // --------------
+
+ // Add loaders
+ rawrbox::RESOURCES::addLoader();
+ // --------------
+
+ // BINDS ----
+ window->onKey += [this](rawrbox::Window& /*w*/, uint32_t key, uint32_t /*scancode*/, uint32_t action, uint32_t /*mods*/) {
+ if (!this->_ready || action != rawrbox::KEY_ACTION_UP || key != rawrbox::KEY_F1) return;
+ this->_layers = !this->_layers;
+ };
+ // -----
+
+ render->init();
+ }
+
+ void Game::loadContent() {
+ std::vector> initialContentFiles = {
+ {"./assets/textures/fire1.gif", 0},
+ {"./assets/textures/screem.png", 0},
+ };
+
+ rawrbox::RESOURCES::loadListAsync(initialContentFiles, [this]() {
+ rawrbox::runOnRenderThread([this]() {
+ this->contentLoaded();
+ });
+ });
+ }
+
+ void Game::contentLoaded() {
+ if (this->_ready) return;
+
+ auto* texture = rawrbox::RESOURCES::getFile("./assets/textures/fire1.gif")->get();
+ auto* texture2 = rawrbox::RESOURCES::getFile("./assets/textures/screem.png")->get();
+
+ // SETUP MODELS ---
+ {
+ auto mesh = rawrbox::MeshUtils::generateCube({1.5F, 0, 0}, {1.0F, 1.0F, 1.0F}, rawrbox::Colors::White());
+ mesh.setTexture(texture);
+ this->_model->addMesh(mesh);
+ this->_bboxes->addMesh(rawrbox::MeshUtils::generateBBOX({1.5F, 0, 0}, mesh.getBBOX()));
+ }
+
+ {
+ auto mesh = rawrbox::MeshUtils::generatePlane({0, 0, 0}, {1.0F, 1.0F}, rawrbox::Colors::White());
+ mesh.setTexture(this->_camera->getRenderTarget());
+ this->_model->addMesh(mesh);
+ this->_bboxes->addMesh(rawrbox::MeshUtils::generateBBOX({0, 0, 0}, mesh.getBBOX()));
+ }
+
+ {
+ auto mesh = rawrbox::MeshUtils::generateCube({-1.5F, 0, 0}, {1.0F, 1.0F, 1.0F}, rawrbox::Colors::White());
+ mesh.setTexture(texture2);
+ this->_model2->addMesh(mesh);
+ this->_bboxes->addMesh(rawrbox::MeshUtils::generateBBOX({-1.5F, 0, 0}, mesh.getBBOX()));
+ }
+ // ----------------
+
+ // TEXT ---
+ this->_text->addText(*rawrbox::DEBUG_FONT_REGULAR, "ONLY VISIBLE IN CAMERA 2", {-1.5F, 1.2F, 0});
+ this->_text->addText(*rawrbox::DEBUG_FONT_REGULAR, "CAMERA 2 RENDER TARGET", {0, 0.6F, 0});
+ this->_text->addText(*rawrbox::DEBUG_FONT_REGULAR, "VISIBLE ON BOTH CAMERAS", {1.5F, 1.2F, 0});
+ this->_text->upload();
+ // --------
+
+ this->_model->upload();
+ this->_model2->upload();
+ this->_bboxes->upload();
+
+ this->_ready = true;
+ }
+
+ void Game::onThreadShutdown(rawrbox::ENGINE_THREADS thread) {
+ if (thread == rawrbox::ENGINE_THREADS::THREAD_RENDER) {
+ this->_model.reset();
+ this->_model2.reset();
+ this->_bboxes.reset();
+ this->_text.reset();
+
+ this->_camera = nullptr;
+
+ rawrbox::RESOURCES::shutdown();
+ }
+
+ rawrbox::Window::shutdown(thread);
+ }
+
+ void Game::pollEvents() {
+ rawrbox::Window::pollEvents();
+ }
+
+ void Game::update() {
+ rawrbox::Window::update();
+ }
+
+ void Game::drawWorld(uint32_t layer) {
+ if (!this->_ready) return;
+
+ this->_model->draw();
+
+ if (this->_layers) {
+ if ((layer & rawrbox::CameraLayers::LAYER_1) > 0) {
+ this->_model2->draw();
+ }
+ } else {
+ this->_model2->draw();
+ }
+
+ this->_bboxes->draw();
+ this->_text->draw();
+ }
+
+ void Game::drawOverlay() {
+ if (!this->_ready) return;
+ auto* stencil = rawrbox::RENDERER->stencil();
+
+ stencil->drawText(fmt::format("[F1] LAYERS -> {}", this->_layers ? "enabled" : "disabled"), {15, 15}, rawrbox::Colors::White(), rawrbox::Colors::Black());
+ }
+
+ void Game::draw() {
+ rawrbox::Window::render(); // Commit primitives
+ }
+} // namespace camera
diff --git a/samples/018-camera/src/main.cpp b/samples/018-camera/src/main.cpp
new file mode 100644
index 00000000..0a273b86
--- /dev/null
+++ b/samples/018-camera/src/main.cpp
@@ -0,0 +1,22 @@
+
+
+#ifdef _WIN32
+ #include
+#endif
+
+#include
+
+int main(int /*argc*/, char* /*argv*/[]) {
+#ifdef _WIN32
+ SetConsoleTitle("CAMERA TEST");
+ SetConsoleCP(CP_UTF8);
+ SetConsoleOutputCP(CP_UTF8);
+#endif
+
+ camera::Game engine;
+ engine.setFPS(120);
+ engine.setTPS(66);
+ engine.run();
+
+ return 0;
+}
diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt
index 1fcde53d..41b895a1 100644
--- a/samples/CMakeLists.txt
+++ b/samples/CMakeLists.txt
@@ -50,3 +50,5 @@ endif()
if(RAWRBOX_BUILD_RAWRBOX_IMGUI)
add_subdirectory("017-imgui")
endif()
+
+add_subdirectory("018-camera")