Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions Assets/Shaders/glsl/skinning.vs
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,12 @@ void main() {
}

mat4 finalBonesMatrix = bonesTransformMatrices[bone_ids[i]];

totalPosition += finalBonesMatrix * vec4(vertex, 1.0f) * bone_weights[i];

mat3 normalMatrix = mat3(transpose(inverse(finalBonesMatrix)));

// Skeletal bones are rigid (rotation + translation), so the 3x3 already is the
// correct normal transform -- no need for a per-bone, per-vertex inverse-transpose.
mat3 normalMatrix = mat3(finalBonesMatrix);
totalNormal += normalMatrix * normal * bone_weights[i];
totalTangent += normalMatrix * tangent * bone_weights[i];
totalBitangent += normalMatrix * bitangent * bone_weights[i];
Expand All @@ -65,6 +67,7 @@ void main() {

gl_Position = uProjection * uView * model * totalPosition;

fview = (inverse(uView) * vec4(0, 0, 0, 1)).xyz;
// Camera world position comes from the UBO instead of a per-vertex inverse(uView).
fview = uCameraPos.xyz;
ftex_coords = tex_coords;
}
1 change: 1 addition & 0 deletions Assets/Shaders/glsl/vert_uniforms.glsl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
layout(std140, binding = 0) uniform SceneData {
mat4 uProjection;
mat4 uView;
vec4 uCameraPos; // world-space camera position (xyz)
};
10 changes: 4 additions & 6 deletions ICE/Assets/include/AssetBank.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,10 @@ class AssetBank {
}

AssetPath getName(AssetUID uid) {
for (const auto& [path, id] : nameMapping) {
if (id == uid) {
return path;
}
}
return AssetPath("");
// O(1): the entry already stores its path. This used to linear-scan nameMapping,
// which made project saves (getName per asset) O(n^2).
auto it = resources.find(uid);
return it == resources.end() ? AssetPath("") : it->second.path;
}

