Serializing

This commit is contained in:
Chewico 2026-02-09 16:51:49 +01:00
parent 818941460f
commit 398b655f3d
29 changed files with 426 additions and 255 deletions

View File

@ -1,25 +1,16 @@
#pragma once #pragma once
#include "DeerCore/Tools/Memory.h" #include "DeerCore/Tools/Path.h"
namespace Deer { namespace Deer {
class World; class World;
class WorldSettings; class WorldSettings;
namespace Universe { namespace Universe {
struct WorldHandle { World* createWorld(const WorldSettings&);
uint32_t worldId = 0;
uint32_t generation = 0;
WorldHandle() {} void saveWorldInJson(World*, const Path& path);
WorldHandle(uint32_t _worldId, uint32_t _generation) : worldId(_worldId), generation(_generation) {}
};
WorldHandle createWorld(const WorldSettings&);
World& getWorld(WorldHandle);
void destroyWorld(WorldHandle);
void destroyAllWorlds(); void destroyAllWorlds();
void flushDestroyedWorlds(); void flushDestroyedWorlds();
} // namespace Universe } // namespace Universe
} // namespace Deer } // namespace Deer

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "DeerCore/Tools/Memory.h" #include "DeerCore/Tools/Memory.h"
#include "DeerCore/Tools/TypeDefs.h" #include "DeerCore/Tools/TypeDefs.h"
#include "DeerCore/Universe.h"
#include <atomic> #include <atomic>
#include <functional> #include <functional>
@ -33,7 +34,6 @@ namespace Deer {
class World { class World {
public: public:
World(const WorldSettings&);
~World(); ~World();
void execute(); void execute();
@ -49,11 +49,14 @@ namespace Deer {
void setRenderFrequency(int); void setRenderFrequency(int);
#endif #endif
private: private:
World(const WorldSettings&);
std::atomic<WorldState> executingState; std::atomic<WorldState> executingState;
WorldSettings worldSettings; WorldSettings worldSettings;
#ifdef DEER_RENDER #ifdef DEER_RENDER
float renderDeltaTime; float renderDeltaTime;
#endif #endif
friend World* Universe::createWorld(const WorldSettings& worldSettings);
}; // namespace World }; // namespace World
} // namespace Deer } // namespace Deer

View File

@ -12,7 +12,7 @@ namespace Deer {
unsigned int height; unsigned int height;
WindowProps(const std::string& _title = "Deer Engine", WindowProps(const std::string& _title = "Deer Engine",
unsigned int _width = 1280, unsigned int _width = 900,
unsigned int _height = 720) unsigned int _height = 720)
: title(_title), width(_width), height(_height) { : title(_title), width(_width), height(_height) {
} }

View File

@ -1,30 +1,30 @@
#pragma once #pragma once
#include "DeerCore/Components.h" #include "DeerCore/Components.h"
#include "DeerCore/EntityEnviroment.h" #include "DeerCore/EntityEnviroment.h"
#include "DeerCore/World/Serialization/SerializationGlobalVars.h"
#include "EntitySerializationStruct.h" #include "EntitySerializationStruct.h"
namespace Deer { namespace Deer {
template <class Archive, typename T> template <class Archive, typename T>
void saveComponent(Archive& archive, const std::string& componentName, Entity const& m_entity) { void saveComponent(Archive& archive, Entity const& m_entity) {
bool hasComponent = m_entity.hasComponent<T>(); bool hasComponent = m_entity.hasComponent<T>();
archive(cereal::make_nvp(("has_" + componentName).c_str(), hasComponent)); archive(cereal::make_nvp(("contains_" + typedef(T).get_name()).c_str(), hasComponent));
if (hasComponent) { if (hasComponent) {
const T& component = m_entity.getComponent<T>(); const T& component = m_entity.getComponent<T>();
archive(cereal::make_nvp(componentName.c_str(), component)); archive(cereal::make_nvp(typedef(T).get_name(), component));
} }
} }
template <class Archive, typename T> template <class Archive, typename T>
void loadComponent(Archive& archive, const std::string& componentName, Entity const& m_entity) { void loadComponent(Archive& archive, Entity const& m_entity) {
bool hasComponent; bool hasComponent;
archive(cereal::make_nvp(("has_" + componentName).c_str(), hasComponent)); archive(cereal::make_nvp(("contains_" + typedef(T).get_name()).c_str(), hasComponent));
if (hasComponent) { if (hasComponent) {
T& component = m_entity.addComponent<T>(); T& component = m_entity.addComponent<T>();
archive(cereal::make_nvp(componentName.c_str(), component)); archive(cereal::make_nvp(typedef(T).get_name(), component));
} }
} }
// ENTITY // ENTITY
template <class Archive> template <class Archive>
void save(Archive& archive, EntitySerializationStruct const& m_entity) { void save(Archive& archive, EntitySerializationStruct const& m_entity) {

View File

@ -4,7 +4,7 @@
namespace Deer { namespace Deer {
class EntityEnvironment; class EntityEnvironment;
struct EntitySerializationStruct { struct EntitySerializationStruct {
uint16_t entityID; uint32_t entityID;
EntityEnvironment* env; EntityEnvironment* env;
}; };
} // namespace Deer } // namespace Deer

View File

@ -0,0 +1,9 @@
#pragma once
namespace Deer {
namespace Serialization {
}
}

View File

@ -0,0 +1,12 @@
#pragma once
#include "DeerCore/World.h"
#include "DeerCore/EntityEnviroment.h"
namespace Deer {
namespace Universe {
template <class Archive>
void save(Archive& archive, World const& world) {
World
}
}
}

View File

@ -9,82 +9,44 @@
namespace Deer { namespace Deer {
namespace Universe { namespace Universe {
struct WorldSlot { std::vector<Scope<World>> universeWorlds;
Scope<World> world = nullptr;
uint32_t generation = 1;
};
std::vector<WorldSlot> universeWorldSlots;
std::mutex universeMutex; std::mutex universeMutex;
int getFreeWorldSlot(); int getFreeWorldSlot();
void unlockedFlushDestroyedWorlds(); bool unlockedFlushDestroyedWorlds();
} // namespace Universe } // namespace Universe
int Universe::getFreeWorldSlot() { World* Universe::createWorld(const WorldSettings& worldSettings) {
for (int i = 0; i < universeWorldSlots.size(); i++) {
if (universeWorldSlots[i].world == nullptr)
return i;
}
return -1;
}
Universe::WorldHandle Universe::createWorld(const WorldSettings& worldSettings) {
std::lock_guard<std::mutex> lock(universeMutex); std::lock_guard<std::mutex> lock(universeMutex);
unlockedFlushDestroyedWorlds(); while (unlockedFlushDestroyedWorlds());;
int universeSlot = getFreeWorldSlot(); universeWorlds.push_back(Scope<World>(new World(worldSettings)));
if (universeSlot == -1) { return universeWorlds.back().get();
universeSlot = universeWorldSlots.size();
universeWorldSlots.push_back({});
}
WorldSlot& worldSlot = universeWorldSlots[universeSlot];
worldSlot.world = MakeScope<World>(worldSettings);
return WorldHandle(universeSlot, worldSlot.generation);
}
World& Universe::getWorld(WorldHandle handle) {
std::lock_guard<std::mutex> lock(universeMutex);
DEER_CORE_ASSERT(handle.worldId < universeWorldSlots.size(), "Invalid world handle");
DEER_CORE_ASSERT(handle.generation == universeWorldSlots[handle.worldId].generation, "Invalid world generation");
DEER_CORE_ASSERT(universeWorldSlots[handle.worldId].world, "World no longer exists");
return *universeWorldSlots[handle.worldId].world;
}
void Universe::destroyWorld(WorldHandle handle) {
std::lock_guard<std::mutex> lock(universeMutex);
DEER_CORE_ASSERT(handle.worldId < universeWorldSlots.size(), "Invalid world handle");
DEER_CORE_ASSERT(handle.generation == universeWorldSlots[handle.worldId].generation, "Invalid world generation");
DEER_CORE_ASSERT(universeWorldSlots[handle.worldId].world, "World no longer exists");
universeWorldSlots[handle.worldId].world->destroy();
unlockedFlushDestroyedWorlds();
} }
void Universe::destroyAllWorlds() { void Universe::destroyAllWorlds() {
std::lock_guard<std::mutex> lock(universeMutex); std::lock_guard<std::mutex> lock(universeMutex);
for (WorldSlot& slot : universeWorldSlots) for (Scope<World>& world : universeWorlds)
slot.world->destroy(); world->destroy();
unlockedFlushDestroyedWorlds(); while (unlockedFlushDestroyedWorlds());;
} }
void Universe::unlockedFlushDestroyedWorlds() { bool Universe::unlockedFlushDestroyedWorlds() {
for (WorldSlot& slot : universeWorldSlots) { for (size_t i = 0; i < universeWorlds.size(); i++) {
if (slot.world != nullptr && slot.world->getExecutionState() == WorldState::ReadyToDestroy) { Scope<World>& world = universeWorlds[i];
slot.world.release(); if (world->getExecutionState() == WorldState::ReadyToDestroy) {
slot.world = nullptr; world.reset();
slot.generation++; world = Scope<World>(universeWorlds.back().release());
universeWorlds.back() = nullptr;
universeWorlds.pop_back();
return true;
} }
} }
return false;
} }
void Universe::flushDestroyedWorlds() { void Universe::flushDestroyedWorlds() {
std::lock_guard<std::mutex> lock(universeMutex); std::lock_guard<std::mutex> lock(universeMutex);
unlockedFlushDestroyedWorlds(); while (unlockedFlushDestroyedWorlds());;
} }
} // namespace Deer } // namespace Deer

View File

@ -0,0 +1,12 @@
#include "DeerCore/Universe.h"
#include "DeerCore/World.h"
#include "DeerCore/Log.h"
#include "cereal/cereal.hpp"
#include "cereal/archives/json.hpp"
namespace Deer {
} // namespace Deer

View File

@ -9,6 +9,15 @@
#include "scriptarray.h" #include "scriptarray.h"
#include "scriptstdstring.h" #include "scriptstdstring.h"
#include "DeerRender/Shader.h"
#include "DeerRender/Mesh.h"
#include "DeerRender/Render/Render.h"
#include "DeerRender/Render/RenderUtils.h"
#include "DeerRender/Components.h"
#include "glm/glm.hpp"
#include "glm/matrix.hpp"
#include <string> #include <string>
namespace Deer { namespace Deer {
@ -89,6 +98,7 @@ namespace Deer {
} }
void frameBuffer_clearRGBA(int r, int g, int b, int a, Resource<FrameBuffer>& frameBuffer) { void frameBuffer_clearRGBA(int r, int g, int b, int a, Resource<FrameBuffer>& frameBuffer) {
int data[] = {r, g, b, a}; int data[] = {r, g, b, a};
frameBuffer.getData().clear();
frameBuffer.getData().clearBuffer(0, data); frameBuffer.getData().clearBuffer(0, data);
} }
bool frameBuffer_isValid(Resource<FrameBuffer>& frameBuffer) { bool frameBuffer_isValid(Resource<FrameBuffer>& frameBuffer) {
@ -97,5 +107,26 @@ namespace Deer {
void frameBuffer_resize(int x, int y, Resource<FrameBuffer>& frameBuffer) { void frameBuffer_resize(int x, int y, Resource<FrameBuffer>& frameBuffer) {
frameBuffer.getData().resize(x, y); frameBuffer.getData().resize(x, y);
} }
void frameBuffer_drawMesh(Resource<GPUMesh> mesh, Resource<Shader> shaderResource, TransformComponent transform, WorldCamera camera, Resource<FrameBuffer>& frameBuffer) {
frameBuffer.getData().bind();
glm::mat4 camMatrix = glm::inverse(camera.transform.getMatrix());
glm::mat4 projectionMatrix = camera.camera.getMatrix();
glm::mat4 invertZ = glm::scale(glm::mat4(1.0f), glm::vec3(1, 1, -1));
// Lets invert the z axis for engine convenience
glm::mat4 cameraProjectionMatrix = projectionMatrix * invertZ * camMatrix;
glm::mat4 matrix = transform.getMatrix();
Shader& shader = shaderResource.getData();
shader.bind();
shader.uploadUniformMat4("u_viewMatrix", cameraProjectionMatrix);
shader.uploadUniformMat4("u_worldMatrix", matrix);
mesh.getData().vertexArray->bind();
Render::submit(*mesh.getData().vertexArray);
frameBuffer.getData().unbind();
}
} // namespace Scripting } // namespace Scripting
} // namespace Deer } // namespace Deer

View File

@ -1,16 +1,16 @@
#pragma once #pragma once
#include "DeerRender/Resource.h" #include "DeerRender/Resource.h"
#include "DeerRender/World.h"
#include "scriptarray.h" #include "scriptarray.h"
#include "scriptdictionary.h" #include "scriptdictionary.h"
#include <stdint.h> #include <stdint.h>
#include <string> #include <string>
#include "DeerRender/Resource.h"
namespace Deer { namespace Deer {
class FrameBuffer; class FrameBuffer;
class GPUMesh; class GPUMesh;
class Shader;
namespace Scripting { namespace Scripting {
template <typename T> template <typename T>
@ -47,6 +47,8 @@ namespace Deer {
void frameBuffer_clearRGBA(int, int, int, int, Resource<FrameBuffer>&); void frameBuffer_clearRGBA(int, int, int, int, Resource<FrameBuffer>&);
bool frameBuffer_isValid(Resource<FrameBuffer>&); bool frameBuffer_isValid(Resource<FrameBuffer>&);
void frameBuffer_resize(int, int, Resource<FrameBuffer>&); void frameBuffer_resize(int, int, Resource<FrameBuffer>&);
void frameBuffer_drawMesh(Resource<GPUMesh>, Resource<Shader>, TransformComponent, WorldCamera, Resource<FrameBuffer>&);
Resource<FrameBuffer> createFrameBuffer(std::string& name, int sixeX, int sizeY); Resource<FrameBuffer> createFrameBuffer(std::string& name, int sixeX, int sizeY);
} // namespace Scripting } // namespace Scripting
} // namespace Deer } // namespace Deer

View File

@ -32,12 +32,9 @@ namespace Deer {
AS_CHECK(scriptEngine->RegisterObjectType("Texture", sizeof(Resource<Texture>), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_ALLINTS | asGetTypeTraits<Resource<Texture>>())); AS_CHECK(scriptEngine->RegisterObjectType("Texture", sizeof(Resource<Texture>), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_ALLINTS | asGetTypeTraits<Resource<Texture>>()));
AS_CHECK(scriptEngine->RegisterObjectType("FrameBuffer", sizeof(Resource<FrameBuffer>), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_ALLINTS | asGetTypeTraits<Resource<FrameBuffer>>())); AS_CHECK(scriptEngine->RegisterObjectType("FrameBuffer", sizeof(Resource<FrameBuffer>), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_ALLINTS | asGetTypeTraits<Resource<FrameBuffer>>()));
} }
int frameBuffer_getWidth(Resource<FrameBuffer>&);
int frameBuffer_getHeight(Resource<FrameBuffer>&);
void frameBuffer_clearRGBA(int, int, int, int, Resource<FrameBuffer>&);
bool frameBuffer_isValid(Resource<FrameBuffer>&);
void frameBuffer_resize(int, int, Resource<FrameBuffer>&);
Resource<FrameBuffer> createFrameBuffer(const std::string name, int sixeX, int sizeY); Resource<FrameBuffer> createFrameBuffer(const std::string name, int sixeX, int sizeY);
void Scripting::registerResourceFunctions() { void Scripting::registerResourceFunctions() {
@ -46,6 +43,7 @@ namespace Deer {
REGISTER_EXT_OBJECT_METHOD(scriptEngine, "FrameBuffer", "bool isValid()", frameBuffer_isValid); REGISTER_EXT_OBJECT_METHOD(scriptEngine, "FrameBuffer", "bool isValid()", frameBuffer_isValid);
REGISTER_EXT_OBJECT_METHOD(scriptEngine, "FrameBuffer", "void resize(int, int)", frameBuffer_resize); REGISTER_EXT_OBJECT_METHOD(scriptEngine, "FrameBuffer", "void resize(int, int)", frameBuffer_resize);
REGISTER_EXT_OBJECT_METHOD(scriptEngine, "FrameBuffer", "void clearRGBA(int, int, int, int)", frameBuffer_clearRGBA); REGISTER_EXT_OBJECT_METHOD(scriptEngine, "FrameBuffer", "void clearRGBA(int, int, int, int)", frameBuffer_clearRGBA);
REGISTER_EXT_OBJECT_METHOD(scriptEngine, "FrameBuffer", "void drawMesh(GPUMesh, Shader, Transform, WorldCamera)", frameBuffer_drawMesh);
scriptEngine->SetDefaultNamespace("Resource"); scriptEngine->SetDefaultNamespace("Resource");
REGISTER_GLOBAL_FUNC(scriptEngine, "FrameBuffer createFrameBuffer(string&in name, int sizeX, int sizeY)", createFrameBuffer); REGISTER_GLOBAL_FUNC(scriptEngine, "FrameBuffer createFrameBuffer(string&in name, int sizeX, int sizeY)", createFrameBuffer);

View File

@ -1,89 +0,0 @@
[Window][DockSpace Demo]
Pos=0,0
Size=2560,1371
Collapsed=0
[Window][Debug##Default]
Pos=60,60
Size=400,400
Collapsed=0
[Window][Terrain Editor]
Pos=925,24
Size=355,434
Collapsed=0
DockId=0x00000005,0
[Window][Viewport]
Pos=369,24
Size=554,434
Collapsed=0
DockId=0x00000005,0
[Window][ViewportPanel]
Pos=389,28
Size=1689,1008
Collapsed=0
DockId=0x00000005,0
[Window][ShaderExplorer]
Pos=0,413
Size=1280,307
Collapsed=0
DockId=0x00000004,0
[Window][TreePanel]
Pos=0,28
Size=387,1008
Collapsed=0
DockId=0x00000001,0
[Window][MeshExplorer]
Pos=0,439
Size=1280,281
Collapsed=0
DockId=0x00000004,0
[Window][PropertiesPanel]
Pos=2080,28
Size=480,1008
Collapsed=0
DockId=0x00000006,0
[Window][CameraPanel]
Pos=265,24
Size=702,477
Collapsed=0
DockId=0x00000005,1
[Window][MU]
Pos=60,60
Size=40,64
Collapsed=0
[Window][Rename entity]
Pos=398,235
Size=643,74
Collapsed=0
[Window][Test]
Pos=423,24
Size=1682,1012
Collapsed=0
DockId=0x00000005,2
[Window][AssetExplorer]
Pos=0,1038
Size=2560,333
Collapsed=0
DockId=0x00000004,0
[Docking][Data]
DockSpace ID=0xA1672E74 Window=0x4647B76E Pos=0,28 Size=2560,1343 Split=Y Selected=0x34A4C10F
DockNode ID=0x00000003 Parent=0xA1672E74 SizeRef=1280,1008 Split=X
DockNode ID=0x00000001 Parent=0x00000003 SizeRef=387,696 Selected=0xE45B9F93
DockNode ID=0x00000002 Parent=0x00000003 SizeRef=2171,696 Split=X Selected=0x34A4C10F
DockNode ID=0x00000005 Parent=0x00000002 SizeRef=1689,1078 CentralNode=1 Selected=0x34A4C10F
DockNode ID=0x00000006 Parent=0x00000002 SizeRef=480,1078 Selected=0xA35A27E3
DockNode ID=0x00000004 Parent=0xA1672E74 SizeRef=1280,333 Selected=0x21191D0B

View File

@ -0,0 +1,32 @@
namespace Previewer {
FrameBuffer getMeshPreview(GPUMesh mesh) {
FrameBuffer frame = Resource::createFrameBuffer(mesh.path, 128, 128);
frame.clearRGBA(0, 0, 0, 255);
WorldCamera wcamera;
wcamera.transform.position = vec3(0, 1, -3.5);
Transform transform;
transform.rotation.setEuler(vec3(0, 135, 0));
Shader shader = Builtin::simpleShader();
frame.drawMesh(mesh, shader, transform, wcamera);
return frame;
}
FrameBuffer getShaderPreview(Shader shader) {
FrameBuffer frame = Resource::createFrameBuffer(shader.path, 128, 128);
frame.clearRGBA(0, 0, 0, 0);
WorldCamera wcamera;
wcamera.transform.rotation.setEuler(vec3(0, 0, 0));
wcamera.transform.position = vec3(0, 0, -1.55);
Transform transform;
GPUMesh mesh = Builtin::sphere();
frame.drawMesh(mesh, shader, transform, wcamera);
return frame;
}
}

View File

@ -1,7 +1,73 @@
bool allowRender = false;
class MeshResource {
string displayName;
string path;
GPUMesh meshResource;
FrameBuffer frameBuffer;
bool loaded = false;
MeshResource(string _meshPath) {
path = _meshPath;
}
void render() {
if (!loaded) {
if (allowRender) {
meshResource = StudioAPI::loadGPUMesh(path);
frameBuffer = Previewer::getMeshPreview(meshResource);
displayName = meshResource.name;
allowRender = false;
loaded = true;
} else {
ImGui::text("Loading");
return;
}
}
ImGui::cartIconButton(displayName, frameBuffer, 128, ImGui::getAvailableSizeX());
ImGui::dragDropSource("MESH", any(meshResource), displayName);
}
}
class ShaderResource {
string displayName;
string path;
Shader shaderResource;
FrameBuffer frameBuffer;
bool loaded = false;
ShaderResource(string _path) {
path = _path;
}
void render() {
if (!loaded) {
if (allowRender) {
shaderResource = StudioAPI::loadShader(path);
frameBuffer = Previewer::getShaderPreview(shaderResource);
displayName = shaderResource.name;
allowRender = false;
loaded = true;
} else {
ImGui::text("Loading");
return;
}
}
ImGui::cartIconButton(displayName, frameBuffer, 128, ImGui::getAvailableSizeX());
ImGui::dragDropSource("SHADER", any(shaderResource), displayName);
}
}
class ResourceExplorer : Panel { class ResourceExplorer : Panel {
string selectedResource = ""; string selectedResource = "";
string currentPath = ""; string currentPath = "";
array<string> subFolders; array<string> subFolders;
array<MeshResource@> meshes;
array<ShaderResource@> shaders;
array<string> subFiles; array<string> subFiles;
bool alreadyRendered = false; bool alreadyRendered = false;
float fase = 0; float fase = 0;
@ -9,7 +75,6 @@ class ResourceExplorer : Panel {
dictionary meshFrameBuffer; dictionary meshFrameBuffer;
void onInit() { void onInit() {
print("hy");
setPath(""); setPath("");
} }
@ -18,11 +83,23 @@ class ResourceExplorer : Panel {
currentPath = path; currentPath = path;
subFolders = StudioAPI::getResourceFolders(path); subFolders = StudioAPI::getResourceFolders(path);
subFiles = StudioAPI::getResourceFiles(path); subFiles = StudioAPI::getResourceFiles(path);
fase = 0; meshes = array<MeshResource@>(0);
shaders = array<ShaderResource@>(0);
for ( uint i = 0; i < subFiles.length(); i++) {
ResourceType resType = StudioAPI::getResourceType(subFiles[i]);
if (resType == ResourceType::Mesh) {
MeshResource@ meshRes = @MeshResource(subFiles[i]);
meshes.insertLast(@meshRes);
}
if (resType == ResourceType::Shader) {
ShaderResource@ shaderRes = @ShaderResource(subFiles[i]);
shaders.insertLast(@shaderRes);
}
}
} }
void onImGui() { void onImGui() {
alreadyRendered = false;
renderMenuBar(); renderMenuBar();
ImGui::space(); ImGui::space();
fase += 0.3; fase += 0.3;
@ -39,36 +116,27 @@ class ResourceExplorer : Panel {
ImGui::nextColumn(); ImGui::nextColumn();
} }
for ( uint i = 0; i < subFiles.length(); i++) { allowRender = true;
drawResource(subFiles[i]); for ( uint i = 0; i < meshes.length(); i++) {
meshes[i].render();
ImGui::nextColumn();
} }
for ( uint i = 0; i < shaders.length(); i++) {
shaders[i].render();
ImGui::nextColumn();
}
} }
void drawResource(string&in filename) { void drawResource(string&in filename) {
ResourceType resType = StudioAPI::getResourceType(filename); ResourceType resType = StudioAPI::getResourceType(filename);
bool selected = filename == selectedResource; bool selected = filename == selectedResource;
if (resType == ResourceType::Mesh) {
FrameBuffer frameBuffer;
GPUMesh mesh = StudioAPI::loadGPUMesh(filename);
//frameBuffer = Previewer::renderMeshPreview_fase(mesh, fase);
meshFrameBuffer[filename] = frameBuffer;
alreadyRendered = true;
Texture mesTexture = StudioAPI::loadIcon("mesh.png");
if (ImGui::cartIconButton(Path::getName(filename), mesTexture, 128, ImGui::getAvailableSizeX())) {
selectedResource = filename;
}
ImGui::dragDropSource("MESH", any(mesh), filename);
ImGui::nextColumn();
return;
}
if (resType == ResourceType::Shader) { if (resType == ResourceType::Shader) {
Texture shaderTexture = StudioAPI::loadIcon("shader.png"); Texture shaderTexture = StudioAPI::loadIcon("shader.png");
Shader shader = StudioAPI::loadShader(filename); Shader shader = StudioAPI::loadShader(filename);
if (ImGui::cartIconButton(Path::getName(filename), shaderTexture, 128, ImGui::getAvailableSizeX())) { FrameBuffer frame = Previewer::getShaderPreview(shader);
if (ImGui::cartIconButton(Path::getName(filename), frame, 128, ImGui::getAvailableSizeX())) {
selectedResource = filename; selectedResource = filename;
} }
ImGui::dragDropSource("SHADER", any(shader), filename); ImGui::dragDropSource("SHADER", any(shader), filename);
@ -92,7 +160,7 @@ class ResourceExplorer : Panel {
} }
void renderMenuBar() { void renderMenuBar() {
// If we select that path // If we select that path
if (ImGui::button("Resources")) { if (ImGui::button("Resources")) {
setPath(""); setPath("");
} }

View File

@ -184,6 +184,10 @@ class TreePanel : Panel {
} }
void onMenuBar() { void onMenuBar() {
if (!(rootNode is null)) {
ImGui::subMenu("Entiy", SimpleFunction(rootNode.renderContextMenu));
}
if (ImGui::menuItem("Refresh")) { if (ImGui::menuItem("Refresh")) {
infoChanged = true; infoChanged = true;
networkBehaviourFilter = EntityNetworkBehaviour::Parent; networkBehaviourFilter = EntityNetworkBehaviour::Parent;

View File

@ -30,14 +30,14 @@ class ViewportPanel : Panel {
if (!ImGui::isPanelActive()) if (!ImGui::isPanelActive())
return; return;
if (ImGui::isMouseDragging(key::MouseRight) && !ImGui::isKeyDown(key::MouseMiddle)) { if (ImGui::isMouseDragging(key::MouseLeft) && !ImGui::isKeyDown(key::MouseMiddle)) {
pitch += ImGui::getMouseDeltaY() * 0.1; pitch += ImGui::getMouseDeltaY() * 0.1;
yaw += ImGui::getMouseDeltaX() * 0.1; yaw += ImGui::getMouseDeltaX() * 0.1;
sceneCamera.transform.rotation.setEuler(vec3(pitch, yaw, 0)); sceneCamera.transform.rotation.setEuler(vec3(pitch, yaw, 0));
} }
if (ImGui::isMouseDragging(key::MouseMiddle) && !ImGui::isKeyDown(key::MouseRight)) { if (ImGui::isMouseDragging(key::MouseMiddle) && !ImGui::isKeyDown(key::MouseLeft)) {
vec3 panDir = vec3(); vec3 panDir = vec3();
panDir.x -= ImGui::getMouseDeltaX(); panDir.x -= ImGui::getMouseDeltaX();

View File

@ -0,0 +1,83 @@
#type vertex
#version 410 core
// Vertex attributes
layout(location = 0) in vec3 v_position;
layout(location = 1) in vec3 v_normal;
layout(location = 2) in vec2 v_UV;
// Outputs to fragment shader
out vec3 normalWS;
out vec3 normalVS;
out vec3 positionVS;
// Uniforms
uniform mat4 u_worldMatrix;
uniform mat4 u_viewMatrix;
void main()
{
gl_Position = u_viewMatrix * u_worldMatrix * vec4(v_position, 1.0);
positionVS = gl_Position.xyz;
mat3 normalMatrix = transpose(inverse(mat3(u_worldMatrix)));
normalWS = normalize(normalMatrix * v_normal);
mat3 normalMatrixView = transpose(inverse(mat3(u_viewMatrix * u_worldMatrix)));
normalVS = normalize(normalMatrixView * v_normal);
}
#type fragment
#version 410 core
// Fragment outputs
layout(location = 0) out vec4 fragColor;
layout(location = 1) out int objectID;
// Inputs from vertex shader
in vec3 normalWS;
in vec3 normalVS;
in vec3 positionVS;
// Uniforms
uniform int u_objectID;
void main()
{
// Directional light
vec3 lightDir = normalize(vec3(1.0, 7.0, 3.0));
// Base light intensity
float light = clamp(dot(normalWS, lightDir) * 0.8 + 0.2, 0.0, 1.0);
// Gradient from purple (dark) to cyan (lit)
vec3 gradientColor = mix(
vec3(0.7137, 0.4471, 0.9412),
vec3(0.5255, 0.9725, 1.0),
light
);
// Rim/fresnel effect
float rim = 0.5 - dot(normalWS, normalize(lightDir)) * 0.5;
float rimValue = rim * rim * rim * rim;
vec3 rimColor = vec3(1.0, 0.8, 0.5) * (rim * rim * rim * rim);
vec3 mixedColor = mix(
gradientColor,
vec3(1, 1, 1) ,
rimValue
);
//float fresnel = dot(, vec3(0, 0, -1));
//fresnel = fresnel * fresnel;
float fresnel = 1 + dot(normalize(positionVS), normalize(normalVS));
fresnel = fresnel * fresnel * fresnel * fresnel;
// Combine everything
fragColor = vec4(mixedColor + vec3(fresnel, fresnel, fresnel), 1.0);
// Object ID output
objectID = u_objectID;
}

View File

@ -0,0 +1,83 @@
#type vertex
#version 410 core
// Vertex attributes
layout(location = 0) in vec3 v_position;
layout(location = 1) in vec3 v_normal;
layout(location = 2) in vec2 v_UV;
// Outputs to fragment shader
out vec3 normalWS;
out vec3 normalVS;
out vec3 positionVS;
// Uniforms
uniform mat4 u_worldMatrix;
uniform mat4 u_viewMatrix;
void main()
{
gl_Position = u_viewMatrix * u_worldMatrix * vec4(v_position, 1.0);
positionVS = gl_Position.xyz;
mat3 normalMatrix = transpose(inverse(mat3(u_worldMatrix)));
normalWS = normalize(normalMatrix * v_normal);
mat3 normalMatrixView = transpose(inverse(mat3(u_viewMatrix * u_worldMatrix)));
normalVS = normalize(normalMatrixView * v_normal);
}
#type fragment
#version 410 core
// Fragment outputs
layout(location = 0) out vec4 fragColor;
layout(location = 1) out int objectID;
// Inputs from vertex shader
in vec3 normalWS;
in vec3 normalVS;
in vec3 positionVS;
// Uniforms
uniform int u_objectID;
void main()
{
// Directional light
vec3 lightDir = normalize(vec3(1.0, 7.0, 3.0));
// Base light intensity
float light = clamp(dot(normalWS, lightDir) * 0.8 + 0.2, 0.0, 1.0);
// Gradient from purple (dark) to cyan (lit)
vec3 gradientColor = mix(
vec3(0.3137, 0.2471, 0.5412),
vec3(0.5255, 0.9725, 1.0),
light
);
// Rim/fresnel effect
float rim = 0.5 - dot(normalWS, normalize(lightDir)) * 0.5;
float rimValue = rim * rim * rim * rim;
vec3 rimColor = vec3(1.0, 0.8, 0.5) * (rim * rim * rim * rim);
vec3 mixedColor = mix(
gradientColor,
vec3(1, 1, 1) ,
rimValue
);
//float fresnel = dot(, vec3(0, 0, -1));
//fresnel = fresnel * fresnel;
float fresnel = 1 + dot(normalize(positionVS), normalize(normalVS));
fresnel = fresnel * fresnel * fresnel * fresnel;
// Combine everything
fragColor = vec4(mixedColor + vec3(fresnel, fresnel, fresnel), 1.0);
// Object ID output
objectID = u_objectID;
}

View File

@ -1,6 +1,6 @@
[Window][DockSpace Demo] [Window][DockSpace Demo]
Pos=0,0 Pos=0,0
Size=2560,1371 Size=1920,1011
Collapsed=0 Collapsed=0
[Window][Debug##Default] [Window][Debug##Default]
@ -8,66 +8,36 @@ Pos=60,60
Size=400,400 Size=400,400
Collapsed=0 Collapsed=0
[Window][TreePanel] [Window][ViewportPanel]
Pos=0,26 Pos=561,26
Size=569,925 Size=934,493
Collapsed=0 Collapsed=0
DockId=0x00000005,0 DockId=0x00000005,0
[Window][PropertiesPanel] [Window][PropertiesPanel]
Pos=1872,26 Pos=1497,26
Size=688,925 Size=423,493
Collapsed=0
DockId=0x00000002,0
[Window][ResourceExplorer]
Pos=0,953
Size=2560,418
Collapsed=0
DockId=0x00000004,0
[Window][ViewportPanel]
Pos=571,26
Size=1299,925
Collapsed=0 Collapsed=0
DockId=0x00000006,0 DockId=0x00000006,0
[Window][Rename entity] [Window][ResourceExplorer]
Pos=848,548 Pos=0,521
Size=306,133 Size=1920,490
Collapsed=0 Collapsed=0
DockId=0x00000004,0
[Window][RENAME_ENTITY_1] [Window][TreePanel]
Pos=755,542 Pos=0,26
Size=380,90 Size=559,493
Collapsed=0 Collapsed=0
DockId=0x00000001,0
[Window][Dear ImGui Demo]
Pos=571,26
Size=1299,925
Collapsed=0
DockId=0x00000006,1
[Window][Dear ImGui Demo/ResizableChild_478B81A3]
IsChild=1
Size=1167,176
[Window][Dear ImGui Demo/Red_BEEF922B]
IsChild=1
Size=200,100
[Window][Dear ImGui Style Editor]
Pos=544,26
Size=1262,926
Collapsed=0
DockId=0x00000006,2
[Docking][Data] [Docking][Data]
DockSpace ID=0x0AC2E849 Window=0xD0388BC8 Pos=0,26 Size=2560,1345 Split=Y Selected=0x16E3C1E7 DockSpace ID=0x0AC2E849 Window=0xD0388BC8 Pos=0,26 Size=1920,985 Split=Y
DockNode ID=0x00000003 Parent=0x0AC2E849 SizeRef=2560,926 Split=X DockNode ID=0x00000003 Parent=0x0AC2E849 SizeRef=1920,493 Split=X
DockNode ID=0x00000001 Parent=0x00000003 SizeRef=1230,1336 Split=X Selected=0x16E3C1E7 DockNode ID=0x00000001 Parent=0x00000003 SizeRef=559,985 Selected=0x16E3C1E7
DockNode ID=0x00000005 Parent=0x00000001 SizeRef=569,572 CentralNode=1 Selected=0x16E3C1E7 DockNode ID=0x00000002 Parent=0x00000003 SizeRef=1359,985 Split=X
DockNode ID=0x00000006 Parent=0x00000001 SizeRef=1299,572 Selected=0x0F5FFC8C DockNode ID=0x00000005 Parent=0x00000002 SizeRef=934,493 CentralNode=1 Selected=0x0F5FFC8C
DockNode ID=0x00000002 Parent=0x00000003 SizeRef=688,1336 Selected=0x9876A79B DockNode ID=0x00000006 Parent=0x00000002 SizeRef=423,493 Selected=0x9876A79B
DockNode ID=0x00000004 Parent=0x0AC2E849 SizeRef=2560,418 Selected=0x018A0F9B DockNode ID=0x00000004 Parent=0x0AC2E849 SizeRef=1920,490 Selected=0x018A0F9B