aboutsummaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/10-common/Enum.hpp19
-rw-r--r--source/10-common/Uid.cpp4
-rw-r--r--source/10-common/Uid.hpp4
-rw-r--r--source/30-game/App.cpp19
-rw-r--r--source/30-game/EditorCorePrivate.cpp182
-rw-r--r--source/30-game/EditorCorePrivate.hpp2
-rw-r--r--source/30-game/EditorUtils.hpp23
-rw-r--r--source/30-game/Renderer.cpp158
-rw-r--r--source/30-game/Renderer.hpp26
9 files changed, 317 insertions, 120 deletions
diff --git a/source/10-common/Enum.hpp b/source/10-common/Enum.hpp
index 8ad75ba..5d75955 100644
--- a/source/10-common/Enum.hpp
+++ b/source/10-common/Enum.hpp
@@ -61,32 +61,32 @@ public:
}
}
- EnumFlags& operator|=(EnumFlags that) {
+ EnumFlags& operator|=(EnumFlags that) const {
mValue |= that.mValue;
return *this;
}
- EnumFlags& operator&=(EnumFlags that) {
+ EnumFlags& operator&=(EnumFlags that) const {
mValue &= that.mValue;
return *this;
}
- EnumFlags& operator^=(EnumFlags that) {
+ EnumFlags& operator^=(EnumFlags that) const {
mValue ^= that.mValue;
return *this;
}
- EnumFlags& operator|=(TEnum e) {
+ EnumFlags& operator|=(TEnum e) const {
mValue |= 1 << static_cast<Underlying>(e);
return *this;
}
- EnumFlags& operator&=(TEnum e) {
+ EnumFlags& operator&=(TEnum e) const {
mValue &= 1 << static_cast<Underlying>(e);
return *this;
}
- EnumFlags& operator^=(TEnum e) {
+ EnumFlags& operator^=(TEnum e) const {
mValue ^= 1 << static_cast<Underlying>(e);
return *this;
}
@@ -101,3 +101,10 @@ public:
EnumFlags operator~() const { return EnumFlags(~mValue); }
};
+
+// Helper class for enumerating enum elements for ImGui::Begin/EndCombo
+template <class TEnum>
+struct EnumElement {
+ const char* name;
+ TEnum value;
+};
diff --git a/source/10-common/Uid.cpp b/source/10-common/Uid.cpp
index 1930cd8..7f8fd9d 100644
--- a/source/10-common/Uid.cpp
+++ b/source/10-common/Uid.cpp
@@ -45,13 +45,13 @@ void Uid::Read(const rapidjson::Value& value) {
this->lower = lower.GetUint64();
}
-void Uid::WriteInto(rapidjson::Value& value, rapidjson::Document& root) {
+void Uid::WriteInto(rapidjson::Value& value, rapidjson::Document& root) const {
value.Reserve(2, root.GetAllocator());
value.PushBack((uint64_t)upper, root.GetAllocator());
value.PushBack((uint64_t)lower, root.GetAllocator());
}
-rapidjson::Value Uid::Write(rapidjson::Document& root) {
+rapidjson::Value Uid::Write(rapidjson::Document& root) const {
rapidjson::Value result(rapidjson::kArrayType);
WriteInto(result, root);
return result;
diff --git a/source/10-common/Uid.hpp b/source/10-common/Uid.hpp
index f58129c..539de03 100644
--- a/source/10-common/Uid.hpp
+++ b/source/10-common/Uid.hpp
@@ -25,8 +25,8 @@ struct Uid {
std::string WriteString();
void Read(const rapidjson::Value& value);
- void WriteInto(rapidjson::Value& value, rapidjson::Document& root);
- rapidjson::Value Write(rapidjson::Document& root);
+ void WriteInto(rapidjson::Value& value, rapidjson::Document& root) const;
+ rapidjson::Value Write(rapidjson::Document& root) const;
auto operator<=>(const Uid&) const = default;
};
diff --git a/source/30-game/App.cpp b/source/30-game/App.cpp
index 45a7545..8328589 100644
--- a/source/30-game/App.cpp
+++ b/source/30-game/App.cpp
@@ -1,5 +1,10 @@
#include "App.hpp"
+#include "ScopeGuard.hpp"
+#include "Utils.hpp"
+
+#include <rapidjson/document.h>
+#include <rapidjson/filereadstream.h>
#include <string>
#include <utility>
@@ -27,6 +32,20 @@ App::App()
mMainCamera.SetEyePos(glm::vec3(0, 0, 1));
mMainCamera.SetTargetDirection(glm::vec3(0, 0, -1));
mMainCamera.SetHasPerspective(false);
+
+ do {
+ auto file = Utils::OpenCstdioFile("assets/GameRendererBindings.json", Utils::Read);
+ if (!file) break;
+ DEFER { fclose(file); };
+
+ char readerBuffer[65536];
+ rapidjson::FileReadStream stream(file, readerBuffer, sizeof(readerBuffer));
+
+ rapidjson::Document root;
+ root.ParseStream(stream);
+
+ mWorldRenderer.LoadBindings(root);
+ } while (false);
}
App::~App() {
diff --git a/source/30-game/EditorCorePrivate.cpp b/source/30-game/EditorCorePrivate.cpp
index 43857a8..1e7b010 100644
--- a/source/30-game/EditorCorePrivate.cpp
+++ b/source/30-game/EditorCorePrivate.cpp
@@ -23,6 +23,10 @@
#include <imgui.h>
#include <misc/cpp/imgui_stdlib.h>
+#include <rapidjson/document.h>
+#include <rapidjson/filereadstream.h>
+#include <rapidjson/filewritestream.h>
+#include <rapidjson/writer.h>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
@@ -399,6 +403,21 @@ struct CreatableGameObject {
},
};
#undef GAMEOBJECT_CONSTRUCTOR
+
+void SaveRendererBindings(const Renderer& renderer) {
+ auto file = Utils::OpenCstdioFile("assets/GameRendererBindings.json", Utils::WriteTruncate);
+ if (!file) return;
+ DEFER { fclose(file); };
+
+ char writerBuffer[65536];
+ rapidjson::FileWriteStream stream(file, writerBuffer, sizeof(writerBuffer));
+ rapidjson::Writer writer(stream);
+
+ rapidjson::Document root(rapidjson::kObjectType);
+ renderer.SaveBindings(root, root);
+
+ root.Accept(writer);
+}
} // namespace ProjectBrussel_UNITY_ID
std::unique_ptr<IEditor> IEditor::CreateInstance(App* app) {
@@ -659,6 +678,8 @@ void EditorInstance::Show() {
}
void EditorInstance::ShowWorldProperties() {
+ using namespace ProjectBrussel_UNITY_ID;
+
if (mApp->IsGameRunning()) {
if (ImGui::Button("Pause")) {
mApp->SetGameRunning(false);
@@ -675,102 +696,119 @@ void EditorInstance::ShowWorldProperties() {
}
}
+ auto& renderer = *mApp->GetWorldRenderer();
auto& camera = *mApp->GetActiveCamera();
- // vvv Camera settings (per instance)
- ImGui::TextUnformatted("Active camera:");
- ImGui::Indent();
+ if (ImGui::CollapsingHeader("Renderer settings")) {
+ if (ImGui::Checkbox("Draw shaded", &mRenderer_DrawShaded)) {
+ renderer.SetRenderOption(Renderer::RO_Shading, mRenderer_DrawShaded);
+ }
+ if (ImGui::Checkbox("Draw wireframe", &mRenderer_DrawWireFrame)) {
+ renderer.SetRenderOption(Renderer::RO_Wireframe, mRenderer_DrawWireFrame);
+ }
- ImGui::TextUnformatted(camera.name.c_str());
- if (ImGui::IsItemHovered()) {
- ImGui::SetTooltip("Object at <%p>", &camera);
+ if (auto ires = Utils::SimpleIresReceptor<IresMaterial>(renderer.binding_WireframeMaterial->GetIres(), *this, IresObject::KD_Material)) {
+ renderer.binding_WireframeMaterial.Attach(ires->GetInstance());
+ SaveRendererBindings(renderer);
+ }
}
- ImGui::InputFloat3("Eye", glm::value_ptr(camera.eye));
- if (ImGui::IsMouseReleased(ImGuiMouseButton_Right) && ImGui::IsItemHovered()) {
- ImGui::OpenPopup("##CTXMENU");
- }
- ImGui::InputFloat3("Target", glm::value_ptr(camera.target));
- if (ImGui::IsMouseReleased(ImGuiMouseButton_Right) && ImGui::IsItemHovered()) {
- ImGui::OpenPopup("##CTXMENU");
- }
- if (ImGui::BeginPopup("##CTXMENU", ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings)) {
- if (ImGui::MenuItem("Reset to origin")) {
- camera.SetEyePos(glm::vec3(1.0f, 1.0f, 1.0f));
- }
- if (ImGui::MenuItem("Reset completely")) {
- camera.eye = glm::vec3(0, 0, 1);
- camera.target = glm::vec3(0, 0, 0);
+ if (ImGui::CollapsingHeader("Camera settings")) {
+ // vvv Camera settings (per instance)
+ ImGui::TextUnformatted("Active camera:");
+ ImGui::Indent();
+
+ ImGui::TextUnformatted(camera.name.c_str());
+ if (ImGui::IsItemHovered()) {
+ ImGui::SetTooltip("Object at <%p>", &camera);
}
- ImGui::EndPopup();
- }
- if (IsCurrentCameraEditor()) {
- const char* preview;
- switch (mEcm) {
- case ECM_2D: preview = "2D view"; break;
- case ECM_Side3D: preview = "Side 3D view"; break;
+ ImGui::InputFloat3("Eye", glm::value_ptr(camera.eye));
+ if (ImGui::IsMouseReleased(ImGuiMouseButton_Right) && ImGui::IsItemHovered()) {
+ ImGui::OpenPopup("##CTXMENU");
+ }
+ ImGui::InputFloat3("Target", glm::value_ptr(camera.target));
+ if (ImGui::IsMouseReleased(ImGuiMouseButton_Right) && ImGui::IsItemHovered()) {
+ ImGui::OpenPopup("##CTXMENU");
}
- if (ImGui::BeginCombo("Mode", preview)) {
- if (ImGui::Selectable("2D view", mEcm == ECM_2D)) {
- if (mEcm != ECM_2D) {
- mEcm = ECM_2D;
+ if (ImGui::BeginPopup("##CTXMENU", ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings)) {
+ if (ImGui::MenuItem("Reset to origin")) {
+ camera.SetEyePos(glm::vec3(1.0f, 1.0f, 1.0f));
+ }
+ if (ImGui::MenuItem("Reset completely")) {
+ camera.eye = glm::vec3(0, 0, 1);
+ camera.target = glm::vec3(0, 0, 0);
+ }
+ ImGui::EndPopup();
+ }
+
+ if (IsCurrentCameraEditor()) {
+ const char* preview;
+ switch (mEcm) {
+ case ECM_2D: preview = "2D view"; break;
+ case ECM_Side3D: preview = "Side 3D view"; break;
+ }
+ if (ImGui::BeginCombo("Mode", preview)) {
+ if (ImGui::Selectable("2D view", mEcm == ECM_2D)) {
+ if (mEcm != ECM_2D) {
+ mEcm = ECM_2D;
- // TODO project eye to world plane
+ // TODO project eye to world plane
- camera.SetHasPerspective(false);
+ camera.SetHasPerspective(false);
+ }
}
- }
- if (ImGui::Selectable("Side 3D view", mEcm == ECM_Side3D, ImGuiSelectableFlags_None)) {
- if (mEcm != ECM_Side3D) {
- mEcm = ECM_Side3D;
+ if (ImGui::Selectable("Side 3D view", mEcm == ECM_Side3D, ImGuiSelectableFlags_None)) {
+ if (mEcm != ECM_Side3D) {
+ mEcm = ECM_Side3D;
- auto origEye = camera.eye;
- auto origTarget = camera.target;
+ auto origEye = camera.eye;
+ auto origTarget = camera.target;
- // New setup: focus on the point of world plane that we were originally "hovering above"
- camera.target = origEye;
- camera.target.z = 0.0f;
+ // New setup: focus on the point of world plane that we were originally "hovering above"
+ camera.target = origEye;
+ camera.target.z = 0.0f;
- // New setup: move the eye back at an angle
- camera.eye = camera.target;
- camera.eye.x += 4.0f * std::cos(60.0f);
- camera.eye.y += 0.0f;
- camera.eye.z += 4.0f * std::sin(60.0f);
+ // New setup: move the eye back at an angle
+ camera.eye = camera.target;
+ camera.eye.x += 4.0f * std::cos(60.0f);
+ camera.eye.y += 0.0f;
+ camera.eye.z += 4.0f * std::sin(60.0f);
- camera.SetHasPerspective(true);
+ camera.SetHasPerspective(true);
+ }
}
+ ImGui::EndCombo();
}
- ImGui::EndCombo();
}
- }
- ImGui::Checkbox("Perspective", &camera.perspective);
- if (camera.perspective) {
- float fovDegress = camera.fov / M_PI * 180.0f;
- if (ImGui::SliderFloat("FOV", &fovDegress, 1.0f, 180.0f)) {
- camera.fov = fovDegress / 180.0f * M_PI;
- }
- } else {
- if (ImGui::InputFloat("Pixels per meter", &camera.pixelsPerMeter)) {
- camera.pixelsPerMeter = std::max(camera.pixelsPerMeter, 0.0f);
+ ImGui::Checkbox("Perspective", &camera.perspective);
+ if (camera.perspective) {
+ float fovDegress = camera.fov / M_PI * 180.0f;
+ if (ImGui::SliderFloat("FOV", &fovDegress, 1.0f, 180.0f)) {
+ camera.fov = fovDegress / 180.0f * M_PI;
+ }
+ } else {
+ if (ImGui::InputFloat("Pixels per meter", &camera.pixelsPerMeter)) {
+ camera.pixelsPerMeter = std::max(camera.pixelsPerMeter, 0.0f);
+ }
}
- }
- ImGui::Unindent();
- // ^^^ Camera settings (per instance)
- // vvv Camera control settings
- ImGui::TextUnformatted("Camera controls:");
- ImGui::Indent();
+ ImGui::Unindent();
+ // ^^^ Camera settings (per instance)
+ // vvv Camera control settings
+ ImGui::TextUnformatted("Camera controls:");
+ ImGui::Indent();
- ImGui::Checkbox("Move camera with WASD", &mMoveCamKeyboard);
- ImGui::SliderFloat("Slide speed", &mMoveCamSlideSpeed, 0.1f, 10.0f);
+ ImGui::Checkbox("Move camera with WASD", &mMoveCamKeyboard);
+ ImGui::SliderFloat("Slide speed", &mMoveCamSlideSpeed, 0.1f, 10.0f);
- ImGui::Checkbox("Move camera with scoll wheel", &mMoveCamScrollWheel);
- ImGui::SliderFloat("Scroll speed", &mMoveCamScrollSpeed, 0.01, 10.0f);
+ ImGui::Checkbox("Move camera with scoll wheel", &mMoveCamScrollWheel);
+ ImGui::SliderFloat("Scroll speed", &mMoveCamScrollSpeed, 0.01, 10.0f);
- ImGui::Unindent();
- // ^^^ Camera control settings
+ ImGui::Unindent();
+ // ^^^ Camera control settings
+ }
}
// TOOD move resource-specific and gameobject-specific inspector code into attachments mechanism
diff --git a/source/30-game/EditorCorePrivate.hpp b/source/30-game/EditorCorePrivate.hpp
index 4fbfb72..42be050 100644
--- a/source/30-game/EditorCorePrivate.hpp
+++ b/source/30-game/EditorCorePrivate.hpp
@@ -102,6 +102,8 @@ private:
bool mDragCam_Happening = false;
bool mMoveCamKeyboard = false;
bool mMoveCamScrollWheel = false;
+ bool mRenderer_DrawShaded = true;
+ bool mRenderer_DrawWireFrame = false;
public:
EditorInstance(App* app);
diff --git a/source/30-game/EditorUtils.hpp b/source/30-game/EditorUtils.hpp
index 99c522b..8a9ab95 100644
--- a/source/30-game/EditorUtils.hpp
+++ b/source/30-game/EditorUtils.hpp
@@ -1,7 +1,11 @@
#pragma once
-#include "Color.hpp"
+#include "EditorCore.hpp"
#include "EditorGuizmo.hpp"
+#include "Ires.hpp"
+
+#include <Color.hpp>
+#include <Metadata.hpp>
#include <imgui.h>
#include <string>
@@ -60,4 +64,21 @@ float CalcImageHeight(glm::vec2 original, int targetWidth);
float CalcImageWidth(glm::vec2 original, float targetHeight);
ImVec2 FitImage(glm::vec2 original);
+// TODO get kind from T
+template <class T>
+T* SimpleIresReceptor(T* existing, IEditor& editor, IresObject::Kind kind) {
+ if (existing) {
+ existing->ShowReference(editor);
+ } else {
+ IresObject::ShowReferenceNull(editor);
+ }
+ if (ImGui::BeginDragDropTarget()) {
+ if (auto payload = ImGui::AcceptDragDropPayload(Metadata::EnumToString(kind).data())) {
+ return *static_cast<T* const*>(payload->Data);
+ }
+ ImGui::EndDragDropTarget();
+ }
+ return nullptr;
+}
+
} // namespace Utils
diff --git a/source/30-game/Renderer.cpp b/source/30-game/Renderer.cpp
index 3497449..ad8bf35 100644
--- a/source/30-game/Renderer.cpp
+++ b/source/30-game/Renderer.cpp
@@ -2,10 +2,16 @@
#include "GameObject.hpp"
+#include <RapidJsonHelper.hpp>
+
+#include <rapidjson/document.h>
#include <cassert>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp>
+#include <string_view>
+
+using namespace std::literals;
RenderObject::RenderObject()
: mVao{ GL_NONE } {
@@ -101,6 +107,28 @@ void RenderObject::DeleteGLObjects() {
}
}
+Renderer::Renderer()
+ : binding_WireframeMaterial{ gDefaultMaterial } //
+{
+ mRenderOptions[RO_Shading] = true;
+ mRenderOptions[RO_Wireframe] = false;
+}
+
+void Renderer::LoadBindings(const rapidjson::Value& bindings) {
+ if (auto rvWireframe = rapidjson::GetProperty(bindings, "WireframeMaterial"sv)) {
+ Uid uidWireframe;
+ uidWireframe.Read(*rvWireframe);
+ // TODO don't assume
+ binding_WireframeMaterial.Attach(((IresMaterial*)IresManager::instance->FindIres(uidWireframe))->GetInstance());
+ }
+}
+
+void Renderer::SaveBindings(rapidjson::Value& into, rapidjson::Document& root) const {
+ if (auto ires = binding_WireframeMaterial->GetIres()) {
+ into.AddMember("WireframeMaterial", ires->GetUid().Write(root), root.GetAllocator());
+ }
+}
+
void Renderer::BeginFrame(Camera& camera, float currentTime, float deltaTime) {
assert(mInsideFrame == false);
mInsideFrame = true;
@@ -121,50 +149,108 @@ void Renderer::Draw(const RenderObject* objects, const GameObject* gameObject, s
assert(mInsideFrame);
- auto vpMatrix = mFrame.matrixProj * mFrame.matrixView;
+ // Desired order: proj * view * (translate * rotate * scale) * vec
+ // <----- order of application <----- ^^^ input
+ glm::mat4 objectMatrix(1.0f);
+ objectMatrix = glm::translate(objectMatrix, gameObject->GetPos());
+ objectMatrix *= glm::toMat4(gameObject->GetRotation());
+ objectMatrix = glm::scale(objectMatrix, gameObject->GetScale());
+ auto mvpMatrix = mFrame.matrixProj * mFrame.matrixView * objectMatrix;
- // TODO shader grouping
- // TODO material grouping
- for (size_t i = 0; i < count; ++i) {
- auto& object = objects[i];
- auto indexBuffer = object.GetIndexBuffer();
- auto mat = object.GetMaterial();
- auto shader = mat->GetShader();
+ if (GetRenderOption(RO_Shading)) {
+ // TODO shader grouping
+ // TODO material grouping
+ for (size_t i = 0; i < count; ++i) {
+ auto& object = objects[i];
+ auto indexBuffer = object.GetIndexBuffer();
+ auto mat = object.GetMaterial();
+ auto shader = mat->GetShader();
- glUseProgram(shader->GetProgram());
+ glUseProgram(shader->GetProgram());
- // Material uniforms
- mat->UseUniforms();
+ // Material uniforms
+ mat->UseUniforms();
- // Next available texture unit ID after all material textures
- int texIdx = mat->GetTextures().size();
+ // Next available texture unit ID after all material textures
+ int texIdx = mat->GetTextures().size();
- // Autofill uniforms
- if (shader->autofill_Transform != kInvalidLocation) {
- glm::mat4 objectMatrix(1.0f);
- objectMatrix = glm::translate(objectMatrix, gameObject->GetPos());
- objectMatrix *= glm::toMat4(gameObject->GetRotation());
- objectMatrix = glm::scale(objectMatrix, gameObject->GetScale());
- glm::mat4 transform = vpMatrix * objectMatrix;
+ // Autofill uniforms
+ if (shader->autofill_Transform != kInvalidLocation) {
+ glUniformMatrix4fv(shader->autofill_Transform, 1, GL_FALSE, &mvpMatrix[0][0]);
+ }
+ if (shader->autofill_Time != kInvalidLocation) {
+ glUniform1f(shader->autofill_Time, mFrame.time);
+ }
+ if (shader->autofill_DeltaTime != kInvalidLocation) {
+ glUniform1f(shader->autofill_DeltaTime, mFrame.deltaTime);
+ }
+ if (shader->autofill_TextureAtlas != kInvalidLocation &&
+ object.autofill_TextureAtlas != nullptr)
+ {
+ glActiveTexture(GL_TEXTURE0 + texIdx);
+ glBindTexture(GL_TEXTURE_2D, object.autofill_TextureAtlas->GetHandle());
+ glUniform1i(shader->autofill_TextureAtlas, texIdx);
+ ++texIdx;
+ }
- glUniformMatrix4fv(shader->autofill_Transform, 1, GL_FALSE, &transform[0][0]);
- }
- if (shader->autofill_Time != kInvalidLocation) {
- glUniform1f(shader->autofill_Time, mFrame.time);
+ glBindVertexArray(object.GetGLVao());
+ glDrawElements(GL_TRIANGLES, indexBuffer->count, indexBuffer->GetIndexTypeGL(), 0);
}
- if (shader->autofill_DeltaTime != kInvalidLocation) {
- glUniform1f(shader->autofill_DeltaTime, mFrame.deltaTime);
- }
- if (shader->autofill_TextureAtlas != kInvalidLocation &&
- object.autofill_TextureAtlas != nullptr)
- {
- glActiveTexture(GL_TEXTURE0 + texIdx);
- glBindTexture(GL_TEXTURE_2D, object.autofill_TextureAtlas->GetHandle());
- glUniform1i(shader->autofill_TextureAtlas, texIdx);
- ++texIdx;
+ }
+
+ if (GetRenderOption(RO_Wireframe)) {
+ auto& mat = *binding_WireframeMaterial;
+ auto& shader = *mat.GetShader();
+ auto& shaderInfo = shader.GetInfo();
+
+ glUseProgram(shader.GetProgram());
+ mat.UseUniforms();
+
+ // TODO reduce calls with consecutive wireframe setting
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ for (size_t i = 0; i < count; ++i) {
+ auto& object = objects[i];
+
+ auto& vBindings = object.GetVertexBufferBindings().bindings;
+ auto vf = object.GetVertexFormat();
+
+ // Setup vertex buffers
+ for (auto& elm : vf->elements) {
+ assert(elm.bindingIndex < vBindings.size());
+ auto& buffer = vBindings[elm.bindingIndex];
+
+ int index = shaderInfo.FindInputLocation(elm.semantic);
+ if (index == -1) {
+ continue;
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER, buffer->handle);
+ glEnableVertexAttribArray(index);
+ glVertexAttribPointer(
+ index,
+ Tags::VectorLenOf(elm.type),
+ Tags::FindGLType(elm.type),
+ Tags::IsNormalized(elm.type),
+ vf->vertexSize,
+ (void*)(uintptr_t)elm.offset);
+ }
+
+ // Setup index buffer
+ auto indexBuffer = object.GetIndexBuffer();
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer->handle);
+
+ glDrawElements(GL_TRIANGLES, indexBuffer->count, indexBuffer->GetIndexTypeGL(), 0);
}
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glBindVertexArray(object.GetGLVao());
- glDrawElements(GL_TRIANGLES, indexBuffer->count, indexBuffer->GetIndexTypeGL(), 0);
+ return;
}
}
+
+bool Renderer::GetRenderOption(RenderOption option) const {
+ return mRenderOptions[option];
+}
+
+void Renderer::SetRenderOption(RenderOption option, bool flag) {
+ mRenderOptions[option] = flag;
+}
diff --git a/source/30-game/Renderer.hpp b/source/30-game/Renderer.hpp
index 98a9f28..856dc31 100644
--- a/source/30-game/Renderer.hpp
+++ b/source/30-game/Renderer.hpp
@@ -2,10 +2,12 @@
#include "Camera.hpp"
#include "Material.hpp"
-#include "RcPtr.hpp"
#include "VertexIndex.hpp"
+#include <RcPtr.hpp>
+
#include <glad/glad.h>
+#include <rapidjson/fwd.h>
#include <cstddef>
#include <glm/glm.hpp>
@@ -56,13 +58,35 @@ struct RendererFrameInfo {
};
class Renderer {
+public:
+ // NOTE: see Renderer constructor for default values
+ enum RenderOption {
+ /// Render everything directly using objects' provided material and vertex/index data.
+ RO_Shading,
+ /// Render everything as wireframes using provided position data.
+ RO_Wireframe,
+ RO_COUNT,
+ };
+
+public:
+ RcPtr<Material> binding_WireframeMaterial;
+
private:
RendererFrameInfo mFrame;
bool mInsideFrame = false;
+ bool mRenderOptions[RO_COUNT] = {};
public:
+ Renderer();
+
+ void LoadBindings(const rapidjson::Value& bindings);
+ void SaveBindings(rapidjson::Value& into, rapidjson::Document& root) const;
+
void BeginFrame(Camera& camera, float currentTime, float deltaTime);
const RendererFrameInfo& GetLastFrameInfo() const { return mFrame; }
void Draw(const RenderObject* objects, const GameObject* gameObject, size_t count);
void EndFrame();
+
+ bool GetRenderOption(RenderOption option) const;
+ void SetRenderOption(RenderOption option, bool flag);
};