hachem.wtf
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md1
-rw-r--r--assets/hdri/night_sky.hdrbin0 -> 51708063 bytes
-rw-r--r--assets/shaders/equirect_to_cubemap.glsl30
-rw-r--r--assets/shaders/grid.glsl40
-rw-r--r--assets/shaders/textured_quad.glsl (renamed from assets/shaders/compute_texture_quad.glsl)0
-rw-r--r--src/core/hdri_manager.h3
-rw-r--r--src/engine/engine.cpp2
-rw-r--r--src/platform/opengl/opengl_texture.cpp6
-rw-r--r--src/states/world_builder_state.cpp160
-rw-r--r--src/states/world_builder_state.h18
10 files changed, 227 insertions, 33 deletions
diff --git a/README.md b/README.md
index 1ef3fd9..beee444 100644
--- a/README.md
+++ b/README.md
@@ -48,6 +48,7 @@ Donut is a real-time black hole ray tracer that simulates the visual effects of
- **Adaptive Performance**: Dynamic step size adjustment for optimal performance
- **Multiple Objects**: Support for rendering stars and other celestial bodies
- **Configurable Parameters**: Extensive settings for simulation and graphics
+- **World Builder**: Interactive 3D scene editor with reference grid for spatial orientation
## System Requirements
diff --git a/assets/hdri/night_sky.hdr b/assets/hdri/night_sky.hdr
new file mode 100644
index 0000000..b473659
--- /dev/null
+++ b/assets/hdri/night_sky.hdr
Binary files differ
diff --git a/assets/shaders/equirect_to_cubemap.glsl b/assets/shaders/equirect_to_cubemap.glsl
index 2b99c9b..690706f 100644
--- a/assets/shaders/equirect_to_cubemap.glsl
+++ b/assets/shaders/equirect_to_cubemap.glsl
@@ -1,23 +1,29 @@
#type vertex
#version 330 core
-layout (location = 0) in vec3 aPos;
-out vec3 WorldPos;
-uniform mat4 projection;
-uniform mat4 view;
+
+layout (location = 0) in vec3 a_Pos;
+out vec3 v_WorldPos;
+
+uniform mat4 u_Projection;
+uniform mat4 u_View;
+
void main()
{
- WorldPos = aPos;
- gl_Position = projection * view * vec4(WorldPos, 1.0);
+ v_WorldPos = a_Pos;
+ gl_Position = u_Projection * u_View * vec4(v_WorldPos, 1.0);
}
#type fragment
#version 330 core
-out vec4 FragColor;
-in vec3 WorldPos;
-uniform sampler2D equirectangularMap;
+
+out vec4 o_FragColor;
+in vec3 v_WorldPos;
+
+uniform sampler2D u_EquirectangularMap;
const vec2 invAtan = vec2(0.1591, 0.3183);
+
vec2 SampleSphericalMap(vec3 v)
{
vec2 uv = vec2(atan(v.z, v.x), asin(v.y));
@@ -27,7 +33,7 @@ vec2 SampleSphericalMap(vec3 v)
}
void main()
{
- vec2 uv = SampleSphericalMap(normalize(WorldPos));
- vec3 color = texture(equirectangularMap, uv).rgb;
- FragColor = vec4(color, 1.0);
+ vec2 uv = SampleSphericalMap(normalize(v_WorldPos));
+ vec3 color = texture(u_EquirectangularMap, uv).rgb;
+ o_FragColor = vec4(color, 1.0);
}
diff --git a/assets/shaders/grid.glsl b/assets/shaders/grid.glsl
new file mode 100644
index 0000000..81523b3
--- /dev/null
+++ b/assets/shaders/grid.glsl
@@ -0,0 +1,40 @@
+#type vertex
+
+#version 330 core
+
+layout(location = 0) in vec3 a_Position;
+
+uniform mat4 u_ViewProjection;
+uniform mat4 u_Transform;
+uniform float u_GridSize;
+
+void main()
+{
+ vec3 scaledPosition = a_Position * (u_GridSize / 50.0);
+ gl_Position = u_ViewProjection * u_Transform * vec4(scaledPosition, 1.0);
+}
+
+#type fragment
+
+#version 330 core
+
+uniform vec3 u_GridColor;
+uniform float u_GridAlpha;
+uniform float u_GridSize;
+uniform vec3 u_CameraPos;
+
+out vec4 o_FragColor;
+
+void main()
+{
+ float distance = length(u_CameraPos);
+ float fadeFactor = 1.0 - clamp(distance / 100.0, 0.0, 0.8);
+
+ vec3 color = u_GridColor;
+ float alpha = u_GridAlpha * fadeFactor;
+
+ float gridFade = 1.0 - clamp(distance / 50.0, 0.0, 0.9);
+ alpha *= gridFade;
+
+ o_FragColor = vec4(color, alpha);
+}
diff --git a/assets/shaders/compute_texture_quad.glsl b/assets/shaders/textured_quad.glsl
index 95f433d..95f433d 100644
--- a/assets/shaders/compute_texture_quad.glsl
+++ b/assets/shaders/textured_quad.glsl
diff --git a/src/core/hdri_manager.h b/src/core/hdri_manager.h
index 5ccd402..3bdf1cb 100644
--- a/src/core/hdri_manager.h
+++ b/src/core/hdri_manager.h
@@ -40,7 +40,8 @@ namespace Donut
{
"assets/hdri/hdr_blue_nebulae_1.hdr",
"assets/hdri/hdr_subdued_blue_nebulae.hdr",
- "assets/hdri/hdr_subdued_multi_nebulae.hdr"
+ "assets/hdri/hdr_subdued_multi_nebulae.hdr",
+ "assets/hdri/night_sky.hdr"
};
};
};
diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp
index 451684b..28cce2f 100644
--- a/src/engine/engine.cpp
+++ b/src/engine/engine.cpp
@@ -33,8 +33,8 @@ namespace Donut
{ glm::vec4(0.00f, 0.00f, 0.00f, m_sag_a.m_rs), glm::vec4(0, 0, 0, 1), static_cast<float>(m_sag_a.m_mass) }
};
- m_shader_program = Ref<Shader>(Shader::create("assets/shaders/compute_texture_quad.glsl"));
m_compute_program = create_compute_program("assets/shaders/geodesic.glsl");
+ m_shader_program = Ref<Shader>(Shader::create("assets/shaders/textured_quad.glsl"));
m_blur_shader = Ref<Shader>(Shader::create("assets/shaders/blur.glsl"));
auto& hdri_manager = HDRIManager::get();
diff --git a/src/platform/opengl/opengl_texture.cpp b/src/platform/opengl/opengl_texture.cpp
index 14ae214..34a5117 100644
--- a/src/platform/opengl/opengl_texture.cpp
+++ b/src/platform/opengl/opengl_texture.cpp
@@ -208,8 +208,8 @@ namespace Donut
};
glUseProgram(shader_program);
- glUniform1i(glGetUniformLocation(shader_program, "equirectangularMap"), 0);
- glUniformMatrix4fv(glGetUniformLocation(shader_program, "projection"), 1, GL_FALSE, &capture_projection[0][0]);
+ glUniform1i(glGetUniformLocation(shader_program, "u_EquirectangularMap"), 0);
+ glUniformMatrix4fv(glGetUniformLocation(shader_program, "u_Projection"), 1, GL_FALSE, &capture_projection[0][0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, hdr_texture);
@@ -217,7 +217,7 @@ namespace Donut
glBindFramebuffer(GL_FRAMEBUFFER, capture_fbo);
for (unsigned int i = 0; i < 6; ++i)
{
- glUniformMatrix4fv(glGetUniformLocation(shader_program, "view"), 1, GL_FALSE, &capture_views[i][0][0]);
+ glUniformMatrix4fv(glGetUniformLocation(shader_program, "u_View"), 1, GL_FALSE, &capture_views[i][0][0]);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, m_renderer_id, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(cube_vao);
diff --git a/src/states/world_builder_state.cpp b/src/states/world_builder_state.cpp
index c0999d4..ab3e2b3 100644
--- a/src/states/world_builder_state.cpp
+++ b/src/states/world_builder_state.cpp
@@ -46,14 +46,18 @@ namespace Donut
m_sphere_shader = Ref<Shader>(Shader::create("assets/shaders/sphere.glsl"));
m_skybox_shader = Ref<Shader>(Shader::create("assets/shaders/skybox.glsl"));
+ m_grid_shader = Ref<Shader>(Shader::create("assets/shaders/grid.glsl"));
if (!m_sphere_shader)
DONUT_ERROR("Failed to create sphere shader");
if (!m_skybox_shader)
DONUT_ERROR("Failed to create skybox shader");
+ if (!m_grid_shader)
+ DONUT_ERROR("Failed to create grid shader");
initialize_sphere_geometry();
initialize_skybox_geometry();
+ initialize_grid_geometry();
auto& hdri_manager = HDRIManager::get();
m_hdri_environment = hdri_manager.get_current_hdri();
@@ -69,6 +73,8 @@ namespace Donut
m_black_hole = Object(glm::vec3(0.0f, 0.0f, 0.0f), 2.0f, black_hole_material);
m_black_hole_initialized = true;
+ m_grid_size = 10.0f;
+
m_initialized = true;
}
@@ -117,6 +123,9 @@ namespace Donut
if (m_hdri_environment)
render_skybox();
+ if (m_show_grid)
+ render_grid();
+
render_scene();
}
@@ -285,13 +294,13 @@ namespace Donut
{
switch (e.get_key_code())
{
- case GLFW_KEY_W:
+ case GLFW_KEY_M:
m_gizmo_operation = ImGuizmo::TRANSLATE;
return true;
- case GLFW_KEY_E:
+ case GLFW_KEY_R:
m_gizmo_operation = ImGuizmo::ROTATE;
return true;
- case GLFW_KEY_R:
+ case GLFW_KEY_S:
m_gizmo_operation = ImGuizmo::SCALE;
return true;
}
@@ -319,7 +328,7 @@ namespace Donut
ImGui::PopFont();
ImGui::Separator();
- if (ImGui::CollapsingHeader("Scene Info", &m_show_scene_info))
+ if (ImGui::CollapsingHeader("Scene Info"))
{
ImGui::Text("Objects in scene: %zu/16 (+ 1 black hole)", m_scene.objs.size());
@@ -367,7 +376,7 @@ namespace Donut
ImGui::Spacing();
- if (ImGui::CollapsingHeader("Create Object", &m_show_object_creator))
+ if (ImGui::CollapsingHeader("Create Object"))
{
ImGui::TextColored(ImVec4(0.9f, 0.9f, 1.0f, 1.0f), "New Sphere");
ImGui::Separator();
@@ -406,7 +415,7 @@ namespace Donut
ImGui::Spacing();
- if (ImGui::CollapsingHeader("Scene Objects", &m_show_object_list))
+ if (ImGui::CollapsingHeader("Scene Objects"))
{
if (m_black_hole_initialized)
{
@@ -458,7 +467,7 @@ namespace Donut
ImGui::Spacing();
- if (ImGui::CollapsingHeader("Gizmo Controls", &m_show_gizmo_controls))
+ if (ImGui::CollapsingHeader("Gizmo Controls"))
{
ImGui::TextColored(ImVec4(0.9f, 0.9f, 1.0f, 1.0f), "Gizmo Operation:");
@@ -473,12 +482,12 @@ namespace Donut
ImGui::Spacing();
ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "Hotkeys:");
- ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "W = Translate, E = Rotate, R = Scale");
+ ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "M = Move, R = Rotate, S = Scale");
}
ImGui::Spacing();
- if (ImGui::CollapsingHeader("Selection Outline", &m_show_outline_controls))
+ if (ImGui::CollapsingHeader("Selection Outline"))
{
ImGui::TextColored(ImVec4(0.9f, 0.9f, 1.0f, 1.0f), "Outline Settings:");
@@ -494,6 +503,33 @@ namespace Donut
ImGui::Spacing();
+ if (ImGui::CollapsingHeader("Grid Settings"))
+ {
+ ImGui::TextColored(ImVec4(0.9f, 0.9f, 1.0f, 1.0f), "Grid Settings:");
+
+ ImGui::Text("Show Grid:");
+ ImGui::SameLine();
+ ImGui::Checkbox("##ShowGrid", &m_show_grid);
+
+ ImGui::Text("Grid Color:");
+ ImGui::ColorEdit3("##GridColor", &m_grid_color.x);
+
+ ImGui::Text("Grid Alpha:");
+ ImGui::SliderFloat("##GridAlpha", &m_grid_alpha, 0.0f, 1.0f, "%.2f");
+
+ ImGui::Text("Grid Size:");
+ ImGui::SliderFloat("##GridSize", &m_grid_size, 1.0f, 500.0f, "%.1f");
+
+ ImGui::Spacing();
+ if (ImGui::Button("Regenerate Grid", ImVec2(ImGui::GetWindowWidth() - 20, 25)))
+ initialize_grid_geometry();
+
+ ImGui::Spacing();
+ ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "Reference grid for spatial orientation");
+ }
+
+ ImGui::Spacing();
+
if (ImGui::CollapsingHeader("HDRI Environment", nullptr))
{
ImGui::TextColored(ImVec4(0.9f, 0.9f, 1.0f, 1.0f), "HDRI Settings:");
@@ -560,7 +596,7 @@ namespace Donut
ImGui::Spacing();
ImGui::Separator();
ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "Camera: Left mouse = rotate, Scroll = zoom");
- ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "Gizmo: W=Translate, E=Rotate, R=Scale");
+ ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "Gizmo: M=Move, R=Rotate, S=Scale");
ImGui::End();
@@ -943,9 +979,7 @@ namespace Donut
void WorldBuilderState::render_skybox()
{
if (!m_skybox_shader || !m_skybox_vao || !m_hdri_environment)
- {
return;
- }
GLFWwindow* window = static_cast<GLFWwindow*>(Application::get().get_window().get_native_window());
int width, height;
@@ -971,4 +1005,106 @@ namespace Donut
RenderCommand::enable_depth_test();
}
+
+ void WorldBuilderState::initialize_grid_geometry()
+ {
+ if (m_grid_vao)
+ {
+ m_grid_vao->unbind();
+ m_grid_vao.reset();
+ }
+
+ const float grid_size = 50.0f;
+ const int grid_lines = 101;
+ const float half_size = grid_size * 0.5f;
+ const float step = grid_size / (grid_lines - 1);
+
+ std::vector<float> vertices;
+ std::vector<uint32_t> indices;
+
+ for (int i = 0; i < grid_lines; ++i)
+ {
+ float z = -half_size + i * step;
+
+ vertices.push_back(-half_size);
+ vertices.push_back(0.0f);
+ vertices.push_back(z);
+
+ vertices.push_back(half_size);
+ vertices.push_back(0.0f);
+ vertices.push_back(z);
+
+ uint32_t base_index = static_cast<uint32_t>(vertices.size() / 3) - 2;
+ indices.push_back(base_index);
+ indices.push_back(base_index + 1);
+ }
+
+ for (int i = 0; i < grid_lines; ++i)
+ {
+ float x = -half_size + i * step;
+
+ vertices.push_back(x);
+ vertices.push_back(0.0f);
+ vertices.push_back(-half_size);
+
+ vertices.push_back(x);
+ vertices.push_back(0.0f);
+ vertices.push_back(half_size);
+
+ uint32_t base_index = static_cast<uint32_t>(vertices.size() / 3) - 2;
+ indices.push_back(base_index);
+ indices.push_back(base_index + 1);
+ }
+
+ auto vertex_buffer = Ref<VertexBuffer>(VertexBuffer::create(vertices.data(), static_cast<uint32_t>(vertices.size() * sizeof(float))));
+ VertexBufferLayout layout;
+ layout.push<float>(3);
+ vertex_buffer->set_layout(layout);
+
+ auto index_buffer = Ref<IndexBuffer>(IndexBuffer::create(indices.data(), static_cast<uint32_t>(indices.size())));
+
+ m_grid_vao = Ref<VertexArray>(VertexArray::create());
+ m_grid_vao->add_vertex_buffer(vertex_buffer);
+ m_grid_vao->set_index_buffer(index_buffer);
+
+ m_grid_vao->unbind();
+ }
+
+ void WorldBuilderState::render_grid()
+ {
+ if (!m_grid_shader || !m_grid_vao)
+ return;
+
+ GLFWwindow* window = static_cast<GLFWwindow*>(Application::get().get_window().get_native_window());
+ int width, height;
+ glfwGetFramebufferSize(window, &width, &height);
+
+ RenderCommand::set_viewport(0, 0, width, height);
+ RenderCommand::enable_depth_test();
+ RenderCommand::enable_blending();
+
+ glm::mat4 view = m_camera.get_view_matrix();
+ glm::mat4 projection = m_camera.get_projection_matrix();
+ glm::mat4 view_projection = projection * view;
+ glm::mat4 transform = glm::mat4(1.0f);
+
+ glm::vec3 camera_pos = m_camera.get_orbital_position();
+
+ m_grid_shader->bind();
+ m_grid_shader->set_mat4("u_ViewProjection", view_projection);
+ m_grid_shader->set_mat4("u_Transform", transform);
+ m_grid_shader->set_float3("u_GridColor", m_grid_color);
+ m_grid_shader->set_float("u_GridAlpha", m_grid_alpha);
+ m_grid_shader->set_float("u_GridSize", m_grid_size);
+ m_grid_shader->set_float3("u_CameraPos", camera_pos);
+
+ m_grid_vao->bind();
+ RenderCommand::draw_lines(m_grid_vao);
+
+ m_grid_vao->unbind();
+ m_grid_shader->unbind();
+ RenderCommand::disable_blending();
+
+ RenderCommand::enable_depth_test();
+ }
};
diff --git a/src/states/world_builder_state.h b/src/states/world_builder_state.h
index edfb346..243b750 100644
--- a/src/states/world_builder_state.h
+++ b/src/states/world_builder_state.h
@@ -40,6 +40,8 @@ namespace Donut
void load_scene();
void render_scene();
void initialize_sphere_geometry();
+ void initialize_grid_geometry();
+ void render_grid();
private:
Scene m_scene;
Camera m_camera;
@@ -52,6 +54,9 @@ namespace Donut
Ref<Shader> m_skybox_shader;
Ref<VertexArray> m_skybox_vao;
+ Ref<Shader> m_grid_shader;
+ Ref<VertexArray> m_grid_vao;
+
glm::vec3 m_new_object_position = glm::vec3(0.0f, 0.0f, 0.0f);
float m_new_object_radius = 1.0f;
glm::vec3 m_new_object_color = glm::vec3(1.0f, 1.0f, 1.0f);
@@ -65,15 +70,20 @@ namespace Donut
ImGuizmo::OPERATION m_gizmo_operation = ImGuizmo::TRANSLATE;
ImGuizmo::MODE m_gizmo_mode = ImGuizmo::LOCAL;
- bool m_show_object_list = true;
- bool m_show_object_creator = true;
- bool m_show_scene_info = true;
- bool m_show_gizmo_controls = true;
+ bool m_show_object_list = true;
+ bool m_show_object_creator = true;
+ bool m_show_scene_info = true;
+ bool m_show_gizmo_controls = true;
bool m_show_outline_controls = true;
+ bool m_show_grid = true;
glm::vec3 m_outline_color = glm::vec3(1.0f, 1.0f, 1.0f);
float m_outline_width = 0.25f;
+ glm::vec3 m_grid_color = glm::vec3(0.5f, 0.5f, 0.5f);
+ float m_grid_alpha = 0.5f;
+ float m_grid_size = 50.0f;
+
Object m_black_hole;
bool m_black_hole_initialized = false;