Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
94c7236
Begun the migration to Slang for the shaders
maxvdec Sep 11, 2026
e5c31e3
Continuing work on the slang shaders
maxvdec Sep 11, 2026
2046aa6
Split Photon Metal path tracer into focused shader libraries
maxvdec Sep 11, 2026
b5bf44a
Preserve whitespace when expanding Photon shader includes
maxvdec Sep 11, 2026
fb64546
Add shared Slang rendering and post-processing libraries
maxvdec Sep 11, 2026
fbdbda6
Migrate deferred shader stages to Slang
maxvdec Sep 11, 2026
bdaf748
Migrate light shader stages to Slang
maxvdec Sep 11, 2026
75226a3
Migrate downsample shader stages to Slang
maxvdec Sep 11, 2026
d024059
Migrate gaussian shader stages to Slang
maxvdec Sep 11, 2026
333afa4
Migrate particle shader stages to Slang
maxvdec Sep 11, 2026
de05881
Migrate skybox shader stages to Slang
maxvdec Sep 11, 2026
7dddac6
Migrate ssr shader stages to Slang
maxvdec Sep 11, 2026
528960f
Migrate upsample shader stages to Slang
maxvdec Sep 11, 2026
6559ff2
Migrate fluid shader stages to Slang
maxvdec Sep 11, 2026
1221226
Migrate fullscreen shader stages to Slang
maxvdec Sep 11, 2026
ae78727
Migrate depth shader stages to Slang
maxvdec Sep 11, 2026
4b32510
Migrate empty shader stages to Slang
maxvdec Sep 11, 2026
6e4d886
Migrate point_depth_nogeom shader stages to Slang
maxvdec Sep 11, 2026
ab44da1
Migrate ssao shader stages to Slang
maxvdec Sep 11, 2026
a48b719
Migrate ssao_blur shader stages to Slang
maxvdec Sep 11, 2026
c6d5346
Migrate color shader stages to Slang
maxvdec Sep 11, 2026
c934298
Migrate debug shader stages to Slang
maxvdec Sep 11, 2026
429b11f
Migrate texture shader stages to Slang
maxvdec Sep 11, 2026
811894e
Migrate text shader stages to Slang
maxvdec Sep 11, 2026
2d683a3
Migrate volumetric shader stages to Slang
maxvdec Sep 11, 2026
2e681f6
Register explicit Slang stage entry points and packed shader symbols
maxvdec Sep 11, 2026
bb99cbb
Migrate Photon denoising to a portable Slang compute shader
maxvdec Sep 11, 2026
b47c371
Wire Slang generation and retire duplicated backend shader trees
maxvdec Sep 11, 2026
4fb2a95
Pin Opal Slang reflection and descriptor compatibility
maxvdec Sep 12, 2026
c314c1b
Order shader generation before header consumers
maxvdec Sep 12, 2026
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
12 changes: 12 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ jobs:
- name: Install Dependencies
run: |
brew install cmake ninja qt@6 sdl3 glm openal-soft assimp vulkan-loader molten-vk vulkan-validationlayers spirv-cross spirv-headers spirv-tools
- name: Install Slang
run: |
case "$(uname -m)" in
arm64) slang_arch=aarch64 ;;
x86_64) slang_arch=x86_64 ;;
*) exit 1 ;;
esac
slang_dir="$RUNNER_TEMP/slang"
mkdir -p "$slang_dir"
curl --fail --location "https://github.com/shader-slang/slang/releases/download/v2024.13/slang-2024.13-macos-${slang_arch}.tar.gz" -o "$RUNNER_TEMP/slang.tar.gz"
tar -xzf "$RUNNER_TEMP/slang.tar.gz" -C "$slang_dir"
echo "$slang_dir/bin" >> "$GITHUB_PATH"
- name: Configure Qt
run: |
echo "$(brew --prefix qt@6)/bin" >> "$GITHUB_PATH"
Expand Down
92 changes: 12 additions & 80 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)

# ─── Rendering Backend ───────────────────────────────────────────────────────
set(BACKEND "AUTO" CACHE STRING "Rendering backend: AUTO, VULKAN, METAL, OPENGL")
set_property(CACHE BACKEND PROPERTY STRINGS AUTO VULKAN METAL OPENGL)
set(BACKEND "AUTO" CACHE STRING "Rendering backend: AUTO, VULKAN, METAL")
set_property(CACHE BACKEND PROPERTY STRINGS AUTO VULKAN METAL)
string(TOUPPER "${BACKEND}" BACKEND)

if (BACKEND STREQUAL "AUTO")
Expand All @@ -69,18 +69,15 @@ if (BACKEND STREQUAL "AUTO")
endif ()
endif ()

