Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
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
52 changes: 34 additions & 18 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -1,23 +1,39 @@
# .clang-format
---
Language: Cpp
BasedOnStyle: LLVM
IndentWidth: 4
TabWidth: 4
UseTab: Never

# Don’t indent contents of namespaces
NamespaceIndentation: None

# Align consecutive assignments
AlignConsecutiveAssignments: true

# Optionally align declarations too (if you like the visual symmetry)
AlignConsecutiveDeclarations: true

# Keep parameters and arguments aligned (can be visually helpful)
ColumnLimit: 120 # No forced wrapping; useful for long VulkanHpp calls
AccessModifierOffset: -4
AlignAfterOpenBracket: Align

# Optional: control brace placement if you like a specific style
BreakBeforeBraces: Attach

# Optional: max line length
ColumnLimit: 100
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AllowShortBlocksOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BinPackParameters: false
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Custom
BraceWrapping:
AfterClass: true
AfterControlStatement: true
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterStruct: true
AfterUnion: true
BeforeCatch: true
BeforeElse: true
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
Cpp11BracedListStyle: true
DerivePointerAlignment: false
NamespaceIndentation: None
PointerAlignment: Left
SortIncludes: true
IncludeBlocks: Preserve
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ build/
cmake-build-debug/
vcpkg_installed/
.idea
resources/
resources/
*.fbx
workspace/
41 changes: 36 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ find_package(spdlog CONFIG REQUIRED)
find_package(VulkanMemoryAllocator CONFIG REQUIRED)
find_package(glm CONFIG REQUIRED)
find_package(imgui CONFIG REQUIRED)
find_package(assimp CONFIG REQUIRED)