AssetUID getUID(const AssetPath& name) {
Expand Down
8 changes: 5 additions & 3 deletions ICE/Assets/include/AssetPath.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
namespace ICE {
class AssetPath {
public:
AssetPath(const AssetPath& cpy);
AssetPath(const AssetPath& cpy) = default; // copy members directly (no re-parse)
AssetPath(std::string path);
std::string toString() const;
const std::string& toString() const;
std::string prefix() const;
template<typename T>
static AssetPath WithTypePrefix(std::string path) {
Expand All @@ -26,7 +26,8 @@ class AssetPath {
return AssetPath(typenames.at(typeid(T)) + ASSET_PATH_SEPARATOR + path);
}

bool operator==(AssetPath other) const { return (other.toString() == this->toString()); }
// Compare the pre-computed canonical string (no allocation / re-parse per comparison).
bool operator==(const AssetPath& other) const { return m_string == other.m_string; }

std::vector<std::string> getPath() const;

Expand All @@ -37,6 +38,7 @@ class AssetPath {
private:
std::vector<std::string> path;
std::string name;
std::string m_string; // canonical "prefix/name", computed once in the constructor
static std::unordered_map<std::type_index, std::string> typenames;
};
} // namespace ICE
Expand Down
2 changes: 1 addition & 1 deletion ICE/Assets/include/Material.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class Material : public Asset {
void renameUniform(const std::string& previous_name, const std::string& new_name);
void removeUniform(const std::string& name);

std::unordered_map<std::string, UniformValue> getAllUniforms() const;
const std::unordered_map<std::string, UniformValue>& getAllUniforms() const;
AssetUID getShader() const;
void setShader(AssetUID shader_id);
bool isTransparent() const;
Expand Down
9 changes: 4 additions & 5 deletions ICE/Assets/src/AssetPath.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@ AssetPath::AssetPath(std::string path) {
}
}
name = path.substr(last, path.length() - last);
m_string = prefix() + name; // canonical form, computed once
}

std::string AssetPath::toString() const {
return (prefix() + name);
const std::string& AssetPath::toString() const {
return m_string;
}

std::vector<std::string> AssetPath::getPath() const {
Expand All @@ -43,9 +44,7 @@ std::string AssetPath::getName() const {

void AssetPath::setName(const std::string &name) {
AssetPath::name = name;
}

AssetPath::AssetPath(const AssetPath &cpy) : AssetPath(cpy.toString()) {
m_string = prefix() + name; // keep the canonical string in sync
}

std::string AssetPath::prefix() const {
Expand Down
2 changes: 1 addition & 1 deletion ICE/Assets/src/Material.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ void Material::removeUniform(const std::string& name) {
}
}

std::unordered_map<std::string, UniformValue> Material::getAllUniforms() const {
const std::unordered_map<std::string, UniformValue>& Material::getAllUniforms() const {
return m_uniforms;
}

Expand Down
19 changes: 18 additions & 1 deletion ICE/Core/src/ICEEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <GLFW/glfw3.h>
#include <Logger.h>
#include <PerspectiveCamera.h>
#include <Profiler.h>
#include <TransformComponent.h>
#include <AnimationSystem.h>
#include <SceneGraphSystem.h>
Expand Down Expand Up @@ -36,6 +37,10 @@ void ICEEngine::initialize(const std::shared_ptr<GraphicsFactory> &graphics_fact
}

void ICEEngine::step() {
// Snapshot the previous frame's profiler samples and start a new frame.
Profiler::get().beginFrame();
ICE_PROFILE_SCOPE("Engine::step");

// Delta time in seconds as a double: the old integer-millisecond cast truncated to 0
// above ~1000 fps (freezing animation) and lost ~13% at 144 Hz.
auto now = std::chrono::steady_clock::now();
Expand All @@ -46,7 +51,19 @@ void ICEEngine::step() {
}
auto render_system = project->getCurrentScene()->getRegistry()->getSystem<RenderSystem>();
render_system->setTarget(m_target_fb);
project->getCurrentScene()->getRegistry()->updateSystems(m_delta_time);
{
ICE_PROFILE_SCOPE("updateSystems");
project->getCurrentScene()->getRegistry()->updateSystems(m_delta_time);
}

// Periodically surface the previous frame's timing breakdown (every ~5s at 60fps).
static int s_profile_log_counter = 0;
if (++s_profile_log_counter >= 300) {
s_profile_log_counter = 0;
for (const auto& [name, ms] : Profiler::get().lastFrame()) {
Logger::Log(Logger::DEBUG, "Profiler", "%s: %.3f ms", name.c_str(), ms);
}
}
}

void ICEEngine::setupScene(const std::shared_ptr<Camera> &camera_) {
Expand Down
2 changes: 1 addition & 1 deletion ICE/Graphics/include/ForwardRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class ForwardRenderer : public Renderer {
ForwardRenderer(const std::shared_ptr<RendererAPI> &api, const std::shared_ptr<GraphicsFactory> &factory);

void submitSkybox(const Skybox &e) override;
void submitDrawable(const Drawable &e) override;
void submitDrawable(Drawable e) override;
void submitLight(const Light &e) override;

void prepareFrame(Camera &camera) override;
Expand Down
6 changes: 6 additions & 0 deletions ICE/Graphics/include/GeometryPass.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

#include <Entity.h>

#include <Eigen/Dense>
#include <vector>

#include "Framebuffer.h"
#include "GraphicsFactory.h"
#include "RenderCommand.h"
Expand All @@ -23,6 +26,9 @@ class GeometryPass : public RenderPass {
// Reused every draw for per-instance data instead of allocating a fresh GL buffer
// per command per frame.
std::shared_ptr<VertexBuffer> m_instance_buffer;
// Reused scratch buffer for packing a skinned mesh's bone palette into a contiguous,
// id-indexed array for a single glUniformMatrix4fv upload.
std::vector<Eigen::Matrix4f> m_bone_palette;
std::vector<RenderCommand>* m_render_queue;
};
} // namespace ICE
7 changes: 7 additions & 0 deletions ICE/Graphics/include/GraphicsAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ class RendererAPI {
virtual void setDepthTest(bool enable) const = 0;
virtual void setDepthMask(bool enable) const = 0;
virtual void setDepthFunc(DepthFunc func) const = 0;
virtual void setBlend(bool enable) const = 0;

// GPU timing via double-buffered GL_TIME_ELAPSED queries. begin/end bracket the GPU work;
// endGPUTimer returns the elapsed GPU time in milliseconds of a *previous* frame (one
// frame of latency) so reading the result never stalls the pipeline.
virtual void beginGPUTimer() const = 0;
virtual double endGPUTimer() const = 0;
virtual void setBackfaceCulling(bool enable) const = 0;
virtual void checkAndLogErrors() const = 0;

Expand Down
3 changes: 3 additions & 0 deletions ICE/Graphics/include/RenderCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ struct RenderCommand {
bool depthTest : 1 = true;
bool depthWrite : 1 = true;
bool is_instanced : 1 = false;
// Alpha blending: only transparent materials need it; opaque draws leave it off so they
// don't lose early-Z/HSR to a blend that does nothing.
bool blend : 1 = false;

DepthFunc depth_func = DepthFunc::Less;

Expand Down
5 changes: 4 additions & 1 deletion ICE/Graphics/include/Renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ struct alignas(16) SceneLightsUBO {
struct alignas(16) CameraUBO {
Eigen::Matrix4f projection;
Eigen::Matrix4f view;
Eigen::Vector4f cameraPos; // world-space camera position (xyz); matches std140 SceneData
};

struct Skybox {
Expand Down Expand Up @@ -70,7 +71,9 @@ class Renderer {
public:
virtual ~Renderer() = default;
virtual void submitSkybox(const Skybox& e) = 0;
virtual void submitDrawable(const Drawable& e) = 0;
// By value so the caller's temporary (with its texture/bone maps) can be moved into the
// renderer's queue instead of copied.
virtual void submitDrawable(Drawable e) = 0;
virtual void submitLight(const Light& e) = 0;
virtual void prepareFrame(Camera& camera) = 0;
virtual std::shared_ptr<Framebuffer> render() = 0;
Expand Down
10 changes: 6 additions & 4 deletions ICE/Graphics/include/ShaderProgram.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ class ShaderProgram {
virtual void loadInts(const std::string &name, int *array, uint32_t size) = 0;

virtual void loadFloat(const std::string &name, float v) = 0;
virtual void loadFloat2(const std::string &name, Eigen::Vector2f vec) = 0;
virtual void loadFloat3(const std::string &name, Eigen::Vector3f vec) = 0;
virtual void loadFloat4(const std::string &name, Eigen::Vector4f vec) = 0;
virtual void loadFloat2(const std::string &name, const Eigen::Vector2f &vec) = 0;
virtual void loadFloat3(const std::string &name, const Eigen::Vector3f &vec) = 0;
virtual void loadFloat4(const std::string &name, const Eigen::Vector4f &vec) = 0;

virtual void loadMat4(const std::string &name, Eigen::Matrix4f mat) = 0;
virtual void loadMat4(const std::string &name, const Eigen::Matrix4f &mat) = 0;
// Upload a contiguous array of matrices in one call (e.g. a bone palette).
virtual void loadMat4v(const std::string &name, const Eigen::Matrix4f *data, uint32_t count) = 0;
};
} // namespace ICE
17 changes: 12 additions & 5 deletions ICE/Graphics/src/ForwardRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <algorithm>
#include <LightComponent.h>
#include <Logger.h>
#include <Profiler.h>
#include <RenderComponent.h>
#include <Scene.h>
#include <TransformComponent.h>
Expand All @@ -29,8 +30,8 @@ ForwardRenderer::ForwardRenderer(const std::shared_ptr<RendererAPI>& api, const
void ForwardRenderer::submitSkybox(const Skybox& e) {
m_skybox.emplace(e);
}
void ForwardRenderer::submitDrawable(const Drawable& e) {
m_drawables.push_back(e);
void ForwardRenderer::submitDrawable(Drawable e) {
m_drawables.push_back(std::move(e));
}
void ForwardRenderer::submitLight(const Light& e) {
m_lights.push_back(e);
Expand All @@ -39,8 +40,10 @@ void ForwardRenderer::submitLight(const Light& e) {
void ForwardRenderer::prepareFrame(Camera& camera) {
auto view_mat = camera.lookThrough();
auto proj_mat = camera.getProjection();
auto cam_pos = camera.getPosition();

CameraUBO camera_ubo_data{.projection = proj_mat, .view = view_mat};
CameraUBO camera_ubo_data{
.projection = proj_mat, .view = view_mat, .cameraPos = Eigen::Vector4f(cam_pos.x(), cam_pos.y(), cam_pos.z(), 1.0f)};
m_camera_ubo->putData(&camera_ubo_data, sizeof(CameraUBO));

SceneLightsUBO light_ubo_data;
Expand Down Expand Up @@ -110,6 +113,7 @@ void ForwardRenderer::prepareFrame(Camera& camera) {
cmd.depthTest = true;
cmd.faceCulling = true;
cmd.is_instanced = false;
cmd.blend = cmd.material->isTransparent();
cmd.computeSortKey(cmd.material->isTransparent(), dist);
m_render_commands.push_back(cmd);
} else {
Expand Down Expand Up @@ -137,6 +141,7 @@ void ForwardRenderer::prepareFrame(Camera& camera) {
cmd.is_instanced = true;
cmd.instance_count = batch.size();
cmd.instance_data = &instance_data_vec; // Link to stored data
cmd.blend = cmd.material->isTransparent();
cmd.computeSortKey(cmd.material->isTransparent(), dist);
m_render_commands.push_back(cmd);
}
Expand All @@ -155,6 +160,7 @@ void ForwardRenderer::prepareFrame(Camera& camera) {
cmd.faceCulling = true;
cmd.bones = &drawable->bone_matrices;
cmd.is_instanced = false;
cmd.blend = cmd.material->isTransparent();
cmd.computeSortKey(cmd.material->isTransparent(), dist);
m_render_commands.push_back(cmd);
}
Expand All @@ -165,9 +171,10 @@ void ForwardRenderer::prepareFrame(Camera& camera) {
}

std::shared_ptr<Framebuffer> ForwardRenderer::render() {
m_api->beginGPUTimer();
m_geometry_pass.execute();
auto result = m_geometry_pass.getResult();
return result;
Profiler::get().addSample("GPU::geometry", m_api->endGPUTimer());
return m_geometry_pass.getResult();
}

void ForwardRenderer::endFrame() {
Expand Down
Loading
Loading