set(BACKEND_OPENGL OFF)
set(BACKEND_VULKAN OFF)
set(BACKEND_METAL OFF)

if (BACKEND STREQUAL "OPENGL")
set(BACKEND_OPENGL ON)
elseif (BACKEND STREQUAL "VULKAN")
if (BACKEND STREQUAL "VULKAN")
set(BACKEND_VULKAN ON)
elseif (BACKEND STREQUAL "METAL")
set(BACKEND_METAL ON)
else ()
message(FATAL_ERROR "Invalid BACKEND='${BACKEND}'. Valid values are: AUTO, VULKAN, METAL, OPENGL")
message(FATAL_ERROR "Invalid BACKEND='${BACKEND}'. Valid values are: AUTO, VULKAN, METAL")
endif ()

message(STATUS "Selected backend: ${BACKEND}")
Expand Down Expand Up @@ -216,10 +213,7 @@ if (NOT BEZEL_NATIVE)
endif ()

# ─── Backend Definitions ─────────────────────────────────────────────────────
if (BACKEND_OPENGL)
add_compile_definitions(OPENGL)
message(STATUS "Building using OpenGL backend")
elseif (BACKEND_VULKAN)
if (BACKEND_VULKAN)
add_compile_definitions(VULKAN GLM_FORCE_DEPTH_ZERO_TO_ONE)
message(STATUS "Building using Vulkan backend")
elseif (BACKEND_METAL)
Expand All @@ -228,55 +222,7 @@ elseif (BACKEND_METAL)
endif ()

# ─── Shader Generation ───────────────────────────────────────────────────────
if (BACKEND_OPENGL)
set(SHADER_INPUT_DIR "${CMAKE_SOURCE_DIR}/shaders/opengl")
elseif (BACKEND_VULKAN)
set(SHADER_INPUT_DIR "${CMAKE_SOURCE_DIR}/shaders/vulkan")
elseif (BACKEND_METAL)
set(SHADER_INPUT_DIR "${CMAKE_SOURCE_DIR}/shaders/metal")
endif ()

set(SHADER_OUTPUT_FILE "${CMAKE_SOURCE_DIR}/include/atlas/core/default_shaders.h")
set(RUNTIME_SCRIPT_INPUT_DIR "${CMAKE_SOURCE_DIR}/runtime/scripts")
set(RUNTIME_SCRIPT_OUTPUT_FILE "${CMAKE_SOURCE_DIR}/include/atlas/runtime/atlasScripts.h")

find_package(Python3 COMPONENTS Interpreter REQUIRED)

