stuff, profiler update. uk, particles
This commit is contained in:
parent
549dac776a
commit
494aeeb072
46
imgui.ini
46
imgui.ini
@ -27,7 +27,7 @@ DockId=0x00000009,0
|
||||
|
||||
[Window][Viewport]
|
||||
Pos=344,19
|
||||
Size=1576,535
|
||||
Size=1576,495
|
||||
Collapsed=0
|
||||
DockId=0x0000000B,0
|
||||
|
||||
@ -36,14 +36,14 @@ Size=1920,19
|
||||
Collapsed=0
|
||||
|
||||
[Window][Performance Info]
|
||||
Pos=1588,840
|
||||
Size=332,118
|
||||
Pos=1588,867
|
||||
Size=332,310
|
||||
Collapsed=0
|
||||
DockId=0x00000003,0
|
||||
DockId=0x00000006,0
|
||||
|
||||
[Window][Console]
|
||||
Pos=344,840
|
||||
Size=612,337
|
||||
Pos=344,867
|
||||
Size=612,310
|
||||
Collapsed=0
|
||||
DockId=0x0000000D,0
|
||||
|
||||
@ -54,8 +54,8 @@ Collapsed=0
|
||||
DockId=0x0000000B,1
|
||||
|
||||
[Window][Profiler]
|
||||
Pos=344,556
|
||||
Size=1576,282
|
||||
Pos=344,516
|
||||
Size=1576,349
|
||||
Collapsed=0
|
||||
DockId=0x0000000C,0
|
||||
|
||||
@ -78,31 +78,29 @@ Collapsed=0
|
||||
DockId=0x00000005,1
|
||||
|
||||
[Window][Color Correction]
|
||||
Pos=1588,960
|
||||
Size=332,217
|
||||
Pos=0,19
|
||||
Size=342,662
|
||||
Collapsed=0
|
||||
DockId=0x00000004,0
|
||||
DockId=0x00000009,1
|
||||
|
||||
[Window][Asset Browser]
|
||||
Pos=958,840
|
||||
Size=628,337
|
||||
Pos=958,867
|
||||
Size=628,310
|
||||
Collapsed=0
|
||||
DockId=0x0000000E,0
|
||||
|
||||
[Docking][Data]
|
||||
DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1920,1158 Split=X
|
||||
DockNode ID=0x00000001 Parent=0x11111111 SizeRef=342,701 Split=Y Selected=0x12EF0F59
|
||||
DockNode ID=0x00000009 Parent=0x00000001 SizeRef=385,662 HiddenTabBar=1 Selected=0x12EF0F59
|
||||
DockNode ID=0x00000009 Parent=0x00000001 SizeRef=385,662 Selected=0x12EF0F59
|
||||
DockNode ID=0x0000000A Parent=0x00000001 SizeRef=385,494 HiddenTabBar=1 Selected=0x36DC96AB
|
||||
DockNode ID=0x00000002 Parent=0x11111111 SizeRef=1576,701 Split=Y Selected=0xC450F867
|
||||
DockNode ID=0x00000007 Parent=0x00000002 SizeRef=606,819 Split=Y Selected=0xC450F867
|
||||
DockNode ID=0x0000000B Parent=0x00000007 SizeRef=1576,535 CentralNode=1 HiddenTabBar=1 Selected=0xC450F867
|
||||
DockNode ID=0x0000000C Parent=0x00000007 SizeRef=1576,282 HiddenTabBar=1 Selected=0x9B5D3198
|
||||
DockNode ID=0x00000008 Parent=0x00000002 SizeRef=606,337 Split=X Selected=0x9B5D3198
|
||||
DockNode ID=0x00000005 Parent=0x00000008 SizeRef=737,481 Split=X Selected=0x9B5D3198
|
||||
DockNode ID=0x0000000D Parent=0x00000005 SizeRef=363,248 HiddenTabBar=1 Selected=0xEA83D666
|
||||
DockNode ID=0x0000000E Parent=0x00000005 SizeRef=372,248 HiddenTabBar=1 Selected=0x36AF052B
|
||||
DockNode ID=0x00000006 Parent=0x00000008 SizeRef=197,481 Split=Y Selected=0x3FC1A724
|
||||
DockNode ID=0x00000003 Parent=0x00000006 SizeRef=226,118 HiddenTabBar=1 Selected=0x3FC1A724
|
||||
DockNode ID=0x00000004 Parent=0x00000006 SizeRef=226,217 HiddenTabBar=1 Selected=0xA873C17F
|
||||
DockNode ID=0x00000007 Parent=0x00000002 SizeRef=606,846 Split=Y Selected=0xC450F867
|
||||
DockNode ID=0x0000000B Parent=0x00000007 SizeRef=1576,495 CentralNode=1 HiddenTabBar=1 Selected=0xC450F867
|
||||
DockNode ID=0x0000000C Parent=0x00000007 SizeRef=1576,349 HiddenTabBar=1 Selected=0x9B5D3198
|
||||
DockNode ID=0x00000008 Parent=0x00000002 SizeRef=606,310 Split=X Selected=0x9B5D3198
|
||||
DockNode ID=0x00000005 Parent=0x00000008 SizeRef=1242,481 Split=X Selected=0x9B5D3198
|
||||
DockNode ID=0x0000000D Parent=0x00000005 SizeRef=612,248 HiddenTabBar=1 Selected=0xEA83D666
|
||||
DockNode ID=0x0000000E Parent=0x00000005 SizeRef=628,248 HiddenTabBar=1 Selected=0x36AF052B
|
||||
DockNode ID=0x00000006 Parent=0x00000008 SizeRef=332,481 HiddenTabBar=1 Selected=0x3FC1A724
|
||||
|
||||
|
17788
profile_export.json
17788
profile_export.json
File diff suppressed because it is too large
Load Diff
@ -1,2 +1,3 @@
|
||||
[COMPILE] g++ -std=c++20 -Wall -g -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -Isrc/vendor/box2d -IC:/msys64/mingw64/include -Isrc\vendor\imgui -IC:\msys64\mingw64\lib\libyaml-cpp.a -MMD -MP -c src\src\Engine.cpp -o src\build\Engine.o
|
||||
[COMPILE] g++ -std=c++20 -Wall -g -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -Isrc/vendor/box2d -IC:/msys64/mingw64/include -IC:\msys64\mingw64\lib\libyaml-cpp.a -Isrc\vendor\imgui -MMD -MP -c src\src\Engine.cpp -o src\build\Engine.o
|
||||
[LINK] g++ src\build\Engine.o src\build\main.o src\build\Renderer.o src\build\Components\CameraComponent.o src\build\Components\LightComponent.o src\build\Components\ParticleComponent.o src\build\Components\PhysicsComponent.o src\build\Components\ScriptComponent.o src\build\Components\SpriteComponent.o src\build\Components\TextComonent.o src\build\Components\TilemapComponent.o src\build\core\utils\AssetLoader.o src\build\core\utils\EngineConfig.o src\build\core\utils\ExceptionHandler.o src\build\core\utils\FileDialog.o src\build\core\utils\input.o src\build\core\utils\Logging.o src\build\core\utils\Profiler.o src\build\core\utils\utils.o src\build\editor\windows\AssetBrowser.o src\build\editor\windows\Inspector.o src\build\Entitys\Object.o src\build\utils\GameObjectsList.o src\build\utils\Shader.o src\build\utils\UID.o src\build\lapi.o src\build\lauxlib.o src\build\lbaselib.o src\build\lcode.o src\build\lcorolib.o src\build\lctype.o src\build\ldblib.o src\build\ldebug.o src\build\ldo.o src\build\ldump.o src\build\lfunc.o src\build\lgc.o src\build\linit.o src\build\liolib.o src\build\llex.o src\build\lmathlib.o src\build\lmem.o src\build\loadlib.o src\build\lobject.o src\build\lopcodes.o src\build\loslib.o src\build\lparser.o src\build\lstate.o src\build\lstring.o src\build\lstrlib.o src\build\ltable.o src\build\ltablib.o src\build\ltm.o src\build\lua.o src\build\luac.o src\build\lundump.o src\build\lutf8lib.o src\build\lvm.o src\build\lzio.o src\build\imgui.o src\build\imgui_demo.o src\build\imgui_draw.o src\build\imgui_impl_glfw.o src\build\imgui_impl_opengl3.o src\build\imgui_tables.o src\build\imgui_widgets.o src\build\aabb.o src\build\arena_allocator.o src\build\array.o src\build\bitset.o src\build\body.o src\build\broad_phase.o src\build\constraint_graph.o src\build\contact.o src\build\contact_solver.o src\build\core.o src\build\distance.o src\build\distance_joint.o src\build\dynamic_tree.o src\build\geometry.o src\build\hull.o src\build\id_pool.o src\build\island.o src\build\joint.o src\build\manifold.o src\build\math_functions.o src\build\motor_joint.o src\build\mouse_joint.o src\build\mover.o src\build\prismatic_joint.o src\build\revolute_joint.o src\build\sensor.o src\build\shape.o src\build\solver.o src\build\solver_set.o src\build\table.o src\build\timer.o src\build\types.o src\build\weld_joint.o src\build\wheel_joint.o src\build\world.o -o src\build\app.exe -LC:\msys64\mingw64\lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto
|
||||
[RUN] Executed app.exe successfully.
|
||||
|
81
src/assets/scenes/Fire.cene
Normal file
81
src/assets/scenes/Fire.cene
Normal file
@ -0,0 +1,81 @@
|
||||
engine_version: 0.1.0
|
||||
scene_name: Fire
|
||||
scene_hash: 815bf9a2e3aaeb3f7898921c2f69042b5a314460409a7b2a6251719d479dd3f9
|
||||
format_version: 1
|
||||
objects:
|
||||
- name: Ground
|
||||
uid: 5c4cf2d6c88d44468a8ea6f9caf56740
|
||||
id: 226
|
||||
position: [0, 0]
|
||||
rotation: 0
|
||||
layer: 0
|
||||
visable: true
|
||||
components:
|
||||
- type: SpriteComponent
|
||||
texture: C:\Users\spenc\OneDrive\Pictures\textures\ganges_river_pebbles_diff_1k.png
|
||||
normalMap: C:\Users\spenc\OneDrive\Pictures\textures\ganges_river_pebbles_nor_gl_1k.png
|
||||
renderType: Lit
|
||||
children: []
|
||||
- name: Camera
|
||||
uid: 143107e596db4a818088a81cda665c71
|
||||
id: 227
|
||||
position: [-900, 0]
|
||||
rotation: 0
|
||||
layer: 0
|
||||
visable: true
|
||||
components:
|
||||
- type: CameraComponent
|
||||
fov: 45
|
||||
aspect: 1.76999998
|
||||
zoom: 1
|
||||
primary: true
|
||||
children: []
|
||||
- name: Light
|
||||
uid: 84bffd029cd444f7b6220dc7d1b773d9
|
||||
id: 232
|
||||
position: [-1024, 0]
|
||||
rotation: 0
|
||||
layer: 0
|
||||
visable: true
|
||||
components:
|
||||
- type: LightComponent
|
||||
color:
|
||||
- 1
|
||||
- 0.0882352591
|
||||
- 0
|
||||
intensity: 0.349999994
|
||||
radius: 999
|
||||
falloff: 1
|
||||
type: 0
|
||||
children: []
|
||||
- name: Fire
|
||||
uid: bebfceeddc754dba94ea936feb49ebda
|
||||
id: 233
|
||||
position: [-1024, 277]
|
||||
rotation: 0
|
||||
layer: 0
|
||||
visable: true
|
||||
components:
|
||||
- type: ParticleComponent
|
||||
maxParticles: 1000
|
||||
emissionRate: 100
|
||||
lifeMin: 0.5
|
||||
lifeMax: 1.5
|
||||
sizeMin: 5
|
||||
sizeMax: 75
|
||||
speedMin: 100
|
||||
speedMax: 660
|
||||
direction: [0, -1]
|
||||
spread: 0.800000012
|
||||
startColor: [1, 0, 0, 1]
|
||||
endColor: [0.882352948, 1, 0, 1]
|
||||
loop: true
|
||||
burst: false
|
||||
children: []
|
||||
color_correction:
|
||||
brightness: 2
|
||||
saturation: 2
|
||||
gamma: 1.05999994
|
||||
bloom: true
|
||||
intensity: 1.40999997
|
||||
threshold: 0.300000012
|
@ -1,6 +1,6 @@
|
||||
engine_version: 0.1.0
|
||||
scene_name: lighting_test_2
|
||||
scene_hash: f1652fd7fe4a93ec56d94e4c343609bbce35d5190f9badd04e281fa8404eeaed
|
||||
scene_hash: 6622c33531e5f56eb45af8ba16579b92f107df240dda01c57391813a98dbb3cb
|
||||
format_version: 1
|
||||
objects:
|
||||
- name: Tiles
|
||||
@ -115,7 +115,7 @@ objects:
|
||||
- name: Red
|
||||
uid: 6afde2dd47aa4557b6afb1a607c99dc8
|
||||
id: 13
|
||||
position: [702.594421, 1407.01233]
|
||||
position: [818.390869, 568.231567]
|
||||
rotation: 0
|
||||
layer: 2
|
||||
visable: true
|
||||
@ -133,7 +133,7 @@ objects:
|
||||
- name: Green
|
||||
uid: 0f950d76d24b4dc18f54cab2c3aaaf9a
|
||||
id: 14
|
||||
position: [853.004333, 554.148438]
|
||||
position: [1521.5116, 1073.82153]
|
||||
rotation: 0
|
||||
layer: 2
|
||||
visable: true
|
||||
@ -151,7 +151,7 @@ objects:
|
||||
- name: Blue
|
||||
uid: 09f722f51c7c4b0f98de3a0a16d127c4
|
||||
id: 15
|
||||
position: [1516.40125, 1110.83923]
|
||||
position: [732.097473, 1429.9469]
|
||||
rotation: 0
|
||||
layer: 2
|
||||
visable: true
|
||||
@ -209,6 +209,78 @@ objects:
|
||||
zoom: 1
|
||||
primary: true
|
||||
children: []
|
||||
- name: Flower Peddels
|
||||
uid: 20b09854d73f4928860c608c7b143f3f
|
||||
id: 16
|
||||
position: [397, 852]
|
||||
rotation: 0
|
||||
layer: 0
|
||||
visable: true
|
||||
components:
|
||||
- type: ParticleComponent
|
||||
maxParticles: 1000
|
||||
emissionRate: 100
|
||||
lifeMin: 5
|
||||
lifeMax: 10
|
||||
sizeMin: 1
|
||||
sizeMax: 10
|
||||
speedMin: 100
|
||||
speedMax: 300
|
||||
direction: [0, 1]
|
||||
spread: 1.57000005
|
||||
startColor: [0, 0.705882311, 1, 1]
|
||||
endColor: [0.792156875, 0, 1, 1]
|
||||
loop: true
|
||||
burst: false
|
||||
children: []
|
||||
- name: Rain
|
||||
uid: 19253834f75d4e69a618c45ddb14e8b0
|
||||
id: 81
|
||||
position: [397, 852]
|
||||
rotation: 0
|
||||
layer: 0
|
||||
visable: true
|
||||
components:
|
||||
- type: ParticleComponent
|
||||
maxParticles: 1000
|
||||
emissionRate: 1000
|
||||
lifeMin: 0.5
|
||||
lifeMax: 1.5
|
||||
sizeMin: 5
|
||||
sizeMax: 10
|
||||
speedMin: 1000
|
||||
speedMax: 3000
|
||||
direction: [0, 1]
|
||||
spread: 0.860000014
|
||||
startColor: [0, 0.647058964, 1, 1]
|
||||
endColor: [0, 0, 1, 0]
|
||||
loop: true
|
||||
burst: false
|
||||
children: []
|
||||
- name: Fire
|
||||
uid: 995af3d194694309a490504eaee3ae92
|
||||
id: 116
|
||||
position: [458, 2244]
|
||||
rotation: 0
|
||||
layer: 0
|
||||
visable: true
|
||||
components:
|
||||
- type: ParticleComponent
|
||||
maxParticles: 1000
|
||||
emissionRate: 251
|
||||
lifeMin: 0.5
|
||||
lifeMax: 1.5
|
||||
sizeMin: 5
|
||||
sizeMax: 98.3000031
|
||||
speedMin: 100
|
||||
speedMax: 500
|
||||
direction: [0, -1]
|
||||
spread: 0.419999987
|
||||
startColor: [1, 0.941176474, 0, 1]
|
||||
endColor: [1, 0, 0, 0]
|
||||
loop: true
|
||||
burst: false
|
||||
children: []
|
||||
color_correction:
|
||||
brightness: 2
|
||||
saturation: 2
|
||||
|
@ -55,19 +55,6 @@ void ParticleComponent::Update(float dt)
|
||||
particles.end());
|
||||
}
|
||||
|
||||
void ParticleComponent::Render()
|
||||
{
|
||||
for (const auto &p : particles)
|
||||
{
|
||||
float t = std::clamp(1.0f - (p.life / settings.lifeMax), 0.0f, 1.0f);
|
||||
Color color = core::types::Color::Lerp(settings.startColor, settings.endColor, t);
|
||||
Renderer::DrawQuad(
|
||||
p.position,
|
||||
core::types::Vec2(p.size, p.size),
|
||||
p.rotation,
|
||||
color);
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleComponent::SpawnParticle()
|
||||
{
|
||||
@ -86,14 +73,10 @@ void ParticleComponent::SpawnParticle()
|
||||
|
||||
particles.push_back(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void ParticleComponent::Save(YAML::Emitter &out) const
|
||||
void ParticleComponent::Save(YAML::Emitter& out) const
|
||||
{
|
||||
out << YAML::Key << "ParticleComponent" << YAML::Value << YAML::BeginMap;
|
||||
out << YAML::BeginMap;
|
||||
out << YAML::Key << "type" << YAML::Value << "ParticleComponent";
|
||||
|
||||
out << YAML::Key << "maxParticles" << YAML::Value << settings.maxParticles;
|
||||
out << YAML::Key << "emissionRate" << YAML::Value << settings.emissionRate;
|
||||
@ -107,7 +90,7 @@ void ParticleComponent::Save(YAML::Emitter &out) const
|
||||
out << YAML::Key << "direction" << YAML::Value << YAML::Flow << YAML::BeginSeq << settings.direction.x << settings.direction.y << YAML::EndSeq;
|
||||
out << YAML::Key << "spread" << YAML::Value << settings.spread;
|
||||
|
||||
auto writeColor = [](const Color &c, YAML::Emitter &out)
|
||||
auto writeColor = [](const Color& c, YAML::Emitter& out)
|
||||
{
|
||||
out << YAML::Flow << YAML::BeginSeq << c.r << c.g << c.b << c.a << YAML::EndSeq;
|
||||
};
|
||||
@ -123,40 +106,40 @@ void ParticleComponent::Save(YAML::Emitter &out) const
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ParticleComponent::Load(const YAML::Node &node)
|
||||
void ParticleComponent::Load(const YAML::Node& node)
|
||||
{
|
||||
if (!node["ParticleComponent"] || !node["ParticleComponent"].IsMap())
|
||||
if (!node || !node.IsMap())
|
||||
return;
|
||||
|
||||
const YAML::Node &comp = node["ParticleComponent"];
|
||||
|
||||
auto vec2 = [](const YAML::Node &n)
|
||||
auto vec2 = [](const YAML::Node& n)
|
||||
{
|
||||
if (!n || !n.IsSequence() || n.size() != 2)
|
||||
return Vec2{};
|
||||
return Vec2(n[0].as<float>(), n[1].as<float>());
|
||||
};
|
||||
|
||||
auto color = [](const YAML::Node &n)
|
||||
auto color = [](const YAML::Node& n)
|
||||
{
|
||||
if (!n || !n.IsSequence() || n.size() != 4)
|
||||
return Color{};
|
||||
return Color(n[0].as<float>(), n[1].as<float>(), n[2].as<float>(), n[3].as<float>());
|
||||
};
|
||||
|
||||
if (comp["maxParticles"]) settings.maxParticles = comp["maxParticles"].as<int>();
|
||||
if (comp["emissionRate"]) settings.emissionRate = comp["emissionRate"].as<float>();
|
||||
if (comp["lifeMin"]) settings.lifeMin = comp["lifeMin"].as<float>();
|
||||
if (comp["lifeMax"]) settings.lifeMax = comp["lifeMax"].as<float>();
|
||||
if (comp["sizeMin"]) settings.sizeMin = comp["sizeMin"].as<float>();
|
||||
if (comp["sizeMax"]) settings.sizeMax = comp["sizeMax"].as<float>();
|
||||
if (comp["speedMin"]) settings.speedMin = comp["speedMin"].as<float>();
|
||||
if (comp["speedMax"]) settings.speedMax = comp["speedMax"].as<float>();
|
||||
if (comp["direction"]) settings.direction = vec2(comp["direction"]);
|
||||
if (comp["spread"]) settings.spread = comp["spread"].as<float>();
|
||||
if (comp["startColor"]) settings.startColor = color(comp["startColor"]);
|
||||
if (comp["endColor"]) settings.endColor = color(comp["endColor"]);
|
||||
if (comp["loop"]) settings.loop = comp["loop"].as<bool>();
|
||||
if (comp["burst"]) settings.burst = comp["burst"].as<bool>();
|
||||
settings.maxParticles = node["maxParticles"].as<int>(settings.maxParticles);
|
||||
settings.emissionRate = node["emissionRate"].as<float>(settings.emissionRate);
|
||||
settings.lifeMin = node["lifeMin"].as<float>(settings.lifeMin);
|
||||
settings.lifeMax = node["lifeMax"].as<float>(settings.lifeMax);
|
||||
settings.sizeMin = node["sizeMin"].as<float>(settings.sizeMin);
|
||||
settings.sizeMax = node["sizeMax"].as<float>(settings.sizeMax);
|
||||
settings.speedMin = node["speedMin"].as<float>(settings.speedMin);
|
||||
settings.speedMax = node["speedMax"].as<float>(settings.speedMax);
|
||||
|
||||
if (node["direction"])
|
||||
settings.direction = vec2(node["direction"]);
|
||||
if (node["spread"])
|
||||
settings.spread = node["spread"].as<float>();
|
||||
if (node["startColor"])
|
||||
settings.startColor = color(node["startColor"]);
|
||||
if (node["endColor"])
|
||||
settings.endColor = color(node["endColor"]);
|
||||
if (node["loop"])
|
||||
settings.loop = node["loop"].as<bool>();
|
||||
if (node["burst"])
|
||||
settings.burst = node["burst"].as<bool>();
|
||||
}
|
||||
|
@ -58,7 +58,6 @@ public:
|
||||
|
||||
void Emit();
|
||||
void Update(float dt);
|
||||
void Render();
|
||||
|
||||
private:
|
||||
std::vector<Particle> particles;
|
||||
|
@ -174,94 +174,167 @@ void DrawProfilerTimelineBars(const ProfileNode &node,
|
||||
origin);
|
||||
}
|
||||
|
||||
static ProfileNode GetAveragedFrameCopy(const ProfileNode &src)
|
||||
inline int CountNodes(const ProfileNode &root) noexcept
|
||||
{
|
||||
ProfileNode averaged = src;
|
||||
averaged.visualStartMs = src.startMs;
|
||||
averaged.visualDurationMs = src.durationMs;
|
||||
int count = 0;
|
||||
std::vector<const ProfileNode *> stack;
|
||||
stack.reserve(32);
|
||||
stack.push_back(&root);
|
||||
|
||||
averaged.children.clear();
|
||||
for (const auto &child : src.children)
|
||||
averaged.children.push_back(GetAveragedFrameCopy(child));
|
||||
while (!stack.empty())
|
||||
{
|
||||
const ProfileNode *node = stack.back();
|
||||
stack.pop_back();
|
||||
++count;
|
||||
for (const auto &child : node->children)
|
||||
stack.push_back(&child);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
return averaged;
|
||||
inline ProfileNode GetAveragedFrameCopy(const ProfileNode &src)
|
||||
{
|
||||
ProfileNode avg(src.name, src.startMs);
|
||||
avg.durationMs = src.durationMs;
|
||||
avg.visualStartMs = avg.startMs;
|
||||
avg.visualDurationMs = avg.durationMs;
|
||||
|
||||
const auto &kids = src.children;
|
||||
avg.children.reserve(kids.size());
|
||||
for (const auto &c : kids)
|
||||
avg.children.push_back(GetAveragedFrameCopy(c));
|
||||
|
||||
return avg;
|
||||
}
|
||||
|
||||
void ShowProfilerTimeline()
|
||||
{
|
||||
static ProfileNode cachedAveragedFrame;
|
||||
static double lastUpdateTime = 0.0;
|
||||
static double updateInterval = 0.25;
|
||||
static bool freezeView = false;
|
||||
PROFILE_ENGINE_SCOPE("Engine::ShowProfilerTimeline");
|
||||
|
||||
const double now = ImGui::GetTime();
|
||||
const ProfileNode *latest = profiler.GetLatestFrame();
|
||||
if (!g_engineConfig.settings.profile_enabled)
|
||||
{
|
||||
if (ImGui::Begin("Profiler", nullptr, ImGuiWindowFlags_NoScrollbar))
|
||||
{
|
||||
ImGui::Text("Profiling Disabled.");
|
||||
ImGui::End();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Statics & timing
|
||||
static ProfileNode cachedFrame;
|
||||
static double lastUpdate = 0.0;
|
||||
static float updateInterval = 0.25f;
|
||||
static bool freezeView = false;
|
||||
static float zoom = 1.0f;
|
||||
|
||||
double now = ImGui::GetTime();
|
||||
auto latest = profiler.GetLatestFrame();
|
||||
|
||||
if (!freezeView && latest && now - lastUpdate >= updateInterval)
|
||||
{
|
||||
cachedFrame = GetAveragedFrameCopy(*latest);
|
||||
lastUpdate = now;
|
||||
}
|
||||
|
||||
if (cachedFrame.durationMs <= 0.0)
|
||||
{
|
||||
ImGui::Begin("Profiler", nullptr, ImGuiWindowFlags_NoScrollbar);
|
||||
ImGui::Text("Waiting for profiler data...");
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::Begin("Profiler", nullptr, ImGuiWindowFlags_NoScrollbar);
|
||||
|
||||
// --- Controls ---
|
||||
if (g_engineConfig.settings.profile_enabled)
|
||||
ImGui::Checkbox("Freeze View", &freezeView);
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(120.0f);
|
||||
ImGui::DragFloat("Update Interval", &updateInterval, 0.05f, 0.05f, 5.0f, "%.2fs");
|
||||
|
||||
updateInterval = std::clamp(updateInterval, 0.05f, 5.0f);
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::DragFloat("Zoom", &zoom, 0.1f, 0.1f, 10.0f, "×%.1f");
|
||||
zoom = std::max(0.1f, zoom);
|
||||
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Export"))
|
||||
{
|
||||
ImGui::Checkbox("Freeze View", &freezeView);
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(100);
|
||||
float interval = static_cast<float>(updateInterval);
|
||||
if (ImGui::DragFloat("Update Interval", &interval, 0.05f, 0.05f, 5.0f))
|
||||
updateInterval = interval;
|
||||
|
||||
updateInterval = std::clamp(updateInterval, 0.05, 5.0);
|
||||
|
||||
// Export JSON button
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Export"))
|
||||
json root = SerializeProfileNode(cachedFrame);
|
||||
std::ofstream out("profile_export.json");
|
||||
if (out)
|
||||
{
|
||||
json root = SerializeProfileNode(cachedAveragedFrame);
|
||||
std::ofstream out("profile_export.json");
|
||||
if (out.is_open())
|
||||
{
|
||||
out << root.dump(4);
|
||||
out.close();
|
||||
Logger::LogInfo("Profiler exported to profile_export.json");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::LogError("Failed to write profiler export.");
|
||||
}
|
||||
out << root.dump(4);
|
||||
Logger::LogInfo("Profiler exported to profile_export.json");
|
||||
}
|
||||
|
||||
if (!freezeView && latest && (now - lastUpdateTime) >= updateInterval)
|
||||
else
|
||||
{
|
||||
cachedAveragedFrame = GetAveragedFrameCopy(*latest);
|
||||
lastUpdateTime = now;
|
||||
Logger::LogError("Failed to write profiler export.");
|
||||
}
|
||||
|
||||
if (cachedAveragedFrame.durationMs <= 0.0f)
|
||||
{
|
||||
ImGui::Text("Waiting for profiler data...");
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
const float rowHeight = 24.0f;
|
||||
const float timelineHeight = 400.0f;
|
||||
float frameDuration = cachedAveragedFrame.visualDurationMs;
|
||||
float timelineWidth = ImGui::GetContentRegionAvail().x * 0.95f;
|
||||
|
||||
ImGui::BeginChild("TimelineScroll", ImVec2(0, timelineHeight));
|
||||
ImVec2 origin = ImGui::GetCursorScreenPos();
|
||||
|
||||
DrawProfilerTimelineBars(cachedAveragedFrame, 0, timelineWidth, frameDuration, origin);
|
||||
|
||||
ImGui::Dummy(ImVec2(timelineWidth, 32 * rowHeight));
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::Text("Frame Duration (Avg): %.2f ms | View Update Rate: %.2fs", frameDuration, updateInterval);
|
||||
}
|
||||
else
|
||||
|
||||
// Layout metrics
|
||||
constexpr float rowH = 24.0f;
|
||||
int rows = CountNodes(cachedFrame);
|
||||
float avail = ImGui::GetContentRegionAvail().x;
|
||||
float width = avail * zoom;
|
||||
float height = std::min(rows * rowH, 400.0f);
|
||||
|
||||
// Begin child & get origin
|
||||
ImGui::BeginChild("TimelineScroll", ImVec2(0, height), false, ImGuiWindowFlags_HorizontalScrollbar);
|
||||
ImVec2 origin = ImGui::GetCursorScreenPos();
|
||||
ImDrawList *draw = ImGui::GetWindowDrawList();
|
||||
ImU32 gridCol = ImGui::GetColorU32(ImGuiCol_Border);
|
||||
|
||||
// Cache grid lines so we only recompute when dims change
|
||||
struct Line
|
||||
{
|
||||
ImGui::Text("Profiling Disabled.");
|
||||
ImVec2 a, b;
|
||||
};
|
||||
static float lastW = -1.0f;
|
||||
static int lastR = -1;
|
||||
static std::vector<Line> gridLines;
|
||||
if (lastW != width || lastR != rows)
|
||||
{
|
||||
gridLines.clear();
|
||||
// horizontal
|
||||
for (int r = 0; r <= rows; ++r)
|
||||
{
|
||||
float y = r * rowH;
|
||||
gridLines.push_back({{0, y}, {width, y}});
|
||||
}
|
||||
// vertical
|
||||
float dx = width / 10.0f;
|
||||
for (int i = 0; i <= 10; ++i)
|
||||
{
|
||||
float x = i * dx;
|
||||
gridLines.push_back({{x, 0}, {x, rows * rowH}});
|
||||
}
|
||||
lastW = width;
|
||||
lastR = rows;
|
||||
}
|
||||
|
||||
// Draw cached grid
|
||||
for (auto &ln : gridLines)
|
||||
{
|
||||
draw->AddLine(
|
||||
{origin.x + ln.a.x, origin.y + ln.a.y},
|
||||
{origin.x + ln.b.x, origin.y + ln.b.y},
|
||||
gridCol);
|
||||
}
|
||||
|
||||
// Bars
|
||||
DrawProfilerTimelineBars(cachedFrame, 0, width, cachedFrame.visualDurationMs, origin);
|
||||
|
||||
// Ensure scrollable size
|
||||
ImGui::Dummy(ImVec2(width, rows * rowH));
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::Text("Frame: %.2f ms | Rate: %.2fs",
|
||||
cachedFrame.visualDurationMs,
|
||||
updateInterval);
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
@ -485,7 +558,7 @@ void Engine::collectObjects(bool playing, const glm::vec2 &camPos, float camZoom
|
||||
}
|
||||
|
||||
if (auto particles = obj->GetComponent<ParticleComponent>())
|
||||
m_particleUpdates.push_back(particles.get()); // <-- Collect particle components
|
||||
m_particleUpdates.push_back(particles.get());
|
||||
|
||||
if (playing)
|
||||
{
|
||||
@ -517,46 +590,35 @@ void Engine::Run()
|
||||
profiler.BeginEngineSection("NewFrame");
|
||||
|
||||
profiler.BeginEngineSection("ImGui_ImplOpenGL3_NewFrame");
|
||||
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
|
||||
profiler.EndEngineSection();
|
||||
|
||||
profiler.BeginEngineSection("ImGui_ImplGlfw_NewFrame");
|
||||
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
|
||||
profiler.EndEngineSection();
|
||||
|
||||
profiler.BeginEngineSection("ImGui::NewFrame");
|
||||
|
||||
ImGui::NewFrame();
|
||||
|
||||
profiler.EndEngineSection();
|
||||
|
||||
profiler.BeginEngineSection("ImGui::DockSpaceOverViewport");
|
||||
|
||||
ImGui::DockSpaceOverViewport(ImGui::GetMainViewport()->ID);
|
||||
|
||||
profiler.EndEngineSection();
|
||||
|
||||
profiler.BeginEngineSection("glfwGetTime");
|
||||
|
||||
float currentTime = glfwGetTime();
|
||||
static float lastTime = currentTime;
|
||||
float deltaTime = currentTime - lastTime;
|
||||
lastTime = currentTime;
|
||||
profiler.EndEngineSection();
|
||||
|
||||
profiler.EndEngineSection();
|
||||
profiler.EndEngineSection(); // End NewFrame
|
||||
|
||||
profiler.BeginEngineSection("Engine::ShowDebugOverlay");
|
||||
|
||||
ShowDebugOverlay(deltaTime);
|
||||
profiler.EndEngineSection();
|
||||
|
||||
profiler.BeginEngineSection("Logger::Draw");
|
||||
|
||||
Logger::Draw();
|
||||
profiler.EndEngineSection();
|
||||
|
||||
@ -564,7 +626,6 @@ void Engine::Run()
|
||||
|
||||
if (ImGui::BeginMainMenuBar())
|
||||
{
|
||||
// — left‑aligned items —
|
||||
if (ImGui::Button(playing ? "Stop" : "Play"))
|
||||
{
|
||||
if (!playing)
|
||||
@ -603,7 +664,6 @@ void Engine::Run()
|
||||
|
||||
if (ImGui::BeginMenu("Options"))
|
||||
{
|
||||
|
||||
if (ImGui::BeginMenu("Settings"))
|
||||
{
|
||||
ImGui::Checkbox("Enable Lighting", &g_engineConfig.settings.lighting_enabled);
|
||||
@ -615,7 +675,8 @@ void Engine::Run()
|
||||
if (g_engineConfig.settings.profile_enabled)
|
||||
{
|
||||
ImGui::Checkbox("Profile Engine", &g_engineConfig.settings.profile_editor);
|
||||
ImGui::Checkbox("Deep Profileing", &g_engineConfig.settings.profile_deep);
|
||||
ImGui::Checkbox("Deep Profiling", &g_engineConfig.settings.profile_deep);
|
||||
// ImGui::Checkbox("GPU Profiling", &g_engineConfig.settings.profile_gpu);
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
@ -631,24 +692,20 @@ void Engine::Run()
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
// — right‑aligned version text —
|
||||
const char *version_fmt = "Create Engine v%s";
|
||||
// build the text
|
||||
char buf[64];
|
||||
std::snprintf(buf, sizeof(buf), version_fmt, g_engineConfig.version.c_str());
|
||||
|
||||
// calculate width of the text
|
||||
float textWidth = ImGui::CalcTextSize(buf).x;
|
||||
// move cursor to far right minus padding
|
||||
float avail = ImGui::GetWindowSize().x - ImGui::GetCursorPosX();
|
||||
ImGuiStyle &style = ImGui::GetStyle();
|
||||
ImGui::SameLine(avail - textWidth - style.FramePadding.x);
|
||||
|
||||
ImGui::TextUnformatted(buf);
|
||||
|
||||
ImGui::EndMainMenuBar();
|
||||
}
|
||||
profiler.EndEngineSection();
|
||||
|
||||
profiler.EndEngineSection(); // End BeginMainMenuBar
|
||||
|
||||
if (g_engineConfig.settings.show_color_correction_window)
|
||||
ShowColorCorrectionWindow();
|
||||
@ -690,7 +747,7 @@ void Engine::Run()
|
||||
}
|
||||
|
||||
for (auto &obj : objects)
|
||||
if (!obj->GetParent()) // Only draw root nodes
|
||||
if (!obj->GetParent())
|
||||
DrawObjectNode(obj);
|
||||
|
||||
ImGui::End();
|
||||
@ -698,44 +755,32 @@ void Engine::Run()
|
||||
|
||||
DrawInspectorUI(selected);
|
||||
|
||||
// Viewport
|
||||
ImGui::Begin("Viewport", nullptr, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
|
||||
ImVec2 size = ImGui::GetContentRegionAvail();
|
||||
|
||||
// Save/restore editor camera position/zoom on play toggle
|
||||
static bool lastPlaying = false;
|
||||
|
||||
if (playing && !lastPlaying)
|
||||
{
|
||||
// Entering play mode – save editor camera
|
||||
editorCameraSavedPos = cameraPos;
|
||||
editorCameraSavedZoom = cameraZoom;
|
||||
editorCameraWasSaved = true;
|
||||
}
|
||||
else if (!playing && lastPlaying)
|
||||
else if (!playing && lastPlaying && editorCameraWasSaved)
|
||||
{
|
||||
// Exiting play mode – restore editor camera
|
||||
if (editorCameraWasSaved)
|
||||
{
|
||||
cameraPos = editorCameraSavedPos;
|
||||
cameraZoom = editorCameraSavedZoom;
|
||||
editorCameraWasSaved = false;
|
||||
}
|
||||
cameraPos = editorCameraSavedPos;
|
||||
cameraZoom = editorCameraSavedZoom;
|
||||
editorCameraWasSaved = false;
|
||||
}
|
||||
|
||||
lastPlaying = playing;
|
||||
|
||||
// Use active camera when playing
|
||||
if (playing && m_activeCamera)
|
||||
{
|
||||
cameraPos = m_activeCamera->GetOwner()->GetWorldPosition();
|
||||
cameraZoom = m_activeCamera->GetZoom();
|
||||
}
|
||||
|
||||
// Use editor camera logic when not playing
|
||||
if (!playing && ImGui::IsWindowHovered())
|
||||
{
|
||||
// Pan
|
||||
if (ImGui::IsMouseDragging(ImGuiMouseButton_Right))
|
||||
{
|
||||
ImVec2 delta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Right);
|
||||
@ -743,7 +788,6 @@ void Engine::Run()
|
||||
cameraPos -= glm::vec2(delta.x, delta.y) / cameraZoom;
|
||||
}
|
||||
|
||||
// Zoom
|
||||
float wheel = ImGui::GetIO().MouseWheel;
|
||||
if (wheel != 0.0f)
|
||||
{
|
||||
@ -768,12 +812,10 @@ void Engine::Run()
|
||||
}
|
||||
}
|
||||
|
||||
// Resize
|
||||
profiler.BeginEngineSection("Renderer::Resize");
|
||||
Renderer::Resize((int)size.x, (int)size.y);
|
||||
profiler.EndEngineSection();
|
||||
|
||||
// Begin
|
||||
profiler.BeginEngineSection("Renderer::Begin");
|
||||
Renderer::Begin();
|
||||
profiler.EndEngineSection();
|
||||
@ -786,21 +828,14 @@ void Engine::Run()
|
||||
m_particleUpdates.clear();
|
||||
profiler.EndEngineSection();
|
||||
|
||||
// profiler.BeginEngineSection("Draw Editor Grid");
|
||||
// Renderer::DrawEditorGrid(cameraPos, cameraZoom);
|
||||
// profiler.EndEngineSection();
|
||||
|
||||
// Collect Objects
|
||||
profiler.BeginEngineSection("Collect Objects");
|
||||
collectObjects(playing, cameraPos, cameraZoom);
|
||||
profiler.EndEngineSection();
|
||||
|
||||
profiler.BeginEngineSection("Renderer::UpdateClusterLights");
|
||||
|
||||
Renderer::UpdateClusterLights();
|
||||
profiler.EndEngineSection();
|
||||
|
||||
// Sort Objects
|
||||
profiler.BeginEngineSection("Sort Objects");
|
||||
if (m_toDraw.size() > 1)
|
||||
{
|
||||
@ -814,40 +849,52 @@ void Engine::Run()
|
||||
}
|
||||
profiler.EndEngineSection();
|
||||
|
||||
if (!g_engineConfig.settings.profile_editor)
|
||||
profiler.BeginFrame();
|
||||
|
||||
m_OnUpdateCalls = 0;
|
||||
|
||||
profiler.BeginSection("Script Updates");
|
||||
|
||||
if (!g_engineConfig.settings.profile_editor)
|
||||
{
|
||||
profiler.BeginFrame();
|
||||
}
|
||||
profiler.BeginSection("Updates");
|
||||
|
||||
profiler.BeginSection("Scripts");
|
||||
for (auto *script : m_scriptUpdates)
|
||||
{
|
||||
profiler.BeginSection("Script: " + script->GetOwner()->GetName());
|
||||
profiler.BeginSection("Object: " + script->GetOwner()->GetName());
|
||||
script->OnUpdate(deltaTime);
|
||||
m_OnUpdateCalls++;
|
||||
profiler.EndSection();
|
||||
}
|
||||
profiler.EndSection();
|
||||
|
||||
|
||||
profiler.BeginSection("Particles");
|
||||
for (auto *script : m_particleUpdates)
|
||||
{
|
||||
profiler.BeginSection("Object: " + script->GetOwner()->GetName());
|
||||
script->Update(deltaTime);
|
||||
profiler.EndSection();
|
||||
}
|
||||
profiler.EndSection();
|
||||
|
||||
profiler.EndSection();
|
||||
|
||||
profiler.BeginSection("Render");
|
||||
for (auto *obj : m_toDraw)
|
||||
{
|
||||
// --- Sprite rendering ---
|
||||
const core::types::Vec2 worldPos = obj->GetWorldPosition();
|
||||
|
||||
if (auto spritePtr = obj->GetComponent<SpriteComponent>())
|
||||
{
|
||||
profiler.BeginSection("Draw Sprite: " + obj->GetName());
|
||||
Renderer::DrawSprite(spritePtr.get(),
|
||||
obj->GetWorldPosition(),
|
||||
cameraZoom,
|
||||
cameraPos);
|
||||
Renderer::DrawSprite(spritePtr.get(), worldPos, cameraZoom, cameraPos);
|
||||
profiler.EndSection();
|
||||
}
|
||||
|
||||
// --- Particle rendering ---
|
||||
if (auto particle = obj->GetComponent<ParticleComponent>())
|
||||
{
|
||||
profiler.BeginSection("Draw Particles" + obj->GetName());
|
||||
profiler.BeginSection("Draw Particles: " + obj->GetName());
|
||||
|
||||
const auto &particles = particle->GetParticles();
|
||||
const auto &settings = particle->GetSettings();
|
||||
|
||||
@ -855,11 +902,10 @@ void Engine::Run()
|
||||
{
|
||||
float t = std::clamp(1.0f - (p.life / settings.lifeMax), 0.0f, 1.0f);
|
||||
core::types::Color color = core::types::Color::Lerp(settings.startColor, settings.endColor, t);
|
||||
Renderer::DrawQuad(
|
||||
p.position,
|
||||
core::types::Vec2(p.size, p.size),
|
||||
p.rotation,
|
||||
color);
|
||||
|
||||
core::types::Vec2 pWorld = p.position + particle->GetOwner()->GetWorldPosition();
|
||||
core::types::Vec2 size = core::types::Vec2(p.size, p.size);
|
||||
Renderer::BatchQuad(pWorld, size, p.rotation, color, cameraPos, cameraZoom);
|
||||
}
|
||||
|
||||
profiler.EndSection();
|
||||
@ -867,80 +913,66 @@ void Engine::Run()
|
||||
}
|
||||
profiler.EndSection();
|
||||
|
||||
// Finish frame profiling
|
||||
if (!g_engineConfig.settings.profile_editor)
|
||||
{
|
||||
profiler.EndFrame();
|
||||
}
|
||||
|
||||
// End renderer
|
||||
Renderer::End();
|
||||
|
||||
// Display render target texture
|
||||
profiler.BeginSection("Engine::DrawGameWindow");
|
||||
|
||||
GLuint texID = Renderer::GetFinalTexture();
|
||||
ImGui::Image((ImTextureID)(uintptr_t)texID, size, ImVec2(0, 1), ImVec2(1, 0));
|
||||
|
||||
ImGui::End();
|
||||
profiler.EndEngineSection();
|
||||
|
||||
if (ImGui::BeginPopup("RenameObject"))
|
||||
{
|
||||
static char nameBuffer[128];
|
||||
static bool once = true;
|
||||
|
||||
if (once && selected)
|
||||
{
|
||||
strcpy(nameBuffer, selected->GetName().c_str());
|
||||
once = false;
|
||||
}
|
||||
|
||||
ImGui::InputText("##rename", nameBuffer, sizeof(nameBuffer));
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::Button("OK"))
|
||||
{
|
||||
if (selected)
|
||||
selected->SetName(nameBuffer);
|
||||
ImGui::CloseCurrentPopup();
|
||||
once = true;
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Cancel"))
|
||||
{
|
||||
ImGui::CloseCurrentPopup();
|
||||
once = true;
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if (g_engineConfig.settings.profile_editor)
|
||||
{
|
||||
profiler.EndFrame(); // Finish frame
|
||||
}
|
||||
// ImGui render
|
||||
ShowProfilerTimeline();
|
||||
|
||||
ImGui::Render();
|
||||
int w, h;
|
||||
glfwGetFramebufferSize(window, &w, &h);
|
||||
glViewport(0, 0, w, h);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
glfwSwapBuffers(window);
|
||||
{
|
||||
PROFILE_ENGINE_SCOPE("Finish Rendering");
|
||||
|
||||
profiler.BeginEngineSection("ImGui::Render");
|
||||
ImGui::Render();
|
||||
profiler.EndEngineSection();
|
||||
|
||||
int w, h;
|
||||
profiler.BeginEngineSection("glfwGetFramebufferSize");
|
||||
glfwGetFramebufferSize(window, &w, &h);
|
||||
profiler.EndEngineSection();
|
||||
|
||||
glViewport(0, 0, w, h);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
profiler.BeginEngineSection("ImGui_ImplOpenGL3_RenderDrawData");
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
profiler.EndEngineSection();
|
||||
|
||||
profiler.BeginEngineSection("glfwSwapBuffers");
|
||||
|
||||
glfwSwapBuffers(window);
|
||||
|
||||
profiler.EndEngineSection();
|
||||
}
|
||||
|
||||
for (auto &obj : pendingDeletion)
|
||||
{
|
||||
Logger::LogVerbose("Deleting Object From Que: '%s', [%d, %s]", obj->GetName().c_str(), obj->uid.id, obj->uid.uuid.c_str());
|
||||
if (obj->GetParent())
|
||||
{
|
||||
obj->GetParent()->RemoveChild(obj.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
objects.erase(std::remove_if(objects.begin(), objects.end(),
|
||||
[&](const std::shared_ptr<Object> &o)
|
||||
{ return o == obj; }),
|
||||
objects.end());
|
||||
}
|
||||
}
|
||||
pendingDeletion.clear();
|
||||
|
||||
if (g_engineConfig.settings.profile_editor)
|
||||
{
|
||||
profiler.EndFrame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -960,11 +992,6 @@ void Engine::DrawObjectNode(const std::shared_ptr<Object> &obj)
|
||||
// === Context Menu ===
|
||||
if (ImGui::BeginPopupContextItem())
|
||||
{
|
||||
if (ImGui::MenuItem("Rename"))
|
||||
{
|
||||
selected = obj;
|
||||
ImGui::OpenPopup("RenameObject");
|
||||
}
|
||||
if (ImGui::MenuItem("Delete"))
|
||||
{
|
||||
pendingDeletion.push_back(obj);
|
||||
@ -1160,6 +1187,7 @@ void Engine::LoadScene(const std::string &path)
|
||||
|
||||
Logger::LogInfo("[LoadScene] Loaded scene: %s", root["scene_name"].as<std::string>().c_str());
|
||||
}
|
||||
|
||||
void Engine::SaveState()
|
||||
{
|
||||
YAML::Emitter out;
|
||||
@ -1214,6 +1242,7 @@ void Engine::LoadState()
|
||||
{
|
||||
auto obj = std::make_shared<Object>("[DefaultObject]");
|
||||
obj->Load(node);
|
||||
|
||||
objects.push_back(obj);
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
|
||||
|
||||
#include "Renderer.h"
|
||||
#include "Components/SpriteComponent.h"
|
||||
#include "utils/Shader.h"
|
||||
@ -46,6 +48,9 @@ GLuint Renderer::s_QuadInstanceVBO = 0;
|
||||
Shader Renderer::s_UnlitQuadShader;
|
||||
std::vector<QuadInstance> Renderer::s_QuadBatch;
|
||||
|
||||
void *Renderer::s_QuadMappedPtr = nullptr;
|
||||
GLuint Renderer::s_QuadPersistentFlags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;
|
||||
|
||||
std::vector<Light> Renderer::s_Lights;
|
||||
|
||||
std::vector<Renderer::Cluster> Renderer::s_Clusters;
|
||||
@ -69,11 +74,11 @@ struct BatchedSprite
|
||||
glm::vec2 screenPos;
|
||||
glm::vec2 size;
|
||||
float rotationRad;
|
||||
glm::vec4 texCoords; // optional, if you support atlases
|
||||
glm::vec4 texCoords;
|
||||
GLuint textureID;
|
||||
GLuint normalMapID;
|
||||
SpriteComponent::RenderType renderType;
|
||||
SpriteComponent *sprite; // optional: to access lighting per sprite if needed
|
||||
SpriteComponent *sprite;
|
||||
};
|
||||
|
||||
struct SortedDrawEntry
|
||||
@ -144,7 +149,16 @@ void Renderer::InitQuadBatch()
|
||||
|
||||
glGenBuffers(1, &s_QuadInstanceVBO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, s_QuadInstanceVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, MAX_QUADS * sizeof(QuadInstance), nullptr, GL_DYNAMIC_DRAW);
|
||||
glGenBuffers(1, &s_QuadInstanceVBO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, s_QuadInstanceVBO);
|
||||
glBufferStorage(GL_ARRAY_BUFFER, MAX_QUADS * sizeof(QuadInstance), nullptr, s_QuadPersistentFlags);
|
||||
|
||||
// Map once for persistent write access
|
||||
s_QuadMappedPtr = glMapBufferRange(GL_ARRAY_BUFFER, 0, MAX_QUADS * sizeof(QuadInstance), s_QuadPersistentFlags);
|
||||
if (!s_QuadMappedPtr)
|
||||
{
|
||||
Logger::LogError("Persistent VBO mapping failed!");
|
||||
}
|
||||
|
||||
std::size_t offset = 0;
|
||||
|
||||
@ -273,6 +287,9 @@ void Renderer::UpdateClusterLights()
|
||||
{
|
||||
PROFILE_ENGINE_SCOPE("Renderer::UpdateClusterLights");
|
||||
|
||||
if (!g_engineConfig.settings.lighting_enabled)
|
||||
return;
|
||||
|
||||
s_ClusterCols = (width + CLUSTER_SIZE - 1) / CLUSTER_SIZE;
|
||||
s_ClusterRows = (height + CLUSTER_SIZE - 1) / CLUSTER_SIZE;
|
||||
const int totalClusters = s_ClusterCols * s_ClusterRows;
|
||||
@ -378,6 +395,7 @@ void Renderer::Resize(int w, int h)
|
||||
width = w;
|
||||
height = h;
|
||||
|
||||
|
||||
// Resize all textures
|
||||
glBindTexture(GL_TEXTURE_2D, textureColorBuffer);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
@ -508,7 +526,16 @@ void Renderer::DrawQuad(const core::types::Vec2 &pos, const core::types::Vec2 &s
|
||||
|
||||
s_QuadBatch.push_back({pos, size, rotation, color});
|
||||
}
|
||||
void Renderer::BatchQuad(const core::types::Vec2 &worldPos, const core::types::Vec2 &size, float rotation, const core::types::Color &color, const core::types::Vec2 &cameraPos, float zoom)
|
||||
{
|
||||
if (s_QuadBatch.size() >= MAX_QUADS)
|
||||
FlushQuads();
|
||||
|
||||
core::types::Vec2 screenPos = (worldPos - cameraPos) * zoom + core::types::Vec2(width * 0.5f, height * 0.5f);
|
||||
core::types::Vec2 finalSize = size * zoom;
|
||||
|
||||
s_QuadBatch.push_back({screenPos, finalSize, rotation, color});
|
||||
}
|
||||
|
||||
void Renderer::DrawSprite(SpriteComponent *sprite, const glm::vec2 &pos, float zoom, glm::vec2 &CameraPos)
|
||||
{
|
||||
@ -540,8 +567,6 @@ void Renderer::DrawSprite(SpriteComponent *sprite, const glm::vec2 &pos, float z
|
||||
sortedDrawList.push_back(drawEntry);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Renderer::FlushQuads()
|
||||
{
|
||||
PROFILE_ENGINE_SCOPE("Renderer::FlushQuads");
|
||||
@ -557,7 +582,16 @@ void Renderer::FlushQuads()
|
||||
|
||||
glBindVertexArray(s_QuadVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, s_QuadInstanceVBO);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, s_QuadBatch.size() * sizeof(QuadInstance), s_QuadBatch.data());
|
||||
{
|
||||
PROFILE_DEEP_SCOPE("Upload");
|
||||
|
||||
s_UnlitQuadShader.Use();
|
||||
s_UnlitQuadShader.SetVec2("uScreen", glm::vec2(width, height));
|
||||
|
||||
glBindVertexArray(s_QuadVAO);
|
||||
// Write directly to mapped buffer
|
||||
std::memcpy(s_QuadMappedPtr, s_QuadBatch.data(), s_QuadBatch.size() * sizeof(QuadInstance));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
@ -768,7 +802,6 @@ GLuint Renderer::GetFinalTexture()
|
||||
if (!s_ColorCorrection || !s_ColorCorrection->bloom)
|
||||
return sceneTex;
|
||||
|
||||
// 1. Extract bright regions
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, extractFBO);
|
||||
glViewport(0, 0, width, height);
|
||||
glClearColor(0, 0, 0, 1);
|
||||
@ -828,7 +861,7 @@ GLuint Renderer::GetRenderTexture()
|
||||
return textureColorBuffer;
|
||||
}
|
||||
|
||||
glm::ivec2 Renderer::GetSize()
|
||||
core::types::Vec2 Renderer::GetSize()
|
||||
{
|
||||
return {width, height};
|
||||
}
|
||||
|
@ -11,7 +11,8 @@
|
||||
#include "core/utils/Profiler.h"
|
||||
#include "core/types/all.h"
|
||||
|
||||
struct ColorCorrection {
|
||||
struct ColorCorrection
|
||||
{
|
||||
float brightness = 1.0f;
|
||||
float saturation = 1.0f;
|
||||
float gamma = 1.0f;
|
||||
@ -20,60 +21,65 @@ struct ColorCorrection {
|
||||
float threshold = 0.2f;
|
||||
float intensity = 1.2f;
|
||||
|
||||
void Upload(Shader& shader) const {
|
||||
void Upload(Shader &shader) const
|
||||
{
|
||||
shader.SetFloat("uBrightness", brightness);
|
||||
shader.SetFloat("uSaturation", saturation);
|
||||
shader.SetFloat("uGamma", gamma);
|
||||
}
|
||||
};
|
||||
|
||||
struct Light {
|
||||
struct Light
|
||||
{
|
||||
glm::vec2 screenPos;
|
||||
glm::vec3 color;
|
||||
float intensity;
|
||||
float radius;
|
||||
};
|
||||
|
||||
struct QuadInstance {
|
||||
struct QuadInstance
|
||||
{
|
||||
core::types::Vec2 pos;
|
||||
core::types::Vec2 size;
|
||||
float rotation;
|
||||
core::types::Color color;
|
||||
};
|
||||
|
||||
|
||||
class Renderer {
|
||||
class Renderer
|
||||
{
|
||||
public:
|
||||
static void Init();
|
||||
static void Resize(int w, int h);
|
||||
static void Begin();
|
||||
static void End();
|
||||
|
||||
static void DrawSprite(SpriteComponent* sprite, const glm::vec2& pos, float zoom, glm::vec2& CameraPos);
|
||||
static void DrawTilemap(TilemapComponent* tilemap, const glm::vec2& worldPos, float zoom, const glm::vec2& cameraPos);
|
||||
static void DrawSprite(SpriteComponent *sprite, const glm::vec2 &pos, float zoom, glm::vec2 &CameraPos);
|
||||
static void DrawTilemap(TilemapComponent *tilemap, const glm::vec2 &worldPos, float zoom, const glm::vec2 &cameraPos);
|
||||
|
||||
static void AddLight(const glm::vec2& screenPos, const glm::vec3& color, float intensity, float radius);
|
||||
static void AddLight(const glm::vec2 &screenPos, const glm::vec3 &color, float intensity, float radius);
|
||||
static void ClearLights();
|
||||
|
||||
static void DrawEditorGrid(const glm::vec2& cameraPos, float zoom);
|
||||
static void DrawGizmoLine(const glm::vec2& worldStart, const glm::vec2& worldEnd, const glm::vec3& color, const glm::vec2& cameraPos, float zoom);
|
||||
static void DrawGizmoRect(const glm::vec2& worldPos, const glm::vec2& size, const glm::vec3& color, const glm::vec2& cameraPos, float zoom);
|
||||
static void DrawGizmoCircle(const glm::vec2& worldCenter, float radius, int segments, const glm::vec3& color, const glm::vec2& cameraPos, float zoom);
|
||||
static void DrawEditorGrid(const glm::vec2 &cameraPos, float zoom);
|
||||
static void DrawGizmoLine(const glm::vec2 &worldStart, const glm::vec2 &worldEnd, const glm::vec3 &color, const glm::vec2 &cameraPos, float zoom);
|
||||
static void DrawGizmoRect(const glm::vec2 &worldPos, const glm::vec2 &size, const glm::vec3 &color, const glm::vec2 &cameraPos, float zoom);
|
||||
static void DrawGizmoCircle(const glm::vec2 &worldCenter, float radius, int segments, const glm::vec3 &color, const glm::vec2 &cameraPos, float zoom);
|
||||
|
||||
static GLuint GetRenderTexture();
|
||||
static glm::ivec2 GetSize();
|
||||
static core::types::Vec2 GetSize();
|
||||
static int GetDrawCallCount();
|
||||
static int GetLightsCount();
|
||||
|
||||
static void SetColorCorrection(std::unique_ptr<ColorCorrection> correction);
|
||||
static ColorCorrection* GetColorCorrection();
|
||||
static ColorCorrection *GetColorCorrection();
|
||||
static GLuint GetFinalTexture();
|
||||
|
||||
static void UpdateClusterLights();
|
||||
static void FlushSprites();
|
||||
|
||||
static void InitQuadBatch();
|
||||
static void DrawQuad(const core::types::Vec2& pos, const core::types::Vec2& size, float rotation, const core::types::Color& color);
|
||||
static void DrawQuad(const core::types::Vec2 &pos, const core::types::Vec2 &size, float rotation, const core::types::Color &color);
|
||||
static void BatchQuad(const core::types::Vec2 &worldPos, const core::types::Vec2 &size, float rotation, const core::types::Color &color, const core::types::Vec2 &cameraPos, float zoom);
|
||||
|
||||
static void FlushQuads();
|
||||
|
||||
private:
|
||||
@ -87,14 +93,15 @@ private:
|
||||
|
||||
static GLuint shader, quadVAO, quadVBO;
|
||||
static void InitQuad();
|
||||
static GLuint LoadShader(const char* vertexSrc, const char* fragmentSrc);
|
||||
static GLuint LoadShader(const char *vertexSrc, const char *fragmentSrc);
|
||||
static std::unique_ptr<ColorCorrection> s_ColorCorrection;
|
||||
|
||||
// Clustered Lighting
|
||||
static constexpr int CLUSTER_SIZE = 16;
|
||||
static constexpr int MAX_LIGHTS_PER_CLUSTER = 32;
|
||||
|
||||
struct Cluster {
|
||||
struct Cluster
|
||||
{
|
||||
std::vector<int> lightIndices;
|
||||
};
|
||||
|
||||
@ -110,4 +117,7 @@ private:
|
||||
static GLuint s_QuadVAO, s_QuadVBO, s_QuadInstanceVBO;
|
||||
static Shader s_UnlitQuadShader;
|
||||
static constexpr size_t MAX_QUADS = 10000;
|
||||
|
||||
static void *s_QuadMappedPtr;
|
||||
static GLuint s_QuadPersistentFlags;
|
||||
};
|
||||
|
@ -1,5 +1,7 @@
|
||||
// core/types/vec2.h
|
||||
#pragma once
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <ostream>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
namespace core
|
||||
@ -9,39 +11,110 @@ namespace core
|
||||
|
||||
struct Vec2
|
||||
{
|
||||
float x = 0.0f, y = 0.0f;
|
||||
float x{0}, y{0};
|
||||
|
||||
// Constructors
|
||||
Vec2() = default;
|
||||
Vec2(float _x, float _y) : x(_x), y(_y) {}
|
||||
Vec2(float x, float y) : x(x), y(y) {}
|
||||
Vec2(float v) : x(v), y(v) {}
|
||||
Vec2(const glm::vec2 &v) : x(v.x), y(v.y) {}
|
||||
|
||||
Vec2 operator*(float s) const { return {x * s, y * s}; }
|
||||
operator glm::vec2() const { return glm::vec2(x, y); }
|
||||
// Conversion to glm
|
||||
operator glm::vec2() const { return {x, y}; }
|
||||
|
||||
// Arithmetic operators
|
||||
Vec2 operator+(const Vec2 &rhs) const { return {x + rhs.x, y + rhs.y}; }
|
||||
Vec2 operator-(const Vec2 &rhs) const { return {x - rhs.x, y - rhs.y}; }
|
||||
Vec2 operator*(float scalar) const { return {x * scalar, y * scalar}; }
|
||||
Vec2 operator/(float scalar) const { return {x / scalar, y / scalar}; }
|
||||
|
||||
Vec2 &operator+=(const Vec2 &rhs)
|
||||
{
|
||||
x += rhs.x;
|
||||
y += rhs.y;
|
||||
return *this;
|
||||
}
|
||||
Vec2 &operator-=(const Vec2 &rhs)
|
||||
{
|
||||
x -= rhs.x;
|
||||
y -= rhs.y;
|
||||
return *this;
|
||||
}
|
||||
Vec2 &operator*=(float scalar)
|
||||
{
|
||||
x *= scalar;
|
||||
y *= scalar;
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend Vec2 operator*(float scalar, const Vec2 &v)
|
||||
Vec2 &operator/=(float scalar)
|
||||
{
|
||||
return v * scalar;
|
||||
}
|
||||
|
||||
Vec2 operator+(const Vec2 &other) const
|
||||
{
|
||||
return {x + other.x, y + other.y};
|
||||
}
|
||||
|
||||
Vec2 &operator+=(const Vec2 &other)
|
||||
{
|
||||
x += other.x;
|
||||
y += other.y;
|
||||
x /= scalar;
|
||||
y /= scalar;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Unary operators
|
||||
Vec2 operator-() const { return {-x, -y}; }
|
||||
|
||||
// Comparison
|
||||
bool operator==(const Vec2 &rhs) const { return x == rhs.x && y == rhs.y; }
|
||||
bool operator!=(const Vec2 &rhs) const { return !(*this == rhs); }
|
||||
|
||||
// Length
|
||||
float Length() const { return std::sqrt(x * x + y * y); }
|
||||
float LengthSquared() const { return x * x + y * y; }
|
||||
|
||||
// Normalization
|
||||
Vec2 Normalized() const
|
||||
{
|
||||
float len = Length();
|
||||
return len != 0 ? *this / len : Vec2(0.0f);
|
||||
}
|
||||
|
||||
void Normalize()
|
||||
{
|
||||
float len = Length();
|
||||
if (len != 0)
|
||||
{
|
||||
x /= len;
|
||||
y /= len;
|
||||
}
|
||||
}
|
||||
|
||||
// Dot product
|
||||
float Dot(const Vec2 &rhs) const { return x * rhs.x + y * rhs.y; }
|
||||
|
||||
// Clamp
|
||||
void Clamp(const Vec2 &min, const Vec2 &max)
|
||||
{
|
||||
x = std::max(min.x, std::min(x, max.x));
|
||||
y = std::max(min.y, std::min(y, max.y));
|
||||
}
|
||||
|
||||
// Lerp
|
||||
static Vec2 Lerp(const Vec2 &a, const Vec2 &b, float t)
|
||||
{
|
||||
return a + (b - a) * t;
|
||||
}
|
||||
|
||||
// Distance
|
||||
static float Distance(const Vec2 &a, const Vec2 &b)
|
||||
{
|
||||
return (a - b).Length();
|
||||
}
|
||||
|
||||
// Serialization helpers (optional)
|
||||
friend std::ostream &operator<<(std::ostream &os, const Vec2 &v)
|
||||
{
|
||||
return os << "(" << v.x << ", " << v.y << ")";
|
||||
}
|
||||
};
|
||||
|
||||
// Scalar * Vec2 support
|
||||
inline Vec2 operator*(float scalar, const Vec2 &v)
|
||||
{
|
||||
return v * scalar;
|
||||
}
|
||||
|
||||
} // namespace types
|
||||
} // namespace core
|
||||
|
@ -18,6 +18,7 @@ EngineConfig g_engineConfig{
|
||||
.show_color_correction_window = false,
|
||||
.lighting_enabled = true,
|
||||
.profile_deep = false,
|
||||
.profile_gpu = false,
|
||||
}};
|
||||
|
||||
static std::filesystem::path GetUserSettingsPath()
|
||||
@ -47,6 +48,8 @@ void EngineConfig::SaveToFile()
|
||||
out << YAML::Key << "show_color_correction_window" << YAML::Value << settings.show_color_correction_window;
|
||||
out << YAML::Key << "lighting_enabled" << YAML::Value << settings.lighting_enabled;
|
||||
out << YAML::Key << "profile_deep" << YAML::Value << settings.profile_deep;
|
||||
out << YAML::Key << "profile_gpu" << YAML::Value << settings.profile_gpu;
|
||||
|
||||
|
||||
|
||||
out << YAML::EndMap;
|
||||
@ -77,4 +80,6 @@ void EngineConfig::LoadFromFile()
|
||||
settings.lighting_enabled = root["lighting_enabled"].as<bool>();
|
||||
if (root["profile_deep"])
|
||||
settings.profile_deep = root["profile_deep"].as<bool>();
|
||||
if (root["profile_gpu"])
|
||||
settings.profile_gpu = root["profile_gpu"].as<bool>();
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ struct UserSettings {
|
||||
bool show_color_correction_window;
|
||||
bool lighting_enabled;
|
||||
bool profile_deep;
|
||||
bool profile_gpu;
|
||||
};
|
||||
|
||||
struct EngineConfig {
|
||||
|
Loading…
Reference in New Issue
Block a user