add_executable(Reactor src/core/main.cpp
add_library(ReactorLib STATIC
src/vulkan/VulkanContext.cpp
src/vulkan/VulkanContext.hpp
src/pch.hpp
Expand Down Expand Up @@ -55,9 +56,39 @@ add_executable(Reactor src/core/main.cpp
src/core/OrbitController.cpp
src/core/OrbitController.hpp
src/core/Application.cpp
src/core/Application.hpp)
src/core/Application.hpp
src/vulkan/Vertex.hpp
src/vulkan/ImageUtils.hpp
src/vulkan/ImageUtils.cpp
src/vulkan/Mesh.cpp
src/vulkan/Mesh.hpp
src/vulkan/MeshGenerators.hpp
src/vulkan/MeshGenerators.cpp
src/core/ModelIO.hpp
src/core/ModelIO.cpp
src/vulkan/ShadowMapping.hpp
src/vulkan/ShadowMapping.cpp
)

target_link_libraries(Reactor PRIVATE Vulkan::Vulkan Vulkan::Headers glfw fmt::fmt spdlog::spdlog GPUOpen::VulkanMemoryAllocator glm::glm)
target_link_libraries(Reactor PRIVATE imgui::imgui)
target_compile_definitions(ReactorLib PUBLIC GLM_ENABLE_EXPERIMENTAL)
target_compile_definitions(ReactorLib PUBLIC GLM_FORCE_DEPTH_ZERO_TO_ONE)

target_precompile_headers(Reactor PRIVATE src/pch.hpp)
target_link_libraries(ReactorLib PUBLIC
Vulkan::Vulkan
Vulkan::Headers
glfw
fmt::fmt
spdlog::spdlog
GPUOpen::VulkanMemoryAllocator
glm::glm
imgui::imgui
assimp::assimp
)

target_precompile_headers(ReactorLib PRIVATE src/pch.hpp)

add_executable(Editor src/core/main.cpp)
target_link_libraries(Editor PRIVATE ReactorLib)

add_executable(BuildModel src/tools/ModelBuilder.cpp)
target_link_libraries(BuildModel PRIVATE ReactorLib)
41 changes: 36 additions & 5 deletions shaders/composite.frag
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,27 @@ layout(location = 0) out vec4 outColor;

layout(binding = 0) uniform sampler2D uInputImage;

// Binding 2: Multisampled depth texture from geometry pass
layout(binding = 2) uniform sampler2DMS uDepthImage;

layout(set = 0, binding = 1) uniform CompositeParams {
float uExposure; // Default: 1.0
float uContrast; // Default: 1.0
float uSaturation; // Default: 1.0
float uVignetteIntensity; // Default: 0.5
float uVignetteFalloff; // Default 0.5
float uExposure;// Default: 1.0
float uContrast;// Default: 1.0
float uSaturation;// Default: 1.0
float uVignetteIntensity;// Default: 0.5
float uVignetteFalloff;// Default 0.5
float uFogDensity;
};

// add camera projection uniforms to the UBO or pass them in another way
const float Z_NEAR = 0.1;
const float Z_FAR = 100.0;

float linearizeDepth(float depth) {
float z_n = 2.0 * depth - 1.0;
return (2.0 * Z_NEAR * Z_FAR) / (Z_FAR + Z_NEAR - z_n * (Z_FAR - Z_NEAR));
}

// ACES Filmic Tone Mapping Curve
vec3 tonemapACES(vec3 x) {
const float a = 2.51;
Expand All @@ -24,6 +37,21 @@ vec3 tonemapACES(vec3 x) {
}

void main() {

ivec2 texelCoord = ivec2(gl_FragCoord.xy);

float depth = texelFetch(uDepthImage, texelCoord, 0).r;

// --- Fog Calculation ---
vec3 fogColor = vec3(0.5, 0.6, 0.7);// A cool, hazy blue
float fogStart = 0.5;
float fogEnd = 120.0;
float viewDistance = linearizeDepth(depth);
// Calculate fog amount (0.0 = no fog, 1.0 = full fog)
float fogFactor = 1.0 - exp(-viewDistance * uFogDensity);
// float fogFactor = uFogDensity;
// ----------------------

// Sample the HDR input image
vec3 hdrColor = texture(uInputImage, fragUV).rgb;

Expand All @@ -43,5 +71,8 @@ void main() {
vec3 grayscale = vec3(dot(finalColor, vec3(0.299, 0.587, 0.114)));
finalColor = mix(grayscale, finalColor, uSaturation);

// Mix the final scene color with the fog color
finalColor = mix(finalColor, fogColor, fogFactor);

outColor = vec4(finalColor, 1.0);
}
51 changes: 49 additions & 2 deletions shaders/triangle.frag
Original file line number Diff line number Diff line change
@@ -1,8 +1,55 @@
#version 450

layout(location = 0) in vec3 vColor;
layout(location = 0) in vec3 inWorldPos;
layout(location = 1) in vec3 inNormal;
layout(location = 2) in vec4 inLightSpacePos;

layout(binding = 1) uniform LightUBO {
vec4 lightDirection;
vec4 lightColor;
float lightIntensity;
} ubo;

layout(binding = 2) uniform sampler2DShadow shadowMap;

// Final output color
layout(location = 0) out vec4 outColor;

float calculateShadow()
{
// Perform perspective divide
vec3 projCoords = inLightSpacePos.xyz / inLightSpacePos.w;

// Convert from [-1, 1] to [0, 1] texture coordinates
projCoords.xy = projCoords.xy * 0.5 + 0.5;

// Get the closest depth from the shadow map (from light's perspective)
// The 'z' coordinate of projCoords is the current fragment's depth from the light
// texture() for sampler2DShadow performs the depth comparison automatically
float shadow = texture(shadowMap, projCoords);

return shadow;
}

void main() {
outColor = vec4(vColor, 1.0);
vec3 objectColor = vec3(0.8, 0.8, 0.8);

vec3 ambient = objectColor * 0.1;

// 2. Calculate the diffuse (directional) light component.
vec3 normal = normalize(inNormal);
vec3 lightDir = normalize(-ubo.lightDirection.xyz);
float diffuseFactor = max(dot(normal, lightDir), 0.0);
vec3 diffuse = objectColor * ubo.lightColor.rgb * ubo.lightIntensity * diffuseFactor;

// 3. Get the shadow factor (1.0 for lit, 0.0 for shadowed).
float shadow = calculateShadow();

// 4. Combine the components for the final color.
// The final color is the ambient light, plus the direct (diffuse) light,
// which IS blocked by shadows.
vec3 finalColor = ambient + (diffuse * shadow);

outColor = vec4(finalColor, 1.0);

}
85 changes: 20 additions & 65 deletions shaders/triangle.vert
Original file line number Diff line number Diff line change
@@ -1,74 +1,29 @@
#version 450

layout(set = 0, binding = 0) uniform UBO {
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inNormal;
layout(location = 2) in vec3 inColor;
layout(location = 3) in vec2 inTexCoord;

layout(location = 0) out vec3 outWorldPos;
layout(location = 1) out vec3 outNormal;
layout(location = 2) out vec4 outLightSpacePos;

layout(binding = 0) uniform SceneUBO {
mat4 view;
mat4 projection;
};
mat4 lightSpaceMatrix;
} ubo;

layout(location = 0) out vec3 vColor;
layout(push_constant) uniform PushConstants {
mat4 model;
} push;

void main() {
// Hardcoded cube made of 12 triangles (36 vertices)
vec3 positions[36] = vec3[](
// Front face
vec3(-0.5, -0.5, 0.5),
vec3( 0.5, -0.5, 0.5),
vec3( 0.5, 0.5, 0.5),
vec3(-0.5, -0.5, 0.5),
vec3( 0.5, 0.5, 0.5),
vec3(-0.5, 0.5, 0.5),

// Back face
vec3(-0.5, -0.5, -0.5),
vec3( 0.5, 0.5, -0.5),
vec3( 0.5, -0.5, -0.5),
vec3(-0.5, -0.5, -0.5),
vec3(-0.5, 0.5, -0.5),
vec3( 0.5, 0.5, -0.5),

// Left face
vec3(-0.5, -0.5, -0.5),
vec3(-0.5, -0.5, 0.5),
vec3(-0.5, 0.5, 0.5),
vec3(-0.5, -0.5, -0.5),
vec3(-0.5, 0.5, 0.5),
vec3(-0.5, 0.5, -0.5),

// Right face
vec3( 0.5, -0.5, -0.5),
vec3( 0.5, 0.5, 0.5),
vec3( 0.5, -0.5, 0.5),
vec3( 0.5, -0.5, -0.5),
vec3( 0.5, 0.5, -0.5),
vec3( 0.5, 0.5, 0.5),

// Top face
vec3(-0.5, 0.5, -0.5),
vec3(-0.5, 0.5, 0.5),
vec3( 0.5, 0.5, 0.5),
vec3(-0.5, 0.5, -0.5),
vec3( 0.5, 0.5, 0.5),
vec3( 0.5, 0.5, -0.5),

// Bottom face
vec3(-0.5, -0.5, -0.5),
vec3( 0.5, -0.5, 0.5),
vec3(-0.5, -0.5, 0.5),
vec3(-0.5, -0.5, -0.5),
vec3( 0.5, -0.5, -0.5),
vec3( 0.5, -0.5, 0.5)
);

vec3 colors[6] = vec3[](
vec3(1.0, 0.0, 0.0),
vec3(0.0, 1.0, 0.0),
vec3(0.0, 0.0, 1.0),
vec3(1.0, 1.0, 0.0),
vec3(1.0, 0.0, 1.0),
vec3(0.0, 1.0, 1.0)
);
vec4 worldPos = push.model * vec4(inPosition, 1.0);
gl_Position = ubo.projection * ubo.view * worldPos;

int face = gl_VertexIndex / 6; // Each face has 6 vertices
gl_Position = projection * view * vec4(positions[gl_VertexIndex], 1.0);
vColor = colors[face];
outWorldPos = worldPos.xyz;
outNormal = normalize(mat3(push.model) * inNormal);
outLightSpacePos = ubo.lightSpaceMatrix * worldPos;
}
5 changes: 3 additions & 2 deletions src/core/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ void Application::initialize() {
m_window = std::make_unique<Window>(1280, 720, "Reactor", *m_eventManager);
m_camera = std::make_unique<Camera>();
m_orbitController = std::make_unique<OrbitController>(*m_camera);
m_orbitController->setSimCityView(20.0f, 45.0f);

// subscribe controller to input events.
m_eventManager->subscribe(EventType::MouseMoved, m_orbitController.get());
Expand All @@ -33,9 +34,9 @@ void Application::initialize() {
m_renderer = std::make_unique<VulkanRenderer>(config, *m_window, *m_camera);
}

void Application::run() {
void Application::run() const {
while (!m_window->shouldClose()) {
m_window->pollEvents();
Window::pollEvents();
m_renderer->drawFrame();
}
}
Expand Down
11 changes: 10 additions & 1 deletion src/core/Application.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,16 @@ class Application {
Application();
~Application();

void run();
// Prevent copying
Application(const Application&) = delete;
Application& operator=(const Application&) = delete;

// Allow moving if needed
Application(Application&&) = default;
Application& operator=(Application&&) = default;

// Runs the main application loop. Returns program exit code.
void run() const;

private:
void initialize();
Expand Down
Loading