file(GLOB_RECURSE SHADER_SOURCES
${SHADER_INPUT_DIR}/*.vert
${SHADER_INPUT_DIR}/*.frag
${SHADER_INPUT_DIR}/*.glsl
${SHADER_INPUT_DIR}/*.geom
${SHADER_INPUT_DIR}/*.tesc
${SHADER_INPUT_DIR}/*.tese
${SHADER_INPUT_DIR}/*.metal
)

file(GLOB_RECURSE RUNTIME_SCRIPT_SOURCES CONFIGURE_DEPENDS
${RUNTIME_SCRIPT_INPUT_DIR}/*.js
${RUNTIME_SCRIPT_INPUT_DIR}/*.mjs
)

if (BACKEND_OPENGL)
set(SHADER_BACKEND_ARG "opengl")
elseif (BACKEND_VULKAN)
set(SHADER_BACKEND_ARG "vulkan")
elseif (BACKEND_METAL)
set(SHADER_BACKEND_ARG "metal")
endif ()

message(STATUS "Packing shaders for ${BACKEND} backend")
add_custom_command(
OUTPUT ${SHADER_OUTPUT_FILE}
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_SOURCE_DIR}/include/atlas/core
COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripts/pack_shaders.py
${SHADER_INPUT_DIR} ${SHADER_OUTPUT_FILE} ${SHADER_BACKEND_ARG}
DEPENDS ${SHADER_SOURCES}
COMMENT "Packing shaders into default_shaders.h"
VERBATIM
)

add_custom_target(generate_shaders DEPENDS ${SHADER_OUTPUT_FILE})
include(cmake/AtlasShaders.cmake)

add_custom_command(
OUTPUT ${RUNTIME_SCRIPT_OUTPUT_FILE}
Expand Down Expand Up @@ -321,9 +267,7 @@ else ()
endif ()

# ─── Platform Packages ───────────────────────────────────────────────────────
if (BACKEND_OPENGL)
find_package(OpenGL REQUIRED)
elseif (BACKEND_VULKAN)
if (BACKEND_VULKAN)
find_package(Vulkan REQUIRED)
message(STATUS "Found Vulkan SDK at ${Vulkan_LIBRARY}")
message(STATUS "Found Vulkan include dirs at ${Vulkan_INCLUDE_DIRS}")
Expand Down Expand Up @@ -441,6 +385,7 @@ set(OPAL_BACKEND "${BACKEND}" CACHE STRING "Opal rendering backend" FORCE)
add_subdirectory(opal)

add_library(bezel STATIC ${BEZEL_SOURCES})
add_dependencies(bezel generate_shaders)
target_link_libraries(bezel
PUBLIC Opal::Opal
PRIVATE ${ATLAS_SDL_TARGET} ${ATLAS_GLM_TARGET}
Expand Down Expand Up @@ -482,9 +427,7 @@ target_link_libraries(aurora
target_include_directories(aurora PRIVATE ${ATLAS_DEP_INCLUDE_DIRS})
add_dependencies(aurora generate_shaders)

if (BACKEND_OPENGL)
target_link_libraries(aurora PRIVATE OpenGL::GL)
elseif (BACKEND_VULKAN)
if (BACKEND_VULKAN)
target_link_libraries(aurora PRIVATE Vulkan::Vulkan)
endif ()

Expand All @@ -497,9 +440,7 @@ target_link_libraries(hydra
target_include_directories(hydra PRIVATE ${ATLAS_DEP_INCLUDE_DIRS})
add_dependencies(hydra generate_shaders)

if (BACKEND_OPENGL)
target_link_libraries(hydra PRIVATE OpenGL::GL)
elseif (BACKEND_VULKAN)
if (BACKEND_VULKAN)
target_link_libraries(hydra PRIVATE Vulkan::Vulkan)
endif ()

Expand Down Expand Up @@ -540,9 +481,7 @@ endif ()

target_include_directories(atlas PRIVATE ${ATLAS_DEP_INCLUDE_DIRS})

if (BACKEND_OPENGL)
target_link_libraries(atlas PRIVATE OpenGL::GL)
elseif (BACKEND_VULKAN)
if (BACKEND_VULKAN)
target_link_libraries(atlas PRIVATE Vulkan::Vulkan)
if (APPLE)
message(STATUS "Configuring MoltenVK for macOS")
Expand All @@ -555,15 +494,8 @@ target_compile_options(atlas PRIVATE -Wno-overlength-strings)

if (WIN32)
target_compile_definitions(atlas PRIVATE _CRT_SECURE_NO_WARNINGS NOMINMAX)
target_link_libraries(atlas PRIVATE opengl32)
elseif (APPLE)
if (BACKEND_OPENGL)
target_link_libraries(atlas PRIVATE
"-framework OpenGL"
"-framework Cocoa"
"-framework IOKit"
)
elseif (BACKEND_VULKAN)
if (BACKEND_VULKAN)
target_link_libraries(atlas PRIVATE
"-framework Cocoa"
"-framework IOKit"
Expand Down
51 changes: 8 additions & 43 deletions atlas/application/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1191,11 +1191,6 @@ Window::Window(const WindowConfiguration &config)
program.compile();
this->depthProgram = program;

#ifdef __APPLE__
this->useMultiPassPointShadows = true;
#else
this->useMultiPassPointShadows = false;
#endif

#ifdef METAL
this->shadowUpdateInterval = 1.0f / 6.0f;
Expand Down Expand Up @@ -4799,52 +4794,22 @@ void Window::renderLightsToShadowMaps(
pointLightPipeline->setUniform1f("far_plane", light->distance);
light->lastShadowParams.farPlane = light->distance;

if (this->useMultiPassPointShadows) {
// Multi-pass rendering: render 6 times, once per cubemap face
for (int face = 0; face < 6; ++face) {
shadowRenderTarget->bindCubemapFace(face);

// Set up render pass for this cubemap face
auto shadowRenderPass = opal::RenderPass::create();
shadowRenderPass->setFramebuffer(
shadowRenderTarget->getFramebuffer());
commandBuffer->beginPass(shadowRenderPass);

commandBuffer->clearDepth(1.0f);

// Set the shadow matrix for this face
pointLightPipeline->setUniformMat4f("shadowMatrix",
shadowTransforms.at(face));
pointLightPipeline->setUniform1i("faceIndex", face);

for (auto *obj : shadowCasters) {
if (!obj->canCastShadows()) {
continue;
}

obj->setProjectionMatrix(glm::mat4(1.0));
obj->setViewMatrix(glm::mat4(1.0));
obj->setPipeline(pointLightPipeline);
obj->render(getDeltaTime(), commandBuffer, false);
}
// Multi-pass rendering: render 6 times, once per cubemap face
for (int face = 0; face < 6; ++face) {
shadowRenderTarget->bindCubemapFace(face);

commandBuffer->endPass();
}
} else {
// Single-pass rendering with geometry shader
// Set up render pass for this cubemap face
auto shadowRenderPass = opal::RenderPass::create();
shadowRenderPass->setFramebuffer(
shadowRenderTarget->getFramebuffer());
commandBuffer->beginPass(shadowRenderPass);

shadowRenderTarget->bind();
commandBuffer->clearDepth(1.0f);

for (size_t i = 0; i < shadowTransforms.size(); ++i) {
pointLightPipeline->setUniformMat4f("shadowMatrices[" +
std::to_string(i) + "]",
shadowTransforms.at(i));
}
// Set the shadow matrix for this face
pointLightPipeline->setUniformMat4f("shadowMatrix",
shadowTransforms.at(face));
pointLightPipeline->setUniform1i("faceIndex", face);

for (auto *obj : shadowCasters) {
if (!obj->canCastShadows()) {
Expand Down
71 changes: 1 addition & 70 deletions atlas/graphics/render_target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -852,76 +852,7 @@ void RenderTarget::render(float dt,
"environment.fogColor", scene->environment.fog.color.r,
scene->environment.fog.color.g, scene->environment.fog.color.b);

if (scene->atmosphere.clouds) {
const Clouds &cloudSettings = *scene->atmosphere.clouds;

const glm::vec3 cloudSize = cloudSettings.size.toGlm();
const glm::vec3 cloudPos = cloudSettings.position.toGlm();

glm::vec3 sunDir = scene->atmosphere.getSunAngle().toGlm();
float sunLength = glm::length(sunDir);
if (sunLength > 1e-3f) {
sunDir /= sunLength;
} else {
sunDir = glm::vec3(0.0f, 1.0f, 0.0f);
}

const Color &sunColor = scene->atmosphere.sunColor;
const float sunIntensity = scene->atmosphere.getLightIntensity();
const Color ambientColor = scene->getAmbientColor();
const float ambientIntensity = scene->getAmbientIntensity();
glm::vec3 ambient = glm::vec3(static_cast<float>(ambientColor.r),
static_cast<float>(ambientColor.g),
static_cast<float>(ambientColor.b)) *
ambientIntensity;

renderTargetPipeline->bindTexture3D(
"cloudsTexture", cloudSettings.getCloudTexture(128), 15,
obj->id);
renderTargetPipeline->setUniform3f("cloudSize", cloudSize.x,
cloudSize.y, cloudSize.z);
renderTargetPipeline->setUniform3f("cloudPosition", cloudPos.x,
cloudPos.y, cloudPos.z);
renderTargetPipeline->setUniform1f("cloudScale",
cloudSettings.scale);
renderTargetPipeline->setUniform3f(
"cloudOffset", cloudSettings.offset.x, cloudSettings.offset.y,
cloudSettings.offset.z);
renderTargetPipeline->setUniform1f("cloudDensityThreshold",
cloudSettings.density);
renderTargetPipeline->setUniform1f("cloudDensityMultiplier",
cloudSettings.densityMultiplier);
renderTargetPipeline->setUniform1f("cloudAbsorption",
cloudSettings.absorption);
renderTargetPipeline->setUniform1f("cloudScattering",
cloudSettings.scattering);
renderTargetPipeline->setUniform1f("cloudPhaseG",
cloudSettings.phase);
renderTargetPipeline->setUniform1f("cloudClusterStrength",
cloudSettings.clusterStrength);
renderTargetPipeline->setUniform1i(
"cloudPrimarySteps",
std::max(1, cloudSettings.primaryStepCount));
renderTargetPipeline->setUniform1i(
"cloudLightSteps", std::max(1, cloudSettings.lightStepCount));
renderTargetPipeline->setUniform1f(
"cloudLightStepMultiplier", cloudSettings.lightStepMultiplier);
renderTargetPipeline->setUniform1f("cloudMinStepLength",
cloudSettings.minStepLength);
renderTargetPipeline->setUniform3f("sunDirection", sunDir.x,
sunDir.y, sunDir.z);
renderTargetPipeline->setUniform3f(
"sunColor", static_cast<float>(sunColor.r),
static_cast<float>(sunColor.g), static_cast<float>(sunColor.b));
renderTargetPipeline->setUniform1f("sunIntensity", sunIntensity);
renderTargetPipeline->setUniform3f("cloudAmbientColor", ambient.x,
ambient.y, ambient.z);
renderTargetPipeline->setUniform1i("hasClouds", 1);
} else {
renderTargetPipeline->bindTexture3D("cloudsTexture", 0, 15,
obj->id);
renderTargetPipeline->setUniform1i("hasClouds", 0);
}

}

renderTargetPipeline->setUniform1i("TextureType",
Expand Down
Loading
Loading