diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index e83b9045..23bf09b7 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -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" diff --git a/CMakeLists.txt b/CMakeLists.txt index 42e0dca6..dc48eb84 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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") @@ -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}") @@ -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) @@ -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} @@ -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}") @@ -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} @@ -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 () @@ -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 () @@ -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") @@ -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" diff --git a/atlas/application/window.cpp b/atlas/application/window.cpp index 6c334ba0..c5dec2c4 100644 --- a/atlas/application/window.cpp +++ b/atlas/application/window.cpp @@ -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; @@ -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()) { diff --git a/atlas/graphics/render_target.cpp b/atlas/graphics/render_target.cpp index 377acf6f..639a8322 100644 --- a/atlas/graphics/render_target.cpp +++ b/atlas/graphics/render_target.cpp @@ -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(ambientColor.r), - static_cast(ambientColor.g), - static_cast(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(sunColor.r), - static_cast(sunColor.g), static_cast(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", diff --git a/atlas/object/shader.cpp b/atlas/object/shader.cpp index 20004ee4..be065a1f 100644 --- a/atlas/object/shader.cpp +++ b/atlas/object/shader.cpp @@ -55,18 +55,8 @@ VertexShader VertexShader::fromDefaultShader(AtlasVertexShader shader) { VertexShader::vertexShaderCache[shader] = vertexShader; break; } - case AtlasVertexShader::Main: { - vertexShader = VertexShader::fromSource(MAIN_VERT); - vertexShader.desiredAttributes = {0, 1, 2, 3, 4, 5}; - vertexShader.capabilities = { - ShaderCapability::Lighting, ShaderCapability::Textures, - ShaderCapability::Shadows, ShaderCapability::EnvironmentMapping, - ShaderCapability::IBL, ShaderCapability::Material, - ShaderCapability::Instances, ShaderCapability::Environment}; - vertexShader.fromDefaultShaderType = shader; - VertexShader::vertexShaderCache[shader] = vertexShader; - break; - } + case AtlasVertexShader::Main: + return VertexShader::fromDefaultShader(AtlasVertexShader::Deferred); case AtlasVertexShader::Texture: { vertexShader = VertexShader::fromSource(TEXTURE_VERT); vertexShader.desiredAttributes = {0, 1, 2}; @@ -115,20 +105,10 @@ VertexShader VertexShader::fromDefaultShader(AtlasVertexShader shader) { VertexShader::vertexShaderCache[shader] = vertexShader; break; } - case AtlasVertexShader::PointLightShadow: { - vertexShader = VertexShader::fromSource(POINT_DEPTH_VERT); - vertexShader.desiredAttributes = {0}; - vertexShader.capabilities = {ShaderCapability::Instances}; - vertexShader.fromDefaultShaderType = shader; - VertexShader::vertexShaderCache[shader] = vertexShader; - break; - } + case AtlasVertexShader::PointLightShadow: + return VertexShader::fromDefaultShader(AtlasVertexShader::PointLightShadowNoGeom); case AtlasVertexShader::PointLightShadowNoGeom: { -#ifdef VULKAN vertexShader = VertexShader::fromSource(POINT_DEPTH_NOGEOM_VERT); -#else - vertexShader = VertexShader::fromSource(POINT_DEPTH_VERT); -#endif vertexShader.desiredAttributes = {0}; vertexShader.capabilities = {ShaderCapability::Instances}; vertexShader.fromDefaultShaderType = shader; @@ -156,14 +136,8 @@ VertexShader VertexShader::fromDefaultShader(AtlasVertexShader shader) { VertexShader::vertexShaderCache[shader] = vertexShader; break; } - case AtlasVertexShader::Terrain: { - vertexShader = VertexShader::fromSource(TERRAIN_VERT); - vertexShader.desiredAttributes = {}; - vertexShader.capabilities = {}; - vertexShader.fromDefaultShaderType = shader; - VertexShader::vertexShaderCache[shader] = vertexShader; - break; - } + case AtlasVertexShader::Terrain: + throw std::runtime_error("Legacy tessellated terrain shaders were removed"); case AtlasVertexShader::Volumetric: { vertexShader = VertexShader::fromSource(VOLUMETRIC_VERT); vertexShader.desiredAttributes = {0, 2}; @@ -234,48 +208,43 @@ ComputeShader ComputeShader::fromDefaultShader(AtlasComputeShader shader) { ComputeShader computeShader; switch (shader) { case AtlasComputeShader::DDGI: { -#ifdef METAL +#if ATLAS_HAS_PHOTON computeShader = ComputeShader::fromSource(DDGI); computeShader.fromDefaultShaderType = shader; ComputeShader::computeShaderCache[shader] = computeShader; break; #else throw std::runtime_error( - "AtlasComputeShader::DDGI is only supported on Metal"); + "AtlasComputeShader::DDGI requires native Photon shaders for the selected backend"); #endif } case AtlasComputeShader::DDGI_WRITE: { -#ifdef METAL +#if ATLAS_HAS_PHOTON computeShader = ComputeShader::fromSource(DDGI_WRITE); computeShader.fromDefaultShaderType = shader; ComputeShader::computeShaderCache[shader] = computeShader; break; #else throw std::runtime_error( - "AtlasComputeShader::DDGI_WRITE is only supported on Metal"); + "AtlasComputeShader::DDGI_WRITE requires native Photon shaders for the selected backend"); #endif } case AtlasComputeShader::PathTracer: { -#ifdef METAL +#if ATLAS_HAS_PHOTON computeShader = ComputeShader::fromSource(PATH); computeShader.fromDefaultShaderType = shader; ComputeShader::computeShaderCache[shader] = computeShader; break; #else throw std::runtime_error( - "AtlasComputeShader::PathTracer is only supported on Metal"); + "AtlasComputeShader::PathTracer requires native Photon shaders for the selected backend"); #endif } case AtlasComputeShader::PathDenoiser: { -#ifdef METAL computeShader = ComputeShader::fromSource(PATH_DENOISE); computeShader.fromDefaultShaderType = shader; ComputeShader::computeShaderCache[shader] = computeShader; break; -#else - throw std::runtime_error( - "AtlasComputeShader::PathDenoiser is only supported on Metal"); -#endif } default: throw std::runtime_error("Unknown default compute shader"); @@ -339,12 +308,8 @@ FragmentShader FragmentShader::fromDefaultShader(AtlasFragmentShader shader) { fragmentShaderCache[shader] = fragmentShader; break; } - case AtlasFragmentShader::Main: { - fragmentShader = FragmentShader::fromSource(MAIN_FRAG); - fragmentShader.fromDefaultShaderType = shader; - fragmentShaderCache[shader] = fragmentShader; - break; - } + case AtlasFragmentShader::Main: + return FragmentShader::fromDefaultShader(AtlasFragmentShader::Deferred); case AtlasFragmentShader::GaussianBlur: { fragmentShader = FragmentShader::fromSource(GAUSSIAN_FRAG); fragmentShader.fromDefaultShaderType = shader; @@ -387,17 +352,13 @@ FragmentShader FragmentShader::fromDefaultShader(AtlasFragmentShader shader) { fragmentShaderCache[shader] = fragmentShader; break; } - case AtlasFragmentShader::PointLightShadow: { - fragmentShader = FragmentShader::fromSource(POINT_DEPTH_FRAG); - fragmentShader.fromDefaultShaderType = shader; - fragmentShaderCache[shader] = fragmentShader; - break; - } + case AtlasFragmentShader::PointLightShadow: + return FragmentShader::fromDefaultShader(AtlasFragmentShader::PointLightShadowNoGeom); case AtlasFragmentShader::PointLightShadowNoGeom: { #ifdef OPENGL fragmentShader = FragmentShader::fromSource(EMPTY_FRAG); #elif defined(VULKAN) || defined(METAL) - fragmentShader = FragmentShader::fromSource(POINT_DEPTH_FRAG); + fragmentShader = FragmentShader::fromSource(POINT_DEPTH_NOGEOM_FRAG); #endif fragmentShader.fromDefaultShaderType = shader; fragmentShaderCache[shader] = fragmentShader; @@ -427,12 +388,8 @@ FragmentShader FragmentShader::fromDefaultShader(AtlasFragmentShader shader) { fragmentShaderCache[shader] = fragmentShader; break; } - case AtlasFragmentShader::Terrain: { - fragmentShader = FragmentShader::fromSource(TERRAIN_FRAG); - fragmentShader.fromDefaultShaderType = shader; - fragmentShaderCache[shader] = fragmentShader; - break; - } + case AtlasFragmentShader::Terrain: + throw std::runtime_error("Legacy tessellated terrain shaders were removed"); case AtlasFragmentShader::Volumetric: { fragmentShader = FragmentShader::fromSource(VOLUMETRIC_FRAG); fragmentShader.fromDefaultShaderType = shader; @@ -509,7 +466,7 @@ void FragmentShader::compile() { GeometryShader GeometryShader::fromDefaultShader(AtlasGeometryShader shader) { switch (shader) { case AtlasGeometryShader::PointLightShadow: - return GeometryShader::fromSource(POINT_DEPTH_GEOM); + throw std::runtime_error("Point-light shadows use six vertex passes"); default: throw std::runtime_error("Unknown default geometry shader"); } @@ -556,11 +513,9 @@ TessellationShader TessellationShader::fromDefaultShader(AtlasTessellationShader shader) { switch (shader) { case AtlasTessellationShader::TerrainControl: - return TessellationShader::fromSource(TERRAIN_CONTROL_TESC, - TessellationShaderType::Control); + throw std::runtime_error("Legacy tessellated terrain shaders were removed"); case AtlasTessellationShader::TerrainEvaluation: - return TessellationShader::fromSource( - TERRAIN_EVAL_TESE, TessellationShaderType::Evaluation); + throw std::runtime_error("Legacy tessellated terrain shaders were removed"); default: throw std::runtime_error("Unknown default tessellation shader"); } diff --git a/cmake/AtlasShaders.cmake b/cmake/AtlasShaders.cmake new file mode 100644 index 00000000..cc0f5b37 --- /dev/null +++ b/cmake/AtlasShaders.cmake @@ -0,0 +1,62 @@ +set(SHADER_INPUT_DIR "${CMAKE_SOURCE_DIR}/shaders") +string(TOLOWER "${BACKEND}" SHADER_BACKEND_ARG) +set(SHADER_GENERATED_INCLUDE_DIR "${CMAKE_BINARY_DIR}/generated/${SHADER_BACKEND_ARG}") +set(SHADER_OUTPUT_FILE "${SHADER_GENERATED_INCLUDE_DIR}/atlas/core/default_shaders.h") +include_directories(BEFORE "${SHADER_GENERATED_INCLUDE_DIR}") + +find_package(Python3 COMPONENTS Interpreter REQUIRED) +find_program(SLANGC_EXECUTABLE NAMES slangc REQUIRED) +find_program(SPIRV_CROSS_EXECUTABLE NAMES spirv-cross REQUIRED) + +set(ATLAS_PHOTON_BACKEND "AUTO" CACHE STRING "Native Photon shaders: AUTO, METAL, VULKAN, OFF") +set_property(CACHE ATLAS_PHOTON_BACKEND PROPERTY STRINGS AUTO METAL VULKAN OFF) +string(TOUPPER "${ATLAS_PHOTON_BACKEND}" PHOTON_SHADER_BACKEND) +if (PHOTON_SHADER_BACKEND STREQUAL "AUTO") + if (BACKEND_METAL) + set(PHOTON_SHADER_BACKEND "METAL") + else () + set(PHOTON_SHADER_BACKEND "OFF") + endif () +endif () +if (NOT PHOTON_SHADER_BACKEND MATCHES "^(METAL|VULKAN|OFF)$") + message(FATAL_ERROR "Invalid ATLAS_PHOTON_BACKEND='${ATLAS_PHOTON_BACKEND}'") +endif () +if (NOT PHOTON_SHADER_BACKEND STREQUAL "OFF" AND NOT PHOTON_SHADER_BACKEND STREQUAL BACKEND) + message(FATAL_ERROR "Photon's shader backend must match BACKEND") +endif () +string(TOLOWER "${PHOTON_SHADER_BACKEND}" PHOTON_SHADER_BACKEND_ARG) +if (NOT PHOTON_SHADER_BACKEND STREQUAL "OFF" AND + NOT EXISTS "${SHADER_INPUT_DIR}/photon/${PHOTON_SHADER_BACKEND_ARG}/manifest.json") + message(FATAL_ERROR "Photon ${PHOTON_SHADER_BACKEND} shaders are not implemented; add shaders/photon/${PHOTON_SHADER_BACKEND_ARG}/manifest.json first") +endif () + +file(GLOB_RECURSE SHADER_SOURCES CONFIGURE_DEPENDS + "${SHADER_INPUT_DIR}/*.slang" + "${SHADER_INPUT_DIR}/*.metal" + "${SHADER_INPUT_DIR}/*.spv" + "${SHADER_INPUT_DIR}/*.json" +) + +set(RUNTIME_SCRIPT_INPUT_DIR "${CMAKE_SOURCE_DIR}/runtime/scripts") +set(RUNTIME_SCRIPT_OUTPUT_FILE "${CMAKE_SOURCE_DIR}/include/atlas/runtime/atlasScripts.h") +file(GLOB_RECURSE RUNTIME_SCRIPT_SOURCES CONFIGURE_DEPENDS + ${RUNTIME_SCRIPT_INPUT_DIR}/*.js + ${RUNTIME_SCRIPT_INPUT_DIR}/*.mjs +) + +set(SHADER_GENERATION_CONFIG "${SHADER_GENERATED_INCLUDE_DIR}/shader-config.txt") +file(GENERATE OUTPUT "${SHADER_GENERATION_CONFIG}" + CONTENT "${BACKEND}\n${PHOTON_SHADER_BACKEND}\n${SLANGC_EXECUTABLE}\n${SPIRV_CROSS_EXECUTABLE}\n") +add_custom_command( + OUTPUT "${SHADER_OUTPUT_FILE}" + COMMAND ${Python3_EXECUTABLE} "${CMAKE_SOURCE_DIR}/scripts/pack_shaders.py" + "${SHADER_INPUT_DIR}" "${SHADER_OUTPUT_FILE}" "${SHADER_BACKEND_ARG}" + --slangc "${SLANGC_EXECUTABLE}" + --spirv-cross "${SPIRV_CROSS_EXECUTABLE}" + --photon-backend "${PHOTON_SHADER_BACKEND_ARG}" + DEPENDS ${SHADER_SOURCES} "${CMAKE_SOURCE_DIR}/scripts/pack_shaders.py" + "${SHADER_GENERATION_CONFIG}" "${SLANGC_EXECUTABLE}" "${SPIRV_CROSS_EXECUTABLE}" + VERBATIM +) +add_custom_target(generate_shaders DEPENDS "${SHADER_OUTPUT_FILE}") + diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt index 5a1e308c..65f79c9b 100644 --- a/editor/CMakeLists.txt +++ b/editor/CMakeLists.txt @@ -173,7 +173,7 @@ if (APPLE) endif () qt_add_executable(AtlasEditor ${EDITOR_FILES}) -add_dependencies(AtlasEditor generate_atlas_themes atlas_editor_cli) +add_dependencies(AtlasEditor generate_shaders generate_atlas_themes atlas_editor_cli) if (APPLE) set_target_properties(AtlasEditor PROPERTIES diff --git a/include/atlas/core/default_shaders.h b/include/atlas/core/default_shaders.h deleted file mode 100644 index a370c282..00000000 --- a/include/atlas/core/default_shaders.h +++ /dev/null @@ -1,10601 +0,0 @@ -// This file contains packed shader source code. -// Metal shaders packed as source -#ifndef ATLAS_GENERATED_SHADERS_H -#define ATLAS_GENERATED_SHADERS_H - -#include - -namespace opal { -const char *packedShaderSource(const char *const *parts, std::size_t count); -} - -struct AtlasPackedShaderSource { - const char *const *parts; - std::size_t count; - - operator const char *() const { - return opal::packedShaderSource(parts, count); - } -}; - -static const char* const COLOR_FRAG_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct main0_out -{ - float4 FragColor [[color(0)]]; - float4 BrightColor [[color(1)]]; -}; - -struct main0_in -{ - float4 vertexColor [[user(locn0)]]; -}; - -fragment main0_out main0(main0_in in [[stage_in]]) -{ - main0_out out = {}; - float3 color = in.vertexColor.xyz / (in.vertexColor.xyz + float3(1.0)); - out.FragColor = float4(color, in.vertexColor.w); - if (length(color) > 1.0) - { - out.BrightColor = float4(color, in.vertexColor.w); - } - return out; -} - -)", -}; -static const AtlasPackedShaderSource COLOR_FRAG = {COLOR_FRAG_PARTS, 1}; - -static const char* const COLOR_VERT_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct UBO -{ - float4x4 model; - float4x4 view; - float4x4 projection; - uint isInstanced; -}; - -struct main0_out -{ - float4 vertexColor [[user(locn0)]]; - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; - float4 aColor [[attribute(1)]]; - float4 instanceModel_0 [[attribute(6)]]; - float4 instanceModel_1 [[attribute(7)]]; - float4 instanceModel_2 [[attribute(8)]]; - float4 instanceModel_3 [[attribute(9)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]], constant UBO& _12 [[buffer(0)]]) -{ - main0_out out = {}; - float4x4 instanceModel = {}; - instanceModel[0] = in.instanceModel_0; - instanceModel[1] = in.instanceModel_1; - instanceModel[2] = in.instanceModel_2; - instanceModel[3] = in.instanceModel_3; - float4x4 mvp; - bool hasInstanceMatrix = abs(instanceModel[3].w) > 0.5; - if ((_12.isInstanced != 0u) && hasInstanceMatrix) - { - mvp = (_12.projection * _12.view) * instanceModel; - } - else - { - mvp = (_12.projection * _12.view) * _12.model; - } - out.gl_Position = mvp * float4(in.aPos, 1.0); - out.vertexColor = in.aColor; - return out; -} -)", -}; -static const AtlasPackedShaderSource COLOR_VERT = {COLOR_VERT_PARTS, 1}; - -static const char* const DDGI_PARTS[] = { -R"(#include -#include -using namespace metal; -using namespace raytracing; - -struct ProbeSpace { - float3 origin; - float _pad0; - - float3 spacing; - float _pad1; - - float3 probeCount; - float _pad2; - - float4 debugColor; - - float4 atlasParams; -}; - -struct RaytracingSettings { - uint raysPerProbe; - float maxRayDistance; - float normalBias; - float hysteresis; - - uint frameIndex; - uint probeUpdateOffset; - uint probeUpdateStride; - uint probeUpdateCount; - float3 skyColor; - uint useSkybox; -}; - -struct Material { - int materialID; - int albedoTextureIndex; - int normalTextureIndex; - int metallicTextureIndex; - int roughnessTextureIndex; - int aoTextureIndex; - float metallic; - float roughness; - float ao; - float emissiveIntensity; - - packed_float3 albedo; - float _pad0; - - packed_float3 emissiveColor; - float _pad1; -}; - -struct Triangle { - float4 v0; - float4 v1; - float4 v2; - float4 n0; - float4 n1; - float4 n2; - - float4 uv0; - float4 uv1; - float4 uv2; - - float4 t0; - float4 t1; - float4 t2; - - float4 b0; - float4 b1; - float4 b2; - - int materialID; - int padding[3]; -}; - -struct SceneCounts { - uint triCount; - uint materialCount; - uint directionalLightCount; - uint pointLightCount; - uint spotLightCount; - uint areaLightCount; - uint textureCount; - uint _pad0; -}; - -struct DirectionalLight { - packed_float3 direction; - float _pad1; - packed_float3 diffuse; - float _pad2; - packed_float3 specular; - float intensity; -}; - -struct PointLight { - packed_float3 position; - float _pad1; - packed_float3 diffuse; - float _pad2; - packed_float3 specular; - float intensity; - float constant0; - float linear; - float quadratic; - float radius; - float _pad3; -}; - -struct SpotLight { - packed_float3 position; - float _pad1; - packed_float3 direction; - float cutOff; - float outerCutOff; - float intensity; - float range; - float _pad4; - packed_float3 diffuse; - float _pad5; - packed_float3 specular; - float _pad6; -}; - -struct AreaLight { - packed_float3 position; - float _pad1; - packed_float3 right; - float _pad2; - packed_float3 up; - float _pad3; - float2 size; - float _pad4; - float _pad5; - packed_float3 diffuse; - float _pad6; - packed_float3 specular; - float angle; - int castsBothSides; - float intensity; - float range; - float _pad9; -}; - -struct Hit { - float t; - float3 n; - float2 uv; - float3 tangent; - float3 bitangent; - int materialID; - uint triIndex; - uint hit; - uint _pad0; -}; - -static inline bool rayTriangleMT(float3 ro, float3 rd, float3 v0, float3 v1, - float3 v2, thread float &t, thread float &u, - thread float &v) { - float3 e1 = v1 - v0; - float3 e2 = v2 - v0; - float3 p = cross(rd, e2); - float det = dot(e1, p); - - if (fabs(det) < 1e-8f) - return false; - float invDet = 1.0f / det; - - float3 s = ro - v0; - u = dot(s, p) * invDet; - if (u < 0.0f || u > 1.0f) - return false; - - float3 q = cross(s, e1); - v = dot(rd, q) * invDet; - if (v < 0.0f || u + v > 1.0f) - return false; - - t = dot(e2, q) * invDet; - return t > 0.0f; -} - -static inline Hit traceScene(float3 ro, float3 rd, device const Triangle *tris, - instance_acceleration_structure sceneAS, - float maxDistance) { - Hit best; - best.t = INFINITY; - best.hit = 0u; - best.materialID = -1; - best.n = float3(0.0f, 1.0f, 0.0f); - best.uv = float2(0.0f); - best.tangent = float3(1.0f, 0.0f, 0.0f); - best.bitangent = float3(0.0f, 0.0f, 1.0f); - best.triIndex = 0u; - best._pad0 = 0u; - - intersector isect; - isect.assume_geometry_type(geometry_type::triangle); - isect.set_triangle_cull_mode(triangle_cull_mode::none); - ray query; - query.origin = ro; - query.direction = rd; - query.min_distance = 0.0001f; - query.max_distance = max(maxDistance, query.min_distance); - auto intersection = isect.intersect(query, sceneAS, 0xFF); - if (intersection.type != intersection_type::none) { - uint i = intersection.primitive_id; - float2 bary = intersection.triangle_barycentric_coord; - float u = bary.x; - float v = bary.y; - float w = 1.0f - u - v; - best.t = intersection.distance; - best.n = normalize(tris[i].n0.xyz * w + tris[i].n1.xyz * u + - tris[i].n2.xyz * v); - best.uv = tris[i].uv0.xy * w + tris[i].uv1.xy * u + tris[i].uv2.xy * v; - float3 tRaw = tris[i].t0.xyz * w + tris[i].t1.xyz * u + tris[i].t2.xyz * v; - float tLen2 = dot(tRaw, tRaw); - best.tangent = (tLen2 > 1e-10f) ? tRaw * rsqrt(tLen2) - : float3(1.0f, 0.0f, 0.0f); - float3 bRaw = tris[i].b0.xyz * w + tris[i].b1.xyz * u + tris[i].b2.xyz * v; - float bLen2 = dot(bRaw, bRaw); - best.bitangent = (bLen2 > 1e-10f) ? bRaw * rsqrt(bLen2) - : float3(0.0f, 0.0f, 1.0f); - best.materialID = tris[i].materialID; - best.triIndex = i; - best.hit = 1u; - } - - return best; -} - -static inline uint wangHash(uint x) { - x = (x ^ 61u) ^ (x >> 16); - x *= 9u; - x = x ^ (x >> 4); - x *= 0x27d4eb2du; - x = x ^ (x >> 15); - return x; -} - -static inline float rand01(thread uint &state) { - state = wangHash(state); - return (float)(state & 0x00FFFFFFu) / 16777216.0f; -} - -static inline uint3 probeCoordFromIndex(uint idx, uint3 counts) { - uint xy = counts.x * counts.y; - uint z = idx / xy; - uint rem = idx - z * xy; - uint y = rem / counts.x; - uint x = rem - y * counts.x; - return uint3(x, y, z); -} - -static inline float3 safeNormalize(float3 v, float3 fallback) { - float len2 = dot(v, v); - if (len2 > 1e-10f) { - return v * rsqrt(len2); - } - return fallback; -} - -constexpr sampler materialTexSampler(coord::normalized, address::repeat, - filter::linear, mip_filter::linear); - -static inline float4 sampleMaterialTexture( - int textureIndex, float2 uv, texture2d materialTexture0, - texture2d materialTexture1, texture2d materialTexture2, - texture2d materialTexture3, texture2d materialTexture4, - texture2d materialTexture5, texture2d materialTexture6, - texture2d materialTexture7, texture2d materialTexture8, - texture2d materialTexture9, texture2d materialTexture10, - texture2d materialTexture11, texture2d materialTexture12, - texture2d materialTexture13, texture2d materialTexture14, - texture2d materialTexture15, texture2d materialTexture16, - texture2d materialTexture17, texture2d materialTexture18, - texture2d materialTexture19, texture2d materialTexture20, - texture2d materialTexture21, texture2d materialTexture22, - texture2d materialTexture23, texture2d materialTexture24, - texture2d materialTexture25, texture2d materialTexture26, - texture2d materialTexture27, texture2d materialTexture28, - texture2d materialTexture29, texture2d materialTexture30, - texture2d materialTexture31, texture2d materialTexture32, - texture2d materialTexture33, texture2d materialTexture34, - texture2d materialTexture35, texture2d materialTexture36, - texture2d materialTexture37, texture2d materialTexture38, - texture2d materialTexture39, texture2d materialTexture40, - texture2d materialTexture41, texture2d materialTexture42, - texture2d materialTexture43, texture2d materialTexture44, - texture2d materialTexture45, texture2d materialTexture46, - texture2d materialTexture47) { - switch (textureIndex) { - case 0: - return materialTexture0.sample)", -R"((materialTexSampler, uv); - case 1: - return materialTexture1.sample(materialTexSampler, uv); - case 2: - return materialTexture2.sample(materialTexSampler, uv); - case 3: - return materialTexture3.sample(materialTexSampler, uv); - case 4: - return materialTexture4.sample(materialTexSampler, uv); - case 5: - return materialTexture5.sample(materialTexSampler, uv); - case 6: - return materialTexture6.sample(materialTexSampler, uv); - case 7: - return materialTexture7.sample(materialTexSampler, uv); - case 8: - return materialTexture8.sample(materialTexSampler, uv); - case 9: - return materialTexture9.sample(materialTexSampler, uv); - case 10: - return materialTexture10.sample(materialTexSampler, uv); - case 11: - return materialTexture11.sample(materialTexSampler, uv); - case 12: - return materialTexture12.sample(materialTexSampler, uv); - case 13: - return materialTexture13.sample(materialTexSampler, uv); - case 14: - return materialTexture14.sample(materialTexSampler, uv); - case 15: - return materialTexture15.sample(materialTexSampler, uv); - case 16: - return materialTexture16.sample(materialTexSampler, uv); - case 17: - return materialTexture17.sample(materialTexSampler, uv); - case 18: - return materialTexture18.sample(materialTexSampler, uv); - case 19: - return materialTexture19.sample(materialTexSampler, uv); - case 20: - return materialTexture20.sample(materialTexSampler, uv); - case 21: - return materialTexture21.sample(materialTexSampler, uv); - case 22: - return materialTexture22.sample(materialTexSampler, uv); - case 23: - return materialTexture23.sample(materialTexSampler, uv); - case 24: - return materialTexture24.sample(materialTexSampler, uv); - case 25: - return materialTexture25.sample(materialTexSampler, uv); - case 26: - return materialTexture26.sample(materialTexSampler, uv); - case 27: - return materialTexture27.sample(materialTexSampler, uv); - case 28: - return materialTexture28.sample(materialTexSampler, uv); - case 29: - return materialTexture29.sample(materialTexSampler, uv); - case 30: - return materialTexture30.sample(materialTexSampler, uv); - case 31: - return materialTexture31.sample(materialTexSampler, uv); - case 32: - return materialTexture32.sample(materialTexSampler, uv); - case 33: - return materialTexture33.sample(materialTexSampler, uv); - case 34: - return materialTexture34.sample(materialTexSampler, uv); - case 35: - return materialTexture35.sample(materialTexSampler, uv); - case 36: - return materialTexture36.sample(materialTexSampler, uv); - case 37: - return materialTexture37.sample(materialTexSampler, uv); - case 38: - return materialTexture38.sample(materialTexSampler, uv); - case 39: - return materialTexture39.sample(materialTexSampler, uv); - case 40: - return materialTexture40.sample(materialTexSampler, uv); - case 41: - return materialTexture41.sample(materialTexSampler, uv); - case 42: - return materialTexture42.sample(materialTexSampler, uv); - case 43: - return materialTexture43.sample(materialTexSampler, uv); - case 44: - return materialTexture44.sample(materialTexSampler, uv); - case 45: - return materialTexture45.sample(materialTexSampler, uv); - case 46: - return materialTexture46.sample(materialTexSampler, uv); - case 47: - return materialTexture47.sample(materialTexSampler, uv); - default: - break; - } - return float4(0.0f); -} - -static inline void resolveMaterialParameters( - device const Material *materials, int materialID, uint materialCount, - float2 uv, uint textureCount, texture2d materialTexture0, - texture2d materialTexture1, texture2d materialTexture2, - texture2d materialTexture3, texture2d materialTexture4, - texture2d materialTexture5, texture2d materialTexture6, - texture2d materialTexture7, texture2d materialTexture8, - texture2d materialTexture9, texture2d materialTexture10, - texture2d materialTexture11, texture2d materialTexture12, - texture2d materialTexture13, texture2d materialTexture14, - texture2d materialTexture15, texture2d materialTexture16, - texture2d materialTexture17, texture2d materialTexture18, - texture2d materialTexture19, texture2d materialTexture20, - texture2d materialTexture21, texture2d materialTexture22, - texture2d materialTexture23, texture2d materialTexture24, - texture2d materialTexture25, texture2d materialTexture26, - texture2d materialTexture27, texture2d materialTexture28, - texture2d materialTexture29, texture2d materialTexture30, - texture2d materialTexture31, texture2d materialTexture32, - texture2d materialTexture33, texture2d materialTexture34, - texture2d materialTexture35, texture2d materialTexture36, - texture2d materialTexture37, texture2d materialTexture38, - texture2d materialTexture39, texture2d materialTexture40, - texture2d materialTexture41, texture2d materialTexture42, - texture2d materialTexture43, texture2d materialTexture44, - texture2d materialTexture45, texture2d materialTexture46, - texture2d materialTexture47, thread float3 &albedo, - thread float &metallic, thread float &roughness, thread float &ao, - thread float3 &emissive, thread int &normalTextureIndex, - thread float &normalStrength) { - albedo = float3(0.7f); - metallic = 0.0f; - roughness = 0.6f; - ao = 1.0f; - emissive = float3(0.0f); - normalTextureIndex = -1; - normalStrength = 0.0f; - - if (materialID < 0 || uint(materialID) >= materialCount) { - return; - } - - const Material mat = materials[materialID]; - albedo = clamp(float3(mat.albedo), float3(0.0f), float3(1.0f)); - metallic = clamp(mat.metallic, 0.0f, 1.0f); - roughness = clamp(mat.roughness, 0.05f, 1.0f); - ao = clamp(mat.ao, 0.0f, 1.0f); - emissive = float3(mat.emissiveColor) * max(mat.emissiveIntensity, 0.0f); - normalStrength = max(mat._pad0, 0.0f); - bool useNormalMap = mat._pad1 > 0.5f && normalStrength > 0.0f; - normalTextureIndex = useNormalMap ? mat.normalTextureIndex : -1; - - if (mat.albedoTextureIndex >= 0 && uint(mat.albedoTextureIndex) < textureCount) { - albedo = clamp(sampleMaterialTexture( - mat.albedoTextureIndex, uv, materialTexture0, - materialTexture1, materialTexture2, materialTexture3, - materialTexture4, materialTexture5, materialTexture6, - materialTexture7, materialTexture8, materialTexture9, - materialTexture10, materialTexture11, - materialTexture12, materialTexture13, - materialTexture14, materialTexture15, - materialTexture16, materialTexture17, - materialTexture18, materialTexture19, - materialTexture20, materialTexture21, - materialTexture22, materialTexture23, - materialTexture24, materialTexture25, - materialTexture26, materialTexture27, - materialTexture28, materialTexture29, - materialTexture30, materialTexture31, - materialTexture32, materialTexture33, - materialTexture34, materialTexture35, - materialTexture36, materialTexture37, - materialTexture38, materialTexture39, - materialTexture40, materialTexture41, - materialTexture42)", -R"(, materialTexture43, - materialTexture44, materialTexture45, - materialTexture46, materialTexture47) - .xyz, - float3(0.0f), float3(1.0f)); - } - if (mat.metallicTextureIndex >= 0 && - uint(mat.metallicTextureIndex) < textureCount) { - float4 metallicSample = sampleMaterialTexture( - mat.metallicTextureIndex, uv, materialTexture0, materialTexture1, - materialTexture2, materialTexture3, materialTexture4, - materialTexture5, materialTexture6, materialTexture7, - materialTexture8, materialTexture9, materialTexture10, - materialTexture11, materialTexture12, materialTexture13, - materialTexture14, materialTexture15, materialTexture16, - materialTexture17, materialTexture18, materialTexture19, - materialTexture20, materialTexture21, materialTexture22, - materialTexture23, materialTexture24, materialTexture25, - materialTexture26, materialTexture27, materialTexture28, - materialTexture29, materialTexture30, materialTexture31, - materialTexture32, materialTexture33, materialTexture34, - materialTexture35, materialTexture36, materialTexture37, - materialTexture38, materialTexture39, materialTexture40, - materialTexture41, materialTexture42, materialTexture43, - materialTexture44, materialTexture45, materialTexture46, - materialTexture47); - float metallicValue = metallicSample.x; - if (mat.roughnessTextureIndex == mat.metallicTextureIndex) { - metallicValue = metallicSample.z; - } - metallic *= clamp(metallicValue, 0.0f, 1.0f); - } - if (mat.roughnessTextureIndex >= 0 && - uint(mat.roughnessTextureIndex) < textureCount) { - float4 roughnessSample = sampleMaterialTexture( - mat.roughnessTextureIndex, uv, materialTexture0, materialTexture1, - materialTexture2, materialTexture3, materialTexture4, - materialTexture5, materialTexture6, materialTexture7, - materialTexture8, materialTexture9, materialTexture10, - materialTexture11, materialTexture12, materialTexture13, - materialTexture14, materialTexture15, materialTexture16, - materialTexture17, materialTexture18, materialTexture19, - materialTexture20, materialTexture21, materialTexture22, - materialTexture23, materialTexture24, materialTexture25, - materialTexture26, materialTexture27, materialTexture28, - materialTexture29, materialTexture30, materialTexture31, - materialTexture32, materialTexture33, materialTexture34, - materialTexture35, materialTexture36, materialTexture37, - materialTexture38, materialTexture39, materialTexture40, - materialTexture41, materialTexture42, materialTexture43, - materialTexture44, materialTexture45, materialTexture46, - materialTexture47); - float roughnessValue = roughnessSample.x; - if (mat.roughnessTextureIndex == mat.metallicTextureIndex) { - roughnessValue = roughnessSample.y; - } - roughness *= clamp(roughnessValue, 0.0f, 1.0f); - } - if (mat.aoTextureIndex >= 0 && uint(mat.aoTextureIndex) < textureCount) { - ao *= clamp(sampleMaterialTexture( - mat.aoTextureIndex, uv, materialTexture0, - materialTexture1, materialTexture2, materialTexture3, - materialTexture4, materialTexture5, materialTexture6, - materialTexture7, materialTexture8, materialTexture9, - materialTexture10, materialTexture11, - materialTexture12, materialTexture13, - materialTexture14, materialTexture15, - materialTexture16, materialTexture17, - materialTexture18, materialTexture19, - materialTexture20, materialTexture21, - materialTexture22, materialTexture23, - materialTexture24, materialTexture25, - materialTexture26, materialTexture27, - materialTexture28, materialTexture29, - materialTexture30, materialTexture31, - materialTexture32, materialTexture33, - materialTexture34, materialTexture35, - materialTexture36, materialTexture37, - materialTexture38, materialTexture39, - materialTexture40, materialTexture41, - materialTexture42, materialTexture43, - materialTexture44, materialTexture45, - materialTexture46, materialTexture47) - .x, - 0.0f, 1.0f); - } - - emissive = clamp(emissive, float3(0.0f), float3(8.0f)); - roughness = clamp(roughness, 0.05f, 1.0f); - metallic = clamp(metallic, 0.0f, 1.0f); - ao = clamp(ao, 0.0f, 1.0f); -} - -static inline float3 resolveNormal( - int normalTextureIndex, float normalStrength, float2 uv, float3 n, float3 tangent, - float3 bitangent, uint textureCount, texture2d materialTexture0, - texture2d materialTexture1, texture2d materialTexture2, - texture2d materialTexture3, texture2d materialTexture4, - texture2d materialTexture5, texture2d materialTexture6, - texture2d materialTexture7, texture2d materialTexture8, - texture2d materialTexture9, texture2d materialTexture10, - texture2d materialTexture11, texture2d materialTexture12, - texture2d materialTexture13, texture2d materialTexture14, - texture2d materialTexture15, texture2d materialTexture16, - texture2d materialTexture17, texture2d materialTexture18, - texture2d materialTexture19, texture2d materialTexture20, - texture2d materialTexture21, texture2d materialTexture22, - texture2d materialTexture23, texture2d materialTexture24, - texture2d materialTexture25, texture2d materialTexture26, - texture2d materialTexture27, texture2d materialTexture28, - texture2d materialTexture29, texture2d materialTexture30, - texture2d materialTexture31, texture2d materialTexture32, - texture2d materialTexture33, texture2d materialTexture34, - texture2d materialTexture35, texture2d materialTexture36, - texture2d materialTexture37, texture2d materialTexture38, - texture2d materialTexture39, texture2d materialTexture40, - texture2d materialTexture41, texture2d materialTexture42, - texture2d materialTexture43, texture2d materialTexture44, - texture2d materialTexture45, texture2d materialTexture46, - texture2d materialTexture47) { - float3 N = safeNormalize(n, float3(0.0f, 1.0f, 0.0f)); - float3 T = safeNormalize(tangent - N * dot(N, tangent), float3(1.0f, 0.0f, 0.0f)); - float3 B = safeNormalize(bitangent - N * dot(N, bitangent), cross(N, T)); - if (dot(cross(T, B), cross(T, B)) <= 1e-10f) { - float3 up = (fabs(N.y) < 0.999f) ? float3(0.0f, 1.0f, 0.0f) - : float3(1.0f, 0.0f, 0.0f); - T = safeNormalize(cross(up, N), float3(1.0f, 0.0f, 0.0f)); - B = safeNormalize(cross(N, T), float3(0.0f, 0.0f, 1.0f)); - } - if (normalTextureIndex >= 0 && uint(normalTextureIndex) < textureCount && - normalStrength > 0.0f) { - float3 texN = sampleMaterialTexture( - normalTextureIndex, uv, materialTexture0, - materialTexture1, materialTexture2, materialTexture3, - materialTexture4, materialTexture5, materialTexture6, - materialTexture7, materialTexture8, materialTexture9, - materialTexture10, m)", -R"(aterialTexture11, - materialTexture12, materialTexture13, - materialTexture14, materialTexture15, - materialTexture16, materialTexture17, - materialTexture18, materialTexture19, - materialTexture20, materialTexture21, - materialTexture22, materialTexture23, - materialTexture24, materialTexture25, - materialTexture26, materialTexture27, - materialTexture28, materialTexture29, - materialTexture30, materialTexture31, - materialTexture32, materialTexture33, - materialTexture34, materialTexture35, - materialTexture36, materialTexture37, - materialTexture38, materialTexture39, - materialTexture40, materialTexture41, - materialTexture42, materialTexture43, - materialTexture44, materialTexture45, - materialTexture46, materialTexture47) - .xyz; - texN = texN * 2.0f - 1.0f; - texN.xy *= normalStrength; - texN = safeNormalize(texN, float3(0.0f, 0.0f, 1.0f)); - N = safeNormalize(float3x3(T, B, N) * texN, N); - } - return N; -} - -static inline float2 octEncode(float3 n) { - n /= max(fabs(n.x) + fabs(n.y) + fabs(n.z), 1e-6f); - float2 e = n.xy; - if (n.z < 0.0f) { - float2 signNotZero = - float2(e.x >= 0.0f ? 1.0f : -1.0f, e.y >= 0.0f ? 1.0f : -1.0f); - e = (1.0f - fabs(e.yx)) * signNotZero; - } - return e; -} - -constexpr sampler ddgiLinearSampler(coord::normalized, address::clamp_to_edge, - filter::linear); - -static inline float3 samplePreviousIrradiance(texture2d previous, - constant ProbeSpace &ps, - float3 posWS, float3 direction) { - uint3 counts = uint3(ps.probeCount); - if (counts.x == 0u || counts.y == 0u || counts.z == 0u) { - return float3(0.0f); - } - float3 grid = clamp((posWS - ps.origin) / max(ps.spacing, float3(1e-4f)), - float3(0.0f), float3(counts - 1u)); - uint3 coord = uint3(round(grid)); - uint probeIndex = coord.x + counts.x * (coord.y + counts.y * coord.z); - uint border = uint(ps.atlasParams.x); - uint innerRes = uint(ps.atlasParams.y); - uint probesPerRow = uint(ps.atlasParams.z); - uint tileRes = innerRes + 2u * border; - uint2 tile = uint2(probeIndex % probesPerRow, probeIndex / probesPerRow); - float2 inner = octEncode(safeNormalize(direction, float3(0.0f, 1.0f, 0.0f))) * - 0.5f + - 0.5f; - float2 pixel = float2(tile * tileRes + border) + - inner * float(max(innerRes, 1u) - 1u) + 0.5f; - float3 history = previous.sample( - ddgiLinearSampler, - pixel / float2(previous.get_width(), - previous.get_height())) - .xyz; - return all(isfinite(history)) ? max(history, float3(0.0f)) - : float3(0.0f); -} - -static inline float3 sampleSky(float3 d, texturecube skybox, - float3 skyColor, uint useSkybox) { - if (useSkybox != 0u) { - return max(skybox.sample(ddgiLinearSampler, d).xyz, float3(0.0f)); - } - float t = clamp(d.y * 0.5f + 0.5f, 0.0f, 1.0f); - return mix(skyColor * 0.08f, skyColor, t); -} - -static inline float shadowVisibility(float3 ro, float3 rd, float maxT, - device const Triangle *tris, - instance_acceleration_structure sceneAS) { - if (maxT <= 1e-4f) { - return 1.0f; - } - Hit h = traceScene(ro, rd, tris, sceneAS, maxT); - if (!h.hit) { - return 1.0f; - } - float minOccluderDistance = max(0.01f, maxT * 0.0025f); - if (h.t <= minOccluderDistance) { - return 1.0f; - } - return (h.t >= maxT) ? 1.0f : 0.0f; -} - -static inline float giNdotL(float3 n, float3 l) { - return max(dot(n, l), 0.0f); -} - -static inline float3 evaluateDirectLights( - float3 posWS, float3 normalWS, float bias, float maxDistance, - device const Triangle *tris, instance_acceleration_structure sceneAS, - device const DirectionalLight *directionalLights, uint directionalLightCount, - device const PointLight *pointLights, uint pointLightCount, - device const SpotLight *spotLights, uint spotLightCount, - device const AreaLight *areaLights, uint areaLightCount) { - float3 n = safeNormalize(normalWS, float3(0.0f, 1.0f, 0.0f)); - float3 sum = float3(0.0f); - - for (uint i = 0; i < directionalLightCount; i++) { - float3 L = safeNormalize(-directionalLights[i].direction, - float3(0.0f, 1.0f, 0.0f)); - float ndl = giNdotL(n, L); - if (ndl <= 0.0f) - continue; - - float visibility = shadowVisibility(posWS + n * bias, L, maxDistance, - tris, sceneAS); - sum += directionalLights[i].diffuse * - max(0.0f, directionalLights[i].intensity) * ndl * visibility; - } - - for (uint i = 0; i < pointLightCount; i++) { - float3 toLight = pointLights[i].position - posWS; - float dist = length(toLight); - float radius = max(pointLights[i].radius, 0.001f); - if (dist <= 1e-4f || dist >= radius) - continue; - - float3 L = toLight / dist; - float ndl = giNdotL(n, L); - if (ndl <= 0.0f) - continue; - - float attenuation = - 1.0f / max(pointLights[i].constant0 + pointLights[i].linear * dist + - pointLights[i].quadratic * dist * dist, - 1e-4f); - float fade = 1.0f - smoothstep(radius * 0.9f, radius, dist); - float visibility = shadowVisibility(posWS + n * bias, L, dist - bias, - tris, sceneAS); - sum += pointLights[i].diffuse * max(0.0f, pointLights[i].intensity) * - attenuation * fade * ndl * visibility; - } - - for (uint i = 0; i < spotLightCount; i++) { - float3 toLight = spotLights[i].position - posWS; - float dist = length(toLight); - float range = max(spotLights[i].range, 0.001f); - if (dist <= 1e-4f || dist >= range) - continue; - - float3 L = toLight / dist; - float ndl = giNdotL(n, L); - if (ndl <= 0.0f) - continue; - - float3 spotDir = safeNormalize(spotLights[i].direction, - float3(0.0f, -1.0f, 0.0f)); - float theta = dot(L, -spotDir); - float epsilon = max(spotLights[i].cutOff - spotLights[i].outerCutOff, - 1e-4f); - float cone = clamp((theta - spotLights[i].outerCutOff) / epsilon, 0.0f, - 1.0f); - if (cone <= 0.0f) - continue; - - float attenuation = - 1.0f / ((1.0f + (dist / range)) + ((dist * dist) / (range * range))); - float fade = 1.0f - smoothstep(range * 0.9f, range, dist); - float visibility = shadowVisibility(posWS + n * bias, L, dist - bias, - tris, sceneAS); - sum += spotLights[i].diffuse * max(0.0f, spotLights[i].intensity) * cone * - attenuation * fade * ndl * visibility; - } - - for (uint i = 0; i < areaLightCount; i++) { - float3 center = areaLights[i].position; - float3 right = safeNormalize(areaLights[i].right, float3(1.0f, 0.0f, 0.0f)); - float3 up = safeNormalize(areaLights[i].up, float3(0.0f, 1.0f, 0.0f)); - float2 halfSize = areaLights[i].size * 0.5f; - - float3 toPoint = posWS - center; - float s = clamp(dot(toPoint, right), -halfSize.x, halfSize.x); - float t = clamp(dot(toPoint, up), -halfSize.y, halfSize.y); - float3 closest = center + right * s + up *)", -R"( t; - - float3 Lvec = closest - posWS; - float dist = length(Lvec); - float range = max(areaLights[i].range, 0.001f); - if (dist <= 1e-4f || dist >= range) - continue; - - float3 L = Lvec / dist; - float ndl = giNdotL(n, L); - if (ndl <= 0.0f) - continue; - - float3 lightNormal = - safeNormalize(cross(right, up), float3(0.0f, -1.0f, 0.0f)); - float nl = dot(lightNormal, -L); - float facing = (areaLights[i].castsBothSides != 0) ? abs(nl) : max(nl, 0.0f); - float cutoff = cos(areaLights[i].angle * 0.01745329251f); - if (facing < cutoff || facing <= 0.0f) - continue; - - float attenuation = - 1.0f / ((1.0f + (dist / range)) + ((dist * dist) / (range * range))); - float fade = 1.0f - smoothstep(range * 0.9f, range, dist); - float visibility = shadowVisibility(posWS + n * bias, L, dist - bias, - tris, sceneAS); - sum += areaLights[i].diffuse * max(0.0f, areaLights[i].intensity) * - facing * attenuation * fade * ndl * visibility; - } - - return sum; -} - -static inline void buildBasis(float3 n, thread float3 &t, thread float3 &b) { - float3 up = (fabs(n.y) < 0.999f) ? float3(0.0f, 1.0f, 0.0f) - : float3(1.0f, 0.0f, 0.0f); - t = safeNormalize(cross(up, n), float3(1.0f, 0.0f, 0.0f)); - b = safeNormalize(cross(n, t), float3(0.0f, 0.0f, 1.0f)); -} - -static inline float3 sampleCosineHemisphere(thread uint &state) { - float u1 = rand01(state); - float u2 = rand01(state); - float r = sqrt(max(0.0f, u1)); - float phi = 6.28318530718f * u2; - float x = r * cos(phi); - float z = r * sin(phi); - float y = sqrt(max(0.0f, 1.0f - u1)); - return float3(x, y, z); -} - -static inline float3 sphericalFibonacci(uint index, uint count, uint frameIndex) { - const float GOLDEN_RATIO = 1.6180339887498949f; - const float TAU = 6.28318530718f; - float i = float(index) + 0.5f; - float phi = TAU * fract(i / GOLDEN_RATIO); - float cosTheta = 1.0f - (2.0f * i) / float(count); - float sinTheta = sqrt(max(0.0f, 1.0f - cosTheta * cosTheta)); - uint rotSeed = wangHash(frameIndex * 1471u + 5743u); - float rotAngle = float(rotSeed & 0xFFFFu) / 65536.0f * TAU; - phi += rotAngle; - return float3(sinTheta * cos(phi), cosTheta, sinTheta * sin(phi)); -} - -kernel void main0(device float4 *probeRadianceOut [[buffer(0)]], - device const Triangle *tris [[buffer(1)]], - device const Material *materials [[buffer(2)]], - constant SceneCounts &sc [[buffer(3)]], - constant ProbeSpace &ps [[buffer(4)]], - constant RaytracingSettings &rt [[buffer(5)]], - device const DirectionalLight *directionalLights [[buffer(6)]], - device const PointLight *pointLights [[buffer(7)]], - device const SpotLight *spotLights [[buffer(8)]], - device const AreaLight *areaLights [[buffer(9)]], - instance_acceleration_structure sceneAS [[buffer(10)]], - texture2d materialTexture0 [[texture(10)]], - texture2d materialTexture1 [[texture(11)]], - texture2d materialTexture2 [[texture(12)]], - texture2d materialTexture3 [[texture(13)]], - texture2d materialTexture4 [[texture(14)]], - texture2d materialTexture5 [[texture(15)]], - texture2d materialTexture6 [[texture(16)]], - texture2d materialTexture7 [[texture(17)]], - texture2d materialTexture8 [[texture(18)]], - texture2d materialTexture9 [[texture(19)]], - texture2d materialTexture10 [[texture(20)]], - texture2d materialTexture11 [[texture(21)]], - texture2d materialTexture12 [[texture(22)]], - texture2d materialTexture13 [[texture(23)]], - texture2d materialTexture14 [[texture(24)]], - texture2d materialTexture15 [[texture(25)]], - texture2d materialTexture16 [[texture(26)]], - texture2d materialTexture17 [[texture(27)]], - texture2d materialTexture18 [[texture(28)]], - texture2d materialTexture19 [[texture(29)]], - texture2d materialTexture20 [[texture(30)]], - texture2d materialTexture21 [[texture(31)]], - texture2d materialTexture22 [[texture(32)]], - texture2d materialTexture23 [[texture(33)]], - texture2d materialTexture24 [[texture(34)]], - texture2d materialTexture25 [[texture(35)]], - texture2d materialTexture26 [[texture(36)]], - texture2d materialTexture27 [[texture(37)]], - texture2d materialTexture28 [[texture(38)]], - texture2d materialTexture29 [[texture(39)]], - texture2d materialTexture30 [[texture(40)]], - texture2d materialTexture31 [[texture(41)]], - texture2d materialTexture32 [[texture(42)]], - texture2d materialTexture33 [[texture(43)]], - texture2d materialTexture34 [[texture(44)]], - texture2d materialTexture35 [[texture(45)]], - texture2d materialTexture36 [[texture(46)]], - texture2d materialTexture37 [[texture(47)]], - texture2d materialTexture38 [[texture(48)]], - texture2d materialTexture39 [[texture(49)]], - texture2d materialTexture40 [[texture(50)]], - texture2d materialTexture41 [[texture(51)]], - texture2d materialTexture42 [[texture(52)]], - texture2d materialTexture43 [[texture(53)]], - texture2d materialTexture44 [[texture(54)]], - texture2d materialTexture45 [[texture(55)]], - texture2d materialTexture46 [[texture(56)]], - texture2d materialTexture47 [[texture(57)]], - texturecube skybox [[texture(60)]], - texture2d previousIrradiance [[texture(61)]], - uint tid [[thread_position_in_grid]]) { - const float PI = 3.14159265359f; - uint totalProbes = (uint)ps.atlasParams.w; - uint raysPerProbe = max(rt.raysPerProbe, 1u); - uint updateStride = max(rt.probeUpdateStride, 1u); - uint updateOffset = - (updateStride > 1u) ? rt.probeUpdateOffset % updateStride : 0u; - if (totalProbes > 0u) { - updateOffset %= totalProbes; - } - uint activeProbeCount = rt.probeUpdateCount; - if (activeProbeCount == 0u && totalProbes > updateOffset) { - activeProbeCount = - (totalProbes - updateOffset + updateStride - 1u) / updateStride; - } - activeProbeCount = max(activeProbeCount, 1u); - uint totalRays = activeProbeCount * raysPerProbe; - - if (tid >= totalRays) - return; - - uint localProbeIndex = tid / raysPerProbe; - uint rayIndex = tid - localProbeIndex * raysPerProbe; - uint probeIndex = updateOffset + localProbeIndex * updateStride; - if (probeIndex >= totalProbes) { - return; - } - - uint3 counts = uint3((uint)ps.probeCount.x, (uint)ps.probeCount.y, - (uint)ps.probeCount.z); - uint3 pc = probeCoordFromIndex(probeIndex, counts); - float3 probePos = ps.origin + float3(pc) * ps.spacing; - - float3 rayDir = sphericalFibonacci(rayIndex, raysPerProbe, rt.frameIndex); - - float maxDistance = max(rt.maxRayDistance, 0.001f); - float bias = max(rt.normalBias, 0.001f); - - float3 ro = probePos + rayDir * bias; - Hit h; - float selfHitThreshold = bias * 4.0f; - for (uint escapeStep = 0u)", -R"(; escapeStep < 1u; escapeStep++) { - h = traceScene(ro, rayDir, tris, sceneAS, maxDistance); - if (h.hit == 0u || h.t >= selfHitThreshold) { - break; - } - ro += rayDir * (h.t + selfHitThreshold); - } - if (h.hit != 0u && h.t < selfHitThreshold) { - h.hit = 0u; - h.t = INFINITY; - } - - float3 radiance = float3(0.0f); - if (h.hit == 0u || h.t > maxDistance) { - radiance = sampleSky(rayDir, skybox, rt.skyColor, rt.useSkybox); - } else { - float3 hitPos = ro + rayDir * h.t; - float3 albedo; - float metallic; - float roughness; - float ao; - float3 emissive; - int normalTextureIndex; - float normalStrength; - resolveMaterialParameters( - materials, h.materialID, sc.materialCount, h.uv, sc.textureCount, - materialTexture0, - materialTexture1, materialTexture2, materialTexture3, - materialTexture4, materialTexture5, materialTexture6, - materialTexture7, materialTexture8, materialTexture9, - materialTexture10, materialTexture11, materialTexture12, - materialTexture13, materialTexture14, materialTexture15, - materialTexture16, materialTexture17, materialTexture18, - materialTexture19, materialTexture20, materialTexture21, - materialTexture22, materialTexture23, materialTexture24, - materialTexture25, materialTexture26, materialTexture27, - materialTexture28, materialTexture29, materialTexture30, - materialTexture31, materialTexture32, materialTexture33, - materialTexture34, materialTexture35, materialTexture36, - materialTexture37, materialTexture38, materialTexture39, - materialTexture40, materialTexture41, materialTexture42, - materialTexture43, materialTexture44, materialTexture45, - materialTexture46, materialTexture47, albedo, metallic, roughness, - ao, emissive, - normalTextureIndex, normalStrength); - float3 hitNormal = resolveNormal( - normalTextureIndex, normalStrength, h.uv, h.n, h.tangent, h.bitangent, - sc.textureCount, materialTexture0, materialTexture1, - materialTexture2, materialTexture3, materialTexture4, - materialTexture5, materialTexture6, materialTexture7, - materialTexture8, materialTexture9, materialTexture10, - materialTexture11, materialTexture12, materialTexture13, - materialTexture14, materialTexture15, materialTexture16, - materialTexture17, materialTexture18, materialTexture19, - materialTexture20, materialTexture21, materialTexture22, - materialTexture23, materialTexture24, materialTexture25, - materialTexture26, materialTexture27, materialTexture28, - materialTexture29, materialTexture30, materialTexture31, - materialTexture32, materialTexture33, materialTexture34, - materialTexture35, materialTexture36, materialTexture37, - materialTexture38, materialTexture39, materialTexture40, - materialTexture41, materialTexture42, materialTexture43, - materialTexture44, materialTexture45, materialTexture46, - materialTexture47); - - if (dot(hitNormal, -rayDir) < 0.0f) { - hitNormal = -hitNormal; - } - - float3 direct = evaluateDirectLights( - hitPos, hitNormal, bias, maxDistance, tris, sceneAS, - directionalLights, sc.directionalLightCount, pointLights, - sc.pointLightCount, spotLights, sc.spotLightCount, areaLights, - sc.areaLightCount); - - float diffuseWeight = 1.0f - metallic; - float3 diffuseResponse = albedo * diffuseWeight * max(ao, 0.05f) / PI; - float3 previousBounce = - rt.frameIndex >= max(rt.probeUpdateStride, 1u) - ? samplePreviousIrradiance(previousIrradiance, ps, - hitPos + hitNormal * bias, hitNormal) - : float3(0.0f); - float3 indirect = previousBounce * diffuseResponse * 0.35f; - radiance = direct * diffuseResponse + indirect + emissive; - radiance = clamp(radiance, float3(0.0f), float3(16.0f)); - } - - uint outIndex = probeIndex * raysPerProbe + rayIndex; - probeRadianceOut[outIndex] = float4(radiance, h.hit != 0u ? h.t : -1.0f); -} -)", -}; -static const AtlasPackedShaderSource DDGI = {DDGI_PARTS, 6}; - -static const char* const DDGI_WRITE_PARTS[] = { -R"(#include -using namespace metal; - -struct ProbeSpace { - float3 origin; - float _pad0; - - float3 spacing; - float _pad1; - - float3 probeCount; - float _pad2; - - float4 debugColor; - - float4 atlasParams; -}; - -struct RaytracingSettings { - uint raysPerProbe; - float maxRayDistance; - float normalBias; - float hysteresis; - - uint frameIndex; - uint probeUpdateOffset; - uint probeUpdateStride; - uint probeUpdateCount; -}; - -static inline uint wangHash(uint x) { - x = (x ^ 61u) ^ (x >> 16); - x *= 9u; - x = x ^ (x >> 4); - x *= 0x27d4eb2du; - x = x ^ (x >> 15); - return x; -} - -static inline float3 octDecode(float2 e) { - float3 n = float3(e.x, e.y, 1.0f - fabs(e.x) - fabs(e.y)); - if (n.z < 0.0f) { - float2 signNotZero = - float2(n.x >= 0.0f ? 1.0f : -1.0f, n.y >= 0.0f ? 1.0f : -1.0f); - float2 folded = (1.0f - fabs(n.yx)) * signNotZero; - n.x = folded.x; - n.y = folded.y; - } - return normalize(n); -} - -static inline float3 sphericalFibonacci(uint index, uint count, uint frameIndex) { - const float GOLDEN_RATIO = 1.6180339887498949f; - const float TAU = 6.28318530718f; - float i = float(index) + 0.5f; - float phi = TAU * fract(i / GOLDEN_RATIO); - float cosTheta = 1.0f - (2.0f * i) / float(count); - float sinTheta = sqrt(max(0.0f, 1.0f - cosTheta * cosTheta)); - uint rotSeed = wangHash(frameIndex * 1471u + 5743u); - float rotAngle = float(rotSeed & 0xFFFFu) / 65536.0f * TAU; - phi += rotAngle; - return float3(sinTheta * cos(phi), cosTheta, sinTheta * sin(phi)); -} - -kernel void main0(texture2d outTexture [[texture(0)]], - texture2d prevTexture [[texture(1)]], - texture2d outDistance [[texture(2)]], - texture2d prevDistance [[texture(3)]], - device float4 *probeRadiance [[buffer(0)]], - constant ProbeSpace &ps [[buffer(1)]], - constant RaytracingSettings &rt [[buffer(2)]], - uint2 gid [[thread_position_in_grid]]) { - const float FOUR_PI = 12.566370614359172f; - - uint border = (uint)ps.atlasParams.x; - uint innerRes = (uint)ps.atlasParams.y; - uint probesPerRow = (uint)ps.atlasParams.z; - uint totalProbes = (uint)ps.atlasParams.w; - - if (gid.x >= outTexture.get_width() || gid.y >= outTexture.get_height()) - return; - - uint tileRes = innerRes + 2u * border; - if (tileRes == 0u || probesPerRow == 0u || totalProbes == 0u || - innerRes == 0u) { - outTexture.write(prevTexture.read(gid), gid); - outDistance.write(prevDistance.read(gid), gid); - return; - } - - uint tileX = gid.x / tileRes; - uint tileY = gid.y / tileRes; - uint probeIndex = tileX + tileY * probesPerRow; - - if (probeIndex >= totalProbes) { - outTexture.write(prevTexture.read(gid), gid); - outDistance.write(prevDistance.read(gid), gid); - return; - } - - uint updateStride = max(rt.probeUpdateStride, 1u); - uint updateOffset = - (updateStride > 1u) ? (rt.probeUpdateOffset % updateStride) : 0u; - bool probeIsActive = - (updateStride <= 1u) || - ((probeIndex >= updateOffset) && - (((probeIndex - updateOffset) % updateStride) == 0u)); - if (!probeIsActive) { - outTexture.write(prevTexture.read(gid), gid); - outDistance.write(prevDistance.read(gid), gid); - return; - } - - uint localX = gid.x - tileX * tileRes; - uint localY = gid.y - tileY * tileRes; - - int innerX = clamp(int(localX) - int(border), 0, int(innerRes) - 1); - int innerY = clamp(int(localY) - int(border), 0, int(innerRes) - 1); - - float2 e = (float2(float(innerX), float(innerY)) + 0.5f) / float(innerRes) * 2.0f - 1.0f; - float3 texelDir = octDecode(e); - - uint raysPerProbe = max(rt.raysPerProbe, 1u); - uint baseOffset = probeIndex * raysPerProbe; - uint rayStep = (raysPerProbe >= 128u) ? 2u : 1u; - uint sampledRayCount = 0u; - - float3 sum = float3(0.0f); - float weightSum = 0.0f; - float distanceSum = 0.0f; - float distanceSquaredSum = 0.0f; - float nearHitCount = 0.0f; - float spacingScale = - max(max(ps.spacing.x, max(ps.spacing.y, ps.spacing.z)), 1e-4f); - float nearHitThreshold = - max(max(rt.normalBias * 2.0f, spacingScale * 0.1f), 0.002f); - - for (uint r = 0; r < raysPerProbe; r += rayStep) { - sampledRayCount++; - float4 raySample = probeRadiance[baseOffset + r]; - float hitDistance = raySample.w; - if (hitDistance > 0.0f && hitDistance < nearHitThreshold) { - nearHitCount += 1.0f; - } - - float3 rayDir = sphericalFibonacci(r, raysPerProbe, rt.frameIndex); - float w = max(0.0f, dot(texelDir, rayDir)); - if (w > 1e-6f) { - float3 rad = raySample.xyz; - if (all(isfinite(rad))) { - sum += rad * w; - weightSum += w; - float distance = hitDistance > 0.0f - ? min(hitDistance, rt.maxRayDistance) - : rt.maxRayDistance; - distanceSum += distance * w; - distanceSquaredSum += distance * distance * w; - } - } - } - - float3 irradiance = float3(0.0f); - float2 distanceMoments = float2(rt.maxRayDistance, - rt.maxRayDistance * rt.maxRayDistance); - float invRayCount = 1.0f / float(max(sampledRayCount, 1u)); - if (weightSum > 1e-6f) { - irradiance = sum * (FOUR_PI * invRayCount); - distanceMoments = float2(distanceSum, distanceSquaredSum) / weightSum; - } - - if (!all(isfinite(irradiance))) { - irradiance = float3(0.0f); - } - - float4 prev = prevTexture.read(gid); - float4 previousDistance = prevDistance.read(gid); - float3 prevValue = all(isfinite(prev.xyz)) ? prev.xyz : float3(0.0f); - float prevValidity = isfinite(prev.w) ? clamp(prev.w, 0.0f, 1.0f) : 1.0f; - - float nearFraction = nearHitCount * invRayCount; - float nearPenalty = smoothstep(0.82f, 0.995f, nearFraction); - float probeValidity = 1.0f - nearPenalty; - probeValidity = clamp(probeValidity, 0.0f, 1.0f); - - float h = clamp(rt.hysteresis, 0.0f, 0.995f); - bool firstProbeUpdate = rt.frameIndex < updateStride; - float3 blended = firstProbeUpdate ? irradiance : mix(irradiance, prevValue, h); - float2 blendedDistance = - firstProbeUpdate - ? distanceMoments - : mix(distanceMoments, previousDistance.xy, h); - float blendedValidity = - firstProbeUpdate - ? probeValidity - : mix(probeValidity, prevValidity, h); - - outTexture.write(float4(max(blended, float3(0.0f)), blendedValidity), gid); - outDistance.write(float4(max(blendedDistance, float2(0.0f)), - blendedValidity, 0.0f), gid); -} -)", -}; -static const AtlasPackedShaderSource DDGI_WRITE = {DDGI_WRITE_PARTS, 1}; - -static const char* const DEBUG_FRAG_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct main0_out -{ - float4 FragColor [[color(0)]]; -}; - -fragment main0_out main0() -{ - main0_out out = {}; - out.FragColor = float4(1.0, 0.0, 1.0, 1.0); - return out; -} - -)", -}; -static const AtlasPackedShaderSource DEBUG_FRAG = {DEBUG_FRAG_PARTS, 1}; - -static const char* const DEBUG_VERT_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct main0_out -{ - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]]) -{ - main0_out out = {}; - out.gl_Position = float4(in.aPos, 1.0); - return out; -} - -)", -}; -static const AtlasPackedShaderSource DEBUG_VERT = {DEBUG_VERT_PARTS, 1}; - -static const char* const DEFERRED_FRAG_PARTS[] = { -R"(#pragma clang diagnostic ignored "-Wmissing-prototypes" - -#include -#include - -using namespace metal; - -struct UBO -{ - int4 textureTypes[16]; - int textureCount; - uint useTexture; - uint useColor; - float3 cameraPosition; - float normalMapStrength; - uint useNormalMap; - float2 textureScale; - float2 textureOffset; -}; - -struct MaterialPush -{ - packed_float3 albedo; - float metallic; - float roughness; - float ao; - float reflectivity; -}; - -struct main0_out -{ - float4 gPosition [[color(0)]]; - float4 gNormal [[color(1)]]; - float4 gAlbedoSpec [[color(2)]]; - float4 gMaterial [[color(3)]]; -}; - -struct main0_in -{ - float2 TexCoord [[user(locn1)]]; - float3 Normal [[user(locn2)]]; - float3 FragPos [[user(locn3)]]; - float3 TBN_0 [[user(locn4)]]; - float3 TBN_1 [[user(locn5)]]; - float3 TBN_2 [[user(locn6)]]; -}; - -static inline __attribute__((always_inline)) -float4 sampleTextureAt(thread const int& textureIndex, thread const float2& uv, texture2d texture1, sampler texture1Smplr, texture2d texture2, sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, texture2d texture4, sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, texture2d texture6, sampler texture6Smplr, texture2d texture7, sampler texture7Smplr, texture2d texture8, sampler texture8Smplr, texture2d texture9, sampler texture9Smplr, texture2d texture10, sampler texture10Smplr) -{ - if (textureIndex == 0) - { - return texture1.sample(texture1Smplr, uv); - } - else - { - if (textureIndex == 1) - { - return texture2.sample(texture2Smplr, uv); - } - else - { - if (textureIndex == 2) - { - return texture3.sample(texture3Smplr, uv); - } - else - { - if (textureIndex == 3) - { - return texture4.sample(texture4Smplr, uv); - } - else - { - if (textureIndex == 4) - { - return texture5.sample(texture5Smplr, uv); - } - else - { - if (textureIndex == 5) - { - return texture6.sample(texture6Smplr, uv); - } - else - { - if (textureIndex == 6) - { - return texture7.sample(texture7Smplr, uv); - } - else - { - if (textureIndex == 7) - { - return texture8.sample(texture8Smplr, uv); - } - else - { - if (textureIndex == 8) - { - return texture9.sample(texture9Smplr, uv); - } - else - { - if (textureIndex == 9) - { - return texture10.sample(texture10Smplr, uv); - } - } - } - } - } - } - } - } - } - } - return float4(0.0); -} - -static inline __attribute__((always_inline)) -float2 parallaxMapping(thread const float2& texCoords, thread const float3& viewDir, constant UBO& _46, texture2d texture1, sampler texture1Smplr, texture2d texture2, sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, texture2d texture4, sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, texture2d texture6, sampler texture6Smplr, texture2d texture7, sampler texture7Smplr, texture2d texture8, sampler texture8Smplr, texture2d texture9, sampler texture9Smplr, texture2d texture10, sampler texture10Smplr) -{ - float3 v = fast::normalize(viewDir); - float numLayers = mix(32.0, 8.0, abs(dot(float3(0.0, 0.0, 1.0), v))); - float layerDepth = 1.0 / numLayers; - float currentLayerDepth = 0.0; - float2 P = (v.xy / float2(fast::max(v.z, 0.0500000007450580596923828125))) * 0.039999999105930328369140625; - float2 deltaTexCoords = P / float2(numLayers); - float2 currentTexCoords = texCoords; - int textureIndex = -1; - for (int i = 0; i < _46.textureCount; i++) - { - if (_46.textureTypes[i].x == 6) - { - textureIndex = i; - break; - } - } - if (textureIndex == (-1)) - { - return currentTexCoords; - } - int param = textureIndex; - float2 param_1 = currentTexCoords; - float currentDepthMapValue = 1.0 - sampleTextureAt(param, param_1, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr).x; - int maxIterations = int(numLayers) + 1; - int iteration = 0; - while (currentLayerDepth < currentDepthMapValue && iteration < maxIterations) - { - currentTexCoords -= deltaTexCoords; - int param_2 = textureIndex; - float2 param_3 = currentTexCoords; - currentDepthMapValue = 1.0 - sampleTextureAt(param_2, param_3, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr).x; - currentLayerDepth += layerDepth; - iteration++; - } - float2 prevTexCoords = currentTexCoords + deltaTexCoords; - float afterDepth = currentDepthMapValue - currentLayerDepth; - int param_4 = textureIndex; - float2 param_5 = prevTexCoords; - float beforeDepth = 1.0 - sampleTextureAt(param_4, param_5, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr).x - (currentLayerDepth - layerDepth); - float denom = afterDepth - beforeDepth; - float weight = abs(denom) > 9.9999997473787516355514526367188e-05 ? fast::clamp(afterDepth / denom, 0.0, 1.0) : 0.0; - currentTexCoords = (prevTexCoords * weight) + (currentTexCoords * (1.0 - weight)); - return currentTexCoords; -} - -static inline __attribute__((always_inline)) -float4 enableTextures(thread const int& type, constant UBO& _46, texture2d texture1, sampler texture1Smplr, thread float2& texCoord, texture2d texture2, sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, texture2d texture4, sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, texture2d texture6, sampler texture6Smplr, texture2d texture7, sampler texture7Smplr, texture2d texture8, sampler texture8Smplr, texture2d texture9, sampler texture9Smplr, texture2d texture10, sampler texture10Smplr) -{ - float4 color = float4(0.0); - int count = 0; - for (int i = 0; i < _46.textureCount; i++) - { - if (_46.textureTypes[i].x == type) - { - if (i == 0) - { - color += texture1.sample(texture1Smplr, texCoord); - } - else - { - if (i == 1) - { - color += texture2.sample(texture2Smplr, texCoord); - } - else - { - if (i == 2) - { - )", -R"( color += texture3.sample(texture3Smplr, texCoord); - } - else - { - if (i == 3) - { - color += texture4.sample(texture4Smplr, texCoord); - } - else - { - if (i == 4) - { - color += texture5.sample(texture5Smplr, texCoord); - } - else - { - if (i == 5) - { - color += texture6.sample(texture6Smplr, texCoord); - } - else - { - if (i == 6) - { - color += texture7.sample(texture7Smplr, texCoord); - } - else - { - if (i == 7) - { - color += texture8.sample(texture8Smplr, texCoord); - } - else - { - if (i == 8) - { - color += texture9.sample(texture9Smplr, texCoord); - } - else - { - if (i == 9) - { - color += texture10.sample(texture10Smplr, texCoord); - } - } - } - } - } - } - } - } - } - } - count++; - } - } - if (count > 0) - { - color /= float4(float(count)); - } - if (count == 0) - { - return float4(-1.0); - } - return color; -} - -fragment main0_out main0(main0_in in [[stage_in]], constant UBO& _46 [[buffer(0)]], constant MaterialPush& material [[buffer(1)]], texture2d texture1 [[texture(0)]], texture2d texture2 [[texture(1)]], texture2d texture3 [[texture(2)]], texture2d texture4 [[texture(3)]], texture2d texture5 [[texture(4)]], texture2d texture6 [[texture(5)]], texture2d texture7 [[texture(6)]], texture2d texture8 [[texture(7)]], texture2d texture9 [[texture(8)]], texture2d texture10 [[texture(9)]], sampler texture1Smplr [[sampler(0)]], sampler texture2Smplr [[sampler(1)]], sampler texture3Smplr [[sampler(2)]], sampler texture4Smplr [[sampler(3)]], sampler texture5Smplr [[sampler(4)]], sampler texture6Smplr [[sampler(5)]], sampler texture7Smplr [[sampler(6)]], sampler texture8Smplr [[sampler(7)]], sampler texture9Smplr [[sampler(8)]], sampler texture10Smplr [[sampler(9)]], float4 gl_FragCoord [[position]]) -{ - main0_out out = {}; - float3x3 TBN = {}; - TBN[0] = in.TBN_0; - TBN[1] = in.TBN_1; - TBN[2] = in.TBN_2; - float2 texCoord = in.TexCoord * _46.textureScale + _46.textureOffset; - bool hasParallaxMap = false; - for (int i = 0; i < _46.textureCount; i++) - { - if (_46.textureTypes[i].x == 6) - { - hasParallaxMap = true; - break; - } - } - if (hasParallaxMap) - { - float3 tangentViewDir = fast::normalize(transpose(TBN) * (_46.cameraPosition - in.FragPos)); - float2 param = texCoord; - float3 param_1 = tangentViewDir; - texCoord = parallaxMapping(param, param_1, _46, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - } - int param_2 = 0; - float4 sampledColor = enableTextures(param_2, _46, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - bool hasColorTexture = any(sampledColor != float4(-1.0)); - float4 baseColor = float4(material.albedo[0], material.albedo[1], material.albedo[2], 1.0); - int param_3 = 0; - float4 albedoTex = enableTextures(param_3, _46, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - if (any(albedoTex != float4(-1.0))) - { - baseColor *= albedoTex; - } - int param_3a = 12; - float4 opacityTex = enableTextures(param_3a, _46, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - if (any(opacityTex != float4(-1.0))) - { - if (opacityTex.x < 0.100000001490116119384765625) - { - discard_fragment(); - } - } - else - { - if ((baseColor.w < 0.100000001490116119384765625) && (material.albedo[3] < 0.999000012874603271484375)) - { - discard_fragment(); - } - } - int param_4 = 5; - float4 normTexture = enableTextures(param_4, _46, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - bool _527 = normTexture.x != (-1.0); - bool _534; - if (_527) - { - _534 = normTexture.y != (-1.0); - } - else - { - _534 = _527; - } - bool _540; - if (_534) - { - _540 = normTexture.z != (-1.0); - } - else - { - _540 = _534; - } - float normalStrength = fast::max(_46.normalMapStrength, 0.0f); - bool useNormalMap = (_46.useNormalMap != 0u) && (normalStrength > 0.0f); - float3 normal; - if (_540 && useNormalMap) - { - float3 tangentNormal = (normTexture.xyz * 2.0) - float3(1.0); - tangentNormal.xy *= normalStrength; - tangentNormal = fast::normalize(tangentNormal); - normal = fast::normalize(TBN * tangentNormal); - } - else - { - normal = fast::normalize(in.Normal); - } - float3 albedoColor = baseColor.xyz; - int param_pbr_pack = 14; - float4 pbrPackTex = enableTextures(param_pbr_pack, _46, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - bool hasPbrPack = any(pbrPackTex != float4(-1.0)); - float metallicValue = material.metallic; - int param_5 = 9; - float4 metallicTex = enableTextures(param_5, _46, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - if (hasPbrPack) - { - metallicValue *= pbrPackTex.z; - } - else if (any(metallicTex != float4(-1.0))) - { - metallicValue *= metallicTex.x; - } - float roughnessValue = mater)", -R"(ial.roughness; - int param_6 = 10; - float4 roughnessTex = enableTextures(param_6, _46, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - if (hasPbrPack) - { - roughnessValue *= pbrPackTex.y; - } - else if (any(roughnessTex != float4(-1.0))) - { - roughnessValue *= roughnessTex.x; - } - float aoValue = material.ao; - int param_7 = 11; - float4 aoTex = enableTextures(param_7, _46, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - if (hasPbrPack) - { - aoValue *= pbrPackTex.x; - } - else if (any(aoTex != float4(-1.0))) - { - aoValue *= aoTex.x; - } - metallicValue = fast::clamp(metallicValue, 0.0, 1.0); - roughnessValue = fast::clamp(roughnessValue, 0.0, 1.0); - aoValue = fast::clamp(aoValue, 0.0, 1.0); - float nonlinearDepth = gl_FragCoord.z; - out.gPosition = float4(in.FragPos, nonlinearDepth); - float3 n = fast::normalize(normal); - bool _639 = !all(n == n); - bool _646; - if (!_639) - { - _646 = length(n) < 9.9999997473787516355514526367188e-05; - } - else - { - _646 = _639; - } - if (_646) - { - n = fast::normalize(in.Normal); - } - out.gNormal = float4(n, 1.0); - float3 a = fast::clamp(albedoColor, float3(0.0), float3(1.0)); - if (!all(a == a)) - { - a = float3(0.0); - } - out.gAlbedoSpec = float4(a, aoValue); - out.gMaterial = float4(metallicValue, roughnessValue, aoValue, fast::clamp(material.reflectivity, 0.0, 1.0)); - return out; -} -)", -}; -static const AtlasPackedShaderSource DEFERRED_FRAG = {DEFERRED_FRAG_PARTS, 3}; - -static const char* const DEFERRED_VERT_PARTS[] = { -R"(#pragma clang diagnostic ignored "-Wmissing-prototypes" - -#include -#include - -using namespace metal; - -// Returns the determinant of a 2x2 matrix. -static inline __attribute__((always_inline)) -float spvDet2x2(float a1, float a2, float b1, float b2) -{ - return a1 * b2 - b1 * a2; -} - -// Returns the determinant of a 3x3 matrix. -static inline __attribute__((always_inline)) -float spvDet3x3(float a1, float a2, float a3, float b1, float b2, float b3, float c1, float c2, float c3) -{ - return a1 * spvDet2x2(b2, b3, c2, c3) - b1 * spvDet2x2(a2, a3, c2, c3) + c1 * spvDet2x2(a2, a3, b2, b3); -} - -// Returns the inverse of a matrix, by using the algorithm of calculating the classical -// adjoint and dividing by the determinant. The contents of the matrix are changed. -static inline __attribute__((always_inline)) -float4x4 spvInverse4x4(float4x4 m) -{ - float4x4 adj; // The adjoint matrix (inverse after dividing by determinant) - - // Create the transpose of the cofactors, as the classical adjoint of the matrix. - adj[0][0] = spvDet3x3(m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], m[2][3], m[3][1], m[3][2], m[3][3]); - adj[0][1] = -spvDet3x3(m[0][1], m[0][2], m[0][3], m[2][1], m[2][2], m[2][3], m[3][1], m[3][2], m[3][3]); - adj[0][2] = spvDet3x3(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], m[3][1], m[3][2], m[3][3]); - adj[0][3] = -spvDet3x3(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], m[2][3]); - - adj[1][0] = -spvDet3x3(m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][2], m[3][3]); - adj[1][1] = spvDet3x3(m[0][0], m[0][2], m[0][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][2], m[3][3]); - adj[1][2] = -spvDet3x3(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], m[3][0], m[3][2], m[3][3]); - adj[1][3] = spvDet3x3(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], m[2][3]); - - adj[2][0] = spvDet3x3(m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], m[2][3], m[3][0], m[3][1], m[3][3]); - adj[2][1] = -spvDet3x3(m[0][0], m[0][1], m[0][3], m[2][0], m[2][1], m[2][3], m[3][0], m[3][1], m[3][3]); - adj[2][2] = spvDet3x3(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], m[3][0], m[3][1], m[3][3]); - adj[2][3] = -spvDet3x3(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], m[2][3]); - - adj[3][0] = -spvDet3x3(m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2], m[3][0], m[3][1], m[3][2]); - adj[3][1] = spvDet3x3(m[0][0], m[0][1], m[0][2], m[2][0], m[2][1], m[2][2], m[3][0], m[3][1], m[3][2]); - adj[3][2] = -spvDet3x3(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[3][0], m[3][1], m[3][2]); - adj[3][3] = spvDet3x3(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2]); - - // Calculate the determinant as a combination of the cofactors of the first row. - float det = (adj[0][0] * m[0][0]) + (adj[0][1] * m[1][0]) + (adj[0][2] * m[2][0]) + (adj[0][3] * m[3][0]); - - // Divide the classical adjoint matrix by the determinant. - // If determinant is zero, matrix is not invertable, so leave it unchanged. - return (det != 0.0f) ? (adj * (1.0f / det)) : m; -} - -struct UBO -{ - float4x4 model; - float4x4 view; - float4x4 projection; - uint isInstanced; -}; - -struct main0_out -{ - float4 outColor [[user(locn0)]]; - float2 TexCoord [[user(locn1)]]; - float3 Normal [[user(locn2)]]; - float3 FragPos [[user(locn3)]]; - float3 TBN_0 [[user(locn4)]]; - float3 TBN_1 [[user(locn5)]]; - float3 TBN_2 [[user(locn6)]]; - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; - float4 aColor [[attribute(1)]]; - float2 aTexCoord [[attribute(2)]]; - float3 aNormal [[attribute(3)]]; - float3 aTangent [[attribute(4)]]; - float3 aBitangent [[attribute(5)]]; - float4 instanceModel_0 [[attribute(6)]]; - float4 instanceModel_1 [[attribute(7)]]; - float4 instanceModel_2 [[attribute(8)]]; - float4 instanceModel_3 [[attribute(9)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]], constant UBO& _12 [[buffer(0)]]) -{ - main0_out out = {}; - float3x3 TBN = {}; - float4x4 instanceModel = {}; - instanceModel[0] = in.instanceModel_0; - instanceModel[1] = in.instanceModel_1; - instanceModel[2] = in.instanceModel_2; - instanceModel[3] = in.instanceModel_3; - float4x4 finalModel; - bool hasInstanceMatrix = abs(instanceModel[3].w) > 0.5; - if ((_12.isInstanced != 0u) && hasInstanceMatrix) - { - finalModel = instanceModel; - } - else - { - finalModel = _12.model; - } - float4 worldPos = finalModel * float4(in.aPos, 1.0); - out.FragPos = worldPos.xyz; - out.gl_Position = (_12.projection * _12.view) * worldPos; - out.TexCoord = in.aTexCoord; - out.outColor = in.aColor; - float4x4 _81 = transpose(spvInverse4x4(finalModel)); - float3x3 normalMatrix = float3x3(_81[0].xyz, _81[1].xyz, _81[2].xyz); - out.Normal = fast::normalize(normalMatrix * in.aNormal); - float3 T = fast::normalize(normalMatrix * in.aTangent); - float3 B = fast::normalize(normalMatrix * in.aBitangent); - float3 N = fast::normalize(normalMatrix * in.aNormal); - TBN = float3x3(float3(T), float3(B), float3(N)); - out.TBN_0 = TBN[0]; - out.TBN_1 = TBN[1]; - out.TBN_2 = TBN[2]; - return out; -} -)", -}; -static const AtlasPackedShaderSource DEFERRED_VERT = {DEFERRED_VERT_PARTS, 1}; - -static const char* const DEPTH_VERT_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct UBO -{ - float4x4 model; - float4x4 view; - float4x4 projection; - uint isInstanced; -}; - -struct main0_out -{ - float4 gl_Position [[position, invariant]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; - float4 instanceModel_0 [[attribute(6)]]; - float4 instanceModel_1 [[attribute(7)]]; - float4 instanceModel_2 [[attribute(8)]]; - float4 instanceModel_3 [[attribute(9)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]], constant UBO& _12 [[buffer(0)]]) -{ - main0_out out = {}; - float4x4 instanceModel = {}; - instanceModel[0] = in.instanceModel_0; - instanceModel[1] = in.instanceModel_1; - instanceModel[2] = in.instanceModel_2; - instanceModel[3] = in.instanceModel_3; - bool hasInstanceMatrix = abs(instanceModel[3].w) > 0.5; - if ((_12.isInstanced != 0u) && hasInstanceMatrix) - { - float4x4 _36 = _12.projection * _12.view; - float4x4 _40 = _36 * instanceModel; - float4 _49 = float4(in.aPos, 1.0); - float4 _50 = _40 * _49; - out.gl_Position = _50; - } - else - { - float4x4 _58 = _12.projection * _12.view; - float4x4 _61 = _58 * _12.model; - float4 _66 = float4(in.aPos, 1.0); - float4 _67 = _61 * _66; - out.gl_Position = _67; - } - return out; -} -)", -}; -static const AtlasPackedShaderSource DEPTH_VERT = {DEPTH_VERT_PARTS, 1}; - -static const char* const DOWNSAMPLE_FRAG_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct Params -{ - float2 srcResolution; -}; - -struct main0_out -{ - float4 downsample [[color(0)]]; -}; - -struct main0_in -{ - float2 TexCoord [[user(locn0)]]; -}; - -fragment main0_out main0(main0_in in [[stage_in]], constant Params& _13 [[buffer(0)]], texture2d srcTexture [[texture(0)]], sampler srcTextureSmplr [[sampler(0)]]) -{ - main0_out out = {}; - float2 srcTexelSize = - float2(1.0) / float2(srcTexture.get_width(), srcTexture.get_height()); - float x = srcTexelSize.x; - float y = srcTexelSize.y; - float2 texCoord = in.TexCoord; - float3 a = srcTexture.sample(srcTextureSmplr, float2(texCoord.x - (2.0 * x), texCoord.y + (2.0 * y))).xyz; - float3 b = srcTexture.sample(srcTextureSmplr, float2(texCoord.x, texCoord.y + (2.0 * y))).xyz; - float3 c = srcTexture.sample(srcTextureSmplr, float2(texCoord.x + (2.0 * x), texCoord.y + (2.0 * y))).xyz; - float3 d = srcTexture.sample(srcTextureSmplr, float2(texCoord.x - (2.0 * x), texCoord.y)).xyz; - float3 e = srcTexture.sample(srcTextureSmplr, float2(texCoord.x, texCoord.y)).xyz; - float3 f = srcTexture.sample(srcTextureSmplr, float2(texCoord.x + (2.0 * x), texCoord.y)).xyz; - float3 g = srcTexture.sample(srcTextureSmplr, float2(texCoord.x - (2.0 * x), texCoord.y - (2.0 * y))).xyz; - float3 h = srcTexture.sample(srcTextureSmplr, float2(texCoord.x, texCoord.y - (2.0 * y))).xyz; - float3 i = srcTexture.sample(srcTextureSmplr, float2(texCoord.x + (2.0 * x), texCoord.y - (2.0 * y))).xyz; - float3 j = srcTexture.sample(srcTextureSmplr, float2(texCoord.x - x, texCoord.y + y)).xyz; - float3 k = srcTexture.sample(srcTextureSmplr, float2(texCoord.x + x, texCoord.y + y)).xyz; - float3 l = srcTexture.sample(srcTextureSmplr, float2(texCoord.x - x, texCoord.y - y)).xyz; - float3 m = srcTexture.sample(srcTextureSmplr, float2(texCoord.x + x, texCoord.y - y)).xyz; - float3 downsampleColor = e * 0.125; - downsampleColor += ((((a + c) + g) + i) * 0.03125); - downsampleColor += ((((b + d) + f) + h) * 0.0625); - downsampleColor += ((((j + k) + l) + m) * 0.125); - out.downsample = float4(downsampleColor, 1.0); - return out; -} -)", -}; -static const AtlasPackedShaderSource DOWNSAMPLE_FRAG = {DOWNSAMPLE_FRAG_PARTS, 1}; - -static const char* const EMPTY_FRAG_PARTS[] = { -R"(#include -#include - -using namespace metal; - -fragment void main0() -{ -} - -)", -}; -static const AtlasPackedShaderSource EMPTY_FRAG = {EMPTY_FRAG_PARTS, 1}; - -static const char* const FLUID_FRAG_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct Uniforms -{ - float4 waterColor; - packed_float3 cameraPos; - float time; - float4x4 projection; - float4x4 view; - float4x4 invProjection; - float4x4 invView; - float3 lightDirection; - float3 lightColor; -}; - -struct Parameters -{ - float refractionStrength; - float reflectionStrength; - float depthFade; - int hasNormalTexture; - int hasMovementTexture; - float3 windForce; -}; - -struct main0_out -{ - float4 FragColor [[color(0)]]; - float4 BrightColor [[color(1)]]; -}; - -struct main0_in -{ - float2 TexCoord [[user(locn0)]]; - float3 WorldPos [[user(locn1)]]; - float3 WorldNormal [[user(locn2)]]; - float3 WorldTangent [[user(locn3)]]; - float3 WorldBitangent [[user(locn4)]]; -}; - -fragment main0_out main0(main0_in in [[stage_in]], constant Uniforms& _19 [[buffer(0)]], constant Parameters& _68 [[buffer(1)]], texture2d movementTexture [[texture(0)]], texture2d normalTexture [[texture(1)]], texture2d reflectionTexture [[texture(2)]], texture2d refractionTexture [[texture(3)]], texture2d sceneTexture [[texture(4)]], sampler movementTextureSmplr [[sampler(0)]], sampler normalTextureSmplr [[sampler(1)]], sampler reflectionTextureSmplr [[sampler(2)]], sampler refractionTextureSmplr [[sampler(3)]], sampler sceneTextureSmplr [[sampler(4)]]) -{ - main0_out out = {}; - float3 normal = fast::normalize(in.WorldNormal); - float3 viewDir = fast::normalize(float3(_19.cameraPos) - in.WorldPos); - float4 clipSpace = (_19.projection * _19.view) * float4(in.WorldPos, 1.0); - float3 ndc = clipSpace.xyz / float3(clipSpace.w); - float2 screenUV = (ndc.xy * 0.5) + float2(0.5); - float windStrength = length(_68.windForce); - float2 _78; - if (windStrength > 0.001000000047497451305389404296875) - { - _78 = fast::normalize(_68.windForce.xy); - } - else - { - _78 = float2(1.0, 0.0); - } - float2 windDir = _78; - float waveSpeed = 0.1500000059604644775390625 + (windStrength * 0.300000011920928955078125); - float waveAmplitude = 0.00999999977648258209228515625 + (windStrength * 0.0199999995529651641845703125); - float waveFrequency = 30.0 + (windStrength * 10.0); - float2 waveOffset; - waveOffset.x = sin(((in.TexCoord.x * windDir.x) + (_19.time * waveSpeed)) * waveFrequency); - waveOffset.y = cos(((in.TexCoord.y * windDir.y) - (_19.time * waveSpeed)) * waveFrequency); - waveOffset *= waveAmplitude; - float2 flowOffset = float2(0.0); - if (_68.hasMovementTexture == 1) - { - float2 windUV = (_68.windForce.xy * _19.time) * 0.0500000007450580596923828125; - float2 movementUV = (in.TexCoord * 2.0) + windUV; - float2 movementSample = movementTexture.sample(movementTextureSmplr, movementUV).xy; - movementSample = (movementSample * 2.0) - float2(1.0); - flowOffset = (movementSample * windStrength) * 0.1500000059604644775390625; - waveOffset += (flowOffset * 0.5); - } - if (_68.hasNormalTexture == 1) - { - float3 T = fast::normalize(in.WorldTangent); - float3 B = fast::normalize(in.WorldBitangent); - float3 N = fast::normalize(in.WorldNormal); - float3x3 TBN = float3x3(float3(T), float3(B), float3(N)); - float normalSpeed = 0.02999999932944774627685546875 + (windStrength * 0.0500000007450580596923828125); - float2 normalUV1 = ((in.TexCoord * 5.0) + (waveOffset * 10.0)) + ((_68.windForce.xy * _19.time) * normalSpeed); - float2 normalUV2 = ((in.TexCoord * 3.0) - (waveOffset * 8.0)) - (((_68.windForce.xy * _19.time) * normalSpeed) * 0.800000011920928955078125); - float3 normalMap1 = normalTexture.sample(normalTextureSmplr, normalUV1).xyz; - float3 normalMap2 = normalTexture.sample(normalTextureSmplr, normalUV2).xyz; - normalMap1 = (normalMap1 * 2.0) - float3(1.0); - normalMap2 = (normalMap2 * 2.0) - float3(1.0); - float3 blendedNormal = fast::normalize(normalMap1 + normalMap2); - float3 worldSpaceNormal = fast::normalize(TBN * blendedNormal); - float normalStrength = 0.5 + (windStrength * 0.300000011920928955078125); - normal = fast::normalize(mix(N, worldSpaceNormal, float3(normalStrength))); - } - float2 reflectionUV = screenUV; - reflectionUV.y = 1.0 - reflectionUV.y; - reflectionUV += (waveOffset * 0.300000011920928955078125); - float2 refractionUV = screenUV - (waveOffset * 0.20000000298023223876953125); - bool _324 = reflectionUV.x >= 0.0; - bool _330; - if (_324) - { - _330 = reflectionUV.x <= 1.0; - } - else - { - _330 = _324; - } - bool _336; - if (_330) - { - _336 = reflectionUV.y >= 0.0; - } - else - { - _336 = _330; - } - bool _342; - if (_336) - { - _342 = reflectionUV.y <= 1.0; - } - else - { - _342 = _336; - } - bool reflectionInBounds = _342; - bool _346 = refractionUV.x >= 0.0; - bool _352; - if (_346) - { - _352 = refractionUV.x <= 1.0; - } - else - { - _352 = _346; - } - bool _358; - if (_352) - { - _358 = refractionUV.y >= 0.0; - } - else - { - _358 = _352; - } - bool _364; - if (_358) - { - _364 = refractionUV.y <= 1.0; - } - else - { - _364 = _358; - } - bool refractionInBounds = _364; - reflectionUV = fast::clamp(reflectionUV, float2(0.0500000007450580596923828125), float2(0.949999988079071044921875)); - refractionUV = fast::clamp(refractionUV, float2(0.0500000007450580596923828125), float2(0.949999988079071044921875)); - float2 reflectionEdgeFade = smoothstep(float2(0.0), float2(0.1500000059604644775390625), reflectionUV) * smoothstep(float2(1.0), float2(0.85000002384185791015625), reflectionUV); - float reflectionFadeFactor = reflectionEdgeFade.x * reflectionEdgeFade.y; - float2 refractionEdgeFade = smoothstep(float2(0.0), float2(0.1500000059604644775390625), refractionUV) * smoothstep(float2(1.0), float2(0.85000002384185791015625), refractionUV); - float refractionFadeFactor = refractionEdgeFade.x * refractionEdgeFade.y; - if (!reflectionInBounds) - { - reflectionFadeFactor *= 0.300000011920928955078125; - } - if (!refractionInBounds) - { - refractionFadeFactor *= 0.300000011920928955078125; - } - float4 reflectionSample = reflectionTexture.sample(reflectionTextureSmplr, reflectionUV); - float4 refractionSample = refractionTexture.sample(refractionTextureSmplr, refractionUV); - float4 sceneFallback = sceneTexture.sample(sceneTextureSmplr, screenUV); - bool validReflection = length(reflectionSample.xyz) > 0.00999999977648258209228515625; - bool validRefraction = length(refractionSample.xyz) > 0.00999999977648258209228515625; - if (!validReflection) - { - reflectionSample = sceneFallback; - } - if (!validRefraction) - { - refractionSample = sceneFallback; - } - float fresnel = powr(1.0 - fast::clamp(dot(normal, viewDir), 0.0, 1.0), 3.0); - fresnel = mix(0.0199999995529651641845703125, 1.0, fresnel); - fresnel *= _68.reflectionStrength; - float3 combined = mix(refractionSample.xyz, reflectionSample.xyz, float3(fresnel)); - float waterTint = fast::clamp(_68.depthFade * 0.300000011920928955078125, 0.0, 0.5); - combined = mix(combined, _19.waterColor.xyz, float3(waterTint)); - float foamAmount = 0.0; - if (_68.hasMovementTexture == 1) - { - float foamFactor = smoothstep(0.699999988079071044921875, 1.0, length(flowOffset) * windStrength); - foamAmount = foamFactor * 0.20000000298023223876953125; - combined = mix(combined, float3(1.0), float3(foamAmount)); - } - float3 lightDir = fast::normalize(-_19.lightDirection); - float diffuse = fast::max(dot(normal, lightDir), 0.0); - diffuse *= 0.300000011920928955078125; - float3 halfDir = fast::normalize(lightDir + viewDir); - float specAngle = fast::max(dot(normal, halfDir), 0.0); - float specular = powr(specAngle, 128.0); - specular *= ((fresnel * 0.5) + 0.5); - float waveVariation = (sin((in.TexCoord.x * 50.0) + (_19.time * 2.0)) * 0.5) + 0.5; - waveVariation *= ((cos((in.TexCoord.y * 5)", -R"(0.0) - (_19.time * 1.5)) * 0.5) + 0.5); - specular *= (0.699999988079071044921875 + (waveVariation * 0.300000011920928955078125)); - float3 lighting = _19.lightColor * (diffuse + (specular * 2.0)); - combined += lighting; - float3 specularHighlight = (_19.lightColor * specular) * 2.5; - specularHighlight += float3(foamAmount * 2.0); - float alpha = mix(0.699999988079071044921875, 0.949999988079071044921875, fresnel); - out.FragColor = float4(combined, alpha); - float luminance = fast::max(fast::max(combined.x, combined.y), combined.z); - float3 bloomColor = float3(0.0); - if (luminance > 1.0) - { - bloomColor = combined - float3(1.0); - } - bloomColor += specularHighlight; - out.BrightColor = float4(bloomColor, alpha); - return out; -} - -)", -}; -static const AtlasPackedShaderSource FLUID_FRAG = {FLUID_FRAG_PARTS, 2}; - -static const char* const FLUID_VERT_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct UBO -{ - float4x4 model; - float4x4 view; - float4x4 projection; -}; - -struct main0_out -{ - float2 TexCoord [[user(locn0)]]; - float3 WorldPos [[user(locn1)]]; - float3 WorldNormal [[user(locn2)]]; - float3 WorldTangent [[user(locn3)]]; - float3 WorldBitangent [[user(locn4)]]; - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; - float2 aTexCoord [[attribute(1)]]; - float3 aNormal [[attribute(2)]]; - float3 aTangent [[attribute(3)]]; - float3 aBitangent [[attribute(4)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]], constant UBO& _19 [[buffer(0)]]) -{ - main0_out out = {}; - out.gl_Position = ((_19.projection * _19.view) * _19.model) * float4(in.aPos, 1.0); - out.TexCoord = in.aTexCoord; - out.WorldPos = float3((_19.model * float4(in.aPos, 1.0)).xyz); - out.WorldNormal = fast::normalize(float3x3(_19.model[0].xyz, _19.model[1].xyz, _19.model[2].xyz) * in.aNormal); - out.WorldTangent = fast::normalize(float3x3(_19.model[0].xyz, _19.model[1].xyz, _19.model[2].xyz) * in.aTangent); - out.WorldBitangent = fast::normalize(float3x3(_19.model[0].xyz, _19.model[1].xyz, _19.model[2].xyz) * in.aBitangent); - return out; -} - -)", -}; -static const AtlasPackedShaderSource FLUID_VERT = {FLUID_VERT_PARTS, 1}; - -static const char* const FULLSCREEN_FRAG_PARTS[] = { -R"(#pragma clang diagnostic ignored "-Wmissing-prototypes" -#pragma clang diagnostic ignored "-Wmissing-braces" - -#include -#include - -using namespace metal; - -template -struct spvUnsafeArray -{ - T elements[Num ? Num : 1]; - - thread T& operator [] (size_t pos) thread - { - return elements[pos]; - } - constexpr const thread T& operator [] (size_t pos) const thread - { - return elements[pos]; - } - - device T& operator [] (size_t pos) device - { - return elements[pos]; - } - constexpr const device T& operator [] (size_t pos) const device - { - return elements[pos]; - } - - constexpr const constant T& operator [] (size_t pos) const constant - { - return elements[pos]; - } - - threadgroup T& operator [] (size_t pos) threadgroup - { - return elements[pos]; - } - constexpr const threadgroup T& operator [] (size_t pos) const threadgroup - { - return elements[pos]; - } -}; - -// Implementation of the GLSL mod() function, which is slightly different than Metal fmod() -template -inline Tx mod(Tx x, Ty y) -{ - return x - y * floor(x / y); -} - -struct ColorCorrection -{ - float exposure; - float contrast; - float saturation; - float gamma; - float temperature; - float tint; -}; - -struct PushConstants -{ - int hasBrightTexture; - int hasDepthTexture; - int hasVolumetricLightTexture; - int hasPositionTexture; - int hasLUTTexture; - int hasSSRTexture; - int TextureType; - float lutSize; - int EffectCount; -}; - -struct EffectBuffer -{ - int Effects[1]; -}; - -struct EffectFloat1Buffer -{ - float EffectFloat1[1]; -}; - -struct EffectFloat2Buffer -{ - float EffectFloat2[1]; -}; - -struct EffectFloat3Buffer -{ - float EffectFloat3[1]; -}; - -struct EffectFloat4Buffer -{ - float EffectFloat4[1]; -}; - -struct EffectFloat5Buffer -{ - float EffectFloat5[1]; -}; - -struct Uniforms -{ - float4x4 invProjectionMatrix; - float4x4 projectionMatrix; - float4x4 viewMatrix; - float4x4 invViewMatrix; - float4x4 lastViewMatrix; - float nearPlane; - float farPlane; - float focusDepth; - float focusRange; - int maxMipLevel; - float deltaTime; - float time; -}; - -struct EffectFloat6Buffer -{ - float EffectFloat6[1]; -}; - -struct Clouds -{ - float3 cloudPosition; - float3 cloudSize; - packed_float3 cameraPosition; - float cloudScale; - packed_float3 cloudOffset; - float cloudDensityThreshold; - float cloudDensityMultiplier; - float cloudAbsorption; - float cloudScattering; - float cloudPhaseG; - float cloudClusterStrength; - int cloudPrimarySteps; - int cloudLightSteps; - float cloudLightStepMultiplier; - float cloudMinStepLength; - float3 sunDirection; - packed_float3 sunColor; - float sunIntensity; - packed_float3 cloudAmbientColor; - int hasClouds; -}; - -struct Environment -{ - packed_float3 fogColor; - float fogIntensity; -}; - -constant spvUnsafeArray _165 = spvUnsafeArray({ float2(-0.0033333334140479564666748046875, 0.0033333334140479564666748046875), float2(0.0, 0.0033333334140479564666748046875), float2(0.0033333334140479564666748046875), float2(-0.0033333334140479564666748046875, 0.0), float2(0.0), float2(0.0033333334140479564666748046875, 0.0), float2(-0.0033333334140479564666748046875), float2(0.0, -0.0033333334140479564666748046875), float2(0.0033333334140479564666748046875, -0.0033333334140479564666748046875) }); -constant spvUnsafeArray _171 = spvUnsafeArray({ -1.0, -1.0, -1.0, -1.0, 9.0, -1.0, -1.0, -1.0, -1.0 }); -constant spvUnsafeArray _311 = spvUnsafeArray({ 1.0, 1.0, 1.0, 1.0, -8.0, 1.0, 1.0, 1.0, 1.0 }); - -struct main0_out -{ - float4 FragColor [[color(0)]]; -}; - -struct main0_in -{ - float2 TexCoord [[user(locn0)]]; -}; - -static inline __attribute__((always_inline)) -float4 sampleColor(thread const float2& uv, constant PushConstants& _372, device EffectBuffer& _381, device EffectFloat1Buffer& _394, device EffectFloat2Buffer& _403, device EffectFloat3Buffer& _411, device EffectFloat4Buffer& _419, device EffectFloat5Buffer& _426, texture2d Texture, sampler TextureSmplr) -{ - for (int i = 0; i < _372.EffectCount; i++) - { - if (_381.Effects[i] == 7) - { - float redOffset = _394.EffectFloat1[i]; - float greenOffset = _403.EffectFloat2[i]; - float blueOffset = _411.EffectFloat3[i]; - float2 focusPoint = float2(_419.EffectFloat4[i], _426.EffectFloat5[i]); - float2 sampleCoord = uv; - float2 direction = sampleCoord - focusPoint; - float red = Texture.sample(TextureSmplr, (sampleCoord + (direction * redOffset))).x; - float green = Texture.sample(TextureSmplr, (sampleCoord + (direction * greenOffset))).y; - float2 blue = Texture.sample(TextureSmplr, (sampleCoord + (direction * blueOffset))).zw; - return float4(red, green, blue); - } - else - { - if (_381.Effects[i] == 9) - { - float pixelSizeInPixels = _394.EffectFloat1[i]; - float2 texSize = float2(int2(Texture.get_width(), Texture.get_height())); - float2 pixelSize = float2(pixelSizeInPixels) / texSize; - float2 pixelated = floor(uv / pixelSize) * pixelSize; - return Texture.sample(TextureSmplr, pixelated); - } - else - { - if (_381.Effects[i] == 10) - { - float radius = _394.EffectFloat1[i]; - float separation = _403.EffectFloat2[i]; - float2 texelSize = float2(1.0) / float2(int2(Texture.get_width(), Texture.get_height())); - float3 maxColor = Texture.sample(TextureSmplr, uv).xyz; - int range = int(radius); - float radiusSq = radius * radius; - int _543 = -range; - for (int x = _543; x <= range; x++) - { - int _554 = -range; - for (int y = _554; y <= range; y++) - { - float distSq = float((x * x) + (y * y)); - if (distSq <= radiusSq) - { - float2 offset = (float2(float(x), float(y)) * texelSize) * separation; - float3 sampled = Texture.sample(TextureSmplr, (uv + offset)).xyz; - maxColor = fast::max(maxColor, sampled); - } - } - } - return float4(maxColor, Texture.sample(TextureSmplr, uv).w); - } - } - } - } - return Texture.sample(TextureSmplr, uv); -} - -static inline __attribute__((always_inline)) -float3 reconstructViewPos(thread const float2& uv, thread const float& depth, constant Uniforms& _849) -{ - float z = (depth * 2.0) - 1.0; - float4 clipPos = float4((uv * 2.0) - float2(1.0), z, 1.0); - float4 viewPos = _849.invProjectionMatrix * clipPos; - viewPos /= float4(viewPos.w); - return viewPos.xyz; -} - -static inline __attribute__((always_inline)) -float4 sharpen(texture2d image, sampler imageSmplr, thread float2& TexCoord) -{ - spvUnsafeArray sampleTex; - for (int i = 0; i < 9; i++) - { - sampleTex[i] = float3(image.sample(imageSmplr, (TexCoord + _165[i])).xyz); - } - float3 col = float3(0.0); - for (int i_1 = 0; i_1 < 9; i_1++) - { - col += (sampleTex[i_1] * _171[i_1]); - } - return float4(col, 1.0); -} - -static inline __attribute__((always_inline)) -float4 blur(texture2d image, sampler imageSmplr, thread const float& radius, thread float2& TexCoord) -{ - float2 texelSize = float2(1.0) / float2(int2(image.get_width(), image.get_height())); - float3 result = float3(0.0); - float total = 0.0; - float sigma = radius * 0.5; - float twoSigmaSq = (2.0 * sigma) * sigma; - int _257 = -int(radius); - for (int x = _257; x <= int(radius); x++) - { - float weight = exp(f)", -R"(loat(-(x * x)) / twoSigmaSq); - float2 offset = float2(float(x), 0.0) * texelSize; - result += (image.sample(imageSmplr, (TexCoord + offset)).xyz * weight); - total += weight; - } - result /= float3(total); - return float4(result, 1.0); -} - -static inline __attribute__((always_inline)) -float4 edgeDetection(texture2d image, sampler imageSmplr, thread float2& TexCoord) -{ - spvUnsafeArray sampleTex; - for (int i = 0; i < 9; i++) - { - sampleTex[i] = float3(image.sample(imageSmplr, (TexCoord + _165[i])).xyz); - } - float3 col = float3(0.0); - for (int i_1 = 0; i_1 < 9; i_1++) - { - col += (sampleTex[i_1] * _311[i_1]); - } - return float4(col, 1.0); -} - -static inline __attribute__((always_inline)) -float4 applyFXAA(texture2d tex, sampler texSmplr, thread const float2& texCoord, constant PushConstants& _372, device EffectBuffer& _381, device EffectFloat1Buffer& _394, device EffectFloat2Buffer& _403, device EffectFloat3Buffer& _411, device EffectFloat4Buffer& _419, device EffectFloat5Buffer& _426, texture2d Texture, sampler TextureSmplr) -{ - float2 texelSize = float2(1.0) / float2(int2(tex.get_width(), tex.get_height())); - float FXAA_SPAN_MAX = 8.0; - float FXAA_REDUCE_MUL = 0.125; - float FXAA_REDUCE_MIN = 0.0078125; - float2 param = texCoord + (float2(-1.0) * texelSize); - float3 rgbNW = sampleColor(param, _372, _381, _394, _403, _411, _419, _426, Texture, TextureSmplr).xyz; - float2 param_1 = texCoord + (float2(1.0, -1.0) * texelSize); - float3 rgbNE = sampleColor(param_1, _372, _381, _394, _403, _411, _419, _426, Texture, TextureSmplr).xyz; - float2 param_2 = texCoord + (float2(-1.0, 1.0) * texelSize); - float3 rgbSW = sampleColor(param_2, _372, _381, _394, _403, _411, _419, _426, Texture, TextureSmplr).xyz; - float2 param_3 = texCoord + (float2(1.0) * texelSize); - float3 rgbSE = sampleColor(param_3, _372, _381, _394, _403, _411, _419, _426, Texture, TextureSmplr).xyz; - float2 param_4 = texCoord; - float3 rgbM = sampleColor(param_4, _372, _381, _394, _403, _411, _419, _426, Texture, TextureSmplr).xyz; - float3 luma = float3(0.2989999949932098388671875, 0.58700001239776611328125, 0.114000000059604644775390625); - float lumaNW = dot(rgbNW, luma); - float lumaNE = dot(rgbNE, luma); - float lumaSW = dot(rgbSW, luma); - float lumaSE = dot(rgbSE, luma); - float lumaM = dot(rgbM, luma); - float lumaMin = fast::min(lumaM, fast::min(fast::min(lumaNW, lumaNE), fast::min(lumaSW, lumaSE))); - float lumaMax = fast::max(lumaM, fast::max(fast::max(lumaNW, lumaNE), fast::max(lumaSW, lumaSE))); - float2 dir; - dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); - dir.y = (lumaNW + lumaSW) - (lumaNE + lumaSE); - float dirReduce = fast::max((((lumaNW + lumaNE) + lumaSW) + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN); - float rcpDirMin = 1.0 / (fast::min(abs(dir.x), abs(dir.y)) + dirReduce); - dir = fast::min(float2(FXAA_SPAN_MAX), fast::max(float2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin)) * texelSize; - float2 param_5 = texCoord + (dir * (-0.16666667163372039794921875)); - float2 param_6 = texCoord + (dir * 0.16666667163372039794921875); - float3 rgbA = (sampleColor(param_5, _372, _381, _394, _403, _411, _419, _426, Texture, TextureSmplr).xyz + sampleColor(param_6, _372, _381, _394, _403, _411, _419, _426, Texture, TextureSmplr).xyz) * 0.5; - float2 param_7 = texCoord + (dir * (-0.5)); - float2 param_8 = texCoord + (dir * 0.5); - float3 rgbB = (rgbA * 0.5) + ((sampleColor(param_7, _372, _381, _394, _403, _411, _419, _426, Texture, TextureSmplr).xyz + sampleColor(param_8, _372, _381, _394, _403, _411, _419, _426, Texture, TextureSmplr).xyz) * 0.25); - float lumaB = dot(rgbB, luma); - if ((lumaB < lumaMin) || (lumaB > lumaMax)) - { - return float4(rgbA, 1.0); - } - else - { - return float4(rgbB, 1.0); - } -} - -static inline __attribute__((always_inline)) -float4 applyColorCorrection(thread const float4& color, thread const ColorCorrection& cc) -{ - float3 linearColor = color.xyz; - linearColor *= powr(2.0, cc.exposure); - linearColor = ((linearColor - float3(0.5)) * cc.contrast) + float3(0.5); - linearColor.x += (cc.temperature * 0.0500000007450580596923828125); - linearColor.y += (cc.tint * 0.0500000007450580596923828125); - float luminance = dot(linearColor, float3(0.2125999927520751953125, 0.715200006961822509765625, 0.072200000286102294921875)); - linearColor = mix(float3(luminance), linearColor, float3(cc.saturation)); - linearColor = fast::clamp(linearColor, float3(0.0), float3(1.0)); - return float4(linearColor, color.w); -} - -static inline __attribute__((always_inline)) -float4 applyColorEffects(thread float4& color, constant PushConstants& _372, device EffectBuffer& _381, device EffectFloat1Buffer& _394, device EffectFloat2Buffer& _403, device EffectFloat3Buffer& _411, device EffectFloat4Buffer& _419, device EffectFloat5Buffer& _426, constant Uniforms& _849, device EffectFloat6Buffer& _1049, thread float4& gl_FragCoord) -{ - ColorCorrection cc; - for (int i = 0; i < _372.EffectCount; i++) - { - if (_381.Effects[i] == 0) - { - color = float4(float3(1.0) - color.xyz, color.w); - } - else - { - if (_381.Effects[i] == 1) - { - float average = ((0.2125999927520751953125 * color.x) + (0.715200006961822509765625 * color.y)) + (0.072200000286102294921875 * color.z); - color = float4(average, average, average, color.w); - } - else - { - if (_381.Effects[i] == 5) - { - cc.exposure = _394.EffectFloat1[i]; - cc.contrast = _403.EffectFloat2[i]; - cc.saturation = _411.EffectFloat3[i]; - cc.gamma = _419.EffectFloat4[i]; - cc.temperature = _426.EffectFloat5[i]; - cc.tint = _1049.EffectFloat6[i]; - float4 param = color; - ColorCorrection param_1 = cc; - color = applyColorCorrection(param, param_1); - } - else - { - if (_381.Effects[i] == 8) - { - float levels = fast::max(_394.EffectFloat1[i], 1.0); - float grayscale = fast::max(color.x, fast::max(color.y, color.z)); - if (grayscale > 9.9999997473787516355514526367188e-05) - { - float lower = floor(grayscale * levels) / levels; - float lowerDiff = abs(grayscale - lower); - float upper = ceil(grayscale * levels) / levels; - float upperDiff = abs(upper - grayscale); - float level0 = (lowerDiff <= upperDiff) ? lower : upper; - float adjustment = level0 / fast::max(grayscale, 9.9999997473787516355514526367188e-05); - color *= adjustment; - } - } - else - { - if (_381.Effects[i] == 11) - { - float amount = _394.EffectFloat1[i]; - float3 seed = float3(gl_FragCoord.xy, _849.deltaTime * 100.0); - float n = dot(seed, float3(12.98980045318603515625, 78.233001708984375, 45.16400146484375)); - float noise = fract(sin(n) * 43758.546875); - float grain = ((noise - 0.5) * 2.0) * amount; - float luminance = dot(color.xyz, float3(0.2989999949932098388671875, 0.58700001239776611328125, 0.114000000059604644775390625)); - float visibility = 1.0 - (abs(luminance - 0.5) * 0.5); - float4 _1210 = color; - float3 _1212 = _1210.xyz + float3(grain * visibility); - color.x = _1212.x; - color.y = _12)", -R"(12.y; - color.z = _1212.z; - float4 _1219 = color; - float3 _1223 = fast::clamp(_1219.xyz, float3(0.0), float3(1.0)); - color.x = _1223.x; - color.y = _1223.y; - color.z = _1223.z; - } - } - } - } - } - } - return color; -} - -static inline __attribute__((always_inline)) -float LinearizeDepth(thread const float& depth, constant Uniforms& _849) -{ - float z = (depth * 2.0) - 1.0; - float linear = ((2.0 * _849.nearPlane) * _849.farPlane) / ((_849.farPlane + _849.nearPlane) - (z * (_849.farPlane - _849.nearPlane))); - return linear / _849.farPlane; -} - -static inline __attribute__((always_inline)) -float2 rayBoxDst(thread const float3& boundsMin, thread const float3& boundsMax, thread const float3& rayOrigin, thread const float3& rayDir) -{ - float3 t0 = (boundsMin - rayOrigin) / rayDir; - float3 t1 = (boundsMax - rayOrigin) / rayDir; - float3 tMin = fast::min(t0, t1); - float3 tMax = fast::max(t0, t1); - float dstA = fast::max(fast::max(tMin.x, tMin.y), tMin.z); - float dstB = fast::min(tMax.x, fast::min(tMax.y, tMax.z)); - float dstToContainer = fast::max(0.0, dstA); - float dstInsideContainer = fast::max(0.0, dstB - dstToContainer); - return float2(dstToContainer, dstInsideContainer); -} - -static inline __attribute__((always_inline)) -float hashNoise(thread const float3& p) -{ - return fract(sin(dot(p, float3(12.98980045318603515625, 78.233001708984375, 37.71900177001953125))) * 43758.546875); -} - -static inline __attribute__((always_inline)) -float saturate0(thread const float& v) -{ - return fast::clamp(v, 0.0, 1.0); -} - -static inline __attribute__((always_inline)) -float calculateCloudDensity(thread const float3& worldPos, constant Clouds& _1929, texture3d cloudsTexture, sampler cloudsTextureSmplr) -{ - float3 halfExtents = fast::max(_1929.cloudSize * 0.5, float3(9.9999997473787516355514526367188e-05)); - float3 localPos = (worldPos - _1929.cloudPosition) / halfExtents; - bool _1947 = any(localPos < float3(-1.0)); - bool _1955; - if (!_1947) - { - _1955 = any(localPos > float3(1.0)); - } - else - { - _1955 = _1947; - } - if (_1955) - { - return 0.0; - } - float3 uvw = (localPos * 0.5) + float3(0.5); - float scale = fast::max(_1929.cloudScale, 0.001000000047497451305389404296875); - float3 noiseCoord = fract((uvw * scale) + float3(_1929.cloudOffset)); - float4 shape = cloudsTexture.sample(cloudsTextureSmplr, noiseCoord); - float param = _1929.cloudClusterStrength; - float cluster = saturate0(param); - float lowerFade = smoothstep(-0.949999988079071044921875, -0.60000002384185791015625, localPos.y); - float upperFade = 1.0 - smoothstep(0.3499999940395355224609375, 0.949999988079071044921875, localPos.y); - float verticalMask = lowerFade * upperFade; - float coverageThreshold = mix(0.60000002384185791015625, 0.2800000011920928955078125, cluster); - float coverageSoftness = mix(0.2199999988079071044921875, 0.3400000035762786865234375, cluster); - float coverageNoise = mix(shape.x, shape.w, 0.4000000059604644775390625 + (cluster * 0.3499999940395355224609375)); - float coverage = smoothstep(coverageThreshold, coverageThreshold + coverageSoftness, coverageNoise); - coverage = powr(coverage, mix(2.0, 0.699999988079071044921875, cluster)); - float detail = mix(smoothstep(0.25, 0.75, shape.y), smoothstep(0.20000000298023223876953125, 0.89999997615814208984375, shape.w), 0.550000011920928955078125); - detail = powr(detail, mix(1.60000002384185791015625, 0.85000002384185791015625, cluster)); - float cavityNoise = smoothstep(0.2199999988079071044921875, 0.85000002384185791015625, shape.z); - float gapMask = fast::clamp(1.0 - (cavityNoise * mix(0.25, 0.699999988079071044921875, cluster)), 0.0, 1.0); - float density = coverage * mix(detail, 1.0, cluster * 0.3499999940395355224609375); - density = fast::max(((density * gapMask) * verticalMask) - 0.0199999995529651641845703125, 0.0); - density *= fast::max(_1929.cloudDensityMultiplier, 0.0); - return density; -} - -static inline __attribute__((always_inline)) -float sampleSunTransmittance(thread const float3& worldPos, thread const float& stepSize, constant Clouds& _1929, texture3d cloudsTexture, sampler cloudsTextureSmplr) -{ - float3 lightDir = -_1929.sunDirection; - float dirLength = length(lightDir); - if (dirLength < 0.001000000047497451305389404296875) - { - lightDir = float3(0.0, 1.0, 0.0); - } - else - { - lightDir /= float3(dirLength); - } - float maxDistance = length(_1929.cloudSize) * 1.5; - float travel = 0.0; - float attenuation = 1.0; - float lightStep = fast::max(stepSize * _1929.cloudLightStepMultiplier, _1929.cloudMinStepLength); - int steps = max(_1929.cloudLightSteps, 1); - for (int i = 0; (i < steps) && (attenuation > 0.0500000007450580596923828125); i++) - { - travel += lightStep; - if (travel > maxDistance) - { - break; - } - float3 samplePos = worldPos + (lightDir * travel); - float3 param = samplePos; - float density = calculateCloudDensity(param, _1929, cloudsTexture, cloudsTextureSmplr); - attenuation *= exp(((-density) * lightStep) * _1929.cloudAbsorption); - lightStep = fast::max(lightStep * _1929.cloudLightStepMultiplier, _1929.cloudMinStepLength); - } - return attenuation; -} - -static inline __attribute__((always_inline)) -float henyeyGreenstein(thread const float& cosTheta, thread const float& g) -{ - float g2 = g * g; - float denom = powr((1.0 + g2) - ((2.0 * g) * cosTheta), 1.5); - return (1.0 - g2) / (12.56637096405029296875 * fast::max(denom, 9.9999997473787516355514526367188e-05)); -} - -static inline __attribute__((always_inline)) -float4 cloudRendering(thread const float4& inColor, thread float2& TexCoord, constant PushConstants& _372, constant Uniforms& _849, constant Clouds& _1929, texture3d cloudsTexture, sampler cloudsTextureSmplr, texture2d DepthTexture, sampler DepthTextureSmplr) -{ - if (_1929.hasClouds != 1) - { - return inColor; - } - float _2197; - if (_372.hasDepthTexture == 1) - { - _2197 = DepthTexture.sample(DepthTextureSmplr, TexCoord).x; - } - else - { - _2197 = 1.0; - } - float nonLinearDepth = _2197; - bool depthAvailable = (_372.hasDepthTexture == 1) && (nonLinearDepth < 1.0); - float depthSample = depthAvailable ? nonLinearDepth : 1.0; - float3 rayOrigin = float3(_1929.cameraPosition); - float4 clipSpace = float4((TexCoord * 2.0) - float2(1.0), (depthSample * 2.0) - 1.0, 1.0); - float4 viewSpace = _849.invProjectionMatrix * clipSpace; - viewSpace /= float4(viewSpace.w); - float3 worldPos = (_849.invViewMatrix * float4(viewSpace.xyz, 1.0)).xyz; - float3 rayDir = fast::normalize(worldPos - rayOrigin); - float _2261; - if (depthAvailable) - { - _2261 = length(worldPos - rayOrigin); - } - else - { - _2261 = 1000000.0; - } - float sceneDistance = _2261; - float3 boundsMin = _1929.cloudPosition - (_1929.cloudSize * 0.5); - float3 boundsMax = _1929.cloudPosition + (_1929.cloudSize * 0.5); - float3 param = boundsMin; - float3 param_1 = boundsMax; - float3 param_2 = rayOrigin; - float3 param_3 = rayDir; - float2 rayBoxInfo = rayBoxDst(param, param_1, param_2, param_3); - float distToContainer = rayBoxInfo.x; - float distInContainer = rayBoxInfo.y; - if (distInContainer <= 0.0) - { - return inColor; - } - float dstLimit = fast::min(sceneDistance - distToContainer, distInContainer); - dstLimit = fast::max(dstLimit, 0.0); - if (dstLimit <= 9.9999997473787516355514526367188e-05) - { - return inColor; - } - int steps = max(_1929.cloudPrimarySteps, 8); - float baseStep = dstLimit / float(steps); - float stepSize = fast::max(baseStep, _1929.cloudMinStepLength); - float3 param_4 = float3(TexCoord, _849.time); - float jitter = hashNoise(param_4) - 0.5; - float travelled = f)", -R"(ast::clamp(jitter, -0.3499999940395355224609375, 0.3499999940395355224609375) * stepSize; - travelled = fast::max(travelled, 0.0); - float3 accumulatedLight = float3(0.0); - float transmittance = 1.0; - float3 sunDir = _1929.sunDirection; - float sunLen = length(sunDir); - if (sunLen > 0.001000000047497451305389404296875) - { - sunDir /= float3(sunLen); - } - else - { - sunDir = float3(0.0, 1.0, 0.0); - } - float phaseG = fast::clamp(_1929.cloudPhaseG, -0.949999988079071044921875, 0.949999988079071044921875); - for (int _step = 0; (_step < steps) && (travelled < dstLimit); _step++) - { - if (transmittance <= 0.00999999977648258209228515625) - { - break; - } - float remainingDistance = dstLimit - travelled; - if (remainingDistance <= 9.9999997473787516355514526367188e-06) - { - break; - } - float current = distToContainer + travelled; - float3 samplePos = rayOrigin + (rayDir * current); - float3 param_5 = samplePos; - float density = calculateCloudDensity(param_5, _1929, cloudsTexture, cloudsTextureSmplr); - if (density > 9.9999997473787516355514526367188e-05) - { - float adaptiveStep = stepSize; - if (density < 0.0199999995529651641845703125) - { - adaptiveStep = stepSize * 2.5; - } - else - { - if (density < 0.0500000007450580596923828125) - { - adaptiveStep = stepSize * 1.60000002384185791015625; - } - } - adaptiveStep = fast::min(adaptiveStep, remainingDistance); - float sampleWeight = density * adaptiveStep; - float3 param_6 = samplePos; - float param_7 = adaptiveStep; - float lightTrans = sampleSunTransmittance(param_6, param_7, _1929, cloudsTexture, cloudsTextureSmplr); - float cosTheta = fast::clamp(dot(rayDir, -sunDir), -1.0, 1.0); - float param_8 = cosTheta; - float param_9 = phaseG; - float phase = henyeyGreenstein(param_8, param_9); - float3 directLight = ((float3(_1929.sunColor) * _1929.sunIntensity) * lightTrans) * phase; - float3 ambientLight = float3(_1929.cloudAmbientColor); - float3 lighting = (((ambientLight * 0.3499999940395355224609375) + directLight) * sampleWeight) * _1929.cloudScattering; - accumulatedLight += (lighting * transmittance); - transmittance *= exp(((-density) * adaptiveStep) * _1929.cloudAbsorption); - travelled += adaptiveStep; - continue; - } - float emptyAdvance = fast::min(stepSize * 2.25, remainingDistance); - float minAdvance = fast::min(stepSize * 0.5, remainingDistance); - travelled += fast::max(emptyAdvance, minAdvance); - } - float3 finalColor = (inColor.xyz * transmittance) + accumulatedLight; - return float4(fast::clamp(finalColor, float3(0.0), float3(1.0)), inColor.w); -} - -static inline __attribute__((always_inline)) -float4 sampleBright(thread const float2& uv, constant PushConstants& _372, device EffectBuffer& _381, device EffectFloat1Buffer& _394, device EffectFloat2Buffer& _403, device EffectFloat3Buffer& _411, device EffectFloat4Buffer& _419, device EffectFloat5Buffer& _426, texture2d BrightTexture, sampler BrightTextureSmplr) -{ - for (int i = 0; i < _372.EffectCount; i++) - { - if (_381.Effects[i] == 7) - { - float redOffset = _394.EffectFloat1[i]; - float greenOffset = _403.EffectFloat2[i]; - float blueOffset = _411.EffectFloat3[i]; - float2 focusPoint = float2(_419.EffectFloat4[i], _426.EffectFloat5[i]); - float2 sampleCoord = uv; - float2 direction = sampleCoord - focusPoint; - float red = BrightTexture.sample(BrightTextureSmplr, (sampleCoord + (direction * redOffset))).x; - float green = BrightTexture.sample(BrightTextureSmplr, (sampleCoord + (direction * greenOffset))).y; - float2 blue = BrightTexture.sample(BrightTextureSmplr, (sampleCoord + (direction * blueOffset))).zw; - return float4(red, green, blue); - } - else - { - if (_381.Effects[i] == 9) - { - float pixelSizeInPixels = _394.EffectFloat1[i]; - float2 texSize = float2(int2(BrightTexture.get_width(), BrightTexture.get_height())); - float2 pixelSize = float2(pixelSizeInPixels) / texSize; - float2 pixelated = floor(uv / pixelSize) * pixelSize; - float4 color = BrightTexture.sample(BrightTextureSmplr, pixelated); - return color; - } - else - { - if (_381.Effects[i] == 10) - { - float radius = _394.EffectFloat1[i]; - float separation = _403.EffectFloat2[i]; - float2 texelSize = float2(1.0) / float2(int2(BrightTexture.get_width(), BrightTexture.get_height())); - float3 maxColor = BrightTexture.sample(BrightTextureSmplr, uv).xyz; - int range = int(radius); - float radiusSq = radius * radius; - int _766 = -range; - for (int x = _766; x <= range; x++) - { - int _777 = -range; - for (int y = _777; y <= range; y++) - { - float distSq = float((x * x) + (y * y)); - if (distSq <= radiusSq) - { - float2 offset = (float2(float(x), float(y)) * texelSize) * separation; - float3 sampled = BrightTexture.sample(BrightTextureSmplr, (uv + offset)).xyz; - maxColor = fast::max(maxColor, sampled); - } - } - } - return float4(maxColor, BrightTexture.sample(BrightTextureSmplr, uv).w); - } - } - } - } - return BrightTexture.sample(BrightTextureSmplr, uv); -} - -static inline __attribute__((always_inline)) -float4 composeSSR(thread const float4& color, thread const float2& uv, constant PushConstants& _372, texture2d SSRTexture, sampler SSRTextureSmplr) -{ - if (_372.hasSSRTexture != 1) - { - return color; - } - float4 ssr = SSRTexture.sample(SSRTextureSmplr, uv); - float reflectionWeight = fast::clamp(ssr.w, 0.0, 1.0); - float baseWeight = 1.0 - reflectionWeight; - float4 result = color; - result.xyz = (result.xyz * baseWeight) + (ssr.xyz * reflectionWeight); - return result; -} - -static inline __attribute__((always_inline)) -float4 composeLighting(thread const float2& uv, thread const float4& baseColor, constant PushConstants& _372, device EffectBuffer& _381, device EffectFloat1Buffer& _394, device EffectFloat2Buffer& _403, device EffectFloat3Buffer& _411, device EffectFloat4Buffer& _419, device EffectFloat5Buffer& _426, texture2d BrightTexture, sampler BrightTextureSmplr, texture2d VolumetricLightTexture, sampler VolumetricLightTextureSmplr, texture2d SSRTexture, sampler SSRTextureSmplr) -{ - float4 color = baseColor; - if (_372.hasBrightTexture == 1) - { - color += sampleBright(uv, _372, _381, _394, _403, _411, _419, _426, BrightTexture, BrightTextureSmplr); - } - if (_372.hasVolumetricLightTexture == 1) - { - color += VolumetricLightTexture.sample(VolumetricLightTextureSmplr, uv); - } - return composeSSR(color, uv, _372, SSRTexture, SSRTextureSmplr); -} - -static inline __attribute__((always_inline)) -float4 applyMotionBlur(thread const float2& texCoord, thread const float& size, thread const float& separation, thread const float4& color, constant PushConstants& _372, device EffectBuffer& _381, device EffectFloat1Buffer& _394, device EffectFloat2Buffer& _403, device EffectFloat3Buffer& _411, device EffectFloat4Buffer& _419, device EffectFloat5Buffer& _426, texture2d Texture, sampler TextureSmplr, texture2d BrightTexture, sampler BrightTextureSmplr, constant Uniforms& _849, texture2d VolumetricLightTexture, sampler VolumetricLightTextureSmplr, texture2d SSRTexture, sampler SSRTextureSmplr, texture2d PositionTexture, sampler PositionTextureSmplr, texture2d DepthTexture, sampler DepthTextureSmplr) -{ - float4 fallbackColor = composeLighting(texCoord, color, _372, _381, _394, _403, _411, _419, _426, BrightTexture, BrightTextureSmplr, VolumetricLightTexture, VolumetricLightTextureSmplr, SSRTexture, SSRTextureSmplr); - if ((size <= 0.0) || (separation <= 0.0)) - { - return fallbackColor; - } - if (_372.hasPositionTexture != 1) - { - return fallbackColor; - } - float4 worldPos = PositionTexture.sample(PositionTextureSmplr, texCoord); - if (worldPos.w <= 0.0) - { - return fallbackColor; - } - float3 viewSpacePos = (_849.viewMatrix * worldPos).xyz; - float distanceToCamera = length(viewSpacePos); - if (distanceToCamera < (_849.nearPlane * 2.0)) - { - return fallbackColor; - } - float4 currentClipPos = (_849.projectionMatrix * _849.viewMatrix) * worldPos; - float _1543 = currentClipPos.w; - float4 _1544 = currentClipPos; - float3 _1547 = _1544.xyz / float3(_1543); - currentClipPos.x = _1547.x; - currentClipPos.y = _1547.y; - currentClipPos.z = _1547.z; - float2 currentUV = (currentClipPos.xy * 0.5) + float2(0.5); - float4 prevClipPos = (_849.projectionMatrix * _849.lastViewMatrix) * worldPos; - float _1569 = prevClipPos.w; - float4 _1570 = prevClipPos; - float3 _1573 = _1570.xyz / float3(_1569); - prevClipPos.x = _1573.x; - prevClipPos.y = _1573.y; - prevClipPos.z = _1573.z; - float2 prevUV = (prevClipPos.xy * 0.5) + float2(0.5); - float2 velocity = (currentUV - prevUV) * separation; - float velocityLength = length(velocity); - float maxVelocity = 0.119999997317790985107421875; - if (velocityLength > maxVelocity) - { - velocity = fast::normalize(velocity) * maxVelocity; - velocityLength = maxVelocity; - } - if (_372.hasSSRTexture == 1) - { - float mirrorWeight = fast::clamp(SSRTexture.sample(SSRTextureSmplr, texCoord).w, 0.0, 1.0); - float blurDamp = mix(1.0, 0.20000000298023223876953125, mirrorWeight); - velocity *= blurDamp; - velocityLength *= blurDamp; - } - if (velocityLength < 9.9999997473787516355514526367188e-05) - { - return fallbackColor; - } - int baseSamples = clamp(int(size), 2, 32); - float sampleScale = mix(0.75, 1.75, fast::clamp(velocityLength / maxVelocity, 0.0, 1.0)); - int samples = clamp(int(float(baseSamples) * sampleScale), 3, 48); - float centerDepth = 0.0; - float depthSoftness = 1.0; - if (_372.hasDepthTexture == 1) - { - float centerDepthRaw = DepthTexture.sample(DepthTextureSmplr, texCoord).x; - centerDepth = LinearizeDepth(centerDepthRaw, _849); - depthSoftness = fast::max(0.00200000009499490261077880859375, centerDepth * 0.0199999995529651641845703125); - } - float jitter = (fract(sin(dot(texCoord * float2(173.3000030517578125, 97.09999847412109375), float2(12.98980045318603515625, 78.233001708984375))) * 43758.546875) - 0.5) * 0.3499999940395355224609375; - float4 result = float4(0.0); - float totalWeight = 0.0; - for (int i = 0; i < samples; i++) - { - float t = (((float(i) + 0.5) / float(samples)) * 2.0) - 1.0; - t += jitter / float(samples); - float2 sampleCoord = texCoord + (velocity * t); - bool _1642 = sampleCoord.x < 0.0; - bool _1648; - if (!_1642) - { - _1648 = sampleCoord.x > 1.0; - } - else - { - _1648 = _1642; - } - bool _1654; - if (!_1648) - { - _1654 = sampleCoord.y < 0.0; - } - else - { - _1654 = _1648; - } - bool _1660; - if (!_1654) - { - _1660 = sampleCoord.y > 1.0; - } - else - { - _1660 = _1654; - } - if (_1660) - { - continue; - } - float depthWeight = 1.0; - if (_372.hasDepthTexture == 1) - { - float sampleDepthRaw = DepthTexture.sample(DepthTextureSmplr, sampleCoord).x; - float sampleDepth = LinearizeDepth(sampleDepthRaw, _849); - float depthDelta = abs(sampleDepth - centerDepth); - depthWeight = 1.0 - smoothstep(depthSoftness, depthSoftness * 2.5, depthDelta); - if (depthWeight <= 0.0) - { - continue; - } - } - float4 sampled = sampleColor(sampleCoord, _372, _381, _394, _403, _411, _419, _426, Texture, TextureSmplr); - sampled = composeLighting(sampleCoord, sampled, _372, _381, _394, _403, _411, _419, _426, BrightTexture, BrightTextureSmplr, VolumetricLightTexture, VolumetricLightTextureSmplr, SSRTexture, SSRTextureSmplr); - float gaussian = exp((-4.0) * t * t); - float weight = gaussian * depthWeight; - result += (sampled * weight); - totalWeight += weight; - } - if (totalWeight > 0.0) - { - return result / float4(totalWeight); - } - return fallbackColor; -} - -static inline __attribute__((always_inline)) -float3 sampleLUT(thread const float3& rgb, thread const float& blueSlice, thread const float& sliceSize, thread const float& slicePixelOffset, constant PushConstants& _372, texture2d LUTTexture, sampler LUTTextureSmplr) -{ - float sliceY = floor(blueSlice / _372.lutSize); - float sliceX = mod(blueSlice, _372.lutSize); - float2 uv; - uv.x = ((sliceX * sliceSize) + slicePixelOffset) + (rgb.x * sliceSize); - uv.y = ((sliceY * sliceSize) + slicePixelOffset) + (rgb.y * sliceSize); - return LUTTexture.sample(LUTTextureSmplr, uv).xyz; -} - -static inline __attribute__((always_inline)) -float4 mapToLUT(thread const float4& color, constant PushConstants& _372, texture2d LUTTexture, sampler LUTTextureSmplr) -{ - if (_372.hasLUTTexture != 1) - { - return color; - } - float sliceSize = 1.0 / _372.lutSize; - float slicePixelOffset = sliceSize * 0.5; - float blueIndex = color.z * (_372.lutSize - 1.0); - float sliceLow = floor(blueIndex); - float sliceHigh = fast::min(sliceLow + 1.0, _372.lutSize - 1.0); - float t = blueIndex - sliceLow; - float3 param = color.xyz; - float param_1 = sliceLow; - float param_2 = sliceSize; - float param_3 = slicePixelOffset; - float3 lowColor = sampleLUT(param, param_1, param_2, param_3, _372, LUTTexture, LUTTextureSmplr); - float3 param_4 = color.xyz; - float param_5 = sliceHigh; - float param_6 = sliceSize; - float param_7 = slicePixelOffset; - float3 highColor = sampleLUT(param_4, param_5, param_6, param_7, _372, LUTTexture, LUTTextureSmplr); - float3 finalRGB = mix(lowColor, highColor, float3(t)); - return float4(finalRGB, color.w); -} - -static inline __attribute__((always_inline)) -float3 acesToneMapping(thread const float3& color) -{ - float a = 2.5099999904632568359375; - float b = 0.02999999932944774627685546875; - float c = 2.4300000667572021484375; - float d = 0.589999973773956298828125; - float e = 0.14000000059604644775390625; - return fast::clamp((color * ((color * a) + float3(b))) / ((color * ((color * c) + float3(d))) + float3(e)), float3(0.0), float3(1.0)); -} - -fragment main0_out main0(main0_in in [[stage_in]], constant PushConstants& _372 [[buffer(0)]], device EffectBuffer& _381 [[buffer(1)]], device EffectFloat1Buffer& _394 [[buffer(2)]], device EffectFloat2Buffer& _403 [[buffer(3)]], device EffectFloat3Buffer& _411 [[buffer(4)]], device EffectFloat4Buffer& _419 [[buffer(5)]], device EffectFloat5Buffer& _426 [[buffer(6)]], constant Uniforms& _849 [[buffer(7)]], device EffectFloat6Buffer& _1049 [[buffer(8)]], constant Clouds& _1929 [[buffer(9)]], constant Environment& environment [[buffer(10)]], texture2d Texture [[texture(0)]], texture2d BrightTexture [[texture(1)]], texture2d VolumetricLightTexture [[texture(2)]], texture2d SSRTexture [[texture(3)]], texture2d PositionTexture [[texture(4)]], texture2d LUTTexture [[texture(5)]], )", -R"(texture3d cloudsTexture [[texture(6)]], texture2d DepthTexture [[texture(7)]], sampler TextureSmplr [[sampler(0)]], sampler BrightTextureSmplr [[sampler(1)]], sampler VolumetricLightTextureSmplr [[sampler(2)]], sampler SSRTextureSmplr [[sampler(3)]], sampler PositionTextureSmplr [[sampler(4)]], sampler LUTTextureSmplr [[sampler(5)]], sampler cloudsTextureSmplr [[sampler(6)]], sampler DepthTextureSmplr [[sampler(7)]], float4 gl_FragCoord [[position]]) -{ - main0_out out = {}; - float2 param = in.TexCoord; - float4 color = sampleColor(param, _372, _381, _394, _403, _411, _419, _426, Texture, TextureSmplr); - float depth = 1.0; - if (_372.hasDepthTexture == 1) - { - depth = DepthTexture.sample(DepthTextureSmplr, in.TexCoord).x; - } - float2 param_1 = in.TexCoord; - float param_2 = depth; - float3 viewPos = reconstructViewPos(param_1, param_2, _849); - float _distance = _372.hasDepthTexture == 1 ? length(viewPos) : _849.farPlane; - bool useMotionBlur = false; - float motionBlurSize = 0.0; - float motionBlurSeparation = 0.0; - for (int i = 0; i < _372.EffectCount; i++) - { - if (_381.Effects[i] == 6) - { - useMotionBlur = true; - motionBlurSize = _394.EffectFloat1[i]; - motionBlurSeparation = _403.EffectFloat2[i]; - } - } - for (int i_1 = 0; i_1 < _372.EffectCount; i_1++) - { - if (_381.Effects[i_1] == 2) - { - color = sharpen(Texture, TextureSmplr, in.TexCoord); - } - else - { - if (_381.Effects[i_1] == 3) - { - float radius = _394.EffectFloat1[i_1]; - float param_3 = radius; - color = blur(Texture, TextureSmplr, param_3, in.TexCoord); - } - else - { - if (_381.Effects[i_1] == 4) - { - color = edgeDetection(Texture, TextureSmplr, in.TexCoord); - } - } - } - } - float2 param_4 = in.TexCoord; - color = applyFXAA(Texture, TextureSmplr, param_4, _372, _381, _394, _403, _411, _419, _426, Texture, TextureSmplr); - float4 param_5 = color; - float4 _2637 = applyColorEffects(param_5, _372, _381, _394, _403, _411, _419, _426, _849, _1049, gl_FragCoord); - color = _2637; - if (_372.hasDepthTexture == 1) - { - float depthValue = DepthTexture.sample(DepthTextureSmplr, in.TexCoord).x; - float param_6 = depthValue; - float linearDepth = LinearizeDepth(param_6, _849); - float coc = fast::clamp(abs(linearDepth - _849.focusDepth) / _849.focusRange, 0.0, 1.0); - float mip = (coc * float(_849.maxMipLevel)) * 1.2000000476837158203125; - float4 param_7 = Texture.sample(TextureSmplr, in.TexCoord, level(mip)); - float4 _2676 = applyColorEffects(param_7, _372, _381, _394, _403, _411, _419, _426, _849, _1049, gl_FragCoord); - float3 blurred = _2676.xyz; - float3 sharp = color.xyz; - float4 param_8 = color; - color = cloudRendering(param_8, in.TexCoord, _372, _849, _1929, cloudsTexture, cloudsTextureSmplr, DepthTexture, DepthTextureSmplr); - } - else - { - float4 param_9 = color; - color = cloudRendering(param_9, in.TexCoord, _372, _849, _1929, cloudsTexture, cloudsTextureSmplr, DepthTexture, DepthTextureSmplr); - } - float4 hdrColor; - if (useMotionBlur) - { - float2 param_10 = in.TexCoord; - float param_11 = motionBlurSize; - float param_12 = motionBlurSeparation; - float4 param_13 = color; - float4 motionBlurred = applyMotionBlur(param_10, param_11, param_12, param_13, _372, _381, _394, _403, _411, _419, _426, Texture, TextureSmplr, BrightTexture, BrightTextureSmplr, _849, VolumetricLightTexture, VolumetricLightTextureSmplr, SSRTexture, SSRTextureSmplr, PositionTexture, PositionTextureSmplr, DepthTexture, DepthTextureSmplr); - out.FragColor = motionBlurred; - return out; - } - else - { - float2 param_14 = in.TexCoord; - float4 param_15 = color; - hdrColor = composeLighting(param_14, param_15, _372, _381, _394, _403, _411, _419, _426, BrightTexture, BrightTextureSmplr, VolumetricLightTexture, VolumetricLightTextureSmplr, SSRTexture, SSRTextureSmplr); - } - float4 param_16 = hdrColor; - hdrColor = mapToLUT(param_16, _372, LUTTexture, LUTTextureSmplr); - float3 param_17 = hdrColor.xyz; - float3 _2744 = acesToneMapping(param_17); - hdrColor.x = _2744.x; - hdrColor.y = _2744.y; - hdrColor.z = _2744.z; - float fogFactor = 1.0 - exp((-_distance) * environment.fogIntensity); - float3 finalColor = mix(hdrColor.xyz, float3(environment.fogColor), float3(fogFactor)); - out.FragColor = float4(finalColor, 1.0); - return out; -} -)", -}; -static const AtlasPackedShaderSource FULLSCREEN_FRAG = {FULLSCREEN_FRAG_PARTS, 6}; - -static const char* const FULLSCREEN_VERT_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct main0_out -{ - float2 TexCoord [[user(locn0)]]; - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; - float2 aTexCoord [[attribute(2)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]]) -{ - main0_out out = {}; - out.gl_Position = float4(in.aPos.xy, 0.0, 1.0); - out.TexCoord = in.aTexCoord; - return out; -} - -)", -}; -static const AtlasPackedShaderSource FULLSCREEN_VERT = {FULLSCREEN_VERT_PARTS, 1}; - -static const char* const GAUSSIAN_FRAG_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct Params -{ - uint horizontal; - float4 weight[5]; - float radius; -}; - -struct main0_out -{ - float4 FragColor [[color(0)]]; -}; - -struct main0_in -{ - float2 TexCoord [[user(locn0)]]; -}; - -fragment main0_out main0(main0_in in [[stage_in]], constant Params& _29 [[buffer(0)]], texture2d image [[texture(0)]], sampler imageSmplr [[sampler(0)]]) -{ - main0_out out = {}; - float2 tex_offset = (float2(1.0) / float2(int2(image.get_width(), image.get_height()))) * _29.radius; - float3 result = image.sample(imageSmplr, in.TexCoord).xyz * _29.weight[0].x; - if (_29.horizontal != 0u) - { - for (int i = 1; i < 5; i++) - { - result += (image.sample(imageSmplr, (in.TexCoord + float2(tex_offset.x * float(i), 0.0))).xyz * _29.weight[i].x); - result += (image.sample(imageSmplr, (in.TexCoord - float2(tex_offset.x * float(i), 0.0))).xyz * _29.weight[i].x); - } - } - else - { - for (int i_1 = 1; i_1 < 5; i_1++) - { - result += (image.sample(imageSmplr, (in.TexCoord + float2(0.0, tex_offset.y * float(i_1)))).xyz * _29.weight[i_1].x); - result += (image.sample(imageSmplr, (in.TexCoord - float2(0.0, tex_offset.y * float(i_1)))).xyz * _29.weight[i_1].x); - } - } - out.FragColor = float4(result, 1.0); - return out; -} - -)", -}; -static const AtlasPackedShaderSource GAUSSIAN_FRAG = {GAUSSIAN_FRAG_PARTS, 1}; - -static const char* const LIGHT_FRAG_PARTS[] = { -R"(#pragma clang diagnostic ignored "-Wmissing-prototypes" -#pragma clang diagnostic ignored "-Wmissing-braces" - -#include -#include - -using namespace metal; - -template struct spvUnsafeArray { - T elements[Num ? Num : 1]; - - thread T &operator[](size_t pos) thread { return elements[pos]; } - constexpr const thread T &operator[](size_t pos) const thread { - return elements[pos]; - } - - device T &operator[](size_t pos) device { return elements[pos]; } - constexpr const device T &operator[](size_t pos) const device { - return elements[pos]; - } - - constexpr const constant T &operator[](size_t pos) const constant { - return elements[pos]; - } - - threadgroup T &operator[](size_t pos) threadgroup { return elements[pos]; } - constexpr const threadgroup T &operator[](size_t pos) const threadgroup { - return elements[pos]; - } -}; - -// Implementation of the GLSL radians() function -template inline T radians(T d) { return d * T(0.01745329251); } - -// Returns the determinant of a 2x2 matrix. -static inline __attribute__((always_inline)) float -spvDet2x2(float a1, float a2, float b1, float b2) { - return a1 * b2 - b1 * a2; -} - -// Returns the determinant of a 3x3 matrix. -static inline __attribute__((always_inline)) float -spvDet3x3(float a1, float a2, float a3, float b1, float b2, float b3, float c1, - float c2, float c3) { - return a1 * spvDet2x2(b2, b3, c2, c3) - b1 * spvDet2x2(a2, a3, c2, c3) + - c1 * spvDet2x2(a2, a3, b2, b3); -} - -// Returns the inverse of a matrix, by using the algorithm of calculating the -// classical adjoint and dividing by the determinant. The contents of the matrix -// are changed. -static inline __attribute__((always_inline)) float4x4 -spvInverse4x4(float4x4 m) { - float4x4 adj; // The adjoint matrix (inverse after dividing by determinant) - - // Create the transpose of the cofactors, as the classical adjoint of the - // matrix. - adj[0][0] = spvDet3x3(m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], m[2][3], - m[3][1], m[3][2], m[3][3]); - adj[0][1] = -spvDet3x3(m[0][1], m[0][2], m[0][3], m[2][1], m[2][2], m[2][3], - m[3][1], m[3][2], m[3][3]); - adj[0][2] = spvDet3x3(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], - m[3][1], m[3][2], m[3][3]); - adj[0][3] = -spvDet3x3(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], - m[2][1], m[2][2], m[2][3]); - - adj[1][0] = -spvDet3x3(m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], m[2][3], - m[3][0], m[3][2], m[3][3]); - adj[1][1] = spvDet3x3(m[0][0], m[0][2], m[0][3], m[2][0], m[2][2], m[2][3], - m[3][0], m[3][2], m[3][3]); - adj[1][2] = -spvDet3x3(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], - m[3][0], m[3][2], m[3][3]); - adj[1][3] = spvDet3x3(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], - m[2][0], m[2][2], m[2][3]); - - adj[2][0] = spvDet3x3(m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], m[2][3], - m[3][0], m[3][1], m[3][3]); - adj[2][1] = -spvDet3x3(m[0][0], m[0][1], m[0][3], m[2][0], m[2][1], m[2][3], - m[3][0], m[3][1], m[3][3]); - adj[2][2] = spvDet3x3(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], - m[3][0], m[3][1], m[3][3]); - adj[2][3] = -spvDet3x3(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], - m[2][0], m[2][1], m[2][3]); - - adj[3][0] = -spvDet3x3(m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2], - m[3][0], m[3][1], m[3][2]); - adj[3][1] = spvDet3x3(m[0][0], m[0][1], m[0][2], m[2][0], m[2][1], m[2][2], - m[3][0], m[3][1], m[3][2]); - adj[3][2] = -spvDet3x3(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], - m[3][0], m[3][1], m[3][2]); - adj[3][3] = spvDet3x3(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], - m[2][0], m[2][1], m[2][2]); - - // Calculate the determinant as a combination of the cofactors of the first - // row. - float det = (adj[0][0] * m[0][0]) + (adj[0][1] * m[1][0]) + - (adj[0][2] * m[2][0]) + (adj[0][3] * m[3][0]); - - // Divide the classical adjoint matrix by the determinant. - // If determinant is zero, matrix is not invertable, so leave it unchanged. - return (det != 0.0f) ? (adj * (1.0f / det)) : m; -} - -struct ShadowParameters { - float4x4 lightView; - float4x4 lightProjection; - float bias0; - int textureIndex; - float farPlane; - int lightIndex; - float3 lightPos; - int lightType; -}; - -struct DirectionalLight { - float3 direction; - float _pad1; - float3 diffuse; - float _pad2; - float3 specular; - float intensity; -}; - -struct PointLight { - float3 position; - float _pad1; - float3 diffuse; - float _pad2; - float3 specular; - float intensity; - float constant0; - float linear; - float quadratic; - float radius; - float _pad3; -}; - -struct SpotLight { - float3 position; - float _pad1; - float3 direction; - float cutOff; - float outerCutOff; - float intensity; - float range; - float _pad4; - float3 diffuse; - float _pad5; - float3 specular; - float _pad6; -}; - -struct UBO { - packed_float3 cameraPosition; - uint useIBL; -}; - -struct Environment { - float rimLightIntensity; - float3 rimLightColor; - float bloomThreshold; -}; - -struct PushConstants { - int directionalLightCount; - int pointLightCount; - int spotlightCount; - int areaLightCount; - int shadowParamCount; -}; - -struct ShadowParameters_1 { - float4x4 lightView; - float4x4 lightProjection; - float bias0; - int textureIndex; - float farPlane; - int lightIndex; - packed_float3 lightPos; - int lightType; -}; - -struct ShadowParams { - spvUnsafeArray shadowParams; -}; - -struct DirectionalLight_1 { - packed_float3 direction; - float _pad1; - packed_float3 diffuse; - float _pad2; - packed_float3 specular; - float intensity; -}; - -struct DirectionalLights { - spvUnsafeArray directionalLights; -}; - -struct PointLight_1 { - packed_float3 position; - float _pad1; - packed_float3 diffuse; - float _pad2; - packed_float3 specular; - float intensity; - float constant0; - float linear; - float quadratic; - float radius; - float _pad3; -}; - -struct PointLights { - spvUnsafeArray pointLights; -}; - -struct SpotLight_1 { - packed_float3 position; - float _pad1; - packed_float3 direction; - float cutOff; - float outerCutOff; - float intensity; - float range; - float _pad4; - packed_float3 diffuse; - float _pad5; - packed_float3 specular; - float _pad6; -}; - -struct SpotLights { - spvUnsafeArray spotlights; -}; - -struct AreaLight { - packed_float3 position; - float _pad1; - packed_float3 right; - float _pad2; - packed_float3 up; - float _pad3; - float2 size; - float _pad4; - float _pad5; - packed_float3 diffuse; - float _pad6; - packed_float3 specular; - float angle; - int castsBothSides; - float intensity; - float range; - float _pad9; -}; - -struct AreaLights { - spvUnsafeArray areaLights; -}; - -struct AmbientLight { - float4 color; - float intensity; - float3 _pad0; -}; - -struct ProbeSpace { - float3 origin; - float _pad0; - - float3 spacing; - float _pad1; - - float3 probeCount; - float _pad2; - - float4 debugColor; - - float4 atlasParams; - // x = textureBorderSize - // y = probeResolution (inner) - // z = probesPerRow - // w = totalProbes (put this here on CPU!) -}; - -constant spvUnsafeArray _660 = spvUnsafeArray( - {float2(-0.3260000050067901611328125, -0.4059999883174896240234375), - float2(-0.839999973773956298828125, -0.07400000095367431640625), - float2(-0.69599997997283935546875, 0.4569999873638153076171875), - float2(-0.20299999415874481201171875, 0.62099999189376831054687)", -R"(5), - float2(0.96200001239776611328125, -0.194999992847442626953125), - float2(0.472999989986419677734375, -0.4799999892711639404296875), - float2(0.518999993801116943359375, 0.767000019550323486328125), - float2(0.185000002384185791015625, -0.89300000667572021484375), - float2(0.507000029087066650390625, 0.064000003039836883544921875), - float2(0.89600002765655517578125, 0.412000000476837158203125), - float2(-0.3219999969005584716796875, -0.933000028133392333984375), - float2(-0.791999995708465576171875, -0.597999989986419677734375)}); -constant spvUnsafeArray _861 = spvUnsafeArray( - {float3(0.5381000041961669921875, 0.18559999763965606689453125, - -0.4318999946117401123046875), - float3(0.13789999485015869140625, 0.248600006103515625, - 0.4429999887943267822265625), - float3(0.3370999991893768310546875, 0.567900002002716064453125, - -0.0057000000961124897003173828125), - float3(-0.699899971485137939453125, -0.0450999997556209564208984375, - -0.0019000000320374965667724609375), - float3(0.068899996578693389892578125, -0.159799993038177490234375, - -0.854700028896331787109375), - float3(0.056000001728534698486328125, 0.0068999999202787876129150390625, - -0.184300005435943603515625), - float3(-0.014600000344216823577880859375, 0.14020000398159027099609375, - 0.076200000941753387451171875), - float3(0.00999999977648258209228515625, -0.19239999353885650634765625, - -0.03440000116825103759765625), - float3(-0.35769999027252197265625, -0.53009998798370361328125, - -0.4357999861240386962890625), - float3(-0.3169000148773193359375, 0.10629999637603759765625, - 0.015799999237060546875), - float3(0.010300000198185443878173828125, -0.5868999958038330078125, - 0.0046000001020729541778564453125), - float3(-0.08969999849796295166015625, -0.4939999878406524658203125, - 0.328700006008148193359375), - float3(0.7118999958038330078125, -0.015399999916553497314453125, - -0.091799996793270111083984375), - float3(-0.053300000727176666259765625, 0.0595999993383884429931640625, - -0.541100025177001953125), - float3(0.03519999980926513671875, -0.063100002706050872802734375, - 0.546000003814697265625), - float3(-0.4776000082492828369140625, 0.2847000062465667724609375, - -0.0271000005304813385009765625), - float3(-0.11200000345706939697265625, 0.1234000027179718017578125, - -0.744599997997283935546875), - float3(-0.212999999523162841796875, -0.07819999754428863525390625, - -0.13789999485015869140625), - float3(0.2944000065326690673828125, -0.3111999928951263427734375, - -0.2644999921321868896484375), - float3(-0.4564000070095062255859375, 0.4174999892711639404296875, - -0.184300005435943603515625)}); - -struct main0_out { - float4 FragColor [[color(0)]]; - float4 BrightColor [[color(1)]]; -}; - -struct main0_in { - float2 TexCoord [[user(locn0)]]; -}; - -static inline __attribute__((always_inline)) float2 getTextureDimensions( - thread const int &textureIndex, texture2d texture1, - sampler texture1Smplr, texture2d texture2, sampler texture2Smplr, - texture2d texture3, sampler texture3Smplr, texture2d texture4, - sampler texture4Smplr, texture2d texture5, sampler texture5Smplr) { - if (textureIndex == 0) { - return float2(int2(texture1.get_width(), texture1.get_height())); - } else { - if (textureIndex == 1) { - return float2(int2(texture2.get_width(), texture2.get_height())); - } else { - if (textureIndex == 2) { - return float2( - int2(texture3.get_width(), texture3.get_height())); - } else { - if (textureIndex == 3) { - return float2( - int2(texture4.get_width(), texture4.get_height())); - } else { - if (textureIndex == 4) { - return float2( - int2(texture5.get_width(), texture5.get_height())); - } - } - } - } - } - return float2(0.0); -} - -static inline __attribute__((always_inline)) float4 sampleCubeTextureAt( - thread const int &textureIndex, thread const float3 &direction, - texturecube cubeMap1, sampler cubeMap1Smplr, - texturecube cubeMap2, sampler cubeMap2Smplr, - texturecube cubeMap3, sampler cubeMap3Smplr, - texturecube cubeMap4, sampler cubeMap4Smplr, - texturecube cubeMap5, sampler cubeMap5Smplr) { - if (textureIndex == 0) { - return cubeMap1.sample(cubeMap1Smplr, direction); - } else { - if (textureIndex == 1) { - return cubeMap2.sample(cubeMap2Smplr, direction); - } else { - if (textureIndex == 2) { - return cubeMap3.sample(cubeMap3Smplr, direction); - } else { - if (textureIndex == 3) { - return cubeMap4.sample(cubeMap4Smplr, direction); - } else { - if (textureIndex == 4) { - return cubeMap5.sample(cubeMap5Smplr, direction); - } - } - } - } - } - return float4(0.0); -} - -static inline __attribute__((always_inline)) float calculatePointShadow( - thread const ShadowParameters &shadowParam, thread const float3 &fragPos, - texture2d texture1, sampler texture1Smplr, texture2d texture2, - sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, - texture2d texture4, sampler texture4Smplr, texture2d texture5, - sampler texture5Smplr, texturecube cubeMap1, sampler cubeMap1Smplr, - texturecube cubeMap2, sampler cubeMap2Smplr, - texturecube cubeMap3, sampler cubeMap3Smplr, - texturecube cubeMap4, sampler cubeMap4Smplr, - texturecube cubeMap5, sampler cubeMap5Smplr) { - int param = shadowParam.textureIndex; - float2 dims = getTextureDimensions( - param, texture1, texture1Smplr, texture2, texture2Smplr, texture3, - texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr); - bool _739 = dims.x == 0.0; - bool _746; - if (!_739) { - _746 = dims.y == 0.0; - } else { - _746 = _739; - } - if (_746) { - return 0.0; - } - float3 fragToLight = fragPos - shadowParam.lightPos; - float currentDepth = length(fragToLight); - if (currentDepth >= shadowParam.farPlane) { - return 0.0; - } - float bias0 = 0.0500000007450580596923828125; - float shadow = 0.0; - float diskRadius = (1.0 + (currentDepth / shadowParam.farPlane)) * - 0.0500000007450580596923828125; - for (int i = 0; i < 10; i++) { - float3 sampleDir = - fast::normalize(fragToLight + (_861[i] * diskRadius)); - int param_1 = shadowParam.textureIndex; - float3 param_2 = sampleDir; - float closestDepth = - sampleCubeTextureAt(param_1, param_2, cubeMap1, cubeMap1Smplr, - cubeMap2, cubeMap2Smplr, cubeMap3, - cubeMap3Smplr, cubeMap4, cubeMap4Smplr, - cubeMap5, cubeMap5Smplr) - .x * - shadowParam.farPlane; - if ((currentDepth - bias0) > closestDepth) { - shadow += 1.0; - } - } - shadow /= 10.0; - return shadow; -} - -static inline __attribute__((always_inline)) float4 sampleTextureAt( - thread const int &textureIndex, thread const float2 &uv, - texture2d texture1, sampler texture1Smplr, texture2d texture2, - sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, - texture2d texture4, sampler texture4Smplr, texture2d texture5, - sampler texture5Smplr) { - if (textureIndex == 0) { - return texture1.sample(texture1Smplr, uv); - } else { - if (textureIndex == 1) { - return texture2.sample(texture2Smplr, uv); - } else {)", -R"( - if (textureIndex == 2) { - return texture3.sample(texture3Smplr, uv); - } else { - if (textureIndex == 3) { - return texture4.sample(texture4Smplr, uv); - } else { - if (textureIndex == 4) { - return texture5.sample(texture5Smplr, uv); - } - } - } - } - } - return float4(0.0); -} - -static inline __attribute__((always_inline)) float calculateShadow( - thread const ShadowParameters &shadowParam, thread const float3 &fragPos, - thread const float3 &normal, texture2d texture1, - sampler texture1Smplr, texture2d texture2, sampler texture2Smplr, - texture2d texture3, sampler texture3Smplr, texture2d texture4, - sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, - constant UBO &_526) { - int param = shadowParam.textureIndex; - float2 dims = getTextureDimensions( - param, texture1, texture1Smplr, texture2, texture2Smplr, texture3, - texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr); - bool _411 = dims.x == 0.0; - bool _419; - if (!_411) { - _419 = dims.y == 0.0; - } else { - _419 = _411; - } - if (_419) { - return 0.0; - } - float4 fragPosLightSpace = - (shadowParam.lightProjection * shadowParam.lightView) * - float4(fragPos, 1.0); - if (fragPosLightSpace.w == 0.0) { - return 0.0; - } - float3 clipCoords = fragPosLightSpace.xyz / float3(fragPosLightSpace.w); - float2 projCoordsXY = (clipCoords.xy * 0.5) + float2(0.5); - float3 projCoords = float3(projCoordsXY, clipCoords.z); - bool _456 = projCoords.x < 0.0; - bool _463; - if (!_456) { - _463 = projCoords.x > 1.0; - } else { - _463 = _456; - } - bool _470; - if (!_463) { - _470 = projCoords.y < 0.0; - } else { - _470 = _463; - } - bool _477; - if (!_470) { - _477 = projCoords.y > 1.0; - } else { - _477 = _470; - } - bool _485; - if (!_477) { - _485 = projCoords.z < 0.0; - } else { - _485 = _477; - } - bool _493; - if (!_485) { - _493 = projCoords.z > 1.0; - } else { - _493 = _485; - } - if (_493) { - return 0.0; - } - float currentDepth = projCoords.z; - bool isAreaShadow = shadowParam.lightType == 2; - float3 lightDirWorld = fast::normalize( - -(spvInverse4x4(shadowParam.lightView) * float4(0.0, 0.0, -1.0, 0.0)) - .xyz); - float biasValue = shadowParam.bias0; - if (isAreaShadow) { - biasValue = fast::max(biasValue, 0.0012000000569969416); - } - float ndotl = fast::max(dot(normal, lightDirWorld), 0.0); - float minBias = - fast::max(isAreaShadow ? 0.0002500000118743628 - : 4.9999998736893758177757263183594e-05, - biasValue * (isAreaShadow ? 0.8500000238418579 : 0.25)); - float bias0 = fast::max(biasValue * (1.0 - ndotl), minBias); - if (isAreaShadow) { - bias0 += 0.0002500000118743628; - } - float shadow = 0.0; - float2 texelSize = float2(1.0) / dims; - float _distance = length(float3(_526.cameraPosition) - fragPos); - float2 shadowMapSize = dims; - float avgDim = 0.5 * (shadowMapSize.x + shadowMapSize.y); - float resFactor = fast::clamp(1024.0 / fast::max(avgDim, 1.0), 0.75, 1.25); - float distFactor = fast::clamp(_distance / 800.0, 0.0, 1.0); - float texelRadius = - mix(isAreaShadow ? 1.7999999523162842 : 1.0, - isAreaShadow ? 4.199999809265137 : 3.0, distFactor) * - resFactor; - float2 filterRadius = texelSize * texelRadius; - int kernelSamples = isAreaShadow ? 6 : 8; - int sampleCount = 0; - for (int i = 0; i < kernelSamples; i++) { - float2 offset = _660[i] * filterRadius; - float2 uv = projCoords.xy + offset; - bool _676 = uv.x < 0.0; - bool _683; - if (!_676) { - _683 = uv.x > 1.0; - } else { - _683 = _676; - } - bool _690; - if (!_683) { - _690 = uv.y < 0.0; - } else { - _690 = _683; - } - bool _697; - if (!_690) { - _697 = uv.y > 1.0; - } else { - _697 = _690; - } - if (_697) { - continue; - } - int param_1 = shadowParam.textureIndex; - float2 param_2 = uv; - float pcfDepth = - sampleTextureAt(param_1, param_2, texture1, texture1Smplr, texture2, - texture2Smplr, texture3, texture3Smplr, texture4, - texture4Smplr, texture5, texture5Smplr) - .x; - shadow += float((currentDepth - bias0) > pcfDepth); - sampleCount++; - } - if (sampleCount > 0) { - shadow /= float(sampleCount); - } - if (isAreaShadow) { - shadow = smoothstep(0.18000000715255737, 0.9200000166893005, shadow); - } - return shadow; -} - -static inline __attribute__((always_inline)) float -distributionGGX(thread const float3 &N, thread const float3 &H, - thread const float &roughness) { - float a = roughness * roughness; - float a2 = a * a; - float NdotH = fast::max(dot(N, H), 0.0); - float NdotH2 = NdotH * NdotH; - float num = a2; - float denom = (NdotH2 * (a2 - 1.0)) + 1.0; - denom = (3.1415927410125732421875 * denom) * denom; - return num / fast::max(denom, 9.9999997473787516355514526367188e-05); -} - -static inline __attribute__((always_inline)) float -geometrySchlickGGX(thread const float &NdotV, thread const float &roughness) { - float r = roughness + 1.0; - float k = (r * r) / 8.0; - float num = NdotV; - float denom = (NdotV * (1.0 - k)) + k; - return num / fast::max(denom, 9.9999997473787516355514526367188e-05); -} - -static inline __attribute__((always_inline)) float -geometrySmith(thread const float3 &N, thread const float3 &V, - thread const float3 &L, thread const float &roughness) { - float NdotV = fast::max(dot(N, V), 0.0); - float NdotL = fast::max(dot(N, L), 0.0); - float param = NdotV; - float param_1 = roughness; - float ggx2 = geometrySchlickGGX(param, param_1); - float param_2 = NdotL; - float param_3 = roughness; - float ggx1 = geometrySchlickGGX(param_2, param_3); - return ggx1 * ggx2; -} - -static inline __attribute__((always_inline)) float3 -fresnelSchlick(thread const float &cosTheta, thread const float3 &F0) { - return F0 + ((float3(1.0) - F0) * powr(1.0 - cosTheta, 5.0)); -} - -static inline __attribute__((always_inline)) float3 -evaluateBRDF(thread const float3 &L, thread const float3 &radiance, - thread const float3 &N, thread const float3 &V, - thread const float3 &F0, thread const float3 &albedo, - thread const float &metallic, thread const float &roughness) { - float3 H = fast::normalize(V + L); - float3 param = N; - float3 param_1 = H; - float param_2 = roughness; - float NDF = distributionGGX(param, param_1, param_2); - float3 param_3 = N; - float3 param_4 = V; - float3 param_5 = L; - float param_6 = roughness; - float G = geometrySmith(param_3, param_4, param_5, param_6); - float param_7 = fast::max(dot(H, V), 0.0); - float3 param_8 = F0; - float3 F = fresnelSchlick(param_7, param_8); - float3 kS = F; - float3 kD = (float3(1.0) - kS) * (1.0 - metallic); - float NdotV = fast::max(dot(N, V), 0.0); - float NdotL = fast::max(dot(N, L), 0.0); - float3 numerator = F * (NDF * G); - float denominator = - fast::max((4.0 * NdotV) * NdotL, 9.9999997473787516355514526367188e-05); - float3 specular = numerator / float3(denominator); - return ((((kD * albedo) / float3(3.1415927410125732421875)) + specular) * - radiance) * - NdotL; -} - -static inline __attribute__((always_inline)) float3 calcDirectionalLight( - thread const DirectionalLight &light, thread const float3 &N, - thread const float3 &V, thread const float3 &F0, - thread const float3 &albedo, thread const float &metallic, - thread const float &roughness) { - float3 L = fast::normalize(-light.direction); - float3 radian)", -R"(ce = light.diffuse * fast::max(light.intensity, 0.0); - float3 param = L; - float3 param_1 = radiance; - float3 param_2 = N; - float3 param_3 = V; - float3 param_4 = F0; - float3 param_5 = albedo; - float param_6 = metallic; - float param_7 = roughness; - return evaluateBRDF(param, param_1, param_2, param_3, param_4, param_5, - param_6, param_7); -} - -static inline __attribute__((always_inline)) float3 -calcPointLight(thread const PointLight &light, thread const float3 &fragPos, - thread const float3 &N, thread const float3 &V, - thread const float3 &F0, thread const float3 &albedo, - thread const float &metallic, thread const float &roughness) { - float3 L = light.position - fragPos; - float _distance = length(L); - float3 _1019; - if (_distance > 0.0) { - _1019 = L / float3(_distance); - } else { - _1019 = float3(0.0, 0.0, 1.0); - } - float3 direction = _1019; - float attenuation = - 1.0 / fast::max((light.constant0 + (light.linear * _distance)) + - ((light.quadratic * _distance) * _distance), - 9.9999997473787516355514526367188e-05); - float fade = 1.0 - smoothstep(light.radius * 0.89999997615814208984375, - light.radius, _distance); - float3 radiance = - ((light.diffuse * fast::max(light.intensity, 0.0)) * attenuation) * - fade; - float3 param = direction; - float3 param_1 = radiance; - float3 param_2 = N; - float3 param_3 = V; - float3 param_4 = F0; - float3 param_5 = albedo; - float param_6 = metallic; - float param_7 = roughness; - return evaluateBRDF(param, param_1, param_2, param_3, param_4, param_5, - param_6, param_7); -} - -static inline __attribute__((always_inline)) float3 -calcSpotLight(thread const SpotLight &light, thread const float3 &fragPos, - thread const float3 &N, thread const float3 &V, - thread const float3 &F0, thread const float3 &albedo, - thread const float &metallic, thread const float &roughness) { - float3 L = light.position - fragPos; - float _distance = length(L); - float3 direction = fast::normalize(L); - float3 spotDirection = fast::normalize(light.direction); - float theta = dot(direction, -spotDirection); - float epsilon = fast::max(light.cutOff - light.outerCutOff, - 9.9999997473787516355514526367188e-05); - float intensity = - fast::clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0); - float range = fast::max(light.range, 0.001000000047497451305389404296875); - float attenuation = 1.0 / ((1.0 + (_distance / range)) + - ((_distance * _distance) / (range * range))); - float fade = - 1.0 - smoothstep(range * 0.89999997615814208984375, range, _distance); - float3 radiance = - (((light.diffuse * fast::max(light.intensity, 0.0)) * attenuation) * - intensity) * - fade; - float3 param = direction; - float3 param_1 = radiance; - float3 param_2 = N; - float3 param_3 = V; - float3 param_4 = F0; - float3 param_5 = albedo; - float param_6 = metallic; - float param_7 = roughness; - return evaluateBRDF(param, param_1, param_2, param_3, param_4, param_5, - param_6, param_7); -} - -static inline __attribute__((always_inline)) float3 -getRimLight(thread const float3 &fragPos, thread float3 &N, thread float3 &V, - thread const float3 &F0, thread const float3 &albedo, - thread const float &metallic, thread const float &roughness, - constant UBO &_526, constant Environment &environment) { - N = fast::normalize(N); - V = fast::normalize(V); - float rim = powr(1.0 - fast::max(dot(N, V), 0.0), 3.0); - rim *= mix(1.2000000476837158203125, 0.300000011920928955078125, roughness); - float3 rimColor = - mix(float3(1.0), albedo, float3(metallic)) * environment.rimLightColor; - rimColor = mix(rimColor, F0, float3(0.5)); - float rimIntensity = environment.rimLightIntensity; - float3 rimLight = (rimColor * rim) * rimIntensity; - float dist = length(float3(_526.cameraPosition) - fragPos); - rimLight /= float3(1.0 + (dist * 0.100000001490116119384765625)); - return rimLight; -} - -static inline __attribute__((always_inline)) float3 -sampleEnvironmentRadiance(thread const float3 &direction, - texturecube skybox, sampler skyboxSmplr) { - return skybox.sample(skyboxSmplr, direction).xyz; -} - -static inline __attribute__((always_inline)) float3 -acesToneMapping(thread float3 &color) { - float a = 2.5099999904632568359375; - float b = 0.02999999932944774627685546875; - float c = 2.4300000667572021484375; - float d = 0.589999973773956298828125; - float e = 0.14000000059604644775390625; - color = (color * ((color * a) + float3(b))) / - ((color * ((color * c) + float3(d))) + float3(e)); - color = powr(fast::clamp(color, float3(0.0), float3(1.0)), - float3(0.4545454680919647216796875)); - return color; -} - -static inline float2 octEncode(float3 n) { - n /= (fabs(n.x) + fabs(n.y) + fabs(n.z) + 1e-6f); - float2 e = n.xy; - - if (n.z < 0.0f) { - float2 signNotZero = - float2(e.x >= 0.0f ? 1.0f : -1.0f, e.y >= 0.0f ? 1.0f : -1.0f); - e = (1.0f - fabs(e.yx)) * signNotZero; - } - return e; -} - -static inline float3 safeNormalizeDDGI(float3 v, float3 fallback) { - float len2 = dot(v, v); - if (len2 > 1e-10f) { - return v * rsqrt(len2); - } - return fallback; -} - -static inline uint probeIndexFromCoord(uint3 c, uint3 counts) { - return c.x + counts.x * (c.y + counts.y * c.z); -} - -static inline float2 ddgiAtlasUV(uint probeIndex, float3 dirWS, - constant ProbeSpace &ps, uint atlasW, - uint atlasH) { - if (atlasW == 0u || atlasH == 0u) { - return float2(0.5f); - } - - uint border = (uint)ps.atlasParams.x; - uint innerRes = (uint)ps.atlasParams.y; - uint probesPerRow = (uint)ps.atlasParams.z; - if (innerRes == 0u || probesPerRow == 0u) { - return float2(0.5f); - } - - uint tileRes = innerRes + 2u * border; - - uint tileX = probeIndex % probesPerRow; - uint tileY = probeIndex / probesPerRow; - - float dirLen = length(dirWS); - float3 safeDir = - (dirLen > 1e-6f) ? (dirWS / float3(dirLen)) : float3(0.0f, 1.0f, 0.0f); - float2 e = octEncode(safeDir); - float2 innerUV = e * 0.5f + 0.5f; - - float2 innerPx = float2((float)(tileX * tileRes + border), - (float)(tileY * tileRes + border)) + - innerUV * float(innerRes - 1u); - - return (innerPx + 0.5f) / float2((float)atlasW, (float)atlasH); -} - -static inline float4 sampleDDGITextureBilinear(texture2d tex, - float2 uv) { - uint w = tex.get_width(); - uint h = tex.get_height(); - if (w == 0u || h == 0u) { - return float4(0.0f); - } - - float2 pixel = uv * float2((float)w, (float)h) - 0.5f; - int2 p0 = int2(floor(pixel)); - int2 p1 = p0 + int2(1, 0); - int2 p2 = p0 + int2(0, 1); - int2 p3 = p0 + int2(1, 1); - - int maxX = int(w) - 1; - int maxY = int(h) - 1; - p0 = int2(clamp(p0.x, 0, maxX), clamp(p0.y, 0, maxY)); - p1 = int2(clamp(p1.x, 0, maxX), clamp(p1.y, 0, maxY)); - p2 = int2(clamp(p2.x, 0, maxX), clamp(p2.y, 0, maxY)); - p3 = int2(clamp(p3.x, 0, maxX), clamp(p3.y, 0, maxY)); - - float2 f = fract(pixel); - float4 c00 = tex.read(uint2((uint)p0.x, (uint)p0.y)); - float4 c10 = tex.read(uint2((uint)p1.x, (uint)p1.y)); - float4 c01 = tex.read(uint2((uint)p2.x, (uint)p2.y)); - float4 c11 = tex.read(uint2((uint)p3.x, (uint)p3.y)); - float4 cx0 = mix(c00, c10, f.x); - float4 cx1 = mix(c01, c11, f.x); - return mix(cx0, cx1, f.y); -} - -static inline float4 -sampleProbeDirectionalRadiance(texture2d ddgiTexture, - constant ProbeSpace &ps, uint probeIndex, - uint atlasW, uint atlasH, float3 dirWS) { - float2 uv = ddgiAtlasUV(pro)", -R"(beIndex, dirWS, ps, atlasW, atlasH); - return sampleDDGITextureBilinear(ddgiTexture, uv); -} - -static inline float3 sampleDDGIIrradiance(texture2d ddgiTexture, - texture2d ddgiDistance, - constant ProbeSpace &ps, float3 posWS, - float3 normalWS) { - uint3 counts = uint3((uint)ps.probeCount.x, (uint)ps.probeCount.y, - (uint)ps.probeCount.z); - - if (counts.x == 0u || counts.y == 0u || counts.z == 0u) - return float3(0.0); - - uint atlasW = ddgiTexture.get_width(); - uint atlasH = ddgiTexture.get_height(); - if (atlasW == 0u || atlasH == 0u) { - return float3(0.0); - } - - float normalLen = length(normalWS); - float3 safeNormal = (normalLen > 1e-6f) ? (normalWS / float3(normalLen)) - : float3(0.0f, 1.0f, 0.0f); - - float3 safeSpacing = max(ps.spacing, float3(1e-4f)); - float spacingScale = - max(max(safeSpacing.x, max(safeSpacing.y, safeSpacing.z)), 1e-4f); - float3 grid = (posWS - ps.origin) / safeSpacing; - - if (counts.x < 2u || counts.y < 2u || counts.z < 2u) { - float3 maxCoord = max(float3(0.0f), float3((float)counts.x - 1.0f, - (float)counts.y - 1.0f, - (float)counts.z - 1.0f)); - float3 clampedGrid = clamp(grid, float3(0.0f), maxCoord); - uint3 nearest = uint3( - (uint)clamp(int(floor(clampedGrid.x + 0.5f)), 0, int(counts.x) - 1), - (uint)clamp(int(floor(clampedGrid.y + 0.5f)), 0, int(counts.y) - 1), - (uint)clamp(int(floor(clampedGrid.z + 0.5f)), 0, - int(counts.z) - 1)); - uint pIndex = probeIndexFromCoord(nearest, counts); - float4 nearestSample = sampleProbeDirectionalRadiance( - ddgiTexture, ps, pIndex, atlasW, atlasH, safeNormal); - float3 nearestProbePos = ps.origin + float3(nearest) * safeSpacing; - float3 nearestDirection = safeNormalizeDDGI( - posWS - nearestProbePos, safeNormal); - float4 nearestMoments = sampleProbeDirectionalRadiance( - ddgiDistance, ps, pIndex, atlasW, atlasH, nearestDirection); - float nearestDistance = length(posWS - nearestProbePos); - float nearestVariance = max(nearestMoments.y - nearestMoments.x * - nearestMoments.x, - 0.0001f); - float nearestDelta = max(nearestDistance - nearestMoments.x, 0.0f); - float nearestVisibility = nearestDelta <= 0.0f - ? 1.0f - : nearestVariance / - (nearestVariance + nearestDelta * - nearestDelta); - float nearestValidity = isfinite(nearestSample.w) - ? clamp(nearestSample.w, 0.0f, 1.0f) - : 0.0f; - float3 nearestIrr = - all(isfinite(nearestSample.xyz)) ? nearestSample.xyz : float3(0.0f); - nearestIrr *= nearestValidity * nearestVisibility; - return max(nearestIrr, float3(0.0f)); - } - - float3 maxGrid = - float3((float)counts.x - 1.0001f, (float)counts.y - 1.0001f, - (float)counts.z - 1.0001f); - float3 clampedGrid = clamp(grid, float3(0.0f), maxGrid); - - float3 baseF = floor(clampedGrid); - float3 frac = clampedGrid - baseF; - int3 baseI = int3(baseF); - int3 maxBase = - int3(int(counts.x) - 2, int(counts.y) - 2, int(counts.z) - 2); - baseI = clamp(baseI, int3(0), maxBase); - - float3 result = float3(0.0f); - float weightSum = 0.0f; - float3 resultNoBackface = float3(0.0f); - float weightSumNoBackface = 0.0f; - - for (uint dz = 0; dz <= 1u; dz++) { - for (uint dy = 0; dy <= 1u; dy++) { - for (uint dx = 0; dx <= 1u; dx++) { - - uint3 pc = uint3(uint(baseI.x) + dx, uint(baseI.y) + dy, - uint(baseI.z) + dz); - uint pIndex = probeIndexFromCoord(pc, counts); - - float trilinearW = ((dx == 0u) ? (1.0f - frac.x) : frac.x) * - ((dy == 0u) ? (1.0f - frac.y) : frac.y) * - ((dz == 0u) ? (1.0f - frac.z) : frac.z); - - float3 probePos = ps.origin + float3(pc) * safeSpacing; - float3 surfaceToProbe = probePos - posWS; - float sDist = length(surfaceToProbe); - float3 dirToProbe = (sDist > 1e-4f) ? surfaceToProbe / sDist - : float3(0.0f, 1.0f, 0.0f); - float frontW = max(dot(safeNormal, dirToProbe), 0.0f); - float backfaceW = - mix(0.180000007152557373046875, 1.0f, frontW * frontW); - float distNorm = sDist / spacingScale; - float distNorm2 = distNorm * distNorm; - float distanceW = - 1.0f / (1.0f + distNorm2 * 0.85000002384185791015625); - - float w = trilinearW * backfaceW * distanceW; - - float4 irrSample = sampleProbeDirectionalRadiance( - ddgiTexture, ps, pIndex, atlasW, atlasH, safeNormal); - float3 probeToSurface = -surfaceToProbe; - float4 distanceSample = sampleProbeDirectionalRadiance( - ddgiDistance, ps, pIndex, atlasW, atlasH, - safeNormalizeDDGI(probeToSurface, safeNormal)); - float variance = max(distanceSample.y - - distanceSample.x * distanceSample.x, - 0.0001f); - float delta = max(sDist - distanceSample.x, 0.0f); - float visibility = delta <= 0.0f - ? 1.0f - : variance / (variance + delta * delta); - visibility = visibility * visibility * visibility; - float probeValidity = isfinite(irrSample.w) - ? clamp(irrSample.w, 0.0f, 1.0f) - : 0.0f; - float validityW = probeValidity; - float3 irr = irrSample.xyz; - if (!all(isfinite(irr))) { - irr = float3(0.0f); - validityW = 0.0f; - } - irr = max(irr, float3(0.0f)); - float weightedW = w * validityW * max(visibility, 0.001f); - result += irr * weightedW; - weightSum += weightedW; - float noBackfaceW = trilinearW * distanceW * validityW * - max(visibility, 0.001f); - resultNoBackface += irr * noBackfaceW; - weightSumNoBackface += noBackfaceW; - } - } - } - - if (weightSum > 1e-5f) { - return result / weightSum; - } - if (weightSumNoBackface > 1e-5f) { - return resultNoBackface / weightSumNoBackface; - } - - uint3 nearest = uint3( - (uint)clamp(int(floor(clampedGrid.x + 0.5f)), 0, int(counts.x) - 1), - (uint)clamp(int(floor(clampedGrid.y + 0.5f)), 0, int(counts.y) - 1), - (uint)clamp(int(floor(clampedGrid.z + 0.5f)), 0, int(counts.z) - 1)); - uint nearestIndex = probeIndexFromCoord(nearest, counts); - float4 fallbackSample = sampleProbeDirectionalRadiance( - ddgiTexture, ps, nearestIndex, atlasW, atlasH, safeNormal); - float fallbackValidity = - isfinite(fallbackSample.w) ? clamp(fallbackSample.w, 0.0f, 1.0f) : 0.0f; - float3 fallback = - all(isfinite(fallbackSample.xyz)) ? fallbackSample.xyz : float3(0.0f); - fallback *= fallbackValidity; - if (!all(isfinite(fallback))) { - fallback = float3(0.0f); - } - return max(fallback, float3(0.0f)); -} - -fragment main0_out main0( - main0_in in [[stage_in]], constant UBO &_526 [[buffer(0)]], - constant Environment &envi)", -R"(ronment [[buffer(1)]], - constant PushConstants &_1355 [[buffer(2)]], - device ShadowParams &_1372 [[buffer(3)]], - device DirectionalLights &_1422 [[buffer(4)]], - device PointLights &_1465 [[buffer(5)]], - device SpotLights &_1510 [[buffer(6)]], - device AreaLights &_1552 [[buffer(7)]], - constant AmbientLight &ambientLight [[buffer(8)]], - constant ProbeSpace &ps [[buffer(9)]], - texture2d texture1 [[texture(0)]], - texture2d texture2 [[texture(1)]], - texture2d texture3 [[texture(2)]], - texture2d texture4 [[texture(3)]], - texture2d texture5 [[texture(4)]], - texturecube cubeMap1 [[texture(5)]], - texturecube cubeMap2 [[texture(6)]], - texturecube cubeMap3 [[texture(7)]], - texturecube cubeMap4 [[texture(8)]], - texturecube cubeMap5 [[texture(9)]], - texturecube skybox [[texture(10)]], - texture2d gPosition [[texture(11)]], - texture2d gNormal [[texture(12)]], - texture2d gAlbedoSpec [[texture(13)]], - texture2d gMaterial [[texture(14)]], - texture2d ssao [[texture(15)]], - texture2d irradianceMap [[texture(16)]], - texture2d ddgiDistanceMap [[texture(17)]], - sampler texture1Smplr [[sampler(0)]], sampler texture2Smplr [[sampler(1)]], - sampler texture3Smplr [[sampler(2)]], sampler texture4Smplr [[sampler(3)]], - sampler texture5Smplr [[sampler(4)]], sampler cubeMap1Smplr [[sampler(5)]], - sampler cubeMap2Smplr [[sampler(6)]], sampler cubeMap3Smplr [[sampler(7)]], - sampler cubeMap4Smplr [[sampler(8)]], sampler cubeMap5Smplr [[sampler(9)]], - sampler skyboxSmplr [[sampler(10)]], sampler gPositionSmplr [[sampler(11)]], - sampler gNormalSmplr [[sampler(12)]], - sampler gAlbedoSpecSmplr [[sampler(13)]], - sampler gMaterialSmplr [[sampler(14)]], sampler ssaoSmplr [[sampler(15)]]) { - main0_out out{}; - float4 gPositionSample = gPosition.sample(gPositionSmplr, in.TexCoord); - float3 FragPos = gPositionSample.xyz; - if (!all(isfinite(FragPos))) { - FragPos = float3(0.0); - } - float depthSample = gPositionSample.w; - float3 sampledNormal = gNormal.sample(gNormalSmplr, in.TexCoord).xyz; - float normalLength = length(sampledNormal); - bool hasNormal = all(isfinite(sampledNormal)) && - normalLength > 9.9999997473787516355514526367188e-06; - bool hasDepth = - isfinite(depthSample) && depthSample < 0.999989986419677734375; - bool hasGeometry = hasNormal || hasDepth; - if (!hasGeometry) { - float2 ndc = in.TexCoord * 2.0f - 1.0f; - float3 backgroundDir = fast::normalize(float3(ndc.x, -ndc.y, 1.0f)); - float3 backgroundColor = - sampleEnvironmentRadiance(backgroundDir, skybox, skyboxSmplr); - out.FragColor = float4(acesToneMapping(backgroundColor), 1.0); - out.BrightColor = float4(0.0, 0.0, 0.0, 1.0); - return out; - } - float3 N = float3(0.0, 1.0, 0.0); - if (hasNormal) { - N = sampledNormal / float3(normalLength); - } else { - float3 geomN = cross(dfdx(FragPos), dfdy(FragPos)); - float geomNLen = length(geomN); - if (all(isfinite(geomN)) && - geomNLen > 9.9999997473787516355514526367188e-06) { - N = geomN / float3(geomNLen); - } - } - float3 geomNormal = cross(dfdx(FragPos), dfdy(FragPos)); - float geomNormalLen = length(geomNormal); - bool hasGeomNormal = all(isfinite(geomNormal)) && - geomNormalLen > 9.9999997473787516355514526367188e-06; - float3 shadowNormal = N; - float3 ddgiNormal = N; - if (hasGeomNormal) { - geomNormal /= float3(geomNormalLen); - if (dot(N, geomNormal) < 0.0) { - geomNormal = -geomNormal; - } - shadowNormal = geomNormal; - ddgiNormal = geomNormal; - } - float4 albedoAo = gAlbedoSpec.sample(gAlbedoSpecSmplr, in.TexCoord); - float3 albedo = fast::clamp(albedoAo.xyz, float3(0.0), float3(1.0)); - if (!all(isfinite(albedo))) { - albedo = float3(0.0); - } - float4 matData = gMaterial.sample(gMaterialSmplr, in.TexCoord); - float metallic = fast::clamp(matData.x, 0.0, 1.0); - float roughness = fast::clamp(matData.y, 0.0, 1.0); - float ao = fast::clamp(matData.z, 0.0, 1.0); - - float viewDistance = - fast::max(length(float3(_526.cameraPosition) - FragPos), - 9.9999999747524270787835121154785e-07); - float3 V = (float3(_526.cameraPosition) - FragPos) / float3(viewDistance); - float3 F0 = - mix(float3(0.039999999105930328369140625), albedo, float3(metallic)); - float ssaoFactor = - fast::clamp(ssao.sample(ssaoSmplr, in.TexCoord).x, 0.0, 1.0); - - float ssaoContrast = - fast::clamp(powr(ssaoFactor, 1.10000002384185791015625), 0.0, 1.0); - float occlusion = - fast::clamp(ao * (0.0500000007450580596923828125 + - (0.949999988079071044921875 * ssaoContrast)), - 0.0, 1.0); - float lightingOcclusion = - fast::clamp(0.0500000007450580596923828125 + - (0.949999988079071044921875 * ssaoContrast), - 0.0500000007450580596923828125, 1.0); - float directionalShadow = 0.0; - float spotShadow = 0.0; - float areaShadow = 0.0; - int areaShadowCount = 0; - float pointShadow = 0.0; - int shadowCount = _1355.shadowParamCount; - for (int i = 0; i < shadowCount; i++) { - if (_1372.shadowParams[i].lightType == 3) { - int lightIndex = _1372.shadowParams[i].lightIndex; - if (lightIndex < 0 || lightIndex >= _1355.pointLightCount || - distance(float3(_1465.pointLights[lightIndex].position), - FragPos) >= _1465.pointLights[lightIndex].radius) { - continue; - } - ShadowParameters _1386; - _1386.lightView = _1372.shadowParams[i].lightView; - _1386.lightProjection = _1372.shadowParams[i].lightProjection; - _1386.bias0 = _1372.shadowParams[i].bias0; - _1386.textureIndex = _1372.shadowParams[i].textureIndex; - _1386.farPlane = _1372.shadowParams[i].farPlane; - _1386.lightIndex = _1372.shadowParams[i].lightIndex; - _1386.lightPos = float3(_1372.shadowParams[i].lightPos); - _1386.lightType = _1372.shadowParams[i].lightType; - ShadowParameters param = _1386; - float3 param_1 = FragPos; - pointShadow = - fast::max(pointShadow, - calculatePointShadow( - param, param_1, texture1, texture1Smplr, texture2, - texture2Smplr, texture3, texture3Smplr, texture4, - texture4Smplr, texture5, texture5Smplr, cubeMap1, - cubeMap1Smplr, cubeMap2, cubeMap2Smplr, cubeMap3, - cubeMap3Smplr, cubeMap4, cubeMap4Smplr, cubeMap5, - cubeMap5Smplr)); - } else if (_1372.shadowParams[i].lightType == 1) { - int lightIndex = _1372.shadowParams[i].lightIndex; - if (lightIndex < 0 || lightIndex >= _1355.spotlightCount || - distance(float3(_1510.spotlights[lightIndex].position), - FragPos) >= _1510.spotlights[lightIndex].range) { - continue; - } - ShadowParameters _1397; - _1397.lightView = _1372.shadowParams[i].lightView; - _1397.lightProjection = _1372.shadowParams[i].lightProjection; - _1397.bias0 = _1372.shadowParams[i].bias0; - _1397.textureIndex = _1372.shadowParams[i].textureIndex; - _1397.farPlane = _1372.shadowParams[i].farPlane; - _1397.lightIndex = _1372.shadowParams[i].lightIndex; - _1397.lightPos = float3(_1372.shadowParams[i].lightPos); - _1397.lightType = _1372.shadowParams[i].lightType; - ShadowParameters param_2 = _1397; - float3 param_3 = FragPos; - float3 param_4 = shadowNormal; - spotShadow = fast::max( - spotShadow, - calculateS)", -R"(hadow(param_2, param_3, param_4, texture1, - texture1Smplr, texture2, texture2Smplr, - texture3, texture3Smplr, texture4, - texture4Smplr, texture5, texture5Smplr, _526)); - } else if (_1372.shadowParams[i].lightType == 2) { - int lightIndex = _1372.shadowParams[i].lightIndex; - if (lightIndex < 0 || lightIndex >= _1355.areaLightCount || - distance(float3(_1552.areaLights[lightIndex].position), - FragPos) >= _1552.areaLights[lightIndex].range) { - continue; - } - ShadowParameters _1397; - _1397.lightView = _1372.shadowParams[i].lightView; - _1397.lightProjection = _1372.shadowParams[i].lightProjection; - _1397.bias0 = _1372.shadowParams[i].bias0; - _1397.textureIndex = _1372.shadowParams[i].textureIndex; - _1397.farPlane = _1372.shadowParams[i].farPlane; - _1397.lightIndex = _1372.shadowParams[i].lightIndex; - _1397.lightPos = float3(_1372.shadowParams[i].lightPos); - _1397.lightType = _1372.shadowParams[i].lightType; - ShadowParameters param_2 = _1397; - float3 param_3 = FragPos; - float3 param_4 = shadowNormal; - areaShadow += calculateShadow( - param_2, param_3, param_4, texture1, texture1Smplr, texture2, - texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, - texture5, texture5Smplr, _526); - areaShadowCount++; - } else { - ShadowParameters _1397; - _1397.lightView = _1372.shadowParams[i].lightView; - _1397.lightProjection = _1372.shadowParams[i].lightProjection; - _1397.bias0 = _1372.shadowParams[i].bias0; - _1397.textureIndex = _1372.shadowParams[i].textureIndex; - _1397.farPlane = _1372.shadowParams[i].farPlane; - _1397.lightIndex = _1372.shadowParams[i].lightIndex; - _1397.lightPos = float3(_1372.shadowParams[i].lightPos); - _1397.lightType = _1372.shadowParams[i].lightType; - ShadowParameters param_2 = _1397; - float3 param_3 = FragPos; - float3 param_4 = shadowNormal; - directionalShadow = fast::max( - directionalShadow, - calculateShadow(param_2, param_3, param_4, texture1, - texture1Smplr, texture2, texture2Smplr, - texture3, texture3Smplr, texture4, - texture4Smplr, texture5, texture5Smplr, _526)); - } - } - if (areaShadowCount > 0) { - areaShadow /= float(areaShadowCount); - } - directionalShadow = - fast::clamp(directionalShadow * 0.85000002384185791015625, 0.0, 1.0); - spotShadow = fast::clamp(spotShadow * 0.85000002384185791015625, 0.0, 1.0); - areaShadow = fast::clamp(areaShadow * 0.449999988079071044921875, 0.0, 1.0); - pointShadow = - fast::clamp(pointShadow * 0.85000002384185791015625, 0.0, 1.0); - float3 directionalResult = float3(0.0); - for (int i_1 = 0; i_1 < _1355.directionalLightCount; i_1++) { - DirectionalLight _1428; - _1428.direction = float3(_1422.directionalLights[i_1].direction); - _1428._pad1 = _1422.directionalLights[i_1]._pad1; - _1428.diffuse = float3(_1422.directionalLights[i_1].diffuse); - _1428._pad2 = _1422.directionalLights[i_1]._pad2; - _1428.specular = float3(_1422.directionalLights[i_1].specular); - _1428.intensity = _1422.directionalLights[i_1].intensity; - DirectionalLight param_5 = _1428; - float3 param_6 = N; - float3 param_7 = V; - float3 param_8 = F0; - float3 param_9 = albedo; - float param_10 = metallic; - float param_11 = roughness; - directionalResult += calcDirectionalLight( - param_5, param_6, param_7, param_8, param_9, param_10, param_11); - } - directionalResult *= (1.0 - directionalShadow); - float3 pointResult = float3(0.0); - for (int i_2 = 0; i_2 < _1355.pointLightCount; i_2++) { - PointLight _1471; - _1471.position = float3(_1465.pointLights[i_2].position); - _1471._pad1 = _1465.pointLights[i_2]._pad1; - _1471.diffuse = float3(_1465.pointLights[i_2].diffuse); - _1471._pad2 = _1465.pointLights[i_2]._pad2; - _1471.specular = float3(_1465.pointLights[i_2].specular); - _1471.intensity = _1465.pointLights[i_2].intensity; - _1471.constant0 = _1465.pointLights[i_2].constant0; - _1471.linear = _1465.pointLights[i_2].linear; - _1471.quadratic = _1465.pointLights[i_2].quadratic; - _1471.radius = _1465.pointLights[i_2].radius; - _1471._pad3 = _1465.pointLights[i_2]._pad3; - PointLight param_12 = _1471; - float3 param_13 = FragPos; - float3 param_14 = N; - float3 param_15 = V; - float3 param_16 = F0; - float3 param_17 = albedo; - float param_18 = metallic; - float param_19 = roughness; - pointResult += calcPointLight(param_12, param_13, param_14, param_15, - param_16, param_17, param_18, param_19); - } - pointResult *= (1.0 - pointShadow); - float3 spotResult = float3(0.0); - for (int i_3 = 0; i_3 < _1355.spotlightCount; i_3++) { - SpotLight _1516; - _1516.position = float3(_1510.spotlights[i_3].position); - _1516._pad1 = _1510.spotlights[i_3]._pad1; - _1516.direction = float3(_1510.spotlights[i_3].direction); - _1516.cutOff = _1510.spotlights[i_3].cutOff; - _1516.outerCutOff = _1510.spotlights[i_3].outerCutOff; - _1516.intensity = _1510.spotlights[i_3].intensity; - _1516.range = _1510.spotlights[i_3].range; - _1516._pad4 = _1510.spotlights[i_3]._pad4; - _1516.diffuse = float3(_1510.spotlights[i_3].diffuse); - _1516._pad5 = _1510.spotlights[i_3]._pad5; - _1516.specular = float3(_1510.spotlights[i_3].specular); - _1516._pad6 = _1510.spotlights[i_3]._pad6; - SpotLight param_20 = _1516; - float3 param_21 = FragPos; - float3 param_22 = N; - float3 param_23 = V; - float3 param_24 = F0; - float3 param_25 = albedo; - float param_26 = metallic; - float param_27 = roughness; - spotResult += calcSpotLight(param_20, param_21, param_22, param_23, - param_24, param_25, param_26, param_27); - } - spotResult *= (1.0 - spotShadow); - float3 areaResult = float3(0.0); - float _1639; - for (int i_4 = 0; i_4 < _1355.areaLightCount; i_4++) { - float3 P = float3(_1552.areaLights[i_4].position); - float3 R = fast::normalize(float3(_1552.areaLights[i_4].right)); - float3 U = fast::normalize(float3(_1552.areaLights[i_4].up)); - float2 halfSize = _1552.areaLights[i_4].size * 0.5; - float3 toPoint = FragPos - P; - float s = fast::clamp(dot(toPoint, R), -halfSize.x, halfSize.x); - float t = fast::clamp(dot(toPoint, U), -halfSize.y, halfSize.y); - float3 Q = (P + (R * s)) + (U * t); - float3 Lvec = Q - FragPos; - float dist = length(Lvec); - if (dist > 9.9999997473787516355514526367188e-05) { - float3 L = Lvec / float3(dist); - float3 Nl = fast::normalize(cross(R, U)); - float ndotl = dot(Nl, -L); - if (_1552.areaLights[i_4].castsBothSides != 0) { - _1639 = abs(ndotl); - } else { - _1639 = fast::max(ndotl, 0.0); - } - float facing = _1639; - float cosTheta = cos(radians(_1552.areaLights[i_4].angle)); - if ((facing >= cosTheta) && (facing > 0.0)) { - float range = fast::max(_1552.areaLights[i_4].range, - 0.001000000047497451305389404296875); - float attenuation = 1.0 / ((1.0 + (dist / range)) + - ((dist * dist) / (range * range))); - float fade = 1.0 - smoothstep(range * 0.89999997615814208984375, - )", -R"( range, dist); - float3 radiance = - (((float3(_1552.areaLights[i_4].diffuse) * - fast::max(_1552.areaLights[i_4].intensity, 0.0)) * - attenuation) * - facing) * - fade; - float3 param_28 = L; - float3 param_29 = radiance; - float3 param_30 = N; - float3 param_31 = V; - float3 param_32 = F0; - float3 param_33 = albedo; - float param_34 = metallic; - float param_35 = roughness; - areaResult += - evaluateBRDF(param_28, param_29, param_30, param_31, - param_32, param_33, param_34, param_35); - } - } - } - areaResult *= (1.0 - areaShadow); - float3 param_36 = FragPos; - float3 param_37 = N; - float3 param_38 = V; - float3 param_39 = F0; - float3 param_40 = albedo; - float param_41 = metallic; - float param_42 = roughness; - float3 _1714 = getRimLight(param_36, param_37, param_38, param_39, param_40, - param_41, param_42, _526, environment); - float3 rimResult = _1714; - float3 lighting = - ((((directionalResult + pointResult) + spotResult) + areaResult) + - rimResult) * - lightingOcclusion; - float3 ambientBase = - ((ambientLight.color.xyz * ambientLight.intensity) * albedo) * - occlusion; - bool ddgiEnabled = ps.atlasParams.w > 0.0f; - float3 ambient = ddgiEnabled ? ambientBase * 0.05f : ambientBase; - - float ddgiSampleBias = - max(max(ps.spacing.x, max(ps.spacing.y, ps.spacing.z)) * 0.05f, 0.002f); - float3 ddgiSamplePos = FragPos + ddgiNormal * ddgiSampleBias; - float3 ddgiIrradiance = - sampleDDGIIrradiance(irradianceMap, ddgiDistanceMap, ps, ddgiSamplePos, - ddgiNormal); - if (!all(isfinite(ddgiIrradiance))) { - ddgiIrradiance = float3(0.0f); - } - ddgiIrradiance = max(ddgiIrradiance, float3(0.0f)); - - float ddgiDebugMode = ps.debugColor.w; - float3 ddgiGain = max(ps.debugColor.xyz, float3(0.0f)); - if (ddgiGain.x < 1e-4f && ddgiGain.y < 1e-4f && ddgiGain.z < 1e-4f) { - ddgiGain = float3(1.0f); - } - - const float INV_PI = 0.31830988618379067153776752674503; - float3 ddgiDiffuse = ddgiIrradiance * albedo * INV_PI * - (1.0f - metallic) * occlusion * ddgiGain; - ambient += ddgiDiffuse; - - float3 ddgiSpecular = float3(0.0f); - - float3 iblContribution = float3(0.0); - if (_526.useIBL != 0u) { - float3 param_43 = N; - float3 irradiance = - sampleEnvironmentRadiance(param_43, skybox, skyboxSmplr); - float3 diffuseIBL = irradiance * albedo; - float3 reflection = reflect(-V, N); - float3 param_44 = reflection; - float3 specularEnv = - sampleEnvironmentRadiance(param_44, skybox, skyboxSmplr); - float param_45 = fast::max(dot(N, V), 0.0); - float3 param_46 = F0; - float3 F = fresnelSchlick(param_45, param_46); - float3 kS = F; - float3 kD = (float3(1.0) - kS) * (1.0 - metallic); - float roughnessAttenuation = mix(1.0, 0.1500000059604644775390625, - fast::clamp(roughness, 0.0, 1.0)); - float3 specularIBL = specularEnv * roughnessAttenuation; - iblContribution = ((kD * diffuseIBL) + (kS * specularIBL)) * occlusion; - } - float3 finalColor = (ambient + lighting + ddgiSpecular) + iblContribution; - - // Debug AO view mode: - // ps.debugColor.w >= 9.5f -> visualize SSAO directly in grayscale. - if (ddgiDebugMode >= 9.5f && ddgiDebugMode < 19.5f) { - finalColor = float3(ssaoFactor); - } else if (ddgiDebugMode >= 39.5f) { - finalColor = - max(ddgiDiffuse * 3.0f + ddgiSpecular * 2.0f, float3(0.0f)); - } else if (ddgiDebugMode >= 29.5f) { - finalColor = ddgiIrradiance * ddgiGain * 4.0f; - } else if (ddgiDebugMode >= 19.5f) { - finalColor = ddgiDiffuse * 3.0f; - } else if (!(_526.useIBL != 0u)) { - float3 I = fast::normalize(FragPos - float3(_526.cameraPosition)); - float3 R_1 = reflect(-I, N); - float param_47 = fast::max(dot(N, -I), 0.0); - float3 param_48 = F0; - float3 F_1 = fresnelSchlick(param_47, param_48); - float3 kS_1 = F_1; - float3 envColor = skybox.sample(skyboxSmplr, R_1).xyz; - float3 reflection_1 = envColor * kS_1; - float3 envMix = F0 * (1.0f - roughness) * 0.20f; - finalColor = mix(finalColor, reflection_1, envMix); - } - out.FragColor = float4(finalColor, 1.0); - float brightness = - dot(out.FragColor.xyz, - float3(0.2125999927520751953125, 0.715200006961822509765625, - 0.072200000286102294921875)); - if (brightness > environment.bloomThreshold) { - out.BrightColor = float4(out.FragColor.xyz, 1.0); - } else { - out.BrightColor = float4(0.0, 0.0, 0.0, 1.0); - } - float3 param_49 = out.FragColor.xyz; - float3 _1897 = acesToneMapping(param_49); - out.FragColor.x = _1897.x; - out.FragColor.y = _1897.y; - out.FragColor.z = _1897.z; - return out; -} -)", -}; -static const AtlasPackedShaderSource LIGHT_FRAG = {LIGHT_FRAG_PARTS, 8}; - -static const char* const LIGHT_VERT_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct main0_out -{ - float2 TexCoord [[user(locn0)]]; - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; - float2 aTexCoord [[attribute(2)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]]) -{ - main0_out out = {}; - out.TexCoord = in.aTexCoord; - out.gl_Position = float4(in.aPos, 1.0); - return out; -} -)", -}; -static const AtlasPackedShaderSource LIGHT_VERT = {LIGHT_VERT_PARTS, 1}; - -static const char* const MAIN_FRAG_PARTS[] = { -R"(#pragma clang diagnostic ignored "-Wmissing-prototypes" -#pragma clang diagnostic ignored "-Wmissing-braces" - -#include -#include - -using namespace metal; - -template -struct spvUnsafeArray -{ - T elements[Num ? Num : 1]; - - thread T& operator [] (size_t pos) thread - { - return elements[pos]; - } - constexpr const thread T& operator [] (size_t pos) const thread - { - return elements[pos]; - } - - device T& operator [] (size_t pos) device - { - return elements[pos]; - } - constexpr const device T& operator [] (size_t pos) const device - { - return elements[pos]; - } - - constexpr const constant T& operator [] (size_t pos) const constant - { - return elements[pos]; - } - - threadgroup T& operator [] (size_t pos) threadgroup - { - return elements[pos]; - } - constexpr const threadgroup T& operator [] (size_t pos) const threadgroup - { - return elements[pos]; - } -}; - -// Implementation of the GLSL radians() function -template -inline T radians(T d) -{ - return d * T(0.01745329251); -} - -static inline __attribute__((always_inline)) -float spvDet2x2(float a1, float a2, float b1, float b2) -{ - return a1 * b2 - b1 * a2; -} - -static inline __attribute__((always_inline)) -float spvDet3x3(float a1, float a2, float a3, float b1, float b2, float b3, float c1, float c2, float c3) -{ - return a1 * spvDet2x2(b2, b3, c2, c3) - b1 * spvDet2x2(a2, a3, c2, c3) + c1 * spvDet2x2(a2, a3, b2, b3); -} - -static inline __attribute__((always_inline)) -float4x4 spvInverse4x4(float4x4 m) -{ - float4x4 adj; - adj[0][0] = spvDet3x3(m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], m[2][3], m[3][1], m[3][2], m[3][3]); - adj[0][1] = -spvDet3x3(m[0][1], m[0][2], m[0][3], m[2][1], m[2][2], m[2][3], m[3][1], m[3][2], m[3][3]); - adj[0][2] = spvDet3x3(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], m[3][1], m[3][2], m[3][3]); - adj[0][3] = -spvDet3x3(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], m[2][3]); - adj[1][0] = -spvDet3x3(m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][2], m[3][3]); - adj[1][1] = spvDet3x3(m[0][0], m[0][2], m[0][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][2], m[3][3]); - adj[1][2] = -spvDet3x3(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], m[3][0], m[3][2], m[3][3]); - adj[1][3] = spvDet3x3(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], m[2][3]); - adj[2][0] = spvDet3x3(m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], m[2][3], m[3][0], m[3][1], m[3][3]); - adj[2][1] = -spvDet3x3(m[0][0], m[0][1], m[0][3], m[2][0], m[2][1], m[2][3], m[3][0], m[3][1], m[3][3]); - adj[2][2] = spvDet3x3(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], m[3][0], m[3][1], m[3][3]); - adj[2][3] = -spvDet3x3(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], m[2][3]); - adj[3][0] = -spvDet3x3(m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2], m[3][0], m[3][1], m[3][2]); - adj[3][1] = spvDet3x3(m[0][0], m[0][1], m[0][2], m[2][0], m[2][1], m[2][2], m[3][0], m[3][1], m[3][2]); - adj[3][2] = -spvDet3x3(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[3][0], m[3][1], m[3][2]); - adj[3][3] = spvDet3x3(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2]); - float det = (adj[0][0] * m[0][0]) + (adj[0][1] * m[1][0]) + (adj[0][2] * m[2][0]) + (adj[0][3] * m[3][0]); - return (det != 0.0f) ? (adj * (1.0f / det)) : m; -} - -struct ShadowParameters -{ - float4x4 lightView; - float4x4 lightProjection; - float bias0; - int textureIndex; - float farPlane; - float _pad1; - float3 lightPos; - int lightType; -}; - -struct Uniforms -{ - int4 textureTypes[16]; - int textureCount; - float3 cameraPosition; - float normalMapStrength; - uint useNormalMap; - float2 textureScale; - float2 textureOffset; -}; - -struct Environment -{ - float rimLightIntensity; - float3 rimLightColor; -}; - -struct PushConstants -{ - uint useTexture; - uint useColor; - uint useIBL; - int directionalLightCount; - int pointLightCount; - int spotlightCount; - int areaLightCount; - int shadowParamCount; -}; - -struct DirectionalLight -{ - packed_float3 direction; - float _pad1; - packed_float3 diffuse; - float _pad2; - packed_float3 specular; - float intensity; -}; - -struct DirectionalLightsUBO -{ - spvUnsafeArray directionalLights; -}; - -struct PointLight -{ - packed_float3 position; - float _pad1; - packed_float3 diffuse; - float _pad2; - packed_float3 specular; - float intensity; - float constant0; - float linear; - float quadratic; - float radius; - float _pad3; -}; - -struct PointLightsUBO -{ - spvUnsafeArray pointLights; -}; - -struct SpotLight -{ - packed_float3 position; - float _pad1; - packed_float3 direction; - float cutOff; - float outerCutOff; - float intensity; - float range; - float _pad4; - packed_float3 diffuse; - float _pad5; - packed_float3 specular; - float _pad6; -}; - -struct SpotLightsUBO -{ - spvUnsafeArray spotlights; -}; - -struct Material -{ - packed_float3 albedo; - float metallic; - float roughness; - float ao; - float reflectivity; -}; - -struct ShadowParameters_1 -{ - float4x4 lightView; - float4x4 lightProjection; - float bias0; - int textureIndex; - float farPlane; - float _pad1; - packed_float3 lightPos; - int lightType; -}; - -struct ShadowParametersUBO -{ - spvUnsafeArray shadowParams; -}; - -struct AreaLight -{ - packed_float3 position; - float _pad1; - packed_float3 right; - float _pad2; - packed_float3 up; - float _pad3; - float2 size; - float _pad4; - float _pad5; - packed_float3 diffuse; - float _pad6; - packed_float3 specular; - float angle; - int castsBothSides; - float intensity; - float range; - float _pad9; -}; - -struct AreaLightsUBO -{ - spvUnsafeArray areaLights; -}; - -struct AmbientLight -{ - float4 color; - float intensity; - float3 _pad0; -}; - -constant spvUnsafeArray _1657 = spvUnsafeArray({ float3(0.5381000041961669921875, 0.18559999763965606689453125, -0.4318999946117401123046875), float3(0.13789999485015869140625, 0.248600006103515625, 0.4429999887943267822265625), float3(0.3370999991893768310546875, 0.567900002002716064453125, -0.0057000000961124897003173828125), float3(-0.699899971485137939453125, -0.0450999997556209564208984375, -0.0019000000320374965667724609375), float3(0.068899996578693389892578125, -0.159799993038177490234375, -0.854700028896331787109375), float3(0.056000001728534698486328125, 0.0068999999202787876129150390625, -0.184300005435943603515625), float3(-0.014600000344216823577880859375, 0.14020000398159027099609375, 0.076200000941753387451171875), float3(0.00999999977648258209228515625, -0.19239999353885650634765625, -0.03440000116825103759765625), float3(-0.35769999027252197265625, -0.53009998798370361328125, -0.4357999861240386962890625), float3(-0.3169000148773193359375, 0.10629999637603759765625, 0.015799999237060546875), float3(0.010300000198185443878173828125, -0.5868999958038330078125, 0.0046000001020729541778564453125), float3(-0.08969999849796295166015625, -0.4939999878406524658203125, 0.328700006008148193359375), float3(0.7118999958038330078125, -0.015399999916553497314453125, -0.091799996793270111083984375), float3(-0.053300000727176666259765625, 0.0595999993383884429931640625, -0.541100025177001953125), float3(0.03519999980926513671875, -0.063100002706050872802734375, 0.546000003814697265625), float3(-0.4776000082492828369140625, 0.2847000062465667724609375, -0.0271000005304813385009765625), float3(-0.11200000345706939697265625, 0.1234000027179718017578125, -0.744599997997283935546875), float3(-0.212999999523162841796875, -0.07819999754428863525390625, -0.13789999485015869140625), float3(0.2944000065326690673828125, -0.3111999928951263427734375, -0.2644999921321868896484375), float3(-0.4564000070095062255859375, 0.4174999892711639404296875, -0.184300005435943603515625), float3(0.123400)", -R"(0027179718017578125, -0.567799985408782958984375, 0.788999974727630615234375), float3(-0.6789000034332275390625, 0.23450000584125518798828125, -0.4566999971866607666015625), float3(0.34560000896453857421875, -0.788999974727630615234375, 0.1234000027179718017578125), float3(-0.23450000584125518798828125, 0.567799985408782958984375, -0.6789000034332275390625), float3(0.788999974727630615234375, 0.1234000027179718017578125, 0.567799985408782958984375), float3(-0.567799985408782958984375, -0.6789000034332275390625, 0.23450000584125518798828125), float3(0.4566999971866607666015625, 0.788999974727630615234375, -0.23450000584125518798828125), float3(-0.788999974727630615234375, 0.34560000896453857421875, -0.567799985408782958984375), float3(0.6789000034332275390625, -0.23450000584125518798828125, 0.788999974727630615234375), float3(-0.1234000027179718017578125, 0.6789000034332275390625, -0.4566999971866607666015625), float3(0.23450000584125518798828125, -0.567799985408782958984375, 0.6789000034332275390625), float3(-0.34560000896453857421875, 0.788999974727630615234375, -0.1234000027179718017578125), float3(0.567799985408782958984375, 0.23450000584125518798828125, -0.788999974727630615234375), float3(-0.6789000034332275390625, -0.567799985408782958984375, 0.34560000896453857421875), float3(0.788999974727630615234375, -0.34560000896453857421875, 0.4566999971866607666015625), float3(-0.23450000584125518798828125, 0.1234000027179718017578125, -0.6789000034332275390625), float3(0.4566999971866607666015625, 0.788999974727630615234375, -0.567799985408782958984375), float3(-0.567799985408782958984375, 0.23450000584125518798828125, 0.6789000034332275390625), float3(0.34560000896453857421875, -0.788999974727630615234375, -0.1234000027179718017578125), float3(-0.788999974727630615234375, 0.567799985408782958984375, -0.23450000584125518798828125), float3(0.6789000034332275390625, -0.1234000027179718017578125, 0.34560000896453857421875), float3(-0.4566999971866607666015625, 0.788999974727630615234375, 0.23450000584125518798828125), float3(0.567799985408782958984375, -0.6789000034332275390625, 0.788999974727630615234375), float3(-0.34560000896453857421875, 0.567799985408782958984375, -0.6789000034332275390625), float3(0.23450000584125518798828125, -0.788999974727630615234375, 0.567799985408782958984375), float3(-0.6789000034332275390625, 0.23450000584125518798828125, -0.1234000027179718017578125), float3(0.788999974727630615234375, -0.34560000896453857421875, -0.567799985408782958984375), float3(-0.567799985408782958984375, 0.6789000034332275390625, 0.23450000584125518798828125), float3(0.4566999971866607666015625, -0.788999974727630615234375, 0.34560000896453857421875), float3(-0.23450000584125518798828125, 0.1234000027179718017578125, -0.788999974727630615234375), float3(0.34560000896453857421875, -0.567799985408782958984375, 0.6789000034332275390625), float3(-0.788999974727630615234375, 0.4566999971866607666015625, -0.34560000896453857421875), float3(0.6789000034332275390625, -0.1234000027179718017578125, -0.567799985408782958984375), float3(-0.4566999971866607666015625, 0.23450000584125518798828125, 0.788999974727630615234375) }); - -struct main0_out -{ - float4 FragColor [[color(0)]]; - float4 BrightColor [[color(1)]]; -}; - -struct main0_in -{ - float2 TexCoord [[user(locn0)]]; - float3 Normal [[user(locn2)]]; - float3 FragPos [[user(locn3)]]; - float3 TBN_0 [[user(locn4)]]; - float3 TBN_1 [[user(locn5)]]; - float3 TBN_2 [[user(locn6)]]; -}; - -static inline __attribute__((always_inline)) -float4 sampleTextureAt(thread const int& textureIndex, thread const float2& uv, texture2d texture1, sampler texture1Smplr, texture2d texture2, sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, texture2d texture4, sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, texture2d texture6, sampler texture6Smplr, texture2d texture7, sampler texture7Smplr, texture2d texture8, sampler texture8Smplr, texture2d texture9, sampler texture9Smplr, texture2d texture10, sampler texture10Smplr) -{ - if (textureIndex == 0) - { - return texture1.sample(texture1Smplr, uv); - } - else - { - if (textureIndex == 1) - { - return texture2.sample(texture2Smplr, uv); - } - else - { - if (textureIndex == 2) - { - return texture3.sample(texture3Smplr, uv); - } - else - { - if (textureIndex == 3) - { - return texture4.sample(texture4Smplr, uv); - } - else - { - if (textureIndex == 4) - { - return texture5.sample(texture5Smplr, uv); - } - else - { - if (textureIndex == 5) - { - return texture6.sample(texture6Smplr, uv); - } - else - { - if (textureIndex == 6) - { - return texture7.sample(texture7Smplr, uv); - } - else - { - if (textureIndex == 7) - { - return texture8.sample(texture8Smplr, uv); - } - else - { - if (textureIndex == 8) - { - return texture9.sample(texture9Smplr, uv); - } - else - { - if (textureIndex == 9) - { - return texture10.sample(texture10Smplr, uv); - } - } - } - } - } - } - } - } - } - } - return float4(0.0); -} - -static inline __attribute__((always_inline)) -float2 parallaxMapping(thread const float2& texCoords, thread const float3& viewDir, constant Uniforms& _163, texture2d texture1, sampler texture1Smplr, texture2d texture2, sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, texture2d texture4, sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, texture2d texture6, sampler texture6Smplr, texture2d texture7, sampler texture7Smplr, texture2d texture8, sampler texture8Smplr, texture2d texture9, sampler texture9Smplr, texture2d texture10, sampler texture10Smplr) -{ - float3 v = fast::normalize(viewDir); - float numLayers = mix(32.0, 8.0, abs(dot(float3(0.0, 0.0, 1.0), v))); - float layerDepth = 1.0 / numLayers; - float currentLayerDepth = 0.0; - float2 P = (v.xy / float2(fast::max(v.z, 0.0500000007450580596923828125))) * 0.039999999105930328369140625; - float2 deltaTexCoords = P / float2(numLayers); - float2 currentTexCoords = texCoords; - int textureIndex = -1; - for (int i = 0; i < _163.textureCount; i++) - { - if (_163.textureTypes[i].x == 6) - { - textureIndex = i; - break; - } - } - if (textureIndex == (-1)) - { - return texCoords; - } - int param = textureIndex; - float2 param_1 = currentTexCoords; - float currentDepthMapValue = 1.0 - sampleTextureAt(param, param_1, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr).x; - while (currentLayerDepth < currentDepthMapValue) - { - currentTexCo)", -R"(ords -= deltaTexCoords; - int param_2 = textureIndex; - float2 param_3 = currentTexCoords; - currentDepthMapValue = 1.0 - sampleTextureAt(param_2, param_3, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr).x; - currentLayerDepth += layerDepth; - } - float2 prevTexCoords = currentTexCoords + deltaTexCoords; - float afterDepth = currentDepthMapValue - currentLayerDepth; - int param_4 = textureIndex; - float2 param_5 = prevTexCoords; - float beforeDepth = 1.0 - sampleTextureAt(param_4, param_5, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr).x - (currentLayerDepth - layerDepth); - float weight = afterDepth / (afterDepth - beforeDepth); - currentTexCoords = (prevTexCoords * weight) + (currentTexCoords * (1.0 - weight)); - return currentTexCoords; -} - -static inline __attribute__((always_inline)) -float4 enableTextures(thread const int& type, constant Uniforms& _163, texture2d texture1, sampler texture1Smplr, thread float2& texCoord, texture2d texture2, sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, texture2d texture4, sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, texture2d texture6, sampler texture6Smplr, texture2d texture7, sampler texture7Smplr, texture2d texture8, sampler texture8Smplr, texture2d texture9, sampler texture9Smplr, texture2d texture10, sampler texture10Smplr) -{ - float4 color = float4(0.0); - int count = 0; - for (int i = 0; i < _163.textureCount; i++) - { - if (_163.textureTypes[i].x == type) - { - if (i == 0) - { - color += texture1.sample(texture1Smplr, texCoord); - } - else - { - if (i == 1) - { - color += texture2.sample(texture2Smplr, texCoord); - } - else - { - if (i == 2) - { - color += texture3.sample(texture3Smplr, texCoord); - } - else - { - if (i == 3) - { - color += texture4.sample(texture4Smplr, texCoord); - } - else - { - if (i == 4) - { - color += texture5.sample(texture5Smplr, texCoord); - } - else - { - if (i == 5) - { - color += texture6.sample(texture6Smplr, texCoord); - } - else - { - if (i == 6) - { - color += texture7.sample(texture7Smplr, texCoord); - } - else - { - if (i == 7) - { - color += texture8.sample(texture8Smplr, texCoord); - } - else - { - if (i == 8) - { - color += texture9.sample(texture9Smplr, texCoord); - } - else - { - if (i == 9) - { - color += texture10.sample(texture10Smplr, texCoord); - } - } - } - } - } - } - } - } - } - } - count++; - } - } - if (count > 0) - { - color /= float4(float(count)); - } - if (count == 0) - { - return float4(-1.0); - } - return color; -} - -static inline __attribute__((always_inline)) -float2 getTextureDimensions(thread const int& textureIndex, texture2d texture1, sampler texture1Smplr, texture2d texture2, sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, texture2d texture4, sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, texture2d texture6, sampler texture6Smplr, texture2d texture7, sampler texture7Smplr, texture2d texture8, sampler texture8Smplr, texture2d texture9, sampler texture9Smplr, texture2d texture10, sampler texture10Smplr) -{ - if (textureIndex == 0) - { - return float2(int2(texture1.get_width(), texture1.get_height())); - } - else - { - if (textureIndex == 1) - { - return float2(int2(texture2.get_width(), texture2.get_height())); - } - else - { - if (textureIndex == 2) - { - return float2(int2(texture3.get_width(), texture3.get_height())); - } - else - { - if (textureIndex == 3) - { - return float2(int2(texture4.get_width(), texture4.get_height())); - } - else - { - if (textureIndex == 4) - { - return float2(int2(texture5.get_width(), texture5.get_height())); - } - else - { - if (textureIndex == 5) - { - return float2(int2(texture6.get_width(), texture6.get_height())); - } - else - { - if (textureIndex == 6) - { - return float2(int2(texture7.get_width(), texture7.get_height())); - } - else - { - if (textureIndex == 7) - { - return float2(int2(texture8.get_width(), texture8.get_height())); - } - else - { - if (textureIndex == 8) - { - return float2(int2(texture9.get_width(), texture9.get_height())); - } - else - { - if (textureIndex == 9) - { - return float2(int2(texture10.get_width(), texture10.get_height())); - } - } - } - } - } - } - } - } - } - } - return float2(0.0); -} - -static inline __attribute__((always_inline)) -float calculateShadow(thread const ShadowParameters& shadowParam, thread const float4& fragP)", -R"(osLightSpace, constant Uniforms& _163, texture2d texture1, sampler texture1Smplr, texture2d texture2, sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, texture2d texture4, sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, texture2d texture6, sampler texture6Smplr, texture2d texture7, sampler texture7Smplr, texture2d texture8, sampler texture8Smplr, texture2d texture9, sampler texture9Smplr, texture2d texture10, sampler texture10Smplr, device DirectionalLightsUBO& _1083, thread float3& Normal, thread float3& FragPos) -{ - float3 projCoords = fragPosLightSpace.xyz / float3(fragPosLightSpace.w); - projCoords = (projCoords * 0.5) + float3(0.5); - bool _1362 = projCoords.x < 0.0; - bool _1369; - if (!_1362) - { - _1369 = projCoords.x > 1.0; - } - else - { - _1369 = _1362; - } - bool _1376; - if (!_1369) - { - _1376 = projCoords.y < 0.0; - } - else - { - _1376 = _1369; - } - bool _1383; - if (!_1376) - { - _1383 = projCoords.y > 1.0; - } - else - { - _1383 = _1376; - } - bool _1390; - if (!_1383) - { - _1390 = projCoords.z < 0.0; - } - else - { - _1390 = _1383; - } - bool _1398; - if (!_1390) - { - _1398 = projCoords.z > 1.0; - } - else - { - _1398 = _1390; - } - if (_1398) - { - return 0.0; - } - float currentDepth = projCoords.z; - float3 lightDir = fast::normalize(-(spvInverse4x4(shadowParam.lightView) * float4(0.0, 0.0, -1.0, 0.0)).xyz); - float3 normal = fast::normalize(Normal); - float biasValue = shadowParam.bias0; - float bias0 = fast::max(biasValue * (1.0 - dot(normal, lightDir)), biasValue); - float shadow = 0.0; - int param = shadowParam.textureIndex; - float2 texelSize = float2(1.0) / getTextureDimensions(param, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - float _distance = length(_163.cameraPosition - FragPos); - int kernelSize = int(mix(1.0, 3.0, fast::clamp(_distance / 100.0, 0.0, 1.0))); - int sampleCount = 0; - int _1444 = -kernelSize; - for (int x = _1444; x <= kernelSize; x++) - { - int _1455 = -kernelSize; - for (int y = _1455; y <= kernelSize; y++) - { - int param_1 = shadowParam.textureIndex; - float2 param_2 = projCoords.xy + (float2(float(x), float(y)) * texelSize); - float pcfDepth = sampleTextureAt(param_1, param_2, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr).x; - shadow += float((currentDepth - bias0) > pcfDepth); - sampleCount++; - } - } - shadow /= float(sampleCount); - return shadow; -} - -static inline __attribute__((always_inline)) -float4 sampleCubeTextureAt(thread const int& textureIndex, thread const float3& direction, texturecube cubeMap1, sampler cubeMap1Smplr, texturecube cubeMap2, sampler cubeMap2Smplr, texturecube cubeMap3, sampler cubeMap3Smplr, texturecube cubeMap4, sampler cubeMap4Smplr, texturecube cubeMap5, sampler cubeMap5Smplr) -{ - if (textureIndex == 0) - { - return cubeMap1.sample(cubeMap1Smplr, direction); - } - else - { - if (textureIndex == 1) - { - return cubeMap2.sample(cubeMap2Smplr, direction); - } - else - { - if (textureIndex == 2) - { - return cubeMap3.sample(cubeMap3Smplr, direction); - } - else - { - if (textureIndex == 3) - { - return cubeMap4.sample(cubeMap4Smplr, direction); - } - else - { - if (textureIndex == 4) - { - return cubeMap5.sample(cubeMap5Smplr, direction); - } - } - } - } - } - return float4(0.0); -} - -static inline __attribute__((always_inline)) -float calculatePointShadow(thread const ShadowParameters& shadowParam, thread const float3& fragPos, texturecube cubeMap1, sampler cubeMap1Smplr, texturecube cubeMap2, sampler cubeMap2Smplr, texturecube cubeMap3, sampler cubeMap3Smplr, texturecube cubeMap4, sampler cubeMap4Smplr, texturecube cubeMap5, sampler cubeMap5Smplr) -{ - float3 fragToLight = fragPos - shadowParam.lightPos; - float currentDepth = length(fragToLight); - float bias0 = 0.0500000007450580596923828125; - float shadow = 0.0; - float diskRadius = (1.0 + (currentDepth / shadowParam.farPlane)) * 0.0500000007450580596923828125; - for (int i = 0; i < 54; i++) - { - float3 sampleDir = fast::normalize(fragToLight + (_1657[i] * diskRadius)); - int param = shadowParam.textureIndex; - float3 param_1 = sampleDir; - float closestDepth = sampleCubeTextureAt(param, param_1, cubeMap1, cubeMap1Smplr, cubeMap2, cubeMap2Smplr, cubeMap3, cubeMap3Smplr, cubeMap4, cubeMap4Smplr, cubeMap5, cubeMap5Smplr).x * shadowParam.farPlane; - if ((currentDepth - bias0) > closestDepth) - { - shadow += 1.0; - } - } - shadow /= 54.0; - return shadow; -} - -static inline __attribute__((always_inline)) -float distributionGGX(thread const float3& N, thread const float3& H, thread const float& roughness) -{ - float a = roughness * roughness; - float a2 = a * a; - float NdotH = fast::max(dot(N, H), 0.0); - float NdotH2 = NdotH * NdotH; - float num = a2; - float denom = (NdotH2 * (a2 - 1.0)) + 1.0; - denom = (3.1415927410125732421875 * denom) * denom; - return num / denom; -} - -static inline __attribute__((always_inline)) -float geometrySchlickGGX(thread const float& NdotV, thread const float& roughness) -{ - float r = roughness + 1.0; - float k = (r * r) / 8.0; - float num = NdotV; - float denom = (NdotV * (1.0 - k)) + k; - return num / denom; -} - -static inline __attribute__((always_inline)) -float geometrySmith(thread const float3& N, thread const float3& V, thread const float3& L, thread const float& roughness) -{ - float NdotV = fast::max(dot(N, V), 0.0); - float NdotL = fast::max(dot(N, L), 0.0); - float param = NdotV; - float param_1 = roughness; - float ggx2 = geometrySchlickGGX(param, param_1); - float param_2 = NdotL; - float param_3 = roughness; - float ggx1 = geometrySchlickGGX(param_2, param_3); - return ggx1 * ggx2; -} - -static inline __attribute__((always_inline)) -float3 fresnelSchlick(thread const float& cosTheta, thread const float3& F0) -{ - return F0 + ((float3(1.0) - F0) * powr(1.0 - cosTheta, 5.0)); -} - -static inline __attribute__((always_inline)) -float3 calculatePBR(thread const float3& N, thread const float3& V, thread const float3& L, thread const float3& F0, thread const float3& radiance, thread const float3& albedo, thread const float& metallic, thread const float& roughness, thread const float& reflectivity) -{ - float3 H = fast::normalize(V + L); - float3 param = N; - float3 param_1 = H; - float param_2 = roughness; - float NDF = distributionGGX(param, param_1, param_2); - float3 param_3 = N; - float3 param_4 = V; - float3 param_5 = L; - float param_6 = roughness; - float G = geometrySmith(param_3, param_4, param_5, param_6); - float param_7 = fast::max(dot(H, V), 0.0); - float3 param_8 = F0; - float3 F = fresnelSchlick(param_7, param_8); - float3 kS = F; - float3 kD = float3(1.0) - kS; - kD *= (1.0 - metallic); - float3 numerator = F * (NDF * G); - float denominator = ((4.0 * fast::max(dot(N, V), 0.0)) * fast::max(dot(N, L), 0.0)) + 9.9999997473787516355514526367188e-05; - float3 specular = numerator / float3(denominator); - float NdotL = fast::max(dot(N, L), 0.0); - float3 Lo = ((((kD * albedo) /)", -R"( float3(3.1415927410125732421875)) + specular) * radiance) * NdotL; - return Lo; -} - -static inline __attribute__((always_inline)) -float3 calcAllDirectionalLights(thread const float3& N, thread const float3& V, thread const float3& albedo, thread const float& metallic, thread const float& roughness, thread const float3& F0, thread const float& reflectivity, constant PushConstants& _1073, device DirectionalLightsUBO& _1083) -{ - float3 Lo = float3(0.0); - for (int i = 0; i < _1073.directionalLightCount; i++) - { - float3 L = fast::normalize(-float3(_1083.directionalLights[i].direction)); - float3 radiance = float3(_1083.directionalLights[i].diffuse) * fast::max(_1083.directionalLights[i].intensity, 0.0); - float3 param = N; - float3 param_1 = V; - float3 param_2 = L; - float3 param_3 = F0; - float3 param_4 = radiance; - float3 param_5 = albedo; - float param_6 = metallic; - float param_7 = roughness; - float param_8 = reflectivity; - Lo += calculatePBR(param, param_1, param_2, param_3, param_4, param_5, param_6, param_7, param_8); - } - return Lo; -} - -static inline __attribute__((always_inline)) -float3 calcAllPointLights(thread const float3& fragPos, thread const float3& N, thread const float3& V, thread const float3& albedo, thread const float& metallic, thread const float& roughness, thread const float3& F0, thread const float& reflectivity, constant PushConstants& _1073, device PointLightsUBO& _1136) -{ - float3 Lo = float3(0.0); - for (int i = 0; i < _1073.pointLightCount; i++) - { - float3 L = float3(_1136.pointLights[i].position) - fragPos; - float _distance = length(L); - _distance = fast::max(_distance, 0.001000000047497451305389404296875); - L = fast::normalize(L); - float range = fast::max(_1136.pointLights[i].radius, 0.001000000047497451305389404296875); - float3 radiance = float3(_1136.pointLights[i].diffuse) * fast::max(_1136.pointLights[i].intensity, 0.0); - float attenuation = 1.0 / ((1.0 + (_distance / range)) + ((_distance * _distance) / (range * range))); - float fade = 1.0 - smoothstep(range * 0.89999997615814208984375, range, _distance); - float3 radianceAttenuated = radiance * attenuation; - radianceAttenuated *= fade; - float3 H = fast::normalize(V + L); - float3 param = N; - float3 param_1 = H; - float param_2 = roughness; - float NDF = distributionGGX(param, param_1, param_2); - float3 param_3 = N; - float3 param_4 = V; - float3 param_5 = L; - float param_6 = roughness; - float G = geometrySmith(param_3, param_4, param_5, param_6); - float param_7 = fast::max(dot(H, V), 0.0); - float3 param_8 = F0; - float3 F = fresnelSchlick(param_7, param_8); - float3 kS = F; - float3 kD = float3(1.0) - kS; - kD *= (1.0 - metallic); - float3 numerator = F * (NDF * G); - float denominator = ((4.0 * fast::max(dot(N, V), 0.0)) * fast::max(dot(N, L), 0.0)) + 9.9999997473787516355514526367188e-05; - float3 specular = numerator / float3(denominator); - float NdotL = fast::max(dot(N, L), 0.0); - Lo += (((((kD * albedo) / float3(3.1415927410125732421875)) + specular) * radianceAttenuated) * NdotL); - } - return Lo; -} - -static inline __attribute__((always_inline)) -float3 calcAllSpotLights(thread const float3& N, thread const float3& fragPos, thread const float3& L, thread const float3& viewDir, thread const float3& albedo, thread const float& metallic, thread const float& roughness, thread const float3& F0, thread const float& reflectivity, constant PushConstants& _1073, device SpotLightsUBO& _1268) -{ - float3 Lo = float3(0.0); - for (int i = 0; i < _1073.spotlightCount; i++) - { - float3 L_1 = fast::normalize(float3(_1268.spotlights[i].position) - fragPos); - float3 spotDirection = fast::normalize(float3(_1268.spotlights[i].direction)); - float theta = dot(L_1, -spotDirection); - float intensity = smoothstep(_1268.spotlights[i].outerCutOff, _1268.spotlights[i].cutOff, theta); - float _distance = length(float3(_1268.spotlights[i].position) - fragPos); - _distance = fast::max(_distance, 0.001000000047497451305389404296875); - float range = fast::max(_1268.spotlights[i].range, 0.001000000047497451305389404296875); - float attenuation = 1.0 / ((1.0 + (_distance / range)) + ((_distance * _distance) / (range * range))); - float fade = 1.0 - smoothstep(range * 0.89999997615814208984375, range, _distance); - float3 radiance = (((float3(_1268.spotlights[i].diffuse) * fast::max(_1268.spotlights[i].intensity, 0.0)) * attenuation) * intensity) * fade; - float3 param = N; - float3 param_1 = viewDir; - float3 param_2 = L_1; - float3 param_3 = F0; - float3 param_4 = radiance; - float3 param_5 = albedo; - float param_6 = metallic; - float param_7 = roughness; - float param_8 = reflectivity; - Lo += calculatePBR(param, param_1, param_2, param_3, param_4, param_5, param_6, param_7, param_8); - } - return Lo; -} - -static inline __attribute__((always_inline)) -float3 getRimLight(thread const float3& fragPos, thread float3& N, thread float3& V, thread const float3& F0, thread const float3& albedo, thread const float& metallic, thread const float& roughness, constant Uniforms& _163, constant Environment& environment) -{ - N = fast::normalize(N); - V = fast::normalize(V); - float rim = powr(1.0 - fast::max(dot(N, V), 0.0), 3.0); - rim *= mix(1.2000000476837158203125, 0.300000011920928955078125, roughness); - float3 rimColor = mix(float3(1.0), albedo, float3(metallic)) * environment.rimLightColor; - rimColor = mix(rimColor, F0, float3(0.5)); - float rimIntensity = environment.rimLightIntensity; - float3 rimLight = (rimColor * rim) * rimIntensity; - float dist = length(_163.cameraPosition - fragPos); - rimLight /= float3(1.0 + (dist * 0.100000001490116119384765625)); - return rimLight; -} - -static inline __attribute__((always_inline)) -float2 directionToEquirect(thread const float3& direction) -{ - float3 dir = fast::normalize(direction); - float phi = precise::atan2(dir.z, dir.x); - float theta = acos(fast::clamp(dir.y, -1.0, 1.0)); - return float2((phi + 3.1415927410125732421875) / 6.283185482025146484375, theta / 3.1415927410125732421875); -} - -static inline __attribute__((always_inline)) -float3 sampleHDRTexture(thread const int& textureIndex, thread const float3& direction, texture2d texture1, sampler texture1Smplr, texture2d texture2, sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, texture2d texture4, sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, texture2d texture6, sampler texture6Smplr, texture2d texture7, sampler texture7Smplr, texture2d texture8, sampler texture8Smplr, texture2d texture9, sampler texture9Smplr, texture2d texture10, sampler texture10Smplr) -{ - float3 param = direction; - float2 uv = directionToEquirect(param); - int param_1 = textureIndex; - float2 param_2 = uv; - return sampleTextureAt(param_1, param_2, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr).xyz; -} - -static inline __attribute__((always_inline)) -float3 sampleEnvironmentRadiance(thread const float3& direction, constant Uniforms& _163, texture2d texture1, sampler texture1Smplr, texture2d texture2, sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, texture2d texture4, sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, texture2d texture6, sampler texture6Smplr, texture2d texture7, sampler texture7Smplr, texture2d texture8, sampler texture8Smplr, texture2d texture9, sampler texture9Smplr, texture2d texture10, sampler texture10Smplr) -{ - float3 envColor)", -R"( = float3(0.0); - int count = 0; - for (int i = 0; i < _163.textureCount; i++) - { - if (_163.textureTypes[i].x == 13) - { - int param = i; - float3 param_1 = direction; - envColor += sampleHDRTexture(param, param_1, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - count++; - } - } - if (count == 0) - { - return float3(0.0); - } - return envColor / float3(float(count)); -} - -static inline __attribute__((always_inline)) -float3 acesToneMapping(thread float3& color) -{ - float a = 2.5099999904632568359375; - float b = 0.02999999932944774627685546875; - float c = 2.4300000667572021484375; - float d = 0.589999973773956298828125; - float e = 0.14000000059604644775390625; - color = (color * ((color * a) + float3(b))) / ((color * ((color * c) + float3(d))) + float3(e)); - color = powr(fast::clamp(color, float3(0.0), float3(1.0)), float3(0.4545454680919647216796875)); - return color; -} - -fragment main0_out main0(main0_in in [[stage_in]], constant Uniforms& _163 [[buffer(0)]], constant Environment& environment [[buffer(1)]], constant PushConstants& _1073 [[buffer(2)]], device DirectionalLightsUBO& _1083 [[buffer(3)]], device PointLightsUBO& _1136 [[buffer(4)]], device SpotLightsUBO& _1268 [[buffer(5)]], constant Material& material [[buffer(6)]], device ShadowParametersUBO& _1905 [[buffer(7)]], device AreaLightsUBO& _2058 [[buffer(8)]], constant AmbientLight& ambientLight [[buffer(9)]], texture2d texture1 [[texture(0)]], texture2d texture2 [[texture(1)]], texture2d texture3 [[texture(2)]], texture2d texture4 [[texture(3)]], texture2d texture5 [[texture(4)]], texture2d texture6 [[texture(5)]], texture2d texture7 [[texture(6)]], texture2d texture8 [[texture(7)]], texture2d texture9 [[texture(8)]], texture2d texture10 [[texture(9)]], texturecube cubeMap1 [[texture(10)]], texturecube cubeMap2 [[texture(11)]], texturecube cubeMap3 [[texture(12)]], texturecube cubeMap4 [[texture(13)]], texturecube cubeMap5 [[texture(14)]], sampler texture1Smplr [[sampler(0)]], sampler texture2Smplr [[sampler(1)]], sampler texture3Smplr [[sampler(2)]], sampler texture4Smplr [[sampler(3)]], sampler texture5Smplr [[sampler(4)]], sampler texture6Smplr [[sampler(5)]], sampler texture7Smplr [[sampler(6)]], sampler texture8Smplr [[sampler(7)]], sampler texture9Smplr [[sampler(8)]], sampler texture10Smplr [[sampler(9)]], sampler cubeMap1Smplr [[sampler(10)]], sampler cubeMap2Smplr [[sampler(11)]], sampler cubeMap3Smplr [[sampler(12)]], sampler cubeMap4Smplr [[sampler(13)]], sampler cubeMap5Smplr [[sampler(14)]]) -{ - main0_out out = {}; - float3x3 TBN = {}; - TBN[0] = in.TBN_0; - TBN[1] = in.TBN_1; - TBN[2] = in.TBN_2; - float2 texCoord = in.TexCoord * _163.textureScale + _163.textureOffset; - bool hasParallaxMap = false; - for (int i = 0; i < _163.textureCount; i++) - { - if (_163.textureTypes[i].x == 6) - { - hasParallaxMap = true; - break; - } - } - if (hasParallaxMap) - { - float3 tangentViewDir = fast::normalize(transpose(TBN) * (_163.cameraPosition - in.FragPos)); - float2 param = texCoord; - float3 param_1 = tangentViewDir; - texCoord = parallaxMapping(param, param_1, _163, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - } - int param_2 = 5; - float4 normTexture = enableTextures(param_2, _163, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - bool _1774 = normTexture.x != (-1.0); - bool _1780; - if (_1774) - { - _1780 = normTexture.y != (-1.0); - } - else - { - _1780 = _1774; - } - bool _1786; - if (_1780) - { - _1786 = normTexture.z != (-1.0); - } - else - { - _1786 = _1780; - } - float normalStrength = fast::max(_163.normalMapStrength, 0.0f); - bool useNormalMap = (_163.useNormalMap != 0u) && (normalStrength > 0.0f); - float3 N; - if (_1786 && useNormalMap) - { - float3 tangentNormal = (normTexture.xyz * 2.0) - float3(1.0); - tangentNormal.xy *= normalStrength; - tangentNormal = fast::normalize(tangentNormal); - N = fast::normalize(TBN * tangentNormal); - } - else - { - N = fast::normalize(in.Normal); - } - N = fast::normalize(N); - float3 V = fast::normalize(_163.cameraPosition - in.FragPos); - float3 albedo = float3(material.albedo); - int param_3 = 0; - float4 albedoTex = enableTextures(param_3, _163, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - if (any(albedoTex != float4(-1.0))) - { - albedo *= albedoTex.xyz; - } - int param_3a = 12; - float4 opacityTex = enableTextures(param_3a, _163, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - if (any(opacityTex != float4(-1.0))) - { - if (opacityTex.x < 0.100000001490116119384765625) - { - discard_fragment(); - } - } - else - { - if ((albedoTex.w < 0.100000001490116119384765625) && (material.albedo[3] < 0.999000012874603271484375)) - { - discard_fragment(); - } - } - int param_pbr_pack = 14; - float4 pbrPackTex = enableTextures(param_pbr_pack, _163, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - bool hasPbrPack = any(pbrPackTex != float4(-1.0)); - float metallic = material.metallic; - int param_4 = 9; - float4 metallicTex = enableTextures(param_4, _163, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - if (hasPbrPack) - { - metallic *= pbrPackTex.z; - } - else if (any(metallicTex != float4(-1.0))) - { - metallic *= metallicTex.x; - } - float roughness = material.roughness; - int param_5 = 10; - float4 roughnessTex = enableTextures(param_5, _163, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - if (hasPbrPack) - { - roughness *= pbrPackTex.y; - } - else if (any(roughnessTex != float4(-1.0))) - { - roughness *= roughnessTex.x; - } - float ao = material.ao; - int param_6 = 11; - float4 aoTex = enableTextures(param_6, _163, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - if (hasPbrPack) - { - ao *= pbrPackTex.x; - } - else if (any(aoTex != float4(-1.0))) - { - ao *= a)", -R"(oTex.x; - } - float3 F0 = float3(0.039999999105930328369140625); - F0 = mix(F0, albedo, float3(metallic)); - float directionalShadow = 0.0; - float spotShadow = 0.0; - float areaShadow = 0.0; - float pointShadow = 0.0; - if (_1073.shadowParamCount > 0) - { - for (int i_1 = 0; i_1 < _1073.shadowParamCount; i_1++) - { - if (_1905.shadowParams[i_1].lightType == 0) - { - float4 fragPosLightSpace = (_1905.shadowParams[i_1].lightProjection * _1905.shadowParams[i_1].lightView) * float4(in.FragPos, 1.0); - ShadowParameters _1934; - _1934.lightView = _1905.shadowParams[i_1].lightView; - _1934.lightProjection = _1905.shadowParams[i_1].lightProjection; - _1934.bias0 = _1905.shadowParams[i_1].bias0; - _1934.textureIndex = _1905.shadowParams[i_1].textureIndex; - _1934.farPlane = _1905.shadowParams[i_1].farPlane; - _1934._pad1 = _1905.shadowParams[i_1]._pad1; - _1934.lightPos = float3(_1905.shadowParams[i_1].lightPos); - _1934.lightType = _1905.shadowParams[i_1].lightType; - ShadowParameters param_7 = _1934; - float4 param_8 = fragPosLightSpace; - areaShadow = fast::max(areaShadow, calculateShadow(param_7, param_8, _163, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr, _1083, in.Normal, in.FragPos)); - } - else if (_1905.shadowParams[i_1].lightType == 1) - { - float4 fragPosLightSpace = (_1905.shadowParams[i_1].lightProjection * _1905.shadowParams[i_1].lightView) * float4(in.FragPos, 1.0); - ShadowParameters _1934; - _1934.lightView = _1905.shadowParams[i_1].lightView; - _1934.lightProjection = _1905.shadowParams[i_1].lightProjection; - _1934.bias0 = _1905.shadowParams[i_1].bias0; - _1934.textureIndex = _1905.shadowParams[i_1].textureIndex; - _1934.farPlane = _1905.shadowParams[i_1].farPlane; - _1934._pad1 = _1905.shadowParams[i_1]._pad1; - _1934.lightPos = float3(_1905.shadowParams[i_1].lightPos); - _1934.lightType = _1905.shadowParams[i_1].lightType; - ShadowParameters param_7 = _1934; - float4 param_8 = fragPosLightSpace; - spotShadow = fast::max(spotShadow, calculateShadow(param_7, param_8, _163, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr, _1083, in.Normal, in.FragPos)); - } - else if (_1905.shadowParams[i_1].lightType == 2) - { - float4 fragPosLightSpace = (_1905.shadowParams[i_1].lightProjection * _1905.shadowParams[i_1].lightView) * float4(in.FragPos, 1.0); - ShadowParameters _1934; - _1934.lightView = _1905.shadowParams[i_1].lightView; - _1934.lightProjection = _1905.shadowParams[i_1].lightProjection; - _1934.bias0 = _1905.shadowParams[i_1].bias0; - _1934.textureIndex = _1905.shadowParams[i_1].textureIndex; - _1934.farPlane = _1905.shadowParams[i_1].farPlane; - _1934._pad1 = _1905.shadowParams[i_1]._pad1; - _1934.lightPos = float3(_1905.shadowParams[i_1].lightPos); - _1934.lightType = _1905.shadowParams[i_1].lightType; - ShadowParameters param_7 = _1934; - float4 param_8 = fragPosLightSpace; - directionalShadow = fast::max(directionalShadow, calculateShadow(param_7, param_8, _163, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr, _1083, in.Normal, in.FragPos)); - } - else - { - ShadowParameters _1945; - _1945.lightView = _1905.shadowParams[i_1].lightView; - _1945.lightProjection = _1905.shadowParams[i_1].lightProjection; - _1945.bias0 = _1905.shadowParams[i_1].bias0; - _1945.textureIndex = _1905.shadowParams[i_1].textureIndex; - _1945.farPlane = _1905.shadowParams[i_1].farPlane; - _1945._pad1 = _1905.shadowParams[i_1]._pad1; - _1945.lightPos = float3(_1905.shadowParams[i_1].lightPos); - _1945.lightType = _1905.shadowParams[i_1].lightType; - ShadowParameters param_9 = _1945; - float3 param_10 = in.FragPos; - pointShadow = fast::max(pointShadow, calculatePointShadow(param_9, param_10, cubeMap1, cubeMap1Smplr, cubeMap2, cubeMap2Smplr, cubeMap3, cubeMap3Smplr, cubeMap4, cubeMap4Smplr, cubeMap5, cubeMap5Smplr)); - } - } - } - float reflectivity = material.reflectivity; - float3 viewDir = fast::normalize(_163.cameraPosition - in.FragPos); - float3 lighting = float3(0.0); - float3 param_11 = N; - float3 param_12 = V; - float3 param_13 = albedo; - float param_14 = metallic; - float param_15 = roughness; - float3 param_16 = F0; - float param_17 = reflectivity; - lighting += (calcAllDirectionalLights(param_11, param_12, param_13, param_14, param_15, param_16, param_17, _1073, _1083) * (1.0 - directionalShadow)); - float3 param_18 = in.FragPos; - float3 param_19 = N; - float3 param_20 = V; - float3 param_21 = albedo; - float param_22 = metallic; - float param_23 = roughness; - float3 param_24 = F0; - float param_25 = reflectivity; - lighting += (calcAllPointLights(param_18, param_19, param_20, param_21, param_22, param_23, param_24, param_25, _1073, _1136) * (1.0 - pointShadow)); - float3 param_26 = N; - float3 param_27 = in.FragPos; - float3 param_28 = V; - float3 param_29 = viewDir; - float3 param_30 = albedo; - float param_31 = metallic; - float param_32 = roughness; - float3 param_33 = F0; - float param_34 = reflectivity; - lighting += calcAllSpotLights(param_26, param_27, param_28, param_29, param_30, param_31, param_32, param_33, param_34, _1073, _1268) * (1.0 - spotShadow); - float3 param_35 = in.FragPos; - float3 param_36 = N; - float3 param_37 = V; - float3 param_38 = F0; - float3 param_39 = albedo; - float param_40 = metallic; - float param_41 = roughness; - float3 _2039 = getRimLight(param_35, param_36, param_37, param_38, param_39, param_40, param_41, _163, environment); - lighting += _2039; - float3 areaResult = float3(0.0); - float _2144; - for (int i_2 = 0; i_2 < _1073.areaLightCount; i_2++) - { - float3 P = float3(_2058.areaLights[i_2].position); - float3 R = fast::normalize(float3(_2058.areaLights[i_2].right)); - float3 U = fast::normalize(float3(_2058.areaLights[i_2].up)); - float2 halfSize = _2058.areaLights[i_2].size * 0.5; - float3 toPoint = in.FragPos - P; - float s = fast::clamp(dot(toPoint, R), -halfSize.x, halfSize.x); - float t = fast::clamp(dot(toPoint, U), -halfSize.y, halfSize.y); - float3 Q = (P + (R * s)) + (U * t); - float3 Lvec = Q - in.FragPos; - float dist = length(Lvec); - if (dist > 9.9999997473787516355514526367188e-05) - { - float3 L = Lvec / float3(dist); - float3 Nl = fast::normalize(cross(R, U)); - float ndotl = dot(Nl, -L); - if (_2058.areaLights[i_2].castsBothSides != 0) - { - _2144 = abs(ndotl); - } - else - { - _2144 = fast::max(ndotl, 0.0); - } - float facing = _2144; - float cosTheta = cos(radians(_2058.areaLights[i_2].angle)); - if ((facing >= cosTh)", -R"(eta) && (facing > 0.0)) - { - float range = fast::max(_2058.areaLights[i_2].range, 0.001000000047497451305389404296875); - float attenuation = 1.0 / ((1.0 + (dist / range)) + ((dist * dist) / (range * range))); - float fade = 1.0 - smoothstep(range * 0.89999997615814208984375, range, dist); - float3 radiance = (((float3(_2058.areaLights[i_2].diffuse) * fast::max(_2058.areaLights[i_2].intensity, 0.0)) * attenuation) * facing) * fade; - float3 H = fast::normalize(V + L); - float3 param_42 = N; - float3 param_43 = H; - float param_44 = roughness; - float NDF = distributionGGX(param_42, param_43, param_44); - float3 param_45 = N; - float3 param_46 = V; - float3 param_47 = L; - float param_48 = roughness; - float G = geometrySmith(param_45, param_46, param_47, param_48); - float param_49 = fast::max(dot(H, V), 0.0); - float3 param_50 = F0; - float3 F = fresnelSchlick(param_49, param_50); - float3 kS = F; - float3 kD = (float3(1.0) - kS) * (1.0 - metallic); - float3 numerator = F * (NDF * G); - float denominator = fast::max((4.0 * fast::max(dot(N, V), 0.0)) * fast::max(dot(N, L), 0.0), 9.9999997473787516355514526367188e-05); - float3 specular = numerator / float3(denominator); - float NdotL = fast::max(dot(N, L), 0.0); - areaResult += (((((kD * albedo) / float3(3.1415927410125732421875)) + specular) * radiance) * NdotL); - } - } - } - lighting += areaResult * (1.0 - areaShadow); - float aoClamped = fast::clamp(ao, 0.0, 1.0); - float aoWithFloor = fast::max(aoClamped, 0.20000000298023223876953125); - float ambientIntensity = ambientLight.intensity; - float3 ambientColor = ambientLight.color.xyz; - if (ambientIntensity <= 9.9999997473787516355514526367188e-05) - { - ambientIntensity = 0.02999999932944774627685546875; - } - if (dot(ambientColor, ambientColor) <= 9.9999999747524270787835121154785e-07) - { - ambientColor = float3(1.0); - } - float3 ambient = ((albedo * ambientIntensity) * ambientColor) * aoWithFloor; - float3 iblContribution = float3(0.0); - if (_1073.useIBL != 0u) - { - float3 param_51 = N; - float3 irradiance = sampleEnvironmentRadiance(param_51, _163, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - float3 diffuseIBL = irradiance * albedo; - float3 reflection = reflect(-V, N); - float3 param_52 = reflection; - float3 specularEnv = sampleEnvironmentRadiance(param_52, _163, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - float param_53 = fast::max(dot(N, V), 0.0); - float3 param_54 = F0; - float3 F_1 = fresnelSchlick(param_53, param_54); - float3 kS_1 = F_1; - float3 kD_1 = float3(1.0) - kS_1; - kD_1 *= (1.0 - metallic); - float roughnessAttenuation = mix(1.0, 0.1500000059604644775390625, fast::clamp(roughness, 0.0, 1.0)); - float3 specularIBL = specularEnv * roughnessAttenuation; - iblContribution = ((kD_1 * diffuseIBL) + (kS_1 * specularIBL)) * aoWithFloor; - } - float3 color = (ambient + lighting) + iblContribution; - out.FragColor = float4(color, 1.0); - float brightness = dot(color, float3(0.2125999927520751953125, 0.715200006961822509765625, 0.072200000286102294921875)); - if (brightness > 0.75) - { - out.BrightColor = float4(color, 1.0); - } - else - { - out.BrightColor = float4(0.0, 0.0, 0.0, 1.0); - } - float3 param_55 = out.FragColor.xyz; - float3 _2399 = acesToneMapping(param_55); - out.FragColor.x = _2399.x; - out.FragColor.y = _2399.y; - out.FragColor.z = _2399.z; - return out; -} -)", -}; -static const AtlasPackedShaderSource MAIN_FRAG = {MAIN_FRAG_PARTS, 8}; - -static const char* const MAIN_VERT_PARTS[] = { -R"(#pragma clang diagnostic ignored "-Wmissing-prototypes" - -#include -#include - -using namespace metal; - -// Returns the determinant of a 2x2 matrix. -static inline __attribute__((always_inline)) -float spvDet2x2(float a1, float a2, float b1, float b2) -{ - return a1 * b2 - b1 * a2; -} - -// Returns the inverse of a matrix, by using the algorithm of calculating the classical -// adjoint and dividing by the determinant. The contents of the matrix are changed. -static inline __attribute__((always_inline)) -float3x3 spvInverse3x3(float3x3 m) -{ - float3x3 adj; // The adjoint matrix (inverse after dividing by determinant) - - // Create the transpose of the cofactors, as the classical adjoint of the matrix. - adj[0][0] = spvDet2x2(m[1][1], m[1][2], m[2][1], m[2][2]); - adj[0][1] = -spvDet2x2(m[0][1], m[0][2], m[2][1], m[2][2]); - adj[0][2] = spvDet2x2(m[0][1], m[0][2], m[1][1], m[1][2]); - - adj[1][0] = -spvDet2x2(m[1][0], m[1][2], m[2][0], m[2][2]); - adj[1][1] = spvDet2x2(m[0][0], m[0][2], m[2][0], m[2][2]); - adj[1][2] = -spvDet2x2(m[0][0], m[0][2], m[1][0], m[1][2]); - - adj[2][0] = spvDet2x2(m[1][0], m[1][1], m[2][0], m[2][1]); - adj[2][1] = -spvDet2x2(m[0][0], m[0][1], m[2][0], m[2][1]); - adj[2][2] = spvDet2x2(m[0][0], m[0][1], m[1][0], m[1][1]); - - // Calculate the determinant as a combination of the cofactors of the first row. - float det = (adj[0][0] * m[0][0]) + (adj[0][1] * m[1][0]) + (adj[0][2] * m[2][0]); - - // Divide the classical adjoint matrix by the determinant. - // If determinant is zero, matrix is not invertable, so leave it unchanged. - return (det != 0.0f) ? (adj * (1.0f / det)) : m; -} - -struct UBO -{ - float4x4 model; - float4x4 view; - float4x4 projection; - uint isInstanced; -}; - -struct main0_out -{ - float2 TexCoord [[user(locn0)]]; - float4 outColor [[user(locn1)]]; - float3 Normal [[user(locn2)]]; - float3 FragPos [[user(locn3)]]; - float3 TBN_0 [[user(locn4)]]; - float3 TBN_1 [[user(locn5)]]; - float3 TBN_2 [[user(locn6)]]; - float4 gl_Position [[position, invariant]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; - float4 aColor [[attribute(1)]]; - float2 aTexCoord [[attribute(2)]]; - float3 aNormal [[attribute(3)]]; - float3 aTangent [[attribute(4)]]; - float3 aBitangent [[attribute(5)]]; - float4 instanceModel_0 [[attribute(6)]]; - float4 instanceModel_1 [[attribute(7)]]; - float4 instanceModel_2 [[attribute(8)]]; - float4 instanceModel_3 [[attribute(9)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]], constant UBO& uniforms [[buffer(0)]]) -{ - main0_out out = {}; - float3x3 TBN = {}; - float4x4 instanceModel = {}; - instanceModel[0] = in.instanceModel_0; - instanceModel[1] = in.instanceModel_1; - instanceModel[2] = in.instanceModel_2; - instanceModel[3] = in.instanceModel_3; - float4x4 modelMatrix = uniforms.model; - bool hasInstanceMatrix = abs(instanceModel[3].w) > 0.5; - if ((uniforms.isInstanced != 0u) && hasInstanceMatrix) - { - modelMatrix = instanceModel; - } - float4x4 mvp = (uniforms.projection * uniforms.view) * modelMatrix; - float4 _56 = float4(in.aPos, 1.0); - float4 _57 = mvp * _56; - out.gl_Position = _57; - out.FragPos = float3((modelMatrix * float4(in.aPos, 1.0)).xyz); - out.TexCoord = in.aTexCoord; - out.outColor = in.aColor; - float3x3 normalMatrix = transpose(spvInverse3x3(float3x3(modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz))); - out.Normal = fast::normalize(normalMatrix * in.aNormal); - float3 N = out.Normal; - float3 T = fast::normalize(normalMatrix * in.aTangent); - float3 B = fast::normalize(normalMatrix * in.aBitangent); - TBN = float3x3(float3(T), float3(B), float3(N)); - out.TBN_0 = TBN[0]; - out.TBN_1 = TBN[1]; - out.TBN_2 = TBN[2]; - return out; -} -)", -}; -static const AtlasPackedShaderSource MAIN_VERT = {MAIN_VERT_PARTS, 1}; - -static const char* const PARTICLE_FRAG_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct Params -{ - uint useTexture; -}; - -struct main0_out -{ - float4 FragColor [[color(0)]]; -}; - -struct main0_in -{ - float2 fragTexCoord [[user(locn0)]]; - float4 fragColor [[user(locn1)]]; -}; - -fragment main0_out main0(main0_in in [[stage_in]], constant Params& _9 [[buffer(0)]], texture2d particleTexture [[texture(0)]], sampler particleTextureSmplr [[sampler(0)]]) -{ - main0_out out = {}; - if (_9.useTexture != 0u) - { - float4 texColor = particleTexture.sample(particleTextureSmplr, in.fragTexCoord); - if (texColor.w < 0.00999999977648258209228515625) - { - discard_fragment(); - } - out.FragColor = texColor * in.fragColor; - } - else - { - float2 center = float2(0.5); - float dist = distance(in.fragTexCoord, center); - float alpha = 1.0 - smoothstep(0.300000011920928955078125, 0.5, dist); - out.FragColor = float4(in.fragColor.xyz, in.fragColor.w * alpha); - if (out.FragColor.w < 0.00999999977648258209228515625) - { - discard_fragment(); - } - } - return out; -} - -)", -}; -static const AtlasPackedShaderSource PARTICLE_FRAG = {PARTICLE_FRAG_PARTS, 1}; - -static const char* const PARTICLE_VERT_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct UniformBufferObject -{ - float4x4 view; - float4x4 projection; - float4x4 model; - uint isAmbient; -}; - -struct main0_out -{ - float2 fragTexCoord [[user(locn0)]]; - float4 fragColor [[user(locn1)]]; - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float3 quadVertex [[attribute(0)]]; - float2 texCoord [[attribute(1)]]; - float3 particlePos [[attribute(2)]]; - float4 particleColor [[attribute(3)]]; - float particleSize [[attribute(4)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]], constant UniformBufferObject& _12 [[buffer(0)]]) -{ - main0_out out = {}; - if (_12.isAmbient != 0u) - { - float4 viewParticlePos = _12.view * float4(in.particlePos, 1.0); - float3 viewPosition = viewParticlePos.xyz + float3(in.quadVertex.x * in.particleSize, in.quadVertex.y * in.particleSize, 0.0); - out.gl_Position = (_12.projection * _12.model) * float4(viewPosition, 1.0); - } - else - { - float3 cameraRight = float3(_12.view[0].x, _12.view[1].x, _12.view[2].x); - float3 cameraUp = float3(_12.view[0].y, _12.view[1].y, _12.view[2].y); - float3 worldPosition = (in.particlePos + ((cameraRight * in.quadVertex.x) * in.particleSize)) + ((cameraUp * in.quadVertex.y) * in.particleSize); - out.gl_Position = (_12.projection * _12.view) * float4(worldPosition, 1.0); - } - out.fragTexCoord = in.texCoord; - out.fragColor = in.particleColor; - return out; -} - -)", -}; -static const AtlasPackedShaderSource PARTICLE_VERT = {PARTICLE_VERT_PARTS, 1}; - -static const char* const PATH_PARTS[] = { -R"(#include -#include -using namespace metal; -using namespace raytracing; - -struct CameraUniforms { - float4x4 invViewProj; - float4x4 prevViewProj; - float3 camPos; - float _pad0; -}; - -struct Material { - float4 albedo; - float metallic; - float roughness; - float ao; - float emissiveIntensity; - packed_float3 emissiveColor; - float _pad0; - int albedoTextureIndex; - int normalTextureIndex; - int metallicTextureIndex; - int roughnessTextureIndex; - int aoTextureIndex; - int opacityTextureIndex; - float _pad1[2]; - - float transmittance; - float ior; - float reflectivity; - float _pad2; - packed_float2 textureScale; - packed_float2 textureOffset; -}; - -static_assert(sizeof(Material) == 112); -static_assert(__builtin_offsetof(Material, emissiveColor) == 32); -static_assert(__builtin_offsetof(Material, albedoTextureIndex) == 48); -static_assert(__builtin_offsetof(Material, transmittance) == 80); -static_assert(__builtin_offsetof(Material, textureScale) == 96); - -struct VertexData { - packed_float3 position; - packed_float3 normal; - packed_float2 uv; - packed_float3 tangent; - packed_float3 bitangent; -}; - -struct InstanceData { - float4x4 model; - float4 normalCol0; - float4 normalCol1; - float4 normalCol2; -}; - -struct DirectionalLightData { - float3 direction; - float intensity; - float3 color; - float _pad0; -}; - -struct PointLight { - packed_float3 position; - float intensity; - packed_float3 color; - float range; -}; - -struct SpotLight { - packed_float3 position; - float intensity; - - packed_float3 direction; - float innerCos; - packed_float3 color; - float outerCos; - - float range; - float _pad0[3]; -}; - -struct AreaLight { - packed_float3 position; - float intensity; - - packed_float3 right; - float halfWidth; - - packed_float3 up; - float halfHeight; - - packed_float3 color; - float twoSided; -}; - -struct EmissiveTriangle { - float4 p0; - float4 p1; - float4 p2; - float4 normal; - packed_float3 emission; - float area; - float cdf; - float selectionPdf; - float2 _pad; -}; - -static_assert(sizeof(EmissiveTriangle) == 96); - -struct SceneData { - uint numDirectionalLights; - uint numPointLights; - uint numSpotLights; - uint numAreaLights; - - uint frameIndex; - uint raysPerPixel; - uint maxBounces; - float indirectStrength; - float ambientIntensity; - uint materialTextureCount; - uint atmosphereEnabled; - float atmosphereSunSize; - float3 atmosphereSunDirection; - float atmosphereSunIntensity; - float3 atmosphereSunColor; - uint pixelStride; - float3 ambientColor; - uint environmentEnabled; - uint accumulationFrameLimit; - float fireflyClamp; - uint numEmissiveTriangles; - float bloomThreshold; -}; - -static_assert(sizeof(SceneData) == 160); -static_assert(__builtin_offsetof(SceneData, atmosphereSunDirection) == 48); -static_assert(__builtin_offsetof(SceneData, atmosphereSunIntensity) == 64); -static_assert(__builtin_offsetof(SceneData, atmosphereSunColor) == 80); -static_assert(__builtin_offsetof(SceneData, pixelStride) == 96); -static_assert(__builtin_offsetof(SceneData, ambientColor) == 112); -static_assert(__builtin_offsetof(SceneData, accumulationFrameLimit) == 132); -static_assert(__builtin_offsetof(SceneData, numEmissiveTriangles) == 140); -static_assert(__builtin_offsetof(SceneData, bloomThreshold) == 144); - -float pow5(float x) { - float x2 = x * x; - return x2 * x2 * x; -} - -float luminance(float3 c) { return dot(c, float3(0.2126, 0.7152, 0.0722)); } - -float powerHeuristic(float pdfA, float pdfB) { - float a2 = pdfA * pdfA; - float b2 = pdfB * pdfB; - return a2 / max(a2 + b2, 1e-8); -} - -float3 clampLuminance(float3 c, float maxL) { - float l = luminance(c); - if (l > maxL && l > 1e-6) { - c *= maxL / l; - } - return c; -} - -uint wang_hash(uint s) { - s = (s ^ 61u) ^ (s >> 16u); - s *= 9u; - s = s ^ (s >> 4u); - s *= 0x27d4eb2du; - s = s ^ (s >> 15u); - return s; -} - -float rand(thread uint &state) { - state = wang_hash(state); - return float(state) / 4294967296.0; -} - -uint seedBase(uint2 gid, uint w, uint frame, uint sampleIndex) { - return gid.x + gid.y * w + frame * 9781u + sampleIndex * 6271u + 1u; -} - -constexpr sampler skyboxSampler(coord::normalized, address::clamp_to_edge, - filter::linear, mip_filter::linear); - -float3 skyColor(float3 dir, float intensity, texturecube skybox, - constant SceneData &sceneData) { - float3 sampleDir = dir; - float len2 = dot(sampleDir, sampleDir); - if (len2 > 1e-10) { - sampleDir *= rsqrt(len2); - } else { - sampleDir = float3(0.0, 1.0, 0.0); - } - float3 sky = skybox.sample(skyboxSampler, sampleDir).xyz; - if (sceneData.atmosphereEnabled != 0) { - float horizon = pow(clamp(1.0 - abs(sampleDir.y), 0.0, 1.0), 4.0); - float daylight = smoothstep(-0.2, 0.15, - sceneData.atmosphereSunDirection.y); - float3 zenith = float3(0.08, 0.28, 0.65); - float3 horizonColor = float3(0.58, 0.72, 0.92); - float3 proceduralSky = mix(zenith, horizonColor, horizon) * - max(daylight, 0.08); - sky = max(sky, proceduralSky); - } - if (sceneData.atmosphereEnabled != 0 && - sceneData.atmosphereSunDirection.y > -0.15) { - float3 sunDirection = sceneData.atmosphereSunDirection; - float sunDirectionLength = dot(sunDirection, sunDirection); - sunDirection = sunDirectionLength > 1e-10 - ? sunDirection * rsqrt(sunDirectionLength) - : float3(0.0, 1.0, 0.0); - float sunDot = dot(sampleDir, sunDirection); - float sizeAdjust = - 1.0 - (sceneData.atmosphereSunSize - 1.0) * 0.001; - float sunSize = 0.9995 * sizeAdjust; - float sunGlowSize = - 0.998 * (1.0 - (sceneData.atmosphereSunSize - 1.0) * 0.003); - float sunHaloSize = - 0.99 * (1.0 - (sceneData.atmosphereSunSize - 1.0) * 0.015); - float sunDisk = smoothstep(sunSize - 0.0002, sunSize, sunDot); - float sunGlow = - smoothstep(sunGlowSize, sunSize, sunDot) * (1.0 - sunDisk); - float sunHalo = smoothstep(sunHaloSize, sunSize, sunDot) * - (1.0 - smoothstep(sunSize, sunGlowSize, sunDot)); - float horizonFade = smoothstep( - -0.15, 0.05, sceneData.atmosphereSunDirection.y); - float sunIntensity = max(sceneData.atmosphereSunIntensity, 0.05); - sky += sceneData.atmosphereSunColor * - (sunDisk * 5.0 + sunGlow * 0.5 + sunHalo) * horizonFade * - sunIntensity; - } - float scale = intensity > 0.0 ? intensity : 1.0; - return sky * scale; -} - -float3 cosineSampleHemisphere(float2 u) { - float r = sqrt(u.x); - float theta = 2.0 * M_PI_F * u.y; - - float x = r * cos(theta); - float y = r * sin(theta); - float z = sqrt(max(0.0, 1.0 - u.x)); - - return float3(x, y, z); -} - -float3x3 buildOrthonormalBasis(float3 N) { - float3 T = normalize(abs(N.x) > 0.1 ? cross(float3(0, 1, 0), N) - : cross(float3(1, 0, 0), N)); - float3 B = cross(N, T); - return float3x3(T, B, N); -} - -float3 normalizeOr(float3 v, float3 fallback) { - float len2 = dot(v, v); - if (len2 > 1e-10) { - return v * rsqrt(len2); - } - return fallback; -} - -float rayOffsetDistance(float3 position) { - float positionScale = - max(abs(position.x), max(abs(position.y), abs(position.z))); - return max(0.0002, positionScale * 0.000002); -} - -float3 offsetRayOrigin(float3 position, float3 geometricNormal, - float3 direction) { - float side = dot(direction, geometricNormal) >= 0.0 ? 1.0 : -1.0; - return position + geometricNormal * (rayOffsetDistance(position) * side); -} - -float2 encodeNormal(float3 normal) { - normal /= max(abs(normal.x) + abs(normal.y) + abs(normal.z), 1e-6); - float2 encoded = normal.xy; - if (normal.z < 0.0) { - float2 signValue = select(float2(-1.0), float2(1.0), encoded >= 0.0); - encoded = (1.0 - a)", -R"(bs(encoded.yx)) * signValue; - } - return encoded; -} - -constexpr sampler materialTexSampler(coord::normalized, address::repeat, - filter::linear, mip_filter::linear); - -#define PT_MATERIAL_TEXTURE_PARAMS \ - texture2d materialTexture0, texture2d materialTexture1, \ - texture2d materialTexture2, texture2d materialTexture3, \ - texture2d materialTexture4, texture2d materialTexture5, \ - texture2d materialTexture6, texture2d materialTexture7, \ - texture2d materialTexture8, texture2d materialTexture9, \ - texture2d materialTexture10, \ - texture2d materialTexture11, \ - texture2d materialTexture12, \ - texture2d materialTexture13, \ - texture2d materialTexture14, \ - texture2d materialTexture15, \ - texture2d materialTexture16, \ - texture2d materialTexture17, \ - texture2d materialTexture18, \ - texture2d materialTexture19, \ - texture2d materialTexture20, \ - texture2d materialTexture21, \ - texture2d materialTexture22, \ - texture2d materialTexture23, \ - texture2d materialTexture24, \ - texture2d materialTexture25, \ - texture2d materialTexture26, \ - texture2d materialTexture27, \ - texture2d materialTexture28, \ - texture2d materialTexture29, \ - texture2d materialTexture30, \ - texture2d materialTexture31, \ - texture2d materialTexture32, \ - texture2d materialTexture33, \ - texture2d materialTexture34, \ - texture2d materialTexture35, \ - texture2d materialTexture36, \ - texture2d materialTexture37, \ - texture2d materialTexture38, \ - texture2d materialTexture39, \ - texture2d materialTexture40, \ - texture2d materialTexture41, \ - texture2d materialTexture42, \ - texture2d materialTexture43, \ - texture2d materialTexture44, \ - texture2d materialTexture45, \ - texture2d materialTexture46, texture2d materialTexture47 - -#define PT_MATERIAL_TEXTURE_ARGS \ - materialTexture0, materialTexture1, materialTexture2, materialTexture3, \ - materialTexture4, materialTexture5, materialTexture6, \ - materialTexture7, materialTexture8, materialTexture9, \ - materialTexture10, materialTexture11, materialTexture12, \ - materialTexture13, materialTexture14, materialTexture15, \ - materialTexture16, materialTexture17, materialTexture18, \ - materialTexture19, materialTexture20, materialTexture21, \ - materialTexture22, materialTexture23, materialTexture24, \ - materialTexture25, materialTexture26, materialTexture27, \ - materialTexture28, materialTexture29, materialTexture30, \ - materialTexture31, materialTexture32, materialTexture33, \ - materialTexture34, materialTexture35, materialTexture36, \ - materialTexture37, materialTexture38, materialTexture39, \ - materialTexture40, materialTexture41, materialTexture42, \ - materialTexture43, materialTexture44, materialTexture45, \ - materialTexture46, materialTexture47 - -#define PT_MATERIAL_TEXTURE_BINDINGS \ - texture2d materialTexture0 [[texture(12)]], \ - texture2d materialTexture1 [[texture(13)]], \ - texture2d materialTexture2 [[texture(14)]], \ - texture2d materialTexture3 [[texture(15)]], \ - texture2d materialTexture4 [[texture(16)]], \ - texture2d materialTexture5 [[texture(17)]], \ - texture2d materialTexture6 [[texture(18)]], \ - texture2d materialTexture7 [[texture(19)]], \ - texture2d materialTexture8 [[texture(20)]], \ - texture2d materialTexture9 [[texture(21)]], \ - texture2d materialTexture10 [[texture(22)]], \ - texture2d materialTexture11 [[texture(23)]], \ - texture2d materialTexture12 [[texture(24)]], \ - texture2d materialTexture13 [[texture(25)]], \ - texture2d materialTexture14 [[texture(26)]], \ - texture2d materialTexture15 [[texture(27)]], \ - texture2d materialTexture16 [[texture(28)]], \ - texture2d materialTexture17 [[texture(29)]], \ - texture2d materialTexture18 [[texture(30)]], \ - texture2d materialTexture19 [[texture(31)]], \ - texture2d materialTexture20 [[texture(32)]], \ - texture2d materialTexture21 [[texture(33)]], \ - texture2d materialTexture22 [[texture(34)]], \ - texture2d materialTexture23 [[texture(35)]], \ - texture2d materialTexture24 [[texture(36)]], \ - texture2d materialTexture25 [[texture(37)]], \ - texture2d materialTexture26 [[texture(38)]], \ - texture2d materialTexture27 [[texture(39)]], \ - texture2d materialTexture28 [[texture(40)]], \ - texture2d materialTexture29 [[texture(41)]], \ - texture2d materialTexture30 [[texture(42)]], \ - texture2d materialTexture31 [[texture(43)]], \ - texture2d materialTexture32 [[texture(44)]], \ - texture2d materialTexture33 [[texture(45)]], \ - texture2d materialTexture34 [[texture(46)]], \ - texture2d materialTexture35 [[texture(47)]], \ - texture2d materialTexture36 [[texture(48)]], \ - texture2d materialTexture37 [[texture(49)]], \ - )", -R"( texture2d materialTexture38 [[texture(50)]], \ - texture2d materialTexture39 [[texture(51)]], \ - texture2d materialTexture40 [[texture(52)]], \ - texture2d materialTexture41 [[texture(53)]], \ - texture2d materialTexture42 [[texture(54)]], \ - texture2d materialTexture43 [[texture(55)]], \ - texture2d materialTexture44 [[texture(56)]], \ - texture2d materialTexture45 [[texture(57)]], \ - texture2d materialTexture46 [[texture(58)]], \ - texture2d materialTexture47 [[texture(59)]] - -float4 sampleMaterialTexture(int textureIndex, float2 uv, - PT_MATERIAL_TEXTURE_PARAMS) { - switch (textureIndex) { - case 0: - return materialTexture0.sample(materialTexSampler, uv); - case 1: - return materialTexture1.sample(materialTexSampler, uv); - case 2: - return materialTexture2.sample(materialTexSampler, uv); - case 3: - return materialTexture3.sample(materialTexSampler, uv); - case 4: - return materialTexture4.sample(materialTexSampler, uv); - case 5: - return materialTexture5.sample(materialTexSampler, uv); - case 6: - return materialTexture6.sample(materialTexSampler, uv); - case 7: - return materialTexture7.sample(materialTexSampler, uv); - case 8: - return materialTexture8.sample(materialTexSampler, uv); - case 9: - return materialTexture9.sample(materialTexSampler, uv); - case 10: - return materialTexture10.sample(materialTexSampler, uv); - case 11: - return materialTexture11.sample(materialTexSampler, uv); - case 12: - return materialTexture12.sample(materialTexSampler, uv); - case 13: - return materialTexture13.sample(materialTexSampler, uv); - case 14: - return materialTexture14.sample(materialTexSampler, uv); - case 15: - return materialTexture15.sample(materialTexSampler, uv); - case 16: - return materialTexture16.sample(materialTexSampler, uv); - case 17: - return materialTexture17.sample(materialTexSampler, uv); - case 18: - return materialTexture18.sample(materialTexSampler, uv); - case 19: - return materialTexture19.sample(materialTexSampler, uv); - case 20: - return materialTexture20.sample(materialTexSampler, uv); - case 21: - return materialTexture21.sample(materialTexSampler, uv); - case 22: - return materialTexture22.sample(materialTexSampler, uv); - case 23: - return materialTexture23.sample(materialTexSampler, uv); - case 24: - return materialTexture24.sample(materialTexSampler, uv); - case 25: - return materialTexture25.sample(materialTexSampler, uv); - case 26: - return materialTexture26.sample(materialTexSampler, uv); - case 27: - return materialTexture27.sample(materialTexSampler, uv); - case 28: - return materialTexture28.sample(materialTexSampler, uv); - case 29: - return materialTexture29.sample(materialTexSampler, uv); - case 30: - return materialTexture30.sample(materialTexSampler, uv); - case 31: - return materialTexture31.sample(materialTexSampler, uv); - case 32: - return materialTexture32.sample(materialTexSampler, uv); - case 33: - return materialTexture33.sample(materialTexSampler, uv); - case 34: - return materialTexture34.sample(materialTexSampler, uv); - case 35: - return materialTexture35.sample(materialTexSampler, uv); - case 36: - return materialTexture36.sample(materialTexSampler, uv); - case 37: - return materialTexture37.sample(materialTexSampler, uv); - case 38: - return materialTexture38.sample(materialTexSampler, uv); - case 39: - return materialTexture39.sample(materialTexSampler, uv); - case 40: - return materialTexture40.sample(materialTexSampler, uv); - case 41: - return materialTexture41.sample(materialTexSampler, uv); - case 42: - return materialTexture42.sample(materialTexSampler, uv); - case 43: - return materialTexture43.sample(materialTexSampler, uv); - case 44: - return materialTexture44.sample(materialTexSampler, uv); - case 45: - return materialTexture45.sample(materialTexSampler, uv); - case 46: - return materialTexture46.sample(materialTexSampler, uv); - case 47: - return materialTexture47.sample(materialTexSampler, uv); - default: - break; - } - return float4(0.0); -} - -struct MaterialTextureArguments { - array, 256> textures [[id(0)]]; -}; - -float4 sampleMaterialTexture( - int textureIndex, float2 uv, - constant MaterialTextureArguments &materialTextureArguments) { - return materialTextureArguments.textures[textureIndex].sample( - materialTexSampler, uv); -} - -#undef PT_MATERIAL_TEXTURE_PARAMS -#undef PT_MATERIAL_TEXTURE_ARGS -#undef PT_MATERIAL_TEXTURE_BINDINGS -#define PT_MATERIAL_TEXTURE_PARAMS \ - constant MaterialTextureArguments &materialTextureArguments -#define PT_MATERIAL_TEXTURE_ARGS materialTextureArguments -#define PT_MATERIAL_TEXTURE_BINDINGS \ - constant MaterialTextureArguments &materialTextureArguments [[buffer(12)]] - -float resolveMaterialOpacity(Material mat, float2 uv, uint textureCount, - PT_MATERIAL_TEXTURE_PARAMS) { - float opacity = clamp(mat.albedo.w, 0.0, 1.0); - if (mat.opacityTextureIndex >= 0 && - uint(mat.opacityTextureIndex) < textureCount) { - float4 opacitySample = sampleMaterialTexture( - mat.opacityTextureIndex, uv, PT_MATERIAL_TEXTURE_ARGS); - opacity *= mat.opacityTextureIndex == mat.albedoTextureIndex - ? opacitySample.w - : opacitySample.x; - } - return clamp(opacity, 0.0, 1.0); -} - -void resolveMaterialParameters(Material mat, float2 uv, uint textureCount, - PT_MATERIAL_TEXTURE_PARAMS, - thread float3 &albedo, thread float &metallic, - thread float &roughness, thread float &ao, - thread float3 &emissive, thread float &outIor, - thread float &outTransmittance) { - albedo = clamp(mat.albedo.xyz, float3(0.0), float3(1.0)); - metallic = mat.metallic; - roughness = mat.roughness; - ao = mat.ao; - emissive = max(float3(mat.emissiveColor) * - max(mat.emissiveIntensity, 0.0), - float3(0.0)); - - outIor = max(mat.ior, 1.0); - outTransmittance = clamp(mat.transmittance, 0.0, 1.0); - - if (mat.albedoTextureIndex >= 0 && - uint(mat.albedoTextureIndex) < textureCount) { - albedo *= clamp(sampleMaterialTexture(mat.albedoTextureIndex, uv, - PT_MATERIAL_TEXTURE_ARGS) - .xyz, - float3(0.0), float3(1.0)); - } - if (mat.metallicTextureIndex >= 0 && - uint(mat.metallicTextureIndex) < textureCount) { - float4 metallicSample = sampleMaterialTexture( - mat.metallicTextureIndex, uv, PT_MATERIAL_TEXTURE_ARGS); - float metallicValue = metallicSample.x; - if (mat.roughnessTextureIndex == mat.metallicTextureIndex) { - metallicValue = metallicSample.z; - } - metallic *= clamp(metallicValue, 0.0, 1.0); - } - if (mat.roughnessTextureIndex >= 0 && - uint(mat.roughnessTextureIndex) < textureCount) { - float4 roughnessSample = sampleMaterialTexture( - mat.roughnessTextureIndex, uv, PT_MATERIAL_TEXTURE_ARGS); - float roughnessValue = roughnessSample.x; - if (mat.roughnessTextureIndex == mat.metallicTextureIndex) { - roughnessValue = roughnessSample.y; - } - roughness *= clamp(roughnessValue, 0.0, 1.0); - } - if (mat.aoTextureIndex >= 0 && uint(mat.a)", -R"(oTextureIndex) < textureCount) { - ao *= clamp(sampleMaterialTexture(mat.aoTextureIndex, uv, - PT_MATERIAL_TEXTURE_ARGS) - .x, - 0.0, 1.0); - } - - albedo = clamp(albedo, float3(0.0), float3(1.0)); - metallic = clamp(metallic, 0.0, 1.0); - roughness = clamp(roughness, 0.001, 1.0); - ao = clamp(ao, 0.0, 1.0); -} - -float3 resolveShadingNormal(Material mat, float2 uv, float3 localN, - float3 localT, float3 localB, InstanceData inst, - uint textureCount, PT_MATERIAL_TEXTURE_PARAMS) { - float3x3 normalMatrix = - float3x3(inst.normalCol0.xyz, inst.normalCol1.xyz, inst.normalCol2.xyz); - float3 N = normalizeOr(normalMatrix * localN, float3(0.0, 1.0, 0.0)); - - float3 T = normalizeOr((inst.model * float4(localT, 0.0)).xyz, - float3(1.0, 0.0, 0.0)); - float3 B = normalizeOr((inst.model * float4(localB, 0.0)).xyz, - float3(0.0, 0.0, 1.0)); - T = normalizeOr(T - N * dot(N, T), float3(1.0, 0.0, 0.0)); - B = normalizeOr(B - N * dot(N, B), cross(N, T)); - if (dot(cross(T, B), cross(T, B)) <= 1e-10) { - float3x3 basis = buildOrthonormalBasis(N); - T = basis[0]; - B = basis[1]; - } - - bool useNormalMap = mat._pad1[0] != 0; - float normalStrength = max(mat._pad0, 0.0f); - if (useNormalMap && normalStrength > 0.0 && mat.normalTextureIndex >= 0 && - uint(mat.normalTextureIndex) < textureCount) { - float3 tangentNormal = sampleMaterialTexture(mat.normalTextureIndex, uv, - PT_MATERIAL_TEXTURE_ARGS) - .xyz; - tangentNormal = tangentNormal * 2.0 - 1.0; - tangentNormal.xy *= normalStrength; - tangentNormal = normalizeOr(tangentNormal, float3(0.0, 0.0, 1.0)); - N = normalizeOr(float3x3(T, B, N) * tangentNormal, N); - } - - return N; -} - -float3 traceShadowVisibility(intersector isect, - primitive_acceleration_structure sceneAS, - float3 P, float3 Ng, float3 L, - float maxDistance, thread uint &rng, - constant Material *materials, - constant uint *primitiveObjects, - constant uint *blasPrimitiveOffsets, - constant VertexData *vertices, - constant uint *indices, - constant InstanceData *instanceData, - constant SceneData &sceneData, - PT_MATERIAL_TEXTURE_PARAMS) { - float shadowBias = rayOffsetDistance(P); - float3 visibility = float3(1.0); - float causticGain = 1.0; - float3 entryNormal = float3(0.0); - uint dielectricObject = 0xFFFFFFFFu; - ray shadowRay; - shadowRay.origin = offsetRayOrigin(P, Ng, L); - shadowRay.direction = L; - shadowRay.min_distance = 0.0; - shadowRay.max_distance = max(maxDistance - shadowBias, shadowBias + 1e-4); - - for (uint alphaStep = 0; alphaStep < 32; ++alphaStep) { - auto shadowHit = isect.intersect(shadowRay, sceneAS); - if (shadowHit.type == intersection_type::none) { - return clampLuminance(visibility * causticGain, 2.5); - } - - uint primitiveIndex = - blasPrimitiveOffsets[shadowHit.geometry_id] + shadowHit.primitive_id; - uint objectIndex = primitiveObjects[primitiveIndex]; - Material material = materials[objectIndex]; - uint i0 = indices[primitiveIndex * 3 + 0]; - uint i1 = indices[primitiveIndex * 3 + 1]; - uint i2 = indices[primitiveIndex * 3 + 2]; - float2 bary = shadowHit.triangle_barycentric_coord; - float b0 = 1.0 - bary.x - bary.y; - float2 uv = float2(vertices[i0].uv) * b0 + - float2(vertices[i1].uv) * bary.x + - float2(vertices[i2].uv) * bary.y; - uv = uv * float2(material.textureScale) + - float2(material.textureOffset); - float opacity = resolveMaterialOpacity( - material, uv, sceneData.materialTextureCount, - PT_MATERIAL_TEXTURE_ARGS); - if (opacity >= 0.999 || rand(rng) < opacity) { - float transmission = clamp(material.transmittance, 0.0, 1.0) * - (1.0 - clamp(material.metallic, 0.0, 1.0)); - if (transmission <= 0.001) { - return float3(0.0); - } - - float3 p0 = float3(vertices[i0].position); - float3 p1 = float3(vertices[i1].position); - float3 p2 = float3(vertices[i2].position); - float3 hitNormal = normalizeOr(cross(p1 - p0, p2 - p0), -L); - hitNormal = dot(hitNormal, L) < 0.0 ? hitNormal : -hitNormal; - float ior = max(material.ior, 1.0); - float dielectricF0 = pow((ior - 1.0) / (ior + 1.0), 2.0); - float fresnel = dielectricF0 + - (1.0 - dielectricF0) * - pow5(1.0 - abs(dot(hitNormal, L))); - float3 tint = mix(float3(1.0), - clamp(material.albedo.xyz, float3(0.0), - float3(1.0)), - 0.15); - visibility *= tint * transmission * (1.0 - fresnel); - if (dielectricObject == objectIndex) { - float curvature = - 1.0 - clamp(abs(dot(entryNormal, hitNormal)), 0.0, 1.0); - float smoothness = - 1.0 - clamp(material.roughness, 0.0, 1.0); - float focus = 1.0 + transmission * max(ior - 1.0, 0.0) * - smoothness * smoothness * - (0.35 + curvature * 3.0); - causticGain *= clamp(focus, 1.0, 2.5); - dielectricObject = 0xFFFFFFFFu; - } else { - dielectricObject = objectIndex; - entryNormal = hitNormal; - } - if (luminance(visibility) <= 0.001) { - return float3(0.0); - } - } - - float advance = shadowHit.distance + rayOffsetDistance(shadowRay.origin); - shadowRay.origin += shadowRay.direction * advance; - shadowRay.max_distance -= advance; - if (shadowRay.max_distance <= shadowBias) { - return clampLuminance(visibility * causticGain, 2.5); - } - } - - return float3(0.0); -} - -float3 sampleDirectionalLightDirection(DirectionalLightData light, - thread uint &rng) { - float3 baseL = normalize(-light.direction); - float3x3 basis = buildOrthonormalBasis(baseL); - float sunRadius = 0.0025; - float2 u = float2(rand(rng), rand(rng)); - float r = sunRadius * sqrt(u.x); - float phi = 2.0 * M_PI_F * u.y; - float3 jittered = - baseL + basis[0] * (r * cos(phi)) + basis[1] * (r * sin(phi)); - return normalize(jittered); -} - -// --------------------------------------------------------------------------- -// PBR helpers: GGX / Cook-Torrance -// --------------------------------------------------------------------------- - -float D_GGX(float NdotH, float roughness) { - float a = max(roughness * roughness, 1e-4); - float a2 = a * a; - float d = (NdotH * NdotH) * (a2 - 1.0) + 1.0; - return a2 / max(M_PI_F * d * d, 1e-6); -} - -float3 F_Schlick(float cosTheta, float3 F0) { - float c = clamp(1.0 - cosTheta, 0.0, 1.0); - return F0 + (1.0 - F0) * pow5(c); -} - -float3 materialF0(float3 albedo, float metallic, float reflectivity, - float ior) { - float dielectricF0 = pow((max(ior, 1.0001) - 1.0) / - (max(ior, 1.0001) + 1.0), - 2.0); - float dielectricScale = mix(0.5, 1.5, clamp(reflectivity, 0.0, 1.0)); - return mix(float3(clamp(dielectricF0 * dielectricScale, 0.0, 0.16)), - albedo, clamp(metallic, 0.0, 1.0)); -} - -float G_Smith(float NdotV, float NdotL, float roughness) { - float r = roughness + 1.0; - float k = (r * r))", -R"( / 8.0; - float gV = NdotV / (NdotV * (1.0 - k) + k); - float gL = NdotL / (NdotL * (1.0 - k) + k); - return gV * gL; -} - -float G1_SmithGGX(float NdotX, float roughness) { - float alpha = max(roughness * roughness, 1e-4); - float alphaSquared = alpha * alpha; - float cosineSquared = NdotX * NdotX; - return (2.0 * NdotX) / - max(NdotX + - sqrt(alphaSquared + (1.0 - alphaSquared) * cosineSquared), - 1e-6); -} - -float disneyDiffuseFactor(float NdotV, float NdotL, float LdotH, - float roughness) { - float fd90 = 0.5 + 2.0 * LdotH * LdotH * roughness; - float lightScatter = 1.0 + (fd90 - 1.0) * pow5(1.0 - NdotL); - float viewScatter = 1.0 + (fd90 - 1.0) * pow5(1.0 - NdotV); - return lightScatter * viewScatter; -} - -// GGX importance-sampled microfacet half-vector (in local TBN space, Z=up) -float3 sampleGGX(float2 u, float roughness) { - float a = roughness * roughness; - float phi = 2.0 * M_PI_F * u.x; - float cosTheta = sqrt((1.0 - u.y) / max(1.0 + (a * a - 1.0) * u.y, 1e-7)); - float sinTheta = sqrt(max(0.0, 1.0 - cosTheta * cosTheta)); - return float3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); -} - -float3 sampleGGXVNDF(float3 localView, float roughness, float2 u) { - float alpha = max(roughness * roughness, 1e-3); - float3 stretchedView = - normalizeOr(float3(alpha * localView.x, alpha * localView.y, - max(localView.z, 1e-5)), - float3(0.0, 0.0, 1.0)); - float lensq = stretchedView.x * stretchedView.x + - stretchedView.y * stretchedView.y; - float3 tangentX = lensq > 1e-7 - ? float3(-stretchedView.y, stretchedView.x, 0.0) * - rsqrt(lensq) - : float3(1.0, 0.0, 0.0); - float3 tangentY = cross(stretchedView, tangentX); - float radius = sqrt(u.x); - float phi = 2.0 * M_PI_F * u.y; - float diskX = radius * cos(phi); - float diskY = radius * sin(phi); - float blend = 0.5 * (1.0 + stretchedView.z); - diskY = mix(sqrt(max(0.0, 1.0 - diskX * diskX)), diskY, blend); - float diskZ = sqrt(max(0.0, 1.0 - diskX * diskX - diskY * diskY)); - float3 visibleNormal = diskX * tangentX + diskY * tangentY + - diskZ * stretchedView; - return normalizeOr(float3(alpha * visibleNormal.x, - alpha * visibleNormal.y, - max(visibleNormal.z, 0.0)), - float3(0.0, 0.0, 1.0)); -} - -// Full Cook-Torrance PBR for a single analytic light -float3 evalPBR(float3 albedo, float metallic, float roughness, - float reflectivity, float ior, float transmittance, float3 N, - float3 V, float3 L, float3 lightColor, float intensity) { - float3 H = normalize(V + L); - float NdotL = max(dot(N, L), 0.0); - float NdotV = max(dot(N, V), 1e-4); - float NdotH = max(dot(N, H), 0.0); - float VdotH = max(dot(V, H), 0.0); - - float clampedRoughness = clamp(roughness, 0.045, 1.0); - float3 F0 = materialF0(albedo, metallic, reflectivity, ior); - float3 F = F_Schlick(VdotH, F0); - float D = D_GGX(NdotH, clampedRoughness); - float G = G_Smith(NdotV, NdotL, clampedRoughness); - - float3 specular = (D * G * F) / max(4.0 * NdotV * NdotL, 1e-4); - float3 kD = (1.0 - F) * (1.0 - clamp(metallic, 0.0, 1.0)) * - (1.0 - clamp(transmittance, 0.0, 1.0)); - float diffuseFactor = disneyDiffuseFactor(NdotV, NdotL, max(dot(L, H), 0.0), - clampedRoughness); - float3 diffuse = (kD * albedo * diffuseFactor) / M_PI_F; - - return (diffuse + specular) * lightColor * intensity * NdotL; -} - -float3 evalSubsurface(float3 albedo, float3 N, float3 V, float3 L, - float3 lightColor, float intensity, float roughness, - float sssStrength, float sssThickness) { - float NdotL = dot(N, L); - float NdotV = max(dot(N, V), 0.0); - float backLit = clamp(-NdotL, 0.0, 1.0); - float wrapAmount = mix(0.2, 0.7, clamp(roughness, 0.0, 1.0)); - float wrapped = clamp((NdotL + wrapAmount) / (1.0 + wrapAmount), 0.0, 1.0); - float viewScatter = pow(clamp(1.0 - max(dot(V, L), 0.0), 0.0, 1.0), 2.0); - float transmission = backLit * (0.35 + 0.65 * viewScatter); - float diffuseBleed = wrapped * (0.5 + 0.5 * (1.0 - NdotV)); - float profile = mix(diffuseBleed, transmission, 0.65); - float thicknessFalloff = exp(-max(sssThickness, 0.01) * (1.0 - backLit)); - return (albedo * lightColor * intensity * sssStrength * profile * - thicknessFalloff) / - M_PI_F; -} - -float3 evalTransmission(float3 albedo, float3 N, float3 V, float3 L, - float3 lightColor, float intensity, float roughness, - float ior) { - float backLighting = max(dot(N, -L), 0.0); - float forwardAlignment = max(dot(-V, L), 0.0); - float3 F0 = float3(pow((ior - 1.0) / (ior + 1.0), 2.0)); - float3 F = F_Schlick(max(dot(N, V), 0.0), F0); - float3 transmitTint = mix(float3(1.0), albedo, 0.1); - float lobeExponent = mix(96.0, 2.0, sqrt(clamp(roughness, 0.0, 1.0))); - float transmissionLobe = pow(forwardAlignment, lobeExponent); - return (1.0 - F) * transmitTint * lightColor * intensity * backLighting * - transmissionLobe; -} - -float3 evalEmissiveTriangleLighting( - intersector isect, - primitive_acceleration_structure sceneAS, float3 P, float3 N, float3 Ng, - float3 V, float3 albedo, float metallic, float roughness, - float reflectivity, float ior, float transmittance, thread uint &rng, - constant SceneData &sceneData, - constant EmissiveTriangle *emissiveTriangles, - constant Material *materials, constant uint *primitiveObjects, - constant uint *blasPrimitiveOffsets, constant VertexData *vertices, - constant uint *indices, constant InstanceData *instanceData, - PT_MATERIAL_TEXTURE_PARAMS) { - if (sceneData.numEmissiveTriangles == 0) { - return float3(0.0); - } - float selector = rand(rng); - uint first = 0; - uint last = sceneData.numEmissiveTriangles - 1; - while (first < last) { - uint middle = first + (last - first) / 2; - if (selector <= emissiveTriangles[middle].cdf) { - last = middle; - } else { - first = middle + 1; - } - } - EmissiveTriangle light = emissiveTriangles[first]; - float sqrtU = sqrt(rand(rng)); - float barycentricV = rand(rng); - float b0 = 1.0 - sqrtU; - float b1 = sqrtU * (1.0 - barycentricV); - float b2 = sqrtU * barycentricV; - float3 lightPosition = light.p0.xyz * b0 + light.p1.xyz * b1 + - light.p2.xyz * b2; - float3 toLight = lightPosition - P; - float distanceSquared = dot(toLight, toLight); - if (distanceSquared <= 1e-8) { - return float3(0.0); - } - float distanceToLight = sqrt(distanceSquared); - float3 L = toLight / distanceToLight; - float surfaceCosine = dot(N, L); - float lightCosine = abs(dot(light.normal.xyz, -L)); - if (surfaceCosine <= 0.0 || dot(Ng, L) <= 0.0 || - lightCosine <= 1e-5 || light.area <= 1e-8 || - light.selectionPdf <= 1e-8) { - return float3(0.0); - } - float solidAnglePdf = light.selectionPdf * distanceSquared / - max(lightCosine * light.area, 1e-8); - float3 visibility = traceShadowVisibility( - isect, sceneAS, P, Ng, L, distanceToLight, rng, materials, - primitiveObjects, blasPrimitiveOffsets, vertices, indices, - instanceData, sceneData, PT_MATERIAL_TEXTURE_ARGS); - return evalPBR(albedo, metallic, roughness, reflectivity, ior, - transmittance, N, V, L, light.emission, - 1.0 / max(solidAnglePdf, 1e-8)) * - visibility; -} - -// --------------------------------------------------------------------------- -// Direct lighting with full PBR (replaces old evalDirectLighting) -// --------------------------------------------------------------------------- - -float3 evalDirectLightingPBR(intersector isect, - primitive_acceleration_structure )", -R"(sceneAS, float3 P, - float3 N, float3 Ng, float3 V, float3 albedo, - float metallic, float roughness, float reflectivity, - float ior, float transmittance, float sssStrength, - float sssThickness, - thread uint &rng, - constant DirectionalLightData &dirLight, - constant SceneData &sceneData, - constant PointLight *pointLights, - constant SpotLight *spotLights, - constant AreaLight *areaLights, - constant EmissiveTriangle *emissiveTriangles, - constant Material *materials, - constant uint *primitiveObjects, - constant uint *blasPrimitiveOffsets, - constant VertexData *vertices, - constant uint *indices, - constant InstanceData *instanceData, - PT_MATERIAL_TEXTURE_PARAMS) { - float3 lighting = float3(0.0); - // Directional - if (sceneData.numDirectionalLights > 0) { - float3 L = sampleDirectionalLightDirection(dirLight, rng); - float3 c = evalPBR(albedo, metallic, roughness, reflectivity, ior, - transmittance, N, V, L, dirLight.color, - max(dirLight.intensity, 0.0)); - float3 s = evalSubsurface(albedo, N, V, L, dirLight.color, - max(dirLight.intensity, 0.0), roughness, - sssStrength, sssThickness); - float3 visibility = traceShadowVisibility( - isect, sceneAS, P, Ng, L, 1e30, rng, materials, primitiveObjects, - blasPrimitiveOffsets, vertices, indices, instanceData, sceneData, - PT_MATERIAL_TEXTURE_ARGS); - lighting += (c + s * (1.0 - transmittance)) * visibility; - } - - // Point lights - for (uint i = 0; i < sceneData.numPointLights; ++i) { - float3 sampledPosition = pointLights[i].position; - float3 toLight = sampledPosition - P; - float dist = max(length(toLight), 1e-4); - float3 L = toLight / dist; - float lightRange = max(pointLights[i].range, 1e-4); - float minDist = max(lightRange * 0.08, 0.15); - float distSq = dist * dist + minDist * minDist; - float rangeFade = 1.0 - smoothstep(lightRange * 0.75, lightRange, dist); - float atten = rangeFade / max(distSq, 1e-4); - float intensity = max(pointLights[i].intensity, 0.0) * atten; - float3 c = evalPBR(albedo, metallic, roughness, reflectivity, ior, - transmittance, N, V, L, pointLights[i].color, - intensity); - float3 s = - evalSubsurface(albedo, N, V, L, pointLights[i].color, intensity, - roughness, sssStrength, sssThickness); - float3 visibility = traceShadowVisibility( - isect, sceneAS, P, Ng, L, dist, rng, materials, primitiveObjects, - blasPrimitiveOffsets, vertices, indices, instanceData, sceneData, - PT_MATERIAL_TEXTURE_ARGS); - lighting += (c + s * (1.0 - transmittance)) * visibility; - } - - // Spot lights - for (uint i = 0; i < sceneData.numSpotLights; ++i) { - float3 sampledPosition = spotLights[i].position; - float3 toLight = sampledPosition - P; - float dist = max(length(toLight), 1e-4); - float3 L = toLight / dist; - float3 fwd = normalize(spotLights[i].direction); - float spotCos = dot(-L, fwd); - float spot = - smoothstep(spotLights[i].outerCos, spotLights[i].innerCos, spotCos); - float lightRange = max(spotLights[i].range, 1e-4); - float minDist = max(lightRange * 0.08, 0.15); - float distSq = dist * dist + minDist * minDist; - float rangeFade = 1.0 - smoothstep(lightRange * 0.75, lightRange, dist); - float atten = rangeFade / max(distSq, 1e-4); - float intensity = max(spotLights[i].intensity, 0.0) * atten * spot; - float3 c = evalPBR(albedo, metallic, roughness, reflectivity, ior, - transmittance, N, V, L, spotLights[i].color, - intensity); - float3 s = - evalSubsurface(albedo, N, V, L, spotLights[i].color, intensity, - roughness, sssStrength, sssThickness); - float3 visibility = traceShadowVisibility( - isect, sceneAS, P, Ng, L, dist, rng, materials, primitiveObjects, - blasPrimitiveOffsets, vertices, indices, instanceData, sceneData, - PT_MATERIAL_TEXTURE_ARGS); - lighting += (c + s * (1.0 - transmittance)) * visibility; - } - - // Area lights - for (uint i = 0; i < sceneData.numAreaLights; ++i) { - float2 lightSample = float2(rand(rng), rand(rng)) * 2.0 - 1.0; - float3 sampledPosition = - areaLights[i].position + - areaLights[i].right * (lightSample.x * areaLights[i].halfWidth) + - areaLights[i].up * (lightSample.y * areaLights[i].halfHeight); - float3 toLight = sampledPosition - P; - float dist = max(length(toLight), 1e-4); - float3 L = toLight / dist; - float3 lightNorm = - normalize(cross(areaLights[i].right, areaLights[i].up)); - float cosLight = areaLights[i].twoSided > 0.5 - ? abs(dot(lightNorm, -L)) - : max(dot(lightNorm, -L), 0.0); - float area = 4.0 * areaLights[i].halfWidth * areaLights[i].halfHeight; - float lightPdfArea = 1.0 / max(area, 1e-6); - float distSq = max(dist * dist, 1e-6); - float atten = cosLight / max(distSq * lightPdfArea, 1e-6); - float intensity = max(areaLights[i].intensity, 0.0) * atten; - float3 c = evalPBR(albedo, metallic, roughness, reflectivity, ior, - transmittance, N, V, L, areaLights[i].color, - intensity); - float3 s = - evalSubsurface(albedo, N, V, L, areaLights[i].color, intensity, - roughness, sssStrength, sssThickness); - float3 visibility = traceShadowVisibility( - isect, sceneAS, P, Ng, L, dist, rng, materials, primitiveObjects, - blasPrimitiveOffsets, vertices, indices, instanceData, sceneData, - PT_MATERIAL_TEXTURE_ARGS); - lighting += (c + s * (1.0 - transmittance)) * visibility; - } - - lighting += evalEmissiveTriangleLighting( - isect, sceneAS, P, N, Ng, V, albedo, metallic, roughness, - reflectivity, ior, transmittance, rng, sceneData, emissiveTriangles, - materials, primitiveObjects, blasPrimitiveOffsets, vertices, indices, - instanceData, PT_MATERIAL_TEXTURE_ARGS); - - return lighting; -} - -// --------------------------------------------------------------------------- -// sampleRadiance — iterative path with GGX importance-sampled indirect bounces -// --------------------------------------------------------------------------- - -float3 sampleRadiance(uint2 gid, uint sampleIndex, uint w, - intersector isect, - primitive_acceleration_structure sceneAS, ray primaryRay, - constant Material *materials, - constant uint *primitiveObjects, - constant uint *blasPrimitiveOffsets, - constant VertexData *vertices, constant uint *indices, - constant InstanceData *instanceData, - constant DirectionalLightData &dirLight, - constant SceneData &sceneData, - constant PointLight *pointLights, - constant SpotLight *spotLights, - constant AreaLight *areaLights, - constant EmissiveTriangle *emissiveTriangles, - PT_MATERIAL_TEXTURE_PARAMS, texturecube skybox, - thread float3 &primaryAlbedo, - )", -R"(thread float3 &primaryNormal, - thread float3 &primaryPosition, - thread float &primaryDepth, - thread float &primaryRoughness, - thread float &primaryHitDistance, - thread uint &primaryObjectId) { - uint rng = seedBase(gid, w, sceneData.frameIndex, sampleIndex); - uint bounceLimit = min(sceneData.maxBounces, 16u); - ray surfaceRay = primaryRay; - float3 radiance = float3(0.0); - float3 throughput = float3(1.0); - float previousBsdfPdf = 0.0; - float previousEnvironmentPdf = 0.0; - bool previousEventWasDelta = true; - - for (uint depth = 0; depth <= bounceLimit; ++depth) { - auto hit = isect.intersect(surfaceRay, sceneAS); - Material mat{}; - InstanceData inst{}; - uint surfaceObjectIndex = 0xFFFFFFFFu; - float2 texUV = float2(0.0); - float3 localN = float3(0.0, 1.0, 0.0); - float3 localT = float3(1.0, 0.0, 0.0); - float3 localB = float3(0.0, 0.0, 1.0); - float3 geometricNormal = float3(0.0, 1.0, 0.0); - bool foundSurface = false; - - for (uint alphaStep = 0; alphaStep < 16; ++alphaStep) { - if (hit.type == intersection_type::none) { - break; - } - - uint primitiveIndex = - blasPrimitiveOffsets[hit.geometry_id] + hit.primitive_id; - surfaceObjectIndex = primitiveObjects[primitiveIndex]; - mat = materials[surfaceObjectIndex]; - inst = instanceData[surfaceObjectIndex]; - - uint i0 = indices[primitiveIndex * 3 + 0]; - uint i1 = indices[primitiveIndex * 3 + 1]; - uint i2 = indices[primitiveIndex * 3 + 2]; - float2 bary = hit.triangle_barycentric_coord; - float b0 = 1.0 - bary.x - bary.y; - float b1 = bary.x; - float b2 = bary.y; - - texUV = float2(vertices[i0].uv) * b0 + - float2(vertices[i1].uv) * b1 + - float2(vertices[i2].uv) * b2; - texUV = texUV * float2(mat.textureScale) + - float2(mat.textureOffset); - localN = normalizeOr(float3(vertices[i0].normal) * b0 + - float3(vertices[i1].normal) * b1 + - float3(vertices[i2].normal) * b2, - float3(0.0, 1.0, 0.0)); - localT = normalizeOr(float3(vertices[i0].tangent) * b0 + - float3(vertices[i1].tangent) * b1 + - float3(vertices[i2].tangent) * b2, - float3(1.0, 0.0, 0.0)); - localB = normalizeOr(float3(vertices[i0].bitangent) * b0 + - float3(vertices[i1].bitangent) * b1 + - float3(vertices[i2].bitangent) * b2, - float3(0.0, 0.0, 1.0)); - float3 p0 = float3(vertices[i0].position); - float3 p1 = float3(vertices[i1].position); - float3 p2 = float3(vertices[i2].position); - float3x3 normalMatrix = float3x3( - inst.normalCol0.xyz, inst.normalCol1.xyz, inst.normalCol2.xyz); - geometricNormal = normalizeOr( - cross(p1 - p0, p2 - p0), - normalizeOr(normalMatrix * localN, float3(0.0, 1.0, 0.0))); - - float alpha = resolveMaterialOpacity( - mat, texUV, sceneData.materialTextureCount, - PT_MATERIAL_TEXTURE_ARGS); - if (alpha >= 0.999 || rand(rng) < alpha) { - foundSurface = true; - break; - } - - float3 rejectedPosition = - surfaceRay.origin + surfaceRay.direction * hit.distance; - surfaceRay.origin = - rejectedPosition + surfaceRay.direction * - rayOffsetDistance(rejectedPosition); - surfaceRay.min_distance = 0.0; - hit = isect.intersect(surfaceRay, sceneAS); - } - - if (!foundSurface) { - float misWeight = previousEventWasDelta - ? 1.0 - : powerHeuristic(previousBsdfPdf, - previousEnvironmentPdf); - radiance += throughput * misWeight * - skyColor(surfaceRay.direction, 0.0, skybox, sceneData); - break; - } - - float3 shadingNormal = resolveShadingNormal( - mat, texUV, localN, localT, localB, inst, - sceneData.materialTextureCount, PT_MATERIAL_TEXTURE_ARGS); - float3 P = surfaceRay.origin + surfaceRay.direction * hit.distance; - float3 V = normalize(-surfaceRay.direction); - bool frontFace = dot(geometricNormal, V) >= 0.0; - float3 Ng = frontFace ? geometricNormal : -geometricNormal; - float3 N = dot(shadingNormal, Ng) >= 0.0 ? shadingNormal : -shadingNormal; - float shadingNormalCosine = dot(N, Ng); - if (shadingNormalCosine < 0.1) { - N = normalizeOr(N + Ng * (0.1 - shadingNormalCosine), Ng); - } - - float3 albedo; - float metallic; - float roughness; - float ao; - float3 emissive; - float ior; - float transmittance; - resolveMaterialParameters(mat, texUV, sceneData.materialTextureCount, - PT_MATERIAL_TEXTURE_ARGS, albedo, metallic, - roughness, ao, emissive, ior, transmittance); - - if (depth == 0) { - primaryAlbedo = albedo; - primaryNormal = N; - primaryPosition = P; - primaryDepth = length(P - primaryRay.origin); - primaryRoughness = roughness; - primaryHitDistance = hit.distance; - primaryObjectId = surfaceObjectIndex; - } - - float reflectivity = clamp(mat.reflectivity, 0.0, 1.0); - float sssStrength = 0.0; - float sssThickness = mix(0.25, 1.75, ao); - float3 direct = evalDirectLightingPBR( - isect, sceneAS, P, N, Ng, V, albedo, metallic, roughness, - reflectivity, ior, transmittance, sssStrength, sssThickness, rng, - dirLight, sceneData, pointLights, spotLights, areaLights, - emissiveTriangles, materials, primitiveObjects, - blasPrimitiveOffsets, vertices, indices, instanceData, - PT_MATERIAL_TEXTURE_ARGS); - radiance += throughput * direct; - if (depth == 0 || previousEventWasDelta || - sceneData.numEmissiveTriangles == 0) { - radiance += throughput * emissive; - } - - if (depth == 0 && sceneData.ambientIntensity > 0.0) { - float aoVisibility = mix(0.2, 1.0, ao); - float dielectricF0 = pow((ior - 1.0) / (ior + 1.0), 2.0); - float3 ambientF0 = mix(float3(dielectricF0), albedo, metallic); - float3 ambientF = F_Schlick(max(dot(N, V), 0.0), ambientF0); - float3 ambientDiffuse = (1.0 - ambientF) * (1.0 - metallic) * - albedo * (1.0 - transmittance); - float3 ambientSpecular = ambientF * mix(1.0, 0.35, roughness) * - (1.0 - transmittance); - float3 ambient = (ambientDiffuse + ambientSpecular) * - sceneData.ambientColor * - sceneData.ambientIntensity * aoVisibility; - radiance += throughput * ambient; - } - - float dielectricF0 = pow((ior - 1.0) / (ior + 1.0), 2.0); - float3 F0 = materialF0(albedo, metallic, mat.reflectivity, ior); - float NdotV = max(dot(N, V), 1e-4); - float3 viewFresnel = F_Schlick(NdotV, F0); - float fresnelProbability = clamp(luminance(viewFresnel), 0.001, 0.999); - float specProb = fresnelProbability; - float transmitProb = transmittance * (1.0 - metallic) * - (1.0 - fresnelProbability); - float diffuseProb = (1.0 - metallic) * (1.0 - transmittance) * - (1.0 - fresnelProbability); - float eta = )", -R"(frontFace ? 1.0 / ior : ior; - float3 idealRefractedDirection = refract(-V, N, eta); - bool totalInternalReflection = - dot(idealRefractedDirection, idealRefractedDirection) < 1e-8; - if (totalInternalReflection) { - specProb += transmitProb; - transmitProb = 0.0; - } - float probabilitySum = - max(specProb + transmitProb + diffuseProb, 1e-4); - specProb /= probabilitySum; - transmitProb /= probabilitySum; - diffuseProb /= probabilitySum; - - float3x3 basis = buildOrthonormalBasis(N); - if (sceneData.environmentEnabled != 0 && - diffuseProb + specProb > 1e-4) { - float3 localEnvironmentDirection = - cosineSampleHemisphere(float2(rand(rng), rand(rng))); - float3 environmentDirection = - normalizeOr(basis * localEnvironmentDirection, N); - float NdotEnvironment = dot(N, environmentDirection); - if (NdotEnvironment > 0.0 && - dot(Ng, environmentDirection) > 0.0) { - float3 visibility = traceShadowVisibility( - isect, sceneAS, P, Ng, environmentDirection, 1e30, rng, - materials, primitiveObjects, blasPrimitiveOffsets, - vertices, indices, instanceData, sceneData, - PT_MATERIAL_TEXTURE_ARGS); - if (luminance(visibility) <= 0.001) { - visibility = float3(0.0); - } - float3 H = normalizeOr(V + environmentDirection, N); - float NdotH = max(dot(N, H), 1e-5); - float VdotH = max(dot(V, H), 1e-5); - float3 F = F_Schlick(VdotH, F0); - float3 kD = (1.0 - F) * (1.0 - metallic) * - (1.0 - transmittance); - float diffuseFactor = disneyDiffuseFactor( - NdotV, NdotEnvironment, - max(dot(environmentDirection, H), 0.0), roughness); - float3 reflectionBsdf = - kD * albedo * diffuseFactor / M_PI_F; - float environmentPdf = NdotEnvironment / M_PI_F; - float bsdfPdf = diffuseProb * environmentPdf; - if (roughness > 0.025 && specProb > 1e-4) { - float D = D_GGX(NdotH, roughness); - float G1V = G1_SmithGGX(NdotV, roughness); - float G1L = - G1_SmithGGX(NdotEnvironment, roughness); - reflectionBsdf += - D * G1V * G1L * F / - max(4.0 * NdotV * NdotEnvironment, 1e-6); - bsdfPdf += specProb * D * G1V / - max(4.0 * NdotV, 1e-6); - } - float competingBsdfPdf = depth < bounceLimit ? bsdfPdf : 0.0; - float misWeight = - powerHeuristic(environmentPdf, competingBsdfPdf); - float3 environmentRadiance = skyColor( - environmentDirection, 0.0, skybox, sceneData); - radiance += throughput * reflectionBsdf * - environmentRadiance * visibility * NdotEnvironment * - misWeight / max(environmentPdf, 1e-6); - } - } - - if (depth == bounceLimit) { - break; - } - - float choice = rand(rng); - float3 bounceWeight = float3(0.0); - float3 nextDirection = N; - float sampledBsdfPdf = 0.0; - float sampledEnvironmentPdf = 0.0; - bool sampledEventWasDelta = true; - - if (choice < specProb && specProb > 1e-4) { - if (roughness <= 0.025 || totalInternalReflection) { - nextDirection = reflect(-V, N); - float3 F = totalInternalReflection - ? float3(1.0) - : F_Schlick(NdotV, F0); - bounceWeight = F / max(specProb, 1e-4); - } else { - float3 localView = - float3(dot(V, basis[0]), dot(V, basis[1]), dot(V, N)); - float3 localH = sampleGGXVNDF( - localView, roughness, float2(rand(rng), rand(rng))); - float3 H = normalizeOr(basis * localH, N); - float VdotH = max(dot(V, H), 1e-5); - nextDirection = reflect(-V, H); - float NdotL = dot(N, nextDirection); - if (NdotL > 0.0 && dot(nextDirection, Ng) > 0.0) { - float NdotH = max(dot(N, H), 1e-5); - float D = D_GGX(NdotH, roughness); - float G1V = G1_SmithGGX(NdotV, roughness); - float G1L = G1_SmithGGX(NdotL, roughness); - float3 F = F_Schlick(VdotH, F0); - float3 specularBsdf = - D * G1V * G1L * F / - max(4.0 * NdotV * NdotL, 1e-6); - float conditionalPdf = - D * G1V / max(4.0 * NdotV, 1e-6); - float combinedPdf = specProb * conditionalPdf; - bounceWeight = specularBsdf * NdotL / - max(combinedPdf, 1e-6); - sampledBsdfPdf = combinedPdf; - sampledEnvironmentPdf = NdotL / M_PI_F; - sampledEventWasDelta = false; - } - } - } else if (choice < specProb + transmitProb && - transmitProb > 1e-4) { - nextDirection = idealRefractedDirection; - float fresnelCosine = NdotV; - if (roughness > 0.025) { - float3 localView = - float3(dot(V, basis[0]), dot(V, basis[1]), dot(V, N)); - float3 localH = sampleGGXVNDF( - localView, roughness, float2(rand(rng), rand(rng))); - float3 H = normalizeOr(basis * localH, N); - float3 roughRefractedDirection = refract(-V, H, eta); - if (dot(roughRefractedDirection, roughRefractedDirection) > - 1e-8 && - dot(roughRefractedDirection, Ng) < 0.0) { - nextDirection = roughRefractedDirection; - fresnelCosine = max(dot(V, H), 0.0); - } - } - float3 F = F_Schlick(fresnelCosine, float3(dielectricF0)); - float3 tint = mix(float3(1.0), albedo, 0.15); - bounceWeight = (1.0 - F) * tint / - max(transmitProb, 1e-4); - } else { - float3 localDirection = - cosineSampleHemisphere(float2(rand(rng), rand(rng))); - nextDirection = normalizeOr(basis * localDirection, N); - float NdotL = max(dot(N, nextDirection), 0.0); - float3 H = normalizeOr(V + nextDirection, N); - float3 F = F_Schlick(max(dot(V, H), 0.0), F0); - float3 kD = (1.0 - F) * (1.0 - metallic) * - (1.0 - transmittance); - float diffuseFactor = disneyDiffuseFactor( - NdotV, NdotL, max(dot(nextDirection, H), 0.0), roughness); - float3 diffuseBsdf = kD * albedo * diffuseFactor / M_PI_F; - float conditionalPdf = NdotL / M_PI_F; - float combinedPdf = diffuseProb * conditionalPdf; - bounceWeight = diffuseBsdf * NdotL / - max(combinedPdf, 1e-6); - sampledBsdfPdf = combinedPdf; - sampledEnvironmentPdf = conditionalPdf; - sampledEventWasDelta = false; - } - - bounceWeight = clampLuminance(max(bounceWeight, float3(0.0)), 16.0); - throughput *= bounceWeight; - throughput = clampLuminance(throughput, 32.0); - if (depth == 0) { - throughput *= max(sceneData.indirectStrength, 0.0); - } - if (!all(isfinite(throughput)) || max(throughput.x, - max(throughput.y, throughput.z)) < - 1e-5) { - break; - } - - if (depth >= 2) { - float survival = clamp(max(throughput.x, - )", -R"( max(throughput.y, throughput.z)), - 0.05, 0.95); - if (rand(rng) > survival) { - break; - } - throughput /= survival; - } - - previousBsdfPdf = sampledBsdfPdf; - previousEnvironmentPdf = sampledEnvironmentPdf; - previousEventWasDelta = sampledEventWasDelta; - - surfaceRay.origin = offsetRayOrigin(P, Ng, nextDirection); - surfaceRay.direction = normalizeOr(nextDirection, N); - surfaceRay.min_distance = 0.0; - surfaceRay.max_distance = 1.0e30; - } - - return radiance; -} - -kernel void main0(texture2d outTex [[texture(0)]], - texture2d historyTex [[texture(1)]], - texture2d brightTex [[texture(2)]], - texture2d albedoRoughnessTex [[texture(3)]], - texture2d normalDepthTex [[texture(4)]], - texture2d motionObjectTex [[texture(5)]], - texture2d historyMomentsTex [[texture(6)]], - texture2d historyGuideTex [[texture(7)]], - texture2d historyOutTex [[texture(8)]], - texture2d historyGuideOutTex [[texture(9)]], - texture2d historyMomentsOutTex [[texture(10)]], - primitive_acceleration_structure sceneAS [[buffer(0)]], - constant CameraUniforms &cam [[buffer(1)]], - constant Material *materials [[buffer(2)]], - constant uint *primitiveObjects [[buffer(3)]], - constant VertexData *vertices [[buffer(4)]], - constant uint *indices [[buffer(5)]], - constant InstanceData *instanceData [[buffer(6)]], - constant DirectionalLightData &dirLight [[buffer(7)]], - constant SceneData &sceneData [[buffer(8)]], - constant PointLight *pointLights [[buffer(9)]], - constant SpotLight *spotLights [[buffer(10)]], - constant AreaLight *areaLights [[buffer(11)]], - constant EmissiveTriangle *emissiveTriangles [[buffer(14)]], - PT_MATERIAL_TEXTURE_BINDINGS, - constant uint *blasPrimitiveOffsets [[buffer(13)]], - texturecube skybox [[texture(60)]], - uint2 gid [[thread_position_in_grid]]) { - uint w = outTex.get_width(); - uint h = outTex.get_height(); - uint pixelStride = max(sceneData.pixelStride, 1u); - gid *= pixelStride; - if (gid.x >= w || gid.y >= h) - return; - - float2 uv = (float2(gid) + 0.5) / float2(w, h); - float3 ro = cam.camPos; - - intersector isect; - isect.assume_geometry_type(geometry_type::triangle); - isect.set_triangle_cull_mode(triangle_cull_mode::none); - - float3 color = float3(0.0); - float3 primaryAlbedo = float3(0.0); - float3 primaryNormal = float3(0.0); - float3 primaryPosition = float3(0.0); - float primaryDepth = 0.0; - float primaryRoughness = 1.0; - float primaryHitDistance = 0.0; - uint primaryObjectId = 0xFFFFFFFFu; - - uint spp = max(sceneData.raysPerPixel, 1u); - for (uint s = 0; s < spp; ++s) { - uint cameraRng = seedBase(gid, w, sceneData.frameIndex, - s + 0x9E3779B9u); - float2 pixelJitter = s == 0 - ? float2(0.0) - : float2(rand(cameraRng), rand(cameraRng)) - - 0.5; - float2 sampleUv = (float2(gid) + 0.5 + pixelJitter) / float2(w, h); - float2 sampleNdc = sampleUv * 2.0 - 1.0; - sampleNdc.y = -sampleNdc.y; - float4 sampleClip = float4(sampleNdc, 1.0, 1.0); - float4 sampleWorldH = cam.invViewProj * sampleClip; - float3 sampleWorldP = sampleWorldH.xyz / sampleWorldH.w; - - ray primaryRay; - primaryRay.origin = ro; - primaryRay.direction = normalize(sampleWorldP - ro); - primaryRay.min_distance = 0.001; - primaryRay.max_distance = 1.0e30; - - float3 sampleAlbedo = float3(0.0); - float3 sampleNormal = float3(0.0); - float3 samplePosition = float3(0.0); - float sampleDepth = 0.0; - float sampleRoughness = 1.0; - float sampleHitDistance = 0.0; - uint sampleObjectId = 0xFFFFFFFFu; - - float3 sample = sampleRadiance( - gid, s, w, isect, sceneAS, primaryRay, materials, primitiveObjects, - blasPrimitiveOffsets, vertices, indices, instanceData, dirLight, - sceneData, pointLights, spotLights, areaLights, - emissiveTriangles, PT_MATERIAL_TEXTURE_ARGS, skybox, sampleAlbedo, - sampleNormal, samplePosition, sampleDepth, sampleRoughness, - sampleHitDistance, sampleObjectId); - if (!all(isfinite(sample))) { - sample = float3(0.0); - } - color += clampLuminance(max(sample, float3(0.0)), - max(sceneData.fireflyClamp, 1.0)); - if (s == 0) { - primaryAlbedo = sampleAlbedo; - primaryNormal = sampleNormal; - primaryPosition = samplePosition; - primaryDepth = sampleDepth; - primaryRoughness = sampleRoughness; - primaryHitDistance = sampleHitDistance; - primaryObjectId = sampleObjectId; - } - } - - color /= float(spp); - if (!all(isfinite(color))) { - color = float3(0.0); - } - - float objectIdValue = primaryObjectId == 0xFFFFFFFFu - ? -1.0 - : float(primaryObjectId); - float2 encodedNormal = encodeNormal(primaryNormal); - float4 currentGuide = - float4(encodedNormal, primaryDepth, objectIdValue); - float4 previousClip = cam.prevViewProj * float4(primaryPosition, 1.0); - float2 previousNdc = previousClip.xy / max(abs(previousClip.w), 0.0001); - float2 previousUv = float2(previousNdc.x * 0.5 + 0.5, - 0.5 - previousNdc.y * 0.5); - bool previousUvValid = previousClip.w > 0.0 && - all(previousUv >= float2(0.0)) && - all(previousUv <= float2(1.0)); - uint2 previousPixel = gid; - if (primaryObjectId != 0xFFFFFFFFu && previousUvValid) { - previousPixel = uint2(clamp(previousUv * float2(w, h), float2(0.0), - float2(w - 1, h - 1))); - } - float4 prevColor = historyTex.read(previousPixel); - float4 previousGuide = historyGuideTex.read(previousPixel); - float4 previousMoments = historyMomentsTex.read(previousPixel); - bool historyValid = sceneData.frameIndex > 0 && prevColor.w > 0.0 && - abs(previousGuide.z - primaryDepth) < - max(0.02, primaryDepth * 0.01) && - distance(previousGuide.xy, encodedNormal) < 0.04 && - abs(previousGuide.w - objectIdValue) < 0.5; - if (!historyValid) { - prevColor = float4(0.0); - previousMoments = float4(0.0); - } - float previousMean = historyValid ? previousMoments.x : 0.0; - float previousVariance = - historyValid - ? max(previousMoments.y - previousMean * previousMean, 0.0) - : 0.0; - float sampleLuminanceLimit = max(sceneData.fireflyClamp, 1.0); - if (historyValid && prevColor.w >= 4.0) { - float statisticalLimit = previousMean + - max(0.5, 6.0 * sqrt(previousVariance)); - sampleLuminanceLimit = - min(sampleLuminanceLimit, max(4.0, statisticalLimit)); - } - color = clampLuminance(color, sampleLuminanceLimit); - float historyLimit = max(float(sceneData.accumulationFrameLimit), 1.0); - float previousWeight = - historyValid ? min(prevColor.w, max(historyLimit - 1.0, 0.0)) : 0.0; - float newHistoryLength = min(previousWeight + 1.0, historyLimit); - float accumulationDenominator = max(previousWeight + 1.0, 1.0); - )", -R"( float3 accum = - (prevColor.xyz * previousWeight + color) / accumulationDenominator; - float moment = luminance(color); - float accumulatedMoment = - (previousMoments.x * previousWeight + moment) / - accumulationDenominator; - float accumulatedMomentSquared = - (previousMoments.y * previousWeight + moment * moment) / - accumulationDenominator; - float variance = max(accumulatedMomentSquared - - accumulatedMoment * accumulatedMoment, - 0.0); - - constexpr float bloomKnee = 0.35; - - float brightness = luminance(accum); - float soft = clamp(brightness - sceneData.bloomThreshold + bloomKnee, 0.0, - bloomKnee * 2.0); - soft = soft * soft / max(bloomKnee * 4.0, 0.00001); - float contribution = max(brightness - sceneData.bloomThreshold, soft) / - max(brightness, 0.00001); - float3 brightColor = accum * contribution; - float2 motion = previousUvValid ? uv - previousUv : float2(0.0); - - for (uint y = 0; y < pixelStride; ++y) { - for (uint x = 0; x < pixelStride; ++x) { - uint2 pixel = gid + uint2(x, y); - if (pixel.x >= w || pixel.y >= h) { - continue; - } - historyOutTex.write(float4(accum, newHistoryLength), pixel); - historyGuideOutTex.write(currentGuide, pixel); - albedoRoughnessTex.write(float4(primaryAlbedo, primaryRoughness), - pixel); - normalDepthTex.write(float4(primaryNormal, primaryDepth), pixel); - motionObjectTex.write(float4(motion, objectIdValue, 1.0), pixel); - historyMomentsOutTex.write( - float4(accumulatedMoment, accumulatedMomentSquared, variance, - primaryHitDistance), - pixel); - outTex.write(float4(accum, 1.0), pixel); - brightTex.write(float4(brightColor, 1.0), pixel); - } - } -} -)", -}; -static const AtlasPackedShaderSource PATH = {PATH_PARTS, 10}; - -static const char* const PATH_DENOISE_PARTS[] = { -R"(#include -using namespace metal; - -struct DenoiseParameters { - int stepWidth; - float bloomThreshold; -}; - -kernel void main0(texture2d inputTexture [[texture(0)]], - texture2d outputTexture [[texture(1)]], - texture2d brightTexture [[texture(2)]], - texture2d guideTexture [[texture(3)]], - texture2d albedoRoughnessTexture - [[texture(4)]], - texture2d momentsTexture [[texture(5)]], - constant DenoiseParameters ¶meters [[buffer(0)]], - uint2 gid [[thread_position_in_grid]]) { - uint width = outputTexture.get_width(); - uint height = outputTexture.get_height(); - if (gid.x >= width || gid.y >= height) - return; - - constexpr int2 offsets[9] = {int2(0, 0), int2(1, 0), int2(-1, 0), - int2(0, 1), int2(0, -1), int2(1, 1), - int2(-1, 1), int2(1, -1), int2(-1, -1)}; - constexpr float weights[9] = {0.28, 0.12, 0.12, 0.12, 0.12, - 0.06, 0.06, 0.06, 0.06}; - float3 center = inputTexture.read(gid).xyz; - float4 centerGuide = guideTexture.read(gid); - float4 centerAlbedoRoughness = albedoRoughnessTexture.read(gid); - float4 centerMoments = momentsTexture.read(gid); - bool centerSurface = centerGuide.w > 0.0; - float centerNormalLength = dot(centerGuide.xyz, centerGuide.xyz); - float centerLuminance = dot(center, float3(0.2126, 0.7152, 0.0722)); - float neighborLuminance = 0.0; - float neighborWeight = 0.0; - for (int i = 1; i < 9; ++i) { - int2 samplePosition = - clamp(int2(gid) + offsets[i] * parameters.stepWidth, int2(0), - int2(width - 1, height - 1)); - float4 sampleGuide = guideTexture.read(uint2(samplePosition)); - bool sampleSurface = sampleGuide.w > 0.0; - if (sampleSurface != centerSurface) - continue; - float sampleLuminance = dot( - inputTexture.read(uint2(samplePosition)).xyz, - float3(0.2126, 0.7152, 0.0722)); - neighborLuminance += sampleLuminance; - neighborWeight += 1.0; - } - if (neighborWeight > 1.0) { - float localLimit = max(3.0, neighborLuminance / neighborWeight * 3.0); - if (centerLuminance > localLimit) { - center *= localLimit / max(centerLuminance, 0.00001); - centerLuminance = localLimit; - } - } - float3 filtered = float3(0.0); - float totalWeight = 0.0; - for (int i = 0; i < 9; ++i) { - int2 samplePosition = - clamp(int2(gid) + offsets[i] * parameters.stepWidth, int2(0), - int2(width - 1, height - 1)); - float3 sampleColor = inputTexture.read(uint2(samplePosition)).xyz; - float4 sampleGuide = guideTexture.read(uint2(samplePosition)); - float4 sampleAlbedoRoughness = - albedoRoughnessTexture.read(uint2(samplePosition)); - float sampleLuminance = - dot(sampleColor, float3(0.2126, 0.7152, 0.0722)); - float roughness = clamp(centerAlbedoRoughness.w, 0.0, 1.0); - float luminanceScale = mix(2.5, 7.0, roughness); - float luminanceDifference = - abs(sampleLuminance - centerLuminance) / - max(1.0, max(sampleLuminance, centerLuminance)); - float edgeWeight = exp(-luminanceDifference * luminanceScale); - bool sampleSurface = sampleGuide.w > 0.0; - float normalWeight = centerSurface == sampleSurface ? 1.0 : 0.0; - float depthWeight = normalWeight; - float albedoWeight = normalWeight; - if (centerSurface && sampleSurface) { - float sampleNormalLength = dot(sampleGuide.xyz, sampleGuide.xyz); - if (centerNormalLength > 1e-6 && sampleNormalLength > 1e-6) { - float normalSimilarity = - dot(centerGuide.xyz * rsqrt(centerNormalLength), - sampleGuide.xyz * rsqrt(sampleNormalLength)); - normalWeight *= pow(max(normalSimilarity, 0.0), 24.0); - } else if (i != 0) { - normalWeight = 0.0; - } - float depthScale = max(0.01, abs(centerGuide.w) * 0.01) * - max(float(parameters.stepWidth), 1.0); - depthWeight *= - exp(-abs(sampleGuide.w - centerGuide.w) / depthScale); - albedoWeight *= exp(-length(sampleAlbedoRoughness.xyz - - centerAlbedoRoughness.xyz) * - 8.0); - } - float weight = weights[i] * edgeWeight * normalWeight * depthWeight * - albedoWeight; - filtered += sampleColor * weight; - totalWeight += weight; - } - float3 spatialResult = - totalWeight > 0.0001 ? filtered / totalWeight : center; - float roughness = clamp(centerAlbedoRoughness.w, 0.0, 1.0); - float relativeNoise = sqrt(max(centerMoments.z, 0.0)) / - max(centerLuminance, 0.05); - float filterStrength = clamp(relativeNoise * 1.5, 0.02, 1.0) * - mix(0.12, 1.0, roughness * roughness); - if (!centerSurface) { - filterStrength *= 0.25; - } - float3 result = mix(center, spatialResult, filterStrength); - float brightness = dot(result, float3(0.2126, 0.7152, 0.0722)); - constexpr float bloomKnee = 0.35; - float soft = clamp(brightness - parameters.bloomThreshold + bloomKnee, 0.0, - bloomKnee * 2.0); - soft = soft * soft / max(bloomKnee * 4.0, 0.00001); - float contribution = max(brightness - parameters.bloomThreshold, soft) / - max(brightness, 0.00001); - outputTexture.write(float4(result, 1.0), gid); - brightTexture.write(float4(result * contribution, 1.0), gid); -} -)", -}; -static const AtlasPackedShaderSource PATH_DENOISE = {PATH_DENOISE_PARTS, 1}; - -static const char* const POINT_DEPTH_FRAG_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct Uniforms -{ - packed_float3 lightPos; - float far_plane; -}; - -struct main0_out -{ - float gl_FragDepth [[depth(any)]]; -}; - -struct main0_in -{ - float4 FragPos [[user(locn0)]]; -}; - -fragment main0_out main0(main0_in in [[stage_in]], constant Uniforms& _17 [[buffer(0)]]) -{ - main0_out out = {}; - float lightDistance = length(in.FragPos.xyz - float3(_17.lightPos)); - lightDistance /= _17.far_plane; - out.gl_FragDepth = lightDistance; - return out; -} - -)", -}; -static const AtlasPackedShaderSource POINT_DEPTH_FRAG = {POINT_DEPTH_FRAG_PARTS, 1}; - -static const char* const POINT_DEPTH_GEOM_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct ShadowMatrices -{ - float4x4 shadowMatrices[6]; -}; - -struct main0_out -{ - float4 FragPos; - float4 gl_Position; - uint gl_Layer; -}; - -unknown main0_out main0(constant ShadowMatrices& _55 [[buffer(0)]]) -{ - main0_out out = {}; - for (int face = 0; face < 6; face++) - { - out.gl_Layer = uint(face); - for (int i = 0; i < 3; i++) - { - out.FragPos = _RESERVED_IDENTIFIER_FIXUP_gl_in[i].out.gl_Position; - out.gl_Position = _55.shadowMatrices[face] * out.FragPos; - EmitVertex(); - } - EndPrimitive(); - } - return out; -} - -)", -}; -static const AtlasPackedShaderSource POINT_DEPTH_GEOM = {POINT_DEPTH_GEOM_PARTS, 1}; - -static const char* const POINT_DEPTH_NOGEOM_FRAG_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct Uniforms -{ - packed_float3 lightPos; - float far_plane; -}; - -struct main0_out -{ - float gl_FragDepth [[depth(any)]]; -}; - -struct main0_in -{ - float4 FragPos [[user(locn0)]]; -}; - -fragment main0_out main0(main0_in in [[stage_in]], constant Uniforms& _17 [[buffer(0)]]) -{ - main0_out out = {}; - float lightDistance = length(in.FragPos.xyz - float3(_17.lightPos)); - lightDistance /= _17.far_plane; - out.gl_FragDepth = lightDistance; - return out; -} - -)", -}; -static const AtlasPackedShaderSource POINT_DEPTH_NOGEOM_FRAG = {POINT_DEPTH_NOGEOM_FRAG_PARTS, 1}; - -static const char* const POINT_DEPTH_NOGEOM_VERT_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct UBO -{ - float4x4 model; - uint isInstanced; -}; - -struct ShadowUniforms -{ - float4x4 shadowMatrix; - int faceIndex; -}; - -struct main0_out -{ - float4 FragPos [[user(locn0)]]; - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; - float4 instanceModel_0 [[attribute(6)]]; - float4 instanceModel_1 [[attribute(7)]]; - float4 instanceModel_2 [[attribute(8)]]; - float4 instanceModel_3 [[attribute(9)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]], constant UBO& _12 [[buffer(0)]], constant ShadowUniforms& _62 [[buffer(1)]]) -{ - main0_out out = {}; - float4x4 instanceModel = {}; - instanceModel[0] = in.instanceModel_0; - instanceModel[1] = in.instanceModel_1; - instanceModel[2] = in.instanceModel_2; - instanceModel[3] = in.instanceModel_3; - float4 worldPos; - bool hasInstanceMatrix = abs(instanceModel[3].w) > 0.5; - if ((_12.isInstanced != 0u) && hasInstanceMatrix) - { - worldPos = (_12.model * instanceModel) * float4(in.aPos, 1.0); - } - else - { - worldPos = _12.model * float4(in.aPos, 1.0); - } - out.FragPos = worldPos; - out.gl_Position = _62.shadowMatrix * worldPos; - return out; -} -)", -}; -static const AtlasPackedShaderSource POINT_DEPTH_NOGEOM_VERT = {POINT_DEPTH_NOGEOM_VERT_PARTS, 1}; - -static const char* const POINT_DEPTH_VERT_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct UBO -{ - float4x4 model; - uint isInstanced; -}; - -struct main0_out -{ - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; - float4 instanceModel_0 [[attribute(6)]]; - float4 instanceModel_1 [[attribute(7)]]; - float4 instanceModel_2 [[attribute(8)]]; - float4 instanceModel_3 [[attribute(9)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]], constant UBO& _12 [[buffer(0)]]) -{ - main0_out out = {}; - float4x4 instanceModel = {}; - instanceModel[0] = in.instanceModel_0; - instanceModel[1] = in.instanceModel_1; - instanceModel[2] = in.instanceModel_2; - instanceModel[3] = in.instanceModel_3; - bool hasInstanceMatrix = abs(instanceModel[3].w) > 0.5; - if ((_12.isInstanced != 0u) && hasInstanceMatrix) - { - out.gl_Position = (_12.model * instanceModel) * float4(in.aPos, 1.0); - } - else - { - out.gl_Position = _12.model * float4(in.aPos, 1.0); - } - return out; -} -)", -}; -static const AtlasPackedShaderSource POINT_DEPTH_VERT = {POINT_DEPTH_VERT_PARTS, 1}; - -static const char* const SKYBOX_FRAG_PARTS[] = { -R"(#pragma clang diagnostic ignored "-Wmissing-prototypes" - -#include -#include - -using namespace metal; - -struct Params -{ - float3 sunDirection; - float4 sunColor; - float3 moonDirection; - float4 moonColor; - int hasDayNight; -}; - -struct AtmosphereParams -{ - float sunTintStrength; - float moonTintStrength; - float sunSizeMultiplier; - float moonSizeMultiplier; - float starDensity; -}; - -struct main0_out -{ - float4 FragColor [[color(0)]]; -}; - -struct main0_in -{ - float3 TexCoords [[user(locn0)]]; -}; - -static inline __attribute__((always_inline)) -float hash13(thread float3& p) -{ - p = fract(p * 443.897003173828125); - p += float3(dot(p, p.yzx + float3(19.1900005340576171875))); - return fract((p.x + p.y) * p.z); -} - -static inline __attribute__((always_inline)) -float3 generateStars(thread const float3& dir, thread const float& density, thread const float& nightFactor) -{ - if ((density <= 0.0) || (nightFactor <= 0.0)) - { - return float3(0.0); - } - float3 starSpace = dir * 50.0; - float3 cell = floor(starSpace); - float3 localPos = fract(starSpace); - float3 param = cell; - float _165 = hash13(param); - float rand = _165; - if (rand < (density * 0.300000011920928955078125)) - { - float3 param_1 = cell + float3(12.340000152587890625, 56.779998779296875, 90.12000274658203125); - float _181 = hash13(param_1); - float randX = _181; - float3 param_2 = cell + float3(23.450000762939453125, 67.8899993896484375, 1.230000019073486328125); - float _190 = hash13(param_2); - float randY = _190; - float3 param_3 = cell + float3(34.560001373291015625, 78.90000152587890625, 12.340000152587890625); - float _198 = hash13(param_3); - float randZ = _198; - float3 starPos = float3(randX, randY, randZ); - float dist = length(localPos - starPos); - float3 param_4 = cell + float3(45.6699981689453125, 89.01000213623046875, 23.450000762939453125); - float _217 = hash13(param_4); - float starSize = 0.0199999995529651641845703125 + (_217 * 0.02999999932944774627685546875); - float3 param_5 = cell + float3(56.779998779296875, 90.12000274658203125, 34.560001373291015625); - float _227 = hash13(param_5); - float brightness = 0.5 + (_227 * 0.5); - float star = smoothstep(starSize, 0.0, dist) * brightness; - float3 param_6 = cell + float3(67.8899993896484375, 1.230000019073486328125, 45.6699981689453125); - float _243 = hash13(param_6); - float twinkle = 0.800000011920928955078125 + (0.20000000298023223876953125 * sin(_243 * 100.0)); - star *= (twinkle * nightFactor); - float3 starColor = float3(1.0); - if (rand > 0.89999997615814208984375) - { - starColor = float3(0.800000011920928955078125, 0.89999997615814208984375, 1.0); - } - else - { - if (rand > 0.800000011920928955078125) - { - starColor = float3(1.0, 0.89999997615814208984375, 0.800000011920928955078125); - } - } - return starColor * star; - } - return float3(0.0); -} - -static inline __attribute__((always_inline)) -float hash21(thread float2& p) -{ - p = fract(p * float2(123.339996337890625, 456.209991455078125)); - p += float2(dot(p, p + float2(45.31999969482421875))); - return fract(p.x * p.y); -} - -static inline __attribute__((always_inline)) -float valueNoise(thread const float2& p) -{ - float2 i = floor(p); - float2 f = fract(p); - f = (f * f) * (float2(3.0) - (f * 2.0)); - float2 param = i; - float _80 = hash21(param); - float a = _80; - float2 param_1 = i + float2(1.0, 0.0); - float _88 = hash21(param_1); - float b = _88; - float2 param_2 = i + float2(0.0, 1.0); - float _94 = hash21(param_2); - float c = _94; - float2 param_3 = i + float2(1.0); - float _100 = hash21(param_3); - float d = _100; - return mix(mix(a, b, f.x), mix(c, d, f.x), f.y); -} - -static inline __attribute__((always_inline)) -float3 generateMoonTexture(thread float2& uv, thread const float& distanceFromCenter, thread const float3& tintColor) -{ - float angle = 0.5; - float ca = cos(angle); - float sa = sin(angle); - uv = float2((ca * uv.x) - (sa * uv.y), (sa * uv.x) + (ca * uv.y)); - float2 param = uv * 2.0; - float largeFeatures = valueNoise(param); - largeFeatures = smoothstep(0.300000011920928955078125, 0.699999988079071044921875, largeFeatures); - float2 param_1 = uv * 8.0; - float mediumCraters = valueNoise(param_1); - float2 craterUV = uv * 6.0; - float2 craterCell = floor(craterUV); - float2 craterLocal = fract(craterUV); - float craters = 1.0; - for (int i = 0; i < 4; i++) - { - float2 neighbor = float2(float(i % 2), float(i / 2)); - float2 cellPoint = craterCell + neighbor; - float2 param_2 = cellPoint; - float _353 = hash21(param_2); - float2 param_3 = cellPoint + float2(13.69999980926513671875, 27.299999237060546875); - float _360 = hash21(param_3); - float2 craterCenter = float2(_353, _360); - float dist = length((craterLocal - neighbor) - craterCenter); - float2 param_4 = cellPoint + float2(5.30000019073486328125, 9.69999980926513671875); - float _378 = hash21(param_4); - float craterSize = 0.1500000059604644775390625 + (0.25 * _378); - if (dist < craterSize) - { - float crater = smoothstep(craterSize, craterSize * 0.300000011920928955078125, dist); - craters = fast::min(craters, 1.0 - (crater * 0.699999988079071044921875)); - } - } - float surface = (largeFeatures * 0.5) + (mediumCraters * 0.5); - surface *= craters; - float intensity = mix(0.300000011920928955078125, 0.75, surface); - float limb = 1.0 - smoothstep(0.60000002384185791015625, 1.0, distanceFromCenter); - intensity *= (0.4000000059604644775390625 + (0.60000002384185791015625 * limb)); - intensity *= 1.2999999523162841796875; - return fast::clamp(tintColor * intensity, float3(0.0), float3(1.0)); -} - -fragment main0_out main0(main0_in in [[stage_in]], constant Params& _452 [[buffer(0)]], constant AtmosphereParams& _484 [[buffer(1)]], texturecube skybox [[texture(0)]], sampler skyboxSmplr [[sampler(0)]]) -{ - main0_out out = {}; - float3 dir = fast::normalize(in.TexCoords); - float3 color = skybox.sample(skyboxSmplr, in.TexCoords).xyz; - if (_452.hasDayNight == 1) - { - float3 normSunDir = fast::normalize(_452.sunDirection); - float3 normMoonDir = fast::normalize(_452.moonDirection); - float sunDot = dot(dir, normSunDir); - float moonDot = dot(dir, normMoonDir); - float nightFactor = smoothstep(0.1500000059604644775390625, -0.20000000298023223876953125, _452.sunDirection.y); - if (_484.starDensity > 0.0) - { - float3 param = dir; - float param_1 = _484.starDensity; - float param_2 = nightFactor; - color += generateStars(param, param_1, param_2); - } - float sunHorizonFade = smoothstep(-0.1500000059604644775390625, 0.0500000007450580596923828125, _452.sunDirection.y); - if (_452.sunDirection.y > (-0.1500000059604644775390625)) - { - float sizeAdjust = 1.0 - ((_484.sunSizeMultiplier - 1.0) * 0.001000000047497451305389404296875); - float sunSize = 0.999499976634979248046875 * sizeAdjust; - float sunGlowSize = 0.99800002574920654296875 * (1.0 - ((_484.sunSizeMultiplier - 1.0) * 0.0030000000260770320892333984375)); - float sunHaloSize = 0.9900000095367431640625 * (1.0 - ((_484.sunSizeMultiplier - 1.0) * 0.014999999664723873138427734375)); - float sunDisk = smoothstep(sunSize - 0.00019999999494757503271102905273438, sunSize, sunDot); - float sunGlow = smoothstep(sunGlowSize, sunSize, sunDot) * (1.0 - sunDisk); - float sunHalo = smoothstep(sunHaloSize, sunSize, sunDot) * (1.0 - smoothstep(sunSize, sunGlowSize, sunDot)); - float horizonBoost = smoothstep(0.100000001490116119384765625, -0.0500000007450580596923828125, _452.sunDirection.y) * 2.0; - sunHalo *= (0.300000011920928955078125 )", -R"(+ horizonBoost); - color += ((_452.sunColor.xyz * (((sunDisk * 5.0) + (sunGlow * 0.5)) + sunHalo)) * sunHorizonFade); - } - float moonHorizonFade = smoothstep(-0.1500000059604644775390625, 0.0500000007450580596923828125, _452.moonDirection.y); - if (_452.moonDirection.y > (-0.1500000059604644775390625)) - { - float sizeAdjust_1 = 1.0 - ((_484.moonSizeMultiplier - 1.0) * 0.001000000047497451305389404296875); - float moonSize = 0.999599993228912353515625 * sizeAdjust_1; - float moonGlowSize = 0.99849998950958251953125 * (1.0 - ((_484.moonSizeMultiplier - 1.0) * 0.0030000000260770320892333984375)); - float moonHaloSize = 0.99199998378753662109375 * (1.0 - ((_484.moonSizeMultiplier - 1.0) * 0.014999999664723873138427734375)); - float moonDisk = smoothstep(moonSize - 0.00019999999494757503271102905273438, moonSize, moonDot); - if (moonDisk > 0.00999999977648258209228515625) - { - float3 up = (abs(normMoonDir.y) < 0.999000012874603271484375) ? float3(0.0, 1.0, 0.0) : float3(1.0, 0.0, 0.0); - float3 right = fast::normalize(cross(up, normMoonDir)); - float3 actualUp = cross(normMoonDir, right); - float3 relativeDir = dir - (normMoonDir * moonDot); - float u = dot(relativeDir, right); - float v = dot(relativeDir, actualUp); - float distFromCenter = length(float2(u, v)) / sqrt(1.0 - (moonSize * moonSize)); - if (distFromCenter < 1.0) - { - float2 moonUV = float2(u, v) * 200.0; - float2 param_3 = moonUV; - float param_4 = distFromCenter; - float3 param_5 = _452.moonColor.xyz; - float3 _703 = generateMoonTexture(param_3, param_4, param_5); - float3 moonTexture = _703; - color += (((moonTexture * moonDisk) * 1.5) * moonHorizonFade); - } - else - { - color += (((_452.moonColor.xyz * moonDisk) * 1.5) * moonHorizonFade); - } - } - float moonGlow = smoothstep(moonGlowSize, moonSize, moonDot) * (1.0 - moonDisk); - float moonHalo = smoothstep(moonHaloSize, moonSize, moonDot) * (1.0 - smoothstep(moonSize, moonGlowSize, moonDot)); - float moonHorizonBoost = smoothstep(0.100000001490116119384765625, -0.0500000007450580596923828125, _452.moonDirection.y) * 2.0; - moonHalo *= (0.20000000298023223876953125 + moonHorizonBoost); - color += ((_452.moonColor.xyz * ((moonGlow * 0.300000011920928955078125) + moonHalo)) * moonHorizonFade); - } - bool _767 = _452.sunDirection.y > (-0.100000001490116119384765625); - bool _773; - if (_767) - { - _773 = _484.sunTintStrength > 0.0; - } - else - { - _773 = _767; - } - if (_773) - { - float sunSkyInfluence = smoothstep(0.699999988079071044921875, 0.949999988079071044921875, sunDot) * smoothstep(-0.100000001490116119384765625, 0.20000000298023223876953125, _452.sunDirection.y); - color = mix(color, color * _452.sunColor.xyz, float3((sunSkyInfluence * 0.300000011920928955078125) * _484.sunTintStrength)); - float sunProximity = smoothstep(0.300000011920928955078125, 0.800000011920928955078125, sunDot) * smoothstep(-0.100000001490116119384765625, 0.300000011920928955078125, _452.sunDirection.y); - color += (((_452.sunColor.xyz * sunProximity) * 0.1500000059604644775390625) * _484.sunTintStrength); - float globalSunTint = smoothstep(-0.100000001490116119384765625, 0.5, _452.sunDirection.y); - color = mix(color, _452.sunColor.xyz, float3((globalSunTint * _484.sunTintStrength) * 0.07999999821186065673828125)); - } - bool _833 = _452.moonDirection.y > (-0.100000001490116119384765625); - bool _839; - if (_833) - { - _839 = _484.moonTintStrength > 0.0; - } - else - { - _839 = _833; - } - if (_839) - { - float moonSkyInfluence = smoothstep(0.800000011920928955078125, 0.949999988079071044921875, moonDot) * smoothstep(-0.100000001490116119384765625, 0.20000000298023223876953125, _452.moonDirection.y); - color = mix(color, color * _452.moonColor.xyz, float3((moonSkyInfluence * 0.20000000298023223876953125) * _484.moonTintStrength)); - float moonProximity = smoothstep(0.5, 0.85000002384185791015625, moonDot) * smoothstep(-0.100000001490116119384765625, 0.300000011920928955078125, _452.moonDirection.y); - color += (((_452.moonColor.xyz * moonProximity) * 0.07999999821186065673828125) * _484.moonTintStrength); - float globalMoonTint = smoothstep(-0.100000001490116119384765625, 0.5, _452.moonDirection.y); - color = mix(color, _452.moonColor.xyz, float3((globalMoonTint * _484.moonTintStrength) * 0.0500000007450580596923828125)); - } - } - out.FragColor = float4(color, 1.0); - return out; -} - -)", -}; -static const AtlasPackedShaderSource SKYBOX_FRAG = {SKYBOX_FRAG_PARTS, 2}; - -static const char* const SKYBOX_VERT_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct UniformBufferObject -{ - float4x4 projection; - float4x4 view; -}; - -struct main0_out -{ - float3 TexCoords [[user(locn0)]]; - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]], constant UniformBufferObject& _19 [[buffer(0)]]) -{ - main0_out out = {}; - out.TexCoords = in.aPos; - float3x3 _32 = float3x3(_19.view[0].xyz, _19.view[1].xyz, _19.view[2].xyz); - float4x4 viewNoTranslation = float4x4(float4(_32[0].x, _32[0].y, _32[0].z, 0.0), float4(_32[1].x, _32[1].y, _32[1].z, 0.0), float4(_32[2].x, _32[2].y, _32[2].z, 0.0), float4(0.0, 0.0, 0.0, 1.0)); - float4 pos = (_19.projection * viewNoTranslation) * float4(in.aPos, 1.0); - out.gl_Position = pos.xyww; - return out; -} - -)", -}; -static const AtlasPackedShaderSource SKYBOX_VERT = {SKYBOX_VERT_PARTS, 1}; - -static const char* const SSAO_BLUR_FRAG_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct main0_out -{ - float FragColor [[color(0)]]; -}; - -struct main0_in -{ - float2 TexCoord [[user(locn0)]]; -}; - -fragment main0_out main0(main0_in in [[stage_in]], texture2d inSSAO [[texture(0)]], sampler inSSAOSmplr [[sampler(0)]]) -{ - main0_out out = {}; - float2 texelSize = float2(1.0) / float2(int2(inSSAO.get_width(), inSSAO.get_height())); - float result = 0.0; - for (int x = -2; x <= 2; x++) - { - for (int y = -2; y <= 2; y++) - { - float2 offset = float2(float(x), float(y)) * texelSize; - result += inSSAO.sample(inSSAOSmplr, (in.TexCoord + offset)).x; - } - } - out.FragColor = result / 25.0; - return out; -} - -)", -}; -static const AtlasPackedShaderSource SSAO_BLUR_FRAG = {SSAO_BLUR_FRAG_PARTS, 1}; - -static const char* const SSAO_FRAG_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct Paramters { - float4x4 projection; - float4x4 inverseProjection; - float4x4 view; - float2 noiseScale; -}; - -struct Samples { - float3 samples[64]; -}; - -struct main0_out { - float FragColor [[color(0)]]; -}; - -struct main0_in { - float2 TexCoord [[user(locn0)]]; -}; - -static inline float3 reconstructViewPos(float2 uv, float depth, - float4x4 inverseProjection) { - float2 ndc; - ndc.x = uv.x * 2.0 - 1.0; - ndc.y = (1.0 - uv.y) * 2.0 - 1.0; - float ndcZ = depth * 2.0 - 1.0; - float4 clip = float4(ndc, ndcZ, 1.0); - float4 viewPos = inverseProjection * clip; - float invW = 1.0 / max(abs(viewPos.w), 1e-6); - return viewPos.xyz * invW; -} - -fragment main0_out main0(main0_in in [[stage_in]], - constant Paramters &_43 [[buffer(0)]], - constant Samples &_137 [[buffer(1)]], - texture2d gPosition [[texture(0)]], - texture2d gNormal [[texture(1)]], - texture2d texNoise [[texture(2)]], - sampler gPositionSmplr [[sampler(0)]], - sampler gNormalSmplr [[sampler(1)]], - sampler texNoiseSmplr [[sampler(2)]]) { - main0_out out = {}; - float3 sampledNormalWorld = gNormal.sample(gNormalSmplr, in.TexCoord).xyz; - float sampledNormalLength = length(sampledNormalWorld); - if (!all(isfinite(sampledNormalWorld)) || - sampledNormalLength <= 0.001000000047497451305389404296875) { - out.FragColor = 1.0; - return out; - } - float4 gPositionCenter = gPosition.sample(gPositionSmplr, in.TexCoord); - float centerDepth = gPositionCenter.w; - if (!isfinite(centerDepth)) { - out.FragColor = 1.0; - return out; - } - centerDepth = clamp(centerDepth, 0.0, 1.0); - float3 fragPos = reconstructViewPos(in.TexCoord, centerDepth, - _43.inverseProjection); - float3 normalWorld = sampledNormalWorld / sampledNormalLength; - float3 normal = fast::normalize((_43.view * float4(normalWorld, 0.0)).xyz); - float3 randomVec = fast::normalize( - (texNoise.sample(texNoiseSmplr, (in.TexCoord * _43.noiseScale)).xyz * - 2.0) - - float3(1.0)); - float3 tangent = - fast::normalize(randomVec - (normal * dot(randomVec, normal))); - float3 bitangent = cross(normal, tangent); - float3x3 TBN = float3x3(float3(tangent), float3(bitangent), float3(normal)); - float viewDepth = abs(fragPos.z); - float baseRadius = - mix(0.550000011920928955078125, 2.2000000476837158203125, - clamp(viewDepth / 140.0, 0.0, 1.0)); - float3 dPosDx = dfdx(fragPos); - float3 dPosDy = dfdy(fragPos); - float pixelWorldScale = max(length(dPosDx), length(dPosDy)); - if (!isfinite(pixelWorldScale)) { - pixelWorldScale = 0.0; - } - float sampleRadius = - clamp(max(baseRadius, pixelWorldScale * 6.0), 0.3499999940395355, - 12.0); - float depthBias = clamp( - max(mix(0.006000000052154064178466796875, - 0.0240000002086162567138671875, - clamp(viewDepth / 180.0, 0.0, 1.0)), - sampleRadius * 0.009999999776482582), - 0.003000000026077032, 0.07999999821186066); - float occlusion = 0.0; - int validSamples = 0; - for (int i = 0; i < 64; i++) { - float3 samplePos = TBN * _137.samples[i]; - samplePos = fragPos + (samplePos * sampleRadius); - float4 offset = _43.projection * float4(samplePos, 1.0); - float _160 = offset.w; - float4 _161 = offset; - float3 _164 = _161.xyz / float3(_160); - offset.x = _164.x; - offset.y = _164.y; - offset.z = _164.z; - float4 _174 = offset; - float2 _178 = (_174.xy * 0.5) + float2(0.5); - offset.x = _178.x; - offset.y = 1.0 - _178.y; - bool _185 = offset.x < 0.0; - bool _192; - if (!_185) { - _192 = offset.x > 1.0; - } else { - _192 = _185; - } - bool _199; - if (!_192) { - _199 = offset.y < 0.0; - } else { - _199 = _192; - } - bool _206; - if (!_199) { - _206 = offset.y > 1.0; - } else { - _206 = _199; - } - if (_206) { - continue; - } - float sampleDepth = gPosition.sample(gPositionSmplr, offset.xy).w; - if (!isfinite(sampleDepth)) { - continue; - } - sampleDepth = clamp(sampleDepth, 0.0, 1.0); - float3 sampleViewPos = - reconstructViewPos(offset.xy, sampleDepth, _43.inverseProjection); - float rangeCheck = - smoothstep(0.0, 1.0, - sampleRadius / (abs(fragPos.z - sampleViewPos.z) + - 0.0005000000237487256526947021484375)); - occlusion += - (float(sampleViewPos.z >= (samplePos.z + depthBias)) * rangeCheck); - validSamples++; - } - if (validSamples > 0) { - occlusion = 1.0 - (occlusion / float(validSamples)); - } else { - occlusion = 1.0; - } - out.FragColor = occlusion; - return out; -} -)", -}; -static const AtlasPackedShaderSource SSAO_FRAG = {SSAO_FRAG_PARTS, 1}; - -static const char* const SSR_BLUR_FRAG_PARTS[] = { -R"(#include -#include - -using namespace metal; - -fragment void main0() -{ -} - -)", -}; -static const AtlasPackedShaderSource SSR_BLUR_FRAG = {SSR_BLUR_FRAG_PARTS, 1}; - -static const char* const SSR_FRAG_PARTS[] = { -R"(#pragma clang diagnostic ignored "-Wmissing-prototypes" - -#include -#include - -using namespace metal; - -struct Uniforms -{ - float4x4 inverseProjection; - float4x4 inverseView; - float4x4 projection; - float4x4 view; - float3 cameraPosition; -}; - -struct SSRParameters -{ - float maxDistance; - float resolution; - int steps; - float thickness; - float maxRoughness; - float historyWeight; - int debugMode; -}; - -struct main0_out -{ - float4 FragColor [[color(0)]]; -}; - -struct main0_in -{ - float2 TexCoord [[user(locn0)]]; -}; - -static inline __attribute__((always_inline)) -float3 fresnelSchlick(thread const float& cosTheta, thread const float3& F0) -{ - return F0 + ((float3(1.0) - F0) * powr(1.0 - cosTheta, 5.0)); -} - -static inline __attribute__((always_inline)) -float3 sampleSkyReflection(thread const float3& normal, thread const float3& viewDir, thread const float3& albedo, thread const float& metallic, texturecube skybox, sampler skyboxSmplr) -{ - float3 reflected = reflect(-fast::normalize(viewDir), fast::normalize(normal)); - float3 skyColor = skybox.sample(skyboxSmplr, reflected).xyz; - float skyLuma = dot(skyColor, float3(0.2125999927520751953125, 0.715200006961822509765625, 0.072200000286102294921875)); - if (skyLuma < 0.001000000047497451305389404296875) - { - float t = fast::clamp((reflected.y * 0.5) + 0.5, 0.0, 1.0); - float3 horizon = float3(0.7400000095367431640625, 0.790000021457672119140625, 0.87999999523162841796875); - float3 zenith = float3(0.5, 0.63999998569488525390625, 0.839999973773956298828125); - skyColor = mix(horizon, zenith, float3(t)); - } - float tintStrength = metallic * 0.3499999940395355224609375; - float3 tint = mix(float3(1.0), albedo, float3(tintStrength)); - return skyColor * tint; -} - -static inline __attribute__((always_inline)) -float4 SSR(thread const float3& worldPos, thread const float3& normal, thread const float3& viewDir, thread const float& roughness, thread const float& metallic, thread const float& reflectivity, thread const float3& albedo, constant Uniforms& _42, constant SSRParameters& _96, thread float4& gl_FragCoord, texture2d gPosition, sampler gPositionSmplr, texture2d sceneColor, sampler sceneColorSmplr, texture2d gNormal, sampler gNormalSmplr, texture2d gDepth, sampler gDepthSmplr, texturecube skybox, sampler skyboxSmplr) -{ - float3 viewPos = (_42.view * float4(worldPos, 1.0)).xyz; - float3 viewNormal = fast::normalize((_42.view * float4(normal, 0.0)).xyz); - float mirrorFactor = fast::clamp(fast::max(metallic, reflectivity) * (1.0 - roughness), 0.0, 1.0); - float3 skyReflection = sampleSkyReflection(normal, viewDir, albedo, metallic, skybox, skyboxSmplr); - float3 viewDirection = fast::normalize(viewPos); - float3 viewReflect = fast::normalize(reflect(viewDirection, viewNormal)); - if (viewReflect.z > 0.0) - { - return float4(0.0); - } - float3 rayOrigin = viewPos + (viewNormal * 0.00999999977648258209228515625); - float3 rayDir = viewReflect; - float stepSize = _96.maxDistance / float(_96.steps); - float3 currentPos = rayOrigin; - float jitter = fract(sin(dot(gl_FragCoord.xy, float2(12.98980045318603515625, 78.233001708984375))) * 43758.546875) * roughness * 0.25; - currentPos += ((rayDir * stepSize) * jitter); - float2 hitUV = float2(-1.0); - float hitDepth = 0.0; - bool hit = false; - float2 fallbackUV = float2(0.0); - bool hasFallbackUV = false; - float3 lastPos = currentPos; - for (int i = 0; i < _96.steps; i++) - { - float t = float(i) / float(_96.steps); - float adaptiveStep = mix(0.300000011920928955078125, 1.0, t); - currentPos += ((rayDir * stepSize) * adaptiveStep); - float4 projectedPos = _42.projection * float4(currentPos, 1.0); - float _186 = projectedPos.w; - float4 _187 = projectedPos; - float3 _190 = _187.xyz / float3(_186); - projectedPos.x = _190.x; - projectedPos.y = _190.y; - projectedPos.z = _190.z; - float2 screenUV = (projectedPos.xy * 0.5) + float2(0.5); - bool _208 = screenUV.x < 0.0; - bool _215; - if (!_208) - { - _215 = screenUV.x > 1.0; - } - else - { - _215 = _208; - } - bool _222; - if (!_215) - { - _222 = screenUV.y < 0.0; - } - else - { - _222 = _215; - } - bool _229; - if (!_222) - { - _229 = screenUV.y > 1.0; - } - else - { - _229 = _222; - } - if (!_229) - { - fallbackUV = screenUV; - hasFallbackUV = true; - } - else - { - break; - } - float hierarchyLevel = fast::clamp(floor(log2(1.0 + float(i) * 0.25)), - 0.0, 5.0); - float rawDepth = gDepth.sample(gDepthSmplr, screenUV, - level(hierarchyLevel)).x; - if (rawDepth >= 0.99989998340606689453125) - { - currentPos += rayDir * stepSize * (exp2(hierarchyLevel) - 1.0); - lastPos = currentPos; - continue; - } - float3 sampleWorldPos = gPosition.sample(gPositionSmplr, screenUV).xyz; - float3 sampleNormal = gNormal.sample(gNormalSmplr, screenUV).xyz; - if (dot(sampleNormal, sampleNormal) < 0.00999999977648258209228515625) - { - lastPos = currentPos; - continue; - } - if (length(sampleWorldPos - worldPos) < 0.07999999821186065673828125) - { - lastPos = currentPos; - continue; - } - float3 sampleViewPos = (_42.view * float4(sampleWorldPos, 1.0)).xyz; - float sampleDepth = -sampleViewPos.z; - float currentDepth = -currentPos.z; - float3 sampleViewNormal = fast::normalize((_42.view * float4(sampleNormal, 0.0)).xyz); - if ((dot(sampleViewNormal, viewNormal) > 0.920000016689300537109375) && (abs(sampleDepth - currentDepth) < (_96.thickness * 1.5))) - { - lastPos = currentPos; - continue; - } - float depthDiff = sampleDepth - currentDepth; - bool _265 = depthDiff > 0.0; - bool _272; - if (_265) - { - _272 = depthDiff < _96.thickness; - } - else - { - _272 = _265; - } - if (_272) - { - float3 binarySearchStart = lastPos; - float3 binarySearchEnd = currentPos; - for (int j = 0; j < 8; j++) - { - float3 midPoint = (binarySearchStart + binarySearchEnd) * 0.5; - float4 midProj = _42.projection * float4(midPoint, 1.0); - float _303 = midProj.w; - float4 _304 = midProj; - float3 _307 = _304.xyz / float3(_303); - midProj.x = _307.x; - midProj.y = _307.y; - midProj.z = _307.z; - float2 midUV = (midProj.xy * 0.5) + float2(0.5); - bool _321 = midUV.x < 0.0; - bool _328; - if (!_321) - { - _328 = midUV.x > 1.0; - } - else - { - _328 = _321; - } - bool _335; - if (!_328) - { - _335 = midUV.y < 0.0; - } - else - { - _335 = _328; - } - bool _342; - if (!_335) - { - _342 = midUV.y > 1.0; - } - else - { - _342 = _335; - } - if (_342) - { - break; - } - float midRawDepth = gDepth.sample(gDepthSmplr, midUV).x; - if (midRawDepth >= 0.99989998340606689453125) - { - binarySearchStart = midPoint; - continue; - } - float3 midSampleWorldPos = gPositio)", -R"(n.sample(gPositionSmplr, midUV).xyz; - float3 midSampleViewPos = (_42.view * float4(midSampleWorldPos, 1.0)).xyz; - float midSampleDepth = -midSampleViewPos.z; - float midCurrentDepth = -midPoint.z; - if (midCurrentDepth < midSampleDepth) - { - binarySearchStart = midPoint; - } - else - { - binarySearchEnd = midPoint; - } - } - float4 finalProj = _42.projection * float4(binarySearchEnd, 1.0); - float _364 = finalProj.w; - float4 _365 = finalProj; - float3 _368 = _365.xyz / float3(_364); - finalProj.x = _368.x; - finalProj.y = _368.y; - finalProj.z = _368.z; - hitUV = (finalProj.xy * 0.5) + float2(0.5); - hitDepth = length(currentPos - rayOrigin); - hit = true; - break; - } - lastPos = currentPos; - } - if (!hit) - { - return float4(0.0); - } - float3 hitColor = sceneColor.sample(sceneColorSmplr, hitUV).xyz; - float tintStrength = metallic * 0.3499999940395355224609375; - float3 metalTint = mix(float3(1.0), albedo, float3(tintStrength)); - hitColor *= metalTint; - float hitDepthRaw = gDepth.sample(gDepthSmplr, hitUV).x; - float3 hitNormalSample = gNormal.sample(gNormalSmplr, hitUV).xyz; - float hitNormalLenSq = dot(hitNormalSample, hitNormalSample); - float3 hitNormalDir = (hitNormalLenSq > 9.9999997473787516355514526367188e-06) ? (hitNormalSample * rsqrt(hitNormalLenSq)) : (-rayDir); - float geometryValidity = 1.0 - smoothstep(0.99800002574920654296875, 1.0, hitDepthRaw); - geometryValidity *= smoothstep(0.00999999977648258209228515625, 0.100000001490116119384765625, hitNormalLenSq); - float normalFacing = fast::max(dot(hitNormalDir, -rayDir), 0.0); - geometryValidity *= smoothstep(0.0500000007450580596923828125, 0.25, normalFacing); - float hitLuma = dot(hitColor, float3(0.2125999927520751953125, 0.715200006961822509765625, 0.072200000286102294921875)); - float skyLuma = dot(skyReflection, float3(0.2125999927520751953125, 0.715200006961822509765625, 0.072200000286102294921875)); - float luminanceValidity = smoothstep(0.00200000009499490261077880859375, 0.02999999932944774627685546875, hitLuma + (skyLuma * 0.100000001490116119384765625)); - float2 edgeFade = smoothstep(float2(0.0), float2(0.1500000059604644775390625), hitUV) * (float2(1.0) - smoothstep(float2(0.85000002384185791015625), float2(1.0), hitUV)); - float edgeFactor = edgeFade.x * edgeFade.y; - float distanceFade = 1.0 - smoothstep(_96.maxDistance * 0.5, _96.maxDistance, hitDepth); - float roughnessFade = 1.0 - smoothstep(0.0, _96.maxRoughness, roughness); - float hitConfidence = (edgeFactor * distanceFade) * roughnessFade; - hitConfidence *= geometryValidity * luminanceValidity; - float3 F0 = mix(float3(0.039999999105930328369140625), albedo, float3(metallic)); - float3 V = fast::normalize(viewDir); - float cosTheta = fast::max(dot(normal, V), 0.0); - float param = cosTheta; - float3 param_1 = F0; - float3 fresnel = fresnelSchlick(param, param_1); - float fresnelFactor = ((fresnel.x + fresnel.y) + fresnel.z) / 3.0; - float fresnelWeight = mix(fresnelFactor, 1.0, mirrorFactor); - float3 reflectionColor = mix(skyReflection, hitColor, float3(hitConfidence)); - float finalFade = mix(hitConfidence * fresnelWeight, 1.0, mirrorFactor); - finalFade = fast::clamp(finalFade, 0.0, 1.0); - return float4(reflectionColor, finalFade); -} - -fragment main0_out main0(main0_in in [[stage_in]], constant Uniforms& _42 [[buffer(0)]], constant SSRParameters& _96 [[buffer(1)]], texture2d gPosition [[texture(0)]], texture2d sceneColor [[texture(1)]], texture2d gNormal [[texture(2)]], texture2d gAlbedoSpec [[texture(3)]], texture2d gMaterial [[texture(4)]], texture2d gDepth [[texture(5)]], texturecube skybox [[texture(6)]], texture2d historyTexture [[texture(7)]], sampler gPositionSmplr [[sampler(0)]], sampler sceneColorSmplr [[sampler(1)]], sampler gNormalSmplr [[sampler(2)]], sampler gAlbedoSpecSmplr [[sampler(3)]], sampler gMaterialSmplr [[sampler(4)]], sampler gDepthSmplr [[sampler(5)]], sampler skyboxSmplr [[sampler(6)]], sampler historyTextureSmplr [[sampler(7)]], float4 gl_FragCoord [[position]]) -{ - main0_out out = {}; - float3 worldPos = gPosition.sample(gPositionSmplr, in.TexCoord).xyz; - float3 normal = fast::normalize(gNormal.sample(gNormalSmplr, in.TexCoord).xyz); - float3 albedo = gAlbedoSpec.sample(gAlbedoSpecSmplr, in.TexCoord).xyz; - float4 material = gMaterial.sample(gMaterialSmplr, in.TexCoord); - float metallic = material.x; - float roughness = material.y; - float reflectivity = material.w; - if (length(normal) < 0.001000000047497451305389404296875) - { - out.FragColor = float4(0.0); - return out; - } - if (roughness > _96.maxRoughness || fast::max(metallic, reflectivity) < 0.02) - { - out.FragColor = float4(0.0); - return out; - } - float3 viewDir = fast::normalize(_42.cameraPosition - worldPos); - float3 param = worldPos; - float3 param_1 = normal; - float3 param_2 = viewDir; - float param_3 = roughness; - float param_4 = metallic; - float param_5 = reflectivity; - float3 param_6 = albedo; - float4 reflection = SSR(param, param_1, param_2, param_3, param_4, param_5, param_6, _42, _96, gl_FragCoord, gPosition, gPositionSmplr, sceneColor, sceneColorSmplr, gNormal, gNormalSmplr, gDepth, gDepthSmplr, skybox, skyboxSmplr); - if (_96.debugMode != 0) - { - out.FragColor = float4(1.0 - reflection.w, reflection.w, 0.0, 1.0); - return out; - } - if (reflection.w > 0.0 && _96.historyWeight > 0.0) - { - float4 history = historyTexture.sample(historyTextureSmplr, in.TexCoord); - float validHistory = step(0.001, history.w); - reflection = mix(reflection, history, _96.historyWeight * validHistory * reflection.w); - } - out.FragColor = reflection; - return out; -} -)", -}; -static const AtlasPackedShaderSource SSR_FRAG = {SSR_FRAG_PARTS, 2}; - -static const char* const TERRAIN_CONTROL_TESC_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct UBO -{ - float4x4 model; - float4x4 view; - float4x4 projection; -}; - -struct main0_out -{ - float2 TextureCoord; - float4 gl_Position; -}; - -struct main0_in -{ - float2 TexCoord [[attribute(0)]]; - float4 gl_Position [[attribute(1)]]; -}; - -kernel void main0(main0_in in [[stage_in]], constant UBO& _56 [[buffer(0)]], uint gl_InvocationID [[thread_index_in_threadgroup]], uint gl_PrimitiveID [[threadgroup_position_in_grid]], device main0_out* spvOut [[buffer(28)]], constant uint* spvIndirectParams [[buffer(29)]], device MTLQuadTessellationFactorsHalf* spvTessLevel [[buffer(26)]], threadgroup main0_in* gl_in [[threadgroup(0)]]) -{ - device main0_out* gl_out = &spvOut[gl_PrimitiveID * 4]; - if (gl_InvocationID < spvIndirectParams[0]) - gl_in[gl_InvocationID] = in; - threadgroup_barrier(mem_flags::mem_threadgroup); - if (gl_InvocationID >= 4) - return; - gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; - gl_out[gl_InvocationID].TextureCoord = gl_in[gl_InvocationID].TexCoord; - if (gl_InvocationID == 0) - { - float4 eyeSpacePos00 = (_56.view * _56.model) * gl_in[0].gl_Position; - float4 eyeSpacePos01 = (_56.view * _56.model) * gl_in[1].gl_Position; - float4 eyeSpacePos10 = (_56.view * _56.model) * gl_in[2].gl_Position; - float4 eyeSpacePos11 = (_56.view * _56.model) * gl_in[3].gl_Position; - float dist00 = fast::clamp((abs(eyeSpacePos00.z) - 20.0) / 780.0, 0.0, 1.0); - float dist01 = fast::clamp((abs(eyeSpacePos01.z) - 20.0) / 780.0, 0.0, 1.0); - float dist10 = fast::clamp((abs(eyeSpacePos10.z) - 20.0) / 780.0, 0.0, 1.0); - float dist11 = fast::clamp((abs(eyeSpacePos11.z) - 20.0) / 780.0, 0.0, 1.0); - float tessLevel0 = mix(64.0, 4.0, fast::min(dist10, dist00)); - float tessLevel1 = mix(64.0, 4.0, fast::min(dist00, dist01)); - float tessLevel2 = mix(64.0, 4.0, fast::min(dist01, dist11)); - float tessLevel3 = mix(64.0, 4.0, fast::min(dist11, dist10)); - spvTessLevel[gl_PrimitiveID].edgeTessellationFactor[0] = half(tessLevel0); - spvTessLevel[gl_PrimitiveID].edgeTessellationFactor[1] = half(tessLevel1); - spvTessLevel[gl_PrimitiveID].edgeTessellationFactor[2] = half(tessLevel2); - spvTessLevel[gl_PrimitiveID].edgeTessellationFactor[3] = half(tessLevel3); - spvTessLevel[gl_PrimitiveID].insideTessellationFactor[0] = half(fast::max(tessLevel1, tessLevel3)); - spvTessLevel[gl_PrimitiveID].insideTessellationFactor[1] = half(fast::max(tessLevel0, tessLevel2)); - } -} - -)", -}; -static const AtlasPackedShaderSource TERRAIN_CONTROL_TESC = {TERRAIN_CONTROL_TESC_PARTS, 1}; - -static const char* const TERRAIN_EVAL_TESE_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct Uniforms -{ - float4x4 lightViewProj; - float maxPeak; - float seaLevel; - uint isFromMap; -}; - -struct UBO -{ - float4x4 model; - float4x4 view; - float4x4 projection; -}; - -struct main0_out -{ - float2 TexCoord [[user(locn0)]]; - float3 FragPos [[user(locn1)]]; - float Height [[user(locn2)]]; - float4 FragPosLightSpace [[user(locn3)]]; - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float2 TextureCoord [[attribute(0)]]; - float4 gl_Position [[attribute(1)]]; -}; - -struct main0_patchIn -{ - patch_control_point gl_in; -}; - -[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]], constant Uniforms& _84 [[buffer(0)]], constant UBO& _145 [[buffer(1)]], texture2d heightMap [[texture(0)]], sampler heightMapSmplr [[sampler(0)]], float2 gl_TessCoordIn [[position_in_patch]]) -{ - main0_out out = {}; - float3 gl_TessCoord = float3(gl_TessCoordIn.x, gl_TessCoordIn.y, 0.0); - float u = gl_TessCoord.x; - float v = gl_TessCoord.y; - float2 t00 = patchIn.gl_in[0].TextureCoord; - float2 t01 = patchIn.gl_in[1].TextureCoord; - float2 t10 = patchIn.gl_in[2].TextureCoord; - float2 t11 = patchIn.gl_in[3].TextureCoord; - float2 t0 = ((t01 - t00) * u) + t00; - float2 t1 = ((t11 - t10) * u) + t10; - float2 texCoord = ((t1 - t0) * v) + t0; - out.Height = (heightMap.sample(heightMapSmplr, texCoord, level(0.0)).x * _84.maxPeak) - _84.seaLevel; - float4 p00 = patchIn.gl_in[0].gl_Position; - float4 p01 = patchIn.gl_in[1].gl_Position; - float4 p10 = patchIn.gl_in[2].gl_Position; - float4 p11 = patchIn.gl_in[3].gl_Position; - float4 p0 = ((p01 - p00) * u) + p00; - float4 p1 = ((p11 - p10) * u) + p10; - float4 position = ((p1 - p0) * v) + p0; - position.y += out.Height; - out.gl_Position = ((_145.projection * _145.view) * _145.model) * position; - out.TexCoord = texCoord; - out.FragPos = float3((_145.model * position).xyz); - out.FragPosLightSpace = (_84.lightViewProj * _145.model) * position; - return out; -} - -)", -}; -static const AtlasPackedShaderSource TERRAIN_EVAL_TESE = {TERRAIN_EVAL_TESE_PARTS, 1}; - -static const char* const TERRAIN_FRAG_PARTS[] = { -R"(#pragma clang diagnostic ignored "-Wmissing-prototypes" - -#include -#include - -using namespace metal; - -struct PushConstants -{ - uint isFromMap; - float4 directionalColor; - float directionalIntensity; - uint hasLight; - uint useShadowMap; - float3 lightDir; - packed_float3 viewDir; - float ambientStrength; - float shadowBias; - int biomesCount; - float diffuseStrength; - float specularStrength; -}; - -struct TerrainParameters -{ - float maxPeak; - float seaLevel; -}; - -struct Biome -{ - int id; - float4 tintColor; - int useTexture; - int textureId; - float minHeight; - float maxHeight; - float minMoisture; - float maxMoisture; - float minTemperature; - float maxTemperature; -}; - -struct Biome_1 -{ - int id; - float4 tintColor; - int useTexture; - int textureId; - float minHeight; - float maxHeight; - float minMoisture; - float maxMoisture; - float minTemperature; - float maxTemperature; -}; - -struct BiomeBuffer -{ - Biome_1 biomes[1]; -}; - -struct main0_out -{ - float4 FragColor [[color(0)]]; - float4 BrightColor [[color(1)]]; -}; - -struct main0_in -{ - float2 TexCoord [[user(locn0)]]; - float3 FragPos [[user(locn1)]]; - float Height [[user(locn2)]]; - float4 FragPosLightSpace [[user(locn3)]]; -}; - -static inline __attribute__((always_inline)) -float3 calculateNormal(texture2d heightMap, sampler heightMapSmplr, thread const float2& texCoord, thread const float& heightScale) -{ - float h = heightMap.sample(heightMapSmplr, texCoord).x * heightScale; - float dx = dfdx(h); - float dy = dfdy(h); - float3 n = fast::normalize(float3(-dx, 1.0, -dy)); - return n; -} - -static inline __attribute__((always_inline)) -float smoothStepRange(thread const float& value, thread const float& minV, thread const float& maxV) -{ - return smoothstep(minV, maxV, value); -} - -static inline __attribute__((always_inline)) -float4 sampleBiomeTexture(thread const int& id, thread const float2& uv, texture2d texture0, sampler texture0Smplr, texture2d texture1, sampler texture1Smplr, texture2d texture2, sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, texture2d texture4, sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, texture2d texture6, sampler texture6Smplr, texture2d texture7, sampler texture7Smplr, texture2d texture8, sampler texture8Smplr, texture2d texture9, sampler texture9Smplr, texture2d texture10, sampler texture10Smplr, texture2d texture11, sampler texture11Smplr) -{ - if (id == 0) - { - return texture0.sample(texture0Smplr, uv); - } - if (id == 1) - { - return texture1.sample(texture1Smplr, uv); - } - if (id == 2) - { - return texture2.sample(texture2Smplr, uv); - } - if (id == 3) - { - return texture3.sample(texture3Smplr, uv); - } - if (id == 4) - { - return texture4.sample(texture4Smplr, uv); - } - if (id == 5) - { - return texture5.sample(texture5Smplr, uv); - } - if (id == 6) - { - return texture6.sample(texture6Smplr, uv); - } - if (id == 7) - { - return texture7.sample(texture7Smplr, uv); - } - if (id == 8) - { - return texture8.sample(texture8Smplr, uv); - } - if (id == 9) - { - return texture9.sample(texture9Smplr, uv); - } - if (id == 10) - { - return texture10.sample(texture10Smplr, uv); - } - if (id == 11) - { - return texture11.sample(texture11Smplr, uv); - } - return float4(1.0, 0.0, 1.0, 1.0); -} - -static inline __attribute__((always_inline)) -float4 triplanarBlend(thread const int& idx, thread const float3& normal, thread const float3& worldPos, thread const float& scale, texture2d texture0, sampler texture0Smplr, texture2d texture1, sampler texture1Smplr, texture2d texture2, sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, texture2d texture4, sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, texture2d texture6, sampler texture6Smplr, texture2d texture7, sampler texture7Smplr, texture2d texture8, sampler texture8Smplr, texture2d texture9, sampler texture9Smplr, texture2d texture10, sampler texture10Smplr, texture2d texture11, sampler texture11Smplr) -{ - float3 blend = abs(normal); - blend = (blend - float3(0.20000000298023223876953125)) * 7.0; - blend = fast::clamp(blend, float3(0.0), float3(1.0)); - blend /= float3((blend.x + blend.y) + blend.z); - int param = idx; - float2 param_1 = worldPos.yz * scale; - float4 xProj = sampleBiomeTexture(param, param_1, texture0, texture0Smplr, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr, texture11, texture11Smplr); - int param_2 = idx; - float2 param_3 = worldPos.xz * scale; - float4 yProj = sampleBiomeTexture(param_2, param_3, texture0, texture0Smplr, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr, texture11, texture11Smplr); - int param_4 = idx; - float2 param_5 = worldPos.xy * scale; - float4 zProj = sampleBiomeTexture(param_4, param_5, texture0, texture0Smplr, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr, texture11, texture11Smplr); - return ((xProj * blend.x) + (yProj * blend.y)) + (zProj * blend.z); -} - -static inline __attribute__((always_inline)) -float calculateShadow(thread const float4& fragPosLightSpace, thread const float3& normal, constant PushConstants& _331, texture2d shadowMap, sampler shadowMapSmplr) -{ - float3 projCoords = fragPosLightSpace.xyz / float3(fragPosLightSpace.w); - projCoords = (projCoords * 0.5) + float3(0.5); - bool _293 = projCoords.z > 1.0; - bool _300; - if (!_293) - { - _300 = projCoords.x < 0.0; - } - else - { - _300 = _293; - } - bool _307; - if (!_300) - { - _307 = projCoords.x > 1.0; - } - else - { - _307 = _300; - } - bool _314; - if (!_307) - { - _314 = projCoords.y < 0.0; - } - else - { - _314 = _307; - } - bool _321; - if (!_314) - { - _321 = projCoords.y > 1.0; - } - else - { - _321 = _314; - } - if (_321) - { - return 0.0; - } - float currentDepth = projCoords.z; - float bias0 = fast::max(_331.shadowBias * (1.0 - dot(normal, _331.lightDir)), _331.shadowBias * 0.100000001490116119384765625); - float shadow = 0.0; - float2 texelSize = float2(1.0) / float2(int2(shadowMap.get_width(), shadowMap.get_height())); - for (int x = -1; x <= 1; x++) - { - for (int y = -1; y <= 1; y++) - { - float pcfDepth = shadowMap.sample(shadowMapSmplr, (projCoords.xy + (float2(float(x), float(y)) * texelSize))).x; - shadow += float((currentDepth - bias0) > pcfDepth); - } - } - shadow /= 9.0; - return shadow; -} - -static inline __attribute__((always_inline)) -float3 acesToneMapping(thread const float3& color) -{ - return fast::clamp((color * ((color * 2.5099999904632568359375) + float3(0.02999999932944774627685546875))) / ((color * ((color * 2.4300000667572021484375) + float3(0.589999973773956298828125))) + float3(0.14000000059604644775390625)), float3(0.0), float3(1.0)); -} - -fragment main0_out main0(main0_in in [[stage_in]], constant PushConstants& _331 [[buffer(0)]], constant TerrainParameters& _444 [[buffer(1)]], device BiomeBuffer& _534 [[buffer(2)]], texture2d texture0 [[texture(0)]], texture2d texture1 [[texture(1)]], texture2d texture2 [[texture(2)]], texture2d texture3 [[tex)", -R"(ture(3)]], texture2d texture4 [[texture(4)]], texture2d texture5 [[texture(5)]], texture2d texture6 [[texture(6)]], texture2d texture7 [[texture(7)]], texture2d texture8 [[texture(8)]], texture2d texture9 [[texture(9)]], texture2d texture10 [[texture(10)]], texture2d texture11 [[texture(11)]], texture2d shadowMap [[texture(12)]], texture2d heightMap [[texture(13)]], texture2d moistureMap [[texture(14)]], texture2d temperatureMap [[texture(15)]], sampler texture0Smplr [[sampler(0)]], sampler texture1Smplr [[sampler(1)]], sampler texture2Smplr [[sampler(2)]], sampler texture3Smplr [[sampler(3)]], sampler texture4Smplr [[sampler(4)]], sampler texture5Smplr [[sampler(5)]], sampler texture6Smplr [[sampler(6)]], sampler texture7Smplr [[sampler(7)]], sampler texture8Smplr [[sampler(8)]], sampler texture9Smplr [[sampler(9)]], sampler texture10Smplr [[sampler(10)]], sampler texture11Smplr [[sampler(11)]], sampler shadowMapSmplr [[sampler(12)]], sampler heightMapSmplr [[sampler(13)]], sampler moistureMapSmplr [[sampler(14)]], sampler temperatureMapSmplr [[sampler(15)]]) -{ - main0_out out = {}; - if (_331.biomesCount <= 0) - { - out.FragColor = float4(float3((in.Height + _444.seaLevel) / _444.maxPeak), 1.0); - return out; - } - float _463; - if (_331.isFromMap != 0u) - { - _463 = heightMap.sample(heightMapSmplr, in.TexCoord).x * 255.0; - } - else - { - _463 = ((in.Height + _444.seaLevel) / _444.maxPeak) * 255.0; - } - float h = _463; - float m = moistureMap.sample(moistureMapSmplr, in.TexCoord).x * 255.0; - float t = temperatureMap.sample(temperatureMapSmplr, in.TexCoord).x * 255.0; - float texelSize = 1.0 / float(int2(heightMap.get_width(), heightMap.get_height()).x); - float heightScale = 64.0; - float2 param = in.TexCoord; - float param_1 = heightScale; - float3 normal = calculateNormal(heightMap, heightMapSmplr, param, param_1); - float4 baseColor = float4(0.0); - float totalWeight = 0.0; - float _550; - float _574; - float _598; - float4 _628; - for (int i = 0; i < _331.biomesCount; i++) - { - Biome _539; - _539.id = _534.biomes[i].id; - _539.tintColor = _534.biomes[i].tintColor; - _539.useTexture = _534.biomes[i].useTexture; - _539.textureId = _534.biomes[i].textureId; - _539.minHeight = _534.biomes[i].minHeight; - _539.maxHeight = _534.biomes[i].maxHeight; - _539.minMoisture = _534.biomes[i].minMoisture; - _539.maxMoisture = _534.biomes[i].maxMoisture; - _539.minTemperature = _534.biomes[i].minTemperature; - _539.maxTemperature = _534.biomes[i].maxTemperature; - Biome b = _539; - bool _543 = b.minHeight < 0.0; - bool _549; - if (_543) - { - _549 = b.maxHeight < 0.0; - } - else - { - _549 = _543; - } - if (_549) - { - _550 = 1.0; - } - else - { - float param_2 = h; - float param_3 = b.minHeight; - float param_4 = b.maxHeight; - _550 = smoothStepRange(param_2, param_3, param_4); - } - float hW = _550; - bool _567 = b.minMoisture < 0.0; - bool _573; - if (_567) - { - _573 = b.maxMoisture < 0.0; - } - else - { - _573 = _567; - } - if (_573) - { - _574 = 1.0; - } - else - { - float param_5 = m; - float param_6 = b.minMoisture; - float param_7 = b.maxMoisture; - _574 = smoothStepRange(param_5, param_6, param_7); - } - float mW = _574; - bool _591 = b.minTemperature < 0.0; - bool _597; - if (_591) - { - _597 = b.maxTemperature < 0.0; - } - else - { - _597 = _591; - } - if (_597) - { - _598 = 1.0; - } - else - { - float param_8 = t; - float param_9 = b.minTemperature; - float param_10 = b.maxTemperature; - _598 = smoothStepRange(param_8, param_9, param_10); - } - float tW = _598; - float weight = ((1.0 - hW) * mW) * tW; - if (weight > 0.001000000047497451305389404296875) - { - if (b.useTexture == 1) - { - int param_11 = i; - float3 param_12 = normal; - float3 param_13 = in.FragPos; - float param_14 = 0.100000001490116119384765625; - _628 = triplanarBlend(param_11, param_12, param_13, param_14, texture0, texture0Smplr, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr, texture11, texture11Smplr); - } - else - { - _628 = b.tintColor; - } - float4 texColor = _628; - baseColor += (texColor * weight); - totalWeight += weight; - } - } - baseColor /= float4(fast::max(totalWeight, 0.001000000047497451305389404296875)); - float detail = (heightMap.sample(heightMapSmplr, (in.TexCoord * 64.0)).x * 0.100000001490116119384765625) + 0.89999997615814208984375; - float4 _670 = baseColor; - float3 _672 = _670.xyz * detail; - baseColor.x = _672.x; - baseColor.y = _672.y; - baseColor.z = _672.z; - float3 finalColor; - if (_331.hasLight != 0u) - { - float3 L = fast::normalize(-_331.lightDir); - float3 N = fast::normalize(normal); - float3 V = fast::normalize(float3(_331.viewDir)); - float3 ambient = baseColor.xyz * _331.ambientStrength; - float diff = fast::max(dot(N, L), 0.0); - float3 diffuse = ((_331.directionalColor.xyz * (_331.diffuseStrength * diff)) * _331.directionalIntensity) * baseColor.xyz; - float3 H = fast::normalize(L + V); - float spec = powr(fast::max(dot(N, H), 0.0), 32.0); - float3 specular = (_331.directionalColor.xyz * (_331.specularStrength * spec)) * _331.directionalIntensity; - float shadow = 0.0; - if (_331.useShadowMap != 0u) - { - float4 param_15 = in.FragPosLightSpace; - float3 param_16 = N; - shadow = calculateShadow(param_15, param_16, _331, shadowMap, shadowMapSmplr); - } - finalColor = ambient + ((diffuse + specular) * (1.0 - shadow)); - } - else - { - finalColor = baseColor.xyz * _331.ambientStrength; - } - float3 param_17 = finalColor; - out.FragColor = float4(acesToneMapping(param_17), 1.0); - out.BrightColor = float4(0.0); - return out; -} - -)", -}; -static const AtlasPackedShaderSource TERRAIN_FRAG = {TERRAIN_FRAG_PARTS, 2}; - -static const char* const TERRAIN_VERT_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct UBO -{ - float4x4 model; - float4x4 view; - float4x4 projection; -}; - -struct main0_out -{ - float2 TexCoord [[user(locn0)]]; - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; - float2 aTexCoord [[attribute(1)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]], constant UBO& _19 [[buffer(0)]]) -{ - main0_out out = {}; - out.gl_Position = ((_19.projection * _19.view) * _19.model) * float4(in.aPos, 1.0); - out.TexCoord = in.aTexCoord; - return out; -} - -)", -}; -static const AtlasPackedShaderSource TERRAIN_VERT = {TERRAIN_VERT_PARTS, 1}; - -static const char* const TEXTURE_FRAG_PARTS[] = { -R"(#pragma clang diagnostic ignored "-Wmissing-prototypes" - -#include -#include - -using namespace metal; - -struct UBO -{ - uint useTexture; - uint onlyTexture; - int textureCount; -}; - -struct main0_out -{ - float4 FragColor [[color(0)]]; -}; - -struct main0_in -{ - float2 TexCoord [[user(locn0)]]; - float4 outColor [[user(locn1)]]; -}; - -static inline __attribute__((always_inline)) -float4 calculateAllTextures(constant UBO& _28, texture2d texture1, sampler texture1Smplr, thread float2& TexCoord, texture2d texture2, sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, texture2d texture4, sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, texture2d texture6, sampler texture6Smplr, texture2d texture7, sampler texture7Smplr, texture2d texture8, sampler texture8Smplr, texture2d texture9, sampler texture9Smplr, texture2d texture10, sampler texture10Smplr, texture2d texture11, sampler texture11Smplr, texture2d texture12, sampler texture12Smplr, texture2d texture13, sampler texture13Smplr, texture2d texture14, sampler texture14Smplr, texture2d texture15, sampler texture15Smplr, texture2d texture16, sampler texture16Smplr) -{ - float4 color = float4(0.0); - for (int i = 0; i < _28.textureCount; i++) - { - if (i == 0) - { - color += texture1.sample(texture1Smplr, TexCoord); - } - else - { - if (i == 1) - { - color += texture2.sample(texture2Smplr, TexCoord); - } - else - { - if (i == 2) - { - color += texture3.sample(texture3Smplr, TexCoord); - } - else - { - if (i == 3) - { - color += texture4.sample(texture4Smplr, TexCoord); - } - else - { - if (i == 4) - { - color += texture5.sample(texture5Smplr, TexCoord); - } - else - { - if (i == 5) - { - color += texture6.sample(texture6Smplr, TexCoord); - } - else - { - if (i == 6) - { - color += texture7.sample(texture7Smplr, TexCoord); - } - else - { - if (i == 7) - { - color += texture8.sample(texture8Smplr, TexCoord); - } - else - { - if (i == 8) - { - color += texture9.sample(texture9Smplr, TexCoord); - } - else - { - if (i == 9) - { - color += texture10.sample(texture10Smplr, TexCoord); - } - else - { - if (i == 10) - { - color += texture11.sample(texture11Smplr, TexCoord); - } - else - { - if (i == 11) - { - color += texture12.sample(texture12Smplr, TexCoord); - } - else - { - if (i == 12) - { - color += texture13.sample(texture13Smplr, TexCoord); - } - else - { - if (i == 13) - { - color += texture14.sample(texture14Smplr, TexCoord); - } - else - { - if (i == 14) - { - color += texture15.sample(texture15Smplr, TexCoord); - } - else - { - if (i == 15) - { - color += texture16.sample(texture16Smplr, TexCoord); - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - color /= float4(float(_28.textureCount)); - return color; -} - -fragment main0_out main0(main0_in in [[stage_in]], constant UBO& _28 [[buffer(0)]], texture2d texture1 [[texture(0)]], texture2d texture2 [[texture(1)]], texture2d texture3 [[texture(2)]], texture2d texture4 [[texture(3)]], texture2d texture5 [[texture(4)]], texture2d texture6 [[texture(5)]], texture2d texture7 [[texture(6)]], texture2d texture8 [[texture(7)]], texture2d texture9 [[texture(8)]], texture2d texture10 [[texture(9)]], texture2d texture11 [[texture(10)]], texture2d texture12 [[texture(11)]], texture2d texture13 [[texture(12)]], texture2d texture14 [[texture(13)]], texture2d texture15 [[texture(14)]], texture2d texture16 [[texture(15)]], sampler texture1Smplr [[sampler(0)]], sampler texture2Smplr [[sampler(1)]], sampler texture3Smplr [[sampler(2)]], sampler texture4Smplr [[sampler(3)]], sampler texture5Smplr [[sampler(4)]], sampler texture6Smplr [[sampler(5)]], sampler texture7Smplr [[sampler(6)]], sampler texture8Smplr [[sampler(7)]], sampler texture9Smplr [[sampler(8)]], sampler texture10Smplr [[sampler(9)]], sampler texture11Smplr [[sampler(10)]], sampler texture12Smplr [[sampler(11)]], sampler texture13Smplr [[sampler(12)]], sampler texture14Smplr [[sampler(13)]], sampler texture15Smplr [[sampler(14)]], sampler texture16Smplr [[sampler(15)]]) -{ - )", -R"( main0_out out = {}; - if (_28.onlyTexture != 0u) - { - out.FragColor = calculateAllTextures(_28, texture1, texture1Smplr, in.TexCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr, texture11, texture11Smplr, texture12, texture12Smplr, texture13, texture13Smplr, texture14, texture14Smplr, texture15, texture15Smplr, texture16, texture16Smplr); - return out; - } - if (_28.useTexture != 0u) - { - out.FragColor = calculateAllTextures(_28, texture1, texture1Smplr, in.TexCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr, texture11, texture11Smplr, texture12, texture12Smplr, texture13, texture13Smplr, texture14, texture14Smplr, texture15, texture15Smplr, texture16, texture16Smplr) * in.outColor; - } - else - { - out.FragColor = in.outColor; - } - return out; -} - -)", -}; -static const AtlasPackedShaderSource TEXTURE_FRAG = {TEXTURE_FRAG_PARTS, 2}; - -static const char* const TEXTURE_VERT_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct UBO -{ - float4x4 model; - float4x4 view; - float4x4 projection; -}; - -struct main0_out -{ - float2 TexCoord [[user(locn0)]]; - float4 outColor [[user(locn1)]]; - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; - float4 aColor [[attribute(1)]]; - float2 aTexCoord [[attribute(2)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]], constant UBO& _13 [[buffer(0)]]) -{ - main0_out out = {}; - float4x4 mvp = (_13.projection * _13.view) * _13.model; - out.gl_Position = mvp * float4(in.aPos, 1.0); - out.TexCoord = in.aTexCoord; - out.outColor = in.aColor; - return out; -} - -)", -}; -static const AtlasPackedShaderSource TEXTURE_VERT = {TEXTURE_VERT_PARTS, 1}; - -static const char* const TEXT_FRAG_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct TextColor -{ - float3 textColor; -}; - -struct main0_out -{ - float4 color [[color(0)]]; -}; - -struct main0_in -{ - float2 texCoords [[user(locn0)]]; -}; - -fragment main0_out main0(main0_in in [[stage_in]], constant TextColor& _30 [[buffer(0)]], texture2d text [[texture(0)]], sampler textSmplr [[sampler(0)]]) -{ - main0_out out = {}; - float4 sampled = float4(1.0, 1.0, 1.0, text.sample(textSmplr, in.texCoords).x); - out.color = float4(_30.textColor, 1.0) * sampled; - return out; -} - -)", -}; -static const AtlasPackedShaderSource TEXT_FRAG = {TEXT_FRAG_PARTS, 1}; - -static const char* const TEXT_VERT_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct Uniforms -{ - float4x4 projection; -}; - -struct main0_out -{ - float2 texCoords [[user(locn0)]]; - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float4 vertex0 [[attribute(0)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]], constant Uniforms& _19 [[buffer(0)]]) -{ - main0_out out = {}; - out.gl_Position = _19.projection * float4(in.vertex0.xy, 0.0, 1.0); - out.texCoords = in.vertex0.zw; - return out; -} - -)", -}; -static const AtlasPackedShaderSource TEXT_VERT = {TEXT_VERT_PARTS, 1}; - -static const char* const UPSAMPLE_FRAG_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct Params -{ - float2 srcResolution; - float filterRadius; -}; - -struct main0_out -{ - float4 upsample [[color(0)]]; -}; - -struct main0_in -{ - float2 TexCoord [[user(locn0)]]; -}; - -fragment main0_out main0(main0_in in [[stage_in]], constant Params& _13 [[buffer(0)]], texture2d srcTexture [[texture(0)]], sampler srcTextureSmplr [[sampler(0)]]) -{ - main0_out out = {}; - float2 texelSize = - float2(1.0) / float2(srcTexture.get_width(), srcTexture.get_height()); - float radius = clamp(_13.filterRadius, 1.0, 8.0); - float x = radius * texelSize.x; - float y = radius * texelSize.y; - float2 texCoord = in.TexCoord; - float2 step1 = float2(x, y); - float2 step2 = step1 * 2.0; - float3 upsampleColor = float3(0.0); - float totalWeight = 0.0; - - float wCenter = 0.16; - float wCardinal1 = 0.11; - float wDiagonal1 = 0.075; - float wCardinal2 = 0.04; - float wDiagonal2 = 0.015; - - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord).xyz * wCenter; - totalWeight += wCenter; - - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(step1.x, 0.0)).xyz * wCardinal1; - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(-step1.x, 0.0)).xyz * wCardinal1; - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(0.0, step1.y)).xyz * wCardinal1; - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(0.0, -step1.y)).xyz * wCardinal1; - totalWeight += wCardinal1 * 4.0; - - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(step1.x, step1.y)).xyz * wDiagonal1; - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(-step1.x, step1.y)).xyz * wDiagonal1; - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(step1.x, -step1.y)).xyz * wDiagonal1; - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(-step1.x, -step1.y)).xyz * wDiagonal1; - totalWeight += wDiagonal1 * 4.0; - - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(step2.x, 0.0)).xyz * wCardinal2; - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(-step2.x, 0.0)).xyz * wCardinal2; - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(0.0, step2.y)).xyz * wCardinal2; - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(0.0, -step2.y)).xyz * wCardinal2; - totalWeight += wCardinal2 * 4.0; - - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(step2.x, step2.y)).xyz * wDiagonal2; - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(-step2.x, step2.y)).xyz * wDiagonal2; - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(step2.x, -step2.y)).xyz * wDiagonal2; - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(-step2.x, -step2.y)).xyz * wDiagonal2; - totalWeight += wDiagonal2 * 4.0; - - upsampleColor /= float3(max(totalWeight, 1e-5)); - out.upsample = float4(upsampleColor, 1.0); - return out; -} -)", -}; -static const AtlasPackedShaderSource UPSAMPLE_FRAG = {UPSAMPLE_FRAG_PARTS, 1}; - -static const char* const VOLUMETRIC_FRAG_PARTS[] = { -R"(#pragma clang diagnostic ignored "-Wmissing-prototypes" - -#include -#include - -using namespace metal; - -struct Sun -{ - float2 sunPos; -}; - -struct VolumetricParameters -{ - float density; - float weight; - float decay; - float exposure; -}; - -struct DirectionalLight -{ - float3 color; -}; - -struct main0_out -{ - float4 FragColor [[color(0)]]; -}; - -struct main0_in -{ - float2 TexCoords [[user(locn0)]]; -}; - -static inline __attribute__((always_inline)) -float3 computeVolumetricLighting(thread const float2& uv, constant Sun& _21, constant VolumetricParameters& _31, texture2d sceneTexture, sampler sceneTextureSmplr, constant DirectionalLight& directionalLight) -{ - float3 color = float3(0.0); - float2 deltaTexCoord = (_21.sunPos - uv) * _31.density; - float2 coord = uv; - float illuminationDecay = 1.0; - for (int i = 0; i < 48; i++) - { - coord += deltaTexCoord; - bool _59 = coord.x < 0.0; - bool _66; - if (!_59) - { - _66 = coord.x > 1.0; - } - else - { - _66 = _59; - } - bool _74; - if (!_66) - { - _74 = coord.y < 0.0; - } - else - { - _74 = _66; - } - bool _81; - if (!_74) - { - _81 = coord.y > 1.0; - } - else - { - _81 = _74; - } - if (_81) - { - break; - } - float3 sampled = sceneTexture.sample(sceneTextureSmplr, coord).xyz; - float brightness = dot(sampled, float3(0.2989999949932098388671875, 0.58700001239776611328125, 0.114000000059604644775390625)); - float3 atmosphere = directionalLight.color * 0.0199999995529651641845703125; - if (brightness > 0.5) - { - atmosphere += (sampled * 0.5); - } - atmosphere *= (illuminationDecay * _31.weight); - color += atmosphere; - illuminationDecay *= _31.decay; - } - return color * 5.0; -} - -fragment main0_out main0(main0_in in [[stage_in]], constant Sun& _21 [[buffer(0)]], constant VolumetricParameters& _31 [[buffer(1)]], constant DirectionalLight& directionalLight [[buffer(2)]], texture2d sceneTexture [[texture(0)]], sampler sceneTextureSmplr [[sampler(0)]]) -{ - main0_out out = {}; - float2 param = in.TexCoords; - float3 rays = computeVolumetricLighting(param, _21, _31, sceneTexture, sceneTextureSmplr, directionalLight); - out.FragColor = float4(rays, 1.0); - return out; -} -)", -}; -static const AtlasPackedShaderSource VOLUMETRIC_FRAG = {VOLUMETRIC_FRAG_PARTS, 1}; - -static const char* const VOLUMETRIC_VERT_PARTS[] = { -R"(#include -#include - -using namespace metal; - -struct main0_out -{ - float2 TexCoords [[user(locn0)]]; - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; - float2 aTexCoords [[attribute(2)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]]) -{ - main0_out out = {}; - out.gl_Position = float4(in.aPos, 1.0); - out.TexCoords = in.aTexCoords; - return out; -} -)", -}; -static const AtlasPackedShaderSource VOLUMETRIC_VERT = {VOLUMETRIC_VERT_PARTS, 1}; - -#endif // ATLAS_GENERATED_SHADERS_H diff --git a/include/atlas/core/shader.h b/include/atlas/core/shader.h index e514d4a9..510e3721 100644 --- a/include/atlas/core/shader.h +++ b/include/atlas/core/shader.h @@ -23,8 +23,8 @@ #include -#define DEFAULT_FRAG_SHADER Main -#define DEFAULT_VERT_SHADER Main +#define DEFAULT_FRAG_SHADER Deferred +#define DEFAULT_VERT_SHADER Deferred /** * @brief Enumeration of default vertex shaders provided by the Atlas engine. diff --git a/include/atlas/object.h b/include/atlas/object.h index ff99b023..ed2aa0b5 100644 --- a/include/atlas/object.h +++ b/include/atlas/object.h @@ -546,7 +546,7 @@ class CoreObject : public GameObject { void disableDeferredRendering() { useDeferredRendering = false; this->shaderProgram = ShaderProgram::fromDefaultShaders( - AtlasVertexShader::Main, AtlasFragmentShader::Main); + AtlasVertexShader::Deferred, AtlasFragmentShader::Deferred); } /** diff --git a/include/atlas/window.h b/include/atlas/window.h index fc648c75..35f852ab 100644 --- a/include/atlas/window.h +++ b/include/atlas/window.h @@ -984,14 +984,6 @@ class Window { int ssrQuality = 1; bool ssrDebugMode = false; - /** - * @brief Whether to use multi-pass point light shadow rendering. - * This is true on platforms without geometry shader support (e.g., - * macOS/MoltenVK). When true, point light shadows are rendered with 6 - * separate passes instead of 1. - */ - bool useMultiPassPointShadows = false; - bool clipPlaneEnabled = false; glm::vec4 clipPlaneEquation{0.0f}; diff --git a/justfile b/justfile index b552cc01..9c680776 100644 --- a/justfile +++ b/justfile @@ -48,7 +48,6 @@ clangd backend="AUTO" bezel_native="OFF": -DCMAKE_CXX_COMPILER_LAUNCHER= \ .. ln -sf build/compile_commands.json compile_commands.json - ln -sf ../build/compile_commands.json opal/compile_commands.json lint: run-clang-tidy -p build -quiet -warnings-as-errors='*' diff --git a/opal b/opal index 304833e5..c9c8e5b1 160000 --- a/opal +++ b/opal @@ -1 +1 @@ -Subproject commit 304833e54ffab148a07a0081bff20efae08b727a +Subproject commit c9c8e5b170ca7334b73b6e15fc901cf30664293a diff --git a/scripts/check_shader_contracts.py b/scripts/check_shader_contracts.py new file mode 100644 index 00000000..c63da302 --- /dev/null +++ b/scripts/check_shader_contracts.py @@ -0,0 +1,98 @@ +from pathlib import Path +import subprocess +import argparse +import shutil +import tempfile +parser = argparse.ArgumentParser() +parser.add_argument('artifacts', type=Path) +parser.add_argument('--spirv-cross-prefix', type=Path, default=Path(shutil.which('spirv-cross')).parent.parent) +arguments = parser.parse_args() +root = Path(__file__).resolve().parent.parent +workspace = tempfile.TemporaryDirectory(prefix='atlas-shader-contracts-') +tmp = Path(workspace.name) +cpp=(root/'opal/src/metal/metal_state.cpp').read_text();header=(root/'opal/src/metal/metal_state.h').read_text();opal=(root/'opal/include/opal/opal.h').read_text();shader=(root/'opal/src/shaders.cpp').read_text() +includes='''#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +using VkDescriptorType = int; +constexpr int VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER = 1; +constexpr int VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE = 2; +constexpr int VK_DESCRIPTOR_TYPE_SAMPLER = 3; +constexpr int VK_DESCRIPTOR_TYPE_STORAGE_IMAGE = 4; +''' +metal=header[header.index('enum class MetalProgramStage'):header.index('struct ContextState')] +metal+='''enum class TextureType { Texture2D, TextureCubeMap, Texture3D, Texture2DArray }; +struct ProgramState { +void *vertexFunction = reinterpret_cast(1); +void *fragmentFunction = reinterpret_cast(1); +void *computeFunction = reinterpret_cast(1); +bool computeProgram = false; +std::unordered_map layouts; +std::vector bindings; +std::unordered_map bindingSize; +std::unordered_map textureBindings; +std::unordered_map textureTypesByBinding; +std::unordered_map> uniformResolutionCache; +}; +''' +metal+=cpp[cpp.index('template inline T alignUp'):cpp.index('template inline T enumOr')] +metal+=cpp[cpp.index('uint32_t stageBindingKey('):cpp.index('MTL::PixelFormat textureFormatToPixelFormat')] +metal+=cpp[cpp.index('bool parseProgramLayouts('):cpp.index('std::string makePipelineKey(')] +ubo=opal[opal.index('struct UniformBindingInfo {'):opal.index('};',opal.index('struct UniformBindingInfo {'))+2] +vulkan=ubo+'''\nstruct Shader { +std::vector spirvBytecode; +std::unordered_map uniformBindings; +void performReflection(); +};\n'''+shader[shader.index('void Shader::performReflection()'):shader.index('const UniformBindingInfo *\nShaderProgram::findUniform')] +main=r''' +std::string read(const std::string &p) { std::ifstream f(p); return {std::istreambuf_iterator(f), {}}; } +int main(int argc, char **argv) { + const std::string root = argv[1]; + const std::vector>> checks = { + {"DEFERRED_VERT", {"model", "view", "projection", "isInstanced"}}, + {"DEFERRED_FRAG", {"textureTypes[0]", "textureTypes[15]", "textureCount", "cameraPosition", "normalMapStrength", "useNormalMap", "textureScale", "textureOffset", "material.albedo", "material.metallic"}}, + {"LIGHT_FRAG", {"cameraPosition", "useIBL", "directionalLightCount", "pointLightCount", "environment.rimLightColor", "ambientLight.color", "ps.origin"}}, + {"GAUSSIAN_FRAG", {"weight[0]", "weight[4]", "horizontal", "radius"}}, + {"SSAO_FRAG", {"samples[0]", "samples[63]", "projection"}}, + {"POINT_DEPTH_NOGEOM_VERT", {"model", "isInstanced", "shadowMatrix"}}, + {"POINT_DEPTH_NOGEOM_FRAG", {"lightPos", "far_plane"}}, + {"FULLSCREEN_FRAG", {"environment.fogColor", "environment.fogIntensity", "hasBrightTexture", "projectionMatrix", "invProjectionMatrix", "viewMatrix", "deltaTime"}}, + {"PATH_DENOISE", {"stepWidth", "bloomThreshold"}} + }; + int count=0; + for (const auto &[symbol, names] : checks) { + auto bytes=read(root+"/"+symbol+".spv"); + Shader shader; shader.spirvBytecode.resize(bytes.size()/4); std::memcpy(shader.spirvBytecode.data(),bytes.data(),bytes.size()); shader.performReflection(); + ProgramState state; + if(symbol=="PATH_DENOISE") parseComputeProgramLayouts(read(root+"/"+symbol+".metal"),state); + else parseProgramLayouts(symbol.ends_with("VERT")?read(root+"/"+symbol+".metal"):"",symbol.ends_with("FRAG")?read(root+"/"+symbol+".metal"):"",state); + for(const auto &name:names) { + auto found=shader.uniformBindings.find(name); + auto locations=resolveUniformLocations(state,name); + if(found==shader.uniformBindings.end() || locations.empty()) {std::cerr<second.offset!=locations.front().offset){std::cerr<\n'+metal+'\n'+vulkan+main;(tmp/'reflection.cpp').write_text(source) +subprocess.run(['clang++','-std=c++20','-I'+str(arguments.spirv_cross_prefix/'include'),str(tmp/'reflection.cpp'),str(arguments.spirv_cross_prefix/'lib/libspirv-cross-core.a'),'-o',str(tmp/'reflection')],check=True) +subprocess.run([str(tmp/'reflection'),str(arguments.artifacts)],check=True) diff --git a/scripts/migrate_shaders.sh b/scripts/migrate_shaders.sh deleted file mode 100755 index d374e028..00000000 --- a/scripts/migrate_shaders.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -if [ $# -ne 2 ]; then - echo "Usage: $0 " - exit 1 -fi - -DIR="$1" -VERSION="$2" - -if [ ! -d "$DIR" ]; then - echo "Error: '$DIR' is not a directory" - exit 1 -fi - -for file in "$DIR"/*; do - [ -f "$file" ] || continue - - { echo "#version ${VERSION} core"; tail -n +2 "$file"; } > "$file.tmp" && mv "$file.tmp" "$file" - - echo "Updated: $file → #version ${VERSION} core" -done diff --git a/scripts/pack_shaders.py b/scripts/pack_shaders.py index a1169303..152d18ec 100644 --- a/scripts/pack_shaders.py +++ b/scripts/pack_shaders.py @@ -1,231 +1,153 @@ -import os -import sys +import argparse +import json +from pathlib import Path +import re import subprocess import tempfile -if len(sys.argv) < 3: - print("Usage: python pack_shaders.py [opengl|vulkan|metal]") - sys.exit(1) - -input_dir = sys.argv[1] -output_file = sys.argv[2] -mode_arg = sys.argv[3].lower() if len(sys.argv) >= 4 else None - -MAX_CHUNK = 8192 -GLSL_EXTENSIONS = {'.vert', '.frag', '.comp', '.geom', '.tesc', '.tese', '.glsl'} -SHADER_EXTENSIONS = GLSL_EXTENSIONS | {'.metal'} - - -def parse_backend_mode(mode): - if mode is None: - return None - if mode in ('opengl', 'vulkan', 'metal'): - return mode - if mode in ('true', '1', 'yes'): - return 'vulkan' - if mode in ('false', '0', 'no'): - return 'opengl' - raise ValueError(f"Unknown backend mode '{mode}'. Expected opengl, vulkan, or metal.") - - -def compile_to_spirv(glsl_code, shader_path): - """Compile GLSL to SPIR-V using glslangValidator or glslc""" - ext = os.path.splitext(shader_path)[1].lower() - stage_map = { - '.vert': 'vert', - '.frag': 'frag', - '.comp': 'comp', - '.geom': 'geom', - '.tesc': 'tesc', - '.tese': 'tese' - } - stage = stage_map.get(ext, 'vert') - - with tempfile.NamedTemporaryFile(mode='w', suffix=f'.{stage}', delete=False) as tmp_in: - tmp_in.write(glsl_code) - tmp_in_path = tmp_in.name - - tmp_out_path = tmp_in_path + '.spv' - - try: - try: - subprocess.run( - ['glslangValidator', '-V', '-o', tmp_out_path, tmp_in_path], - check=True, - capture_output=True - ) - except (subprocess.CalledProcessError, FileNotFoundError): - subprocess.run( - ['glslc', f'-fshader-stage={stage}', '-o', tmp_out_path, tmp_in_path], - check=True, - capture_output=True - ) - - with open(tmp_out_path, 'rb') as f: - return f.read() - - except subprocess.CalledProcessError as e: - print(f"Error compiling {shader_path}: {e}") - print(f"stderr: {e.stderr.decode() if e.stderr else 'N/A'}") - return None - - finally: - if os.path.exists(tmp_in_path): - os.remove(tmp_in_path) - if os.path.exists(tmp_out_path): - os.remove(tmp_out_path) - - -def detect_backend(path): - explicit_backend = parse_backend_mode(mode_arg) - if explicit_backend is not None: - return explicit_backend - - normalized = os.path.normpath(path).lower() - base = os.path.basename(normalized) - if base in ('opengl', 'vulkan', 'metal'): - return base - parts = normalized.split(os.sep) - for backend in ('metal', 'vulkan', 'opengl'): - if backend in parts: - return backend - return 'opengl' - - -try: - backend_mode = detect_backend(input_dir) -except ValueError as e: - print(f"Error: {e}") - sys.exit(1) - - -def canonical_shader_name(filename): - if filename.endswith('.metal'): - filename = filename[:-6] - return filename - - -def variable_name_from_filename(filename): - canonical = canonical_shader_name(filename) - return canonical.replace('.', '_').replace('-', '_').upper() - - -def should_compile_file(path, backend): - if backend != 'vulkan': - return False - ext = os.path.splitext(path)[1].lower() - if ext == '.metal': - return False - return ext in GLSL_EXTENSIONS - - -def shader_priority(relative_path, backend): - rel = relative_path.replace('\\', '/') - if backend == 'metal': - if rel.startswith('vulkan/'): - return 2 - if rel.startswith('opengl/'): - return 1 - return 0 - - -def write_chunks(out, var_name, contents): - """Write shader source as chunk arrays to avoid oversized string literals""" - out.write(f'static const char* const {var_name}_PARTS[] = {{\n') - - part_count = 0 - if contents == "": - out.write('R"()",\n') - part_count = 1 - else: - for i in range(0, len(contents), MAX_CHUNK): - chunk = contents[i:i + MAX_CHUNK] - out.write(f'R"({chunk})",\n') - part_count += 1 - - out.write('};\n') - out.write( - f'static const AtlasPackedShaderSource {var_name} = ' - f'{{{var_name}_PARTS, {part_count}}};\n\n' - ) - - -with open(output_file, "w") as out: - backend = backend_mode - - out.write("// This file contains packed shader source code.\n") - if backend == 'vulkan': - out.write("// Shaders compiled to SPIR-V for Vulkan\n") - elif backend == 'metal': - out.write("// Metal shaders packed as source\n") - out.write("#ifndef ATLAS_GENERATED_SHADERS_H\n") - out.write("#define ATLAS_GENERATED_SHADERS_H\n\n") - out.write("#include \n\n") - out.write("namespace opal {\n") - out.write("const char *packedShaderSource(const char *const *parts, std::size_t count);\n") - out.write("}\n\n") - out.write("struct AtlasPackedShaderSource {\n") - out.write(" const char *const *parts;\n") - out.write(" std::size_t count;\n\n") - out.write(" operator const char *() const {\n") - out.write(" return opal::packedShaderSource(parts, count);\n") - out.write(" }\n") - out.write("};\n\n") - - shader_files = [] - for root, _, files in os.walk(input_dir): - for filename in files: - path = os.path.join(root, filename) - if not os.path.isfile(path): - continue - ext = os.path.splitext(filename)[1].lower() - if ext not in SHADER_EXTENSIONS: - continue - rel = os.path.relpath(path, input_dir) - shader_files.append((rel, path, filename)) - - shader_files.sort(key=lambda x: x[0].replace('\\', '/')) - - chosen_files = {} - for rel, path, filename in shader_files: - var_name = variable_name_from_filename(filename) - priority = shader_priority(rel, backend) - existing = chosen_files.get(var_name) - if existing is None: - chosen_files[var_name] = (priority, rel, path, filename) +def run(command): + result = subprocess.run(command, capture_output=True, text=True) + if result.returncode: + raise RuntimeError(f"Shader command failed: {' '.join(map(str, command))}\n" + f"{result.stdout}{result.stderr}") + return result.stdout + + +def read_source(path, stack=()): + path = Path(path).resolve() + if path in stack: + raise ValueError(f"Cyclic shader include: {path}") + return re.sub( + r'^[ \t]*#include "([^"\n]+)"\n', + lambda match: read_source(path.parent / match[1], (*stack, path)), + path.read_text(), flags=re.MULTILINE) + + +def write_atomic(path, contents): + path.parent.mkdir(parents=True, exist_ok=True) + with tempfile.NamedTemporaryFile(mode="w", dir=path.parent, + delete=False) as temporary: + temporary.write(contents) + temporary_path = Path(temporary.name) + temporary_path.replace(path) + + +def pack_source(symbol, source): + if ')ATLAS_SHADER"' in source: + raise ValueError(f"Raw-string delimiter collision in {symbol}") + chunks = [source[i:i + 8192] for i in range(0, len(source), 8192)] or [""] + parts = "\n".join(f'R"ATLAS_SHADER({chunk})ATLAS_SHADER",' for chunk in chunks) + return (f"inline const char *const {symbol}_PARTS[] = {{\n{parts}\n}};\n" + f"inline const AtlasPackedShaderSource {symbol} = " + f"{{{symbol}_PARTS, {len(chunks)}}};\n") + + +def generate(input_dir, output_file, backend, slangc, spirv_cross, + photon_backend, photon_manifest=None): + input_dir = Path(input_dir).resolve() + output_file = Path(output_file).resolve() + artifact_dir = output_file.parent / "shader_artifacts" + artifact_dir.mkdir(parents=True, exist_ok=True) + manifest = json.loads((input_dir / "manifest.json").read_text()) + entries = list(manifest["shaders"]) + native = [] + if photon_backend != "off": + if photon_backend != backend: + raise ValueError("Photon's native backend must match Atlas's backend") + native_manifest = (Path(photon_manifest) if photon_manifest else + input_dir / "photon" / photon_backend / "manifest.json") + if not native_manifest.is_file(): + raise ValueError(f"Photon {photon_backend} shaders are not implemented: " + f"missing {native_manifest}") + extension = json.loads(native_manifest.read_text()) + entries.extend(extension.get("shaders", [])) + native = extension.get("native", []) + symbols = {entry["symbol"] for entry in entries + native} + if not {"PATH", "DDGI", "DDGI_WRITE"}.issubset(symbols): + raise ValueError("Photon requires PATH, DDGI, and DDGI_WRITE shaders") + + packed = {} + artifacts = [] + for entry in sorted(entries, key=lambda item: item["symbol"]): + symbol = entry["symbol"] + if not re.fullmatch(r"[A-Z][A-Z0-9_]*", symbol) or symbol in packed: + raise ValueError(f"Invalid or duplicate shader symbol: {symbol}") + source = input_dir / entry["source"] + stage = entry["stage"] + if stage not in ("vertex", "fragment", "compute"): + raise ValueError(f"Unsupported shader stage: {stage}") + spirv = artifact_dir / f"{symbol}.spv" + run([slangc, str(source), "-I", str(input_dir), "-D", + f"ATLAS_{stage.upper()}=1", "-entry", entry["entry"], + "-target", "spirv", "-profile", "spirv_1_3", "-preserve-params", + "-o", str(spirv)]) + reflection = run([spirv_cross, str(spirv), "--reflect"]) + write_atomic(artifact_dir / f"{symbol}.json", reflection) + if backend == "metal": + metal = artifact_dir / f"{symbol}.metal" + run([spirv_cross, str(spirv), "--msl", "--msl-version", "230000", + "--output", str(metal)]) + packed[symbol] = metal.read_text() else: - prev_priority, prev_rel, _, _ = existing - if priority > prev_priority: - chosen_files[var_name] = (priority, rel, path, filename) - print(f"Info: Replaced shader symbol {var_name}: {prev_rel} -> {rel}") - else: - print(f"Info: Skipping duplicate shader symbol {var_name}: {rel}") - - ordered_entries = sorted(chosen_files.items(), key=lambda item: item[0]) - for var_name, (_, rel, path, filename) in ordered_entries: - with open(path, "r") as f: - contents = f.read() - - if should_compile_file(path, backend): - if contents.strip() == "": - out.write(f'// {rel} is empty\n') - write_chunks(out, var_name, "") - else: - spirv_bytes = compile_to_spirv(contents, path) - if spirv_bytes is not None: - hex_string = ''.join(f'{b:02x}' for b in spirv_bytes) - out.write(f'// Compiled from {rel} (SPIR-V as hex string)\n') - write_chunks(out, var_name, hex_string) - else: - print(f"Warning: Failed to compile {rel}, emitting empty shader") - write_chunks(out, var_name, "") + packed[symbol] = spirv.read_bytes().hex() + artifacts.append({**entry, "spirv": str(spirv)}) + + for entry in native: + symbol = entry["symbol"] + if not re.fullmatch(r"[A-Z][A-Z0-9_]*", symbol) or symbol in packed: + raise ValueError(f"Invalid or duplicate native shader symbol: {symbol}") + source = input_dir / entry["source"] + if backend == "metal" and source.suffix == ".metal": + packed[symbol] = read_source(source) + write_atomic(artifact_dir / f"{symbol}.metal", packed[symbol]) + elif backend == "vulkan" and source.suffix == ".spv": + data = source.read_bytes() + if len(data) % 4 or data[:4] != b"\x03\x02\x23\x07": + raise ValueError(f"Invalid native SPIR-V: {source}") + packed[symbol] = data.hex() else: - write_chunks(out, var_name, contents) + raise ValueError(f"Invalid native {backend} shader: {source}") - out.write("#endif // ATLAS_GENERATED_SHADERS_H\n") + header = """#pragma once +#include +namespace opal { +const char *packedShaderSource(const char *const *parts, std::size_t count); +} -print(f"Shaders packed successfully to {output_file}") -if backend_mode == 'vulkan': - print("SPIR-V compilation enabled") +struct AtlasPackedShaderSource { + const char *const *parts; + std::size_t count; + operator const char *() const { + return opal::packedShaderSource(parts, count); + } +}; + +""" + header += f"#define ATLAS_HAS_PHOTON {int(photon_backend != 'off')}\n" + header += f"#define ATLAS_PHOTON_NATIVE_METAL {int(photon_backend == 'metal')}\n\n" + for symbol, source in sorted(packed.items()): + header += pack_source(symbol, source) + "\n" + write_atomic(output_file, header) + write_atomic(artifact_dir / "manifest.json", json.dumps(artifacts, indent=2) + "\n") + print(f"Generated {len(entries)} Slang stages and {len(native)} native " + f"Photon shaders for {backend}: {output_file}") + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("input_dir") + parser.add_argument("output_file") + parser.add_argument("backend", choices=("vulkan", "metal")) + parser.add_argument("--slangc", default="slangc") + parser.add_argument("--spirv-cross", default="spirv-cross") + parser.add_argument("--photon-backend", choices=("off", "metal", "vulkan"), + default="off") + parser.add_argument("--photon-manifest") + arguments = parser.parse_args() + generate(**vars(arguments)) + + +if __name__ == "__main__": + main() diff --git a/shaders/README.md b/shaders/README.md new file mode 100644 index 00000000..1dd2974b --- /dev/null +++ b/shaders/README.md @@ -0,0 +1,26 @@ +# Atlas shaders + +Slang is the source language for Atlas raster passes and Photon denoising. `manifest.json` records each program, stage, entry point, and packed C++ symbol. Vertex and fragment stages share a file; `ATLAS_VERTEX`, `ATLAS_FRAGMENT`, and `ATLAS_COMPUTE` select the stage. Reusable code lives in `utils`. + +CMake requires `slangc` and `spirv-cross`. Slang 2024.13 is the validated compiler and is installed by CI. Override `SLANGC_EXECUTABLE` or `SPIRV_CROSS_EXECUTABLE` when these tools are outside PATH. + +`generate_shaders` compiles Slang to SPIR-V. Vulkan consumes that bytecode; Metal consumes MSL generated from the same bytecode with SPIRV-Cross. The packed header and intermediate artifacts live under `build/generated//atlas/core`. Nothing generated is written into the source tree. Source files, shared libraries, manifests, compiler executables, and generation settings are dependencies. Compilation errors stop generation; an incomplete header never replaces the previous one. + +Author entry points use `vertexMain`, `screenVertexMain`, `fragmentMain`, or `computeMain`. Generated entry points are normalized to Vulkan `main` and Metal `main0`, matching Opal's existing loaders. Matrices use row-major Slang storage and row-vector `mul` calls to preserve Atlas's column-major CPU matrix bytes. Do not change one convention without the other. + +The name-based uniform API remains supported. Opal reflects generated array and matrix wrappers, indexed uniforms, named storage buffers, and sampler-free textures. Photon ray tracing stays native Metal under `photon/metal`; its local includes are expanded before packing. + +`BACKEND` supports `AUTO`, `METAL`, and `VULKAN`. `ATLAS_PHOTON_BACKEND` supports `AUTO`, `METAL`, `VULKAN`, and `OFF`; AUTO enables native Photon only on Metal. A future Vulkan implementation must provide `photon/vulkan/manifest.json`, with `PATH`, `DDGI`, and `DDGI_WRITE` entries. The manifest accepts `shaders` entries in the root manifest format or `native` entries containing a shader-root-relative `.spv` source and symbol. Selecting Vulkan Photon before this exists fails explicitly. No Vulkan ray-tracing implementation is included. + +Legacy forward Main shaders now resolve to deferred PBR. Unused Blinn-Phong, tessellated terrain, geometry-shadow variants, SSR blur, and volumetric-cloud shaders have been removed. The old terrain and geometry shader factory values reject use explicitly. Cloud settings retained in older scene files no longer activate a rendering pass. Volumetric light scattering, fluids, bloom, SSAO, SSR, skyboxes, text, and debugging passes remain. + +Shader-only verification, without building Atlas: + +```sh +python3 scripts/pack_shaders.py shaders /tmp/atlas-shaders/default_shaders.h metal --photon-backend metal +python3 scripts/check_shader_contracts.py /tmp/atlas-shaders/shader_artifacts +spirv-val --target-env vulkan1.1 /tmp/atlas-shaders/shader_artifacts/DEFERRED_FRAG.spv +xcrun -sdk macosx metal -std=metal3.0 -c /tmp/atlas-shaders/shader_artifacts/DEFERRED_FRAG.metal -o /tmp/deferred.air +``` + +The contract checker compiles an isolated harness from Opal's actual reflection functions and compares Vulkan and Metal uniform offsets and buffer names. It requires a C++20 compiler and SPIRV-Cross development headers/library; `--spirv-cross-prefix` selects their installation prefix. Shader validation does not replace an Atlas build or a rendered-scene check. diff --git a/shaders/deferred/deferred.slang b/shaders/deferred/deferred.slang new file mode 100644 index 00000000..ae9ebf97 --- /dev/null +++ b/shaders/deferred/deferred.slang @@ -0,0 +1,492 @@ +#if defined(ATLAS_VERTEX) +#include "utils/matrix.slang" + +struct UBO +{ + row_major float4x4 model; + row_major float4x4 view; + row_major float4x4 projection; + uint isInstanced; +}; + +struct VertexOutput +{ + [[vk::location(0)]] float4 outColor : TEXCOORD0; + [[vk::location(1)]] float2 TexCoord : TEXCOORD1; + [[vk::location(2)]] float3 Normal : TEXCOORD2; + [[vk::location(3)]] float3 FragPos : TEXCOORD3; + [[vk::location(4)]] float3 TBN_0 : TEXCOORD4; + [[vk::location(5)]] float3 TBN_1 : TEXCOORD5; + [[vk::location(6)]] float3 TBN_2 : TEXCOORD6; + float4 gl_Position : SV_Position; +}; + +struct VertexInput +{ + [[vk::location(0)]] float3 aPos : TEXCOORD0; + [[vk::location(1)]] float4 aColor : TEXCOORD1; + [[vk::location(2)]] float2 aTexCoord : TEXCOORD2; + [[vk::location(3)]] float3 aNormal : TEXCOORD3; + [[vk::location(4)]] float3 aTangent : TEXCOORD4; + [[vk::location(5)]] float3 aBitangent : TEXCOORD5; + [[vk::location(6)]] float4 instanceModel_0 : TEXCOORD6; + [[vk::location(7)]] float4 instanceModel_1 : TEXCOORD7; + [[vk::location(8)]] float4 instanceModel_2 : TEXCOORD8; + [[vk::location(9)]] float4 instanceModel_3 : TEXCOORD9; +}; + +[[vk::binding(0, 0)]] ConstantBuffer uniforms; +[shader("vertex")] +VertexOutput vertexMain(VertexInput input) +{ + VertexOutput output = {}; + row_major float3x3 TBN = {}; + row_major float4x4 instanceModel = {}; + instanceModel[0] = input.instanceModel_0; + instanceModel[1] = input.instanceModel_1; + instanceModel[2] = input.instanceModel_2; + instanceModel[3] = input.instanceModel_3; + row_major float4x4 finalModel; + bool hasInstanceMatrix = abs(instanceModel[3].w) > 0.5; + if ((uniforms.isInstanced != 0u) && hasInstanceMatrix) + { + finalModel = instanceModel; + } + else + { + finalModel = uniforms.model; + } + float4 worldPos = mul(float4(input.aPos, 1.0), finalModel); + output.FragPos = worldPos.xyz; + output.gl_Position = mul(worldPos, (mul(uniforms.view, uniforms.projection))); + output.TexCoord = input.aTexCoord; + output.outColor = input.aColor; + row_major float4x4 _81 = transpose(inverseMatrix(finalModel)); + row_major float3x3 normalMatrix = float3x3(_81[0].xyz, _81[1].xyz, _81[2].xyz); + output.Normal = normalize(mul(input.aNormal, normalMatrix)); + float3 T = normalize(mul(input.aTangent, normalMatrix)); + float3 B = normalize(mul(input.aBitangent, normalMatrix)); + float3 N = normalize(mul(input.aNormal, normalMatrix)); + TBN = float3x3(float3(T), float3(B), float3(N)); + output.TBN_0 = TBN[0]; + output.TBN_1 = TBN[1]; + output.TBN_2 = TBN[2]; + return output; +} +#endif + +#if defined(ATLAS_FRAGMENT) +struct UBO +{ + int4 textureTypes[16]; + int textureCount; + uint useTexture; + uint useColor; + float3 cameraPosition; + float normalMapStrength; + uint useNormalMap; + float2 textureScale; + float2 textureOffset; +}; + +struct MaterialPush +{ + float3 albedo; + float metallic; + float roughness; + float ao; + float reflectivity; +}; + +struct FragmentOutput +{ + float4 gPosition : SV_Target0; + float4 gNormal : SV_Target1; + float4 gAlbedoSpec : SV_Target2; + float4 gMaterial : SV_Target3; +}; + +struct FragmentInput +{ + [[vk::location(1)]] float2 TexCoord : TEXCOORD1; + [[vk::location(2)]] float3 Normal : TEXCOORD2; + [[vk::location(3)]] float3 FragPos : TEXCOORD3; + [[vk::location(4)]] float3 TBN_0 : TEXCOORD4; + [[vk::location(5)]] float3 TBN_1 : TEXCOORD5; + [[vk::location(6)]] float3 TBN_2 : TEXCOORD6; +}; + +float4 sampleTextureAt(int textureIndex, float2 uv, Sampler2D texture1, Sampler2D texture2, Sampler2D texture3, Sampler2D texture4, Sampler2D texture5, Sampler2D texture6, Sampler2D texture7, Sampler2D texture8, Sampler2D texture9, Sampler2D texture10) +{ + if (textureIndex == 0) + { + return texture1.Sample(uv); + } + else + { + if (textureIndex == 1) + { + return texture2.Sample(uv); + } + else + { + if (textureIndex == 2) + { + return texture3.Sample(uv); + } + else + { + if (textureIndex == 3) + { + return texture4.Sample(uv); + } + else + { + if (textureIndex == 4) + { + return texture5.Sample(uv); + } + else + { + if (textureIndex == 5) + { + return texture6.Sample(uv); + } + else + { + if (textureIndex == 6) + { + return texture7.Sample(uv); + } + else + { + if (textureIndex == 7) + { + return texture8.Sample(uv); + } + else + { + if (textureIndex == 8) + { + return texture9.Sample(uv); + } + else + { + if (textureIndex == 9) + { + return texture10.Sample(uv); + } + } + } + } + } + } + } + } + } + } + return float4(0.0); +} + +float2 parallaxMapping(float2 texCoords, float3 viewDir, UBO uniforms, Sampler2D texture1, Sampler2D texture2, Sampler2D texture3, Sampler2D texture4, Sampler2D texture5, Sampler2D texture6, Sampler2D texture7, Sampler2D texture8, Sampler2D texture9, Sampler2D texture10) +{ + float3 v = normalize(viewDir); + float numLayers = lerp(32.0, 8.0, abs(dot(float3(0.0, 0.0, 1.0), v))); + float layerDepth = 1.0 / numLayers; + float currentLayerDepth = 0.0; + float2 P = (v.xy / float2(max(v.z, 0.0500000007))) * 0.0399999991; + float2 deltaTexCoords = P / float2(numLayers); + float2 currentTexCoords = texCoords; + int textureIndex = -1; + for (int i = 0; i < uniforms.textureCount; i++) + { + if (uniforms.textureTypes[i].x == 6) + { + textureIndex = i; + break; + } + } + if (textureIndex == (-1)) + { + return currentTexCoords; + } + int param = textureIndex; + float2 param_1 = currentTexCoords; + float currentDepthMapValue = 1.0 - sampleTextureAt(param, param_1, texture1, texture2, texture3, texture4, texture5, texture6, texture7, texture8, texture9, texture10).x; + int maxIterations = int(numLayers) + 1; + int iteration = 0; + while (currentLayerDepth < currentDepthMapValue && iteration < maxIterations) + { + currentTexCoords -= deltaTexCoords; + int param_2 = textureIndex; + float2 param_3 = currentTexCoords; + currentDepthMapValue = 1.0 - sampleTextureAt(param_2, param_3, texture1, texture2, texture3, texture4, texture5, texture6, texture7, texture8, texture9, texture10).x; + currentLayerDepth += layerDepth; + iteration++; + } + float2 prevTexCoords = currentTexCoords + deltaTexCoords; + float afterDepth = currentDepthMapValue - currentLayerDepth; + int param_4 = textureIndex; + float2 param_5 = prevTexCoords; + float beforeDepth = 1.0 - sampleTextureAt(param_4, param_5, texture1, texture2, texture3, texture4, texture5, texture6, texture7, texture8, texture9, texture10).x - (currentLayerDepth - layerDepth); + float denom = afterDepth - beforeDepth; + float weight = abs(denom) > 9.99999975e-05 ? clamp(afterDepth / denom, 0.0, 1.0) : 0.0; + currentTexCoords = (prevTexCoords * weight) + (currentTexCoords * (1.0 - weight)); + return currentTexCoords; +} + +float4 enableTextures(int type, UBO uniforms, Sampler2D texture1, inout float2 texCoord, Sampler2D texture2, Sampler2D texture3, Sampler2D texture4, Sampler2D texture5, Sampler2D texture6, Sampler2D texture7, Sampler2D texture8, Sampler2D texture9, Sampler2D texture10) +{ + float4 color = float4(0.0); + int count = 0; + for (int i = 0; i < uniforms.textureCount; i++) + { + if (uniforms.textureTypes[i].x == type) + { + if (i == 0) + { + color += texture1.Sample(texCoord); + } + else + { + if (i == 1) + { + color += texture2.Sample(texCoord); + } + else + { + if (i == 2) + { + color += texture3.Sample(texCoord); + } + else + { + if (i == 3) + { + color += texture4.Sample(texCoord); + } + else + { + if (i == 4) + { + color += texture5.Sample(texCoord); + } + else + { + if (i == 5) + { + color += texture6.Sample(texCoord); + } + else + { + if (i == 6) + { + color += texture7.Sample(texCoord); + } + else + { + if (i == 7) + { + color += texture8.Sample(texCoord); + } + else + { + if (i == 8) + { + color += texture9.Sample(texCoord); + } + else + { + if (i == 9) + { + color += texture10.Sample(texCoord); + } + } + } + } + } + } + } + } + } + } + count++; + } + } + if (count > 0) + { + color /= float4(float(count)); + } + if (count == 0) + { + return float4(-1.0); + } + return color; +} + +[[vk::binding(0, 1)]] ConstantBuffer uniforms; +[[vk::push_constant]] ConstantBuffer material; +[[vk::binding(0, 2)]] Sampler2D texture1; +[[vk::binding(1, 2)]] Sampler2D texture2; +[[vk::binding(2, 2)]] Sampler2D texture3; +[[vk::binding(3, 2)]] Sampler2D texture4; +[[vk::binding(4, 2)]] Sampler2D texture5; +[[vk::binding(5, 2)]] Sampler2D texture6; +[[vk::binding(6, 2)]] Sampler2D texture7; +[[vk::binding(7, 2)]] Sampler2D texture8; +[[vk::binding(8, 2)]] Sampler2D texture9; +[[vk::binding(9, 2)]] Sampler2D texture10; +[shader("fragment")] +FragmentOutput fragmentMain(FragmentInput input, float4 gl_FragCoord : SV_Position) +{ + FragmentOutput output = {}; + row_major float3x3 TBN = {}; + TBN[0] = input.TBN_0; + TBN[1] = input.TBN_1; + TBN[2] = input.TBN_2; + float2 texCoord = input.TexCoord * uniforms.textureScale + uniforms.textureOffset; + bool hasParallaxMap = false; + for (int i = 0; i < uniforms.textureCount; i++) + { + if (uniforms.textureTypes[i].x == 6) + { + hasParallaxMap = true; + break; + } + } + if (hasParallaxMap) + { + float3 tangentViewDir = normalize(mul((uniforms.cameraPosition - input.FragPos), transpose(TBN))); + float2 param = texCoord; + float3 param_1 = tangentViewDir; + texCoord = parallaxMapping(param, param_1, uniforms, texture1, texture2, texture3, texture4, texture5, texture6, texture7, texture8, texture9, texture10); + } + int param_2 = 0; + float4 sampledColor = enableTextures(param_2, uniforms, texture1, texCoord, texture2, texture3, texture4, texture5, texture6, texture7, texture8, texture9, texture10); + bool hasColorTexture = any(sampledColor != float4(-1.0)); + float4 baseColor = float4(material.albedo[0], material.albedo[1], material.albedo[2], 1.0); + int param_3 = 0; + float4 albedoTex = enableTextures(param_3, uniforms, texture1, texCoord, texture2, texture3, texture4, texture5, texture6, texture7, texture8, texture9, texture10); + if (any(albedoTex != float4(-1.0))) + { + baseColor *= albedoTex; + } + int param_3a = 12; + float4 opacityTex = enableTextures(param_3a, uniforms, texture1, texCoord, texture2, texture3, texture4, texture5, texture6, texture7, texture8, texture9, texture10); + if (any(opacityTex != float4(-1.0))) + { + if (opacityTex.x < 0.100000001) + { + discard; + } + } + else + { + if ((baseColor.w < 0.100000001) && (material.albedo[3] < 0.999000013)) + { + discard; + } + } + int param_4 = 5; + float4 normTexture = enableTextures(param_4, uniforms, texture1, texCoord, texture2, texture3, texture4, texture5, texture6, texture7, texture8, texture9, texture10); + bool _527 = normTexture.x != (-1.0); + bool _534; + if (_527) + { + _534 = normTexture.y != (-1.0); + } + else + { + _534 = _527; + } + bool _540; + if (_534) + { + _540 = normTexture.z != (-1.0); + } + else + { + _540 = _534; + } + float normalStrength = max(uniforms.normalMapStrength, 0.0f); + bool useNormalMap = (uniforms.useNormalMap != 0u) && (normalStrength > 0.0f); + float3 normal; + if (_540 && useNormalMap) + { + float3 tangentNormal = (normTexture.xyz * 2.0) - float3(1.0); + tangentNormal.xy *= normalStrength; + tangentNormal = normalize(tangentNormal); + normal = normalize(mul(tangentNormal, TBN)); + } + else + { + normal = normalize(input.Normal); + } + float3 albedoColor = baseColor.xyz; + int param_pbr_pack = 14; + float4 pbrPackTex = enableTextures(param_pbr_pack, uniforms, texture1, texCoord, texture2, texture3, texture4, texture5, texture6, texture7, texture8, texture9, texture10); + bool hasPbrPack = any(pbrPackTex != float4(-1.0)); + float metallicValue = material.metallic; + int param_5 = 9; + float4 metallicTex = enableTextures(param_5, uniforms, texture1, texCoord, texture2, texture3, texture4, texture5, texture6, texture7, texture8, texture9, texture10); + if (hasPbrPack) + { + metallicValue *= pbrPackTex.z; + } + else if (any(metallicTex != float4(-1.0))) + { + metallicValue *= metallicTex.x; + } + float roughnessValue = material.roughness; + int param_6 = 10; + float4 roughnessTex = enableTextures(param_6, uniforms, texture1, texCoord, texture2, texture3, texture4, texture5, texture6, texture7, texture8, texture9, texture10); + if (hasPbrPack) + { + roughnessValue *= pbrPackTex.y; + } + else if (any(roughnessTex != float4(-1.0))) + { + roughnessValue *= roughnessTex.x; + } + float aoValue = material.ao; + int param_7 = 11; + float4 aoTex = enableTextures(param_7, uniforms, texture1, texCoord, texture2, texture3, texture4, texture5, texture6, texture7, texture8, texture9, texture10); + if (hasPbrPack) + { + aoValue *= pbrPackTex.x; + } + else if (any(aoTex != float4(-1.0))) + { + aoValue *= aoTex.x; + } + metallicValue = clamp(metallicValue, 0.0, 1.0); + roughnessValue = clamp(roughnessValue, 0.0, 1.0); + aoValue = clamp(aoValue, 0.0, 1.0); + float nonlinearDepth = gl_FragCoord.z; + output.gPosition = float4(input.FragPos, nonlinearDepth); + float3 n = normalize(normal); + bool _639 = !all(n == n); + bool _646; + if (!_639) + { + _646 = length(n) < 9.99999975e-05; + } + else + { + _646 = _639; + } + if (_646) + { + n = normalize(input.Normal); + } + output.gNormal = float4(n, 1.0); + float3 a = clamp(albedoColor, float3(0.0), float3(1.0)); + if (!all(a == a)) + { + a = float3(0.0); + } + output.gAlbedoSpec = float4(a, aoValue); + output.gMaterial = float4(metallicValue, roughnessValue, aoValue, clamp(material.reflectivity, 0.0, 1.0)); + return output; +} +#endif diff --git a/shaders/deferred/light.slang b/shaders/deferred/light.slang new file mode 100644 index 00000000..70341aaf --- /dev/null +++ b/shaders/deferred/light.slang @@ -0,0 +1,623 @@ +#if defined(ATLAS_VERTEX) +#include "utils/fullscreen.slang" +#endif + +#if defined(ATLAS_FRAGMENT) +#include "utils/matrix.slang" +#include "utils/image.slang" + +struct ShadowParameters { + row_major float4x4 lightView; + row_major float4x4 lightProjection; + float bias0; + int textureIndex; + float farPlane; + int lightIndex; + float3 lightPos; + int lightType; +}; + +struct DirectionalLight { + float3 direction; + float _pad1; + float3 diffuse; + float _pad2; + float3 specular; + float intensity; +}; + +struct PointLight { + float3 position; + float _pad1; + float3 diffuse; + float _pad2; + float3 specular; + float intensity; + float constant0; + float linear; + float quadratic; + float radius; + float _pad3; +}; + +struct SpotLight { + float3 position; + float _pad1; + float3 direction; + float cutOff; + float outerCutOff; + float intensity; + float range; + float _pad4; + float3 diffuse; + float _pad5; + float3 specular; + float _pad6; +}; + +struct UBO { + float3 cameraPosition; + uint useIBL; +}; + +struct Environment { + float rimLightIntensity; + float3 rimLightColor; + float bloomThreshold; +}; + +struct PushConstants { + int directionalLightCount; + int pointLightCount; + int spotlightCount; + int areaLightCount; + int shadowParamCount; +}; + +struct AreaLight { + float3 position; + float _pad1; + float3 right; + float _pad2; + float3 up; + float _pad3; + float2 size; + float _pad4; + float _pad5; + float3 diffuse; + float _pad6; + float3 specular; + float angle; + int castsBothSides; + float intensity; + float range; + float _pad9; +}; + +struct AmbientLight { + float4 color; + float intensity; + float3 _pad0; +}; + +struct ProbeSpace { + float3 origin; + float _pad0; + + float3 spacing; + float _pad1; + + float3 probeCount; + float _pad2; + + float4 debugColor; + + float4 atlasParams; + +}; + +static const float2 _660[12] = {float2(-0.326000005, -0.405999988), + float2(-0.839999974, -0.074000001), + float2(-0.69599998, 0.456999987), + float2(-0.202999994, 0.620999992), + float2(0.962000012, -0.194999993), + float2(0.47299999, -0.479999989), + float2(0.518999994, 0.76700002), + float2(0.185000002, -0.893000007), + float2(0.507000029, 0.064000003), + float2(0.896000028, 0.412), + float2(-0.321999997, -0.933000028), + float2(-0.791999996, -0.59799999)}; +static const float3 _861[20] = {float3(0.538100004, 0.185599998, + -0.431899995), + float3(0.137899995, 0.248600006, + 0.442999989), + float3(0.337099999, 0.567900002, + -0.0057000001), + float3(-0.699899971, -0.0450999998, + -0.00190000003), + float3(0.0688999966, -0.159799993, + -0.854700029), + float3(0.0560000017, 0.00689999992, + -0.184300005), + float3(-0.0146000003, 0.140200004, + 0.0762000009), + float3(0.00999999978, -0.192399994, + -0.0344000012), + float3(-0.35769999, -0.530099988, + -0.435799986), + float3(-0.316900015, 0.106299996, + 0.0157999992), + float3(0.0103000002, -0.586899996, + 0.0046000001), + float3(-0.0896999985, -0.493999988, + 0.328700006), + float3(0.711899996, -0.0153999999, + -0.0917999968), + float3(-0.0533000007, 0.0595999993, + -0.541100025), + float3(0.0351999998, -0.0631000027, + 0.546000004), + float3(-0.477600008, 0.284700006, + -0.0271000005), + float3(-0.112000003, 0.123400003, + -0.744599998), + float3(-0.213, -0.0781999975, + -0.137899995), + float3(0.294400007, -0.311199993, + -0.264499992), + float3(-0.456400007, 0.417499989, + -0.184300005)}; + +struct FragmentOutput { + float4 FragColor : SV_Target0; + float4 BrightColor : SV_Target1; +}; + +struct FragmentInput { + [[vk::location(0)]] float2 TexCoord : TEXCOORD0; +}; + +#include "utils/deferred_lighting.slang" +#include "utils/ddgi.slang" + +[[vk::binding(0, 1)]] ConstantBuffer uniforms; +[[vk::binding(1, 1)]] ConstantBuffer environment; +[[vk::push_constant]] ConstantBuffer parameters; +[[vk::binding(0, 5)]] StructuredBuffer ShadowParams; +[[vk::binding(0, 4)]] StructuredBuffer DirectionalLights; +[[vk::binding(1, 4)]] StructuredBuffer PointLights; +[[vk::binding(2, 4)]] StructuredBuffer SpotLights; +[[vk::binding(3, 4)]] StructuredBuffer AreaLights; +[[vk::binding(2, 1)]] ConstantBuffer ambientLight; +[[vk::binding(9, 1)]] ConstantBuffer ps; +[[vk::binding(5, 2)]] Sampler2D texture1; +[[vk::binding(6, 2)]] Sampler2D texture2; +[[vk::binding(7, 2)]] Sampler2D texture3; +[[vk::binding(8, 2)]] Sampler2D texture4; +[[vk::binding(9, 2)]] Sampler2D texture5; +[[vk::binding(0, 3)]] SamplerCube cubeMap1; +[[vk::binding(1, 3)]] SamplerCube cubeMap2; +[[vk::binding(2, 3)]] SamplerCube cubeMap3; +[[vk::binding(3, 3)]] SamplerCube cubeMap4; +[[vk::binding(4, 3)]] SamplerCube cubeMap5; +[[vk::binding(5, 3)]] SamplerCube skybox; +[[vk::binding(0, 2)]] Sampler2D gPosition; +[[vk::binding(1, 2)]] Sampler2D gNormal; +[[vk::binding(2, 2)]] Sampler2D gAlbedoSpec; +[[vk::binding(3, 2)]] Sampler2D gMaterial; +[[vk::binding(4, 2)]] Sampler2D ssao; +[[vk::binding(16, 6)]] Texture2D irradianceMap; +[[vk::binding(17, 6)]] Texture2D ddgiDistanceMap; +[shader("fragment")] +FragmentOutput fragmentMain(FragmentInput input) { + FragmentOutput output = {}; + float4 gPositionSample = gPosition.Sample(input.TexCoord); + float3 FragPos = gPositionSample.xyz; + if (!all(isfinite(FragPos))) { + FragPos = float3(0.0); + } + float depthSample = gPositionSample.w; + float3 sampledNormal = gNormal.Sample(input.TexCoord).xyz; + float normalLength = length(sampledNormal); + bool hasNormal = all(isfinite(sampledNormal)) && + normalLength > 9.99999975e-06; + bool hasDepth = + isfinite(depthSample) && depthSample < 0.999989986; + bool hasGeometry = hasNormal || hasDepth; + if (!hasGeometry) { + float2 ndc = input.TexCoord * 2.0f - 1.0f; + float3 backgroundDir = normalize(float3(ndc.x, -ndc.y, 1.0f)); + float3 backgroundColor = + sampleEnvironmentRadiance(backgroundDir, skybox); + output.FragColor = float4(acesToneMapping(backgroundColor), 1.0); + output.BrightColor = float4(0.0, 0.0, 0.0, 1.0); + return output; + } + float3 N = float3(0.0, 1.0, 0.0); + if (hasNormal) { + N = sampledNormal / float3(normalLength); + } else { + float3 geomN = cross(ddx(FragPos), ddy(FragPos)); + float geomNLen = length(geomN); + if (all(isfinite(geomN)) && + geomNLen > 9.99999975e-06) { + N = geomN / float3(geomNLen); + } + } + float3 geomNormal = cross(ddx(FragPos), ddy(FragPos)); + float geomNormalLen = length(geomNormal); + bool hasGeomNormal = all(isfinite(geomNormal)) && + geomNormalLen > 9.99999975e-06; + float3 shadowNormal = N; + float3 ddgiNormal = N; + if (hasGeomNormal) { + geomNormal /= float3(geomNormalLen); + if (dot(N, geomNormal) < 0.0) { + geomNormal = -geomNormal; + } + shadowNormal = geomNormal; + ddgiNormal = geomNormal; + } + float4 albedoAo = gAlbedoSpec.Sample(input.TexCoord); + float3 albedo = clamp(albedoAo.xyz, float3(0.0), float3(1.0)); + if (!all(isfinite(albedo))) { + albedo = float3(0.0); + } + float4 matData = gMaterial.Sample(input.TexCoord); + float metallic = clamp(matData.x, 0.0, 1.0); + float roughness = clamp(matData.y, 0.0, 1.0); + float ao = clamp(matData.z, 0.0, 1.0); + + float viewDistance = + max(length(float3(uniforms.cameraPosition) - FragPos), + 9.99999997e-07); + float3 V = (float3(uniforms.cameraPosition) - FragPos) / float3(viewDistance); + float3 F0 = + lerp(float3(0.0399999991), albedo, float3(metallic)); + float ssaoFactor = + clamp(ssao.Sample(input.TexCoord).x, 0.0, 1.0); + + float ssaoContrast = + clamp(powr(ssaoFactor, 1.10000002), 0.0, 1.0); + float occlusion = + clamp(ao * (0.0500000007 + + (0.949999988 * ssaoContrast)), + 0.0, 1.0); + float lightingOcclusion = + clamp(0.0500000007 + + (0.949999988 * ssaoContrast), + 0.0500000007, 1.0); + float directionalShadow = 0.0; + float spotShadow = 0.0; + float areaShadow = 0.0; + int areaShadowCount = 0; + float pointShadow = 0.0; + int shadowCount = parameters.shadowParamCount; + for (int i = 0; i < shadowCount; i++) { + if (ShadowParams[i].lightType == 3) { + int lightIndex = ShadowParams[i].lightIndex; + if (lightIndex < 0 || lightIndex >= parameters.pointLightCount || + distance(float3(PointLights[lightIndex].position), + FragPos) >= PointLights[lightIndex].radius) { + continue; + } + ShadowParameters _1386; + _1386.lightView = ShadowParams[i].lightView; + _1386.lightProjection = ShadowParams[i].lightProjection; + _1386.bias0 = ShadowParams[i].bias0; + _1386.textureIndex = ShadowParams[i].textureIndex; + _1386.farPlane = ShadowParams[i].farPlane; + _1386.lightIndex = ShadowParams[i].lightIndex; + _1386.lightPos = float3(ShadowParams[i].lightPos); + _1386.lightType = ShadowParams[i].lightType; + ShadowParameters param = _1386; + float3 param_1 = FragPos; + pointShadow = + max(pointShadow, + calculatePointShadow( + param, param_1, texture1, texture2, texture3, texture4, texture5, cubeMap1, cubeMap2, cubeMap3, cubeMap4, cubeMap5)); + } else if (ShadowParams[i].lightType == 1) { + int lightIndex = ShadowParams[i].lightIndex; + if (lightIndex < 0 || lightIndex >= parameters.spotlightCount || + distance(float3(SpotLights[lightIndex].position), + FragPos) >= SpotLights[lightIndex].range) { + continue; + } + ShadowParameters _1397; + _1397.lightView = ShadowParams[i].lightView; + _1397.lightProjection = ShadowParams[i].lightProjection; + _1397.bias0 = ShadowParams[i].bias0; + _1397.textureIndex = ShadowParams[i].textureIndex; + _1397.farPlane = ShadowParams[i].farPlane; + _1397.lightIndex = ShadowParams[i].lightIndex; + _1397.lightPos = float3(ShadowParams[i].lightPos); + _1397.lightType = ShadowParams[i].lightType; + ShadowParameters param_2 = _1397; + float3 param_3 = FragPos; + float3 param_4 = shadowNormal; + spotShadow = max( + spotShadow, + calculateShadow(param_2, param_3, param_4, texture1, texture2, + texture3, texture4, texture5, uniforms)); + } else if (ShadowParams[i].lightType == 2) { + int lightIndex = ShadowParams[i].lightIndex; + if (lightIndex < 0 || lightIndex >= parameters.areaLightCount || + distance(float3(AreaLights[lightIndex].position), + FragPos) >= AreaLights[lightIndex].range) { + continue; + } + ShadowParameters _1397; + _1397.lightView = ShadowParams[i].lightView; + _1397.lightProjection = ShadowParams[i].lightProjection; + _1397.bias0 = ShadowParams[i].bias0; + _1397.textureIndex = ShadowParams[i].textureIndex; + _1397.farPlane = ShadowParams[i].farPlane; + _1397.lightIndex = ShadowParams[i].lightIndex; + _1397.lightPos = float3(ShadowParams[i].lightPos); + _1397.lightType = ShadowParams[i].lightType; + ShadowParameters param_2 = _1397; + float3 param_3 = FragPos; + float3 param_4 = shadowNormal; + areaShadow += calculateShadow( + param_2, param_3, param_4, texture1, texture2, texture3, texture4, + texture5, uniforms); + areaShadowCount++; + } else { + ShadowParameters _1397; + _1397.lightView = ShadowParams[i].lightView; + _1397.lightProjection = ShadowParams[i].lightProjection; + _1397.bias0 = ShadowParams[i].bias0; + _1397.textureIndex = ShadowParams[i].textureIndex; + _1397.farPlane = ShadowParams[i].farPlane; + _1397.lightIndex = ShadowParams[i].lightIndex; + _1397.lightPos = float3(ShadowParams[i].lightPos); + _1397.lightType = ShadowParams[i].lightType; + ShadowParameters param_2 = _1397; + float3 param_3 = FragPos; + float3 param_4 = shadowNormal; + directionalShadow = max( + directionalShadow, + calculateShadow(param_2, param_3, param_4, texture1, texture2, + texture3, texture4, texture5, uniforms)); + } + } + if (areaShadowCount > 0) { + areaShadow /= float(areaShadowCount); + } + directionalShadow = + clamp(directionalShadow * 0.850000024, 0.0, 1.0); + spotShadow = clamp(spotShadow * 0.850000024, 0.0, 1.0); + areaShadow = clamp(areaShadow * 0.449999988, 0.0, 1.0); + pointShadow = + clamp(pointShadow * 0.850000024, 0.0, 1.0); + float3 directionalResult = float3(0.0); + for (int i_1 = 0; i_1 < parameters.directionalLightCount; i_1++) { + DirectionalLight _1428; + _1428.direction = float3(DirectionalLights[i_1].direction); + _1428._pad1 = DirectionalLights[i_1]._pad1; + _1428.diffuse = float3(DirectionalLights[i_1].diffuse); + _1428._pad2 = DirectionalLights[i_1]._pad2; + _1428.specular = float3(DirectionalLights[i_1].specular); + _1428.intensity = DirectionalLights[i_1].intensity; + DirectionalLight param_5 = _1428; + float3 param_6 = N; + float3 param_7 = V; + float3 param_8 = F0; + float3 param_9 = albedo; + float param_10 = metallic; + float param_11 = roughness; + directionalResult += calcDirectionalLight( + param_5, param_6, param_7, param_8, param_9, param_10, param_11); + } + directionalResult *= (1.0 - directionalShadow); + float3 pointResult = float3(0.0); + for (int i_2 = 0; i_2 < parameters.pointLightCount; i_2++) { + PointLight _1471; + _1471.position = float3(PointLights[i_2].position); + _1471._pad1 = PointLights[i_2]._pad1; + _1471.diffuse = float3(PointLights[i_2].diffuse); + _1471._pad2 = PointLights[i_2]._pad2; + _1471.specular = float3(PointLights[i_2].specular); + _1471.intensity = PointLights[i_2].intensity; + _1471.constant0 = PointLights[i_2].constant0; + _1471.linear = PointLights[i_2].linear; + _1471.quadratic = PointLights[i_2].quadratic; + _1471.radius = PointLights[i_2].radius; + _1471._pad3 = PointLights[i_2]._pad3; + PointLight param_12 = _1471; + float3 param_13 = FragPos; + float3 param_14 = N; + float3 param_15 = V; + float3 param_16 = F0; + float3 param_17 = albedo; + float param_18 = metallic; + float param_19 = roughness; + pointResult += calcPointLight(param_12, param_13, param_14, param_15, + param_16, param_17, param_18, param_19); + } + pointResult *= (1.0 - pointShadow); + float3 spotResult = float3(0.0); + for (int i_3 = 0; i_3 < parameters.spotlightCount; i_3++) { + SpotLight _1516; + _1516.position = float3(SpotLights[i_3].position); + _1516._pad1 = SpotLights[i_3]._pad1; + _1516.direction = float3(SpotLights[i_3].direction); + _1516.cutOff = SpotLights[i_3].cutOff; + _1516.outerCutOff = SpotLights[i_3].outerCutOff; + _1516.intensity = SpotLights[i_3].intensity; + _1516.range = SpotLights[i_3].range; + _1516._pad4 = SpotLights[i_3]._pad4; + _1516.diffuse = float3(SpotLights[i_3].diffuse); + _1516._pad5 = SpotLights[i_3]._pad5; + _1516.specular = float3(SpotLights[i_3].specular); + _1516._pad6 = SpotLights[i_3]._pad6; + SpotLight param_20 = _1516; + float3 param_21 = FragPos; + float3 param_22 = N; + float3 param_23 = V; + float3 param_24 = F0; + float3 param_25 = albedo; + float param_26 = metallic; + float param_27 = roughness; + spotResult += calcSpotLight(param_20, param_21, param_22, param_23, + param_24, param_25, param_26, param_27); + } + spotResult *= (1.0 - spotShadow); + float3 areaResult = float3(0.0); + float _1639; + for (int i_4 = 0; i_4 < parameters.areaLightCount; i_4++) { + float3 P = float3(AreaLights[i_4].position); + float3 R = normalize(float3(AreaLights[i_4].right)); + float3 U = normalize(float3(AreaLights[i_4].up)); + float2 halfSize = AreaLights[i_4].size * 0.5; + float3 toPoint = FragPos - P; + float s = clamp(dot(toPoint, R), -halfSize.x, halfSize.x); + float t = clamp(dot(toPoint, U), -halfSize.y, halfSize.y); + float3 Q = (P + (R * s)) + (U * t); + float3 Lvec = Q - FragPos; + float dist = length(Lvec); + if (dist > 9.99999975e-05) { + float3 L = Lvec / float3(dist); + float3 Nl = normalize(cross(R, U)); + float ndotl = dot(Nl, -L); + if (AreaLights[i_4].castsBothSides != 0) { + _1639 = abs(ndotl); + } else { + _1639 = max(ndotl, 0.0); + } + float facing = _1639; + float cosTheta = cos(radians(AreaLights[i_4].angle)); + if ((facing >= cosTheta) && (facing > 0.0)) { + float range = max(AreaLights[i_4].range, + 0.00100000005); + float attenuation = 1.0 / ((1.0 + (dist / range)) + + ((dist * dist) / (range * range))); + float fade = 1.0 - smoothstep(range * 0.899999976, + range, dist); + float3 radiance = + (((float3(AreaLights[i_4].diffuse) * + max(AreaLights[i_4].intensity, 0.0)) * + attenuation) * + facing) * + fade; + float3 param_28 = L; + float3 param_29 = radiance; + float3 param_30 = N; + float3 param_31 = V; + float3 param_32 = F0; + float3 param_33 = albedo; + float param_34 = metallic; + float param_35 = roughness; + areaResult += + evaluateBRDF(param_28, param_29, param_30, param_31, + param_32, param_33, param_34, param_35); + } + } + } + areaResult *= (1.0 - areaShadow); + float3 param_36 = FragPos; + float3 param_37 = N; + float3 param_38 = V; + float3 param_39 = F0; + float3 param_40 = albedo; + float param_41 = metallic; + float param_42 = roughness; + float3 _1714 = getRimLight(param_36, param_37, param_38, param_39, param_40, + param_41, param_42, uniforms, environment); + float3 rimResult = _1714; + float3 lighting = + ((((directionalResult + pointResult) + spotResult) + areaResult) + + rimResult) * + lightingOcclusion; + float3 ambientBase = + ((ambientLight.color.xyz * ambientLight.intensity) * albedo) * + occlusion; + bool ddgiEnabled = ps.atlasParams.w > 0.0f; + float3 ambient = ddgiEnabled ? ambientBase * 0.05f : ambientBase; + + float ddgiSampleBias = + max(max(ps.spacing.x, max(ps.spacing.y, ps.spacing.z)) * 0.05f, 0.002f); + float3 ddgiSamplePos = FragPos + ddgiNormal * ddgiSampleBias; + float3 ddgiIrradiance = + sampleDDGIIrradiance(irradianceMap, ddgiDistanceMap, ps, ddgiSamplePos, + ddgiNormal); + if (!all(isfinite(ddgiIrradiance))) { + ddgiIrradiance = float3(0.0f); + } + ddgiIrradiance = max(ddgiIrradiance, float3(0.0f)); + + float ddgiDebugMode = ps.debugColor.w; + float3 ddgiGain = max(ps.debugColor.xyz, float3(0.0f)); + if (ddgiGain.x < 1e-4f && ddgiGain.y < 1e-4f && ddgiGain.z < 1e-4f) { + ddgiGain = float3(1.0f); + } + + const float INV_PI = 0.318309886; + float3 ddgiDiffuse = ddgiIrradiance * albedo * INV_PI * + (1.0f - metallic) * occlusion * ddgiGain; + ambient += ddgiDiffuse; + + float3 ddgiSpecular = float3(0.0f); + + float3 iblContribution = float3(0.0); + if (uniforms.useIBL != 0u) { + float3 param_43 = N; + float3 irradiance = + sampleEnvironmentRadiance(param_43, skybox); + float3 diffuseIBL = irradiance * albedo; + float3 reflection = reflect(-V, N); + float3 param_44 = reflection; + float3 specularEnv = + sampleEnvironmentRadiance(param_44, skybox); + float param_45 = max(dot(N, V), 0.0); + float3 param_46 = F0; + float3 F = fresnelSchlick(param_45, param_46); + float3 kS = F; + float3 kD = (float3(1.0) - kS) * (1.0 - metallic); + float roughnessAttenuation = lerp(1.0, 0.150000006, + clamp(roughness, 0.0, 1.0)); + float3 specularIBL = specularEnv * roughnessAttenuation; + iblContribution = ((kD * diffuseIBL) + (kS * specularIBL)) * occlusion; + } + float3 finalColor = (ambient + lighting + ddgiSpecular) + iblContribution; + + if (ddgiDebugMode >= 9.5f && ddgiDebugMode < 19.5f) { + finalColor = float3(ssaoFactor); + } else if (ddgiDebugMode >= 39.5f) { + finalColor = + max(ddgiDiffuse * 3.0f + ddgiSpecular * 2.0f, float3(0.0f)); + } else if (ddgiDebugMode >= 29.5f) { + finalColor = ddgiIrradiance * ddgiGain * 4.0f; + } else if (ddgiDebugMode >= 19.5f) { + finalColor = ddgiDiffuse * 3.0f; + } else if (!(uniforms.useIBL != 0u)) { + float3 I = normalize(FragPos - float3(uniforms.cameraPosition)); + float3 R_1 = reflect(-I, N); + float param_47 = max(dot(N, -I), 0.0); + float3 param_48 = F0; + float3 F_1 = fresnelSchlick(param_47, param_48); + float3 kS_1 = F_1; + float3 envColor = skybox.Sample(R_1).xyz; + float3 reflection_1 = envColor * kS_1; + float3 envMix = F0 * (1.0f - roughness) * 0.20f; + finalColor = lerp(finalColor, reflection_1, envMix); + } + output.FragColor = float4(finalColor, 1.0); + float brightness = + dot(output.FragColor.xyz, + float3(0.212599993, 0.715200007, + 0.0722000003)); + if (brightness > environment.bloomThreshold) { + output.BrightColor = float4(output.FragColor.xyz, 1.0); + } else { + output.BrightColor = float4(0.0, 0.0, 0.0, 1.0); + } + float3 param_49 = output.FragColor.xyz; + float3 _1897 = acesToneMapping(param_49); + output.FragColor.x = _1897.x; + output.FragColor.y = _1897.y; + output.FragColor.z = _1897.z; + return output; +} +#endif diff --git a/shaders/effects/downsample.slang b/shaders/effects/downsample.slang new file mode 100644 index 00000000..e479eb77 --- /dev/null +++ b/shaders/effects/downsample.slang @@ -0,0 +1,50 @@ +#if defined(ATLAS_FRAGMENT) +#include "utils/image.slang" + +struct Params +{ + float2 srcResolution; +}; + +struct FragmentOutput +{ + float4 downsample : SV_Target0; +}; + +struct FragmentInput +{ + [[vk::location(0)]] float2 TexCoord : TEXCOORD0; +}; + +[[vk::binding(0, 1)]] ConstantBuffer params; +[[vk::binding(0, 2)]] Sampler2D srcTexture; +[shader("fragment")] +FragmentOutput fragmentMain(FragmentInput input) +{ + FragmentOutput output = {}; + float2 srcTexelSize = + float2(1.0) / float2(textureSize(srcTexture).x, textureSize(srcTexture).y); + float x = srcTexelSize.x; + float y = srcTexelSize.y; + float2 texCoord = input.TexCoord; + float3 a = srcTexture.Sample(float2(texCoord.x - (2.0 * x), texCoord.y + (2.0 * y))).xyz; + float3 b = srcTexture.Sample(float2(texCoord.x, texCoord.y + (2.0 * y))).xyz; + float3 c = srcTexture.Sample(float2(texCoord.x + (2.0 * x), texCoord.y + (2.0 * y))).xyz; + float3 d = srcTexture.Sample(float2(texCoord.x - (2.0 * x), texCoord.y)).xyz; + float3 e = srcTexture.Sample(float2(texCoord.x, texCoord.y)).xyz; + float3 f = srcTexture.Sample(float2(texCoord.x + (2.0 * x), texCoord.y)).xyz; + float3 g = srcTexture.Sample(float2(texCoord.x - (2.0 * x), texCoord.y - (2.0 * y))).xyz; + float3 h = srcTexture.Sample(float2(texCoord.x, texCoord.y - (2.0 * y))).xyz; + float3 i = srcTexture.Sample(float2(texCoord.x + (2.0 * x), texCoord.y - (2.0 * y))).xyz; + float3 j = srcTexture.Sample(float2(texCoord.x - x, texCoord.y + y)).xyz; + float3 k = srcTexture.Sample(float2(texCoord.x + x, texCoord.y + y)).xyz; + float3 l = srcTexture.Sample(float2(texCoord.x - x, texCoord.y - y)).xyz; + float3 m = srcTexture.Sample(float2(texCoord.x + x, texCoord.y - y)).xyz; + float3 downsampleColor = e * 0.125; + downsampleColor += ((((a + c) + g) + i) * 0.03125); + downsampleColor += ((((b + d) + f) + h) * 0.0625); + downsampleColor += ((((j + k) + l) + m) * 0.125); + output.downsample = float4(downsampleColor, 1.0); + return output; +} +#endif diff --git a/shaders/effects/gaussian.slang b/shaders/effects/gaussian.slang new file mode 100644 index 00000000..c39f79ed --- /dev/null +++ b/shaders/effects/gaussian.slang @@ -0,0 +1,48 @@ +#if defined(ATLAS_FRAGMENT) +#include "utils/image.slang" + +struct Params +{ + uint horizontal; + float4 weight[5]; + float radius; +}; + +struct FragmentOutput +{ + float4 FragColor : SV_Target0; +}; + +struct FragmentInput +{ + [[vk::location(0)]] float2 TexCoord : TEXCOORD0; +}; + +[[vk::binding(0, 1)]] ConstantBuffer params; +[[vk::binding(0, 2)]] Sampler2D image; +[shader("fragment")] +FragmentOutput fragmentMain(FragmentInput input) +{ + FragmentOutput output = {}; + float2 tex_offset = (float2(1.0) / float2(int2(textureSize(image).x, textureSize(image).y))) * params.radius; + float3 result = image.Sample(input.TexCoord).xyz * params.weight[0].x; + if (params.horizontal != 0u) + { + for (int i = 1; i < 5; i++) + { + result += (image.Sample((input.TexCoord + float2(tex_offset.x * float(i), 0.0))).xyz * params.weight[i].x); + result += (image.Sample((input.TexCoord - float2(tex_offset.x * float(i), 0.0))).xyz * params.weight[i].x); + } + } + else + { + for (int i_1 = 1; i_1 < 5; i_1++) + { + result += (image.Sample((input.TexCoord + float2(0.0, tex_offset.y * float(i_1)))).xyz * params.weight[i_1].x); + result += (image.Sample((input.TexCoord - float2(0.0, tex_offset.y * float(i_1)))).xyz * params.weight[i_1].x); + } + } + output.FragColor = float4(result, 1.0); + return output; +} +#endif diff --git a/shaders/effects/particle.slang b/shaders/effects/particle.slang new file mode 100644 index 00000000..ae4562da --- /dev/null +++ b/shaders/effects/particle.slang @@ -0,0 +1,95 @@ +#if defined(ATLAS_VERTEX) +struct UniformBufferObject +{ + row_major float4x4 view; + row_major float4x4 projection; + row_major float4x4 model; + uint isAmbient; +}; + +struct VertexOutput +{ + [[vk::location(0)]] float2 fragTexCoord : TEXCOORD0; + [[vk::location(1)]] float4 fragColor : TEXCOORD1; + float4 gl_Position : SV_Position; +}; + +struct VertexInput +{ + [[vk::location(0)]] float3 quadVertex : TEXCOORD0; + [[vk::location(1)]] float2 texCoord : TEXCOORD1; + [[vk::location(2)]] float3 particlePos : TEXCOORD2; + [[vk::location(3)]] float4 particleColor : TEXCOORD3; + [[vk::location(4)]] float particleSize : TEXCOORD4; +}; + +[[vk::binding(0, 0)]] ConstantBuffer uniforms; +[shader("vertex")] +VertexOutput vertexMain(VertexInput input) +{ + VertexOutput output = {}; + if (uniforms.isAmbient != 0u) + { + float4 viewParticlePos = mul(float4(input.particlePos, 1.0), uniforms.view); + float3 viewPosition = viewParticlePos.xyz + float3(input.quadVertex.x * input.particleSize, input.quadVertex.y * input.particleSize, 0.0); + output.gl_Position = mul(float4(viewPosition, 1.0), (mul(uniforms.model, uniforms.projection))); + } + else + { + float3 cameraRight = float3(uniforms.view[0].x, uniforms.view[1].x, uniforms.view[2].x); + float3 cameraUp = float3(uniforms.view[0].y, uniforms.view[1].y, uniforms.view[2].y); + float3 worldPosition = (input.particlePos + ((cameraRight * input.quadVertex.x) * input.particleSize)) + ((cameraUp * input.quadVertex.y) * input.particleSize); + output.gl_Position = mul(float4(worldPosition, 1.0), (mul(uniforms.view, uniforms.projection))); + } + output.fragTexCoord = input.texCoord; + output.fragColor = input.particleColor; + return output; +} +#endif + +#if defined(ATLAS_FRAGMENT) +struct Params +{ + uint useTexture; +}; + +struct FragmentOutput +{ + float4 FragColor : SV_Target0; +}; + +struct FragmentInput +{ + [[vk::location(0)]] float2 fragTexCoord : TEXCOORD0; + [[vk::location(1)]] float4 fragColor : TEXCOORD1; +}; + +[[vk::binding(0, 1)]] ConstantBuffer params; +[[vk::binding(0, 2)]] Sampler2D particleTexture; +[shader("fragment")] +FragmentOutput fragmentMain(FragmentInput input) +{ + FragmentOutput output = {}; + if (params.useTexture != 0u) + { + float4 texColor = particleTexture.Sample(input.fragTexCoord); + if (texColor.w < 0.00999999978) + { + discard; + } + output.FragColor = texColor * input.fragColor; + } + else + { + float2 center = float2(0.5); + float dist = distance(input.fragTexCoord, center); + float alpha = 1.0 - smoothstep(0.300000012, 0.5, dist); + output.FragColor = float4(input.fragColor.xyz, input.fragColor.w * alpha); + if (output.FragColor.w < 0.00999999978) + { + discard; + } + } + return output; +} +#endif diff --git a/shaders/effects/skybox.slang b/shaders/effects/skybox.slang new file mode 100644 index 00000000..114fb95e --- /dev/null +++ b/shaders/effects/skybox.slang @@ -0,0 +1,309 @@ +#if defined(ATLAS_VERTEX) +struct UniformBufferObject +{ + row_major float4x4 projection; + row_major float4x4 view; +}; + +struct VertexOutput +{ + [[vk::location(0)]] float3 TexCoords : TEXCOORD0; + float4 gl_Position : SV_Position; +}; + +struct VertexInput +{ + [[vk::location(0)]] float3 aPos : TEXCOORD0; +}; + +[[vk::binding(0, 0)]] ConstantBuffer uniforms; +[shader("vertex")] +VertexOutput vertexMain(VertexInput input) +{ + VertexOutput output = {}; + output.TexCoords = input.aPos; + row_major float3x3 _32 = float3x3(uniforms.view[0].xyz, uniforms.view[1].xyz, uniforms.view[2].xyz); + row_major float4x4 viewNoTranslation = float4x4(float4(_32[0].x, _32[0].y, _32[0].z, 0.0), float4(_32[1].x, _32[1].y, _32[1].z, 0.0), float4(_32[2].x, _32[2].y, _32[2].z, 0.0), float4(0.0, 0.0, 0.0, 1.0)); + float4 pos = mul(float4(input.aPos, 1.0), (mul(viewNoTranslation, uniforms.projection))); + output.gl_Position = pos.xyww; + return output; +} +#endif + +#if defined(ATLAS_FRAGMENT) +struct Params +{ + float3 sunDirection; + float4 sunColor; + float3 moonDirection; + float4 moonColor; + int hasDayNight; +}; + +struct AtmosphereParams +{ + float sunTintStrength; + float moonTintStrength; + float sunSizeMultiplier; + float moonSizeMultiplier; + float starDensity; +}; + +struct FragmentOutput +{ + float4 FragColor : SV_Target0; +}; + +struct FragmentInput +{ + [[vk::location(0)]] float3 TexCoords : TEXCOORD0; +}; + +float hash13(inout float3 p) +{ + p = frac(p * 443.897003); + p += float3(dot(p, p.yzx + float3(19.1900005))); + return frac((p.x + p.y) * p.z); +} + +float3 generateStars(float3 dir, float density, float nightFactor) +{ + if ((density <= 0.0) || (nightFactor <= 0.0)) + { + return float3(0.0); + } + float3 starSpace = dir * 50.0; + float3 cell = floor(starSpace); + float3 localPos = frac(starSpace); + float3 param = cell; + float _165 = hash13(param); + float rand = _165; + if (rand < (density * 0.300000012)) + { + float3 param_1 = cell + float3(12.3400002, 56.7799988, 90.1200027); + float _181 = hash13(param_1); + float randX = _181; + float3 param_2 = cell + float3(23.4500008, 67.8899994, 1.23000002); + float _190 = hash13(param_2); + float randY = _190; + float3 param_3 = cell + float3(34.5600014, 78.9000015, 12.3400002); + float _198 = hash13(param_3); + float randZ = _198; + float3 starPos = float3(randX, randY, randZ); + float dist = length(localPos - starPos); + float3 param_4 = cell + float3(45.6699982, 89.0100021, 23.4500008); + float _217 = hash13(param_4); + float starSize = 0.0199999996 + (_217 * 0.0299999993); + float3 param_5 = cell + float3(56.7799988, 90.1200027, 34.5600014); + float _227 = hash13(param_5); + float brightness = 0.5 + (_227 * 0.5); + float star = smoothstep(starSize, 0.0, dist) * brightness; + float3 param_6 = cell + float3(67.8899994, 1.23000002, 45.6699982); + float _243 = hash13(param_6); + float twinkle = 0.800000012 + (0.200000003 * sin(_243 * 100.0)); + star *= (twinkle * nightFactor); + float3 starColor = float3(1.0); + if (rand > 0.899999976) + { + starColor = float3(0.800000012, 0.899999976, 1.0); + } + else + { + if (rand > 0.800000012) + { + starColor = float3(1.0, 0.899999976, 0.800000012); + } + } + return starColor * star; + } + return float3(0.0); +} + +float hash21(inout float2 p) +{ + p = frac(p * float2(123.339996, 456.209991)); + p += float2(dot(p, p + float2(45.3199997))); + return frac(p.x * p.y); +} + +float valueNoise(float2 p) +{ + float2 i = floor(p); + float2 f = frac(p); + f = (f * f) * (float2(3.0) - (f * 2.0)); + float2 param = i; + float _80 = hash21(param); + float a = _80; + float2 param_1 = i + float2(1.0, 0.0); + float _88 = hash21(param_1); + float b = _88; + float2 param_2 = i + float2(0.0, 1.0); + float _94 = hash21(param_2); + float c = _94; + float2 param_3 = i + float2(1.0); + float _100 = hash21(param_3); + float d = _100; + return lerp(lerp(a, b, f.x), lerp(c, d, f.x), f.y); +} + +float3 generateMoonTexture(inout float2 uv, float distanceFromCenter, float3 tintColor) +{ + float angle = 0.5; + float ca = cos(angle); + float sa = sin(angle); + uv = float2((ca * uv.x) - (sa * uv.y), (sa * uv.x) + (ca * uv.y)); + float2 param = uv * 2.0; + float largeFeatures = valueNoise(param); + largeFeatures = smoothstep(0.300000012, 0.699999988, largeFeatures); + float2 param_1 = uv * 8.0; + float mediumCraters = valueNoise(param_1); + float2 craterUV = uv * 6.0; + float2 craterCell = floor(craterUV); + float2 craterLocal = frac(craterUV); + float craters = 1.0; + for (int i = 0; i < 4; i++) + { + float2 neighbor = float2(float(i % 2), float(i / 2)); + float2 cellPoint = craterCell + neighbor; + float2 param_2 = cellPoint; + float _353 = hash21(param_2); + float2 param_3 = cellPoint + float2(13.6999998, 27.2999992); + float _360 = hash21(param_3); + float2 craterCenter = float2(_353, _360); + float dist = length((craterLocal - neighbor) - craterCenter); + float2 param_4 = cellPoint + float2(5.30000019, 9.69999981); + float _378 = hash21(param_4); + float craterSize = 0.150000006 + (0.25 * _378); + if (dist < craterSize) + { + float crater = smoothstep(craterSize, craterSize * 0.300000012, dist); + craters = min(craters, 1.0 - (crater * 0.699999988)); + } + } + float surface = (largeFeatures * 0.5) + (mediumCraters * 0.5); + surface *= craters; + float intensity = lerp(0.300000012, 0.75, surface); + float limb = 1.0 - smoothstep(0.600000024, 1.0, distanceFromCenter); + intensity *= (0.400000006 + (0.600000024 * limb)); + intensity *= 1.29999995; + return clamp(tintColor * intensity, float3(0.0), float3(1.0)); +} + +[[vk::binding(0, 1)]] ConstantBuffer params; +[[vk::binding(1, 1)]] ConstantBuffer atmosphereParams; +[[vk::binding(0, 2)]] SamplerCube skybox; +[shader("fragment")] +FragmentOutput fragmentMain(FragmentInput input) +{ + FragmentOutput output = {}; + float3 dir = normalize(input.TexCoords); + float3 color = skybox.Sample(input.TexCoords).xyz; + if (params.hasDayNight == 1) + { + float3 normSunDir = normalize(params.sunDirection); + float3 normMoonDir = normalize(params.moonDirection); + float sunDot = dot(dir, normSunDir); + float moonDot = dot(dir, normMoonDir); + float nightFactor = smoothstep(0.150000006, -0.200000003, params.sunDirection.y); + if (atmosphereParams.starDensity > 0.0) + { + float3 param = dir; + float param_1 = atmosphereParams.starDensity; + float param_2 = nightFactor; + color += generateStars(param, param_1, param_2); + } + float sunHorizonFade = smoothstep(-0.150000006, 0.0500000007, params.sunDirection.y); + if (params.sunDirection.y > (-0.150000006)) + { + float sizeAdjust = 1.0 - ((atmosphereParams.sunSizeMultiplier - 1.0) * 0.00100000005); + float sunSize = 0.999499977 * sizeAdjust; + float sunGlowSize = 0.998000026 * (1.0 - ((atmosphereParams.sunSizeMultiplier - 1.0) * 0.00300000003)); + float sunHaloSize = 0.99000001 * (1.0 - ((atmosphereParams.sunSizeMultiplier - 1.0) * 0.0149999997)); + float sunDisk = smoothstep(sunSize - 0.000199999995, sunSize, sunDot); + float sunGlow = smoothstep(sunGlowSize, sunSize, sunDot) * (1.0 - sunDisk); + float sunHalo = smoothstep(sunHaloSize, sunSize, sunDot) * (1.0 - smoothstep(sunSize, sunGlowSize, sunDot)); + float horizonBoost = smoothstep(0.100000001, -0.0500000007, params.sunDirection.y) * 2.0; + sunHalo *= (0.300000012 + horizonBoost); + color += ((params.sunColor.xyz * (((sunDisk * 5.0) + (sunGlow * 0.5)) + sunHalo)) * sunHorizonFade); + } + float moonHorizonFade = smoothstep(-0.150000006, 0.0500000007, params.moonDirection.y); + if (params.moonDirection.y > (-0.150000006)) + { + float sizeAdjust_1 = 1.0 - ((atmosphereParams.moonSizeMultiplier - 1.0) * 0.00100000005); + float moonSize = 0.999599993 * sizeAdjust_1; + float moonGlowSize = 0.99849999 * (1.0 - ((atmosphereParams.moonSizeMultiplier - 1.0) * 0.00300000003)); + float moonHaloSize = 0.991999984 * (1.0 - ((atmosphereParams.moonSizeMultiplier - 1.0) * 0.0149999997)); + float moonDisk = smoothstep(moonSize - 0.000199999995, moonSize, moonDot); + if (moonDisk > 0.00999999978) + { + float3 up = (abs(normMoonDir.y) < 0.999000013) ? float3(0.0, 1.0, 0.0) : float3(1.0, 0.0, 0.0); + float3 right = normalize(cross(up, normMoonDir)); + float3 actualUp = cross(normMoonDir, right); + float3 relativeDir = dir - (normMoonDir * moonDot); + float u = dot(relativeDir, right); + float v = dot(relativeDir, actualUp); + float distFromCenter = length(float2(u, v)) / sqrt(1.0 - (moonSize * moonSize)); + if (distFromCenter < 1.0) + { + float2 moonUV = float2(u, v) * 200.0; + float2 param_3 = moonUV; + float param_4 = distFromCenter; + float3 param_5 = params.moonColor.xyz; + float3 _703 = generateMoonTexture(param_3, param_4, param_5); + float3 moonTexture = _703; + color += (((moonTexture * moonDisk) * 1.5) * moonHorizonFade); + } + else + { + color += (((params.moonColor.xyz * moonDisk) * 1.5) * moonHorizonFade); + } + } + float moonGlow = smoothstep(moonGlowSize, moonSize, moonDot) * (1.0 - moonDisk); + float moonHalo = smoothstep(moonHaloSize, moonSize, moonDot) * (1.0 - smoothstep(moonSize, moonGlowSize, moonDot)); + float moonHorizonBoost = smoothstep(0.100000001, -0.0500000007, params.moonDirection.y) * 2.0; + moonHalo *= (0.200000003 + moonHorizonBoost); + color += ((params.moonColor.xyz * ((moonGlow * 0.300000012) + moonHalo)) * moonHorizonFade); + } + bool _767 = params.sunDirection.y > (-0.100000001); + bool _773; + if (_767) + { + _773 = atmosphereParams.sunTintStrength > 0.0; + } + else + { + _773 = _767; + } + if (_773) + { + float sunSkyInfluence = smoothstep(0.699999988, 0.949999988, sunDot) * smoothstep(-0.100000001, 0.200000003, params.sunDirection.y); + color = lerp(color, color * params.sunColor.xyz, float3((sunSkyInfluence * 0.300000012) * atmosphereParams.sunTintStrength)); + float sunProximity = smoothstep(0.300000012, 0.800000012, sunDot) * smoothstep(-0.100000001, 0.300000012, params.sunDirection.y); + color += (((params.sunColor.xyz * sunProximity) * 0.150000006) * atmosphereParams.sunTintStrength); + float globalSunTint = smoothstep(-0.100000001, 0.5, params.sunDirection.y); + color = lerp(color, params.sunColor.xyz, float3((globalSunTint * atmosphereParams.sunTintStrength) * 0.0799999982)); + } + bool _833 = params.moonDirection.y > (-0.100000001); + bool _839; + if (_833) + { + _839 = atmosphereParams.moonTintStrength > 0.0; + } + else + { + _839 = _833; + } + if (_839) + { + float moonSkyInfluence = smoothstep(0.800000012, 0.949999988, moonDot) * smoothstep(-0.100000001, 0.200000003, params.moonDirection.y); + color = lerp(color, color * params.moonColor.xyz, float3((moonSkyInfluence * 0.200000003) * atmosphereParams.moonTintStrength)); + float moonProximity = smoothstep(0.5, 0.850000024, moonDot) * smoothstep(-0.100000001, 0.300000012, params.moonDirection.y); + color += (((params.moonColor.xyz * moonProximity) * 0.0799999982) * atmosphereParams.moonTintStrength); + float globalMoonTint = smoothstep(-0.100000001, 0.5, params.moonDirection.y); + color = lerp(color, params.moonColor.xyz, float3((globalMoonTint * atmosphereParams.moonTintStrength) * 0.0500000007)); + } + } + output.FragColor = float4(color, 1.0); + return output; +} +#endif diff --git a/shaders/effects/ssr.slang b/shaders/effects/ssr.slang new file mode 100644 index 00000000..78023fc5 --- /dev/null +++ b/shaders/effects/ssr.slang @@ -0,0 +1,343 @@ +#if defined(ATLAS_FRAGMENT) +struct Uniforms +{ + row_major float4x4 inverseProjection; + row_major float4x4 inverseView; + row_major float4x4 projection; + row_major float4x4 view; + float3 cameraPosition; +}; + +struct SSRParameters +{ + float maxDistance; + float resolution; + int steps; + float thickness; + float maxRoughness; + float historyWeight; + int debugMode; +}; + +struct FragmentOutput +{ + float4 FragColor : SV_Target0; +}; + +struct FragmentInput +{ + [[vk::location(0)]] float2 TexCoord : TEXCOORD0; +}; + +float3 fresnelSchlick(float cosTheta, float3 F0) +{ + return F0 + ((float3(1.0) - F0) * powr(1.0 - cosTheta, 5.0)); +} + +float3 sampleSkyReflection(float3 normal, float3 viewDir, float3 albedo, float metallic, SamplerCube skybox) +{ + float3 reflected = reflect(-normalize(viewDir), normalize(normal)); + float3 skyColor = skybox.Sample(reflected).xyz; + float skyLuma = dot(skyColor, float3(0.212599993, 0.715200007, 0.0722000003)); + if (skyLuma < 0.00100000005) + { + float t = clamp((reflected.y * 0.5) + 0.5, 0.0, 1.0); + float3 horizon = float3(0.74000001, 0.790000021, 0.879999995); + float3 zenith = float3(0.5, 0.639999986, 0.839999974); + skyColor = lerp(horizon, zenith, float3(t)); + } + float tintStrength = metallic * 0.349999994; + float3 tint = lerp(float3(1.0), albedo, float3(tintStrength)); + return skyColor * tint; +} + +float4 SSR(float3 worldPos, float3 normal, float3 viewDir, float roughness, float metallic, float reflectivity, float3 albedo, Uniforms uniforms, SSRParameters sSRParameters, inout float4 gl_FragCoord, Sampler2D gPosition, Sampler2D sceneColor, Sampler2D gNormal, Sampler2D gDepth, SamplerCube skybox) +{ + float3 viewPos = (mul(float4(worldPos, 1.0), uniforms.view)).xyz; + float3 viewNormal = normalize((mul(float4(normal, 0.0), uniforms.view)).xyz); + float mirrorFactor = clamp(max(metallic, reflectivity) * (1.0 - roughness), 0.0, 1.0); + float3 skyReflection = sampleSkyReflection(normal, viewDir, albedo, metallic, skybox); + float3 viewDirection = normalize(viewPos); + float3 viewReflect = normalize(reflect(viewDirection, viewNormal)); + if (viewReflect.z > 0.0) + { + return float4(0.0); + } + float3 rayOrigin = viewPos + (viewNormal * 0.00999999978); + float3 rayDir = viewReflect; + float stepSize = sSRParameters.maxDistance / float(sSRParameters.steps); + float3 currentPos = rayOrigin; + float jitter = frac(sin(dot(gl_FragCoord.xy, float2(12.9898005, 78.2330017))) * 43758.546875) * roughness * 0.25; + currentPos += ((rayDir * stepSize) * jitter); + float2 hitUV = float2(-1.0); + float hitDepth = 0.0; + bool hit = false; + float2 fallbackUV = float2(0.0); + bool hasFallbackUV = false; + float3 lastPos = currentPos; + for (int i = 0; i < sSRParameters.steps; i++) + { + float t = float(i) / float(sSRParameters.steps); + float adaptiveStep = lerp(0.300000012, 1.0, t); + currentPos += ((rayDir * stepSize) * adaptiveStep); + float4 projectedPos = mul(float4(currentPos, 1.0), uniforms.projection); + float _186 = projectedPos.w; + float4 _187 = projectedPos; + float3 _190 = _187.xyz / float3(_186); + projectedPos.x = _190.x; + projectedPos.y = _190.y; + projectedPos.z = _190.z; + float2 screenUV = (projectedPos.xy * 0.5) + float2(0.5); + bool _208 = screenUV.x < 0.0; + bool _215; + if (!_208) + { + _215 = screenUV.x > 1.0; + } + else + { + _215 = _208; + } + bool _222; + if (!_215) + { + _222 = screenUV.y < 0.0; + } + else + { + _222 = _215; + } + bool _229; + if (!_222) + { + _229 = screenUV.y > 1.0; + } + else + { + _229 = _222; + } + if (!_229) + { + fallbackUV = screenUV; + hasFallbackUV = true; + } + else + { + break; + } + float hierarchyLevel = clamp(floor(log2(1.0 + float(i) * 0.25)), + 0.0, 5.0); + float rawDepth = gDepth.SampleLevel(screenUV, + hierarchyLevel).x; + if (rawDepth >= 0.999899983) + { + currentPos += rayDir * stepSize * (exp2(hierarchyLevel) - 1.0); + lastPos = currentPos; + continue; + } + float3 sampleWorldPos = gPosition.Sample(screenUV).xyz; + float3 sampleNormal = gNormal.Sample(screenUV).xyz; + if (dot(sampleNormal, sampleNormal) < 0.00999999978) + { + lastPos = currentPos; + continue; + } + if (length(sampleWorldPos - worldPos) < 0.0799999982) + { + lastPos = currentPos; + continue; + } + float3 sampleViewPos = (mul(float4(sampleWorldPos, 1.0), uniforms.view)).xyz; + float sampleDepth = -sampleViewPos.z; + float currentDepth = -currentPos.z; + float3 sampleViewNormal = normalize((mul(float4(sampleNormal, 0.0), uniforms.view)).xyz); + if ((dot(sampleViewNormal, viewNormal) > 0.920000017) && (abs(sampleDepth - currentDepth) < (sSRParameters.thickness * 1.5))) + { + lastPos = currentPos; + continue; + } + float depthDiff = sampleDepth - currentDepth; + bool _265 = depthDiff > 0.0; + bool _272; + if (_265) + { + _272 = depthDiff < sSRParameters.thickness; + } + else + { + _272 = _265; + } + if (_272) + { + float3 binarySearchStart = lastPos; + float3 binarySearchEnd = currentPos; + for (int j = 0; j < 8; j++) + { + float3 midPoint = (binarySearchStart + binarySearchEnd) * 0.5; + float4 midProj = mul(float4(midPoint, 1.0), uniforms.projection); + float _303 = midProj.w; + float4 _304 = midProj; + float3 _307 = _304.xyz / float3(_303); + midProj.x = _307.x; + midProj.y = _307.y; + midProj.z = _307.z; + float2 midUV = (midProj.xy * 0.5) + float2(0.5); + bool _321 = midUV.x < 0.0; + bool _328; + if (!_321) + { + _328 = midUV.x > 1.0; + } + else + { + _328 = _321; + } + bool _335; + if (!_328) + { + _335 = midUV.y < 0.0; + } + else + { + _335 = _328; + } + bool _342; + if (!_335) + { + _342 = midUV.y > 1.0; + } + else + { + _342 = _335; + } + if (_342) + { + break; + } + float midRawDepth = gDepth.Sample(midUV).x; + if (midRawDepth >= 0.999899983) + { + binarySearchStart = midPoint; + continue; + } + float3 midSampleWorldPos = gPosition.Sample(midUV).xyz; + float3 midSampleViewPos = (mul(float4(midSampleWorldPos, 1.0), uniforms.view)).xyz; + float midSampleDepth = -midSampleViewPos.z; + float midCurrentDepth = -midPoint.z; + if (midCurrentDepth < midSampleDepth) + { + binarySearchStart = midPoint; + } + else + { + binarySearchEnd = midPoint; + } + } + float4 finalProj = mul(float4(binarySearchEnd, 1.0), uniforms.projection); + float _364 = finalProj.w; + float4 _365 = finalProj; + float3 _368 = _365.xyz / float3(_364); + finalProj.x = _368.x; + finalProj.y = _368.y; + finalProj.z = _368.z; + hitUV = (finalProj.xy * 0.5) + float2(0.5); + hitDepth = length(currentPos - rayOrigin); + hit = true; + break; + } + lastPos = currentPos; + } + if (!hit) + { + return float4(0.0); + } + float3 hitColor = sceneColor.Sample(hitUV).xyz; + float tintStrength = metallic * 0.349999994; + float3 metalTint = lerp(float3(1.0), albedo, float3(tintStrength)); + hitColor *= metalTint; + float hitDepthRaw = gDepth.Sample(hitUV).x; + float3 hitNormalSample = gNormal.Sample(hitUV).xyz; + float hitNormalLenSq = dot(hitNormalSample, hitNormalSample); + float3 hitNormalDir = (hitNormalLenSq > 9.99999975e-06) ? (hitNormalSample * rsqrt(hitNormalLenSq)) : (-rayDir); + float geometryValidity = 1.0 - smoothstep(0.998000026, 1.0, hitDepthRaw); + geometryValidity *= smoothstep(0.00999999978, 0.100000001, hitNormalLenSq); + float normalFacing = max(dot(hitNormalDir, -rayDir), 0.0); + geometryValidity *= smoothstep(0.0500000007, 0.25, normalFacing); + float hitLuma = dot(hitColor, float3(0.212599993, 0.715200007, 0.0722000003)); + float skyLuma = dot(skyReflection, float3(0.212599993, 0.715200007, 0.0722000003)); + float luminanceValidity = smoothstep(0.00200000009, 0.0299999993, hitLuma + (skyLuma * 0.100000001)); + float2 edgeFade = smoothstep(float2(0.0), float2(0.150000006), hitUV) * (float2(1.0) - smoothstep(float2(0.850000024), float2(1.0), hitUV)); + float edgeFactor = edgeFade.x * edgeFade.y; + float distanceFade = 1.0 - smoothstep(sSRParameters.maxDistance * 0.5, sSRParameters.maxDistance, hitDepth); + float roughnessFade = 1.0 - smoothstep(0.0, sSRParameters.maxRoughness, roughness); + float hitConfidence = (edgeFactor * distanceFade) * roughnessFade; + hitConfidence *= geometryValidity * luminanceValidity; + float3 F0 = lerp(float3(0.0399999991), albedo, float3(metallic)); + float3 V = normalize(viewDir); + float cosTheta = max(dot(normal, V), 0.0); + float param = cosTheta; + float3 param_1 = F0; + float3 fresnel = fresnelSchlick(param, param_1); + float fresnelFactor = ((fresnel.x + fresnel.y) + fresnel.z) / 3.0; + float fresnelWeight = lerp(fresnelFactor, 1.0, mirrorFactor); + float3 reflectionColor = lerp(skyReflection, hitColor, float3(hitConfidence)); + float finalFade = lerp(hitConfidence * fresnelWeight, 1.0, mirrorFactor); + finalFade = clamp(finalFade, 0.0, 1.0); + return float4(reflectionColor, finalFade); +} + +[[vk::binding(0, 1)]] ConstantBuffer uniforms; +[[vk::binding(1, 1)]] ConstantBuffer sSRParameters; +[[vk::binding(0, 2)]] Sampler2D gPosition; +[[vk::binding(4, 2)]] Sampler2D sceneColor; +[[vk::binding(1, 2)]] Sampler2D gNormal; +[[vk::binding(2, 2)]] Sampler2D gAlbedoSpec; +[[vk::binding(3, 2)]] Sampler2D gMaterial; +[[vk::binding(5, 2)]] Sampler2D gDepth; +[[vk::binding(0, 3)]] SamplerCube skybox; +[[vk::binding(6, 2)]] Sampler2D historyTexture; +[shader("fragment")] +FragmentOutput fragmentMain(FragmentInput input, float4 gl_FragCoord : SV_Position) +{ + FragmentOutput output = {}; + float3 worldPos = gPosition.Sample(input.TexCoord).xyz; + float3 normal = normalize(gNormal.Sample(input.TexCoord).xyz); + float3 albedo = gAlbedoSpec.Sample(input.TexCoord).xyz; + float4 material = gMaterial.Sample(input.TexCoord); + float metallic = material.x; + float roughness = material.y; + float reflectivity = material.w; + if (length(normal) < 0.00100000005) + { + output.FragColor = float4(0.0); + return output; + } + if (roughness > sSRParameters.maxRoughness || max(metallic, reflectivity) < 0.02) + { + output.FragColor = float4(0.0); + return output; + } + float3 viewDir = normalize(uniforms.cameraPosition - worldPos); + float3 param = worldPos; + float3 param_1 = normal; + float3 param_2 = viewDir; + float param_3 = roughness; + float param_4 = metallic; + float param_5 = reflectivity; + float3 param_6 = albedo; + float4 reflection = SSR(param, param_1, param_2, param_3, param_4, param_5, param_6, uniforms, sSRParameters, gl_FragCoord, gPosition, sceneColor, gNormal, gDepth, skybox); + if (sSRParameters.debugMode != 0) + { + output.FragColor = float4(1.0 - reflection.w, reflection.w, 0.0, 1.0); + return output; + } + if (reflection.w > 0.0 && sSRParameters.historyWeight > 0.0) + { + float4 history = historyTexture.Sample(input.TexCoord); + float validHistory = step(0.001, history.w); + reflection = lerp(reflection, history, sSRParameters.historyWeight * validHistory * reflection.w); + } + output.FragColor = reflection; + return output; +} +#endif diff --git a/shaders/effects/upsample.slang b/shaders/effects/upsample.slang new file mode 100644 index 00000000..8a7903d6 --- /dev/null +++ b/shaders/effects/upsample.slang @@ -0,0 +1,74 @@ +#if defined(ATLAS_FRAGMENT) +#include "utils/image.slang" + +struct Params +{ + float2 srcResolution; + float filterRadius; +}; + +struct FragmentOutput +{ + float4 upsample : SV_Target0; +}; + +struct FragmentInput +{ + [[vk::location(0)]] float2 TexCoord : TEXCOORD0; +}; + +[[vk::binding(0, 1)]] ConstantBuffer params; +[[vk::binding(0, 2)]] Sampler2D srcTexture; +[shader("fragment")] +FragmentOutput fragmentMain(FragmentInput input) +{ + FragmentOutput output = {}; + float2 texelSize = + float2(1.0) / float2(textureSize(srcTexture).x, textureSize(srcTexture).y); + float radius = clamp(params.filterRadius, 1.0, 8.0); + float x = radius * texelSize.x; + float y = radius * texelSize.y; + float2 texCoord = input.TexCoord; + float2 step1 = float2(x, y); + float2 step2 = step1 * 2.0; + float3 upsampleColor = float3(0.0); + float totalWeight = 0.0; + + float wCenter = 0.16; + float wCardinal1 = 0.11; + float wDiagonal1 = 0.075; + float wCardinal2 = 0.04; + float wDiagonal2 = 0.015; + + upsampleColor += srcTexture.Sample(texCoord).xyz * wCenter; + totalWeight += wCenter; + + upsampleColor += srcTexture.Sample(texCoord + float2(step1.x, 0.0)).xyz * wCardinal1; + upsampleColor += srcTexture.Sample(texCoord + float2(-step1.x, 0.0)).xyz * wCardinal1; + upsampleColor += srcTexture.Sample(texCoord + float2(0.0, step1.y)).xyz * wCardinal1; + upsampleColor += srcTexture.Sample(texCoord + float2(0.0, -step1.y)).xyz * wCardinal1; + totalWeight += wCardinal1 * 4.0; + + upsampleColor += srcTexture.Sample(texCoord + float2(step1.x, step1.y)).xyz * wDiagonal1; + upsampleColor += srcTexture.Sample(texCoord + float2(-step1.x, step1.y)).xyz * wDiagonal1; + upsampleColor += srcTexture.Sample(texCoord + float2(step1.x, -step1.y)).xyz * wDiagonal1; + upsampleColor += srcTexture.Sample(texCoord + float2(-step1.x, -step1.y)).xyz * wDiagonal1; + totalWeight += wDiagonal1 * 4.0; + + upsampleColor += srcTexture.Sample(texCoord + float2(step2.x, 0.0)).xyz * wCardinal2; + upsampleColor += srcTexture.Sample(texCoord + float2(-step2.x, 0.0)).xyz * wCardinal2; + upsampleColor += srcTexture.Sample(texCoord + float2(0.0, step2.y)).xyz * wCardinal2; + upsampleColor += srcTexture.Sample(texCoord + float2(0.0, -step2.y)).xyz * wCardinal2; + totalWeight += wCardinal2 * 4.0; + + upsampleColor += srcTexture.Sample(texCoord + float2(step2.x, step2.y)).xyz * wDiagonal2; + upsampleColor += srcTexture.Sample(texCoord + float2(-step2.x, step2.y)).xyz * wDiagonal2; + upsampleColor += srcTexture.Sample(texCoord + float2(step2.x, -step2.y)).xyz * wDiagonal2; + upsampleColor += srcTexture.Sample(texCoord + float2(-step2.x, -step2.y)).xyz * wDiagonal2; + totalWeight += wDiagonal2 * 4.0; + + upsampleColor /= float3(max(totalWeight, 1e-5)); + output.upsample = float4(upsampleColor, 1.0); + return output; +} +#endif diff --git a/shaders/fluid/fluid.slang b/shaders/fluid/fluid.slang new file mode 100644 index 00000000..8dedf2ef --- /dev/null +++ b/shaders/fluid/fluid.slang @@ -0,0 +1,272 @@ +#if defined(ATLAS_VERTEX) +struct UBO +{ + row_major float4x4 model; + row_major float4x4 view; + row_major float4x4 projection; +}; + +struct VertexOutput +{ + [[vk::location(0)]] float2 TexCoord : TEXCOORD0; + [[vk::location(1)]] float3 WorldPos : TEXCOORD1; + [[vk::location(2)]] float3 WorldNormal : TEXCOORD2; + [[vk::location(3)]] float3 WorldTangent : TEXCOORD3; + [[vk::location(4)]] float3 WorldBitangent : TEXCOORD4; + float4 gl_Position : SV_Position; +}; + +struct VertexInput +{ + [[vk::location(0)]] float3 aPos : TEXCOORD0; + [[vk::location(1)]] float2 aTexCoord : TEXCOORD1; + [[vk::location(2)]] float3 aNormal : TEXCOORD2; + [[vk::location(3)]] float3 aTangent : TEXCOORD3; + [[vk::location(4)]] float3 aBitangent : TEXCOORD4; +}; + +[[vk::binding(0, 0)]] ConstantBuffer uniforms; +[shader("vertex")] +VertexOutput vertexMain(VertexInput input) +{ + VertexOutput output = {}; + output.gl_Position = mul(float4(input.aPos, 1.0), (mul(uniforms.model, (mul(uniforms.view, uniforms.projection))))); + output.TexCoord = input.aTexCoord; + output.WorldPos = float3((mul(float4(input.aPos, 1.0), uniforms.model)).xyz); + output.WorldNormal = normalize(mul(input.aNormal, float3x3(uniforms.model[0].xyz, uniforms.model[1].xyz, uniforms.model[2].xyz))); + output.WorldTangent = normalize(mul(input.aTangent, float3x3(uniforms.model[0].xyz, uniforms.model[1].xyz, uniforms.model[2].xyz))); + output.WorldBitangent = normalize(mul(input.aBitangent, float3x3(uniforms.model[0].xyz, uniforms.model[1].xyz, uniforms.model[2].xyz))); + return output; +} +#endif + +#if defined(ATLAS_FRAGMENT) +struct Uniforms +{ + float4 waterColor; + float3 cameraPos; + float time; + row_major float4x4 projection; + row_major float4x4 view; + row_major float4x4 invProjection; + row_major float4x4 invView; + float3 lightDirection; + float3 lightColor; +}; + +struct Parameters +{ + float refractionStrength; + float reflectionStrength; + float depthFade; + int hasNormalTexture; + int hasMovementTexture; + float3 windForce; +}; + +struct FragmentOutput +{ + float4 FragColor : SV_Target0; + float4 BrightColor : SV_Target1; +}; + +struct FragmentInput +{ + [[vk::location(0)]] float2 TexCoord : TEXCOORD0; + [[vk::location(1)]] float3 WorldPos : TEXCOORD1; + [[vk::location(2)]] float3 WorldNormal : TEXCOORD2; + [[vk::location(3)]] float3 WorldTangent : TEXCOORD3; + [[vk::location(4)]] float3 WorldBitangent : TEXCOORD4; +}; + +[[vk::binding(0, 1)]] ConstantBuffer uniforms; +[[vk::binding(1, 1)]] ConstantBuffer parameters; +[[vk::binding(4, 2)]] Sampler2D movementTexture; +[[vk::binding(5, 2)]] Sampler2D normalTexture; +[[vk::binding(2, 2)]] Sampler2D reflectionTexture; +[[vk::binding(3, 2)]] Sampler2D refractionTexture; +[[vk::binding(0, 2)]] Sampler2D sceneTexture; +[shader("fragment")] +FragmentOutput fragmentMain(FragmentInput input) +{ + FragmentOutput output = {}; + float3 normal = normalize(input.WorldNormal); + float3 viewDir = normalize(float3(uniforms.cameraPos) - input.WorldPos); + float4 clipSpace = mul(float4(input.WorldPos, 1.0), (mul(uniforms.view, uniforms.projection))); + float3 ndc = clipSpace.xyz / float3(clipSpace.w); + float2 screenUV = (ndc.xy * 0.5) + float2(0.5); + float windStrength = length(parameters.windForce); + float2 _78; + if (windStrength > 0.00100000005) + { + _78 = normalize(parameters.windForce.xy); + } + else + { + _78 = float2(1.0, 0.0); + } + float2 windDir = _78; + float waveSpeed = 0.150000006 + (windStrength * 0.300000012); + float waveAmplitude = 0.00999999978 + (windStrength * 0.0199999996); + float waveFrequency = 30.0 + (windStrength * 10.0); + float2 waveOffset; + waveOffset.x = sin(((input.TexCoord.x * windDir.x) + (uniforms.time * waveSpeed)) * waveFrequency); + waveOffset.y = cos(((input.TexCoord.y * windDir.y) - (uniforms.time * waveSpeed)) * waveFrequency); + waveOffset *= waveAmplitude; + float2 flowOffset = float2(0.0); + if (parameters.hasMovementTexture == 1) + { + float2 windUV = (parameters.windForce.xy * uniforms.time) * 0.0500000007; + float2 movementUV = (input.TexCoord * 2.0) + windUV; + float2 movementSample = movementTexture.Sample(movementUV).xy; + movementSample = (movementSample * 2.0) - float2(1.0); + flowOffset = (movementSample * windStrength) * 0.150000006; + waveOffset += (flowOffset * 0.5); + } + if (parameters.hasNormalTexture == 1) + { + float3 T = normalize(input.WorldTangent); + float3 B = normalize(input.WorldBitangent); + float3 N = normalize(input.WorldNormal); + row_major float3x3 TBN = float3x3(float3(T), float3(B), float3(N)); + float normalSpeed = 0.0299999993 + (windStrength * 0.0500000007); + float2 normalUV1 = ((input.TexCoord * 5.0) + (waveOffset * 10.0)) + ((parameters.windForce.xy * uniforms.time) * normalSpeed); + float2 normalUV2 = ((input.TexCoord * 3.0) - (waveOffset * 8.0)) - (((parameters.windForce.xy * uniforms.time) * normalSpeed) * 0.800000012); + float3 normalMap1 = normalTexture.Sample(normalUV1).xyz; + float3 normalMap2 = normalTexture.Sample(normalUV2).xyz; + normalMap1 = (normalMap1 * 2.0) - float3(1.0); + normalMap2 = (normalMap2 * 2.0) - float3(1.0); + float3 blendedNormal = normalize(normalMap1 + normalMap2); + float3 worldSpaceNormal = normalize(mul(blendedNormal, TBN)); + float normalStrength = 0.5 + (windStrength * 0.300000012); + normal = normalize(lerp(N, worldSpaceNormal, float3(normalStrength))); + } + float2 reflectionUV = screenUV; + reflectionUV.y = 1.0 - reflectionUV.y; + reflectionUV += (waveOffset * 0.300000012); + float2 refractionUV = screenUV - (waveOffset * 0.200000003); + bool _324 = reflectionUV.x >= 0.0; + bool _330; + if (_324) + { + _330 = reflectionUV.x <= 1.0; + } + else + { + _330 = _324; + } + bool _336; + if (_330) + { + _336 = reflectionUV.y >= 0.0; + } + else + { + _336 = _330; + } + bool _342; + if (_336) + { + _342 = reflectionUV.y <= 1.0; + } + else + { + _342 = _336; + } + bool reflectionInBounds = _342; + bool _346 = refractionUV.x >= 0.0; + bool _352; + if (_346) + { + _352 = refractionUV.x <= 1.0; + } + else + { + _352 = _346; + } + bool _358; + if (_352) + { + _358 = refractionUV.y >= 0.0; + } + else + { + _358 = _352; + } + bool _364; + if (_358) + { + _364 = refractionUV.y <= 1.0; + } + else + { + _364 = _358; + } + bool refractionInBounds = _364; + reflectionUV = clamp(reflectionUV, float2(0.0500000007), float2(0.949999988)); + refractionUV = clamp(refractionUV, float2(0.0500000007), float2(0.949999988)); + float2 reflectionEdgeFade = smoothstep(float2(0.0), float2(0.150000006), reflectionUV) * smoothstep(float2(1.0), float2(0.850000024), reflectionUV); + float reflectionFadeFactor = reflectionEdgeFade.x * reflectionEdgeFade.y; + float2 refractionEdgeFade = smoothstep(float2(0.0), float2(0.150000006), refractionUV) * smoothstep(float2(1.0), float2(0.850000024), refractionUV); + float refractionFadeFactor = refractionEdgeFade.x * refractionEdgeFade.y; + if (!reflectionInBounds) + { + reflectionFadeFactor *= 0.300000012; + } + if (!refractionInBounds) + { + refractionFadeFactor *= 0.300000012; + } + float4 reflectionSample = reflectionTexture.Sample(reflectionUV); + float4 refractionSample = refractionTexture.Sample(refractionUV); + float4 sceneFallback = sceneTexture.Sample(screenUV); + bool validReflection = length(reflectionSample.xyz) > 0.00999999978; + bool validRefraction = length(refractionSample.xyz) > 0.00999999978; + if (!validReflection) + { + reflectionSample = sceneFallback; + } + if (!validRefraction) + { + refractionSample = sceneFallback; + } + float fresnel = powr(1.0 - clamp(dot(normal, viewDir), 0.0, 1.0), 3.0); + fresnel = lerp(0.0199999996, 1.0, fresnel); + fresnel *= parameters.reflectionStrength; + float3 combined = lerp(refractionSample.xyz, reflectionSample.xyz, float3(fresnel)); + float waterTint = clamp(parameters.depthFade * 0.300000012, 0.0, 0.5); + combined = lerp(combined, uniforms.waterColor.xyz, float3(waterTint)); + float foamAmount = 0.0; + if (parameters.hasMovementTexture == 1) + { + float foamFactor = smoothstep(0.699999988, 1.0, length(flowOffset) * windStrength); + foamAmount = foamFactor * 0.200000003; + combined = lerp(combined, float3(1.0), float3(foamAmount)); + } + float3 lightDir = normalize(-uniforms.lightDirection); + float diffuse = max(dot(normal, lightDir), 0.0); + diffuse *= 0.300000012; + float3 halfDir = normalize(lightDir + viewDir); + float specAngle = max(dot(normal, halfDir), 0.0); + float specular = powr(specAngle, 128.0); + specular *= ((fresnel * 0.5) + 0.5); + float waveVariation = (sin((input.TexCoord.x * 50.0) + (uniforms.time * 2.0)) * 0.5) + 0.5; + waveVariation *= ((cos((input.TexCoord.y * 50.0) - (uniforms.time * 1.5)) * 0.5) + 0.5); + specular *= (0.699999988 + (waveVariation * 0.300000012)); + float3 lighting = uniforms.lightColor * (diffuse + (specular * 2.0)); + combined += lighting; + float3 specularHighlight = (uniforms.lightColor * specular) * 2.5; + specularHighlight += float3(foamAmount * 2.0); + float alpha = lerp(0.699999988, 0.949999988, fresnel); + output.FragColor = float4(combined, alpha); + float luminance = max(max(combined.x, combined.y), combined.z); + float3 bloomColor = float3(0.0); + if (luminance > 1.0) + { + bloomColor = combined - float3(1.0); + } + bloomColor += specularHighlight; + output.BrightColor = float4(bloomColor, alpha); + return output; +} +#endif diff --git a/shaders/fullscreen.slang b/shaders/fullscreen.slang new file mode 100644 index 00000000..c0ebaf75 --- /dev/null +++ b/shaders/fullscreen.slang @@ -0,0 +1,192 @@ +#if defined(ATLAS_VERTEX) +#include "utils/fullscreen.slang" +#endif + +#if defined(ATLAS_FRAGMENT) +#include "utils/image.slang" + +float mod(float x, float y) { return x - y * floor(x / y); } + +struct ColorCorrection +{ + float exposure; + float contrast; + float saturation; + float gamma; + float temperature; + float tint; +}; + +struct PushConstants +{ + int hasBrightTexture; + int hasDepthTexture; + int hasVolumetricLightTexture; + int hasPositionTexture; + int hasLUTTexture; + int hasSSRTexture; + int TextureType; + float lutSize; + int EffectCount; +}; + +struct Uniforms +{ + row_major float4x4 invProjectionMatrix; + row_major float4x4 projectionMatrix; + row_major float4x4 viewMatrix; + row_major float4x4 invViewMatrix; + row_major float4x4 lastViewMatrix; + float nearPlane; + float farPlane; + float focusDepth; + float focusRange; + int maxMipLevel; + float deltaTime; + float time; +}; + +struct Environment +{ + float3 fogColor; + float fogIntensity; +}; + +static const float2 _165[9] = { float2(-0.00333333341, 0.00333333341), float2(0.0, 0.00333333341), float2(0.00333333341), float2(-0.00333333341, 0.0), float2(0.0), float2(0.00333333341, 0.0), float2(-0.00333333341), float2(0.0, -0.00333333341), float2(0.00333333341, -0.00333333341) }; +static const float _171[9] = { -1.0, -1.0, -1.0, -1.0, 9.0, -1.0, -1.0, -1.0, -1.0 }; +static const float _311[9] = { 1.0, 1.0, 1.0, 1.0, -8.0, 1.0, 1.0, 1.0, 1.0 }; + +struct FragmentOutput +{ + float4 FragColor : SV_Target0; +}; + +struct FragmentInput +{ + [[vk::location(0)]] float2 TexCoord : TEXCOORD0; +}; + +[[vk::push_constant]] ConstantBuffer parameters; +[[vk::binding(0, 3)]] StructuredBuffer EffectBuffer; +[[vk::binding(1, 3)]] StructuredBuffer EffectFloat1Buffer; +[[vk::binding(2, 3)]] StructuredBuffer EffectFloat2Buffer; +[[vk::binding(3, 3)]] StructuredBuffer EffectFloat3Buffer; +[[vk::binding(4, 3)]] StructuredBuffer EffectFloat4Buffer; +[[vk::binding(5, 3)]] StructuredBuffer EffectFloat5Buffer; +[[vk::binding(1, 1)]] ConstantBuffer uniforms; +[[vk::binding(6, 3)]] StructuredBuffer EffectFloat6Buffer; +[[vk::binding(0, 1)]] ConstantBuffer environment; +[[vk::binding(0, 2)]] Sampler2D Texture; +[[vk::binding(1, 2)]] Sampler2D BrightTexture; +[[vk::binding(3, 2)]] Sampler2D VolumetricLightTexture; +[[vk::binding(6, 2)]] Sampler2D SSRTexture; +[[vk::binding(4, 2)]] Sampler2D PositionTexture; +[[vk::binding(5, 2)]] Sampler2D LUTTexture; +[[vk::binding(2, 2)]] Sampler2D DepthTexture; + +#include "utils/post_processing.slang" + +[shader("fragment")] +FragmentOutput fragmentMain(FragmentInput input, float4 gl_FragCoord : SV_Position) +{ + FragmentOutput output = {}; + float2 param = input.TexCoord; + float4 color = sampleColor(param); + float depth = 1.0; + if (parameters.hasDepthTexture == 1) + { + depth = DepthTexture.Sample(input.TexCoord).x; + } + float2 param_1 = input.TexCoord; + float param_2 = depth; + float3 viewPos = reconstructViewPos(param_1, param_2); + float _distance = parameters.hasDepthTexture == 1 ? length(viewPos) : uniforms.farPlane; + bool useMotionBlur = false; + float motionBlurSize = 0.0; + float motionBlurSeparation = 0.0; + for (int i = 0; i < parameters.EffectCount; i++) + { + if (EffectBuffer[i] == 6) + { + useMotionBlur = true; + motionBlurSize = EffectFloat1Buffer[i]; + motionBlurSeparation = EffectFloat2Buffer[i]; + } + } + for (int i_1 = 0; i_1 < parameters.EffectCount; i_1++) + { + if (EffectBuffer[i_1] == 2) + { + color = sharpen(Texture, input.TexCoord); + } + else + { + if (EffectBuffer[i_1] == 3) + { + float radius = EffectFloat1Buffer[i_1]; + float param_3 = radius; + color = blur(Texture, param_3, input.TexCoord); + } + else + { + if (EffectBuffer[i_1] == 4) + { + color = edgeDetection(Texture, input.TexCoord); + } + } + } + } + float2 param_4 = input.TexCoord; + color = applyFXAA(Texture, param_4); + float4 param_5 = color; + float4 _2637 = applyColorEffects(param_5, gl_FragCoord); + color = _2637; + if (parameters.hasDepthTexture == 1) + { + float depthValue = DepthTexture.Sample(input.TexCoord).x; + float param_6 = depthValue; + float linearDepth = LinearizeDepth(param_6); + float coc = clamp(abs(linearDepth - uniforms.focusDepth) / uniforms.focusRange, 0.0, 1.0); + float mip = (coc * float(uniforms.maxMipLevel)) * 1.20000005; + float4 param_7 = Texture.SampleLevel(input.TexCoord, mip); + float4 _2676 = applyColorEffects(param_7, gl_FragCoord); + float3 blurred = _2676.xyz; + float3 sharp = color.xyz; + float4 param_8 = color; + color = param_8; + } + else + { + float4 param_9 = color; + color = param_9; + } + float4 hdrColor; + if (useMotionBlur) + { + float2 param_10 = input.TexCoord; + float param_11 = motionBlurSize; + float param_12 = motionBlurSeparation; + float4 param_13 = color; + float4 motionBlurred = applyMotionBlur(param_10, param_11, param_12, param_13); + output.FragColor = motionBlurred; + return output; + } + else + { + float2 param_14 = input.TexCoord; + float4 param_15 = color; + hdrColor = composeLighting(param_14, param_15); + } + float4 param_16 = hdrColor; + hdrColor = mapToLUT(param_16); + float3 param_17 = hdrColor.xyz; + float3 _2744 = acesToneMapping(param_17); + hdrColor.x = _2744.x; + hdrColor.y = _2744.y; + hdrColor.z = _2744.z; + float fogFactor = 1.0 - exp((-_distance) * environment.fogIntensity); + float3 finalColor = lerp(hdrColor.xyz, float3(environment.fogColor), float3(fogFactor)); + output.FragColor = float4(finalColor, 1.0); + return output; +} +#endif diff --git a/shaders/manifest.json b/shaders/manifest.json new file mode 100644 index 00000000..6b228b84 --- /dev/null +++ b/shaders/manifest.json @@ -0,0 +1,202 @@ +{ + "shaders": [ + { + "source": "ui/text.slang", + "stage": "vertex", + "entry": "vertexMain", + "symbol": "TEXT_VERT" + }, + { + "source": "ui/text.slang", + "stage": "fragment", + "entry": "fragmentMain", + "symbol": "TEXT_FRAG" + }, + { + "source": "simple/color.slang", + "stage": "vertex", + "entry": "vertexMain", + "symbol": "COLOR_VERT" + }, + { + "source": "simple/color.slang", + "stage": "fragment", + "entry": "fragmentMain", + "symbol": "COLOR_FRAG" + }, + { + "source": "simple/debug.slang", + "stage": "vertex", + "entry": "vertexMain", + "symbol": "DEBUG_VERT" + }, + { + "source": "simple/debug.slang", + "stage": "fragment", + "entry": "fragmentMain", + "symbol": "DEBUG_FRAG" + }, + { + "source": "simple/texture.slang", + "stage": "vertex", + "entry": "vertexMain", + "symbol": "TEXTURE_VERT" + }, + { + "source": "simple/texture.slang", + "stage": "fragment", + "entry": "fragmentMain", + "symbol": "TEXTURE_FRAG" + }, + { + "source": "effects/downsample.slang", + "stage": "fragment", + "entry": "fragmentMain", + "symbol": "DOWNSAMPLE_FRAG" + }, + { + "source": "effects/gaussian.slang", + "stage": "fragment", + "entry": "fragmentMain", + "symbol": "GAUSSIAN_FRAG" + }, + { + "source": "effects/particle.slang", + "stage": "vertex", + "entry": "vertexMain", + "symbol": "PARTICLE_VERT" + }, + { + "source": "effects/particle.slang", + "stage": "fragment", + "entry": "fragmentMain", + "symbol": "PARTICLE_FRAG" + }, + { + "source": "effects/skybox.slang", + "stage": "vertex", + "entry": "vertexMain", + "symbol": "SKYBOX_VERT" + }, + { + "source": "effects/skybox.slang", + "stage": "fragment", + "entry": "fragmentMain", + "symbol": "SKYBOX_FRAG" + }, + { + "source": "effects/ssr.slang", + "stage": "fragment", + "entry": "fragmentMain", + "symbol": "SSR_FRAG" + }, + { + "source": "effects/upsample.slang", + "stage": "fragment", + "entry": "fragmentMain", + "symbol": "UPSAMPLE_FRAG" + }, + { + "source": "shadows/depth.slang", + "stage": "vertex", + "entry": "vertexMain", + "symbol": "DEPTH_VERT" + }, + { + "source": "shadows/empty.slang", + "stage": "fragment", + "entry": "fragmentMain", + "symbol": "EMPTY_FRAG" + }, + { + "source": "shadows/point_depth_nogeom.slang", + "stage": "vertex", + "entry": "vertexMain", + "symbol": "POINT_DEPTH_NOGEOM_VERT" + }, + { + "source": "shadows/point_depth_nogeom.slang", + "stage": "fragment", + "entry": "fragmentMain", + "symbol": "POINT_DEPTH_NOGEOM_FRAG" + }, + { + "source": "shadows/ssao.slang", + "stage": "fragment", + "entry": "fragmentMain", + "symbol": "SSAO_FRAG" + }, + { + "source": "shadows/ssao_blur.slang", + "stage": "fragment", + "entry": "fragmentMain", + "symbol": "SSAO_BLUR_FRAG" + }, + { + "source": "deferred/deferred.slang", + "stage": "vertex", + "entry": "vertexMain", + "symbol": "DEFERRED_VERT" + }, + { + "source": "deferred/deferred.slang", + "stage": "fragment", + "entry": "fragmentMain", + "symbol": "DEFERRED_FRAG" + }, + { + "source": "deferred/light.slang", + "stage": "vertex", + "entry": "screenVertexMain", + "symbol": "LIGHT_VERT" + }, + { + "source": "deferred/light.slang", + "stage": "fragment", + "entry": "fragmentMain", + "symbol": "LIGHT_FRAG" + }, + { + "source": "fullscreen.slang", + "stage": "vertex", + "entry": "vertexMain", + "symbol": "FULLSCREEN_VERT" + }, + { + "source": "fullscreen.slang", + "stage": "fragment", + "entry": "fragmentMain", + "symbol": "FULLSCREEN_FRAG" + }, + { + "source": "fluid/fluid.slang", + "stage": "vertex", + "entry": "vertexMain", + "symbol": "FLUID_VERT" + }, + { + "source": "fluid/fluid.slang", + "stage": "fragment", + "entry": "fragmentMain", + "symbol": "FLUID_FRAG" + }, + { + "source": "volumetric/volumetric.slang", + "stage": "vertex", + "entry": "screenVertexMain", + "symbol": "VOLUMETRIC_VERT" + }, + { + "source": "volumetric/volumetric.slang", + "stage": "fragment", + "entry": "fragmentMain", + "symbol": "VOLUMETRIC_FRAG" + }, + { + "source": "photon/path_denoise.slang", + "stage": "compute", + "entry": "computeMain", + "symbol": "PATH_DENOISE" + } + ] +} diff --git a/shaders/metal/deferred/deferred.frag.metal b/shaders/metal/deferred/deferred.frag.metal deleted file mode 100644 index c8cef9ea..00000000 --- a/shaders/metal/deferred/deferred.frag.metal +++ /dev/null @@ -1,410 +0,0 @@ -#pragma clang diagnostic ignored "-Wmissing-prototypes" - -#include -#include - -using namespace metal; - -struct UBO -{ - int4 textureTypes[16]; - int textureCount; - uint useTexture; - uint useColor; - float3 cameraPosition; - float normalMapStrength; - uint useNormalMap; - float2 textureScale; - float2 textureOffset; -}; - -struct MaterialPush -{ - packed_float3 albedo; - float metallic; - float roughness; - float ao; - float reflectivity; -}; - -struct main0_out -{ - float4 gPosition [[color(0)]]; - float4 gNormal [[color(1)]]; - float4 gAlbedoSpec [[color(2)]]; - float4 gMaterial [[color(3)]]; -}; - -struct main0_in -{ - float2 TexCoord [[user(locn1)]]; - float3 Normal [[user(locn2)]]; - float3 FragPos [[user(locn3)]]; - float3 TBN_0 [[user(locn4)]]; - float3 TBN_1 [[user(locn5)]]; - float3 TBN_2 [[user(locn6)]]; -}; - -static inline __attribute__((always_inline)) -float4 sampleTextureAt(thread const int& textureIndex, thread const float2& uv, texture2d texture1, sampler texture1Smplr, texture2d texture2, sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, texture2d texture4, sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, texture2d texture6, sampler texture6Smplr, texture2d texture7, sampler texture7Smplr, texture2d texture8, sampler texture8Smplr, texture2d texture9, sampler texture9Smplr, texture2d texture10, sampler texture10Smplr) -{ - if (textureIndex == 0) - { - return texture1.sample(texture1Smplr, uv); - } - else - { - if (textureIndex == 1) - { - return texture2.sample(texture2Smplr, uv); - } - else - { - if (textureIndex == 2) - { - return texture3.sample(texture3Smplr, uv); - } - else - { - if (textureIndex == 3) - { - return texture4.sample(texture4Smplr, uv); - } - else - { - if (textureIndex == 4) - { - return texture5.sample(texture5Smplr, uv); - } - else - { - if (textureIndex == 5) - { - return texture6.sample(texture6Smplr, uv); - } - else - { - if (textureIndex == 6) - { - return texture7.sample(texture7Smplr, uv); - } - else - { - if (textureIndex == 7) - { - return texture8.sample(texture8Smplr, uv); - } - else - { - if (textureIndex == 8) - { - return texture9.sample(texture9Smplr, uv); - } - else - { - if (textureIndex == 9) - { - return texture10.sample(texture10Smplr, uv); - } - } - } - } - } - } - } - } - } - } - return float4(0.0); -} - -static inline __attribute__((always_inline)) -float2 parallaxMapping(thread const float2& texCoords, thread const float3& viewDir, constant UBO& _46, texture2d texture1, sampler texture1Smplr, texture2d texture2, sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, texture2d texture4, sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, texture2d texture6, sampler texture6Smplr, texture2d texture7, sampler texture7Smplr, texture2d texture8, sampler texture8Smplr, texture2d texture9, sampler texture9Smplr, texture2d texture10, sampler texture10Smplr) -{ - float3 v = fast::normalize(viewDir); - float numLayers = mix(32.0, 8.0, abs(dot(float3(0.0, 0.0, 1.0), v))); - float layerDepth = 1.0 / numLayers; - float currentLayerDepth = 0.0; - float2 P = (v.xy / float2(fast::max(v.z, 0.0500000007450580596923828125))) * 0.039999999105930328369140625; - float2 deltaTexCoords = P / float2(numLayers); - float2 currentTexCoords = texCoords; - int textureIndex = -1; - for (int i = 0; i < _46.textureCount; i++) - { - if (_46.textureTypes[i].x == 6) - { - textureIndex = i; - break; - } - } - if (textureIndex == (-1)) - { - return currentTexCoords; - } - int param = textureIndex; - float2 param_1 = currentTexCoords; - float currentDepthMapValue = 1.0 - sampleTextureAt(param, param_1, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr).x; - int maxIterations = int(numLayers) + 1; - int iteration = 0; - while (currentLayerDepth < currentDepthMapValue && iteration < maxIterations) - { - currentTexCoords -= deltaTexCoords; - int param_2 = textureIndex; - float2 param_3 = currentTexCoords; - currentDepthMapValue = 1.0 - sampleTextureAt(param_2, param_3, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr).x; - currentLayerDepth += layerDepth; - iteration++; - } - float2 prevTexCoords = currentTexCoords + deltaTexCoords; - float afterDepth = currentDepthMapValue - currentLayerDepth; - int param_4 = textureIndex; - float2 param_5 = prevTexCoords; - float beforeDepth = 1.0 - sampleTextureAt(param_4, param_5, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr).x - (currentLayerDepth - layerDepth); - float denom = afterDepth - beforeDepth; - float weight = abs(denom) > 9.9999997473787516355514526367188e-05 ? fast::clamp(afterDepth / denom, 0.0, 1.0) : 0.0; - currentTexCoords = (prevTexCoords * weight) + (currentTexCoords * (1.0 - weight)); - return currentTexCoords; -} - -static inline __attribute__((always_inline)) -float4 enableTextures(thread const int& type, constant UBO& _46, texture2d texture1, sampler texture1Smplr, thread float2& texCoord, texture2d texture2, sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, texture2d texture4, sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, texture2d texture6, sampler texture6Smplr, texture2d texture7, sampler texture7Smplr, texture2d texture8, sampler texture8Smplr, texture2d texture9, sampler texture9Smplr, texture2d texture10, sampler texture10Smplr) -{ - float4 color = float4(0.0); - int count = 0; - for (int i = 0; i < _46.textureCount; i++) - { - if (_46.textureTypes[i].x == type) - { - if (i == 0) - { - color += texture1.sample(texture1Smplr, texCoord); - } - else - { - if (i == 1) - { - color += texture2.sample(texture2Smplr, texCoord); - } - else - { - if (i == 2) - { - color += texture3.sample(texture3Smplr, texCoord); - } - else - { - if (i == 3) - { - color += texture4.sample(texture4Smplr, texCoord); - } - else - { - if (i == 4) - { - color += texture5.sample(texture5Smplr, texCoord); - } - else - { - if (i == 5) - { - color += texture6.sample(texture6Smplr, texCoord); - } - else - { - if (i == 6) - { - color += texture7.sample(texture7Smplr, texCoord); - } - else - { - if (i == 7) - { - color += texture8.sample(texture8Smplr, texCoord); - } - else - { - if (i == 8) - { - color += texture9.sample(texture9Smplr, texCoord); - } - else - { - if (i == 9) - { - color += texture10.sample(texture10Smplr, texCoord); - } - } - } - } - } - } - } - } - } - } - count++; - } - } - if (count > 0) - { - color /= float4(float(count)); - } - if (count == 0) - { - return float4(-1.0); - } - return color; -} - -fragment main0_out main0(main0_in in [[stage_in]], constant UBO& _46 [[buffer(0)]], constant MaterialPush& material [[buffer(1)]], texture2d texture1 [[texture(0)]], texture2d texture2 [[texture(1)]], texture2d texture3 [[texture(2)]], texture2d texture4 [[texture(3)]], texture2d texture5 [[texture(4)]], texture2d texture6 [[texture(5)]], texture2d texture7 [[texture(6)]], texture2d texture8 [[texture(7)]], texture2d texture9 [[texture(8)]], texture2d texture10 [[texture(9)]], sampler texture1Smplr [[sampler(0)]], sampler texture2Smplr [[sampler(1)]], sampler texture3Smplr [[sampler(2)]], sampler texture4Smplr [[sampler(3)]], sampler texture5Smplr [[sampler(4)]], sampler texture6Smplr [[sampler(5)]], sampler texture7Smplr [[sampler(6)]], sampler texture8Smplr [[sampler(7)]], sampler texture9Smplr [[sampler(8)]], sampler texture10Smplr [[sampler(9)]], float4 gl_FragCoord [[position]]) -{ - main0_out out = {}; - float3x3 TBN = {}; - TBN[0] = in.TBN_0; - TBN[1] = in.TBN_1; - TBN[2] = in.TBN_2; - float2 texCoord = in.TexCoord * _46.textureScale + _46.textureOffset; - bool hasParallaxMap = false; - for (int i = 0; i < _46.textureCount; i++) - { - if (_46.textureTypes[i].x == 6) - { - hasParallaxMap = true; - break; - } - } - if (hasParallaxMap) - { - float3 tangentViewDir = fast::normalize(transpose(TBN) * (_46.cameraPosition - in.FragPos)); - float2 param = texCoord; - float3 param_1 = tangentViewDir; - texCoord = parallaxMapping(param, param_1, _46, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - } - int param_2 = 0; - float4 sampledColor = enableTextures(param_2, _46, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - bool hasColorTexture = any(sampledColor != float4(-1.0)); - float4 baseColor = float4(material.albedo[0], material.albedo[1], material.albedo[2], 1.0); - int param_3 = 0; - float4 albedoTex = enableTextures(param_3, _46, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - if (any(albedoTex != float4(-1.0))) - { - baseColor *= albedoTex; - } - int param_3a = 12; - float4 opacityTex = enableTextures(param_3a, _46, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - if (any(opacityTex != float4(-1.0))) - { - if (opacityTex.x < 0.100000001490116119384765625) - { - discard_fragment(); - } - } - else - { - if ((baseColor.w < 0.100000001490116119384765625) && (material.albedo[3] < 0.999000012874603271484375)) - { - discard_fragment(); - } - } - int param_4 = 5; - float4 normTexture = enableTextures(param_4, _46, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - bool _527 = normTexture.x != (-1.0); - bool _534; - if (_527) - { - _534 = normTexture.y != (-1.0); - } - else - { - _534 = _527; - } - bool _540; - if (_534) - { - _540 = normTexture.z != (-1.0); - } - else - { - _540 = _534; - } - float normalStrength = fast::max(_46.normalMapStrength, 0.0f); - bool useNormalMap = (_46.useNormalMap != 0u) && (normalStrength > 0.0f); - float3 normal; - if (_540 && useNormalMap) - { - float3 tangentNormal = (normTexture.xyz * 2.0) - float3(1.0); - tangentNormal.xy *= normalStrength; - tangentNormal = fast::normalize(tangentNormal); - normal = fast::normalize(TBN * tangentNormal); - } - else - { - normal = fast::normalize(in.Normal); - } - float3 albedoColor = baseColor.xyz; - int param_pbr_pack = 14; - float4 pbrPackTex = enableTextures(param_pbr_pack, _46, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - bool hasPbrPack = any(pbrPackTex != float4(-1.0)); - float metallicValue = material.metallic; - int param_5 = 9; - float4 metallicTex = enableTextures(param_5, _46, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - if (hasPbrPack) - { - metallicValue *= pbrPackTex.z; - } - else if (any(metallicTex != float4(-1.0))) - { - metallicValue *= metallicTex.x; - } - float roughnessValue = material.roughness; - int param_6 = 10; - float4 roughnessTex = enableTextures(param_6, _46, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - if (hasPbrPack) - { - roughnessValue *= pbrPackTex.y; - } - else if (any(roughnessTex != float4(-1.0))) - { - roughnessValue *= roughnessTex.x; - } - float aoValue = material.ao; - int param_7 = 11; - float4 aoTex = enableTextures(param_7, _46, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - if (hasPbrPack) - { - aoValue *= pbrPackTex.x; - } - else if (any(aoTex != float4(-1.0))) - { - aoValue *= aoTex.x; - } - metallicValue = fast::clamp(metallicValue, 0.0, 1.0); - roughnessValue = fast::clamp(roughnessValue, 0.0, 1.0); - aoValue = fast::clamp(aoValue, 0.0, 1.0); - float nonlinearDepth = gl_FragCoord.z; - out.gPosition = float4(in.FragPos, nonlinearDepth); - float3 n = fast::normalize(normal); - bool _639 = !all(n == n); - bool _646; - if (!_639) - { - _646 = length(n) < 9.9999997473787516355514526367188e-05; - } - else - { - _646 = _639; - } - if (_646) - { - n = fast::normalize(in.Normal); - } - out.gNormal = float4(n, 1.0); - float3 a = fast::clamp(albedoColor, float3(0.0), float3(1.0)); - if (!all(a == a)) - { - a = float3(0.0); - } - out.gAlbedoSpec = float4(a, aoValue); - out.gMaterial = float4(metallicValue, roughnessValue, aoValue, fast::clamp(material.reflectivity, 0.0, 1.0)); - return out; -} diff --git a/shaders/metal/deferred/deferred.vert.metal b/shaders/metal/deferred/deferred.vert.metal deleted file mode 100644 index 28b52b3e..00000000 --- a/shaders/metal/deferred/deferred.vert.metal +++ /dev/null @@ -1,127 +0,0 @@ -#pragma clang diagnostic ignored "-Wmissing-prototypes" - -#include -#include - -using namespace metal; - -// Returns the determinant of a 2x2 matrix. -static inline __attribute__((always_inline)) -float spvDet2x2(float a1, float a2, float b1, float b2) -{ - return a1 * b2 - b1 * a2; -} - -// Returns the determinant of a 3x3 matrix. -static inline __attribute__((always_inline)) -float spvDet3x3(float a1, float a2, float a3, float b1, float b2, float b3, float c1, float c2, float c3) -{ - return a1 * spvDet2x2(b2, b3, c2, c3) - b1 * spvDet2x2(a2, a3, c2, c3) + c1 * spvDet2x2(a2, a3, b2, b3); -} - -// Returns the inverse of a matrix, by using the algorithm of calculating the classical -// adjoint and dividing by the determinant. The contents of the matrix are changed. -static inline __attribute__((always_inline)) -float4x4 spvInverse4x4(float4x4 m) -{ - float4x4 adj; // The adjoint matrix (inverse after dividing by determinant) - - // Create the transpose of the cofactors, as the classical adjoint of the matrix. - adj[0][0] = spvDet3x3(m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], m[2][3], m[3][1], m[3][2], m[3][3]); - adj[0][1] = -spvDet3x3(m[0][1], m[0][2], m[0][3], m[2][1], m[2][2], m[2][3], m[3][1], m[3][2], m[3][3]); - adj[0][2] = spvDet3x3(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], m[3][1], m[3][2], m[3][3]); - adj[0][3] = -spvDet3x3(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], m[2][3]); - - adj[1][0] = -spvDet3x3(m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][2], m[3][3]); - adj[1][1] = spvDet3x3(m[0][0], m[0][2], m[0][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][2], m[3][3]); - adj[1][2] = -spvDet3x3(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], m[3][0], m[3][2], m[3][3]); - adj[1][3] = spvDet3x3(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], m[2][3]); - - adj[2][0] = spvDet3x3(m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], m[2][3], m[3][0], m[3][1], m[3][3]); - adj[2][1] = -spvDet3x3(m[0][0], m[0][1], m[0][3], m[2][0], m[2][1], m[2][3], m[3][0], m[3][1], m[3][3]); - adj[2][2] = spvDet3x3(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], m[3][0], m[3][1], m[3][3]); - adj[2][3] = -spvDet3x3(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], m[2][3]); - - adj[3][0] = -spvDet3x3(m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2], m[3][0], m[3][1], m[3][2]); - adj[3][1] = spvDet3x3(m[0][0], m[0][1], m[0][2], m[2][0], m[2][1], m[2][2], m[3][0], m[3][1], m[3][2]); - adj[3][2] = -spvDet3x3(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[3][0], m[3][1], m[3][2]); - adj[3][3] = spvDet3x3(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2]); - - // Calculate the determinant as a combination of the cofactors of the first row. - float det = (adj[0][0] * m[0][0]) + (adj[0][1] * m[1][0]) + (adj[0][2] * m[2][0]) + (adj[0][3] * m[3][0]); - - // Divide the classical adjoint matrix by the determinant. - // If determinant is zero, matrix is not invertable, so leave it unchanged. - return (det != 0.0f) ? (adj * (1.0f / det)) : m; -} - -struct UBO -{ - float4x4 model; - float4x4 view; - float4x4 projection; - uint isInstanced; -}; - -struct main0_out -{ - float4 outColor [[user(locn0)]]; - float2 TexCoord [[user(locn1)]]; - float3 Normal [[user(locn2)]]; - float3 FragPos [[user(locn3)]]; - float3 TBN_0 [[user(locn4)]]; - float3 TBN_1 [[user(locn5)]]; - float3 TBN_2 [[user(locn6)]]; - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; - float4 aColor [[attribute(1)]]; - float2 aTexCoord [[attribute(2)]]; - float3 aNormal [[attribute(3)]]; - float3 aTangent [[attribute(4)]]; - float3 aBitangent [[attribute(5)]]; - float4 instanceModel_0 [[attribute(6)]]; - float4 instanceModel_1 [[attribute(7)]]; - float4 instanceModel_2 [[attribute(8)]]; - float4 instanceModel_3 [[attribute(9)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]], constant UBO& _12 [[buffer(0)]]) -{ - main0_out out = {}; - float3x3 TBN = {}; - float4x4 instanceModel = {}; - instanceModel[0] = in.instanceModel_0; - instanceModel[1] = in.instanceModel_1; - instanceModel[2] = in.instanceModel_2; - instanceModel[3] = in.instanceModel_3; - float4x4 finalModel; - bool hasInstanceMatrix = abs(instanceModel[3].w) > 0.5; - if ((_12.isInstanced != 0u) && hasInstanceMatrix) - { - finalModel = instanceModel; - } - else - { - finalModel = _12.model; - } - float4 worldPos = finalModel * float4(in.aPos, 1.0); - out.FragPos = worldPos.xyz; - out.gl_Position = (_12.projection * _12.view) * worldPos; - out.TexCoord = in.aTexCoord; - out.outColor = in.aColor; - float4x4 _81 = transpose(spvInverse4x4(finalModel)); - float3x3 normalMatrix = float3x3(_81[0].xyz, _81[1].xyz, _81[2].xyz); - out.Normal = fast::normalize(normalMatrix * in.aNormal); - float3 T = fast::normalize(normalMatrix * in.aTangent); - float3 B = fast::normalize(normalMatrix * in.aBitangent); - float3 N = fast::normalize(normalMatrix * in.aNormal); - TBN = float3x3(float3(T), float3(B), float3(N)); - out.TBN_0 = TBN[0]; - out.TBN_1 = TBN[1]; - out.TBN_2 = TBN[2]; - return out; -} diff --git a/shaders/metal/deferred/light.frag.metal b/shaders/metal/deferred/light.frag.metal deleted file mode 100644 index ee297b2d..00000000 --- a/shaders/metal/deferred/light.frag.metal +++ /dev/null @@ -1,1549 +0,0 @@ -#pragma clang diagnostic ignored "-Wmissing-prototypes" -#pragma clang diagnostic ignored "-Wmissing-braces" - -#include -#include - -using namespace metal; - -template struct spvUnsafeArray { - T elements[Num ? Num : 1]; - - thread T &operator[](size_t pos) thread { return elements[pos]; } - constexpr const thread T &operator[](size_t pos) const thread { - return elements[pos]; - } - - device T &operator[](size_t pos) device { return elements[pos]; } - constexpr const device T &operator[](size_t pos) const device { - return elements[pos]; - } - - constexpr const constant T &operator[](size_t pos) const constant { - return elements[pos]; - } - - threadgroup T &operator[](size_t pos) threadgroup { return elements[pos]; } - constexpr const threadgroup T &operator[](size_t pos) const threadgroup { - return elements[pos]; - } -}; - -// Implementation of the GLSL radians() function -template inline T radians(T d) { return d * T(0.01745329251); } - -// Returns the determinant of a 2x2 matrix. -static inline __attribute__((always_inline)) float -spvDet2x2(float a1, float a2, float b1, float b2) { - return a1 * b2 - b1 * a2; -} - -// Returns the determinant of a 3x3 matrix. -static inline __attribute__((always_inline)) float -spvDet3x3(float a1, float a2, float a3, float b1, float b2, float b3, float c1, - float c2, float c3) { - return a1 * spvDet2x2(b2, b3, c2, c3) - b1 * spvDet2x2(a2, a3, c2, c3) + - c1 * spvDet2x2(a2, a3, b2, b3); -} - -// Returns the inverse of a matrix, by using the algorithm of calculating the -// classical adjoint and dividing by the determinant. The contents of the matrix -// are changed. -static inline __attribute__((always_inline)) float4x4 -spvInverse4x4(float4x4 m) { - float4x4 adj; // The adjoint matrix (inverse after dividing by determinant) - - // Create the transpose of the cofactors, as the classical adjoint of the - // matrix. - adj[0][0] = spvDet3x3(m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], m[2][3], - m[3][1], m[3][2], m[3][3]); - adj[0][1] = -spvDet3x3(m[0][1], m[0][2], m[0][3], m[2][1], m[2][2], m[2][3], - m[3][1], m[3][2], m[3][3]); - adj[0][2] = spvDet3x3(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], - m[3][1], m[3][2], m[3][3]); - adj[0][3] = -spvDet3x3(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], - m[2][1], m[2][2], m[2][3]); - - adj[1][0] = -spvDet3x3(m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], m[2][3], - m[3][0], m[3][2], m[3][3]); - adj[1][1] = spvDet3x3(m[0][0], m[0][2], m[0][3], m[2][0], m[2][2], m[2][3], - m[3][0], m[3][2], m[3][3]); - adj[1][2] = -spvDet3x3(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], - m[3][0], m[3][2], m[3][3]); - adj[1][3] = spvDet3x3(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], - m[2][0], m[2][2], m[2][3]); - - adj[2][0] = spvDet3x3(m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], m[2][3], - m[3][0], m[3][1], m[3][3]); - adj[2][1] = -spvDet3x3(m[0][0], m[0][1], m[0][3], m[2][0], m[2][1], m[2][3], - m[3][0], m[3][1], m[3][3]); - adj[2][2] = spvDet3x3(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], - m[3][0], m[3][1], m[3][3]); - adj[2][3] = -spvDet3x3(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], - m[2][0], m[2][1], m[2][3]); - - adj[3][0] = -spvDet3x3(m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2], - m[3][0], m[3][1], m[3][2]); - adj[3][1] = spvDet3x3(m[0][0], m[0][1], m[0][2], m[2][0], m[2][1], m[2][2], - m[3][0], m[3][1], m[3][2]); - adj[3][2] = -spvDet3x3(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], - m[3][0], m[3][1], m[3][2]); - adj[3][3] = spvDet3x3(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], - m[2][0], m[2][1], m[2][2]); - - // Calculate the determinant as a combination of the cofactors of the first - // row. - float det = (adj[0][0] * m[0][0]) + (adj[0][1] * m[1][0]) + - (adj[0][2] * m[2][0]) + (adj[0][3] * m[3][0]); - - // Divide the classical adjoint matrix by the determinant. - // If determinant is zero, matrix is not invertable, so leave it unchanged. - return (det != 0.0f) ? (adj * (1.0f / det)) : m; -} - -struct ShadowParameters { - float4x4 lightView; - float4x4 lightProjection; - float bias0; - int textureIndex; - float farPlane; - int lightIndex; - float3 lightPos; - int lightType; -}; - -struct DirectionalLight { - float3 direction; - float _pad1; - float3 diffuse; - float _pad2; - float3 specular; - float intensity; -}; - -struct PointLight { - float3 position; - float _pad1; - float3 diffuse; - float _pad2; - float3 specular; - float intensity; - float constant0; - float linear; - float quadratic; - float radius; - float _pad3; -}; - -struct SpotLight { - float3 position; - float _pad1; - float3 direction; - float cutOff; - float outerCutOff; - float intensity; - float range; - float _pad4; - float3 diffuse; - float _pad5; - float3 specular; - float _pad6; -}; - -struct UBO { - packed_float3 cameraPosition; - uint useIBL; -}; - -struct Environment { - float rimLightIntensity; - float3 rimLightColor; - float bloomThreshold; -}; - -struct PushConstants { - int directionalLightCount; - int pointLightCount; - int spotlightCount; - int areaLightCount; - int shadowParamCount; -}; - -struct ShadowParameters_1 { - float4x4 lightView; - float4x4 lightProjection; - float bias0; - int textureIndex; - float farPlane; - int lightIndex; - packed_float3 lightPos; - int lightType; -}; - -struct ShadowParams { - spvUnsafeArray shadowParams; -}; - -struct DirectionalLight_1 { - packed_float3 direction; - float _pad1; - packed_float3 diffuse; - float _pad2; - packed_float3 specular; - float intensity; -}; - -struct DirectionalLights { - spvUnsafeArray directionalLights; -}; - -struct PointLight_1 { - packed_float3 position; - float _pad1; - packed_float3 diffuse; - float _pad2; - packed_float3 specular; - float intensity; - float constant0; - float linear; - float quadratic; - float radius; - float _pad3; -}; - -struct PointLights { - spvUnsafeArray pointLights; -}; - -struct SpotLight_1 { - packed_float3 position; - float _pad1; - packed_float3 direction; - float cutOff; - float outerCutOff; - float intensity; - float range; - float _pad4; - packed_float3 diffuse; - float _pad5; - packed_float3 specular; - float _pad6; -}; - -struct SpotLights { - spvUnsafeArray spotlights; -}; - -struct AreaLight { - packed_float3 position; - float _pad1; - packed_float3 right; - float _pad2; - packed_float3 up; - float _pad3; - float2 size; - float _pad4; - float _pad5; - packed_float3 diffuse; - float _pad6; - packed_float3 specular; - float angle; - int castsBothSides; - float intensity; - float range; - float _pad9; -}; - -struct AreaLights { - spvUnsafeArray areaLights; -}; - -struct AmbientLight { - float4 color; - float intensity; - float3 _pad0; -}; - -struct ProbeSpace { - float3 origin; - float _pad0; - - float3 spacing; - float _pad1; - - float3 probeCount; - float _pad2; - - float4 debugColor; - - float4 atlasParams; - // x = textureBorderSize - // y = probeResolution (inner) - // z = probesPerRow - // w = totalProbes (put this here on CPU!) -}; - -constant spvUnsafeArray _660 = spvUnsafeArray( - {float2(-0.3260000050067901611328125, -0.4059999883174896240234375), - float2(-0.839999973773956298828125, -0.07400000095367431640625), - float2(-0.69599997997283935546875, 0.4569999873638153076171875), - float2(-0.20299999415874481201171875, 0.620999991893768310546875), - float2(0.96200001239776611328125, -0.194999992847442626953125), - float2(0.472999989986419677734375, -0.4799999892711639404296875), - float2(0.518999993801116943359375, 0.767000019550323486328125), - float2(0.185000002384185791015625, -0.89300000667572021484375), - float2(0.507000029087066650390625, 0.064000003039836883544921875), - float2(0.89600002765655517578125, 0.412000000476837158203125), - float2(-0.3219999969005584716796875, -0.933000028133392333984375), - float2(-0.791999995708465576171875, -0.597999989986419677734375)}); -constant spvUnsafeArray _861 = spvUnsafeArray( - {float3(0.5381000041961669921875, 0.18559999763965606689453125, - -0.4318999946117401123046875), - float3(0.13789999485015869140625, 0.248600006103515625, - 0.4429999887943267822265625), - float3(0.3370999991893768310546875, 0.567900002002716064453125, - -0.0057000000961124897003173828125), - float3(-0.699899971485137939453125, -0.0450999997556209564208984375, - -0.0019000000320374965667724609375), - float3(0.068899996578693389892578125, -0.159799993038177490234375, - -0.854700028896331787109375), - float3(0.056000001728534698486328125, 0.0068999999202787876129150390625, - -0.184300005435943603515625), - float3(-0.014600000344216823577880859375, 0.14020000398159027099609375, - 0.076200000941753387451171875), - float3(0.00999999977648258209228515625, -0.19239999353885650634765625, - -0.03440000116825103759765625), - float3(-0.35769999027252197265625, -0.53009998798370361328125, - -0.4357999861240386962890625), - float3(-0.3169000148773193359375, 0.10629999637603759765625, - 0.015799999237060546875), - float3(0.010300000198185443878173828125, -0.5868999958038330078125, - 0.0046000001020729541778564453125), - float3(-0.08969999849796295166015625, -0.4939999878406524658203125, - 0.328700006008148193359375), - float3(0.7118999958038330078125, -0.015399999916553497314453125, - -0.091799996793270111083984375), - float3(-0.053300000727176666259765625, 0.0595999993383884429931640625, - -0.541100025177001953125), - float3(0.03519999980926513671875, -0.063100002706050872802734375, - 0.546000003814697265625), - float3(-0.4776000082492828369140625, 0.2847000062465667724609375, - -0.0271000005304813385009765625), - float3(-0.11200000345706939697265625, 0.1234000027179718017578125, - -0.744599997997283935546875), - float3(-0.212999999523162841796875, -0.07819999754428863525390625, - -0.13789999485015869140625), - float3(0.2944000065326690673828125, -0.3111999928951263427734375, - -0.2644999921321868896484375), - float3(-0.4564000070095062255859375, 0.4174999892711639404296875, - -0.184300005435943603515625)}); - -struct main0_out { - float4 FragColor [[color(0)]]; - float4 BrightColor [[color(1)]]; -}; - -struct main0_in { - float2 TexCoord [[user(locn0)]]; -}; - -static inline __attribute__((always_inline)) float2 getTextureDimensions( - thread const int &textureIndex, texture2d texture1, - sampler texture1Smplr, texture2d texture2, sampler texture2Smplr, - texture2d texture3, sampler texture3Smplr, texture2d texture4, - sampler texture4Smplr, texture2d texture5, sampler texture5Smplr) { - if (textureIndex == 0) { - return float2(int2(texture1.get_width(), texture1.get_height())); - } else { - if (textureIndex == 1) { - return float2(int2(texture2.get_width(), texture2.get_height())); - } else { - if (textureIndex == 2) { - return float2( - int2(texture3.get_width(), texture3.get_height())); - } else { - if (textureIndex == 3) { - return float2( - int2(texture4.get_width(), texture4.get_height())); - } else { - if (textureIndex == 4) { - return float2( - int2(texture5.get_width(), texture5.get_height())); - } - } - } - } - } - return float2(0.0); -} - -static inline __attribute__((always_inline)) float4 sampleCubeTextureAt( - thread const int &textureIndex, thread const float3 &direction, - texturecube cubeMap1, sampler cubeMap1Smplr, - texturecube cubeMap2, sampler cubeMap2Smplr, - texturecube cubeMap3, sampler cubeMap3Smplr, - texturecube cubeMap4, sampler cubeMap4Smplr, - texturecube cubeMap5, sampler cubeMap5Smplr) { - if (textureIndex == 0) { - return cubeMap1.sample(cubeMap1Smplr, direction); - } else { - if (textureIndex == 1) { - return cubeMap2.sample(cubeMap2Smplr, direction); - } else { - if (textureIndex == 2) { - return cubeMap3.sample(cubeMap3Smplr, direction); - } else { - if (textureIndex == 3) { - return cubeMap4.sample(cubeMap4Smplr, direction); - } else { - if (textureIndex == 4) { - return cubeMap5.sample(cubeMap5Smplr, direction); - } - } - } - } - } - return float4(0.0); -} - -static inline __attribute__((always_inline)) float calculatePointShadow( - thread const ShadowParameters &shadowParam, thread const float3 &fragPos, - texture2d texture1, sampler texture1Smplr, texture2d texture2, - sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, - texture2d texture4, sampler texture4Smplr, texture2d texture5, - sampler texture5Smplr, texturecube cubeMap1, sampler cubeMap1Smplr, - texturecube cubeMap2, sampler cubeMap2Smplr, - texturecube cubeMap3, sampler cubeMap3Smplr, - texturecube cubeMap4, sampler cubeMap4Smplr, - texturecube cubeMap5, sampler cubeMap5Smplr) { - int param = shadowParam.textureIndex; - float2 dims = getTextureDimensions( - param, texture1, texture1Smplr, texture2, texture2Smplr, texture3, - texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr); - bool _739 = dims.x == 0.0; - bool _746; - if (!_739) { - _746 = dims.y == 0.0; - } else { - _746 = _739; - } - if (_746) { - return 0.0; - } - float3 fragToLight = fragPos - shadowParam.lightPos; - float currentDepth = length(fragToLight); - if (currentDepth >= shadowParam.farPlane) { - return 0.0; - } - float bias0 = 0.0500000007450580596923828125; - float shadow = 0.0; - float diskRadius = (1.0 + (currentDepth / shadowParam.farPlane)) * - 0.0500000007450580596923828125; - for (int i = 0; i < 10; i++) { - float3 sampleDir = - fast::normalize(fragToLight + (_861[i] * diskRadius)); - int param_1 = shadowParam.textureIndex; - float3 param_2 = sampleDir; - float closestDepth = - sampleCubeTextureAt(param_1, param_2, cubeMap1, cubeMap1Smplr, - cubeMap2, cubeMap2Smplr, cubeMap3, - cubeMap3Smplr, cubeMap4, cubeMap4Smplr, - cubeMap5, cubeMap5Smplr) - .x * - shadowParam.farPlane; - if ((currentDepth - bias0) > closestDepth) { - shadow += 1.0; - } - } - shadow /= 10.0; - return shadow; -} - -static inline __attribute__((always_inline)) float4 sampleTextureAt( - thread const int &textureIndex, thread const float2 &uv, - texture2d texture1, sampler texture1Smplr, texture2d texture2, - sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, - texture2d texture4, sampler texture4Smplr, texture2d texture5, - sampler texture5Smplr) { - if (textureIndex == 0) { - return texture1.sample(texture1Smplr, uv); - } else { - if (textureIndex == 1) { - return texture2.sample(texture2Smplr, uv); - } else { - if (textureIndex == 2) { - return texture3.sample(texture3Smplr, uv); - } else { - if (textureIndex == 3) { - return texture4.sample(texture4Smplr, uv); - } else { - if (textureIndex == 4) { - return texture5.sample(texture5Smplr, uv); - } - } - } - } - } - return float4(0.0); -} - -static inline __attribute__((always_inline)) float calculateShadow( - thread const ShadowParameters &shadowParam, thread const float3 &fragPos, - thread const float3 &normal, texture2d texture1, - sampler texture1Smplr, texture2d texture2, sampler texture2Smplr, - texture2d texture3, sampler texture3Smplr, texture2d texture4, - sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, - constant UBO &_526) { - int param = shadowParam.textureIndex; - float2 dims = getTextureDimensions( - param, texture1, texture1Smplr, texture2, texture2Smplr, texture3, - texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr); - bool _411 = dims.x == 0.0; - bool _419; - if (!_411) { - _419 = dims.y == 0.0; - } else { - _419 = _411; - } - if (_419) { - return 0.0; - } - float4 fragPosLightSpace = - (shadowParam.lightProjection * shadowParam.lightView) * - float4(fragPos, 1.0); - if (fragPosLightSpace.w == 0.0) { - return 0.0; - } - float3 clipCoords = fragPosLightSpace.xyz / float3(fragPosLightSpace.w); - float2 projCoordsXY = (clipCoords.xy * 0.5) + float2(0.5); - float3 projCoords = float3(projCoordsXY, clipCoords.z); - bool _456 = projCoords.x < 0.0; - bool _463; - if (!_456) { - _463 = projCoords.x > 1.0; - } else { - _463 = _456; - } - bool _470; - if (!_463) { - _470 = projCoords.y < 0.0; - } else { - _470 = _463; - } - bool _477; - if (!_470) { - _477 = projCoords.y > 1.0; - } else { - _477 = _470; - } - bool _485; - if (!_477) { - _485 = projCoords.z < 0.0; - } else { - _485 = _477; - } - bool _493; - if (!_485) { - _493 = projCoords.z > 1.0; - } else { - _493 = _485; - } - if (_493) { - return 0.0; - } - float currentDepth = projCoords.z; - bool isAreaShadow = shadowParam.lightType == 2; - float3 lightDirWorld = fast::normalize( - -(spvInverse4x4(shadowParam.lightView) * float4(0.0, 0.0, -1.0, 0.0)) - .xyz); - float biasValue = shadowParam.bias0; - if (isAreaShadow) { - biasValue = fast::max(biasValue, 0.0012000000569969416); - } - float ndotl = fast::max(dot(normal, lightDirWorld), 0.0); - float minBias = - fast::max(isAreaShadow ? 0.0002500000118743628 - : 4.9999998736893758177757263183594e-05, - biasValue * (isAreaShadow ? 0.8500000238418579 : 0.25)); - float bias0 = fast::max(biasValue * (1.0 - ndotl), minBias); - if (isAreaShadow) { - bias0 += 0.0002500000118743628; - } - float shadow = 0.0; - float2 texelSize = float2(1.0) / dims; - float _distance = length(float3(_526.cameraPosition) - fragPos); - float2 shadowMapSize = dims; - float avgDim = 0.5 * (shadowMapSize.x + shadowMapSize.y); - float resFactor = fast::clamp(1024.0 / fast::max(avgDim, 1.0), 0.75, 1.25); - float distFactor = fast::clamp(_distance / 800.0, 0.0, 1.0); - float texelRadius = - mix(isAreaShadow ? 1.7999999523162842 : 1.0, - isAreaShadow ? 4.199999809265137 : 3.0, distFactor) * - resFactor; - float2 filterRadius = texelSize * texelRadius; - int kernelSamples = isAreaShadow ? 6 : 8; - int sampleCount = 0; - for (int i = 0; i < kernelSamples; i++) { - float2 offset = _660[i] * filterRadius; - float2 uv = projCoords.xy + offset; - bool _676 = uv.x < 0.0; - bool _683; - if (!_676) { - _683 = uv.x > 1.0; - } else { - _683 = _676; - } - bool _690; - if (!_683) { - _690 = uv.y < 0.0; - } else { - _690 = _683; - } - bool _697; - if (!_690) { - _697 = uv.y > 1.0; - } else { - _697 = _690; - } - if (_697) { - continue; - } - int param_1 = shadowParam.textureIndex; - float2 param_2 = uv; - float pcfDepth = - sampleTextureAt(param_1, param_2, texture1, texture1Smplr, texture2, - texture2Smplr, texture3, texture3Smplr, texture4, - texture4Smplr, texture5, texture5Smplr) - .x; - shadow += float((currentDepth - bias0) > pcfDepth); - sampleCount++; - } - if (sampleCount > 0) { - shadow /= float(sampleCount); - } - if (isAreaShadow) { - shadow = smoothstep(0.18000000715255737, 0.9200000166893005, shadow); - } - return shadow; -} - -static inline __attribute__((always_inline)) float -distributionGGX(thread const float3 &N, thread const float3 &H, - thread const float &roughness) { - float a = roughness * roughness; - float a2 = a * a; - float NdotH = fast::max(dot(N, H), 0.0); - float NdotH2 = NdotH * NdotH; - float num = a2; - float denom = (NdotH2 * (a2 - 1.0)) + 1.0; - denom = (3.1415927410125732421875 * denom) * denom; - return num / fast::max(denom, 9.9999997473787516355514526367188e-05); -} - -static inline __attribute__((always_inline)) float -geometrySchlickGGX(thread const float &NdotV, thread const float &roughness) { - float r = roughness + 1.0; - float k = (r * r) / 8.0; - float num = NdotV; - float denom = (NdotV * (1.0 - k)) + k; - return num / fast::max(denom, 9.9999997473787516355514526367188e-05); -} - -static inline __attribute__((always_inline)) float -geometrySmith(thread const float3 &N, thread const float3 &V, - thread const float3 &L, thread const float &roughness) { - float NdotV = fast::max(dot(N, V), 0.0); - float NdotL = fast::max(dot(N, L), 0.0); - float param = NdotV; - float param_1 = roughness; - float ggx2 = geometrySchlickGGX(param, param_1); - float param_2 = NdotL; - float param_3 = roughness; - float ggx1 = geometrySchlickGGX(param_2, param_3); - return ggx1 * ggx2; -} - -static inline __attribute__((always_inline)) float3 -fresnelSchlick(thread const float &cosTheta, thread const float3 &F0) { - return F0 + ((float3(1.0) - F0) * powr(1.0 - cosTheta, 5.0)); -} - -static inline __attribute__((always_inline)) float3 -evaluateBRDF(thread const float3 &L, thread const float3 &radiance, - thread const float3 &N, thread const float3 &V, - thread const float3 &F0, thread const float3 &albedo, - thread const float &metallic, thread const float &roughness) { - float3 H = fast::normalize(V + L); - float3 param = N; - float3 param_1 = H; - float param_2 = roughness; - float NDF = distributionGGX(param, param_1, param_2); - float3 param_3 = N; - float3 param_4 = V; - float3 param_5 = L; - float param_6 = roughness; - float G = geometrySmith(param_3, param_4, param_5, param_6); - float param_7 = fast::max(dot(H, V), 0.0); - float3 param_8 = F0; - float3 F = fresnelSchlick(param_7, param_8); - float3 kS = F; - float3 kD = (float3(1.0) - kS) * (1.0 - metallic); - float NdotV = fast::max(dot(N, V), 0.0); - float NdotL = fast::max(dot(N, L), 0.0); - float3 numerator = F * (NDF * G); - float denominator = - fast::max((4.0 * NdotV) * NdotL, 9.9999997473787516355514526367188e-05); - float3 specular = numerator / float3(denominator); - return ((((kD * albedo) / float3(3.1415927410125732421875)) + specular) * - radiance) * - NdotL; -} - -static inline __attribute__((always_inline)) float3 calcDirectionalLight( - thread const DirectionalLight &light, thread const float3 &N, - thread const float3 &V, thread const float3 &F0, - thread const float3 &albedo, thread const float &metallic, - thread const float &roughness) { - float3 L = fast::normalize(-light.direction); - float3 radiance = light.diffuse * fast::max(light.intensity, 0.0); - float3 param = L; - float3 param_1 = radiance; - float3 param_2 = N; - float3 param_3 = V; - float3 param_4 = F0; - float3 param_5 = albedo; - float param_6 = metallic; - float param_7 = roughness; - return evaluateBRDF(param, param_1, param_2, param_3, param_4, param_5, - param_6, param_7); -} - -static inline __attribute__((always_inline)) float3 -calcPointLight(thread const PointLight &light, thread const float3 &fragPos, - thread const float3 &N, thread const float3 &V, - thread const float3 &F0, thread const float3 &albedo, - thread const float &metallic, thread const float &roughness) { - float3 L = light.position - fragPos; - float _distance = length(L); - float3 _1019; - if (_distance > 0.0) { - _1019 = L / float3(_distance); - } else { - _1019 = float3(0.0, 0.0, 1.0); - } - float3 direction = _1019; - float attenuation = - 1.0 / fast::max((light.constant0 + (light.linear * _distance)) + - ((light.quadratic * _distance) * _distance), - 9.9999997473787516355514526367188e-05); - float fade = 1.0 - smoothstep(light.radius * 0.89999997615814208984375, - light.radius, _distance); - float3 radiance = - ((light.diffuse * fast::max(light.intensity, 0.0)) * attenuation) * - fade; - float3 param = direction; - float3 param_1 = radiance; - float3 param_2 = N; - float3 param_3 = V; - float3 param_4 = F0; - float3 param_5 = albedo; - float param_6 = metallic; - float param_7 = roughness; - return evaluateBRDF(param, param_1, param_2, param_3, param_4, param_5, - param_6, param_7); -} - -static inline __attribute__((always_inline)) float3 -calcSpotLight(thread const SpotLight &light, thread const float3 &fragPos, - thread const float3 &N, thread const float3 &V, - thread const float3 &F0, thread const float3 &albedo, - thread const float &metallic, thread const float &roughness) { - float3 L = light.position - fragPos; - float _distance = length(L); - float3 direction = fast::normalize(L); - float3 spotDirection = fast::normalize(light.direction); - float theta = dot(direction, -spotDirection); - float epsilon = fast::max(light.cutOff - light.outerCutOff, - 9.9999997473787516355514526367188e-05); - float intensity = - fast::clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0); - float range = fast::max(light.range, 0.001000000047497451305389404296875); - float attenuation = 1.0 / ((1.0 + (_distance / range)) + - ((_distance * _distance) / (range * range))); - float fade = - 1.0 - smoothstep(range * 0.89999997615814208984375, range, _distance); - float3 radiance = - (((light.diffuse * fast::max(light.intensity, 0.0)) * attenuation) * - intensity) * - fade; - float3 param = direction; - float3 param_1 = radiance; - float3 param_2 = N; - float3 param_3 = V; - float3 param_4 = F0; - float3 param_5 = albedo; - float param_6 = metallic; - float param_7 = roughness; - return evaluateBRDF(param, param_1, param_2, param_3, param_4, param_5, - param_6, param_7); -} - -static inline __attribute__((always_inline)) float3 -getRimLight(thread const float3 &fragPos, thread float3 &N, thread float3 &V, - thread const float3 &F0, thread const float3 &albedo, - thread const float &metallic, thread const float &roughness, - constant UBO &_526, constant Environment &environment) { - N = fast::normalize(N); - V = fast::normalize(V); - float rim = powr(1.0 - fast::max(dot(N, V), 0.0), 3.0); - rim *= mix(1.2000000476837158203125, 0.300000011920928955078125, roughness); - float3 rimColor = - mix(float3(1.0), albedo, float3(metallic)) * environment.rimLightColor; - rimColor = mix(rimColor, F0, float3(0.5)); - float rimIntensity = environment.rimLightIntensity; - float3 rimLight = (rimColor * rim) * rimIntensity; - float dist = length(float3(_526.cameraPosition) - fragPos); - rimLight /= float3(1.0 + (dist * 0.100000001490116119384765625)); - return rimLight; -} - -static inline __attribute__((always_inline)) float3 -sampleEnvironmentRadiance(thread const float3 &direction, - texturecube skybox, sampler skyboxSmplr) { - return skybox.sample(skyboxSmplr, direction).xyz; -} - -static inline __attribute__((always_inline)) float3 -acesToneMapping(thread float3 &color) { - float a = 2.5099999904632568359375; - float b = 0.02999999932944774627685546875; - float c = 2.4300000667572021484375; - float d = 0.589999973773956298828125; - float e = 0.14000000059604644775390625; - color = (color * ((color * a) + float3(b))) / - ((color * ((color * c) + float3(d))) + float3(e)); - color = powr(fast::clamp(color, float3(0.0), float3(1.0)), - float3(0.4545454680919647216796875)); - return color; -} - -static inline float2 octEncode(float3 n) { - n /= (fabs(n.x) + fabs(n.y) + fabs(n.z) + 1e-6f); - float2 e = n.xy; - - if (n.z < 0.0f) { - float2 signNotZero = - float2(e.x >= 0.0f ? 1.0f : -1.0f, e.y >= 0.0f ? 1.0f : -1.0f); - e = (1.0f - fabs(e.yx)) * signNotZero; - } - return e; -} - -static inline float3 safeNormalizeDDGI(float3 v, float3 fallback) { - float len2 = dot(v, v); - if (len2 > 1e-10f) { - return v * rsqrt(len2); - } - return fallback; -} - -static inline uint probeIndexFromCoord(uint3 c, uint3 counts) { - return c.x + counts.x * (c.y + counts.y * c.z); -} - -static inline float2 ddgiAtlasUV(uint probeIndex, float3 dirWS, - constant ProbeSpace &ps, uint atlasW, - uint atlasH) { - if (atlasW == 0u || atlasH == 0u) { - return float2(0.5f); - } - - uint border = (uint)ps.atlasParams.x; - uint innerRes = (uint)ps.atlasParams.y; - uint probesPerRow = (uint)ps.atlasParams.z; - if (innerRes == 0u || probesPerRow == 0u) { - return float2(0.5f); - } - - uint tileRes = innerRes + 2u * border; - - uint tileX = probeIndex % probesPerRow; - uint tileY = probeIndex / probesPerRow; - - float dirLen = length(dirWS); - float3 safeDir = - (dirLen > 1e-6f) ? (dirWS / float3(dirLen)) : float3(0.0f, 1.0f, 0.0f); - float2 e = octEncode(safeDir); - float2 innerUV = e * 0.5f + 0.5f; - - float2 innerPx = float2((float)(tileX * tileRes + border), - (float)(tileY * tileRes + border)) + - innerUV * float(innerRes - 1u); - - return (innerPx + 0.5f) / float2((float)atlasW, (float)atlasH); -} - -static inline float4 sampleDDGITextureBilinear(texture2d tex, - float2 uv) { - uint w = tex.get_width(); - uint h = tex.get_height(); - if (w == 0u || h == 0u) { - return float4(0.0f); - } - - float2 pixel = uv * float2((float)w, (float)h) - 0.5f; - int2 p0 = int2(floor(pixel)); - int2 p1 = p0 + int2(1, 0); - int2 p2 = p0 + int2(0, 1); - int2 p3 = p0 + int2(1, 1); - - int maxX = int(w) - 1; - int maxY = int(h) - 1; - p0 = int2(clamp(p0.x, 0, maxX), clamp(p0.y, 0, maxY)); - p1 = int2(clamp(p1.x, 0, maxX), clamp(p1.y, 0, maxY)); - p2 = int2(clamp(p2.x, 0, maxX), clamp(p2.y, 0, maxY)); - p3 = int2(clamp(p3.x, 0, maxX), clamp(p3.y, 0, maxY)); - - float2 f = fract(pixel); - float4 c00 = tex.read(uint2((uint)p0.x, (uint)p0.y)); - float4 c10 = tex.read(uint2((uint)p1.x, (uint)p1.y)); - float4 c01 = tex.read(uint2((uint)p2.x, (uint)p2.y)); - float4 c11 = tex.read(uint2((uint)p3.x, (uint)p3.y)); - float4 cx0 = mix(c00, c10, f.x); - float4 cx1 = mix(c01, c11, f.x); - return mix(cx0, cx1, f.y); -} - -static inline float4 -sampleProbeDirectionalRadiance(texture2d ddgiTexture, - constant ProbeSpace &ps, uint probeIndex, - uint atlasW, uint atlasH, float3 dirWS) { - float2 uv = ddgiAtlasUV(probeIndex, dirWS, ps, atlasW, atlasH); - return sampleDDGITextureBilinear(ddgiTexture, uv); -} - -static inline float3 sampleDDGIIrradiance(texture2d ddgiTexture, - texture2d ddgiDistance, - constant ProbeSpace &ps, float3 posWS, - float3 normalWS) { - uint3 counts = uint3((uint)ps.probeCount.x, (uint)ps.probeCount.y, - (uint)ps.probeCount.z); - - if (counts.x == 0u || counts.y == 0u || counts.z == 0u) - return float3(0.0); - - uint atlasW = ddgiTexture.get_width(); - uint atlasH = ddgiTexture.get_height(); - if (atlasW == 0u || atlasH == 0u) { - return float3(0.0); - } - - float normalLen = length(normalWS); - float3 safeNormal = (normalLen > 1e-6f) ? (normalWS / float3(normalLen)) - : float3(0.0f, 1.0f, 0.0f); - - float3 safeSpacing = max(ps.spacing, float3(1e-4f)); - float spacingScale = - max(max(safeSpacing.x, max(safeSpacing.y, safeSpacing.z)), 1e-4f); - float3 grid = (posWS - ps.origin) / safeSpacing; - - if (counts.x < 2u || counts.y < 2u || counts.z < 2u) { - float3 maxCoord = max(float3(0.0f), float3((float)counts.x - 1.0f, - (float)counts.y - 1.0f, - (float)counts.z - 1.0f)); - float3 clampedGrid = clamp(grid, float3(0.0f), maxCoord); - uint3 nearest = uint3( - (uint)clamp(int(floor(clampedGrid.x + 0.5f)), 0, int(counts.x) - 1), - (uint)clamp(int(floor(clampedGrid.y + 0.5f)), 0, int(counts.y) - 1), - (uint)clamp(int(floor(clampedGrid.z + 0.5f)), 0, - int(counts.z) - 1)); - uint pIndex = probeIndexFromCoord(nearest, counts); - float4 nearestSample = sampleProbeDirectionalRadiance( - ddgiTexture, ps, pIndex, atlasW, atlasH, safeNormal); - float3 nearestProbePos = ps.origin + float3(nearest) * safeSpacing; - float3 nearestDirection = safeNormalizeDDGI( - posWS - nearestProbePos, safeNormal); - float4 nearestMoments = sampleProbeDirectionalRadiance( - ddgiDistance, ps, pIndex, atlasW, atlasH, nearestDirection); - float nearestDistance = length(posWS - nearestProbePos); - float nearestVariance = max(nearestMoments.y - nearestMoments.x * - nearestMoments.x, - 0.0001f); - float nearestDelta = max(nearestDistance - nearestMoments.x, 0.0f); - float nearestVisibility = nearestDelta <= 0.0f - ? 1.0f - : nearestVariance / - (nearestVariance + nearestDelta * - nearestDelta); - float nearestValidity = isfinite(nearestSample.w) - ? clamp(nearestSample.w, 0.0f, 1.0f) - : 0.0f; - float3 nearestIrr = - all(isfinite(nearestSample.xyz)) ? nearestSample.xyz : float3(0.0f); - nearestIrr *= nearestValidity * nearestVisibility; - return max(nearestIrr, float3(0.0f)); - } - - float3 maxGrid = - float3((float)counts.x - 1.0001f, (float)counts.y - 1.0001f, - (float)counts.z - 1.0001f); - float3 clampedGrid = clamp(grid, float3(0.0f), maxGrid); - - float3 baseF = floor(clampedGrid); - float3 frac = clampedGrid - baseF; - int3 baseI = int3(baseF); - int3 maxBase = - int3(int(counts.x) - 2, int(counts.y) - 2, int(counts.z) - 2); - baseI = clamp(baseI, int3(0), maxBase); - - float3 result = float3(0.0f); - float weightSum = 0.0f; - float3 resultNoBackface = float3(0.0f); - float weightSumNoBackface = 0.0f; - - for (uint dz = 0; dz <= 1u; dz++) { - for (uint dy = 0; dy <= 1u; dy++) { - for (uint dx = 0; dx <= 1u; dx++) { - - uint3 pc = uint3(uint(baseI.x) + dx, uint(baseI.y) + dy, - uint(baseI.z) + dz); - uint pIndex = probeIndexFromCoord(pc, counts); - - float trilinearW = ((dx == 0u) ? (1.0f - frac.x) : frac.x) * - ((dy == 0u) ? (1.0f - frac.y) : frac.y) * - ((dz == 0u) ? (1.0f - frac.z) : frac.z); - - float3 probePos = ps.origin + float3(pc) * safeSpacing; - float3 surfaceToProbe = probePos - posWS; - float sDist = length(surfaceToProbe); - float3 dirToProbe = (sDist > 1e-4f) ? surfaceToProbe / sDist - : float3(0.0f, 1.0f, 0.0f); - float frontW = max(dot(safeNormal, dirToProbe), 0.0f); - float backfaceW = - mix(0.180000007152557373046875, 1.0f, frontW * frontW); - float distNorm = sDist / spacingScale; - float distNorm2 = distNorm * distNorm; - float distanceW = - 1.0f / (1.0f + distNorm2 * 0.85000002384185791015625); - - float w = trilinearW * backfaceW * distanceW; - - float4 irrSample = sampleProbeDirectionalRadiance( - ddgiTexture, ps, pIndex, atlasW, atlasH, safeNormal); - float3 probeToSurface = -surfaceToProbe; - float4 distanceSample = sampleProbeDirectionalRadiance( - ddgiDistance, ps, pIndex, atlasW, atlasH, - safeNormalizeDDGI(probeToSurface, safeNormal)); - float variance = max(distanceSample.y - - distanceSample.x * distanceSample.x, - 0.0001f); - float delta = max(sDist - distanceSample.x, 0.0f); - float visibility = delta <= 0.0f - ? 1.0f - : variance / (variance + delta * delta); - visibility = visibility * visibility * visibility; - float probeValidity = isfinite(irrSample.w) - ? clamp(irrSample.w, 0.0f, 1.0f) - : 0.0f; - float validityW = probeValidity; - float3 irr = irrSample.xyz; - if (!all(isfinite(irr))) { - irr = float3(0.0f); - validityW = 0.0f; - } - irr = max(irr, float3(0.0f)); - float weightedW = w * validityW * max(visibility, 0.001f); - result += irr * weightedW; - weightSum += weightedW; - float noBackfaceW = trilinearW * distanceW * validityW * - max(visibility, 0.001f); - resultNoBackface += irr * noBackfaceW; - weightSumNoBackface += noBackfaceW; - } - } - } - - if (weightSum > 1e-5f) { - return result / weightSum; - } - if (weightSumNoBackface > 1e-5f) { - return resultNoBackface / weightSumNoBackface; - } - - uint3 nearest = uint3( - (uint)clamp(int(floor(clampedGrid.x + 0.5f)), 0, int(counts.x) - 1), - (uint)clamp(int(floor(clampedGrid.y + 0.5f)), 0, int(counts.y) - 1), - (uint)clamp(int(floor(clampedGrid.z + 0.5f)), 0, int(counts.z) - 1)); - uint nearestIndex = probeIndexFromCoord(nearest, counts); - float4 fallbackSample = sampleProbeDirectionalRadiance( - ddgiTexture, ps, nearestIndex, atlasW, atlasH, safeNormal); - float fallbackValidity = - isfinite(fallbackSample.w) ? clamp(fallbackSample.w, 0.0f, 1.0f) : 0.0f; - float3 fallback = - all(isfinite(fallbackSample.xyz)) ? fallbackSample.xyz : float3(0.0f); - fallback *= fallbackValidity; - if (!all(isfinite(fallback))) { - fallback = float3(0.0f); - } - return max(fallback, float3(0.0f)); -} - -fragment main0_out main0( - main0_in in [[stage_in]], constant UBO &_526 [[buffer(0)]], - constant Environment &environment [[buffer(1)]], - constant PushConstants &_1355 [[buffer(2)]], - device ShadowParams &_1372 [[buffer(3)]], - device DirectionalLights &_1422 [[buffer(4)]], - device PointLights &_1465 [[buffer(5)]], - device SpotLights &_1510 [[buffer(6)]], - device AreaLights &_1552 [[buffer(7)]], - constant AmbientLight &ambientLight [[buffer(8)]], - constant ProbeSpace &ps [[buffer(9)]], - texture2d texture1 [[texture(0)]], - texture2d texture2 [[texture(1)]], - texture2d texture3 [[texture(2)]], - texture2d texture4 [[texture(3)]], - texture2d texture5 [[texture(4)]], - texturecube cubeMap1 [[texture(5)]], - texturecube cubeMap2 [[texture(6)]], - texturecube cubeMap3 [[texture(7)]], - texturecube cubeMap4 [[texture(8)]], - texturecube cubeMap5 [[texture(9)]], - texturecube skybox [[texture(10)]], - texture2d gPosition [[texture(11)]], - texture2d gNormal [[texture(12)]], - texture2d gAlbedoSpec [[texture(13)]], - texture2d gMaterial [[texture(14)]], - texture2d ssao [[texture(15)]], - texture2d irradianceMap [[texture(16)]], - texture2d ddgiDistanceMap [[texture(17)]], - sampler texture1Smplr [[sampler(0)]], sampler texture2Smplr [[sampler(1)]], - sampler texture3Smplr [[sampler(2)]], sampler texture4Smplr [[sampler(3)]], - sampler texture5Smplr [[sampler(4)]], sampler cubeMap1Smplr [[sampler(5)]], - sampler cubeMap2Smplr [[sampler(6)]], sampler cubeMap3Smplr [[sampler(7)]], - sampler cubeMap4Smplr [[sampler(8)]], sampler cubeMap5Smplr [[sampler(9)]], - sampler skyboxSmplr [[sampler(10)]], sampler gPositionSmplr [[sampler(11)]], - sampler gNormalSmplr [[sampler(12)]], - sampler gAlbedoSpecSmplr [[sampler(13)]], - sampler gMaterialSmplr [[sampler(14)]], sampler ssaoSmplr [[sampler(15)]]) { - main0_out out{}; - float4 gPositionSample = gPosition.sample(gPositionSmplr, in.TexCoord); - float3 FragPos = gPositionSample.xyz; - if (!all(isfinite(FragPos))) { - FragPos = float3(0.0); - } - float depthSample = gPositionSample.w; - float3 sampledNormal = gNormal.sample(gNormalSmplr, in.TexCoord).xyz; - float normalLength = length(sampledNormal); - bool hasNormal = all(isfinite(sampledNormal)) && - normalLength > 9.9999997473787516355514526367188e-06; - bool hasDepth = - isfinite(depthSample) && depthSample < 0.999989986419677734375; - bool hasGeometry = hasNormal || hasDepth; - if (!hasGeometry) { - float2 ndc = in.TexCoord * 2.0f - 1.0f; - float3 backgroundDir = fast::normalize(float3(ndc.x, -ndc.y, 1.0f)); - float3 backgroundColor = - sampleEnvironmentRadiance(backgroundDir, skybox, skyboxSmplr); - out.FragColor = float4(acesToneMapping(backgroundColor), 1.0); - out.BrightColor = float4(0.0, 0.0, 0.0, 1.0); - return out; - } - float3 N = float3(0.0, 1.0, 0.0); - if (hasNormal) { - N = sampledNormal / float3(normalLength); - } else { - float3 geomN = cross(dfdx(FragPos), dfdy(FragPos)); - float geomNLen = length(geomN); - if (all(isfinite(geomN)) && - geomNLen > 9.9999997473787516355514526367188e-06) { - N = geomN / float3(geomNLen); - } - } - float3 geomNormal = cross(dfdx(FragPos), dfdy(FragPos)); - float geomNormalLen = length(geomNormal); - bool hasGeomNormal = all(isfinite(geomNormal)) && - geomNormalLen > 9.9999997473787516355514526367188e-06; - float3 shadowNormal = N; - float3 ddgiNormal = N; - if (hasGeomNormal) { - geomNormal /= float3(geomNormalLen); - if (dot(N, geomNormal) < 0.0) { - geomNormal = -geomNormal; - } - shadowNormal = geomNormal; - ddgiNormal = geomNormal; - } - float4 albedoAo = gAlbedoSpec.sample(gAlbedoSpecSmplr, in.TexCoord); - float3 albedo = fast::clamp(albedoAo.xyz, float3(0.0), float3(1.0)); - if (!all(isfinite(albedo))) { - albedo = float3(0.0); - } - float4 matData = gMaterial.sample(gMaterialSmplr, in.TexCoord); - float metallic = fast::clamp(matData.x, 0.0, 1.0); - float roughness = fast::clamp(matData.y, 0.0, 1.0); - float ao = fast::clamp(matData.z, 0.0, 1.0); - - float viewDistance = - fast::max(length(float3(_526.cameraPosition) - FragPos), - 9.9999999747524270787835121154785e-07); - float3 V = (float3(_526.cameraPosition) - FragPos) / float3(viewDistance); - float3 F0 = - mix(float3(0.039999999105930328369140625), albedo, float3(metallic)); - float ssaoFactor = - fast::clamp(ssao.sample(ssaoSmplr, in.TexCoord).x, 0.0, 1.0); - - float ssaoContrast = - fast::clamp(powr(ssaoFactor, 1.10000002384185791015625), 0.0, 1.0); - float occlusion = - fast::clamp(ao * (0.0500000007450580596923828125 + - (0.949999988079071044921875 * ssaoContrast)), - 0.0, 1.0); - float lightingOcclusion = - fast::clamp(0.0500000007450580596923828125 + - (0.949999988079071044921875 * ssaoContrast), - 0.0500000007450580596923828125, 1.0); - float directionalShadow = 0.0; - float spotShadow = 0.0; - float areaShadow = 0.0; - int areaShadowCount = 0; - float pointShadow = 0.0; - int shadowCount = _1355.shadowParamCount; - for (int i = 0; i < shadowCount; i++) { - if (_1372.shadowParams[i].lightType == 3) { - int lightIndex = _1372.shadowParams[i].lightIndex; - if (lightIndex < 0 || lightIndex >= _1355.pointLightCount || - distance(float3(_1465.pointLights[lightIndex].position), - FragPos) >= _1465.pointLights[lightIndex].radius) { - continue; - } - ShadowParameters _1386; - _1386.lightView = _1372.shadowParams[i].lightView; - _1386.lightProjection = _1372.shadowParams[i].lightProjection; - _1386.bias0 = _1372.shadowParams[i].bias0; - _1386.textureIndex = _1372.shadowParams[i].textureIndex; - _1386.farPlane = _1372.shadowParams[i].farPlane; - _1386.lightIndex = _1372.shadowParams[i].lightIndex; - _1386.lightPos = float3(_1372.shadowParams[i].lightPos); - _1386.lightType = _1372.shadowParams[i].lightType; - ShadowParameters param = _1386; - float3 param_1 = FragPos; - pointShadow = - fast::max(pointShadow, - calculatePointShadow( - param, param_1, texture1, texture1Smplr, texture2, - texture2Smplr, texture3, texture3Smplr, texture4, - texture4Smplr, texture5, texture5Smplr, cubeMap1, - cubeMap1Smplr, cubeMap2, cubeMap2Smplr, cubeMap3, - cubeMap3Smplr, cubeMap4, cubeMap4Smplr, cubeMap5, - cubeMap5Smplr)); - } else if (_1372.shadowParams[i].lightType == 1) { - int lightIndex = _1372.shadowParams[i].lightIndex; - if (lightIndex < 0 || lightIndex >= _1355.spotlightCount || - distance(float3(_1510.spotlights[lightIndex].position), - FragPos) >= _1510.spotlights[lightIndex].range) { - continue; - } - ShadowParameters _1397; - _1397.lightView = _1372.shadowParams[i].lightView; - _1397.lightProjection = _1372.shadowParams[i].lightProjection; - _1397.bias0 = _1372.shadowParams[i].bias0; - _1397.textureIndex = _1372.shadowParams[i].textureIndex; - _1397.farPlane = _1372.shadowParams[i].farPlane; - _1397.lightIndex = _1372.shadowParams[i].lightIndex; - _1397.lightPos = float3(_1372.shadowParams[i].lightPos); - _1397.lightType = _1372.shadowParams[i].lightType; - ShadowParameters param_2 = _1397; - float3 param_3 = FragPos; - float3 param_4 = shadowNormal; - spotShadow = fast::max( - spotShadow, - calculateShadow(param_2, param_3, param_4, texture1, - texture1Smplr, texture2, texture2Smplr, - texture3, texture3Smplr, texture4, - texture4Smplr, texture5, texture5Smplr, _526)); - } else if (_1372.shadowParams[i].lightType == 2) { - int lightIndex = _1372.shadowParams[i].lightIndex; - if (lightIndex < 0 || lightIndex >= _1355.areaLightCount || - distance(float3(_1552.areaLights[lightIndex].position), - FragPos) >= _1552.areaLights[lightIndex].range) { - continue; - } - ShadowParameters _1397; - _1397.lightView = _1372.shadowParams[i].lightView; - _1397.lightProjection = _1372.shadowParams[i].lightProjection; - _1397.bias0 = _1372.shadowParams[i].bias0; - _1397.textureIndex = _1372.shadowParams[i].textureIndex; - _1397.farPlane = _1372.shadowParams[i].farPlane; - _1397.lightIndex = _1372.shadowParams[i].lightIndex; - _1397.lightPos = float3(_1372.shadowParams[i].lightPos); - _1397.lightType = _1372.shadowParams[i].lightType; - ShadowParameters param_2 = _1397; - float3 param_3 = FragPos; - float3 param_4 = shadowNormal; - areaShadow += calculateShadow( - param_2, param_3, param_4, texture1, texture1Smplr, texture2, - texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, - texture5, texture5Smplr, _526); - areaShadowCount++; - } else { - ShadowParameters _1397; - _1397.lightView = _1372.shadowParams[i].lightView; - _1397.lightProjection = _1372.shadowParams[i].lightProjection; - _1397.bias0 = _1372.shadowParams[i].bias0; - _1397.textureIndex = _1372.shadowParams[i].textureIndex; - _1397.farPlane = _1372.shadowParams[i].farPlane; - _1397.lightIndex = _1372.shadowParams[i].lightIndex; - _1397.lightPos = float3(_1372.shadowParams[i].lightPos); - _1397.lightType = _1372.shadowParams[i].lightType; - ShadowParameters param_2 = _1397; - float3 param_3 = FragPos; - float3 param_4 = shadowNormal; - directionalShadow = fast::max( - directionalShadow, - calculateShadow(param_2, param_3, param_4, texture1, - texture1Smplr, texture2, texture2Smplr, - texture3, texture3Smplr, texture4, - texture4Smplr, texture5, texture5Smplr, _526)); - } - } - if (areaShadowCount > 0) { - areaShadow /= float(areaShadowCount); - } - directionalShadow = - fast::clamp(directionalShadow * 0.85000002384185791015625, 0.0, 1.0); - spotShadow = fast::clamp(spotShadow * 0.85000002384185791015625, 0.0, 1.0); - areaShadow = fast::clamp(areaShadow * 0.449999988079071044921875, 0.0, 1.0); - pointShadow = - fast::clamp(pointShadow * 0.85000002384185791015625, 0.0, 1.0); - float3 directionalResult = float3(0.0); - for (int i_1 = 0; i_1 < _1355.directionalLightCount; i_1++) { - DirectionalLight _1428; - _1428.direction = float3(_1422.directionalLights[i_1].direction); - _1428._pad1 = _1422.directionalLights[i_1]._pad1; - _1428.diffuse = float3(_1422.directionalLights[i_1].diffuse); - _1428._pad2 = _1422.directionalLights[i_1]._pad2; - _1428.specular = float3(_1422.directionalLights[i_1].specular); - _1428.intensity = _1422.directionalLights[i_1].intensity; - DirectionalLight param_5 = _1428; - float3 param_6 = N; - float3 param_7 = V; - float3 param_8 = F0; - float3 param_9 = albedo; - float param_10 = metallic; - float param_11 = roughness; - directionalResult += calcDirectionalLight( - param_5, param_6, param_7, param_8, param_9, param_10, param_11); - } - directionalResult *= (1.0 - directionalShadow); - float3 pointResult = float3(0.0); - for (int i_2 = 0; i_2 < _1355.pointLightCount; i_2++) { - PointLight _1471; - _1471.position = float3(_1465.pointLights[i_2].position); - _1471._pad1 = _1465.pointLights[i_2]._pad1; - _1471.diffuse = float3(_1465.pointLights[i_2].diffuse); - _1471._pad2 = _1465.pointLights[i_2]._pad2; - _1471.specular = float3(_1465.pointLights[i_2].specular); - _1471.intensity = _1465.pointLights[i_2].intensity; - _1471.constant0 = _1465.pointLights[i_2].constant0; - _1471.linear = _1465.pointLights[i_2].linear; - _1471.quadratic = _1465.pointLights[i_2].quadratic; - _1471.radius = _1465.pointLights[i_2].radius; - _1471._pad3 = _1465.pointLights[i_2]._pad3; - PointLight param_12 = _1471; - float3 param_13 = FragPos; - float3 param_14 = N; - float3 param_15 = V; - float3 param_16 = F0; - float3 param_17 = albedo; - float param_18 = metallic; - float param_19 = roughness; - pointResult += calcPointLight(param_12, param_13, param_14, param_15, - param_16, param_17, param_18, param_19); - } - pointResult *= (1.0 - pointShadow); - float3 spotResult = float3(0.0); - for (int i_3 = 0; i_3 < _1355.spotlightCount; i_3++) { - SpotLight _1516; - _1516.position = float3(_1510.spotlights[i_3].position); - _1516._pad1 = _1510.spotlights[i_3]._pad1; - _1516.direction = float3(_1510.spotlights[i_3].direction); - _1516.cutOff = _1510.spotlights[i_3].cutOff; - _1516.outerCutOff = _1510.spotlights[i_3].outerCutOff; - _1516.intensity = _1510.spotlights[i_3].intensity; - _1516.range = _1510.spotlights[i_3].range; - _1516._pad4 = _1510.spotlights[i_3]._pad4; - _1516.diffuse = float3(_1510.spotlights[i_3].diffuse); - _1516._pad5 = _1510.spotlights[i_3]._pad5; - _1516.specular = float3(_1510.spotlights[i_3].specular); - _1516._pad6 = _1510.spotlights[i_3]._pad6; - SpotLight param_20 = _1516; - float3 param_21 = FragPos; - float3 param_22 = N; - float3 param_23 = V; - float3 param_24 = F0; - float3 param_25 = albedo; - float param_26 = metallic; - float param_27 = roughness; - spotResult += calcSpotLight(param_20, param_21, param_22, param_23, - param_24, param_25, param_26, param_27); - } - spotResult *= (1.0 - spotShadow); - float3 areaResult = float3(0.0); - float _1639; - for (int i_4 = 0; i_4 < _1355.areaLightCount; i_4++) { - float3 P = float3(_1552.areaLights[i_4].position); - float3 R = fast::normalize(float3(_1552.areaLights[i_4].right)); - float3 U = fast::normalize(float3(_1552.areaLights[i_4].up)); - float2 halfSize = _1552.areaLights[i_4].size * 0.5; - float3 toPoint = FragPos - P; - float s = fast::clamp(dot(toPoint, R), -halfSize.x, halfSize.x); - float t = fast::clamp(dot(toPoint, U), -halfSize.y, halfSize.y); - float3 Q = (P + (R * s)) + (U * t); - float3 Lvec = Q - FragPos; - float dist = length(Lvec); - if (dist > 9.9999997473787516355514526367188e-05) { - float3 L = Lvec / float3(dist); - float3 Nl = fast::normalize(cross(R, U)); - float ndotl = dot(Nl, -L); - if (_1552.areaLights[i_4].castsBothSides != 0) { - _1639 = abs(ndotl); - } else { - _1639 = fast::max(ndotl, 0.0); - } - float facing = _1639; - float cosTheta = cos(radians(_1552.areaLights[i_4].angle)); - if ((facing >= cosTheta) && (facing > 0.0)) { - float range = fast::max(_1552.areaLights[i_4].range, - 0.001000000047497451305389404296875); - float attenuation = 1.0 / ((1.0 + (dist / range)) + - ((dist * dist) / (range * range))); - float fade = 1.0 - smoothstep(range * 0.89999997615814208984375, - range, dist); - float3 radiance = - (((float3(_1552.areaLights[i_4].diffuse) * - fast::max(_1552.areaLights[i_4].intensity, 0.0)) * - attenuation) * - facing) * - fade; - float3 param_28 = L; - float3 param_29 = radiance; - float3 param_30 = N; - float3 param_31 = V; - float3 param_32 = F0; - float3 param_33 = albedo; - float param_34 = metallic; - float param_35 = roughness; - areaResult += - evaluateBRDF(param_28, param_29, param_30, param_31, - param_32, param_33, param_34, param_35); - } - } - } - areaResult *= (1.0 - areaShadow); - float3 param_36 = FragPos; - float3 param_37 = N; - float3 param_38 = V; - float3 param_39 = F0; - float3 param_40 = albedo; - float param_41 = metallic; - float param_42 = roughness; - float3 _1714 = getRimLight(param_36, param_37, param_38, param_39, param_40, - param_41, param_42, _526, environment); - float3 rimResult = _1714; - float3 lighting = - ((((directionalResult + pointResult) + spotResult) + areaResult) + - rimResult) * - lightingOcclusion; - float3 ambientBase = - ((ambientLight.color.xyz * ambientLight.intensity) * albedo) * - occlusion; - bool ddgiEnabled = ps.atlasParams.w > 0.0f; - float3 ambient = ddgiEnabled ? ambientBase * 0.05f : ambientBase; - - float ddgiSampleBias = - max(max(ps.spacing.x, max(ps.spacing.y, ps.spacing.z)) * 0.05f, 0.002f); - float3 ddgiSamplePos = FragPos + ddgiNormal * ddgiSampleBias; - float3 ddgiIrradiance = - sampleDDGIIrradiance(irradianceMap, ddgiDistanceMap, ps, ddgiSamplePos, - ddgiNormal); - if (!all(isfinite(ddgiIrradiance))) { - ddgiIrradiance = float3(0.0f); - } - ddgiIrradiance = max(ddgiIrradiance, float3(0.0f)); - - float ddgiDebugMode = ps.debugColor.w; - float3 ddgiGain = max(ps.debugColor.xyz, float3(0.0f)); - if (ddgiGain.x < 1e-4f && ddgiGain.y < 1e-4f && ddgiGain.z < 1e-4f) { - ddgiGain = float3(1.0f); - } - - const float INV_PI = 0.31830988618379067153776752674503; - float3 ddgiDiffuse = ddgiIrradiance * albedo * INV_PI * - (1.0f - metallic) * occlusion * ddgiGain; - ambient += ddgiDiffuse; - - float3 ddgiSpecular = float3(0.0f); - - float3 iblContribution = float3(0.0); - if (_526.useIBL != 0u) { - float3 param_43 = N; - float3 irradiance = - sampleEnvironmentRadiance(param_43, skybox, skyboxSmplr); - float3 diffuseIBL = irradiance * albedo; - float3 reflection = reflect(-V, N); - float3 param_44 = reflection; - float3 specularEnv = - sampleEnvironmentRadiance(param_44, skybox, skyboxSmplr); - float param_45 = fast::max(dot(N, V), 0.0); - float3 param_46 = F0; - float3 F = fresnelSchlick(param_45, param_46); - float3 kS = F; - float3 kD = (float3(1.0) - kS) * (1.0 - metallic); - float roughnessAttenuation = mix(1.0, 0.1500000059604644775390625, - fast::clamp(roughness, 0.0, 1.0)); - float3 specularIBL = specularEnv * roughnessAttenuation; - iblContribution = ((kD * diffuseIBL) + (kS * specularIBL)) * occlusion; - } - float3 finalColor = (ambient + lighting + ddgiSpecular) + iblContribution; - - // Debug AO view mode: - // ps.debugColor.w >= 9.5f -> visualize SSAO directly in grayscale. - if (ddgiDebugMode >= 9.5f && ddgiDebugMode < 19.5f) { - finalColor = float3(ssaoFactor); - } else if (ddgiDebugMode >= 39.5f) { - finalColor = - max(ddgiDiffuse * 3.0f + ddgiSpecular * 2.0f, float3(0.0f)); - } else if (ddgiDebugMode >= 29.5f) { - finalColor = ddgiIrradiance * ddgiGain * 4.0f; - } else if (ddgiDebugMode >= 19.5f) { - finalColor = ddgiDiffuse * 3.0f; - } else if (!(_526.useIBL != 0u)) { - float3 I = fast::normalize(FragPos - float3(_526.cameraPosition)); - float3 R_1 = reflect(-I, N); - float param_47 = fast::max(dot(N, -I), 0.0); - float3 param_48 = F0; - float3 F_1 = fresnelSchlick(param_47, param_48); - float3 kS_1 = F_1; - float3 envColor = skybox.sample(skyboxSmplr, R_1).xyz; - float3 reflection_1 = envColor * kS_1; - float3 envMix = F0 * (1.0f - roughness) * 0.20f; - finalColor = mix(finalColor, reflection_1, envMix); - } - out.FragColor = float4(finalColor, 1.0); - float brightness = - dot(out.FragColor.xyz, - float3(0.2125999927520751953125, 0.715200006961822509765625, - 0.072200000286102294921875)); - if (brightness > environment.bloomThreshold) { - out.BrightColor = float4(out.FragColor.xyz, 1.0); - } else { - out.BrightColor = float4(0.0, 0.0, 0.0, 1.0); - } - float3 param_49 = out.FragColor.xyz; - float3 _1897 = acesToneMapping(param_49); - out.FragColor.x = _1897.x; - out.FragColor.y = _1897.y; - out.FragColor.z = _1897.z; - return out; -} diff --git a/shaders/metal/deferred/light.vert.metal b/shaders/metal/deferred/light.vert.metal deleted file mode 100644 index de3e3fa2..00000000 --- a/shaders/metal/deferred/light.vert.metal +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include - -using namespace metal; - -struct main0_out -{ - float2 TexCoord [[user(locn0)]]; - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; - float2 aTexCoord [[attribute(2)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]]) -{ - main0_out out = {}; - out.TexCoord = in.aTexCoord; - out.gl_Position = float4(in.aPos, 1.0); - return out; -} diff --git a/shaders/metal/effects/downsample.frag.metal b/shaders/metal/effects/downsample.frag.metal deleted file mode 100644 index cea71ad6..00000000 --- a/shaders/metal/effects/downsample.frag.metal +++ /dev/null @@ -1,48 +0,0 @@ -#include -#include - -using namespace metal; - -struct Params -{ - float2 srcResolution; -}; - -struct main0_out -{ - float4 downsample [[color(0)]]; -}; - -struct main0_in -{ - float2 TexCoord [[user(locn0)]]; -}; - -fragment main0_out main0(main0_in in [[stage_in]], constant Params& _13 [[buffer(0)]], texture2d srcTexture [[texture(0)]], sampler srcTextureSmplr [[sampler(0)]]) -{ - main0_out out = {}; - float2 srcTexelSize = - float2(1.0) / float2(srcTexture.get_width(), srcTexture.get_height()); - float x = srcTexelSize.x; - float y = srcTexelSize.y; - float2 texCoord = in.TexCoord; - float3 a = srcTexture.sample(srcTextureSmplr, float2(texCoord.x - (2.0 * x), texCoord.y + (2.0 * y))).xyz; - float3 b = srcTexture.sample(srcTextureSmplr, float2(texCoord.x, texCoord.y + (2.0 * y))).xyz; - float3 c = srcTexture.sample(srcTextureSmplr, float2(texCoord.x + (2.0 * x), texCoord.y + (2.0 * y))).xyz; - float3 d = srcTexture.sample(srcTextureSmplr, float2(texCoord.x - (2.0 * x), texCoord.y)).xyz; - float3 e = srcTexture.sample(srcTextureSmplr, float2(texCoord.x, texCoord.y)).xyz; - float3 f = srcTexture.sample(srcTextureSmplr, float2(texCoord.x + (2.0 * x), texCoord.y)).xyz; - float3 g = srcTexture.sample(srcTextureSmplr, float2(texCoord.x - (2.0 * x), texCoord.y - (2.0 * y))).xyz; - float3 h = srcTexture.sample(srcTextureSmplr, float2(texCoord.x, texCoord.y - (2.0 * y))).xyz; - float3 i = srcTexture.sample(srcTextureSmplr, float2(texCoord.x + (2.0 * x), texCoord.y - (2.0 * y))).xyz; - float3 j = srcTexture.sample(srcTextureSmplr, float2(texCoord.x - x, texCoord.y + y)).xyz; - float3 k = srcTexture.sample(srcTextureSmplr, float2(texCoord.x + x, texCoord.y + y)).xyz; - float3 l = srcTexture.sample(srcTextureSmplr, float2(texCoord.x - x, texCoord.y - y)).xyz; - float3 m = srcTexture.sample(srcTextureSmplr, float2(texCoord.x + x, texCoord.y - y)).xyz; - float3 downsampleColor = e * 0.125; - downsampleColor += ((((a + c) + g) + i) * 0.03125); - downsampleColor += ((((b + d) + f) + h) * 0.0625); - downsampleColor += ((((j + k) + l) + m) * 0.125); - out.downsample = float4(downsampleColor, 1.0); - return out; -} diff --git a/shaders/metal/effects/gaussian.frag.metal b/shaders/metal/effects/gaussian.frag.metal deleted file mode 100644 index 368fd502..00000000 --- a/shaders/metal/effects/gaussian.frag.metal +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include - -using namespace metal; - -struct Params -{ - uint horizontal; - float4 weight[5]; - float radius; -}; - -struct main0_out -{ - float4 FragColor [[color(0)]]; -}; - -struct main0_in -{ - float2 TexCoord [[user(locn0)]]; -}; - -fragment main0_out main0(main0_in in [[stage_in]], constant Params& _29 [[buffer(0)]], texture2d image [[texture(0)]], sampler imageSmplr [[sampler(0)]]) -{ - main0_out out = {}; - float2 tex_offset = (float2(1.0) / float2(int2(image.get_width(), image.get_height()))) * _29.radius; - float3 result = image.sample(imageSmplr, in.TexCoord).xyz * _29.weight[0].x; - if (_29.horizontal != 0u) - { - for (int i = 1; i < 5; i++) - { - result += (image.sample(imageSmplr, (in.TexCoord + float2(tex_offset.x * float(i), 0.0))).xyz * _29.weight[i].x); - result += (image.sample(imageSmplr, (in.TexCoord - float2(tex_offset.x * float(i), 0.0))).xyz * _29.weight[i].x); - } - } - else - { - for (int i_1 = 1; i_1 < 5; i_1++) - { - result += (image.sample(imageSmplr, (in.TexCoord + float2(0.0, tex_offset.y * float(i_1)))).xyz * _29.weight[i_1].x); - result += (image.sample(imageSmplr, (in.TexCoord - float2(0.0, tex_offset.y * float(i_1)))).xyz * _29.weight[i_1].x); - } - } - out.FragColor = float4(result, 1.0); - return out; -} - diff --git a/shaders/metal/effects/particle.frag.metal b/shaders/metal/effects/particle.frag.metal deleted file mode 100644 index 628ea288..00000000 --- a/shaders/metal/effects/particle.frag.metal +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include - -using namespace metal; - -struct Params -{ - uint useTexture; -}; - -struct main0_out -{ - float4 FragColor [[color(0)]]; -}; - -struct main0_in -{ - float2 fragTexCoord [[user(locn0)]]; - float4 fragColor [[user(locn1)]]; -}; - -fragment main0_out main0(main0_in in [[stage_in]], constant Params& _9 [[buffer(0)]], texture2d particleTexture [[texture(0)]], sampler particleTextureSmplr [[sampler(0)]]) -{ - main0_out out = {}; - if (_9.useTexture != 0u) - { - float4 texColor = particleTexture.sample(particleTextureSmplr, in.fragTexCoord); - if (texColor.w < 0.00999999977648258209228515625) - { - discard_fragment(); - } - out.FragColor = texColor * in.fragColor; - } - else - { - float2 center = float2(0.5); - float dist = distance(in.fragTexCoord, center); - float alpha = 1.0 - smoothstep(0.300000011920928955078125, 0.5, dist); - out.FragColor = float4(in.fragColor.xyz, in.fragColor.w * alpha); - if (out.FragColor.w < 0.00999999977648258209228515625) - { - discard_fragment(); - } - } - return out; -} - diff --git a/shaders/metal/effects/particle.vert.metal b/shaders/metal/effects/particle.vert.metal deleted file mode 100644 index 959f1c8f..00000000 --- a/shaders/metal/effects/particle.vert.metal +++ /dev/null @@ -1,50 +0,0 @@ -#include -#include - -using namespace metal; - -struct UniformBufferObject -{ - float4x4 view; - float4x4 projection; - float4x4 model; - uint isAmbient; -}; - -struct main0_out -{ - float2 fragTexCoord [[user(locn0)]]; - float4 fragColor [[user(locn1)]]; - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float3 quadVertex [[attribute(0)]]; - float2 texCoord [[attribute(1)]]; - float3 particlePos [[attribute(2)]]; - float4 particleColor [[attribute(3)]]; - float particleSize [[attribute(4)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]], constant UniformBufferObject& _12 [[buffer(0)]]) -{ - main0_out out = {}; - if (_12.isAmbient != 0u) - { - float4 viewParticlePos = _12.view * float4(in.particlePos, 1.0); - float3 viewPosition = viewParticlePos.xyz + float3(in.quadVertex.x * in.particleSize, in.quadVertex.y * in.particleSize, 0.0); - out.gl_Position = (_12.projection * _12.model) * float4(viewPosition, 1.0); - } - else - { - float3 cameraRight = float3(_12.view[0].x, _12.view[1].x, _12.view[2].x); - float3 cameraUp = float3(_12.view[0].y, _12.view[1].y, _12.view[2].y); - float3 worldPosition = (in.particlePos + ((cameraRight * in.quadVertex.x) * in.particleSize)) + ((cameraUp * in.quadVertex.y) * in.particleSize); - out.gl_Position = (_12.projection * _12.view) * float4(worldPosition, 1.0); - } - out.fragTexCoord = in.texCoord; - out.fragColor = in.particleColor; - return out; -} - diff --git a/shaders/metal/effects/skybox.frag.metal b/shaders/metal/effects/skybox.frag.metal deleted file mode 100644 index 3854058e..00000000 --- a/shaders/metal/effects/skybox.frag.metal +++ /dev/null @@ -1,284 +0,0 @@ -#pragma clang diagnostic ignored "-Wmissing-prototypes" - -#include -#include - -using namespace metal; - -struct Params -{ - float3 sunDirection; - float4 sunColor; - float3 moonDirection; - float4 moonColor; - int hasDayNight; -}; - -struct AtmosphereParams -{ - float sunTintStrength; - float moonTintStrength; - float sunSizeMultiplier; - float moonSizeMultiplier; - float starDensity; -}; - -struct main0_out -{ - float4 FragColor [[color(0)]]; -}; - -struct main0_in -{ - float3 TexCoords [[user(locn0)]]; -}; - -static inline __attribute__((always_inline)) -float hash13(thread float3& p) -{ - p = fract(p * 443.897003173828125); - p += float3(dot(p, p.yzx + float3(19.1900005340576171875))); - return fract((p.x + p.y) * p.z); -} - -static inline __attribute__((always_inline)) -float3 generateStars(thread const float3& dir, thread const float& density, thread const float& nightFactor) -{ - if ((density <= 0.0) || (nightFactor <= 0.0)) - { - return float3(0.0); - } - float3 starSpace = dir * 50.0; - float3 cell = floor(starSpace); - float3 localPos = fract(starSpace); - float3 param = cell; - float _165 = hash13(param); - float rand = _165; - if (rand < (density * 0.300000011920928955078125)) - { - float3 param_1 = cell + float3(12.340000152587890625, 56.779998779296875, 90.12000274658203125); - float _181 = hash13(param_1); - float randX = _181; - float3 param_2 = cell + float3(23.450000762939453125, 67.8899993896484375, 1.230000019073486328125); - float _190 = hash13(param_2); - float randY = _190; - float3 param_3 = cell + float3(34.560001373291015625, 78.90000152587890625, 12.340000152587890625); - float _198 = hash13(param_3); - float randZ = _198; - float3 starPos = float3(randX, randY, randZ); - float dist = length(localPos - starPos); - float3 param_4 = cell + float3(45.6699981689453125, 89.01000213623046875, 23.450000762939453125); - float _217 = hash13(param_4); - float starSize = 0.0199999995529651641845703125 + (_217 * 0.02999999932944774627685546875); - float3 param_5 = cell + float3(56.779998779296875, 90.12000274658203125, 34.560001373291015625); - float _227 = hash13(param_5); - float brightness = 0.5 + (_227 * 0.5); - float star = smoothstep(starSize, 0.0, dist) * brightness; - float3 param_6 = cell + float3(67.8899993896484375, 1.230000019073486328125, 45.6699981689453125); - float _243 = hash13(param_6); - float twinkle = 0.800000011920928955078125 + (0.20000000298023223876953125 * sin(_243 * 100.0)); - star *= (twinkle * nightFactor); - float3 starColor = float3(1.0); - if (rand > 0.89999997615814208984375) - { - starColor = float3(0.800000011920928955078125, 0.89999997615814208984375, 1.0); - } - else - { - if (rand > 0.800000011920928955078125) - { - starColor = float3(1.0, 0.89999997615814208984375, 0.800000011920928955078125); - } - } - return starColor * star; - } - return float3(0.0); -} - -static inline __attribute__((always_inline)) -float hash21(thread float2& p) -{ - p = fract(p * float2(123.339996337890625, 456.209991455078125)); - p += float2(dot(p, p + float2(45.31999969482421875))); - return fract(p.x * p.y); -} - -static inline __attribute__((always_inline)) -float valueNoise(thread const float2& p) -{ - float2 i = floor(p); - float2 f = fract(p); - f = (f * f) * (float2(3.0) - (f * 2.0)); - float2 param = i; - float _80 = hash21(param); - float a = _80; - float2 param_1 = i + float2(1.0, 0.0); - float _88 = hash21(param_1); - float b = _88; - float2 param_2 = i + float2(0.0, 1.0); - float _94 = hash21(param_2); - float c = _94; - float2 param_3 = i + float2(1.0); - float _100 = hash21(param_3); - float d = _100; - return mix(mix(a, b, f.x), mix(c, d, f.x), f.y); -} - -static inline __attribute__((always_inline)) -float3 generateMoonTexture(thread float2& uv, thread const float& distanceFromCenter, thread const float3& tintColor) -{ - float angle = 0.5; - float ca = cos(angle); - float sa = sin(angle); - uv = float2((ca * uv.x) - (sa * uv.y), (sa * uv.x) + (ca * uv.y)); - float2 param = uv * 2.0; - float largeFeatures = valueNoise(param); - largeFeatures = smoothstep(0.300000011920928955078125, 0.699999988079071044921875, largeFeatures); - float2 param_1 = uv * 8.0; - float mediumCraters = valueNoise(param_1); - float2 craterUV = uv * 6.0; - float2 craterCell = floor(craterUV); - float2 craterLocal = fract(craterUV); - float craters = 1.0; - for (int i = 0; i < 4; i++) - { - float2 neighbor = float2(float(i % 2), float(i / 2)); - float2 cellPoint = craterCell + neighbor; - float2 param_2 = cellPoint; - float _353 = hash21(param_2); - float2 param_3 = cellPoint + float2(13.69999980926513671875, 27.299999237060546875); - float _360 = hash21(param_3); - float2 craterCenter = float2(_353, _360); - float dist = length((craterLocal - neighbor) - craterCenter); - float2 param_4 = cellPoint + float2(5.30000019073486328125, 9.69999980926513671875); - float _378 = hash21(param_4); - float craterSize = 0.1500000059604644775390625 + (0.25 * _378); - if (dist < craterSize) - { - float crater = smoothstep(craterSize, craterSize * 0.300000011920928955078125, dist); - craters = fast::min(craters, 1.0 - (crater * 0.699999988079071044921875)); - } - } - float surface = (largeFeatures * 0.5) + (mediumCraters * 0.5); - surface *= craters; - float intensity = mix(0.300000011920928955078125, 0.75, surface); - float limb = 1.0 - smoothstep(0.60000002384185791015625, 1.0, distanceFromCenter); - intensity *= (0.4000000059604644775390625 + (0.60000002384185791015625 * limb)); - intensity *= 1.2999999523162841796875; - return fast::clamp(tintColor * intensity, float3(0.0), float3(1.0)); -} - -fragment main0_out main0(main0_in in [[stage_in]], constant Params& _452 [[buffer(0)]], constant AtmosphereParams& _484 [[buffer(1)]], texturecube skybox [[texture(0)]], sampler skyboxSmplr [[sampler(0)]]) -{ - main0_out out = {}; - float3 dir = fast::normalize(in.TexCoords); - float3 color = skybox.sample(skyboxSmplr, in.TexCoords).xyz; - if (_452.hasDayNight == 1) - { - float3 normSunDir = fast::normalize(_452.sunDirection); - float3 normMoonDir = fast::normalize(_452.moonDirection); - float sunDot = dot(dir, normSunDir); - float moonDot = dot(dir, normMoonDir); - float nightFactor = smoothstep(0.1500000059604644775390625, -0.20000000298023223876953125, _452.sunDirection.y); - if (_484.starDensity > 0.0) - { - float3 param = dir; - float param_1 = _484.starDensity; - float param_2 = nightFactor; - color += generateStars(param, param_1, param_2); - } - float sunHorizonFade = smoothstep(-0.1500000059604644775390625, 0.0500000007450580596923828125, _452.sunDirection.y); - if (_452.sunDirection.y > (-0.1500000059604644775390625)) - { - float sizeAdjust = 1.0 - ((_484.sunSizeMultiplier - 1.0) * 0.001000000047497451305389404296875); - float sunSize = 0.999499976634979248046875 * sizeAdjust; - float sunGlowSize = 0.99800002574920654296875 * (1.0 - ((_484.sunSizeMultiplier - 1.0) * 0.0030000000260770320892333984375)); - float sunHaloSize = 0.9900000095367431640625 * (1.0 - ((_484.sunSizeMultiplier - 1.0) * 0.014999999664723873138427734375)); - float sunDisk = smoothstep(sunSize - 0.00019999999494757503271102905273438, sunSize, sunDot); - float sunGlow = smoothstep(sunGlowSize, sunSize, sunDot) * (1.0 - sunDisk); - float sunHalo = smoothstep(sunHaloSize, sunSize, sunDot) * (1.0 - smoothstep(sunSize, sunGlowSize, sunDot)); - float horizonBoost = smoothstep(0.100000001490116119384765625, -0.0500000007450580596923828125, _452.sunDirection.y) * 2.0; - sunHalo *= (0.300000011920928955078125 + horizonBoost); - color += ((_452.sunColor.xyz * (((sunDisk * 5.0) + (sunGlow * 0.5)) + sunHalo)) * sunHorizonFade); - } - float moonHorizonFade = smoothstep(-0.1500000059604644775390625, 0.0500000007450580596923828125, _452.moonDirection.y); - if (_452.moonDirection.y > (-0.1500000059604644775390625)) - { - float sizeAdjust_1 = 1.0 - ((_484.moonSizeMultiplier - 1.0) * 0.001000000047497451305389404296875); - float moonSize = 0.999599993228912353515625 * sizeAdjust_1; - float moonGlowSize = 0.99849998950958251953125 * (1.0 - ((_484.moonSizeMultiplier - 1.0) * 0.0030000000260770320892333984375)); - float moonHaloSize = 0.99199998378753662109375 * (1.0 - ((_484.moonSizeMultiplier - 1.0) * 0.014999999664723873138427734375)); - float moonDisk = smoothstep(moonSize - 0.00019999999494757503271102905273438, moonSize, moonDot); - if (moonDisk > 0.00999999977648258209228515625) - { - float3 up = (abs(normMoonDir.y) < 0.999000012874603271484375) ? float3(0.0, 1.0, 0.0) : float3(1.0, 0.0, 0.0); - float3 right = fast::normalize(cross(up, normMoonDir)); - float3 actualUp = cross(normMoonDir, right); - float3 relativeDir = dir - (normMoonDir * moonDot); - float u = dot(relativeDir, right); - float v = dot(relativeDir, actualUp); - float distFromCenter = length(float2(u, v)) / sqrt(1.0 - (moonSize * moonSize)); - if (distFromCenter < 1.0) - { - float2 moonUV = float2(u, v) * 200.0; - float2 param_3 = moonUV; - float param_4 = distFromCenter; - float3 param_5 = _452.moonColor.xyz; - float3 _703 = generateMoonTexture(param_3, param_4, param_5); - float3 moonTexture = _703; - color += (((moonTexture * moonDisk) * 1.5) * moonHorizonFade); - } - else - { - color += (((_452.moonColor.xyz * moonDisk) * 1.5) * moonHorizonFade); - } - } - float moonGlow = smoothstep(moonGlowSize, moonSize, moonDot) * (1.0 - moonDisk); - float moonHalo = smoothstep(moonHaloSize, moonSize, moonDot) * (1.0 - smoothstep(moonSize, moonGlowSize, moonDot)); - float moonHorizonBoost = smoothstep(0.100000001490116119384765625, -0.0500000007450580596923828125, _452.moonDirection.y) * 2.0; - moonHalo *= (0.20000000298023223876953125 + moonHorizonBoost); - color += ((_452.moonColor.xyz * ((moonGlow * 0.300000011920928955078125) + moonHalo)) * moonHorizonFade); - } - bool _767 = _452.sunDirection.y > (-0.100000001490116119384765625); - bool _773; - if (_767) - { - _773 = _484.sunTintStrength > 0.0; - } - else - { - _773 = _767; - } - if (_773) - { - float sunSkyInfluence = smoothstep(0.699999988079071044921875, 0.949999988079071044921875, sunDot) * smoothstep(-0.100000001490116119384765625, 0.20000000298023223876953125, _452.sunDirection.y); - color = mix(color, color * _452.sunColor.xyz, float3((sunSkyInfluence * 0.300000011920928955078125) * _484.sunTintStrength)); - float sunProximity = smoothstep(0.300000011920928955078125, 0.800000011920928955078125, sunDot) * smoothstep(-0.100000001490116119384765625, 0.300000011920928955078125, _452.sunDirection.y); - color += (((_452.sunColor.xyz * sunProximity) * 0.1500000059604644775390625) * _484.sunTintStrength); - float globalSunTint = smoothstep(-0.100000001490116119384765625, 0.5, _452.sunDirection.y); - color = mix(color, _452.sunColor.xyz, float3((globalSunTint * _484.sunTintStrength) * 0.07999999821186065673828125)); - } - bool _833 = _452.moonDirection.y > (-0.100000001490116119384765625); - bool _839; - if (_833) - { - _839 = _484.moonTintStrength > 0.0; - } - else - { - _839 = _833; - } - if (_839) - { - float moonSkyInfluence = smoothstep(0.800000011920928955078125, 0.949999988079071044921875, moonDot) * smoothstep(-0.100000001490116119384765625, 0.20000000298023223876953125, _452.moonDirection.y); - color = mix(color, color * _452.moonColor.xyz, float3((moonSkyInfluence * 0.20000000298023223876953125) * _484.moonTintStrength)); - float moonProximity = smoothstep(0.5, 0.85000002384185791015625, moonDot) * smoothstep(-0.100000001490116119384765625, 0.300000011920928955078125, _452.moonDirection.y); - color += (((_452.moonColor.xyz * moonProximity) * 0.07999999821186065673828125) * _484.moonTintStrength); - float globalMoonTint = smoothstep(-0.100000001490116119384765625, 0.5, _452.moonDirection.y); - color = mix(color, _452.moonColor.xyz, float3((globalMoonTint * _484.moonTintStrength) * 0.0500000007450580596923828125)); - } - } - out.FragColor = float4(color, 1.0); - return out; -} - diff --git a/shaders/metal/effects/skybox.vert.metal b/shaders/metal/effects/skybox.vert.metal deleted file mode 100644 index 9b39a063..00000000 --- a/shaders/metal/effects/skybox.vert.metal +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include - -using namespace metal; - -struct UniformBufferObject -{ - float4x4 projection; - float4x4 view; -}; - -struct main0_out -{ - float3 TexCoords [[user(locn0)]]; - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]], constant UniformBufferObject& _19 [[buffer(0)]]) -{ - main0_out out = {}; - out.TexCoords = in.aPos; - float3x3 _32 = float3x3(_19.view[0].xyz, _19.view[1].xyz, _19.view[2].xyz); - float4x4 viewNoTranslation = float4x4(float4(_32[0].x, _32[0].y, _32[0].z, 0.0), float4(_32[1].x, _32[1].y, _32[1].z, 0.0), float4(_32[2].x, _32[2].y, _32[2].z, 0.0), float4(0.0, 0.0, 0.0, 1.0)); - float4 pos = (_19.projection * viewNoTranslation) * float4(in.aPos, 1.0); - out.gl_Position = pos.xyww; - return out; -} - diff --git a/shaders/metal/effects/ssr.frag.metal b/shaders/metal/effects/ssr.frag.metal deleted file mode 100644 index 6fbe25b7..00000000 --- a/shaders/metal/effects/ssr.frag.metal +++ /dev/null @@ -1,340 +0,0 @@ -#pragma clang diagnostic ignored "-Wmissing-prototypes" - -#include -#include - -using namespace metal; - -struct Uniforms -{ - float4x4 inverseProjection; - float4x4 inverseView; - float4x4 projection; - float4x4 view; - float3 cameraPosition; -}; - -struct SSRParameters -{ - float maxDistance; - float resolution; - int steps; - float thickness; - float maxRoughness; - float historyWeight; - int debugMode; -}; - -struct main0_out -{ - float4 FragColor [[color(0)]]; -}; - -struct main0_in -{ - float2 TexCoord [[user(locn0)]]; -}; - -static inline __attribute__((always_inline)) -float3 fresnelSchlick(thread const float& cosTheta, thread const float3& F0) -{ - return F0 + ((float3(1.0) - F0) * powr(1.0 - cosTheta, 5.0)); -} - -static inline __attribute__((always_inline)) -float3 sampleSkyReflection(thread const float3& normal, thread const float3& viewDir, thread const float3& albedo, thread const float& metallic, texturecube skybox, sampler skyboxSmplr) -{ - float3 reflected = reflect(-fast::normalize(viewDir), fast::normalize(normal)); - float3 skyColor = skybox.sample(skyboxSmplr, reflected).xyz; - float skyLuma = dot(skyColor, float3(0.2125999927520751953125, 0.715200006961822509765625, 0.072200000286102294921875)); - if (skyLuma < 0.001000000047497451305389404296875) - { - float t = fast::clamp((reflected.y * 0.5) + 0.5, 0.0, 1.0); - float3 horizon = float3(0.7400000095367431640625, 0.790000021457672119140625, 0.87999999523162841796875); - float3 zenith = float3(0.5, 0.63999998569488525390625, 0.839999973773956298828125); - skyColor = mix(horizon, zenith, float3(t)); - } - float tintStrength = metallic * 0.3499999940395355224609375; - float3 tint = mix(float3(1.0), albedo, float3(tintStrength)); - return skyColor * tint; -} - -static inline __attribute__((always_inline)) -float4 SSR(thread const float3& worldPos, thread const float3& normal, thread const float3& viewDir, thread const float& roughness, thread const float& metallic, thread const float& reflectivity, thread const float3& albedo, constant Uniforms& _42, constant SSRParameters& _96, thread float4& gl_FragCoord, texture2d gPosition, sampler gPositionSmplr, texture2d sceneColor, sampler sceneColorSmplr, texture2d gNormal, sampler gNormalSmplr, texture2d gDepth, sampler gDepthSmplr, texturecube skybox, sampler skyboxSmplr) -{ - float3 viewPos = (_42.view * float4(worldPos, 1.0)).xyz; - float3 viewNormal = fast::normalize((_42.view * float4(normal, 0.0)).xyz); - float mirrorFactor = fast::clamp(fast::max(metallic, reflectivity) * (1.0 - roughness), 0.0, 1.0); - float3 skyReflection = sampleSkyReflection(normal, viewDir, albedo, metallic, skybox, skyboxSmplr); - float3 viewDirection = fast::normalize(viewPos); - float3 viewReflect = fast::normalize(reflect(viewDirection, viewNormal)); - if (viewReflect.z > 0.0) - { - return float4(0.0); - } - float3 rayOrigin = viewPos + (viewNormal * 0.00999999977648258209228515625); - float3 rayDir = viewReflect; - float stepSize = _96.maxDistance / float(_96.steps); - float3 currentPos = rayOrigin; - float jitter = fract(sin(dot(gl_FragCoord.xy, float2(12.98980045318603515625, 78.233001708984375))) * 43758.546875) * roughness * 0.25; - currentPos += ((rayDir * stepSize) * jitter); - float2 hitUV = float2(-1.0); - float hitDepth = 0.0; - bool hit = false; - float2 fallbackUV = float2(0.0); - bool hasFallbackUV = false; - float3 lastPos = currentPos; - for (int i = 0; i < _96.steps; i++) - { - float t = float(i) / float(_96.steps); - float adaptiveStep = mix(0.300000011920928955078125, 1.0, t); - currentPos += ((rayDir * stepSize) * adaptiveStep); - float4 projectedPos = _42.projection * float4(currentPos, 1.0); - float _186 = projectedPos.w; - float4 _187 = projectedPos; - float3 _190 = _187.xyz / float3(_186); - projectedPos.x = _190.x; - projectedPos.y = _190.y; - projectedPos.z = _190.z; - float2 screenUV = (projectedPos.xy * 0.5) + float2(0.5); - bool _208 = screenUV.x < 0.0; - bool _215; - if (!_208) - { - _215 = screenUV.x > 1.0; - } - else - { - _215 = _208; - } - bool _222; - if (!_215) - { - _222 = screenUV.y < 0.0; - } - else - { - _222 = _215; - } - bool _229; - if (!_222) - { - _229 = screenUV.y > 1.0; - } - else - { - _229 = _222; - } - if (!_229) - { - fallbackUV = screenUV; - hasFallbackUV = true; - } - else - { - break; - } - float hierarchyLevel = fast::clamp(floor(log2(1.0 + float(i) * 0.25)), - 0.0, 5.0); - float rawDepth = gDepth.sample(gDepthSmplr, screenUV, - level(hierarchyLevel)).x; - if (rawDepth >= 0.99989998340606689453125) - { - currentPos += rayDir * stepSize * (exp2(hierarchyLevel) - 1.0); - lastPos = currentPos; - continue; - } - float3 sampleWorldPos = gPosition.sample(gPositionSmplr, screenUV).xyz; - float3 sampleNormal = gNormal.sample(gNormalSmplr, screenUV).xyz; - if (dot(sampleNormal, sampleNormal) < 0.00999999977648258209228515625) - { - lastPos = currentPos; - continue; - } - if (length(sampleWorldPos - worldPos) < 0.07999999821186065673828125) - { - lastPos = currentPos; - continue; - } - float3 sampleViewPos = (_42.view * float4(sampleWorldPos, 1.0)).xyz; - float sampleDepth = -sampleViewPos.z; - float currentDepth = -currentPos.z; - float3 sampleViewNormal = fast::normalize((_42.view * float4(sampleNormal, 0.0)).xyz); - if ((dot(sampleViewNormal, viewNormal) > 0.920000016689300537109375) && (abs(sampleDepth - currentDepth) < (_96.thickness * 1.5))) - { - lastPos = currentPos; - continue; - } - float depthDiff = sampleDepth - currentDepth; - bool _265 = depthDiff > 0.0; - bool _272; - if (_265) - { - _272 = depthDiff < _96.thickness; - } - else - { - _272 = _265; - } - if (_272) - { - float3 binarySearchStart = lastPos; - float3 binarySearchEnd = currentPos; - for (int j = 0; j < 8; j++) - { - float3 midPoint = (binarySearchStart + binarySearchEnd) * 0.5; - float4 midProj = _42.projection * float4(midPoint, 1.0); - float _303 = midProj.w; - float4 _304 = midProj; - float3 _307 = _304.xyz / float3(_303); - midProj.x = _307.x; - midProj.y = _307.y; - midProj.z = _307.z; - float2 midUV = (midProj.xy * 0.5) + float2(0.5); - bool _321 = midUV.x < 0.0; - bool _328; - if (!_321) - { - _328 = midUV.x > 1.0; - } - else - { - _328 = _321; - } - bool _335; - if (!_328) - { - _335 = midUV.y < 0.0; - } - else - { - _335 = _328; - } - bool _342; - if (!_335) - { - _342 = midUV.y > 1.0; - } - else - { - _342 = _335; - } - if (_342) - { - break; - } - float midRawDepth = gDepth.sample(gDepthSmplr, midUV).x; - if (midRawDepth >= 0.99989998340606689453125) - { - binarySearchStart = midPoint; - continue; - } - float3 midSampleWorldPos = gPosition.sample(gPositionSmplr, midUV).xyz; - float3 midSampleViewPos = (_42.view * float4(midSampleWorldPos, 1.0)).xyz; - float midSampleDepth = -midSampleViewPos.z; - float midCurrentDepth = -midPoint.z; - if (midCurrentDepth < midSampleDepth) - { - binarySearchStart = midPoint; - } - else - { - binarySearchEnd = midPoint; - } - } - float4 finalProj = _42.projection * float4(binarySearchEnd, 1.0); - float _364 = finalProj.w; - float4 _365 = finalProj; - float3 _368 = _365.xyz / float3(_364); - finalProj.x = _368.x; - finalProj.y = _368.y; - finalProj.z = _368.z; - hitUV = (finalProj.xy * 0.5) + float2(0.5); - hitDepth = length(currentPos - rayOrigin); - hit = true; - break; - } - lastPos = currentPos; - } - if (!hit) - { - return float4(0.0); - } - float3 hitColor = sceneColor.sample(sceneColorSmplr, hitUV).xyz; - float tintStrength = metallic * 0.3499999940395355224609375; - float3 metalTint = mix(float3(1.0), albedo, float3(tintStrength)); - hitColor *= metalTint; - float hitDepthRaw = gDepth.sample(gDepthSmplr, hitUV).x; - float3 hitNormalSample = gNormal.sample(gNormalSmplr, hitUV).xyz; - float hitNormalLenSq = dot(hitNormalSample, hitNormalSample); - float3 hitNormalDir = (hitNormalLenSq > 9.9999997473787516355514526367188e-06) ? (hitNormalSample * rsqrt(hitNormalLenSq)) : (-rayDir); - float geometryValidity = 1.0 - smoothstep(0.99800002574920654296875, 1.0, hitDepthRaw); - geometryValidity *= smoothstep(0.00999999977648258209228515625, 0.100000001490116119384765625, hitNormalLenSq); - float normalFacing = fast::max(dot(hitNormalDir, -rayDir), 0.0); - geometryValidity *= smoothstep(0.0500000007450580596923828125, 0.25, normalFacing); - float hitLuma = dot(hitColor, float3(0.2125999927520751953125, 0.715200006961822509765625, 0.072200000286102294921875)); - float skyLuma = dot(skyReflection, float3(0.2125999927520751953125, 0.715200006961822509765625, 0.072200000286102294921875)); - float luminanceValidity = smoothstep(0.00200000009499490261077880859375, 0.02999999932944774627685546875, hitLuma + (skyLuma * 0.100000001490116119384765625)); - float2 edgeFade = smoothstep(float2(0.0), float2(0.1500000059604644775390625), hitUV) * (float2(1.0) - smoothstep(float2(0.85000002384185791015625), float2(1.0), hitUV)); - float edgeFactor = edgeFade.x * edgeFade.y; - float distanceFade = 1.0 - smoothstep(_96.maxDistance * 0.5, _96.maxDistance, hitDepth); - float roughnessFade = 1.0 - smoothstep(0.0, _96.maxRoughness, roughness); - float hitConfidence = (edgeFactor * distanceFade) * roughnessFade; - hitConfidence *= geometryValidity * luminanceValidity; - float3 F0 = mix(float3(0.039999999105930328369140625), albedo, float3(metallic)); - float3 V = fast::normalize(viewDir); - float cosTheta = fast::max(dot(normal, V), 0.0); - float param = cosTheta; - float3 param_1 = F0; - float3 fresnel = fresnelSchlick(param, param_1); - float fresnelFactor = ((fresnel.x + fresnel.y) + fresnel.z) / 3.0; - float fresnelWeight = mix(fresnelFactor, 1.0, mirrorFactor); - float3 reflectionColor = mix(skyReflection, hitColor, float3(hitConfidence)); - float finalFade = mix(hitConfidence * fresnelWeight, 1.0, mirrorFactor); - finalFade = fast::clamp(finalFade, 0.0, 1.0); - return float4(reflectionColor, finalFade); -} - -fragment main0_out main0(main0_in in [[stage_in]], constant Uniforms& _42 [[buffer(0)]], constant SSRParameters& _96 [[buffer(1)]], texture2d gPosition [[texture(0)]], texture2d sceneColor [[texture(1)]], texture2d gNormal [[texture(2)]], texture2d gAlbedoSpec [[texture(3)]], texture2d gMaterial [[texture(4)]], texture2d gDepth [[texture(5)]], texturecube skybox [[texture(6)]], texture2d historyTexture [[texture(7)]], sampler gPositionSmplr [[sampler(0)]], sampler sceneColorSmplr [[sampler(1)]], sampler gNormalSmplr [[sampler(2)]], sampler gAlbedoSpecSmplr [[sampler(3)]], sampler gMaterialSmplr [[sampler(4)]], sampler gDepthSmplr [[sampler(5)]], sampler skyboxSmplr [[sampler(6)]], sampler historyTextureSmplr [[sampler(7)]], float4 gl_FragCoord [[position]]) -{ - main0_out out = {}; - float3 worldPos = gPosition.sample(gPositionSmplr, in.TexCoord).xyz; - float3 normal = fast::normalize(gNormal.sample(gNormalSmplr, in.TexCoord).xyz); - float3 albedo = gAlbedoSpec.sample(gAlbedoSpecSmplr, in.TexCoord).xyz; - float4 material = gMaterial.sample(gMaterialSmplr, in.TexCoord); - float metallic = material.x; - float roughness = material.y; - float reflectivity = material.w; - if (length(normal) < 0.001000000047497451305389404296875) - { - out.FragColor = float4(0.0); - return out; - } - if (roughness > _96.maxRoughness || fast::max(metallic, reflectivity) < 0.02) - { - out.FragColor = float4(0.0); - return out; - } - float3 viewDir = fast::normalize(_42.cameraPosition - worldPos); - float3 param = worldPos; - float3 param_1 = normal; - float3 param_2 = viewDir; - float param_3 = roughness; - float param_4 = metallic; - float param_5 = reflectivity; - float3 param_6 = albedo; - float4 reflection = SSR(param, param_1, param_2, param_3, param_4, param_5, param_6, _42, _96, gl_FragCoord, gPosition, gPositionSmplr, sceneColor, sceneColorSmplr, gNormal, gNormalSmplr, gDepth, gDepthSmplr, skybox, skyboxSmplr); - if (_96.debugMode != 0) - { - out.FragColor = float4(1.0 - reflection.w, reflection.w, 0.0, 1.0); - return out; - } - if (reflection.w > 0.0 && _96.historyWeight > 0.0) - { - float4 history = historyTexture.sample(historyTextureSmplr, in.TexCoord); - float validHistory = step(0.001, history.w); - reflection = mix(reflection, history, _96.historyWeight * validHistory * reflection.w); - } - out.FragColor = reflection; - return out; -} diff --git a/shaders/metal/effects/ssr_blur.frag.metal b/shaders/metal/effects/ssr_blur.frag.metal deleted file mode 100644 index 92ac1d9f..00000000 --- a/shaders/metal/effects/ssr_blur.frag.metal +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include - -using namespace metal; - -fragment void main0() -{ -} - diff --git a/shaders/metal/effects/upsample.frag.metal b/shaders/metal/effects/upsample.frag.metal deleted file mode 100644 index 7e8106ee..00000000 --- a/shaders/metal/effects/upsample.frag.metal +++ /dev/null @@ -1,72 +0,0 @@ -#include -#include - -using namespace metal; - -struct Params -{ - float2 srcResolution; - float filterRadius; -}; - -struct main0_out -{ - float4 upsample [[color(0)]]; -}; - -struct main0_in -{ - float2 TexCoord [[user(locn0)]]; -}; - -fragment main0_out main0(main0_in in [[stage_in]], constant Params& _13 [[buffer(0)]], texture2d srcTexture [[texture(0)]], sampler srcTextureSmplr [[sampler(0)]]) -{ - main0_out out = {}; - float2 texelSize = - float2(1.0) / float2(srcTexture.get_width(), srcTexture.get_height()); - float radius = clamp(_13.filterRadius, 1.0, 8.0); - float x = radius * texelSize.x; - float y = radius * texelSize.y; - float2 texCoord = in.TexCoord; - float2 step1 = float2(x, y); - float2 step2 = step1 * 2.0; - float3 upsampleColor = float3(0.0); - float totalWeight = 0.0; - - float wCenter = 0.16; - float wCardinal1 = 0.11; - float wDiagonal1 = 0.075; - float wCardinal2 = 0.04; - float wDiagonal2 = 0.015; - - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord).xyz * wCenter; - totalWeight += wCenter; - - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(step1.x, 0.0)).xyz * wCardinal1; - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(-step1.x, 0.0)).xyz * wCardinal1; - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(0.0, step1.y)).xyz * wCardinal1; - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(0.0, -step1.y)).xyz * wCardinal1; - totalWeight += wCardinal1 * 4.0; - - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(step1.x, step1.y)).xyz * wDiagonal1; - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(-step1.x, step1.y)).xyz * wDiagonal1; - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(step1.x, -step1.y)).xyz * wDiagonal1; - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(-step1.x, -step1.y)).xyz * wDiagonal1; - totalWeight += wDiagonal1 * 4.0; - - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(step2.x, 0.0)).xyz * wCardinal2; - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(-step2.x, 0.0)).xyz * wCardinal2; - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(0.0, step2.y)).xyz * wCardinal2; - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(0.0, -step2.y)).xyz * wCardinal2; - totalWeight += wCardinal2 * 4.0; - - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(step2.x, step2.y)).xyz * wDiagonal2; - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(-step2.x, step2.y)).xyz * wDiagonal2; - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(step2.x, -step2.y)).xyz * wDiagonal2; - upsampleColor += srcTexture.sample(srcTextureSmplr, texCoord + float2(-step2.x, -step2.y)).xyz * wDiagonal2; - totalWeight += wDiagonal2 * 4.0; - - upsampleColor /= float3(max(totalWeight, 1e-5)); - out.upsample = float4(upsampleColor, 1.0); - return out; -} diff --git a/shaders/metal/fullscreen.frag.metal b/shaders/metal/fullscreen.frag.metal deleted file mode 100644 index bab92d6b..00000000 --- a/shaders/metal/fullscreen.frag.metal +++ /dev/null @@ -1,1059 +0,0 @@ -#pragma clang diagnostic ignored "-Wmissing-prototypes" -#pragma clang diagnostic ignored "-Wmissing-braces" - -#include -#include - -using namespace metal; - -template -struct spvUnsafeArray -{ - T elements[Num ? Num : 1]; - - thread T& operator [] (size_t pos) thread - { - return elements[pos]; - } - constexpr const thread T& operator [] (size_t pos) const thread - { - return elements[pos]; - } - - device T& operator [] (size_t pos) device - { - return elements[pos]; - } - constexpr const device T& operator [] (size_t pos) const device - { - return elements[pos]; - } - - constexpr const constant T& operator [] (size_t pos) const constant - { - return elements[pos]; - } - - threadgroup T& operator [] (size_t pos) threadgroup - { - return elements[pos]; - } - constexpr const threadgroup T& operator [] (size_t pos) const threadgroup - { - return elements[pos]; - } -}; - -// Implementation of the GLSL mod() function, which is slightly different than Metal fmod() -template -inline Tx mod(Tx x, Ty y) -{ - return x - y * floor(x / y); -} - -struct ColorCorrection -{ - float exposure; - float contrast; - float saturation; - float gamma; - float temperature; - float tint; -}; - -struct PushConstants -{ - int hasBrightTexture; - int hasDepthTexture; - int hasVolumetricLightTexture; - int hasPositionTexture; - int hasLUTTexture; - int hasSSRTexture; - int TextureType; - float lutSize; - int EffectCount; -}; - -struct EffectBuffer -{ - int Effects[1]; -}; - -struct EffectFloat1Buffer -{ - float EffectFloat1[1]; -}; - -struct EffectFloat2Buffer -{ - float EffectFloat2[1]; -}; - -struct EffectFloat3Buffer -{ - float EffectFloat3[1]; -}; - -struct EffectFloat4Buffer -{ - float EffectFloat4[1]; -}; - -struct EffectFloat5Buffer -{ - float EffectFloat5[1]; -}; - -struct Uniforms -{ - float4x4 invProjectionMatrix; - float4x4 projectionMatrix; - float4x4 viewMatrix; - float4x4 invViewMatrix; - float4x4 lastViewMatrix; - float nearPlane; - float farPlane; - float focusDepth; - float focusRange; - int maxMipLevel; - float deltaTime; - float time; -}; - -struct EffectFloat6Buffer -{ - float EffectFloat6[1]; -}; - -struct Clouds -{ - float3 cloudPosition; - float3 cloudSize; - packed_float3 cameraPosition; - float cloudScale; - packed_float3 cloudOffset; - float cloudDensityThreshold; - float cloudDensityMultiplier; - float cloudAbsorption; - float cloudScattering; - float cloudPhaseG; - float cloudClusterStrength; - int cloudPrimarySteps; - int cloudLightSteps; - float cloudLightStepMultiplier; - float cloudMinStepLength; - float3 sunDirection; - packed_float3 sunColor; - float sunIntensity; - packed_float3 cloudAmbientColor; - int hasClouds; -}; - -struct Environment -{ - packed_float3 fogColor; - float fogIntensity; -}; - -constant spvUnsafeArray _165 = spvUnsafeArray({ float2(-0.0033333334140479564666748046875, 0.0033333334140479564666748046875), float2(0.0, 0.0033333334140479564666748046875), float2(0.0033333334140479564666748046875), float2(-0.0033333334140479564666748046875, 0.0), float2(0.0), float2(0.0033333334140479564666748046875, 0.0), float2(-0.0033333334140479564666748046875), float2(0.0, -0.0033333334140479564666748046875), float2(0.0033333334140479564666748046875, -0.0033333334140479564666748046875) }); -constant spvUnsafeArray _171 = spvUnsafeArray({ -1.0, -1.0, -1.0, -1.0, 9.0, -1.0, -1.0, -1.0, -1.0 }); -constant spvUnsafeArray _311 = spvUnsafeArray({ 1.0, 1.0, 1.0, 1.0, -8.0, 1.0, 1.0, 1.0, 1.0 }); - -struct main0_out -{ - float4 FragColor [[color(0)]]; -}; - -struct main0_in -{ - float2 TexCoord [[user(locn0)]]; -}; - -static inline __attribute__((always_inline)) -float4 sampleColor(thread const float2& uv, constant PushConstants& _372, device EffectBuffer& _381, device EffectFloat1Buffer& _394, device EffectFloat2Buffer& _403, device EffectFloat3Buffer& _411, device EffectFloat4Buffer& _419, device EffectFloat5Buffer& _426, texture2d Texture, sampler TextureSmplr) -{ - for (int i = 0; i < _372.EffectCount; i++) - { - if (_381.Effects[i] == 7) - { - float redOffset = _394.EffectFloat1[i]; - float greenOffset = _403.EffectFloat2[i]; - float blueOffset = _411.EffectFloat3[i]; - float2 focusPoint = float2(_419.EffectFloat4[i], _426.EffectFloat5[i]); - float2 sampleCoord = uv; - float2 direction = sampleCoord - focusPoint; - float red = Texture.sample(TextureSmplr, (sampleCoord + (direction * redOffset))).x; - float green = Texture.sample(TextureSmplr, (sampleCoord + (direction * greenOffset))).y; - float2 blue = Texture.sample(TextureSmplr, (sampleCoord + (direction * blueOffset))).zw; - return float4(red, green, blue); - } - else - { - if (_381.Effects[i] == 9) - { - float pixelSizeInPixels = _394.EffectFloat1[i]; - float2 texSize = float2(int2(Texture.get_width(), Texture.get_height())); - float2 pixelSize = float2(pixelSizeInPixels) / texSize; - float2 pixelated = floor(uv / pixelSize) * pixelSize; - return Texture.sample(TextureSmplr, pixelated); - } - else - { - if (_381.Effects[i] == 10) - { - float radius = _394.EffectFloat1[i]; - float separation = _403.EffectFloat2[i]; - float2 texelSize = float2(1.0) / float2(int2(Texture.get_width(), Texture.get_height())); - float3 maxColor = Texture.sample(TextureSmplr, uv).xyz; - int range = int(radius); - float radiusSq = radius * radius; - int _543 = -range; - for (int x = _543; x <= range; x++) - { - int _554 = -range; - for (int y = _554; y <= range; y++) - { - float distSq = float((x * x) + (y * y)); - if (distSq <= radiusSq) - { - float2 offset = (float2(float(x), float(y)) * texelSize) * separation; - float3 sampled = Texture.sample(TextureSmplr, (uv + offset)).xyz; - maxColor = fast::max(maxColor, sampled); - } - } - } - return float4(maxColor, Texture.sample(TextureSmplr, uv).w); - } - } - } - } - return Texture.sample(TextureSmplr, uv); -} - -static inline __attribute__((always_inline)) -float3 reconstructViewPos(thread const float2& uv, thread const float& depth, constant Uniforms& _849) -{ - float z = (depth * 2.0) - 1.0; - float4 clipPos = float4((uv * 2.0) - float2(1.0), z, 1.0); - float4 viewPos = _849.invProjectionMatrix * clipPos; - viewPos /= float4(viewPos.w); - return viewPos.xyz; -} - -static inline __attribute__((always_inline)) -float4 sharpen(texture2d image, sampler imageSmplr, thread float2& TexCoord) -{ - spvUnsafeArray sampleTex; - for (int i = 0; i < 9; i++) - { - sampleTex[i] = float3(image.sample(imageSmplr, (TexCoord + _165[i])).xyz); - } - float3 col = float3(0.0); - for (int i_1 = 0; i_1 < 9; i_1++) - { - col += (sampleTex[i_1] * _171[i_1]); - } - return float4(col, 1.0); -} - -static inline __attribute__((always_inline)) -float4 blur(texture2d image, sampler imageSmplr, thread const float& radius, thread float2& TexCoord) -{ - float2 texelSize = float2(1.0) / float2(int2(image.get_width(), image.get_height())); - float3 result = float3(0.0); - float total = 0.0; - float sigma = radius * 0.5; - float twoSigmaSq = (2.0 * sigma) * sigma; - int _257 = -int(radius); - for (int x = _257; x <= int(radius); x++) - { - float weight = exp(float(-(x * x)) / twoSigmaSq); - float2 offset = float2(float(x), 0.0) * texelSize; - result += (image.sample(imageSmplr, (TexCoord + offset)).xyz * weight); - total += weight; - } - result /= float3(total); - return float4(result, 1.0); -} - -static inline __attribute__((always_inline)) -float4 edgeDetection(texture2d image, sampler imageSmplr, thread float2& TexCoord) -{ - spvUnsafeArray sampleTex; - for (int i = 0; i < 9; i++) - { - sampleTex[i] = float3(image.sample(imageSmplr, (TexCoord + _165[i])).xyz); - } - float3 col = float3(0.0); - for (int i_1 = 0; i_1 < 9; i_1++) - { - col += (sampleTex[i_1] * _311[i_1]); - } - return float4(col, 1.0); -} - -static inline __attribute__((always_inline)) -float4 applyFXAA(texture2d tex, sampler texSmplr, thread const float2& texCoord, constant PushConstants& _372, device EffectBuffer& _381, device EffectFloat1Buffer& _394, device EffectFloat2Buffer& _403, device EffectFloat3Buffer& _411, device EffectFloat4Buffer& _419, device EffectFloat5Buffer& _426, texture2d Texture, sampler TextureSmplr) -{ - float2 texelSize = float2(1.0) / float2(int2(tex.get_width(), tex.get_height())); - float FXAA_SPAN_MAX = 8.0; - float FXAA_REDUCE_MUL = 0.125; - float FXAA_REDUCE_MIN = 0.0078125; - float2 param = texCoord + (float2(-1.0) * texelSize); - float3 rgbNW = sampleColor(param, _372, _381, _394, _403, _411, _419, _426, Texture, TextureSmplr).xyz; - float2 param_1 = texCoord + (float2(1.0, -1.0) * texelSize); - float3 rgbNE = sampleColor(param_1, _372, _381, _394, _403, _411, _419, _426, Texture, TextureSmplr).xyz; - float2 param_2 = texCoord + (float2(-1.0, 1.0) * texelSize); - float3 rgbSW = sampleColor(param_2, _372, _381, _394, _403, _411, _419, _426, Texture, TextureSmplr).xyz; - float2 param_3 = texCoord + (float2(1.0) * texelSize); - float3 rgbSE = sampleColor(param_3, _372, _381, _394, _403, _411, _419, _426, Texture, TextureSmplr).xyz; - float2 param_4 = texCoord; - float3 rgbM = sampleColor(param_4, _372, _381, _394, _403, _411, _419, _426, Texture, TextureSmplr).xyz; - float3 luma = float3(0.2989999949932098388671875, 0.58700001239776611328125, 0.114000000059604644775390625); - float lumaNW = dot(rgbNW, luma); - float lumaNE = dot(rgbNE, luma); - float lumaSW = dot(rgbSW, luma); - float lumaSE = dot(rgbSE, luma); - float lumaM = dot(rgbM, luma); - float lumaMin = fast::min(lumaM, fast::min(fast::min(lumaNW, lumaNE), fast::min(lumaSW, lumaSE))); - float lumaMax = fast::max(lumaM, fast::max(fast::max(lumaNW, lumaNE), fast::max(lumaSW, lumaSE))); - float2 dir; - dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); - dir.y = (lumaNW + lumaSW) - (lumaNE + lumaSE); - float dirReduce = fast::max((((lumaNW + lumaNE) + lumaSW) + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN); - float rcpDirMin = 1.0 / (fast::min(abs(dir.x), abs(dir.y)) + dirReduce); - dir = fast::min(float2(FXAA_SPAN_MAX), fast::max(float2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin)) * texelSize; - float2 param_5 = texCoord + (dir * (-0.16666667163372039794921875)); - float2 param_6 = texCoord + (dir * 0.16666667163372039794921875); - float3 rgbA = (sampleColor(param_5, _372, _381, _394, _403, _411, _419, _426, Texture, TextureSmplr).xyz + sampleColor(param_6, _372, _381, _394, _403, _411, _419, _426, Texture, TextureSmplr).xyz) * 0.5; - float2 param_7 = texCoord + (dir * (-0.5)); - float2 param_8 = texCoord + (dir * 0.5); - float3 rgbB = (rgbA * 0.5) + ((sampleColor(param_7, _372, _381, _394, _403, _411, _419, _426, Texture, TextureSmplr).xyz + sampleColor(param_8, _372, _381, _394, _403, _411, _419, _426, Texture, TextureSmplr).xyz) * 0.25); - float lumaB = dot(rgbB, luma); - if ((lumaB < lumaMin) || (lumaB > lumaMax)) - { - return float4(rgbA, 1.0); - } - else - { - return float4(rgbB, 1.0); - } -} - -static inline __attribute__((always_inline)) -float4 applyColorCorrection(thread const float4& color, thread const ColorCorrection& cc) -{ - float3 linearColor = color.xyz; - linearColor *= powr(2.0, cc.exposure); - linearColor = ((linearColor - float3(0.5)) * cc.contrast) + float3(0.5); - linearColor.x += (cc.temperature * 0.0500000007450580596923828125); - linearColor.y += (cc.tint * 0.0500000007450580596923828125); - float luminance = dot(linearColor, float3(0.2125999927520751953125, 0.715200006961822509765625, 0.072200000286102294921875)); - linearColor = mix(float3(luminance), linearColor, float3(cc.saturation)); - linearColor = fast::clamp(linearColor, float3(0.0), float3(1.0)); - return float4(linearColor, color.w); -} - -static inline __attribute__((always_inline)) -float4 applyColorEffects(thread float4& color, constant PushConstants& _372, device EffectBuffer& _381, device EffectFloat1Buffer& _394, device EffectFloat2Buffer& _403, device EffectFloat3Buffer& _411, device EffectFloat4Buffer& _419, device EffectFloat5Buffer& _426, constant Uniforms& _849, device EffectFloat6Buffer& _1049, thread float4& gl_FragCoord) -{ - ColorCorrection cc; - for (int i = 0; i < _372.EffectCount; i++) - { - if (_381.Effects[i] == 0) - { - color = float4(float3(1.0) - color.xyz, color.w); - } - else - { - if (_381.Effects[i] == 1) - { - float average = ((0.2125999927520751953125 * color.x) + (0.715200006961822509765625 * color.y)) + (0.072200000286102294921875 * color.z); - color = float4(average, average, average, color.w); - } - else - { - if (_381.Effects[i] == 5) - { - cc.exposure = _394.EffectFloat1[i]; - cc.contrast = _403.EffectFloat2[i]; - cc.saturation = _411.EffectFloat3[i]; - cc.gamma = _419.EffectFloat4[i]; - cc.temperature = _426.EffectFloat5[i]; - cc.tint = _1049.EffectFloat6[i]; - float4 param = color; - ColorCorrection param_1 = cc; - color = applyColorCorrection(param, param_1); - } - else - { - if (_381.Effects[i] == 8) - { - float levels = fast::max(_394.EffectFloat1[i], 1.0); - float grayscale = fast::max(color.x, fast::max(color.y, color.z)); - if (grayscale > 9.9999997473787516355514526367188e-05) - { - float lower = floor(grayscale * levels) / levels; - float lowerDiff = abs(grayscale - lower); - float upper = ceil(grayscale * levels) / levels; - float upperDiff = abs(upper - grayscale); - float level0 = (lowerDiff <= upperDiff) ? lower : upper; - float adjustment = level0 / fast::max(grayscale, 9.9999997473787516355514526367188e-05); - color *= adjustment; - } - } - else - { - if (_381.Effects[i] == 11) - { - float amount = _394.EffectFloat1[i]; - float3 seed = float3(gl_FragCoord.xy, _849.deltaTime * 100.0); - float n = dot(seed, float3(12.98980045318603515625, 78.233001708984375, 45.16400146484375)); - float noise = fract(sin(n) * 43758.546875); - float grain = ((noise - 0.5) * 2.0) * amount; - float luminance = dot(color.xyz, float3(0.2989999949932098388671875, 0.58700001239776611328125, 0.114000000059604644775390625)); - float visibility = 1.0 - (abs(luminance - 0.5) * 0.5); - float4 _1210 = color; - float3 _1212 = _1210.xyz + float3(grain * visibility); - color.x = _1212.x; - color.y = _1212.y; - color.z = _1212.z; - float4 _1219 = color; - float3 _1223 = fast::clamp(_1219.xyz, float3(0.0), float3(1.0)); - color.x = _1223.x; - color.y = _1223.y; - color.z = _1223.z; - } - } - } - } - } - } - return color; -} - -static inline __attribute__((always_inline)) -float LinearizeDepth(thread const float& depth, constant Uniforms& _849) -{ - float z = (depth * 2.0) - 1.0; - float linear = ((2.0 * _849.nearPlane) * _849.farPlane) / ((_849.farPlane + _849.nearPlane) - (z * (_849.farPlane - _849.nearPlane))); - return linear / _849.farPlane; -} - -static inline __attribute__((always_inline)) -float2 rayBoxDst(thread const float3& boundsMin, thread const float3& boundsMax, thread const float3& rayOrigin, thread const float3& rayDir) -{ - float3 t0 = (boundsMin - rayOrigin) / rayDir; - float3 t1 = (boundsMax - rayOrigin) / rayDir; - float3 tMin = fast::min(t0, t1); - float3 tMax = fast::max(t0, t1); - float dstA = fast::max(fast::max(tMin.x, tMin.y), tMin.z); - float dstB = fast::min(tMax.x, fast::min(tMax.y, tMax.z)); - float dstToContainer = fast::max(0.0, dstA); - float dstInsideContainer = fast::max(0.0, dstB - dstToContainer); - return float2(dstToContainer, dstInsideContainer); -} - -static inline __attribute__((always_inline)) -float hashNoise(thread const float3& p) -{ - return fract(sin(dot(p, float3(12.98980045318603515625, 78.233001708984375, 37.71900177001953125))) * 43758.546875); -} - -static inline __attribute__((always_inline)) -float saturate0(thread const float& v) -{ - return fast::clamp(v, 0.0, 1.0); -} - -static inline __attribute__((always_inline)) -float calculateCloudDensity(thread const float3& worldPos, constant Clouds& _1929, texture3d cloudsTexture, sampler cloudsTextureSmplr) -{ - float3 halfExtents = fast::max(_1929.cloudSize * 0.5, float3(9.9999997473787516355514526367188e-05)); - float3 localPos = (worldPos - _1929.cloudPosition) / halfExtents; - bool _1947 = any(localPos < float3(-1.0)); - bool _1955; - if (!_1947) - { - _1955 = any(localPos > float3(1.0)); - } - else - { - _1955 = _1947; - } - if (_1955) - { - return 0.0; - } - float3 uvw = (localPos * 0.5) + float3(0.5); - float scale = fast::max(_1929.cloudScale, 0.001000000047497451305389404296875); - float3 noiseCoord = fract((uvw * scale) + float3(_1929.cloudOffset)); - float4 shape = cloudsTexture.sample(cloudsTextureSmplr, noiseCoord); - float param = _1929.cloudClusterStrength; - float cluster = saturate0(param); - float lowerFade = smoothstep(-0.949999988079071044921875, -0.60000002384185791015625, localPos.y); - float upperFade = 1.0 - smoothstep(0.3499999940395355224609375, 0.949999988079071044921875, localPos.y); - float verticalMask = lowerFade * upperFade; - float coverageThreshold = mix(0.60000002384185791015625, 0.2800000011920928955078125, cluster); - float coverageSoftness = mix(0.2199999988079071044921875, 0.3400000035762786865234375, cluster); - float coverageNoise = mix(shape.x, shape.w, 0.4000000059604644775390625 + (cluster * 0.3499999940395355224609375)); - float coverage = smoothstep(coverageThreshold, coverageThreshold + coverageSoftness, coverageNoise); - coverage = powr(coverage, mix(2.0, 0.699999988079071044921875, cluster)); - float detail = mix(smoothstep(0.25, 0.75, shape.y), smoothstep(0.20000000298023223876953125, 0.89999997615814208984375, shape.w), 0.550000011920928955078125); - detail = powr(detail, mix(1.60000002384185791015625, 0.85000002384185791015625, cluster)); - float cavityNoise = smoothstep(0.2199999988079071044921875, 0.85000002384185791015625, shape.z); - float gapMask = fast::clamp(1.0 - (cavityNoise * mix(0.25, 0.699999988079071044921875, cluster)), 0.0, 1.0); - float density = coverage * mix(detail, 1.0, cluster * 0.3499999940395355224609375); - density = fast::max(((density * gapMask) * verticalMask) - 0.0199999995529651641845703125, 0.0); - density *= fast::max(_1929.cloudDensityMultiplier, 0.0); - return density; -} - -static inline __attribute__((always_inline)) -float sampleSunTransmittance(thread const float3& worldPos, thread const float& stepSize, constant Clouds& _1929, texture3d cloudsTexture, sampler cloudsTextureSmplr) -{ - float3 lightDir = -_1929.sunDirection; - float dirLength = length(lightDir); - if (dirLength < 0.001000000047497451305389404296875) - { - lightDir = float3(0.0, 1.0, 0.0); - } - else - { - lightDir /= float3(dirLength); - } - float maxDistance = length(_1929.cloudSize) * 1.5; - float travel = 0.0; - float attenuation = 1.0; - float lightStep = fast::max(stepSize * _1929.cloudLightStepMultiplier, _1929.cloudMinStepLength); - int steps = max(_1929.cloudLightSteps, 1); - for (int i = 0; (i < steps) && (attenuation > 0.0500000007450580596923828125); i++) - { - travel += lightStep; - if (travel > maxDistance) - { - break; - } - float3 samplePos = worldPos + (lightDir * travel); - float3 param = samplePos; - float density = calculateCloudDensity(param, _1929, cloudsTexture, cloudsTextureSmplr); - attenuation *= exp(((-density) * lightStep) * _1929.cloudAbsorption); - lightStep = fast::max(lightStep * _1929.cloudLightStepMultiplier, _1929.cloudMinStepLength); - } - return attenuation; -} - -static inline __attribute__((always_inline)) -float henyeyGreenstein(thread const float& cosTheta, thread const float& g) -{ - float g2 = g * g; - float denom = powr((1.0 + g2) - ((2.0 * g) * cosTheta), 1.5); - return (1.0 - g2) / (12.56637096405029296875 * fast::max(denom, 9.9999997473787516355514526367188e-05)); -} - -static inline __attribute__((always_inline)) -float4 cloudRendering(thread const float4& inColor, thread float2& TexCoord, constant PushConstants& _372, constant Uniforms& _849, constant Clouds& _1929, texture3d cloudsTexture, sampler cloudsTextureSmplr, texture2d DepthTexture, sampler DepthTextureSmplr) -{ - if (_1929.hasClouds != 1) - { - return inColor; - } - float _2197; - if (_372.hasDepthTexture == 1) - { - _2197 = DepthTexture.sample(DepthTextureSmplr, TexCoord).x; - } - else - { - _2197 = 1.0; - } - float nonLinearDepth = _2197; - bool depthAvailable = (_372.hasDepthTexture == 1) && (nonLinearDepth < 1.0); - float depthSample = depthAvailable ? nonLinearDepth : 1.0; - float3 rayOrigin = float3(_1929.cameraPosition); - float4 clipSpace = float4((TexCoord * 2.0) - float2(1.0), (depthSample * 2.0) - 1.0, 1.0); - float4 viewSpace = _849.invProjectionMatrix * clipSpace; - viewSpace /= float4(viewSpace.w); - float3 worldPos = (_849.invViewMatrix * float4(viewSpace.xyz, 1.0)).xyz; - float3 rayDir = fast::normalize(worldPos - rayOrigin); - float _2261; - if (depthAvailable) - { - _2261 = length(worldPos - rayOrigin); - } - else - { - _2261 = 1000000.0; - } - float sceneDistance = _2261; - float3 boundsMin = _1929.cloudPosition - (_1929.cloudSize * 0.5); - float3 boundsMax = _1929.cloudPosition + (_1929.cloudSize * 0.5); - float3 param = boundsMin; - float3 param_1 = boundsMax; - float3 param_2 = rayOrigin; - float3 param_3 = rayDir; - float2 rayBoxInfo = rayBoxDst(param, param_1, param_2, param_3); - float distToContainer = rayBoxInfo.x; - float distInContainer = rayBoxInfo.y; - if (distInContainer <= 0.0) - { - return inColor; - } - float dstLimit = fast::min(sceneDistance - distToContainer, distInContainer); - dstLimit = fast::max(dstLimit, 0.0); - if (dstLimit <= 9.9999997473787516355514526367188e-05) - { - return inColor; - } - int steps = max(_1929.cloudPrimarySteps, 8); - float baseStep = dstLimit / float(steps); - float stepSize = fast::max(baseStep, _1929.cloudMinStepLength); - float3 param_4 = float3(TexCoord, _849.time); - float jitter = hashNoise(param_4) - 0.5; - float travelled = fast::clamp(jitter, -0.3499999940395355224609375, 0.3499999940395355224609375) * stepSize; - travelled = fast::max(travelled, 0.0); - float3 accumulatedLight = float3(0.0); - float transmittance = 1.0; - float3 sunDir = _1929.sunDirection; - float sunLen = length(sunDir); - if (sunLen > 0.001000000047497451305389404296875) - { - sunDir /= float3(sunLen); - } - else - { - sunDir = float3(0.0, 1.0, 0.0); - } - float phaseG = fast::clamp(_1929.cloudPhaseG, -0.949999988079071044921875, 0.949999988079071044921875); - for (int _step = 0; (_step < steps) && (travelled < dstLimit); _step++) - { - if (transmittance <= 0.00999999977648258209228515625) - { - break; - } - float remainingDistance = dstLimit - travelled; - if (remainingDistance <= 9.9999997473787516355514526367188e-06) - { - break; - } - float current = distToContainer + travelled; - float3 samplePos = rayOrigin + (rayDir * current); - float3 param_5 = samplePos; - float density = calculateCloudDensity(param_5, _1929, cloudsTexture, cloudsTextureSmplr); - if (density > 9.9999997473787516355514526367188e-05) - { - float adaptiveStep = stepSize; - if (density < 0.0199999995529651641845703125) - { - adaptiveStep = stepSize * 2.5; - } - else - { - if (density < 0.0500000007450580596923828125) - { - adaptiveStep = stepSize * 1.60000002384185791015625; - } - } - adaptiveStep = fast::min(adaptiveStep, remainingDistance); - float sampleWeight = density * adaptiveStep; - float3 param_6 = samplePos; - float param_7 = adaptiveStep; - float lightTrans = sampleSunTransmittance(param_6, param_7, _1929, cloudsTexture, cloudsTextureSmplr); - float cosTheta = fast::clamp(dot(rayDir, -sunDir), -1.0, 1.0); - float param_8 = cosTheta; - float param_9 = phaseG; - float phase = henyeyGreenstein(param_8, param_9); - float3 directLight = ((float3(_1929.sunColor) * _1929.sunIntensity) * lightTrans) * phase; - float3 ambientLight = float3(_1929.cloudAmbientColor); - float3 lighting = (((ambientLight * 0.3499999940395355224609375) + directLight) * sampleWeight) * _1929.cloudScattering; - accumulatedLight += (lighting * transmittance); - transmittance *= exp(((-density) * adaptiveStep) * _1929.cloudAbsorption); - travelled += adaptiveStep; - continue; - } - float emptyAdvance = fast::min(stepSize * 2.25, remainingDistance); - float minAdvance = fast::min(stepSize * 0.5, remainingDistance); - travelled += fast::max(emptyAdvance, minAdvance); - } - float3 finalColor = (inColor.xyz * transmittance) + accumulatedLight; - return float4(fast::clamp(finalColor, float3(0.0), float3(1.0)), inColor.w); -} - -static inline __attribute__((always_inline)) -float4 sampleBright(thread const float2& uv, constant PushConstants& _372, device EffectBuffer& _381, device EffectFloat1Buffer& _394, device EffectFloat2Buffer& _403, device EffectFloat3Buffer& _411, device EffectFloat4Buffer& _419, device EffectFloat5Buffer& _426, texture2d BrightTexture, sampler BrightTextureSmplr) -{ - for (int i = 0; i < _372.EffectCount; i++) - { - if (_381.Effects[i] == 7) - { - float redOffset = _394.EffectFloat1[i]; - float greenOffset = _403.EffectFloat2[i]; - float blueOffset = _411.EffectFloat3[i]; - float2 focusPoint = float2(_419.EffectFloat4[i], _426.EffectFloat5[i]); - float2 sampleCoord = uv; - float2 direction = sampleCoord - focusPoint; - float red = BrightTexture.sample(BrightTextureSmplr, (sampleCoord + (direction * redOffset))).x; - float green = BrightTexture.sample(BrightTextureSmplr, (sampleCoord + (direction * greenOffset))).y; - float2 blue = BrightTexture.sample(BrightTextureSmplr, (sampleCoord + (direction * blueOffset))).zw; - return float4(red, green, blue); - } - else - { - if (_381.Effects[i] == 9) - { - float pixelSizeInPixels = _394.EffectFloat1[i]; - float2 texSize = float2(int2(BrightTexture.get_width(), BrightTexture.get_height())); - float2 pixelSize = float2(pixelSizeInPixels) / texSize; - float2 pixelated = floor(uv / pixelSize) * pixelSize; - float4 color = BrightTexture.sample(BrightTextureSmplr, pixelated); - return color; - } - else - { - if (_381.Effects[i] == 10) - { - float radius = _394.EffectFloat1[i]; - float separation = _403.EffectFloat2[i]; - float2 texelSize = float2(1.0) / float2(int2(BrightTexture.get_width(), BrightTexture.get_height())); - float3 maxColor = BrightTexture.sample(BrightTextureSmplr, uv).xyz; - int range = int(radius); - float radiusSq = radius * radius; - int _766 = -range; - for (int x = _766; x <= range; x++) - { - int _777 = -range; - for (int y = _777; y <= range; y++) - { - float distSq = float((x * x) + (y * y)); - if (distSq <= radiusSq) - { - float2 offset = (float2(float(x), float(y)) * texelSize) * separation; - float3 sampled = BrightTexture.sample(BrightTextureSmplr, (uv + offset)).xyz; - maxColor = fast::max(maxColor, sampled); - } - } - } - return float4(maxColor, BrightTexture.sample(BrightTextureSmplr, uv).w); - } - } - } - } - return BrightTexture.sample(BrightTextureSmplr, uv); -} - -static inline __attribute__((always_inline)) -float4 composeSSR(thread const float4& color, thread const float2& uv, constant PushConstants& _372, texture2d SSRTexture, sampler SSRTextureSmplr) -{ - if (_372.hasSSRTexture != 1) - { - return color; - } - float4 ssr = SSRTexture.sample(SSRTextureSmplr, uv); - float reflectionWeight = fast::clamp(ssr.w, 0.0, 1.0); - float baseWeight = 1.0 - reflectionWeight; - float4 result = color; - result.xyz = (result.xyz * baseWeight) + (ssr.xyz * reflectionWeight); - return result; -} - -static inline __attribute__((always_inline)) -float4 composeLighting(thread const float2& uv, thread const float4& baseColor, constant PushConstants& _372, device EffectBuffer& _381, device EffectFloat1Buffer& _394, device EffectFloat2Buffer& _403, device EffectFloat3Buffer& _411, device EffectFloat4Buffer& _419, device EffectFloat5Buffer& _426, texture2d BrightTexture, sampler BrightTextureSmplr, texture2d VolumetricLightTexture, sampler VolumetricLightTextureSmplr, texture2d SSRTexture, sampler SSRTextureSmplr) -{ - float4 color = baseColor; - if (_372.hasBrightTexture == 1) - { - color += sampleBright(uv, _372, _381, _394, _403, _411, _419, _426, BrightTexture, BrightTextureSmplr); - } - if (_372.hasVolumetricLightTexture == 1) - { - color += VolumetricLightTexture.sample(VolumetricLightTextureSmplr, uv); - } - return composeSSR(color, uv, _372, SSRTexture, SSRTextureSmplr); -} - -static inline __attribute__((always_inline)) -float4 applyMotionBlur(thread const float2& texCoord, thread const float& size, thread const float& separation, thread const float4& color, constant PushConstants& _372, device EffectBuffer& _381, device EffectFloat1Buffer& _394, device EffectFloat2Buffer& _403, device EffectFloat3Buffer& _411, device EffectFloat4Buffer& _419, device EffectFloat5Buffer& _426, texture2d Texture, sampler TextureSmplr, texture2d BrightTexture, sampler BrightTextureSmplr, constant Uniforms& _849, texture2d VolumetricLightTexture, sampler VolumetricLightTextureSmplr, texture2d SSRTexture, sampler SSRTextureSmplr, texture2d PositionTexture, sampler PositionTextureSmplr, texture2d DepthTexture, sampler DepthTextureSmplr) -{ - float4 fallbackColor = composeLighting(texCoord, color, _372, _381, _394, _403, _411, _419, _426, BrightTexture, BrightTextureSmplr, VolumetricLightTexture, VolumetricLightTextureSmplr, SSRTexture, SSRTextureSmplr); - if ((size <= 0.0) || (separation <= 0.0)) - { - return fallbackColor; - } - if (_372.hasPositionTexture != 1) - { - return fallbackColor; - } - float4 worldPos = PositionTexture.sample(PositionTextureSmplr, texCoord); - if (worldPos.w <= 0.0) - { - return fallbackColor; - } - float3 viewSpacePos = (_849.viewMatrix * worldPos).xyz; - float distanceToCamera = length(viewSpacePos); - if (distanceToCamera < (_849.nearPlane * 2.0)) - { - return fallbackColor; - } - float4 currentClipPos = (_849.projectionMatrix * _849.viewMatrix) * worldPos; - float _1543 = currentClipPos.w; - float4 _1544 = currentClipPos; - float3 _1547 = _1544.xyz / float3(_1543); - currentClipPos.x = _1547.x; - currentClipPos.y = _1547.y; - currentClipPos.z = _1547.z; - float2 currentUV = (currentClipPos.xy * 0.5) + float2(0.5); - float4 prevClipPos = (_849.projectionMatrix * _849.lastViewMatrix) * worldPos; - float _1569 = prevClipPos.w; - float4 _1570 = prevClipPos; - float3 _1573 = _1570.xyz / float3(_1569); - prevClipPos.x = _1573.x; - prevClipPos.y = _1573.y; - prevClipPos.z = _1573.z; - float2 prevUV = (prevClipPos.xy * 0.5) + float2(0.5); - float2 velocity = (currentUV - prevUV) * separation; - float velocityLength = length(velocity); - float maxVelocity = 0.119999997317790985107421875; - if (velocityLength > maxVelocity) - { - velocity = fast::normalize(velocity) * maxVelocity; - velocityLength = maxVelocity; - } - if (_372.hasSSRTexture == 1) - { - float mirrorWeight = fast::clamp(SSRTexture.sample(SSRTextureSmplr, texCoord).w, 0.0, 1.0); - float blurDamp = mix(1.0, 0.20000000298023223876953125, mirrorWeight); - velocity *= blurDamp; - velocityLength *= blurDamp; - } - if (velocityLength < 9.9999997473787516355514526367188e-05) - { - return fallbackColor; - } - int baseSamples = clamp(int(size), 2, 32); - float sampleScale = mix(0.75, 1.75, fast::clamp(velocityLength / maxVelocity, 0.0, 1.0)); - int samples = clamp(int(float(baseSamples) * sampleScale), 3, 48); - float centerDepth = 0.0; - float depthSoftness = 1.0; - if (_372.hasDepthTexture == 1) - { - float centerDepthRaw = DepthTexture.sample(DepthTextureSmplr, texCoord).x; - centerDepth = LinearizeDepth(centerDepthRaw, _849); - depthSoftness = fast::max(0.00200000009499490261077880859375, centerDepth * 0.0199999995529651641845703125); - } - float jitter = (fract(sin(dot(texCoord * float2(173.3000030517578125, 97.09999847412109375), float2(12.98980045318603515625, 78.233001708984375))) * 43758.546875) - 0.5) * 0.3499999940395355224609375; - float4 result = float4(0.0); - float totalWeight = 0.0; - for (int i = 0; i < samples; i++) - { - float t = (((float(i) + 0.5) / float(samples)) * 2.0) - 1.0; - t += jitter / float(samples); - float2 sampleCoord = texCoord + (velocity * t); - bool _1642 = sampleCoord.x < 0.0; - bool _1648; - if (!_1642) - { - _1648 = sampleCoord.x > 1.0; - } - else - { - _1648 = _1642; - } - bool _1654; - if (!_1648) - { - _1654 = sampleCoord.y < 0.0; - } - else - { - _1654 = _1648; - } - bool _1660; - if (!_1654) - { - _1660 = sampleCoord.y > 1.0; - } - else - { - _1660 = _1654; - } - if (_1660) - { - continue; - } - float depthWeight = 1.0; - if (_372.hasDepthTexture == 1) - { - float sampleDepthRaw = DepthTexture.sample(DepthTextureSmplr, sampleCoord).x; - float sampleDepth = LinearizeDepth(sampleDepthRaw, _849); - float depthDelta = abs(sampleDepth - centerDepth); - depthWeight = 1.0 - smoothstep(depthSoftness, depthSoftness * 2.5, depthDelta); - if (depthWeight <= 0.0) - { - continue; - } - } - float4 sampled = sampleColor(sampleCoord, _372, _381, _394, _403, _411, _419, _426, Texture, TextureSmplr); - sampled = composeLighting(sampleCoord, sampled, _372, _381, _394, _403, _411, _419, _426, BrightTexture, BrightTextureSmplr, VolumetricLightTexture, VolumetricLightTextureSmplr, SSRTexture, SSRTextureSmplr); - float gaussian = exp((-4.0) * t * t); - float weight = gaussian * depthWeight; - result += (sampled * weight); - totalWeight += weight; - } - if (totalWeight > 0.0) - { - return result / float4(totalWeight); - } - return fallbackColor; -} - -static inline __attribute__((always_inline)) -float3 sampleLUT(thread const float3& rgb, thread const float& blueSlice, thread const float& sliceSize, thread const float& slicePixelOffset, constant PushConstants& _372, texture2d LUTTexture, sampler LUTTextureSmplr) -{ - float sliceY = floor(blueSlice / _372.lutSize); - float sliceX = mod(blueSlice, _372.lutSize); - float2 uv; - uv.x = ((sliceX * sliceSize) + slicePixelOffset) + (rgb.x * sliceSize); - uv.y = ((sliceY * sliceSize) + slicePixelOffset) + (rgb.y * sliceSize); - return LUTTexture.sample(LUTTextureSmplr, uv).xyz; -} - -static inline __attribute__((always_inline)) -float4 mapToLUT(thread const float4& color, constant PushConstants& _372, texture2d LUTTexture, sampler LUTTextureSmplr) -{ - if (_372.hasLUTTexture != 1) - { - return color; - } - float sliceSize = 1.0 / _372.lutSize; - float slicePixelOffset = sliceSize * 0.5; - float blueIndex = color.z * (_372.lutSize - 1.0); - float sliceLow = floor(blueIndex); - float sliceHigh = fast::min(sliceLow + 1.0, _372.lutSize - 1.0); - float t = blueIndex - sliceLow; - float3 param = color.xyz; - float param_1 = sliceLow; - float param_2 = sliceSize; - float param_3 = slicePixelOffset; - float3 lowColor = sampleLUT(param, param_1, param_2, param_3, _372, LUTTexture, LUTTextureSmplr); - float3 param_4 = color.xyz; - float param_5 = sliceHigh; - float param_6 = sliceSize; - float param_7 = slicePixelOffset; - float3 highColor = sampleLUT(param_4, param_5, param_6, param_7, _372, LUTTexture, LUTTextureSmplr); - float3 finalRGB = mix(lowColor, highColor, float3(t)); - return float4(finalRGB, color.w); -} - -static inline __attribute__((always_inline)) -float3 acesToneMapping(thread const float3& color) -{ - float a = 2.5099999904632568359375; - float b = 0.02999999932944774627685546875; - float c = 2.4300000667572021484375; - float d = 0.589999973773956298828125; - float e = 0.14000000059604644775390625; - return fast::clamp((color * ((color * a) + float3(b))) / ((color * ((color * c) + float3(d))) + float3(e)), float3(0.0), float3(1.0)); -} - -fragment main0_out main0(main0_in in [[stage_in]], constant PushConstants& _372 [[buffer(0)]], device EffectBuffer& _381 [[buffer(1)]], device EffectFloat1Buffer& _394 [[buffer(2)]], device EffectFloat2Buffer& _403 [[buffer(3)]], device EffectFloat3Buffer& _411 [[buffer(4)]], device EffectFloat4Buffer& _419 [[buffer(5)]], device EffectFloat5Buffer& _426 [[buffer(6)]], constant Uniforms& _849 [[buffer(7)]], device EffectFloat6Buffer& _1049 [[buffer(8)]], constant Clouds& _1929 [[buffer(9)]], constant Environment& environment [[buffer(10)]], texture2d Texture [[texture(0)]], texture2d BrightTexture [[texture(1)]], texture2d VolumetricLightTexture [[texture(2)]], texture2d SSRTexture [[texture(3)]], texture2d PositionTexture [[texture(4)]], texture2d LUTTexture [[texture(5)]], texture3d cloudsTexture [[texture(6)]], texture2d DepthTexture [[texture(7)]], sampler TextureSmplr [[sampler(0)]], sampler BrightTextureSmplr [[sampler(1)]], sampler VolumetricLightTextureSmplr [[sampler(2)]], sampler SSRTextureSmplr [[sampler(3)]], sampler PositionTextureSmplr [[sampler(4)]], sampler LUTTextureSmplr [[sampler(5)]], sampler cloudsTextureSmplr [[sampler(6)]], sampler DepthTextureSmplr [[sampler(7)]], float4 gl_FragCoord [[position]]) -{ - main0_out out = {}; - float2 param = in.TexCoord; - float4 color = sampleColor(param, _372, _381, _394, _403, _411, _419, _426, Texture, TextureSmplr); - float depth = 1.0; - if (_372.hasDepthTexture == 1) - { - depth = DepthTexture.sample(DepthTextureSmplr, in.TexCoord).x; - } - float2 param_1 = in.TexCoord; - float param_2 = depth; - float3 viewPos = reconstructViewPos(param_1, param_2, _849); - float _distance = _372.hasDepthTexture == 1 ? length(viewPos) : _849.farPlane; - bool useMotionBlur = false; - float motionBlurSize = 0.0; - float motionBlurSeparation = 0.0; - for (int i = 0; i < _372.EffectCount; i++) - { - if (_381.Effects[i] == 6) - { - useMotionBlur = true; - motionBlurSize = _394.EffectFloat1[i]; - motionBlurSeparation = _403.EffectFloat2[i]; - } - } - for (int i_1 = 0; i_1 < _372.EffectCount; i_1++) - { - if (_381.Effects[i_1] == 2) - { - color = sharpen(Texture, TextureSmplr, in.TexCoord); - } - else - { - if (_381.Effects[i_1] == 3) - { - float radius = _394.EffectFloat1[i_1]; - float param_3 = radius; - color = blur(Texture, TextureSmplr, param_3, in.TexCoord); - } - else - { - if (_381.Effects[i_1] == 4) - { - color = edgeDetection(Texture, TextureSmplr, in.TexCoord); - } - } - } - } - float2 param_4 = in.TexCoord; - color = applyFXAA(Texture, TextureSmplr, param_4, _372, _381, _394, _403, _411, _419, _426, Texture, TextureSmplr); - float4 param_5 = color; - float4 _2637 = applyColorEffects(param_5, _372, _381, _394, _403, _411, _419, _426, _849, _1049, gl_FragCoord); - color = _2637; - if (_372.hasDepthTexture == 1) - { - float depthValue = DepthTexture.sample(DepthTextureSmplr, in.TexCoord).x; - float param_6 = depthValue; - float linearDepth = LinearizeDepth(param_6, _849); - float coc = fast::clamp(abs(linearDepth - _849.focusDepth) / _849.focusRange, 0.0, 1.0); - float mip = (coc * float(_849.maxMipLevel)) * 1.2000000476837158203125; - float4 param_7 = Texture.sample(TextureSmplr, in.TexCoord, level(mip)); - float4 _2676 = applyColorEffects(param_7, _372, _381, _394, _403, _411, _419, _426, _849, _1049, gl_FragCoord); - float3 blurred = _2676.xyz; - float3 sharp = color.xyz; - float4 param_8 = color; - color = cloudRendering(param_8, in.TexCoord, _372, _849, _1929, cloudsTexture, cloudsTextureSmplr, DepthTexture, DepthTextureSmplr); - } - else - { - float4 param_9 = color; - color = cloudRendering(param_9, in.TexCoord, _372, _849, _1929, cloudsTexture, cloudsTextureSmplr, DepthTexture, DepthTextureSmplr); - } - float4 hdrColor; - if (useMotionBlur) - { - float2 param_10 = in.TexCoord; - float param_11 = motionBlurSize; - float param_12 = motionBlurSeparation; - float4 param_13 = color; - float4 motionBlurred = applyMotionBlur(param_10, param_11, param_12, param_13, _372, _381, _394, _403, _411, _419, _426, Texture, TextureSmplr, BrightTexture, BrightTextureSmplr, _849, VolumetricLightTexture, VolumetricLightTextureSmplr, SSRTexture, SSRTextureSmplr, PositionTexture, PositionTextureSmplr, DepthTexture, DepthTextureSmplr); - out.FragColor = motionBlurred; - return out; - } - else - { - float2 param_14 = in.TexCoord; - float4 param_15 = color; - hdrColor = composeLighting(param_14, param_15, _372, _381, _394, _403, _411, _419, _426, BrightTexture, BrightTextureSmplr, VolumetricLightTexture, VolumetricLightTextureSmplr, SSRTexture, SSRTextureSmplr); - } - float4 param_16 = hdrColor; - hdrColor = mapToLUT(param_16, _372, LUTTexture, LUTTextureSmplr); - float3 param_17 = hdrColor.xyz; - float3 _2744 = acesToneMapping(param_17); - hdrColor.x = _2744.x; - hdrColor.y = _2744.y; - hdrColor.z = _2744.z; - float fogFactor = 1.0 - exp((-_distance) * environment.fogIntensity); - float3 finalColor = mix(hdrColor.xyz, float3(environment.fogColor), float3(fogFactor)); - out.FragColor = float4(finalColor, 1.0); - return out; -} diff --git a/shaders/metal/fullscreen.vert.metal b/shaders/metal/fullscreen.vert.metal deleted file mode 100644 index dd8f0cc0..00000000 --- a/shaders/metal/fullscreen.vert.metal +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include - -using namespace metal; - -struct main0_out -{ - float2 TexCoord [[user(locn0)]]; - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; - float2 aTexCoord [[attribute(2)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]]) -{ - main0_out out = {}; - out.gl_Position = float4(in.aPos.xy, 0.0, 1.0); - out.TexCoord = in.aTexCoord; - return out; -} - diff --git a/shaders/metal/main.frag.metal b/shaders/metal/main.frag.metal deleted file mode 100644 index 229e3702..00000000 --- a/shaders/metal/main.frag.metal +++ /dev/null @@ -1,1263 +0,0 @@ -#pragma clang diagnostic ignored "-Wmissing-prototypes" -#pragma clang diagnostic ignored "-Wmissing-braces" - -#include -#include - -using namespace metal; - -template -struct spvUnsafeArray -{ - T elements[Num ? Num : 1]; - - thread T& operator [] (size_t pos) thread - { - return elements[pos]; - } - constexpr const thread T& operator [] (size_t pos) const thread - { - return elements[pos]; - } - - device T& operator [] (size_t pos) device - { - return elements[pos]; - } - constexpr const device T& operator [] (size_t pos) const device - { - return elements[pos]; - } - - constexpr const constant T& operator [] (size_t pos) const constant - { - return elements[pos]; - } - - threadgroup T& operator [] (size_t pos) threadgroup - { - return elements[pos]; - } - constexpr const threadgroup T& operator [] (size_t pos) const threadgroup - { - return elements[pos]; - } -}; - -// Implementation of the GLSL radians() function -template -inline T radians(T d) -{ - return d * T(0.01745329251); -} - -static inline __attribute__((always_inline)) -float spvDet2x2(float a1, float a2, float b1, float b2) -{ - return a1 * b2 - b1 * a2; -} - -static inline __attribute__((always_inline)) -float spvDet3x3(float a1, float a2, float a3, float b1, float b2, float b3, float c1, float c2, float c3) -{ - return a1 * spvDet2x2(b2, b3, c2, c3) - b1 * spvDet2x2(a2, a3, c2, c3) + c1 * spvDet2x2(a2, a3, b2, b3); -} - -static inline __attribute__((always_inline)) -float4x4 spvInverse4x4(float4x4 m) -{ - float4x4 adj; - adj[0][0] = spvDet3x3(m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], m[2][3], m[3][1], m[3][2], m[3][3]); - adj[0][1] = -spvDet3x3(m[0][1], m[0][2], m[0][3], m[2][1], m[2][2], m[2][3], m[3][1], m[3][2], m[3][3]); - adj[0][2] = spvDet3x3(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], m[3][1], m[3][2], m[3][3]); - adj[0][3] = -spvDet3x3(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], m[2][3]); - adj[1][0] = -spvDet3x3(m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][2], m[3][3]); - adj[1][1] = spvDet3x3(m[0][0], m[0][2], m[0][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][2], m[3][3]); - adj[1][2] = -spvDet3x3(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], m[3][0], m[3][2], m[3][3]); - adj[1][3] = spvDet3x3(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], m[2][3]); - adj[2][0] = spvDet3x3(m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], m[2][3], m[3][0], m[3][1], m[3][3]); - adj[2][1] = -spvDet3x3(m[0][0], m[0][1], m[0][3], m[2][0], m[2][1], m[2][3], m[3][0], m[3][1], m[3][3]); - adj[2][2] = spvDet3x3(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], m[3][0], m[3][1], m[3][3]); - adj[2][3] = -spvDet3x3(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], m[2][3]); - adj[3][0] = -spvDet3x3(m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2], m[3][0], m[3][1], m[3][2]); - adj[3][1] = spvDet3x3(m[0][0], m[0][1], m[0][2], m[2][0], m[2][1], m[2][2], m[3][0], m[3][1], m[3][2]); - adj[3][2] = -spvDet3x3(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[3][0], m[3][1], m[3][2]); - adj[3][3] = spvDet3x3(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2]); - float det = (adj[0][0] * m[0][0]) + (adj[0][1] * m[1][0]) + (adj[0][2] * m[2][0]) + (adj[0][3] * m[3][0]); - return (det != 0.0f) ? (adj * (1.0f / det)) : m; -} - -struct ShadowParameters -{ - float4x4 lightView; - float4x4 lightProjection; - float bias0; - int textureIndex; - float farPlane; - float _pad1; - float3 lightPos; - int lightType; -}; - -struct Uniforms -{ - int4 textureTypes[16]; - int textureCount; - float3 cameraPosition; - float normalMapStrength; - uint useNormalMap; - float2 textureScale; - float2 textureOffset; -}; - -struct Environment -{ - float rimLightIntensity; - float3 rimLightColor; -}; - -struct PushConstants -{ - uint useTexture; - uint useColor; - uint useIBL; - int directionalLightCount; - int pointLightCount; - int spotlightCount; - int areaLightCount; - int shadowParamCount; -}; - -struct DirectionalLight -{ - packed_float3 direction; - float _pad1; - packed_float3 diffuse; - float _pad2; - packed_float3 specular; - float intensity; -}; - -struct DirectionalLightsUBO -{ - spvUnsafeArray directionalLights; -}; - -struct PointLight -{ - packed_float3 position; - float _pad1; - packed_float3 diffuse; - float _pad2; - packed_float3 specular; - float intensity; - float constant0; - float linear; - float quadratic; - float radius; - float _pad3; -}; - -struct PointLightsUBO -{ - spvUnsafeArray pointLights; -}; - -struct SpotLight -{ - packed_float3 position; - float _pad1; - packed_float3 direction; - float cutOff; - float outerCutOff; - float intensity; - float range; - float _pad4; - packed_float3 diffuse; - float _pad5; - packed_float3 specular; - float _pad6; -}; - -struct SpotLightsUBO -{ - spvUnsafeArray spotlights; -}; - -struct Material -{ - packed_float3 albedo; - float metallic; - float roughness; - float ao; - float reflectivity; -}; - -struct ShadowParameters_1 -{ - float4x4 lightView; - float4x4 lightProjection; - float bias0; - int textureIndex; - float farPlane; - float _pad1; - packed_float3 lightPos; - int lightType; -}; - -struct ShadowParametersUBO -{ - spvUnsafeArray shadowParams; -}; - -struct AreaLight -{ - packed_float3 position; - float _pad1; - packed_float3 right; - float _pad2; - packed_float3 up; - float _pad3; - float2 size; - float _pad4; - float _pad5; - packed_float3 diffuse; - float _pad6; - packed_float3 specular; - float angle; - int castsBothSides; - float intensity; - float range; - float _pad9; -}; - -struct AreaLightsUBO -{ - spvUnsafeArray areaLights; -}; - -struct AmbientLight -{ - float4 color; - float intensity; - float3 _pad0; -}; - -constant spvUnsafeArray _1657 = spvUnsafeArray({ float3(0.5381000041961669921875, 0.18559999763965606689453125, -0.4318999946117401123046875), float3(0.13789999485015869140625, 0.248600006103515625, 0.4429999887943267822265625), float3(0.3370999991893768310546875, 0.567900002002716064453125, -0.0057000000961124897003173828125), float3(-0.699899971485137939453125, -0.0450999997556209564208984375, -0.0019000000320374965667724609375), float3(0.068899996578693389892578125, -0.159799993038177490234375, -0.854700028896331787109375), float3(0.056000001728534698486328125, 0.0068999999202787876129150390625, -0.184300005435943603515625), float3(-0.014600000344216823577880859375, 0.14020000398159027099609375, 0.076200000941753387451171875), float3(0.00999999977648258209228515625, -0.19239999353885650634765625, -0.03440000116825103759765625), float3(-0.35769999027252197265625, -0.53009998798370361328125, -0.4357999861240386962890625), float3(-0.3169000148773193359375, 0.10629999637603759765625, 0.015799999237060546875), float3(0.010300000198185443878173828125, -0.5868999958038330078125, 0.0046000001020729541778564453125), float3(-0.08969999849796295166015625, -0.4939999878406524658203125, 0.328700006008148193359375), float3(0.7118999958038330078125, -0.015399999916553497314453125, -0.091799996793270111083984375), float3(-0.053300000727176666259765625, 0.0595999993383884429931640625, -0.541100025177001953125), float3(0.03519999980926513671875, -0.063100002706050872802734375, 0.546000003814697265625), float3(-0.4776000082492828369140625, 0.2847000062465667724609375, -0.0271000005304813385009765625), float3(-0.11200000345706939697265625, 0.1234000027179718017578125, -0.744599997997283935546875), float3(-0.212999999523162841796875, -0.07819999754428863525390625, -0.13789999485015869140625), float3(0.2944000065326690673828125, -0.3111999928951263427734375, -0.2644999921321868896484375), float3(-0.4564000070095062255859375, 0.4174999892711639404296875, -0.184300005435943603515625), float3(0.1234000027179718017578125, -0.567799985408782958984375, 0.788999974727630615234375), float3(-0.6789000034332275390625, 0.23450000584125518798828125, -0.4566999971866607666015625), float3(0.34560000896453857421875, -0.788999974727630615234375, 0.1234000027179718017578125), float3(-0.23450000584125518798828125, 0.567799985408782958984375, -0.6789000034332275390625), float3(0.788999974727630615234375, 0.1234000027179718017578125, 0.567799985408782958984375), float3(-0.567799985408782958984375, -0.6789000034332275390625, 0.23450000584125518798828125), float3(0.4566999971866607666015625, 0.788999974727630615234375, -0.23450000584125518798828125), float3(-0.788999974727630615234375, 0.34560000896453857421875, -0.567799985408782958984375), float3(0.6789000034332275390625, -0.23450000584125518798828125, 0.788999974727630615234375), float3(-0.1234000027179718017578125, 0.6789000034332275390625, -0.4566999971866607666015625), float3(0.23450000584125518798828125, -0.567799985408782958984375, 0.6789000034332275390625), float3(-0.34560000896453857421875, 0.788999974727630615234375, -0.1234000027179718017578125), float3(0.567799985408782958984375, 0.23450000584125518798828125, -0.788999974727630615234375), float3(-0.6789000034332275390625, -0.567799985408782958984375, 0.34560000896453857421875), float3(0.788999974727630615234375, -0.34560000896453857421875, 0.4566999971866607666015625), float3(-0.23450000584125518798828125, 0.1234000027179718017578125, -0.6789000034332275390625), float3(0.4566999971866607666015625, 0.788999974727630615234375, -0.567799985408782958984375), float3(-0.567799985408782958984375, 0.23450000584125518798828125, 0.6789000034332275390625), float3(0.34560000896453857421875, -0.788999974727630615234375, -0.1234000027179718017578125), float3(-0.788999974727630615234375, 0.567799985408782958984375, -0.23450000584125518798828125), float3(0.6789000034332275390625, -0.1234000027179718017578125, 0.34560000896453857421875), float3(-0.4566999971866607666015625, 0.788999974727630615234375, 0.23450000584125518798828125), float3(0.567799985408782958984375, -0.6789000034332275390625, 0.788999974727630615234375), float3(-0.34560000896453857421875, 0.567799985408782958984375, -0.6789000034332275390625), float3(0.23450000584125518798828125, -0.788999974727630615234375, 0.567799985408782958984375), float3(-0.6789000034332275390625, 0.23450000584125518798828125, -0.1234000027179718017578125), float3(0.788999974727630615234375, -0.34560000896453857421875, -0.567799985408782958984375), float3(-0.567799985408782958984375, 0.6789000034332275390625, 0.23450000584125518798828125), float3(0.4566999971866607666015625, -0.788999974727630615234375, 0.34560000896453857421875), float3(-0.23450000584125518798828125, 0.1234000027179718017578125, -0.788999974727630615234375), float3(0.34560000896453857421875, -0.567799985408782958984375, 0.6789000034332275390625), float3(-0.788999974727630615234375, 0.4566999971866607666015625, -0.34560000896453857421875), float3(0.6789000034332275390625, -0.1234000027179718017578125, -0.567799985408782958984375), float3(-0.4566999971866607666015625, 0.23450000584125518798828125, 0.788999974727630615234375) }); - -struct main0_out -{ - float4 FragColor [[color(0)]]; - float4 BrightColor [[color(1)]]; -}; - -struct main0_in -{ - float2 TexCoord [[user(locn0)]]; - float3 Normal [[user(locn2)]]; - float3 FragPos [[user(locn3)]]; - float3 TBN_0 [[user(locn4)]]; - float3 TBN_1 [[user(locn5)]]; - float3 TBN_2 [[user(locn6)]]; -}; - -static inline __attribute__((always_inline)) -float4 sampleTextureAt(thread const int& textureIndex, thread const float2& uv, texture2d texture1, sampler texture1Smplr, texture2d texture2, sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, texture2d texture4, sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, texture2d texture6, sampler texture6Smplr, texture2d texture7, sampler texture7Smplr, texture2d texture8, sampler texture8Smplr, texture2d texture9, sampler texture9Smplr, texture2d texture10, sampler texture10Smplr) -{ - if (textureIndex == 0) - { - return texture1.sample(texture1Smplr, uv); - } - else - { - if (textureIndex == 1) - { - return texture2.sample(texture2Smplr, uv); - } - else - { - if (textureIndex == 2) - { - return texture3.sample(texture3Smplr, uv); - } - else - { - if (textureIndex == 3) - { - return texture4.sample(texture4Smplr, uv); - } - else - { - if (textureIndex == 4) - { - return texture5.sample(texture5Smplr, uv); - } - else - { - if (textureIndex == 5) - { - return texture6.sample(texture6Smplr, uv); - } - else - { - if (textureIndex == 6) - { - return texture7.sample(texture7Smplr, uv); - } - else - { - if (textureIndex == 7) - { - return texture8.sample(texture8Smplr, uv); - } - else - { - if (textureIndex == 8) - { - return texture9.sample(texture9Smplr, uv); - } - else - { - if (textureIndex == 9) - { - return texture10.sample(texture10Smplr, uv); - } - } - } - } - } - } - } - } - } - } - return float4(0.0); -} - -static inline __attribute__((always_inline)) -float2 parallaxMapping(thread const float2& texCoords, thread const float3& viewDir, constant Uniforms& _163, texture2d texture1, sampler texture1Smplr, texture2d texture2, sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, texture2d texture4, sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, texture2d texture6, sampler texture6Smplr, texture2d texture7, sampler texture7Smplr, texture2d texture8, sampler texture8Smplr, texture2d texture9, sampler texture9Smplr, texture2d texture10, sampler texture10Smplr) -{ - float3 v = fast::normalize(viewDir); - float numLayers = mix(32.0, 8.0, abs(dot(float3(0.0, 0.0, 1.0), v))); - float layerDepth = 1.0 / numLayers; - float currentLayerDepth = 0.0; - float2 P = (v.xy / float2(fast::max(v.z, 0.0500000007450580596923828125))) * 0.039999999105930328369140625; - float2 deltaTexCoords = P / float2(numLayers); - float2 currentTexCoords = texCoords; - int textureIndex = -1; - for (int i = 0; i < _163.textureCount; i++) - { - if (_163.textureTypes[i].x == 6) - { - textureIndex = i; - break; - } - } - if (textureIndex == (-1)) - { - return texCoords; - } - int param = textureIndex; - float2 param_1 = currentTexCoords; - float currentDepthMapValue = 1.0 - sampleTextureAt(param, param_1, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr).x; - while (currentLayerDepth < currentDepthMapValue) - { - currentTexCoords -= deltaTexCoords; - int param_2 = textureIndex; - float2 param_3 = currentTexCoords; - currentDepthMapValue = 1.0 - sampleTextureAt(param_2, param_3, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr).x; - currentLayerDepth += layerDepth; - } - float2 prevTexCoords = currentTexCoords + deltaTexCoords; - float afterDepth = currentDepthMapValue - currentLayerDepth; - int param_4 = textureIndex; - float2 param_5 = prevTexCoords; - float beforeDepth = 1.0 - sampleTextureAt(param_4, param_5, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr).x - (currentLayerDepth - layerDepth); - float weight = afterDepth / (afterDepth - beforeDepth); - currentTexCoords = (prevTexCoords * weight) + (currentTexCoords * (1.0 - weight)); - return currentTexCoords; -} - -static inline __attribute__((always_inline)) -float4 enableTextures(thread const int& type, constant Uniforms& _163, texture2d texture1, sampler texture1Smplr, thread float2& texCoord, texture2d texture2, sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, texture2d texture4, sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, texture2d texture6, sampler texture6Smplr, texture2d texture7, sampler texture7Smplr, texture2d texture8, sampler texture8Smplr, texture2d texture9, sampler texture9Smplr, texture2d texture10, sampler texture10Smplr) -{ - float4 color = float4(0.0); - int count = 0; - for (int i = 0; i < _163.textureCount; i++) - { - if (_163.textureTypes[i].x == type) - { - if (i == 0) - { - color += texture1.sample(texture1Smplr, texCoord); - } - else - { - if (i == 1) - { - color += texture2.sample(texture2Smplr, texCoord); - } - else - { - if (i == 2) - { - color += texture3.sample(texture3Smplr, texCoord); - } - else - { - if (i == 3) - { - color += texture4.sample(texture4Smplr, texCoord); - } - else - { - if (i == 4) - { - color += texture5.sample(texture5Smplr, texCoord); - } - else - { - if (i == 5) - { - color += texture6.sample(texture6Smplr, texCoord); - } - else - { - if (i == 6) - { - color += texture7.sample(texture7Smplr, texCoord); - } - else - { - if (i == 7) - { - color += texture8.sample(texture8Smplr, texCoord); - } - else - { - if (i == 8) - { - color += texture9.sample(texture9Smplr, texCoord); - } - else - { - if (i == 9) - { - color += texture10.sample(texture10Smplr, texCoord); - } - } - } - } - } - } - } - } - } - } - count++; - } - } - if (count > 0) - { - color /= float4(float(count)); - } - if (count == 0) - { - return float4(-1.0); - } - return color; -} - -static inline __attribute__((always_inline)) -float2 getTextureDimensions(thread const int& textureIndex, texture2d texture1, sampler texture1Smplr, texture2d texture2, sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, texture2d texture4, sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, texture2d texture6, sampler texture6Smplr, texture2d texture7, sampler texture7Smplr, texture2d texture8, sampler texture8Smplr, texture2d texture9, sampler texture9Smplr, texture2d texture10, sampler texture10Smplr) -{ - if (textureIndex == 0) - { - return float2(int2(texture1.get_width(), texture1.get_height())); - } - else - { - if (textureIndex == 1) - { - return float2(int2(texture2.get_width(), texture2.get_height())); - } - else - { - if (textureIndex == 2) - { - return float2(int2(texture3.get_width(), texture3.get_height())); - } - else - { - if (textureIndex == 3) - { - return float2(int2(texture4.get_width(), texture4.get_height())); - } - else - { - if (textureIndex == 4) - { - return float2(int2(texture5.get_width(), texture5.get_height())); - } - else - { - if (textureIndex == 5) - { - return float2(int2(texture6.get_width(), texture6.get_height())); - } - else - { - if (textureIndex == 6) - { - return float2(int2(texture7.get_width(), texture7.get_height())); - } - else - { - if (textureIndex == 7) - { - return float2(int2(texture8.get_width(), texture8.get_height())); - } - else - { - if (textureIndex == 8) - { - return float2(int2(texture9.get_width(), texture9.get_height())); - } - else - { - if (textureIndex == 9) - { - return float2(int2(texture10.get_width(), texture10.get_height())); - } - } - } - } - } - } - } - } - } - } - return float2(0.0); -} - -static inline __attribute__((always_inline)) -float calculateShadow(thread const ShadowParameters& shadowParam, thread const float4& fragPosLightSpace, constant Uniforms& _163, texture2d texture1, sampler texture1Smplr, texture2d texture2, sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, texture2d texture4, sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, texture2d texture6, sampler texture6Smplr, texture2d texture7, sampler texture7Smplr, texture2d texture8, sampler texture8Smplr, texture2d texture9, sampler texture9Smplr, texture2d texture10, sampler texture10Smplr, device DirectionalLightsUBO& _1083, thread float3& Normal, thread float3& FragPos) -{ - float3 projCoords = fragPosLightSpace.xyz / float3(fragPosLightSpace.w); - projCoords = (projCoords * 0.5) + float3(0.5); - bool _1362 = projCoords.x < 0.0; - bool _1369; - if (!_1362) - { - _1369 = projCoords.x > 1.0; - } - else - { - _1369 = _1362; - } - bool _1376; - if (!_1369) - { - _1376 = projCoords.y < 0.0; - } - else - { - _1376 = _1369; - } - bool _1383; - if (!_1376) - { - _1383 = projCoords.y > 1.0; - } - else - { - _1383 = _1376; - } - bool _1390; - if (!_1383) - { - _1390 = projCoords.z < 0.0; - } - else - { - _1390 = _1383; - } - bool _1398; - if (!_1390) - { - _1398 = projCoords.z > 1.0; - } - else - { - _1398 = _1390; - } - if (_1398) - { - return 0.0; - } - float currentDepth = projCoords.z; - float3 lightDir = fast::normalize(-(spvInverse4x4(shadowParam.lightView) * float4(0.0, 0.0, -1.0, 0.0)).xyz); - float3 normal = fast::normalize(Normal); - float biasValue = shadowParam.bias0; - float bias0 = fast::max(biasValue * (1.0 - dot(normal, lightDir)), biasValue); - float shadow = 0.0; - int param = shadowParam.textureIndex; - float2 texelSize = float2(1.0) / getTextureDimensions(param, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - float _distance = length(_163.cameraPosition - FragPos); - int kernelSize = int(mix(1.0, 3.0, fast::clamp(_distance / 100.0, 0.0, 1.0))); - int sampleCount = 0; - int _1444 = -kernelSize; - for (int x = _1444; x <= kernelSize; x++) - { - int _1455 = -kernelSize; - for (int y = _1455; y <= kernelSize; y++) - { - int param_1 = shadowParam.textureIndex; - float2 param_2 = projCoords.xy + (float2(float(x), float(y)) * texelSize); - float pcfDepth = sampleTextureAt(param_1, param_2, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr).x; - shadow += float((currentDepth - bias0) > pcfDepth); - sampleCount++; - } - } - shadow /= float(sampleCount); - return shadow; -} - -static inline __attribute__((always_inline)) -float4 sampleCubeTextureAt(thread const int& textureIndex, thread const float3& direction, texturecube cubeMap1, sampler cubeMap1Smplr, texturecube cubeMap2, sampler cubeMap2Smplr, texturecube cubeMap3, sampler cubeMap3Smplr, texturecube cubeMap4, sampler cubeMap4Smplr, texturecube cubeMap5, sampler cubeMap5Smplr) -{ - if (textureIndex == 0) - { - return cubeMap1.sample(cubeMap1Smplr, direction); - } - else - { - if (textureIndex == 1) - { - return cubeMap2.sample(cubeMap2Smplr, direction); - } - else - { - if (textureIndex == 2) - { - return cubeMap3.sample(cubeMap3Smplr, direction); - } - else - { - if (textureIndex == 3) - { - return cubeMap4.sample(cubeMap4Smplr, direction); - } - else - { - if (textureIndex == 4) - { - return cubeMap5.sample(cubeMap5Smplr, direction); - } - } - } - } - } - return float4(0.0); -} - -static inline __attribute__((always_inline)) -float calculatePointShadow(thread const ShadowParameters& shadowParam, thread const float3& fragPos, texturecube cubeMap1, sampler cubeMap1Smplr, texturecube cubeMap2, sampler cubeMap2Smplr, texturecube cubeMap3, sampler cubeMap3Smplr, texturecube cubeMap4, sampler cubeMap4Smplr, texturecube cubeMap5, sampler cubeMap5Smplr) -{ - float3 fragToLight = fragPos - shadowParam.lightPos; - float currentDepth = length(fragToLight); - float bias0 = 0.0500000007450580596923828125; - float shadow = 0.0; - float diskRadius = (1.0 + (currentDepth / shadowParam.farPlane)) * 0.0500000007450580596923828125; - for (int i = 0; i < 54; i++) - { - float3 sampleDir = fast::normalize(fragToLight + (_1657[i] * diskRadius)); - int param = shadowParam.textureIndex; - float3 param_1 = sampleDir; - float closestDepth = sampleCubeTextureAt(param, param_1, cubeMap1, cubeMap1Smplr, cubeMap2, cubeMap2Smplr, cubeMap3, cubeMap3Smplr, cubeMap4, cubeMap4Smplr, cubeMap5, cubeMap5Smplr).x * shadowParam.farPlane; - if ((currentDepth - bias0) > closestDepth) - { - shadow += 1.0; - } - } - shadow /= 54.0; - return shadow; -} - -static inline __attribute__((always_inline)) -float distributionGGX(thread const float3& N, thread const float3& H, thread const float& roughness) -{ - float a = roughness * roughness; - float a2 = a * a; - float NdotH = fast::max(dot(N, H), 0.0); - float NdotH2 = NdotH * NdotH; - float num = a2; - float denom = (NdotH2 * (a2 - 1.0)) + 1.0; - denom = (3.1415927410125732421875 * denom) * denom; - return num / denom; -} - -static inline __attribute__((always_inline)) -float geometrySchlickGGX(thread const float& NdotV, thread const float& roughness) -{ - float r = roughness + 1.0; - float k = (r * r) / 8.0; - float num = NdotV; - float denom = (NdotV * (1.0 - k)) + k; - return num / denom; -} - -static inline __attribute__((always_inline)) -float geometrySmith(thread const float3& N, thread const float3& V, thread const float3& L, thread const float& roughness) -{ - float NdotV = fast::max(dot(N, V), 0.0); - float NdotL = fast::max(dot(N, L), 0.0); - float param = NdotV; - float param_1 = roughness; - float ggx2 = geometrySchlickGGX(param, param_1); - float param_2 = NdotL; - float param_3 = roughness; - float ggx1 = geometrySchlickGGX(param_2, param_3); - return ggx1 * ggx2; -} - -static inline __attribute__((always_inline)) -float3 fresnelSchlick(thread const float& cosTheta, thread const float3& F0) -{ - return F0 + ((float3(1.0) - F0) * powr(1.0 - cosTheta, 5.0)); -} - -static inline __attribute__((always_inline)) -float3 calculatePBR(thread const float3& N, thread const float3& V, thread const float3& L, thread const float3& F0, thread const float3& radiance, thread const float3& albedo, thread const float& metallic, thread const float& roughness, thread const float& reflectivity) -{ - float3 H = fast::normalize(V + L); - float3 param = N; - float3 param_1 = H; - float param_2 = roughness; - float NDF = distributionGGX(param, param_1, param_2); - float3 param_3 = N; - float3 param_4 = V; - float3 param_5 = L; - float param_6 = roughness; - float G = geometrySmith(param_3, param_4, param_5, param_6); - float param_7 = fast::max(dot(H, V), 0.0); - float3 param_8 = F0; - float3 F = fresnelSchlick(param_7, param_8); - float3 kS = F; - float3 kD = float3(1.0) - kS; - kD *= (1.0 - metallic); - float3 numerator = F * (NDF * G); - float denominator = ((4.0 * fast::max(dot(N, V), 0.0)) * fast::max(dot(N, L), 0.0)) + 9.9999997473787516355514526367188e-05; - float3 specular = numerator / float3(denominator); - float NdotL = fast::max(dot(N, L), 0.0); - float3 Lo = ((((kD * albedo) / float3(3.1415927410125732421875)) + specular) * radiance) * NdotL; - return Lo; -} - -static inline __attribute__((always_inline)) -float3 calcAllDirectionalLights(thread const float3& N, thread const float3& V, thread const float3& albedo, thread const float& metallic, thread const float& roughness, thread const float3& F0, thread const float& reflectivity, constant PushConstants& _1073, device DirectionalLightsUBO& _1083) -{ - float3 Lo = float3(0.0); - for (int i = 0; i < _1073.directionalLightCount; i++) - { - float3 L = fast::normalize(-float3(_1083.directionalLights[i].direction)); - float3 radiance = float3(_1083.directionalLights[i].diffuse) * fast::max(_1083.directionalLights[i].intensity, 0.0); - float3 param = N; - float3 param_1 = V; - float3 param_2 = L; - float3 param_3 = F0; - float3 param_4 = radiance; - float3 param_5 = albedo; - float param_6 = metallic; - float param_7 = roughness; - float param_8 = reflectivity; - Lo += calculatePBR(param, param_1, param_2, param_3, param_4, param_5, param_6, param_7, param_8); - } - return Lo; -} - -static inline __attribute__((always_inline)) -float3 calcAllPointLights(thread const float3& fragPos, thread const float3& N, thread const float3& V, thread const float3& albedo, thread const float& metallic, thread const float& roughness, thread const float3& F0, thread const float& reflectivity, constant PushConstants& _1073, device PointLightsUBO& _1136) -{ - float3 Lo = float3(0.0); - for (int i = 0; i < _1073.pointLightCount; i++) - { - float3 L = float3(_1136.pointLights[i].position) - fragPos; - float _distance = length(L); - _distance = fast::max(_distance, 0.001000000047497451305389404296875); - L = fast::normalize(L); - float range = fast::max(_1136.pointLights[i].radius, 0.001000000047497451305389404296875); - float3 radiance = float3(_1136.pointLights[i].diffuse) * fast::max(_1136.pointLights[i].intensity, 0.0); - float attenuation = 1.0 / ((1.0 + (_distance / range)) + ((_distance * _distance) / (range * range))); - float fade = 1.0 - smoothstep(range * 0.89999997615814208984375, range, _distance); - float3 radianceAttenuated = radiance * attenuation; - radianceAttenuated *= fade; - float3 H = fast::normalize(V + L); - float3 param = N; - float3 param_1 = H; - float param_2 = roughness; - float NDF = distributionGGX(param, param_1, param_2); - float3 param_3 = N; - float3 param_4 = V; - float3 param_5 = L; - float param_6 = roughness; - float G = geometrySmith(param_3, param_4, param_5, param_6); - float param_7 = fast::max(dot(H, V), 0.0); - float3 param_8 = F0; - float3 F = fresnelSchlick(param_7, param_8); - float3 kS = F; - float3 kD = float3(1.0) - kS; - kD *= (1.0 - metallic); - float3 numerator = F * (NDF * G); - float denominator = ((4.0 * fast::max(dot(N, V), 0.0)) * fast::max(dot(N, L), 0.0)) + 9.9999997473787516355514526367188e-05; - float3 specular = numerator / float3(denominator); - float NdotL = fast::max(dot(N, L), 0.0); - Lo += (((((kD * albedo) / float3(3.1415927410125732421875)) + specular) * radianceAttenuated) * NdotL); - } - return Lo; -} - -static inline __attribute__((always_inline)) -float3 calcAllSpotLights(thread const float3& N, thread const float3& fragPos, thread const float3& L, thread const float3& viewDir, thread const float3& albedo, thread const float& metallic, thread const float& roughness, thread const float3& F0, thread const float& reflectivity, constant PushConstants& _1073, device SpotLightsUBO& _1268) -{ - float3 Lo = float3(0.0); - for (int i = 0; i < _1073.spotlightCount; i++) - { - float3 L_1 = fast::normalize(float3(_1268.spotlights[i].position) - fragPos); - float3 spotDirection = fast::normalize(float3(_1268.spotlights[i].direction)); - float theta = dot(L_1, -spotDirection); - float intensity = smoothstep(_1268.spotlights[i].outerCutOff, _1268.spotlights[i].cutOff, theta); - float _distance = length(float3(_1268.spotlights[i].position) - fragPos); - _distance = fast::max(_distance, 0.001000000047497451305389404296875); - float range = fast::max(_1268.spotlights[i].range, 0.001000000047497451305389404296875); - float attenuation = 1.0 / ((1.0 + (_distance / range)) + ((_distance * _distance) / (range * range))); - float fade = 1.0 - smoothstep(range * 0.89999997615814208984375, range, _distance); - float3 radiance = (((float3(_1268.spotlights[i].diffuse) * fast::max(_1268.spotlights[i].intensity, 0.0)) * attenuation) * intensity) * fade; - float3 param = N; - float3 param_1 = viewDir; - float3 param_2 = L_1; - float3 param_3 = F0; - float3 param_4 = radiance; - float3 param_5 = albedo; - float param_6 = metallic; - float param_7 = roughness; - float param_8 = reflectivity; - Lo += calculatePBR(param, param_1, param_2, param_3, param_4, param_5, param_6, param_7, param_8); - } - return Lo; -} - -static inline __attribute__((always_inline)) -float3 getRimLight(thread const float3& fragPos, thread float3& N, thread float3& V, thread const float3& F0, thread const float3& albedo, thread const float& metallic, thread const float& roughness, constant Uniforms& _163, constant Environment& environment) -{ - N = fast::normalize(N); - V = fast::normalize(V); - float rim = powr(1.0 - fast::max(dot(N, V), 0.0), 3.0); - rim *= mix(1.2000000476837158203125, 0.300000011920928955078125, roughness); - float3 rimColor = mix(float3(1.0), albedo, float3(metallic)) * environment.rimLightColor; - rimColor = mix(rimColor, F0, float3(0.5)); - float rimIntensity = environment.rimLightIntensity; - float3 rimLight = (rimColor * rim) * rimIntensity; - float dist = length(_163.cameraPosition - fragPos); - rimLight /= float3(1.0 + (dist * 0.100000001490116119384765625)); - return rimLight; -} - -static inline __attribute__((always_inline)) -float2 directionToEquirect(thread const float3& direction) -{ - float3 dir = fast::normalize(direction); - float phi = precise::atan2(dir.z, dir.x); - float theta = acos(fast::clamp(dir.y, -1.0, 1.0)); - return float2((phi + 3.1415927410125732421875) / 6.283185482025146484375, theta / 3.1415927410125732421875); -} - -static inline __attribute__((always_inline)) -float3 sampleHDRTexture(thread const int& textureIndex, thread const float3& direction, texture2d texture1, sampler texture1Smplr, texture2d texture2, sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, texture2d texture4, sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, texture2d texture6, sampler texture6Smplr, texture2d texture7, sampler texture7Smplr, texture2d texture8, sampler texture8Smplr, texture2d texture9, sampler texture9Smplr, texture2d texture10, sampler texture10Smplr) -{ - float3 param = direction; - float2 uv = directionToEquirect(param); - int param_1 = textureIndex; - float2 param_2 = uv; - return sampleTextureAt(param_1, param_2, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr).xyz; -} - -static inline __attribute__((always_inline)) -float3 sampleEnvironmentRadiance(thread const float3& direction, constant Uniforms& _163, texture2d texture1, sampler texture1Smplr, texture2d texture2, sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, texture2d texture4, sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, texture2d texture6, sampler texture6Smplr, texture2d texture7, sampler texture7Smplr, texture2d texture8, sampler texture8Smplr, texture2d texture9, sampler texture9Smplr, texture2d texture10, sampler texture10Smplr) -{ - float3 envColor = float3(0.0); - int count = 0; - for (int i = 0; i < _163.textureCount; i++) - { - if (_163.textureTypes[i].x == 13) - { - int param = i; - float3 param_1 = direction; - envColor += sampleHDRTexture(param, param_1, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - count++; - } - } - if (count == 0) - { - return float3(0.0); - } - return envColor / float3(float(count)); -} - -static inline __attribute__((always_inline)) -float3 acesToneMapping(thread float3& color) -{ - float a = 2.5099999904632568359375; - float b = 0.02999999932944774627685546875; - float c = 2.4300000667572021484375; - float d = 0.589999973773956298828125; - float e = 0.14000000059604644775390625; - color = (color * ((color * a) + float3(b))) / ((color * ((color * c) + float3(d))) + float3(e)); - color = powr(fast::clamp(color, float3(0.0), float3(1.0)), float3(0.4545454680919647216796875)); - return color; -} - -fragment main0_out main0(main0_in in [[stage_in]], constant Uniforms& _163 [[buffer(0)]], constant Environment& environment [[buffer(1)]], constant PushConstants& _1073 [[buffer(2)]], device DirectionalLightsUBO& _1083 [[buffer(3)]], device PointLightsUBO& _1136 [[buffer(4)]], device SpotLightsUBO& _1268 [[buffer(5)]], constant Material& material [[buffer(6)]], device ShadowParametersUBO& _1905 [[buffer(7)]], device AreaLightsUBO& _2058 [[buffer(8)]], constant AmbientLight& ambientLight [[buffer(9)]], texture2d texture1 [[texture(0)]], texture2d texture2 [[texture(1)]], texture2d texture3 [[texture(2)]], texture2d texture4 [[texture(3)]], texture2d texture5 [[texture(4)]], texture2d texture6 [[texture(5)]], texture2d texture7 [[texture(6)]], texture2d texture8 [[texture(7)]], texture2d texture9 [[texture(8)]], texture2d texture10 [[texture(9)]], texturecube cubeMap1 [[texture(10)]], texturecube cubeMap2 [[texture(11)]], texturecube cubeMap3 [[texture(12)]], texturecube cubeMap4 [[texture(13)]], texturecube cubeMap5 [[texture(14)]], sampler texture1Smplr [[sampler(0)]], sampler texture2Smplr [[sampler(1)]], sampler texture3Smplr [[sampler(2)]], sampler texture4Smplr [[sampler(3)]], sampler texture5Smplr [[sampler(4)]], sampler texture6Smplr [[sampler(5)]], sampler texture7Smplr [[sampler(6)]], sampler texture8Smplr [[sampler(7)]], sampler texture9Smplr [[sampler(8)]], sampler texture10Smplr [[sampler(9)]], sampler cubeMap1Smplr [[sampler(10)]], sampler cubeMap2Smplr [[sampler(11)]], sampler cubeMap3Smplr [[sampler(12)]], sampler cubeMap4Smplr [[sampler(13)]], sampler cubeMap5Smplr [[sampler(14)]]) -{ - main0_out out = {}; - float3x3 TBN = {}; - TBN[0] = in.TBN_0; - TBN[1] = in.TBN_1; - TBN[2] = in.TBN_2; - float2 texCoord = in.TexCoord * _163.textureScale + _163.textureOffset; - bool hasParallaxMap = false; - for (int i = 0; i < _163.textureCount; i++) - { - if (_163.textureTypes[i].x == 6) - { - hasParallaxMap = true; - break; - } - } - if (hasParallaxMap) - { - float3 tangentViewDir = fast::normalize(transpose(TBN) * (_163.cameraPosition - in.FragPos)); - float2 param = texCoord; - float3 param_1 = tangentViewDir; - texCoord = parallaxMapping(param, param_1, _163, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - } - int param_2 = 5; - float4 normTexture = enableTextures(param_2, _163, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - bool _1774 = normTexture.x != (-1.0); - bool _1780; - if (_1774) - { - _1780 = normTexture.y != (-1.0); - } - else - { - _1780 = _1774; - } - bool _1786; - if (_1780) - { - _1786 = normTexture.z != (-1.0); - } - else - { - _1786 = _1780; - } - float normalStrength = fast::max(_163.normalMapStrength, 0.0f); - bool useNormalMap = (_163.useNormalMap != 0u) && (normalStrength > 0.0f); - float3 N; - if (_1786 && useNormalMap) - { - float3 tangentNormal = (normTexture.xyz * 2.0) - float3(1.0); - tangentNormal.xy *= normalStrength; - tangentNormal = fast::normalize(tangentNormal); - N = fast::normalize(TBN * tangentNormal); - } - else - { - N = fast::normalize(in.Normal); - } - N = fast::normalize(N); - float3 V = fast::normalize(_163.cameraPosition - in.FragPos); - float3 albedo = float3(material.albedo); - int param_3 = 0; - float4 albedoTex = enableTextures(param_3, _163, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - if (any(albedoTex != float4(-1.0))) - { - albedo *= albedoTex.xyz; - } - int param_3a = 12; - float4 opacityTex = enableTextures(param_3a, _163, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - if (any(opacityTex != float4(-1.0))) - { - if (opacityTex.x < 0.100000001490116119384765625) - { - discard_fragment(); - } - } - else - { - if ((albedoTex.w < 0.100000001490116119384765625) && (material.albedo[3] < 0.999000012874603271484375)) - { - discard_fragment(); - } - } - int param_pbr_pack = 14; - float4 pbrPackTex = enableTextures(param_pbr_pack, _163, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - bool hasPbrPack = any(pbrPackTex != float4(-1.0)); - float metallic = material.metallic; - int param_4 = 9; - float4 metallicTex = enableTextures(param_4, _163, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - if (hasPbrPack) - { - metallic *= pbrPackTex.z; - } - else if (any(metallicTex != float4(-1.0))) - { - metallic *= metallicTex.x; - } - float roughness = material.roughness; - int param_5 = 10; - float4 roughnessTex = enableTextures(param_5, _163, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - if (hasPbrPack) - { - roughness *= pbrPackTex.y; - } - else if (any(roughnessTex != float4(-1.0))) - { - roughness *= roughnessTex.x; - } - float ao = material.ao; - int param_6 = 11; - float4 aoTex = enableTextures(param_6, _163, texture1, texture1Smplr, texCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - if (hasPbrPack) - { - ao *= pbrPackTex.x; - } - else if (any(aoTex != float4(-1.0))) - { - ao *= aoTex.x; - } - float3 F0 = float3(0.039999999105930328369140625); - F0 = mix(F0, albedo, float3(metallic)); - float directionalShadow = 0.0; - float spotShadow = 0.0; - float areaShadow = 0.0; - float pointShadow = 0.0; - if (_1073.shadowParamCount > 0) - { - for (int i_1 = 0; i_1 < _1073.shadowParamCount; i_1++) - { - if (_1905.shadowParams[i_1].lightType == 0) - { - float4 fragPosLightSpace = (_1905.shadowParams[i_1].lightProjection * _1905.shadowParams[i_1].lightView) * float4(in.FragPos, 1.0); - ShadowParameters _1934; - _1934.lightView = _1905.shadowParams[i_1].lightView; - _1934.lightProjection = _1905.shadowParams[i_1].lightProjection; - _1934.bias0 = _1905.shadowParams[i_1].bias0; - _1934.textureIndex = _1905.shadowParams[i_1].textureIndex; - _1934.farPlane = _1905.shadowParams[i_1].farPlane; - _1934._pad1 = _1905.shadowParams[i_1]._pad1; - _1934.lightPos = float3(_1905.shadowParams[i_1].lightPos); - _1934.lightType = _1905.shadowParams[i_1].lightType; - ShadowParameters param_7 = _1934; - float4 param_8 = fragPosLightSpace; - areaShadow = fast::max(areaShadow, calculateShadow(param_7, param_8, _163, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr, _1083, in.Normal, in.FragPos)); - } - else if (_1905.shadowParams[i_1].lightType == 1) - { - float4 fragPosLightSpace = (_1905.shadowParams[i_1].lightProjection * _1905.shadowParams[i_1].lightView) * float4(in.FragPos, 1.0); - ShadowParameters _1934; - _1934.lightView = _1905.shadowParams[i_1].lightView; - _1934.lightProjection = _1905.shadowParams[i_1].lightProjection; - _1934.bias0 = _1905.shadowParams[i_1].bias0; - _1934.textureIndex = _1905.shadowParams[i_1].textureIndex; - _1934.farPlane = _1905.shadowParams[i_1].farPlane; - _1934._pad1 = _1905.shadowParams[i_1]._pad1; - _1934.lightPos = float3(_1905.shadowParams[i_1].lightPos); - _1934.lightType = _1905.shadowParams[i_1].lightType; - ShadowParameters param_7 = _1934; - float4 param_8 = fragPosLightSpace; - spotShadow = fast::max(spotShadow, calculateShadow(param_7, param_8, _163, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr, _1083, in.Normal, in.FragPos)); - } - else if (_1905.shadowParams[i_1].lightType == 2) - { - float4 fragPosLightSpace = (_1905.shadowParams[i_1].lightProjection * _1905.shadowParams[i_1].lightView) * float4(in.FragPos, 1.0); - ShadowParameters _1934; - _1934.lightView = _1905.shadowParams[i_1].lightView; - _1934.lightProjection = _1905.shadowParams[i_1].lightProjection; - _1934.bias0 = _1905.shadowParams[i_1].bias0; - _1934.textureIndex = _1905.shadowParams[i_1].textureIndex; - _1934.farPlane = _1905.shadowParams[i_1].farPlane; - _1934._pad1 = _1905.shadowParams[i_1]._pad1; - _1934.lightPos = float3(_1905.shadowParams[i_1].lightPos); - _1934.lightType = _1905.shadowParams[i_1].lightType; - ShadowParameters param_7 = _1934; - float4 param_8 = fragPosLightSpace; - directionalShadow = fast::max(directionalShadow, calculateShadow(param_7, param_8, _163, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr, _1083, in.Normal, in.FragPos)); - } - else - { - ShadowParameters _1945; - _1945.lightView = _1905.shadowParams[i_1].lightView; - _1945.lightProjection = _1905.shadowParams[i_1].lightProjection; - _1945.bias0 = _1905.shadowParams[i_1].bias0; - _1945.textureIndex = _1905.shadowParams[i_1].textureIndex; - _1945.farPlane = _1905.shadowParams[i_1].farPlane; - _1945._pad1 = _1905.shadowParams[i_1]._pad1; - _1945.lightPos = float3(_1905.shadowParams[i_1].lightPos); - _1945.lightType = _1905.shadowParams[i_1].lightType; - ShadowParameters param_9 = _1945; - float3 param_10 = in.FragPos; - pointShadow = fast::max(pointShadow, calculatePointShadow(param_9, param_10, cubeMap1, cubeMap1Smplr, cubeMap2, cubeMap2Smplr, cubeMap3, cubeMap3Smplr, cubeMap4, cubeMap4Smplr, cubeMap5, cubeMap5Smplr)); - } - } - } - float reflectivity = material.reflectivity; - float3 viewDir = fast::normalize(_163.cameraPosition - in.FragPos); - float3 lighting = float3(0.0); - float3 param_11 = N; - float3 param_12 = V; - float3 param_13 = albedo; - float param_14 = metallic; - float param_15 = roughness; - float3 param_16 = F0; - float param_17 = reflectivity; - lighting += (calcAllDirectionalLights(param_11, param_12, param_13, param_14, param_15, param_16, param_17, _1073, _1083) * (1.0 - directionalShadow)); - float3 param_18 = in.FragPos; - float3 param_19 = N; - float3 param_20 = V; - float3 param_21 = albedo; - float param_22 = metallic; - float param_23 = roughness; - float3 param_24 = F0; - float param_25 = reflectivity; - lighting += (calcAllPointLights(param_18, param_19, param_20, param_21, param_22, param_23, param_24, param_25, _1073, _1136) * (1.0 - pointShadow)); - float3 param_26 = N; - float3 param_27 = in.FragPos; - float3 param_28 = V; - float3 param_29 = viewDir; - float3 param_30 = albedo; - float param_31 = metallic; - float param_32 = roughness; - float3 param_33 = F0; - float param_34 = reflectivity; - lighting += calcAllSpotLights(param_26, param_27, param_28, param_29, param_30, param_31, param_32, param_33, param_34, _1073, _1268) * (1.0 - spotShadow); - float3 param_35 = in.FragPos; - float3 param_36 = N; - float3 param_37 = V; - float3 param_38 = F0; - float3 param_39 = albedo; - float param_40 = metallic; - float param_41 = roughness; - float3 _2039 = getRimLight(param_35, param_36, param_37, param_38, param_39, param_40, param_41, _163, environment); - lighting += _2039; - float3 areaResult = float3(0.0); - float _2144; - for (int i_2 = 0; i_2 < _1073.areaLightCount; i_2++) - { - float3 P = float3(_2058.areaLights[i_2].position); - float3 R = fast::normalize(float3(_2058.areaLights[i_2].right)); - float3 U = fast::normalize(float3(_2058.areaLights[i_2].up)); - float2 halfSize = _2058.areaLights[i_2].size * 0.5; - float3 toPoint = in.FragPos - P; - float s = fast::clamp(dot(toPoint, R), -halfSize.x, halfSize.x); - float t = fast::clamp(dot(toPoint, U), -halfSize.y, halfSize.y); - float3 Q = (P + (R * s)) + (U * t); - float3 Lvec = Q - in.FragPos; - float dist = length(Lvec); - if (dist > 9.9999997473787516355514526367188e-05) - { - float3 L = Lvec / float3(dist); - float3 Nl = fast::normalize(cross(R, U)); - float ndotl = dot(Nl, -L); - if (_2058.areaLights[i_2].castsBothSides != 0) - { - _2144 = abs(ndotl); - } - else - { - _2144 = fast::max(ndotl, 0.0); - } - float facing = _2144; - float cosTheta = cos(radians(_2058.areaLights[i_2].angle)); - if ((facing >= cosTheta) && (facing > 0.0)) - { - float range = fast::max(_2058.areaLights[i_2].range, 0.001000000047497451305389404296875); - float attenuation = 1.0 / ((1.0 + (dist / range)) + ((dist * dist) / (range * range))); - float fade = 1.0 - smoothstep(range * 0.89999997615814208984375, range, dist); - float3 radiance = (((float3(_2058.areaLights[i_2].diffuse) * fast::max(_2058.areaLights[i_2].intensity, 0.0)) * attenuation) * facing) * fade; - float3 H = fast::normalize(V + L); - float3 param_42 = N; - float3 param_43 = H; - float param_44 = roughness; - float NDF = distributionGGX(param_42, param_43, param_44); - float3 param_45 = N; - float3 param_46 = V; - float3 param_47 = L; - float param_48 = roughness; - float G = geometrySmith(param_45, param_46, param_47, param_48); - float param_49 = fast::max(dot(H, V), 0.0); - float3 param_50 = F0; - float3 F = fresnelSchlick(param_49, param_50); - float3 kS = F; - float3 kD = (float3(1.0) - kS) * (1.0 - metallic); - float3 numerator = F * (NDF * G); - float denominator = fast::max((4.0 * fast::max(dot(N, V), 0.0)) * fast::max(dot(N, L), 0.0), 9.9999997473787516355514526367188e-05); - float3 specular = numerator / float3(denominator); - float NdotL = fast::max(dot(N, L), 0.0); - areaResult += (((((kD * albedo) / float3(3.1415927410125732421875)) + specular) * radiance) * NdotL); - } - } - } - lighting += areaResult * (1.0 - areaShadow); - float aoClamped = fast::clamp(ao, 0.0, 1.0); - float aoWithFloor = fast::max(aoClamped, 0.20000000298023223876953125); - float ambientIntensity = ambientLight.intensity; - float3 ambientColor = ambientLight.color.xyz; - if (ambientIntensity <= 9.9999997473787516355514526367188e-05) - { - ambientIntensity = 0.02999999932944774627685546875; - } - if (dot(ambientColor, ambientColor) <= 9.9999999747524270787835121154785e-07) - { - ambientColor = float3(1.0); - } - float3 ambient = ((albedo * ambientIntensity) * ambientColor) * aoWithFloor; - float3 iblContribution = float3(0.0); - if (_1073.useIBL != 0u) - { - float3 param_51 = N; - float3 irradiance = sampleEnvironmentRadiance(param_51, _163, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - float3 diffuseIBL = irradiance * albedo; - float3 reflection = reflect(-V, N); - float3 param_52 = reflection; - float3 specularEnv = sampleEnvironmentRadiance(param_52, _163, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr); - float param_53 = fast::max(dot(N, V), 0.0); - float3 param_54 = F0; - float3 F_1 = fresnelSchlick(param_53, param_54); - float3 kS_1 = F_1; - float3 kD_1 = float3(1.0) - kS_1; - kD_1 *= (1.0 - metallic); - float roughnessAttenuation = mix(1.0, 0.1500000059604644775390625, fast::clamp(roughness, 0.0, 1.0)); - float3 specularIBL = specularEnv * roughnessAttenuation; - iblContribution = ((kD_1 * diffuseIBL) + (kS_1 * specularIBL)) * aoWithFloor; - } - float3 color = (ambient + lighting) + iblContribution; - out.FragColor = float4(color, 1.0); - float brightness = dot(color, float3(0.2125999927520751953125, 0.715200006961822509765625, 0.072200000286102294921875)); - if (brightness > 0.75) - { - out.BrightColor = float4(color, 1.0); - } - else - { - out.BrightColor = float4(0.0, 0.0, 0.0, 1.0); - } - float3 param_55 = out.FragColor.xyz; - float3 _2399 = acesToneMapping(param_55); - out.FragColor.x = _2399.x; - out.FragColor.y = _2399.y; - out.FragColor.z = _2399.z; - return out; -} diff --git a/shaders/metal/main.vert.metal b/shaders/metal/main.vert.metal deleted file mode 100644 index 560b5603..00000000 --- a/shaders/metal/main.vert.metal +++ /dev/null @@ -1,109 +0,0 @@ -#pragma clang diagnostic ignored "-Wmissing-prototypes" - -#include -#include - -using namespace metal; - -// Returns the determinant of a 2x2 matrix. -static inline __attribute__((always_inline)) -float spvDet2x2(float a1, float a2, float b1, float b2) -{ - return a1 * b2 - b1 * a2; -} - -// Returns the inverse of a matrix, by using the algorithm of calculating the classical -// adjoint and dividing by the determinant. The contents of the matrix are changed. -static inline __attribute__((always_inline)) -float3x3 spvInverse3x3(float3x3 m) -{ - float3x3 adj; // The adjoint matrix (inverse after dividing by determinant) - - // Create the transpose of the cofactors, as the classical adjoint of the matrix. - adj[0][0] = spvDet2x2(m[1][1], m[1][2], m[2][1], m[2][2]); - adj[0][1] = -spvDet2x2(m[0][1], m[0][2], m[2][1], m[2][2]); - adj[0][2] = spvDet2x2(m[0][1], m[0][2], m[1][1], m[1][2]); - - adj[1][0] = -spvDet2x2(m[1][0], m[1][2], m[2][0], m[2][2]); - adj[1][1] = spvDet2x2(m[0][0], m[0][2], m[2][0], m[2][2]); - adj[1][2] = -spvDet2x2(m[0][0], m[0][2], m[1][0], m[1][2]); - - adj[2][0] = spvDet2x2(m[1][0], m[1][1], m[2][0], m[2][1]); - adj[2][1] = -spvDet2x2(m[0][0], m[0][1], m[2][0], m[2][1]); - adj[2][2] = spvDet2x2(m[0][0], m[0][1], m[1][0], m[1][1]); - - // Calculate the determinant as a combination of the cofactors of the first row. - float det = (adj[0][0] * m[0][0]) + (adj[0][1] * m[1][0]) + (adj[0][2] * m[2][0]); - - // Divide the classical adjoint matrix by the determinant. - // If determinant is zero, matrix is not invertable, so leave it unchanged. - return (det != 0.0f) ? (adj * (1.0f / det)) : m; -} - -struct UBO -{ - float4x4 model; - float4x4 view; - float4x4 projection; - uint isInstanced; -}; - -struct main0_out -{ - float2 TexCoord [[user(locn0)]]; - float4 outColor [[user(locn1)]]; - float3 Normal [[user(locn2)]]; - float3 FragPos [[user(locn3)]]; - float3 TBN_0 [[user(locn4)]]; - float3 TBN_1 [[user(locn5)]]; - float3 TBN_2 [[user(locn6)]]; - float4 gl_Position [[position, invariant]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; - float4 aColor [[attribute(1)]]; - float2 aTexCoord [[attribute(2)]]; - float3 aNormal [[attribute(3)]]; - float3 aTangent [[attribute(4)]]; - float3 aBitangent [[attribute(5)]]; - float4 instanceModel_0 [[attribute(6)]]; - float4 instanceModel_1 [[attribute(7)]]; - float4 instanceModel_2 [[attribute(8)]]; - float4 instanceModel_3 [[attribute(9)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]], constant UBO& uniforms [[buffer(0)]]) -{ - main0_out out = {}; - float3x3 TBN = {}; - float4x4 instanceModel = {}; - instanceModel[0] = in.instanceModel_0; - instanceModel[1] = in.instanceModel_1; - instanceModel[2] = in.instanceModel_2; - instanceModel[3] = in.instanceModel_3; - float4x4 modelMatrix = uniforms.model; - bool hasInstanceMatrix = abs(instanceModel[3].w) > 0.5; - if ((uniforms.isInstanced != 0u) && hasInstanceMatrix) - { - modelMatrix = instanceModel; - } - float4x4 mvp = (uniforms.projection * uniforms.view) * modelMatrix; - float4 _56 = float4(in.aPos, 1.0); - float4 _57 = mvp * _56; - out.gl_Position = _57; - out.FragPos = float3((modelMatrix * float4(in.aPos, 1.0)).xyz); - out.TexCoord = in.aTexCoord; - out.outColor = in.aColor; - float3x3 normalMatrix = transpose(spvInverse3x3(float3x3(modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz))); - out.Normal = fast::normalize(normalMatrix * in.aNormal); - float3 N = out.Normal; - float3 T = fast::normalize(normalMatrix * in.aTangent); - float3 B = fast::normalize(normalMatrix * in.aBitangent); - TBN = float3x3(float3(T), float3(B), float3(N)); - out.TBN_0 = TBN[0]; - out.TBN_1 = TBN[1]; - out.TBN_2 = TBN[2]; - return out; -} diff --git a/shaders/metal/path_tracing/path.metal b/shaders/metal/path_tracing/path.metal deleted file mode 100644 index c86ac3ae..00000000 --- a/shaders/metal/path_tracing/path.metal +++ /dev/null @@ -1,1675 +0,0 @@ -#include -#include -using namespace metal; -using namespace raytracing; - -struct CameraUniforms { - float4x4 invViewProj; - float4x4 prevViewProj; - float3 camPos; - float _pad0; -}; - -struct Material { - float4 albedo; - float metallic; - float roughness; - float ao; - float emissiveIntensity; - packed_float3 emissiveColor; - float _pad0; - int albedoTextureIndex; - int normalTextureIndex; - int metallicTextureIndex; - int roughnessTextureIndex; - int aoTextureIndex; - int opacityTextureIndex; - float _pad1[2]; - - float transmittance; - float ior; - float reflectivity; - float _pad2; - packed_float2 textureScale; - packed_float2 textureOffset; -}; - -static_assert(sizeof(Material) == 112); -static_assert(__builtin_offsetof(Material, emissiveColor) == 32); -static_assert(__builtin_offsetof(Material, albedoTextureIndex) == 48); -static_assert(__builtin_offsetof(Material, transmittance) == 80); -static_assert(__builtin_offsetof(Material, textureScale) == 96); - -struct VertexData { - packed_float3 position; - packed_float3 normal; - packed_float2 uv; - packed_float3 tangent; - packed_float3 bitangent; -}; - -struct InstanceData { - float4x4 model; - float4 normalCol0; - float4 normalCol1; - float4 normalCol2; -}; - -struct DirectionalLightData { - float3 direction; - float intensity; - float3 color; - float _pad0; -}; - -struct PointLight { - packed_float3 position; - float intensity; - packed_float3 color; - float range; -}; - -struct SpotLight { - packed_float3 position; - float intensity; - - packed_float3 direction; - float innerCos; - packed_float3 color; - float outerCos; - - float range; - float _pad0[3]; -}; - -struct AreaLight { - packed_float3 position; - float intensity; - - packed_float3 right; - float halfWidth; - - packed_float3 up; - float halfHeight; - - packed_float3 color; - float twoSided; -}; - -struct EmissiveTriangle { - float4 p0; - float4 p1; - float4 p2; - float4 normal; - packed_float3 emission; - float area; - float cdf; - float selectionPdf; - float2 _pad; -}; - -static_assert(sizeof(EmissiveTriangle) == 96); - -struct SceneData { - uint numDirectionalLights; - uint numPointLights; - uint numSpotLights; - uint numAreaLights; - - uint frameIndex; - uint raysPerPixel; - uint maxBounces; - float indirectStrength; - float ambientIntensity; - uint materialTextureCount; - uint atmosphereEnabled; - float atmosphereSunSize; - float3 atmosphereSunDirection; - float atmosphereSunIntensity; - float3 atmosphereSunColor; - uint pixelStride; - float3 ambientColor; - uint environmentEnabled; - uint accumulationFrameLimit; - float fireflyClamp; - uint numEmissiveTriangles; - float bloomThreshold; -}; - -static_assert(sizeof(SceneData) == 160); -static_assert(__builtin_offsetof(SceneData, atmosphereSunDirection) == 48); -static_assert(__builtin_offsetof(SceneData, atmosphereSunIntensity) == 64); -static_assert(__builtin_offsetof(SceneData, atmosphereSunColor) == 80); -static_assert(__builtin_offsetof(SceneData, pixelStride) == 96); -static_assert(__builtin_offsetof(SceneData, ambientColor) == 112); -static_assert(__builtin_offsetof(SceneData, accumulationFrameLimit) == 132); -static_assert(__builtin_offsetof(SceneData, numEmissiveTriangles) == 140); -static_assert(__builtin_offsetof(SceneData, bloomThreshold) == 144); - -float pow5(float x) { - float x2 = x * x; - return x2 * x2 * x; -} - -float luminance(float3 c) { return dot(c, float3(0.2126, 0.7152, 0.0722)); } - -float powerHeuristic(float pdfA, float pdfB) { - float a2 = pdfA * pdfA; - float b2 = pdfB * pdfB; - return a2 / max(a2 + b2, 1e-8); -} - -float3 clampLuminance(float3 c, float maxL) { - float l = luminance(c); - if (l > maxL && l > 1e-6) { - c *= maxL / l; - } - return c; -} - -uint wang_hash(uint s) { - s = (s ^ 61u) ^ (s >> 16u); - s *= 9u; - s = s ^ (s >> 4u); - s *= 0x27d4eb2du; - s = s ^ (s >> 15u); - return s; -} - -float rand(thread uint &state) { - state = wang_hash(state); - return float(state) / 4294967296.0; -} - -uint seedBase(uint2 gid, uint w, uint frame, uint sampleIndex) { - return gid.x + gid.y * w + frame * 9781u + sampleIndex * 6271u + 1u; -} - -constexpr sampler skyboxSampler(coord::normalized, address::clamp_to_edge, - filter::linear, mip_filter::linear); - -float3 skyColor(float3 dir, float intensity, texturecube skybox, - constant SceneData &sceneData) { - float3 sampleDir = dir; - float len2 = dot(sampleDir, sampleDir); - if (len2 > 1e-10) { - sampleDir *= rsqrt(len2); - } else { - sampleDir = float3(0.0, 1.0, 0.0); - } - float3 sky = skybox.sample(skyboxSampler, sampleDir).xyz; - if (sceneData.atmosphereEnabled != 0) { - float horizon = pow(clamp(1.0 - abs(sampleDir.y), 0.0, 1.0), 4.0); - float daylight = smoothstep(-0.2, 0.15, - sceneData.atmosphereSunDirection.y); - float3 zenith = float3(0.08, 0.28, 0.65); - float3 horizonColor = float3(0.58, 0.72, 0.92); - float3 proceduralSky = mix(zenith, horizonColor, horizon) * - max(daylight, 0.08); - sky = max(sky, proceduralSky); - } - if (sceneData.atmosphereEnabled != 0 && - sceneData.atmosphereSunDirection.y > -0.15) { - float3 sunDirection = sceneData.atmosphereSunDirection; - float sunDirectionLength = dot(sunDirection, sunDirection); - sunDirection = sunDirectionLength > 1e-10 - ? sunDirection * rsqrt(sunDirectionLength) - : float3(0.0, 1.0, 0.0); - float sunDot = dot(sampleDir, sunDirection); - float sizeAdjust = - 1.0 - (sceneData.atmosphereSunSize - 1.0) * 0.001; - float sunSize = 0.9995 * sizeAdjust; - float sunGlowSize = - 0.998 * (1.0 - (sceneData.atmosphereSunSize - 1.0) * 0.003); - float sunHaloSize = - 0.99 * (1.0 - (sceneData.atmosphereSunSize - 1.0) * 0.015); - float sunDisk = smoothstep(sunSize - 0.0002, sunSize, sunDot); - float sunGlow = - smoothstep(sunGlowSize, sunSize, sunDot) * (1.0 - sunDisk); - float sunHalo = smoothstep(sunHaloSize, sunSize, sunDot) * - (1.0 - smoothstep(sunSize, sunGlowSize, sunDot)); - float horizonFade = smoothstep( - -0.15, 0.05, sceneData.atmosphereSunDirection.y); - float sunIntensity = max(sceneData.atmosphereSunIntensity, 0.05); - sky += sceneData.atmosphereSunColor * - (sunDisk * 5.0 + sunGlow * 0.5 + sunHalo) * horizonFade * - sunIntensity; - } - float scale = intensity > 0.0 ? intensity : 1.0; - return sky * scale; -} - -float3 cosineSampleHemisphere(float2 u) { - float r = sqrt(u.x); - float theta = 2.0 * M_PI_F * u.y; - - float x = r * cos(theta); - float y = r * sin(theta); - float z = sqrt(max(0.0, 1.0 - u.x)); - - return float3(x, y, z); -} - -float3x3 buildOrthonormalBasis(float3 N) { - float3 T = normalize(abs(N.x) > 0.1 ? cross(float3(0, 1, 0), N) - : cross(float3(1, 0, 0), N)); - float3 B = cross(N, T); - return float3x3(T, B, N); -} - -float3 normalizeOr(float3 v, float3 fallback) { - float len2 = dot(v, v); - if (len2 > 1e-10) { - return v * rsqrt(len2); - } - return fallback; -} - -float rayOffsetDistance(float3 position) { - float positionScale = - max(abs(position.x), max(abs(position.y), abs(position.z))); - return max(0.0002, positionScale * 0.000002); -} - -float3 offsetRayOrigin(float3 position, float3 geometricNormal, - float3 direction) { - float side = dot(direction, geometricNormal) >= 0.0 ? 1.0 : -1.0; - return position + geometricNormal * (rayOffsetDistance(position) * side); -} - -float2 encodeNormal(float3 normal) { - normal /= max(abs(normal.x) + abs(normal.y) + abs(normal.z), 1e-6); - float2 encoded = normal.xy; - if (normal.z < 0.0) { - float2 signValue = select(float2(-1.0), float2(1.0), encoded >= 0.0); - encoded = (1.0 - abs(encoded.yx)) * signValue; - } - return encoded; -} - -constexpr sampler materialTexSampler(coord::normalized, address::repeat, - filter::linear, mip_filter::linear); - -#define PT_MATERIAL_TEXTURE_PARAMS \ - texture2d materialTexture0, texture2d materialTexture1, \ - texture2d materialTexture2, texture2d materialTexture3, \ - texture2d materialTexture4, texture2d materialTexture5, \ - texture2d materialTexture6, texture2d materialTexture7, \ - texture2d materialTexture8, texture2d materialTexture9, \ - texture2d materialTexture10, \ - texture2d materialTexture11, \ - texture2d materialTexture12, \ - texture2d materialTexture13, \ - texture2d materialTexture14, \ - texture2d materialTexture15, \ - texture2d materialTexture16, \ - texture2d materialTexture17, \ - texture2d materialTexture18, \ - texture2d materialTexture19, \ - texture2d materialTexture20, \ - texture2d materialTexture21, \ - texture2d materialTexture22, \ - texture2d materialTexture23, \ - texture2d materialTexture24, \ - texture2d materialTexture25, \ - texture2d materialTexture26, \ - texture2d materialTexture27, \ - texture2d materialTexture28, \ - texture2d materialTexture29, \ - texture2d materialTexture30, \ - texture2d materialTexture31, \ - texture2d materialTexture32, \ - texture2d materialTexture33, \ - texture2d materialTexture34, \ - texture2d materialTexture35, \ - texture2d materialTexture36, \ - texture2d materialTexture37, \ - texture2d materialTexture38, \ - texture2d materialTexture39, \ - texture2d materialTexture40, \ - texture2d materialTexture41, \ - texture2d materialTexture42, \ - texture2d materialTexture43, \ - texture2d materialTexture44, \ - texture2d materialTexture45, \ - texture2d materialTexture46, texture2d materialTexture47 - -#define PT_MATERIAL_TEXTURE_ARGS \ - materialTexture0, materialTexture1, materialTexture2, materialTexture3, \ - materialTexture4, materialTexture5, materialTexture6, \ - materialTexture7, materialTexture8, materialTexture9, \ - materialTexture10, materialTexture11, materialTexture12, \ - materialTexture13, materialTexture14, materialTexture15, \ - materialTexture16, materialTexture17, materialTexture18, \ - materialTexture19, materialTexture20, materialTexture21, \ - materialTexture22, materialTexture23, materialTexture24, \ - materialTexture25, materialTexture26, materialTexture27, \ - materialTexture28, materialTexture29, materialTexture30, \ - materialTexture31, materialTexture32, materialTexture33, \ - materialTexture34, materialTexture35, materialTexture36, \ - materialTexture37, materialTexture38, materialTexture39, \ - materialTexture40, materialTexture41, materialTexture42, \ - materialTexture43, materialTexture44, materialTexture45, \ - materialTexture46, materialTexture47 - -#define PT_MATERIAL_TEXTURE_BINDINGS \ - texture2d materialTexture0 [[texture(12)]], \ - texture2d materialTexture1 [[texture(13)]], \ - texture2d materialTexture2 [[texture(14)]], \ - texture2d materialTexture3 [[texture(15)]], \ - texture2d materialTexture4 [[texture(16)]], \ - texture2d materialTexture5 [[texture(17)]], \ - texture2d materialTexture6 [[texture(18)]], \ - texture2d materialTexture7 [[texture(19)]], \ - texture2d materialTexture8 [[texture(20)]], \ - texture2d materialTexture9 [[texture(21)]], \ - texture2d materialTexture10 [[texture(22)]], \ - texture2d materialTexture11 [[texture(23)]], \ - texture2d materialTexture12 [[texture(24)]], \ - texture2d materialTexture13 [[texture(25)]], \ - texture2d materialTexture14 [[texture(26)]], \ - texture2d materialTexture15 [[texture(27)]], \ - texture2d materialTexture16 [[texture(28)]], \ - texture2d materialTexture17 [[texture(29)]], \ - texture2d materialTexture18 [[texture(30)]], \ - texture2d materialTexture19 [[texture(31)]], \ - texture2d materialTexture20 [[texture(32)]], \ - texture2d materialTexture21 [[texture(33)]], \ - texture2d materialTexture22 [[texture(34)]], \ - texture2d materialTexture23 [[texture(35)]], \ - texture2d materialTexture24 [[texture(36)]], \ - texture2d materialTexture25 [[texture(37)]], \ - texture2d materialTexture26 [[texture(38)]], \ - texture2d materialTexture27 [[texture(39)]], \ - texture2d materialTexture28 [[texture(40)]], \ - texture2d materialTexture29 [[texture(41)]], \ - texture2d materialTexture30 [[texture(42)]], \ - texture2d materialTexture31 [[texture(43)]], \ - texture2d materialTexture32 [[texture(44)]], \ - texture2d materialTexture33 [[texture(45)]], \ - texture2d materialTexture34 [[texture(46)]], \ - texture2d materialTexture35 [[texture(47)]], \ - texture2d materialTexture36 [[texture(48)]], \ - texture2d materialTexture37 [[texture(49)]], \ - texture2d materialTexture38 [[texture(50)]], \ - texture2d materialTexture39 [[texture(51)]], \ - texture2d materialTexture40 [[texture(52)]], \ - texture2d materialTexture41 [[texture(53)]], \ - texture2d materialTexture42 [[texture(54)]], \ - texture2d materialTexture43 [[texture(55)]], \ - texture2d materialTexture44 [[texture(56)]], \ - texture2d materialTexture45 [[texture(57)]], \ - texture2d materialTexture46 [[texture(58)]], \ - texture2d materialTexture47 [[texture(59)]] - -float4 sampleMaterialTexture(int textureIndex, float2 uv, - PT_MATERIAL_TEXTURE_PARAMS) { - switch (textureIndex) { - case 0: - return materialTexture0.sample(materialTexSampler, uv); - case 1: - return materialTexture1.sample(materialTexSampler, uv); - case 2: - return materialTexture2.sample(materialTexSampler, uv); - case 3: - return materialTexture3.sample(materialTexSampler, uv); - case 4: - return materialTexture4.sample(materialTexSampler, uv); - case 5: - return materialTexture5.sample(materialTexSampler, uv); - case 6: - return materialTexture6.sample(materialTexSampler, uv); - case 7: - return materialTexture7.sample(materialTexSampler, uv); - case 8: - return materialTexture8.sample(materialTexSampler, uv); - case 9: - return materialTexture9.sample(materialTexSampler, uv); - case 10: - return materialTexture10.sample(materialTexSampler, uv); - case 11: - return materialTexture11.sample(materialTexSampler, uv); - case 12: - return materialTexture12.sample(materialTexSampler, uv); - case 13: - return materialTexture13.sample(materialTexSampler, uv); - case 14: - return materialTexture14.sample(materialTexSampler, uv); - case 15: - return materialTexture15.sample(materialTexSampler, uv); - case 16: - return materialTexture16.sample(materialTexSampler, uv); - case 17: - return materialTexture17.sample(materialTexSampler, uv); - case 18: - return materialTexture18.sample(materialTexSampler, uv); - case 19: - return materialTexture19.sample(materialTexSampler, uv); - case 20: - return materialTexture20.sample(materialTexSampler, uv); - case 21: - return materialTexture21.sample(materialTexSampler, uv); - case 22: - return materialTexture22.sample(materialTexSampler, uv); - case 23: - return materialTexture23.sample(materialTexSampler, uv); - case 24: - return materialTexture24.sample(materialTexSampler, uv); - case 25: - return materialTexture25.sample(materialTexSampler, uv); - case 26: - return materialTexture26.sample(materialTexSampler, uv); - case 27: - return materialTexture27.sample(materialTexSampler, uv); - case 28: - return materialTexture28.sample(materialTexSampler, uv); - case 29: - return materialTexture29.sample(materialTexSampler, uv); - case 30: - return materialTexture30.sample(materialTexSampler, uv); - case 31: - return materialTexture31.sample(materialTexSampler, uv); - case 32: - return materialTexture32.sample(materialTexSampler, uv); - case 33: - return materialTexture33.sample(materialTexSampler, uv); - case 34: - return materialTexture34.sample(materialTexSampler, uv); - case 35: - return materialTexture35.sample(materialTexSampler, uv); - case 36: - return materialTexture36.sample(materialTexSampler, uv); - case 37: - return materialTexture37.sample(materialTexSampler, uv); - case 38: - return materialTexture38.sample(materialTexSampler, uv); - case 39: - return materialTexture39.sample(materialTexSampler, uv); - case 40: - return materialTexture40.sample(materialTexSampler, uv); - case 41: - return materialTexture41.sample(materialTexSampler, uv); - case 42: - return materialTexture42.sample(materialTexSampler, uv); - case 43: - return materialTexture43.sample(materialTexSampler, uv); - case 44: - return materialTexture44.sample(materialTexSampler, uv); - case 45: - return materialTexture45.sample(materialTexSampler, uv); - case 46: - return materialTexture46.sample(materialTexSampler, uv); - case 47: - return materialTexture47.sample(materialTexSampler, uv); - default: - break; - } - return float4(0.0); -} - -struct MaterialTextureArguments { - array, 256> textures [[id(0)]]; -}; - -float4 sampleMaterialTexture( - int textureIndex, float2 uv, - constant MaterialTextureArguments &materialTextureArguments) { - return materialTextureArguments.textures[textureIndex].sample( - materialTexSampler, uv); -} - -#undef PT_MATERIAL_TEXTURE_PARAMS -#undef PT_MATERIAL_TEXTURE_ARGS -#undef PT_MATERIAL_TEXTURE_BINDINGS -#define PT_MATERIAL_TEXTURE_PARAMS \ - constant MaterialTextureArguments &materialTextureArguments -#define PT_MATERIAL_TEXTURE_ARGS materialTextureArguments -#define PT_MATERIAL_TEXTURE_BINDINGS \ - constant MaterialTextureArguments &materialTextureArguments [[buffer(12)]] - -float resolveMaterialOpacity(Material mat, float2 uv, uint textureCount, - PT_MATERIAL_TEXTURE_PARAMS) { - float opacity = clamp(mat.albedo.w, 0.0, 1.0); - if (mat.opacityTextureIndex >= 0 && - uint(mat.opacityTextureIndex) < textureCount) { - float4 opacitySample = sampleMaterialTexture( - mat.opacityTextureIndex, uv, PT_MATERIAL_TEXTURE_ARGS); - opacity *= mat.opacityTextureIndex == mat.albedoTextureIndex - ? opacitySample.w - : opacitySample.x; - } - return clamp(opacity, 0.0, 1.0); -} - -void resolveMaterialParameters(Material mat, float2 uv, uint textureCount, - PT_MATERIAL_TEXTURE_PARAMS, - thread float3 &albedo, thread float &metallic, - thread float &roughness, thread float &ao, - thread float3 &emissive, thread float &outIor, - thread float &outTransmittance) { - albedo = clamp(mat.albedo.xyz, float3(0.0), float3(1.0)); - metallic = mat.metallic; - roughness = mat.roughness; - ao = mat.ao; - emissive = max(float3(mat.emissiveColor) * - max(mat.emissiveIntensity, 0.0), - float3(0.0)); - - outIor = max(mat.ior, 1.0); - outTransmittance = clamp(mat.transmittance, 0.0, 1.0); - - if (mat.albedoTextureIndex >= 0 && - uint(mat.albedoTextureIndex) < textureCount) { - albedo *= clamp(sampleMaterialTexture(mat.albedoTextureIndex, uv, - PT_MATERIAL_TEXTURE_ARGS) - .xyz, - float3(0.0), float3(1.0)); - } - if (mat.metallicTextureIndex >= 0 && - uint(mat.metallicTextureIndex) < textureCount) { - float4 metallicSample = sampleMaterialTexture( - mat.metallicTextureIndex, uv, PT_MATERIAL_TEXTURE_ARGS); - float metallicValue = metallicSample.x; - if (mat.roughnessTextureIndex == mat.metallicTextureIndex) { - metallicValue = metallicSample.z; - } - metallic *= clamp(metallicValue, 0.0, 1.0); - } - if (mat.roughnessTextureIndex >= 0 && - uint(mat.roughnessTextureIndex) < textureCount) { - float4 roughnessSample = sampleMaterialTexture( - mat.roughnessTextureIndex, uv, PT_MATERIAL_TEXTURE_ARGS); - float roughnessValue = roughnessSample.x; - if (mat.roughnessTextureIndex == mat.metallicTextureIndex) { - roughnessValue = roughnessSample.y; - } - roughness *= clamp(roughnessValue, 0.0, 1.0); - } - if (mat.aoTextureIndex >= 0 && uint(mat.aoTextureIndex) < textureCount) { - ao *= clamp(sampleMaterialTexture(mat.aoTextureIndex, uv, - PT_MATERIAL_TEXTURE_ARGS) - .x, - 0.0, 1.0); - } - - albedo = clamp(albedo, float3(0.0), float3(1.0)); - metallic = clamp(metallic, 0.0, 1.0); - roughness = clamp(roughness, 0.001, 1.0); - ao = clamp(ao, 0.0, 1.0); -} - -float3 resolveShadingNormal(Material mat, float2 uv, float3 localN, - float3 localT, float3 localB, InstanceData inst, - uint textureCount, PT_MATERIAL_TEXTURE_PARAMS) { - float3x3 normalMatrix = - float3x3(inst.normalCol0.xyz, inst.normalCol1.xyz, inst.normalCol2.xyz); - float3 N = normalizeOr(normalMatrix * localN, float3(0.0, 1.0, 0.0)); - - float3 T = normalizeOr((inst.model * float4(localT, 0.0)).xyz, - float3(1.0, 0.0, 0.0)); - float3 B = normalizeOr((inst.model * float4(localB, 0.0)).xyz, - float3(0.0, 0.0, 1.0)); - T = normalizeOr(T - N * dot(N, T), float3(1.0, 0.0, 0.0)); - B = normalizeOr(B - N * dot(N, B), cross(N, T)); - if (dot(cross(T, B), cross(T, B)) <= 1e-10) { - float3x3 basis = buildOrthonormalBasis(N); - T = basis[0]; - B = basis[1]; - } - - bool useNormalMap = mat._pad1[0] != 0; - float normalStrength = max(mat._pad0, 0.0f); - if (useNormalMap && normalStrength > 0.0 && mat.normalTextureIndex >= 0 && - uint(mat.normalTextureIndex) < textureCount) { - float3 tangentNormal = sampleMaterialTexture(mat.normalTextureIndex, uv, - PT_MATERIAL_TEXTURE_ARGS) - .xyz; - tangentNormal = tangentNormal * 2.0 - 1.0; - tangentNormal.xy *= normalStrength; - tangentNormal = normalizeOr(tangentNormal, float3(0.0, 0.0, 1.0)); - N = normalizeOr(float3x3(T, B, N) * tangentNormal, N); - } - - return N; -} - -float3 traceShadowVisibility(intersector isect, - primitive_acceleration_structure sceneAS, - float3 P, float3 Ng, float3 L, - float maxDistance, thread uint &rng, - constant Material *materials, - constant uint *primitiveObjects, - constant uint *blasPrimitiveOffsets, - constant VertexData *vertices, - constant uint *indices, - constant InstanceData *instanceData, - constant SceneData &sceneData, - PT_MATERIAL_TEXTURE_PARAMS) { - float shadowBias = rayOffsetDistance(P); - float3 visibility = float3(1.0); - float causticGain = 1.0; - float3 entryNormal = float3(0.0); - uint dielectricObject = 0xFFFFFFFFu; - ray shadowRay; - shadowRay.origin = offsetRayOrigin(P, Ng, L); - shadowRay.direction = L; - shadowRay.min_distance = 0.0; - shadowRay.max_distance = max(maxDistance - shadowBias, shadowBias + 1e-4); - - for (uint alphaStep = 0; alphaStep < 32; ++alphaStep) { - auto shadowHit = isect.intersect(shadowRay, sceneAS); - if (shadowHit.type == intersection_type::none) { - return clampLuminance(visibility * causticGain, 2.5); - } - - uint primitiveIndex = - blasPrimitiveOffsets[shadowHit.geometry_id] + shadowHit.primitive_id; - uint objectIndex = primitiveObjects[primitiveIndex]; - Material material = materials[objectIndex]; - uint i0 = indices[primitiveIndex * 3 + 0]; - uint i1 = indices[primitiveIndex * 3 + 1]; - uint i2 = indices[primitiveIndex * 3 + 2]; - float2 bary = shadowHit.triangle_barycentric_coord; - float b0 = 1.0 - bary.x - bary.y; - float2 uv = float2(vertices[i0].uv) * b0 + - float2(vertices[i1].uv) * bary.x + - float2(vertices[i2].uv) * bary.y; - uv = uv * float2(material.textureScale) + - float2(material.textureOffset); - float opacity = resolveMaterialOpacity( - material, uv, sceneData.materialTextureCount, - PT_MATERIAL_TEXTURE_ARGS); - if (opacity >= 0.999 || rand(rng) < opacity) { - float transmission = clamp(material.transmittance, 0.0, 1.0) * - (1.0 - clamp(material.metallic, 0.0, 1.0)); - if (transmission <= 0.001) { - return float3(0.0); - } - - float3 p0 = float3(vertices[i0].position); - float3 p1 = float3(vertices[i1].position); - float3 p2 = float3(vertices[i2].position); - float3 hitNormal = normalizeOr(cross(p1 - p0, p2 - p0), -L); - hitNormal = dot(hitNormal, L) < 0.0 ? hitNormal : -hitNormal; - float ior = max(material.ior, 1.0); - float dielectricF0 = pow((ior - 1.0) / (ior + 1.0), 2.0); - float fresnel = dielectricF0 + - (1.0 - dielectricF0) * - pow5(1.0 - abs(dot(hitNormal, L))); - float3 tint = mix(float3(1.0), - clamp(material.albedo.xyz, float3(0.0), - float3(1.0)), - 0.15); - visibility *= tint * transmission * (1.0 - fresnel); - if (dielectricObject == objectIndex) { - float curvature = - 1.0 - clamp(abs(dot(entryNormal, hitNormal)), 0.0, 1.0); - float smoothness = - 1.0 - clamp(material.roughness, 0.0, 1.0); - float focus = 1.0 + transmission * max(ior - 1.0, 0.0) * - smoothness * smoothness * - (0.35 + curvature * 3.0); - causticGain *= clamp(focus, 1.0, 2.5); - dielectricObject = 0xFFFFFFFFu; - } else { - dielectricObject = objectIndex; - entryNormal = hitNormal; - } - if (luminance(visibility) <= 0.001) { - return float3(0.0); - } - } - - float advance = shadowHit.distance + rayOffsetDistance(shadowRay.origin); - shadowRay.origin += shadowRay.direction * advance; - shadowRay.max_distance -= advance; - if (shadowRay.max_distance <= shadowBias) { - return clampLuminance(visibility * causticGain, 2.5); - } - } - - return float3(0.0); -} - -float3 sampleDirectionalLightDirection(DirectionalLightData light, - thread uint &rng) { - float3 baseL = normalize(-light.direction); - float3x3 basis = buildOrthonormalBasis(baseL); - float sunRadius = 0.0025; - float2 u = float2(rand(rng), rand(rng)); - float r = sunRadius * sqrt(u.x); - float phi = 2.0 * M_PI_F * u.y; - float3 jittered = - baseL + basis[0] * (r * cos(phi)) + basis[1] * (r * sin(phi)); - return normalize(jittered); -} - -// --------------------------------------------------------------------------- -// PBR helpers: GGX / Cook-Torrance -// --------------------------------------------------------------------------- - -float D_GGX(float NdotH, float roughness) { - float a = max(roughness * roughness, 1e-4); - float a2 = a * a; - float d = (NdotH * NdotH) * (a2 - 1.0) + 1.0; - return a2 / max(M_PI_F * d * d, 1e-6); -} - -float3 F_Schlick(float cosTheta, float3 F0) { - float c = clamp(1.0 - cosTheta, 0.0, 1.0); - return F0 + (1.0 - F0) * pow5(c); -} - -float3 materialF0(float3 albedo, float metallic, float reflectivity, - float ior) { - float dielectricF0 = pow((max(ior, 1.0001) - 1.0) / - (max(ior, 1.0001) + 1.0), - 2.0); - float dielectricScale = mix(0.5, 1.5, clamp(reflectivity, 0.0, 1.0)); - return mix(float3(clamp(dielectricF0 * dielectricScale, 0.0, 0.16)), - albedo, clamp(metallic, 0.0, 1.0)); -} - -float G_Smith(float NdotV, float NdotL, float roughness) { - float r = roughness + 1.0; - float k = (r * r) / 8.0; - float gV = NdotV / (NdotV * (1.0 - k) + k); - float gL = NdotL / (NdotL * (1.0 - k) + k); - return gV * gL; -} - -float G1_SmithGGX(float NdotX, float roughness) { - float alpha = max(roughness * roughness, 1e-4); - float alphaSquared = alpha * alpha; - float cosineSquared = NdotX * NdotX; - return (2.0 * NdotX) / - max(NdotX + - sqrt(alphaSquared + (1.0 - alphaSquared) * cosineSquared), - 1e-6); -} - -float disneyDiffuseFactor(float NdotV, float NdotL, float LdotH, - float roughness) { - float fd90 = 0.5 + 2.0 * LdotH * LdotH * roughness; - float lightScatter = 1.0 + (fd90 - 1.0) * pow5(1.0 - NdotL); - float viewScatter = 1.0 + (fd90 - 1.0) * pow5(1.0 - NdotV); - return lightScatter * viewScatter; -} - -// GGX importance-sampled microfacet half-vector (in local TBN space, Z=up) -float3 sampleGGX(float2 u, float roughness) { - float a = roughness * roughness; - float phi = 2.0 * M_PI_F * u.x; - float cosTheta = sqrt((1.0 - u.y) / max(1.0 + (a * a - 1.0) * u.y, 1e-7)); - float sinTheta = sqrt(max(0.0, 1.0 - cosTheta * cosTheta)); - return float3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); -} - -float3 sampleGGXVNDF(float3 localView, float roughness, float2 u) { - float alpha = max(roughness * roughness, 1e-3); - float3 stretchedView = - normalizeOr(float3(alpha * localView.x, alpha * localView.y, - max(localView.z, 1e-5)), - float3(0.0, 0.0, 1.0)); - float lensq = stretchedView.x * stretchedView.x + - stretchedView.y * stretchedView.y; - float3 tangentX = lensq > 1e-7 - ? float3(-stretchedView.y, stretchedView.x, 0.0) * - rsqrt(lensq) - : float3(1.0, 0.0, 0.0); - float3 tangentY = cross(stretchedView, tangentX); - float radius = sqrt(u.x); - float phi = 2.0 * M_PI_F * u.y; - float diskX = radius * cos(phi); - float diskY = radius * sin(phi); - float blend = 0.5 * (1.0 + stretchedView.z); - diskY = mix(sqrt(max(0.0, 1.0 - diskX * diskX)), diskY, blend); - float diskZ = sqrt(max(0.0, 1.0 - diskX * diskX - diskY * diskY)); - float3 visibleNormal = diskX * tangentX + diskY * tangentY + - diskZ * stretchedView; - return normalizeOr(float3(alpha * visibleNormal.x, - alpha * visibleNormal.y, - max(visibleNormal.z, 0.0)), - float3(0.0, 0.0, 1.0)); -} - -// Full Cook-Torrance PBR for a single analytic light -float3 evalPBR(float3 albedo, float metallic, float roughness, - float reflectivity, float ior, float transmittance, float3 N, - float3 V, float3 L, float3 lightColor, float intensity) { - float3 H = normalize(V + L); - float NdotL = max(dot(N, L), 0.0); - float NdotV = max(dot(N, V), 1e-4); - float NdotH = max(dot(N, H), 0.0); - float VdotH = max(dot(V, H), 0.0); - - float clampedRoughness = clamp(roughness, 0.045, 1.0); - float3 F0 = materialF0(albedo, metallic, reflectivity, ior); - float3 F = F_Schlick(VdotH, F0); - float D = D_GGX(NdotH, clampedRoughness); - float G = G_Smith(NdotV, NdotL, clampedRoughness); - - float3 specular = (D * G * F) / max(4.0 * NdotV * NdotL, 1e-4); - float3 kD = (1.0 - F) * (1.0 - clamp(metallic, 0.0, 1.0)) * - (1.0 - clamp(transmittance, 0.0, 1.0)); - float diffuseFactor = disneyDiffuseFactor(NdotV, NdotL, max(dot(L, H), 0.0), - clampedRoughness); - float3 diffuse = (kD * albedo * diffuseFactor) / M_PI_F; - - return (diffuse + specular) * lightColor * intensity * NdotL; -} - -float3 evalSubsurface(float3 albedo, float3 N, float3 V, float3 L, - float3 lightColor, float intensity, float roughness, - float sssStrength, float sssThickness) { - float NdotL = dot(N, L); - float NdotV = max(dot(N, V), 0.0); - float backLit = clamp(-NdotL, 0.0, 1.0); - float wrapAmount = mix(0.2, 0.7, clamp(roughness, 0.0, 1.0)); - float wrapped = clamp((NdotL + wrapAmount) / (1.0 + wrapAmount), 0.0, 1.0); - float viewScatter = pow(clamp(1.0 - max(dot(V, L), 0.0), 0.0, 1.0), 2.0); - float transmission = backLit * (0.35 + 0.65 * viewScatter); - float diffuseBleed = wrapped * (0.5 + 0.5 * (1.0 - NdotV)); - float profile = mix(diffuseBleed, transmission, 0.65); - float thicknessFalloff = exp(-max(sssThickness, 0.01) * (1.0 - backLit)); - return (albedo * lightColor * intensity * sssStrength * profile * - thicknessFalloff) / - M_PI_F; -} - -float3 evalTransmission(float3 albedo, float3 N, float3 V, float3 L, - float3 lightColor, float intensity, float roughness, - float ior) { - float backLighting = max(dot(N, -L), 0.0); - float forwardAlignment = max(dot(-V, L), 0.0); - float3 F0 = float3(pow((ior - 1.0) / (ior + 1.0), 2.0)); - float3 F = F_Schlick(max(dot(N, V), 0.0), F0); - float3 transmitTint = mix(float3(1.0), albedo, 0.1); - float lobeExponent = mix(96.0, 2.0, sqrt(clamp(roughness, 0.0, 1.0))); - float transmissionLobe = pow(forwardAlignment, lobeExponent); - return (1.0 - F) * transmitTint * lightColor * intensity * backLighting * - transmissionLobe; -} - -float3 evalEmissiveTriangleLighting( - intersector isect, - primitive_acceleration_structure sceneAS, float3 P, float3 N, float3 Ng, - float3 V, float3 albedo, float metallic, float roughness, - float reflectivity, float ior, float transmittance, thread uint &rng, - constant SceneData &sceneData, - constant EmissiveTriangle *emissiveTriangles, - constant Material *materials, constant uint *primitiveObjects, - constant uint *blasPrimitiveOffsets, constant VertexData *vertices, - constant uint *indices, constant InstanceData *instanceData, - PT_MATERIAL_TEXTURE_PARAMS) { - if (sceneData.numEmissiveTriangles == 0) { - return float3(0.0); - } - float selector = rand(rng); - uint first = 0; - uint last = sceneData.numEmissiveTriangles - 1; - while (first < last) { - uint middle = first + (last - first) / 2; - if (selector <= emissiveTriangles[middle].cdf) { - last = middle; - } else { - first = middle + 1; - } - } - EmissiveTriangle light = emissiveTriangles[first]; - float sqrtU = sqrt(rand(rng)); - float barycentricV = rand(rng); - float b0 = 1.0 - sqrtU; - float b1 = sqrtU * (1.0 - barycentricV); - float b2 = sqrtU * barycentricV; - float3 lightPosition = light.p0.xyz * b0 + light.p1.xyz * b1 + - light.p2.xyz * b2; - float3 toLight = lightPosition - P; - float distanceSquared = dot(toLight, toLight); - if (distanceSquared <= 1e-8) { - return float3(0.0); - } - float distanceToLight = sqrt(distanceSquared); - float3 L = toLight / distanceToLight; - float surfaceCosine = dot(N, L); - float lightCosine = abs(dot(light.normal.xyz, -L)); - if (surfaceCosine <= 0.0 || dot(Ng, L) <= 0.0 || - lightCosine <= 1e-5 || light.area <= 1e-8 || - light.selectionPdf <= 1e-8) { - return float3(0.0); - } - float solidAnglePdf = light.selectionPdf * distanceSquared / - max(lightCosine * light.area, 1e-8); - float3 visibility = traceShadowVisibility( - isect, sceneAS, P, Ng, L, distanceToLight, rng, materials, - primitiveObjects, blasPrimitiveOffsets, vertices, indices, - instanceData, sceneData, PT_MATERIAL_TEXTURE_ARGS); - return evalPBR(albedo, metallic, roughness, reflectivity, ior, - transmittance, N, V, L, light.emission, - 1.0 / max(solidAnglePdf, 1e-8)) * - visibility; -} - -// --------------------------------------------------------------------------- -// Direct lighting with full PBR (replaces old evalDirectLighting) -// --------------------------------------------------------------------------- - -float3 evalDirectLightingPBR(intersector isect, - primitive_acceleration_structure sceneAS, float3 P, - float3 N, float3 Ng, float3 V, float3 albedo, - float metallic, float roughness, float reflectivity, - float ior, float transmittance, float sssStrength, - float sssThickness, - thread uint &rng, - constant DirectionalLightData &dirLight, - constant SceneData &sceneData, - constant PointLight *pointLights, - constant SpotLight *spotLights, - constant AreaLight *areaLights, - constant EmissiveTriangle *emissiveTriangles, - constant Material *materials, - constant uint *primitiveObjects, - constant uint *blasPrimitiveOffsets, - constant VertexData *vertices, - constant uint *indices, - constant InstanceData *instanceData, - PT_MATERIAL_TEXTURE_PARAMS) { - float3 lighting = float3(0.0); - // Directional - if (sceneData.numDirectionalLights > 0) { - float3 L = sampleDirectionalLightDirection(dirLight, rng); - float3 c = evalPBR(albedo, metallic, roughness, reflectivity, ior, - transmittance, N, V, L, dirLight.color, - max(dirLight.intensity, 0.0)); - float3 s = evalSubsurface(albedo, N, V, L, dirLight.color, - max(dirLight.intensity, 0.0), roughness, - sssStrength, sssThickness); - float3 visibility = traceShadowVisibility( - isect, sceneAS, P, Ng, L, 1e30, rng, materials, primitiveObjects, - blasPrimitiveOffsets, vertices, indices, instanceData, sceneData, - PT_MATERIAL_TEXTURE_ARGS); - lighting += (c + s * (1.0 - transmittance)) * visibility; - } - - // Point lights - for (uint i = 0; i < sceneData.numPointLights; ++i) { - float3 sampledPosition = pointLights[i].position; - float3 toLight = sampledPosition - P; - float dist = max(length(toLight), 1e-4); - float3 L = toLight / dist; - float lightRange = max(pointLights[i].range, 1e-4); - float minDist = max(lightRange * 0.08, 0.15); - float distSq = dist * dist + minDist * minDist; - float rangeFade = 1.0 - smoothstep(lightRange * 0.75, lightRange, dist); - float atten = rangeFade / max(distSq, 1e-4); - float intensity = max(pointLights[i].intensity, 0.0) * atten; - float3 c = evalPBR(albedo, metallic, roughness, reflectivity, ior, - transmittance, N, V, L, pointLights[i].color, - intensity); - float3 s = - evalSubsurface(albedo, N, V, L, pointLights[i].color, intensity, - roughness, sssStrength, sssThickness); - float3 visibility = traceShadowVisibility( - isect, sceneAS, P, Ng, L, dist, rng, materials, primitiveObjects, - blasPrimitiveOffsets, vertices, indices, instanceData, sceneData, - PT_MATERIAL_TEXTURE_ARGS); - lighting += (c + s * (1.0 - transmittance)) * visibility; - } - - // Spot lights - for (uint i = 0; i < sceneData.numSpotLights; ++i) { - float3 sampledPosition = spotLights[i].position; - float3 toLight = sampledPosition - P; - float dist = max(length(toLight), 1e-4); - float3 L = toLight / dist; - float3 fwd = normalize(spotLights[i].direction); - float spotCos = dot(-L, fwd); - float spot = - smoothstep(spotLights[i].outerCos, spotLights[i].innerCos, spotCos); - float lightRange = max(spotLights[i].range, 1e-4); - float minDist = max(lightRange * 0.08, 0.15); - float distSq = dist * dist + minDist * minDist; - float rangeFade = 1.0 - smoothstep(lightRange * 0.75, lightRange, dist); - float atten = rangeFade / max(distSq, 1e-4); - float intensity = max(spotLights[i].intensity, 0.0) * atten * spot; - float3 c = evalPBR(albedo, metallic, roughness, reflectivity, ior, - transmittance, N, V, L, spotLights[i].color, - intensity); - float3 s = - evalSubsurface(albedo, N, V, L, spotLights[i].color, intensity, - roughness, sssStrength, sssThickness); - float3 visibility = traceShadowVisibility( - isect, sceneAS, P, Ng, L, dist, rng, materials, primitiveObjects, - blasPrimitiveOffsets, vertices, indices, instanceData, sceneData, - PT_MATERIAL_TEXTURE_ARGS); - lighting += (c + s * (1.0 - transmittance)) * visibility; - } - - // Area lights - for (uint i = 0; i < sceneData.numAreaLights; ++i) { - float2 lightSample = float2(rand(rng), rand(rng)) * 2.0 - 1.0; - float3 sampledPosition = - areaLights[i].position + - areaLights[i].right * (lightSample.x * areaLights[i].halfWidth) + - areaLights[i].up * (lightSample.y * areaLights[i].halfHeight); - float3 toLight = sampledPosition - P; - float dist = max(length(toLight), 1e-4); - float3 L = toLight / dist; - float3 lightNorm = - normalize(cross(areaLights[i].right, areaLights[i].up)); - float cosLight = areaLights[i].twoSided > 0.5 - ? abs(dot(lightNorm, -L)) - : max(dot(lightNorm, -L), 0.0); - float area = 4.0 * areaLights[i].halfWidth * areaLights[i].halfHeight; - float lightPdfArea = 1.0 / max(area, 1e-6); - float distSq = max(dist * dist, 1e-6); - float atten = cosLight / max(distSq * lightPdfArea, 1e-6); - float intensity = max(areaLights[i].intensity, 0.0) * atten; - float3 c = evalPBR(albedo, metallic, roughness, reflectivity, ior, - transmittance, N, V, L, areaLights[i].color, - intensity); - float3 s = - evalSubsurface(albedo, N, V, L, areaLights[i].color, intensity, - roughness, sssStrength, sssThickness); - float3 visibility = traceShadowVisibility( - isect, sceneAS, P, Ng, L, dist, rng, materials, primitiveObjects, - blasPrimitiveOffsets, vertices, indices, instanceData, sceneData, - PT_MATERIAL_TEXTURE_ARGS); - lighting += (c + s * (1.0 - transmittance)) * visibility; - } - - lighting += evalEmissiveTriangleLighting( - isect, sceneAS, P, N, Ng, V, albedo, metallic, roughness, - reflectivity, ior, transmittance, rng, sceneData, emissiveTriangles, - materials, primitiveObjects, blasPrimitiveOffsets, vertices, indices, - instanceData, PT_MATERIAL_TEXTURE_ARGS); - - return lighting; -} - -// --------------------------------------------------------------------------- -// sampleRadiance — iterative path with GGX importance-sampled indirect bounces -// --------------------------------------------------------------------------- - -float3 sampleRadiance(uint2 gid, uint sampleIndex, uint w, - intersector isect, - primitive_acceleration_structure sceneAS, ray primaryRay, - constant Material *materials, - constant uint *primitiveObjects, - constant uint *blasPrimitiveOffsets, - constant VertexData *vertices, constant uint *indices, - constant InstanceData *instanceData, - constant DirectionalLightData &dirLight, - constant SceneData &sceneData, - constant PointLight *pointLights, - constant SpotLight *spotLights, - constant AreaLight *areaLights, - constant EmissiveTriangle *emissiveTriangles, - PT_MATERIAL_TEXTURE_PARAMS, texturecube skybox, - thread float3 &primaryAlbedo, - thread float3 &primaryNormal, - thread float3 &primaryPosition, - thread float &primaryDepth, - thread float &primaryRoughness, - thread float &primaryHitDistance, - thread uint &primaryObjectId) { - uint rng = seedBase(gid, w, sceneData.frameIndex, sampleIndex); - uint bounceLimit = min(sceneData.maxBounces, 16u); - ray surfaceRay = primaryRay; - float3 radiance = float3(0.0); - float3 throughput = float3(1.0); - float previousBsdfPdf = 0.0; - float previousEnvironmentPdf = 0.0; - bool previousEventWasDelta = true; - - for (uint depth = 0; depth <= bounceLimit; ++depth) { - auto hit = isect.intersect(surfaceRay, sceneAS); - Material mat{}; - InstanceData inst{}; - uint surfaceObjectIndex = 0xFFFFFFFFu; - float2 texUV = float2(0.0); - float3 localN = float3(0.0, 1.0, 0.0); - float3 localT = float3(1.0, 0.0, 0.0); - float3 localB = float3(0.0, 0.0, 1.0); - float3 geometricNormal = float3(0.0, 1.0, 0.0); - bool foundSurface = false; - - for (uint alphaStep = 0; alphaStep < 16; ++alphaStep) { - if (hit.type == intersection_type::none) { - break; - } - - uint primitiveIndex = - blasPrimitiveOffsets[hit.geometry_id] + hit.primitive_id; - surfaceObjectIndex = primitiveObjects[primitiveIndex]; - mat = materials[surfaceObjectIndex]; - inst = instanceData[surfaceObjectIndex]; - - uint i0 = indices[primitiveIndex * 3 + 0]; - uint i1 = indices[primitiveIndex * 3 + 1]; - uint i2 = indices[primitiveIndex * 3 + 2]; - float2 bary = hit.triangle_barycentric_coord; - float b0 = 1.0 - bary.x - bary.y; - float b1 = bary.x; - float b2 = bary.y; - - texUV = float2(vertices[i0].uv) * b0 + - float2(vertices[i1].uv) * b1 + - float2(vertices[i2].uv) * b2; - texUV = texUV * float2(mat.textureScale) + - float2(mat.textureOffset); - localN = normalizeOr(float3(vertices[i0].normal) * b0 + - float3(vertices[i1].normal) * b1 + - float3(vertices[i2].normal) * b2, - float3(0.0, 1.0, 0.0)); - localT = normalizeOr(float3(vertices[i0].tangent) * b0 + - float3(vertices[i1].tangent) * b1 + - float3(vertices[i2].tangent) * b2, - float3(1.0, 0.0, 0.0)); - localB = normalizeOr(float3(vertices[i0].bitangent) * b0 + - float3(vertices[i1].bitangent) * b1 + - float3(vertices[i2].bitangent) * b2, - float3(0.0, 0.0, 1.0)); - float3 p0 = float3(vertices[i0].position); - float3 p1 = float3(vertices[i1].position); - float3 p2 = float3(vertices[i2].position); - float3x3 normalMatrix = float3x3( - inst.normalCol0.xyz, inst.normalCol1.xyz, inst.normalCol2.xyz); - geometricNormal = normalizeOr( - cross(p1 - p0, p2 - p0), - normalizeOr(normalMatrix * localN, float3(0.0, 1.0, 0.0))); - - float alpha = resolveMaterialOpacity( - mat, texUV, sceneData.materialTextureCount, - PT_MATERIAL_TEXTURE_ARGS); - if (alpha >= 0.999 || rand(rng) < alpha) { - foundSurface = true; - break; - } - - float3 rejectedPosition = - surfaceRay.origin + surfaceRay.direction * hit.distance; - surfaceRay.origin = - rejectedPosition + surfaceRay.direction * - rayOffsetDistance(rejectedPosition); - surfaceRay.min_distance = 0.0; - hit = isect.intersect(surfaceRay, sceneAS); - } - - if (!foundSurface) { - float misWeight = previousEventWasDelta - ? 1.0 - : powerHeuristic(previousBsdfPdf, - previousEnvironmentPdf); - radiance += throughput * misWeight * - skyColor(surfaceRay.direction, 0.0, skybox, sceneData); - break; - } - - float3 shadingNormal = resolveShadingNormal( - mat, texUV, localN, localT, localB, inst, - sceneData.materialTextureCount, PT_MATERIAL_TEXTURE_ARGS); - float3 P = surfaceRay.origin + surfaceRay.direction * hit.distance; - float3 V = normalize(-surfaceRay.direction); - bool frontFace = dot(geometricNormal, V) >= 0.0; - float3 Ng = frontFace ? geometricNormal : -geometricNormal; - float3 N = dot(shadingNormal, Ng) >= 0.0 ? shadingNormal : -shadingNormal; - float shadingNormalCosine = dot(N, Ng); - if (shadingNormalCosine < 0.1) { - N = normalizeOr(N + Ng * (0.1 - shadingNormalCosine), Ng); - } - - float3 albedo; - float metallic; - float roughness; - float ao; - float3 emissive; - float ior; - float transmittance; - resolveMaterialParameters(mat, texUV, sceneData.materialTextureCount, - PT_MATERIAL_TEXTURE_ARGS, albedo, metallic, - roughness, ao, emissive, ior, transmittance); - - if (depth == 0) { - primaryAlbedo = albedo; - primaryNormal = N; - primaryPosition = P; - primaryDepth = length(P - primaryRay.origin); - primaryRoughness = roughness; - primaryHitDistance = hit.distance; - primaryObjectId = surfaceObjectIndex; - } - - float reflectivity = clamp(mat.reflectivity, 0.0, 1.0); - float sssStrength = 0.0; - float sssThickness = mix(0.25, 1.75, ao); - float3 direct = evalDirectLightingPBR( - isect, sceneAS, P, N, Ng, V, albedo, metallic, roughness, - reflectivity, ior, transmittance, sssStrength, sssThickness, rng, - dirLight, sceneData, pointLights, spotLights, areaLights, - emissiveTriangles, materials, primitiveObjects, - blasPrimitiveOffsets, vertices, indices, instanceData, - PT_MATERIAL_TEXTURE_ARGS); - radiance += throughput * direct; - if (depth == 0 || previousEventWasDelta || - sceneData.numEmissiveTriangles == 0) { - radiance += throughput * emissive; - } - - if (depth == 0 && sceneData.ambientIntensity > 0.0) { - float aoVisibility = mix(0.2, 1.0, ao); - float dielectricF0 = pow((ior - 1.0) / (ior + 1.0), 2.0); - float3 ambientF0 = mix(float3(dielectricF0), albedo, metallic); - float3 ambientF = F_Schlick(max(dot(N, V), 0.0), ambientF0); - float3 ambientDiffuse = (1.0 - ambientF) * (1.0 - metallic) * - albedo * (1.0 - transmittance); - float3 ambientSpecular = ambientF * mix(1.0, 0.35, roughness) * - (1.0 - transmittance); - float3 ambient = (ambientDiffuse + ambientSpecular) * - sceneData.ambientColor * - sceneData.ambientIntensity * aoVisibility; - radiance += throughput * ambient; - } - - float dielectricF0 = pow((ior - 1.0) / (ior + 1.0), 2.0); - float3 F0 = materialF0(albedo, metallic, mat.reflectivity, ior); - float NdotV = max(dot(N, V), 1e-4); - float3 viewFresnel = F_Schlick(NdotV, F0); - float fresnelProbability = clamp(luminance(viewFresnel), 0.001, 0.999); - float specProb = fresnelProbability; - float transmitProb = transmittance * (1.0 - metallic) * - (1.0 - fresnelProbability); - float diffuseProb = (1.0 - metallic) * (1.0 - transmittance) * - (1.0 - fresnelProbability); - float eta = frontFace ? 1.0 / ior : ior; - float3 idealRefractedDirection = refract(-V, N, eta); - bool totalInternalReflection = - dot(idealRefractedDirection, idealRefractedDirection) < 1e-8; - if (totalInternalReflection) { - specProb += transmitProb; - transmitProb = 0.0; - } - float probabilitySum = - max(specProb + transmitProb + diffuseProb, 1e-4); - specProb /= probabilitySum; - transmitProb /= probabilitySum; - diffuseProb /= probabilitySum; - - float3x3 basis = buildOrthonormalBasis(N); - if (sceneData.environmentEnabled != 0 && - diffuseProb + specProb > 1e-4) { - float3 localEnvironmentDirection = - cosineSampleHemisphere(float2(rand(rng), rand(rng))); - float3 environmentDirection = - normalizeOr(basis * localEnvironmentDirection, N); - float NdotEnvironment = dot(N, environmentDirection); - if (NdotEnvironment > 0.0 && - dot(Ng, environmentDirection) > 0.0) { - float3 visibility = traceShadowVisibility( - isect, sceneAS, P, Ng, environmentDirection, 1e30, rng, - materials, primitiveObjects, blasPrimitiveOffsets, - vertices, indices, instanceData, sceneData, - PT_MATERIAL_TEXTURE_ARGS); - if (luminance(visibility) <= 0.001) { - visibility = float3(0.0); - } - float3 H = normalizeOr(V + environmentDirection, N); - float NdotH = max(dot(N, H), 1e-5); - float VdotH = max(dot(V, H), 1e-5); - float3 F = F_Schlick(VdotH, F0); - float3 kD = (1.0 - F) * (1.0 - metallic) * - (1.0 - transmittance); - float diffuseFactor = disneyDiffuseFactor( - NdotV, NdotEnvironment, - max(dot(environmentDirection, H), 0.0), roughness); - float3 reflectionBsdf = - kD * albedo * diffuseFactor / M_PI_F; - float environmentPdf = NdotEnvironment / M_PI_F; - float bsdfPdf = diffuseProb * environmentPdf; - if (roughness > 0.025 && specProb > 1e-4) { - float D = D_GGX(NdotH, roughness); - float G1V = G1_SmithGGX(NdotV, roughness); - float G1L = - G1_SmithGGX(NdotEnvironment, roughness); - reflectionBsdf += - D * G1V * G1L * F / - max(4.0 * NdotV * NdotEnvironment, 1e-6); - bsdfPdf += specProb * D * G1V / - max(4.0 * NdotV, 1e-6); - } - float competingBsdfPdf = depth < bounceLimit ? bsdfPdf : 0.0; - float misWeight = - powerHeuristic(environmentPdf, competingBsdfPdf); - float3 environmentRadiance = skyColor( - environmentDirection, 0.0, skybox, sceneData); - radiance += throughput * reflectionBsdf * - environmentRadiance * visibility * NdotEnvironment * - misWeight / max(environmentPdf, 1e-6); - } - } - - if (depth == bounceLimit) { - break; - } - - float choice = rand(rng); - float3 bounceWeight = float3(0.0); - float3 nextDirection = N; - float sampledBsdfPdf = 0.0; - float sampledEnvironmentPdf = 0.0; - bool sampledEventWasDelta = true; - - if (choice < specProb && specProb > 1e-4) { - if (roughness <= 0.025 || totalInternalReflection) { - nextDirection = reflect(-V, N); - float3 F = totalInternalReflection - ? float3(1.0) - : F_Schlick(NdotV, F0); - bounceWeight = F / max(specProb, 1e-4); - } else { - float3 localView = - float3(dot(V, basis[0]), dot(V, basis[1]), dot(V, N)); - float3 localH = sampleGGXVNDF( - localView, roughness, float2(rand(rng), rand(rng))); - float3 H = normalizeOr(basis * localH, N); - float VdotH = max(dot(V, H), 1e-5); - nextDirection = reflect(-V, H); - float NdotL = dot(N, nextDirection); - if (NdotL > 0.0 && dot(nextDirection, Ng) > 0.0) { - float NdotH = max(dot(N, H), 1e-5); - float D = D_GGX(NdotH, roughness); - float G1V = G1_SmithGGX(NdotV, roughness); - float G1L = G1_SmithGGX(NdotL, roughness); - float3 F = F_Schlick(VdotH, F0); - float3 specularBsdf = - D * G1V * G1L * F / - max(4.0 * NdotV * NdotL, 1e-6); - float conditionalPdf = - D * G1V / max(4.0 * NdotV, 1e-6); - float combinedPdf = specProb * conditionalPdf; - bounceWeight = specularBsdf * NdotL / - max(combinedPdf, 1e-6); - sampledBsdfPdf = combinedPdf; - sampledEnvironmentPdf = NdotL / M_PI_F; - sampledEventWasDelta = false; - } - } - } else if (choice < specProb + transmitProb && - transmitProb > 1e-4) { - nextDirection = idealRefractedDirection; - float fresnelCosine = NdotV; - if (roughness > 0.025) { - float3 localView = - float3(dot(V, basis[0]), dot(V, basis[1]), dot(V, N)); - float3 localH = sampleGGXVNDF( - localView, roughness, float2(rand(rng), rand(rng))); - float3 H = normalizeOr(basis * localH, N); - float3 roughRefractedDirection = refract(-V, H, eta); - if (dot(roughRefractedDirection, roughRefractedDirection) > - 1e-8 && - dot(roughRefractedDirection, Ng) < 0.0) { - nextDirection = roughRefractedDirection; - fresnelCosine = max(dot(V, H), 0.0); - } - } - float3 F = F_Schlick(fresnelCosine, float3(dielectricF0)); - float3 tint = mix(float3(1.0), albedo, 0.15); - bounceWeight = (1.0 - F) * tint / - max(transmitProb, 1e-4); - } else { - float3 localDirection = - cosineSampleHemisphere(float2(rand(rng), rand(rng))); - nextDirection = normalizeOr(basis * localDirection, N); - float NdotL = max(dot(N, nextDirection), 0.0); - float3 H = normalizeOr(V + nextDirection, N); - float3 F = F_Schlick(max(dot(V, H), 0.0), F0); - float3 kD = (1.0 - F) * (1.0 - metallic) * - (1.0 - transmittance); - float diffuseFactor = disneyDiffuseFactor( - NdotV, NdotL, max(dot(nextDirection, H), 0.0), roughness); - float3 diffuseBsdf = kD * albedo * diffuseFactor / M_PI_F; - float conditionalPdf = NdotL / M_PI_F; - float combinedPdf = diffuseProb * conditionalPdf; - bounceWeight = diffuseBsdf * NdotL / - max(combinedPdf, 1e-6); - sampledBsdfPdf = combinedPdf; - sampledEnvironmentPdf = conditionalPdf; - sampledEventWasDelta = false; - } - - bounceWeight = clampLuminance(max(bounceWeight, float3(0.0)), 16.0); - throughput *= bounceWeight; - throughput = clampLuminance(throughput, 32.0); - if (depth == 0) { - throughput *= max(sceneData.indirectStrength, 0.0); - } - if (!all(isfinite(throughput)) || max(throughput.x, - max(throughput.y, throughput.z)) < - 1e-5) { - break; - } - - if (depth >= 2) { - float survival = clamp(max(throughput.x, - max(throughput.y, throughput.z)), - 0.05, 0.95); - if (rand(rng) > survival) { - break; - } - throughput /= survival; - } - - previousBsdfPdf = sampledBsdfPdf; - previousEnvironmentPdf = sampledEnvironmentPdf; - previousEventWasDelta = sampledEventWasDelta; - - surfaceRay.origin = offsetRayOrigin(P, Ng, nextDirection); - surfaceRay.direction = normalizeOr(nextDirection, N); - surfaceRay.min_distance = 0.0; - surfaceRay.max_distance = 1.0e30; - } - - return radiance; -} - -kernel void main0(texture2d outTex [[texture(0)]], - texture2d historyTex [[texture(1)]], - texture2d brightTex [[texture(2)]], - texture2d albedoRoughnessTex [[texture(3)]], - texture2d normalDepthTex [[texture(4)]], - texture2d motionObjectTex [[texture(5)]], - texture2d historyMomentsTex [[texture(6)]], - texture2d historyGuideTex [[texture(7)]], - texture2d historyOutTex [[texture(8)]], - texture2d historyGuideOutTex [[texture(9)]], - texture2d historyMomentsOutTex [[texture(10)]], - primitive_acceleration_structure sceneAS [[buffer(0)]], - constant CameraUniforms &cam [[buffer(1)]], - constant Material *materials [[buffer(2)]], - constant uint *primitiveObjects [[buffer(3)]], - constant VertexData *vertices [[buffer(4)]], - constant uint *indices [[buffer(5)]], - constant InstanceData *instanceData [[buffer(6)]], - constant DirectionalLightData &dirLight [[buffer(7)]], - constant SceneData &sceneData [[buffer(8)]], - constant PointLight *pointLights [[buffer(9)]], - constant SpotLight *spotLights [[buffer(10)]], - constant AreaLight *areaLights [[buffer(11)]], - constant EmissiveTriangle *emissiveTriangles [[buffer(14)]], - PT_MATERIAL_TEXTURE_BINDINGS, - constant uint *blasPrimitiveOffsets [[buffer(13)]], - texturecube skybox [[texture(60)]], - uint2 gid [[thread_position_in_grid]]) { - uint w = outTex.get_width(); - uint h = outTex.get_height(); - uint pixelStride = max(sceneData.pixelStride, 1u); - gid *= pixelStride; - if (gid.x >= w || gid.y >= h) - return; - - float2 uv = (float2(gid) + 0.5) / float2(w, h); - float3 ro = cam.camPos; - - intersector isect; - isect.assume_geometry_type(geometry_type::triangle); - isect.set_triangle_cull_mode(triangle_cull_mode::none); - - float3 color = float3(0.0); - float3 primaryAlbedo = float3(0.0); - float3 primaryNormal = float3(0.0); - float3 primaryPosition = float3(0.0); - float primaryDepth = 0.0; - float primaryRoughness = 1.0; - float primaryHitDistance = 0.0; - uint primaryObjectId = 0xFFFFFFFFu; - - uint spp = max(sceneData.raysPerPixel, 1u); - for (uint s = 0; s < spp; ++s) { - uint cameraRng = seedBase(gid, w, sceneData.frameIndex, - s + 0x9E3779B9u); - float2 pixelJitter = s == 0 - ? float2(0.0) - : float2(rand(cameraRng), rand(cameraRng)) - - 0.5; - float2 sampleUv = (float2(gid) + 0.5 + pixelJitter) / float2(w, h); - float2 sampleNdc = sampleUv * 2.0 - 1.0; - sampleNdc.y = -sampleNdc.y; - float4 sampleClip = float4(sampleNdc, 1.0, 1.0); - float4 sampleWorldH = cam.invViewProj * sampleClip; - float3 sampleWorldP = sampleWorldH.xyz / sampleWorldH.w; - - ray primaryRay; - primaryRay.origin = ro; - primaryRay.direction = normalize(sampleWorldP - ro); - primaryRay.min_distance = 0.001; - primaryRay.max_distance = 1.0e30; - - float3 sampleAlbedo = float3(0.0); - float3 sampleNormal = float3(0.0); - float3 samplePosition = float3(0.0); - float sampleDepth = 0.0; - float sampleRoughness = 1.0; - float sampleHitDistance = 0.0; - uint sampleObjectId = 0xFFFFFFFFu; - - float3 sample = sampleRadiance( - gid, s, w, isect, sceneAS, primaryRay, materials, primitiveObjects, - blasPrimitiveOffsets, vertices, indices, instanceData, dirLight, - sceneData, pointLights, spotLights, areaLights, - emissiveTriangles, PT_MATERIAL_TEXTURE_ARGS, skybox, sampleAlbedo, - sampleNormal, samplePosition, sampleDepth, sampleRoughness, - sampleHitDistance, sampleObjectId); - if (!all(isfinite(sample))) { - sample = float3(0.0); - } - color += clampLuminance(max(sample, float3(0.0)), - max(sceneData.fireflyClamp, 1.0)); - if (s == 0) { - primaryAlbedo = sampleAlbedo; - primaryNormal = sampleNormal; - primaryPosition = samplePosition; - primaryDepth = sampleDepth; - primaryRoughness = sampleRoughness; - primaryHitDistance = sampleHitDistance; - primaryObjectId = sampleObjectId; - } - } - - color /= float(spp); - if (!all(isfinite(color))) { - color = float3(0.0); - } - - float objectIdValue = primaryObjectId == 0xFFFFFFFFu - ? -1.0 - : float(primaryObjectId); - float2 encodedNormal = encodeNormal(primaryNormal); - float4 currentGuide = - float4(encodedNormal, primaryDepth, objectIdValue); - float4 previousClip = cam.prevViewProj * float4(primaryPosition, 1.0); - float2 previousNdc = previousClip.xy / max(abs(previousClip.w), 0.0001); - float2 previousUv = float2(previousNdc.x * 0.5 + 0.5, - 0.5 - previousNdc.y * 0.5); - bool previousUvValid = previousClip.w > 0.0 && - all(previousUv >= float2(0.0)) && - all(previousUv <= float2(1.0)); - uint2 previousPixel = gid; - if (primaryObjectId != 0xFFFFFFFFu && previousUvValid) { - previousPixel = uint2(clamp(previousUv * float2(w, h), float2(0.0), - float2(w - 1, h - 1))); - } - float4 prevColor = historyTex.read(previousPixel); - float4 previousGuide = historyGuideTex.read(previousPixel); - float4 previousMoments = historyMomentsTex.read(previousPixel); - bool historyValid = sceneData.frameIndex > 0 && prevColor.w > 0.0 && - abs(previousGuide.z - primaryDepth) < - max(0.02, primaryDepth * 0.01) && - distance(previousGuide.xy, encodedNormal) < 0.04 && - abs(previousGuide.w - objectIdValue) < 0.5; - if (!historyValid) { - prevColor = float4(0.0); - previousMoments = float4(0.0); - } - float previousMean = historyValid ? previousMoments.x : 0.0; - float previousVariance = - historyValid - ? max(previousMoments.y - previousMean * previousMean, 0.0) - : 0.0; - float sampleLuminanceLimit = max(sceneData.fireflyClamp, 1.0); - if (historyValid && prevColor.w >= 4.0) { - float statisticalLimit = previousMean + - max(0.5, 6.0 * sqrt(previousVariance)); - sampleLuminanceLimit = - min(sampleLuminanceLimit, max(4.0, statisticalLimit)); - } - color = clampLuminance(color, sampleLuminanceLimit); - float historyLimit = max(float(sceneData.accumulationFrameLimit), 1.0); - float previousWeight = - historyValid ? min(prevColor.w, max(historyLimit - 1.0, 0.0)) : 0.0; - float newHistoryLength = min(previousWeight + 1.0, historyLimit); - float accumulationDenominator = max(previousWeight + 1.0, 1.0); - float3 accum = - (prevColor.xyz * previousWeight + color) / accumulationDenominator; - float moment = luminance(color); - float accumulatedMoment = - (previousMoments.x * previousWeight + moment) / - accumulationDenominator; - float accumulatedMomentSquared = - (previousMoments.y * previousWeight + moment * moment) / - accumulationDenominator; - float variance = max(accumulatedMomentSquared - - accumulatedMoment * accumulatedMoment, - 0.0); - - constexpr float bloomKnee = 0.35; - - float brightness = luminance(accum); - float soft = clamp(brightness - sceneData.bloomThreshold + bloomKnee, 0.0, - bloomKnee * 2.0); - soft = soft * soft / max(bloomKnee * 4.0, 0.00001); - float contribution = max(brightness - sceneData.bloomThreshold, soft) / - max(brightness, 0.00001); - float3 brightColor = accum * contribution; - float2 motion = previousUvValid ? uv - previousUv : float2(0.0); - - for (uint y = 0; y < pixelStride; ++y) { - for (uint x = 0; x < pixelStride; ++x) { - uint2 pixel = gid + uint2(x, y); - if (pixel.x >= w || pixel.y >= h) { - continue; - } - historyOutTex.write(float4(accum, newHistoryLength), pixel); - historyGuideOutTex.write(currentGuide, pixel); - albedoRoughnessTex.write(float4(primaryAlbedo, primaryRoughness), - pixel); - normalDepthTex.write(float4(primaryNormal, primaryDepth), pixel); - motionObjectTex.write(float4(motion, objectIdValue, 1.0), pixel); - historyMomentsOutTex.write( - float4(accumulatedMoment, accumulatedMomentSquared, variance, - primaryHitDistance), - pixel); - outTex.write(float4(accum, 1.0), pixel); - brightTex.write(float4(brightColor, 1.0), pixel); - } - } -} diff --git a/shaders/metal/shadows/depth.vert.metal b/shaders/metal/shadows/depth.vert.metal deleted file mode 100644 index d70b6ba8..00000000 --- a/shaders/metal/shadows/depth.vert.metal +++ /dev/null @@ -1,54 +0,0 @@ -#include -#include - -using namespace metal; - -struct UBO -{ - float4x4 model; - float4x4 view; - float4x4 projection; - uint isInstanced; -}; - -struct main0_out -{ - float4 gl_Position [[position, invariant]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; - float4 instanceModel_0 [[attribute(6)]]; - float4 instanceModel_1 [[attribute(7)]]; - float4 instanceModel_2 [[attribute(8)]]; - float4 instanceModel_3 [[attribute(9)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]], constant UBO& _12 [[buffer(0)]]) -{ - main0_out out = {}; - float4x4 instanceModel = {}; - instanceModel[0] = in.instanceModel_0; - instanceModel[1] = in.instanceModel_1; - instanceModel[2] = in.instanceModel_2; - instanceModel[3] = in.instanceModel_3; - bool hasInstanceMatrix = abs(instanceModel[3].w) > 0.5; - if ((_12.isInstanced != 0u) && hasInstanceMatrix) - { - float4x4 _36 = _12.projection * _12.view; - float4x4 _40 = _36 * instanceModel; - float4 _49 = float4(in.aPos, 1.0); - float4 _50 = _40 * _49; - out.gl_Position = _50; - } - else - { - float4x4 _58 = _12.projection * _12.view; - float4x4 _61 = _58 * _12.model; - float4 _66 = float4(in.aPos, 1.0); - float4 _67 = _61 * _66; - out.gl_Position = _67; - } - return out; -} diff --git a/shaders/metal/shadows/empty.frag.metal b/shaders/metal/shadows/empty.frag.metal deleted file mode 100644 index 92ac1d9f..00000000 --- a/shaders/metal/shadows/empty.frag.metal +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include - -using namespace metal; - -fragment void main0() -{ -} - diff --git a/shaders/metal/shadows/point_depth.frag.metal b/shaders/metal/shadows/point_depth.frag.metal deleted file mode 100644 index f6831b19..00000000 --- a/shaders/metal/shadows/point_depth.frag.metal +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include - -using namespace metal; - -struct Uniforms -{ - packed_float3 lightPos; - float far_plane; -}; - -struct main0_out -{ - float gl_FragDepth [[depth(any)]]; -}; - -struct main0_in -{ - float4 FragPos [[user(locn0)]]; -}; - -fragment main0_out main0(main0_in in [[stage_in]], constant Uniforms& _17 [[buffer(0)]]) -{ - main0_out out = {}; - float lightDistance = length(in.FragPos.xyz - float3(_17.lightPos)); - lightDistance /= _17.far_plane; - out.gl_FragDepth = lightDistance; - return out; -} - diff --git a/shaders/metal/shadows/point_depth.geom.metal b/shaders/metal/shadows/point_depth.geom.metal deleted file mode 100644 index 5f064eeb..00000000 --- a/shaders/metal/shadows/point_depth.geom.metal +++ /dev/null @@ -1,34 +0,0 @@ -#include -#include - -using namespace metal; - -struct ShadowMatrices -{ - float4x4 shadowMatrices[6]; -}; - -struct main0_out -{ - float4 FragPos; - float4 gl_Position; - uint gl_Layer; -}; - -unknown main0_out main0(constant ShadowMatrices& _55 [[buffer(0)]]) -{ - main0_out out = {}; - for (int face = 0; face < 6; face++) - { - out.gl_Layer = uint(face); - for (int i = 0; i < 3; i++) - { - out.FragPos = _RESERVED_IDENTIFIER_FIXUP_gl_in[i].out.gl_Position; - out.gl_Position = _55.shadowMatrices[face] * out.FragPos; - EmitVertex(); - } - EndPrimitive(); - } - return out; -} - diff --git a/shaders/metal/shadows/point_depth.vert.metal b/shaders/metal/shadows/point_depth.vert.metal deleted file mode 100644 index ec42fab8..00000000 --- a/shaders/metal/shadows/point_depth.vert.metal +++ /dev/null @@ -1,44 +0,0 @@ -#include -#include - -using namespace metal; - -struct UBO -{ - float4x4 model; - uint isInstanced; -}; - -struct main0_out -{ - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; - float4 instanceModel_0 [[attribute(6)]]; - float4 instanceModel_1 [[attribute(7)]]; - float4 instanceModel_2 [[attribute(8)]]; - float4 instanceModel_3 [[attribute(9)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]], constant UBO& _12 [[buffer(0)]]) -{ - main0_out out = {}; - float4x4 instanceModel = {}; - instanceModel[0] = in.instanceModel_0; - instanceModel[1] = in.instanceModel_1; - instanceModel[2] = in.instanceModel_2; - instanceModel[3] = in.instanceModel_3; - bool hasInstanceMatrix = abs(instanceModel[3].w) > 0.5; - if ((_12.isInstanced != 0u) && hasInstanceMatrix) - { - out.gl_Position = (_12.model * instanceModel) * float4(in.aPos, 1.0); - } - else - { - out.gl_Position = _12.model * float4(in.aPos, 1.0); - } - return out; -} diff --git a/shaders/metal/shadows/point_depth_nogeom.frag.metal b/shaders/metal/shadows/point_depth_nogeom.frag.metal deleted file mode 100644 index f6831b19..00000000 --- a/shaders/metal/shadows/point_depth_nogeom.frag.metal +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include - -using namespace metal; - -struct Uniforms -{ - packed_float3 lightPos; - float far_plane; -}; - -struct main0_out -{ - float gl_FragDepth [[depth(any)]]; -}; - -struct main0_in -{ - float4 FragPos [[user(locn0)]]; -}; - -fragment main0_out main0(main0_in in [[stage_in]], constant Uniforms& _17 [[buffer(0)]]) -{ - main0_out out = {}; - float lightDistance = length(in.FragPos.xyz - float3(_17.lightPos)); - lightDistance /= _17.far_plane; - out.gl_FragDepth = lightDistance; - return out; -} - diff --git a/shaders/metal/shadows/point_depth_nogeom.vert.metal b/shaders/metal/shadows/point_depth_nogeom.vert.metal deleted file mode 100644 index c9d78d44..00000000 --- a/shaders/metal/shadows/point_depth_nogeom.vert.metal +++ /dev/null @@ -1,54 +0,0 @@ -#include -#include - -using namespace metal; - -struct UBO -{ - float4x4 model; - uint isInstanced; -}; - -struct ShadowUniforms -{ - float4x4 shadowMatrix; - int faceIndex; -}; - -struct main0_out -{ - float4 FragPos [[user(locn0)]]; - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; - float4 instanceModel_0 [[attribute(6)]]; - float4 instanceModel_1 [[attribute(7)]]; - float4 instanceModel_2 [[attribute(8)]]; - float4 instanceModel_3 [[attribute(9)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]], constant UBO& _12 [[buffer(0)]], constant ShadowUniforms& _62 [[buffer(1)]]) -{ - main0_out out = {}; - float4x4 instanceModel = {}; - instanceModel[0] = in.instanceModel_0; - instanceModel[1] = in.instanceModel_1; - instanceModel[2] = in.instanceModel_2; - instanceModel[3] = in.instanceModel_3; - float4 worldPos; - bool hasInstanceMatrix = abs(instanceModel[3].w) > 0.5; - if ((_12.isInstanced != 0u) && hasInstanceMatrix) - { - worldPos = (_12.model * instanceModel) * float4(in.aPos, 1.0); - } - else - { - worldPos = _12.model * float4(in.aPos, 1.0); - } - out.FragPos = worldPos; - out.gl_Position = _62.shadowMatrix * worldPos; - return out; -} diff --git a/shaders/metal/shadows/ssao_blur.frag.metal b/shaders/metal/shadows/ssao_blur.frag.metal deleted file mode 100644 index 64c12b74..00000000 --- a/shaders/metal/shadows/ssao_blur.frag.metal +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include - -using namespace metal; - -struct main0_out -{ - float FragColor [[color(0)]]; -}; - -struct main0_in -{ - float2 TexCoord [[user(locn0)]]; -}; - -fragment main0_out main0(main0_in in [[stage_in]], texture2d inSSAO [[texture(0)]], sampler inSSAOSmplr [[sampler(0)]]) -{ - main0_out out = {}; - float2 texelSize = float2(1.0) / float2(int2(inSSAO.get_width(), inSSAO.get_height())); - float result = 0.0; - for (int x = -2; x <= 2; x++) - { - for (int y = -2; y <= 2; y++) - { - float2 offset = float2(float(x), float(y)) * texelSize; - result += inSSAO.sample(inSSAOSmplr, (in.TexCoord + offset)).x; - } - } - out.FragColor = result / 25.0; - return out; -} - diff --git a/shaders/metal/simple/color.frag.metal b/shaders/metal/simple/color.frag.metal deleted file mode 100644 index 81fc8c11..00000000 --- a/shaders/metal/simple/color.frag.metal +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include - -using namespace metal; - -struct main0_out -{ - float4 FragColor [[color(0)]]; - float4 BrightColor [[color(1)]]; -}; - -struct main0_in -{ - float4 vertexColor [[user(locn0)]]; -}; - -fragment main0_out main0(main0_in in [[stage_in]]) -{ - main0_out out = {}; - float3 color = in.vertexColor.xyz / (in.vertexColor.xyz + float3(1.0)); - out.FragColor = float4(color, in.vertexColor.w); - if (length(color) > 1.0) - { - out.BrightColor = float4(color, in.vertexColor.w); - } - return out; -} - diff --git a/shaders/metal/simple/color.vert.metal b/shaders/metal/simple/color.vert.metal deleted file mode 100644 index 538a514e..00000000 --- a/shaders/metal/simple/color.vert.metal +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include - -using namespace metal; - -struct UBO -{ - float4x4 model; - float4x4 view; - float4x4 projection; - uint isInstanced; -}; - -struct main0_out -{ - float4 vertexColor [[user(locn0)]]; - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; - float4 aColor [[attribute(1)]]; - float4 instanceModel_0 [[attribute(6)]]; - float4 instanceModel_1 [[attribute(7)]]; - float4 instanceModel_2 [[attribute(8)]]; - float4 instanceModel_3 [[attribute(9)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]], constant UBO& _12 [[buffer(0)]]) -{ - main0_out out = {}; - float4x4 instanceModel = {}; - instanceModel[0] = in.instanceModel_0; - instanceModel[1] = in.instanceModel_1; - instanceModel[2] = in.instanceModel_2; - instanceModel[3] = in.instanceModel_3; - float4x4 mvp; - bool hasInstanceMatrix = abs(instanceModel[3].w) > 0.5; - if ((_12.isInstanced != 0u) && hasInstanceMatrix) - { - mvp = (_12.projection * _12.view) * instanceModel; - } - else - { - mvp = (_12.projection * _12.view) * _12.model; - } - out.gl_Position = mvp * float4(in.aPos, 1.0); - out.vertexColor = in.aColor; - return out; -} diff --git a/shaders/metal/simple/debug.frag.metal b/shaders/metal/simple/debug.frag.metal deleted file mode 100644 index 5af10475..00000000 --- a/shaders/metal/simple/debug.frag.metal +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include - -using namespace metal; - -struct main0_out -{ - float4 FragColor [[color(0)]]; -}; - -fragment main0_out main0() -{ - main0_out out = {}; - out.FragColor = float4(1.0, 0.0, 1.0, 1.0); - return out; -} - diff --git a/shaders/metal/simple/debug.vert.metal b/shaders/metal/simple/debug.vert.metal deleted file mode 100644 index bd53378f..00000000 --- a/shaders/metal/simple/debug.vert.metal +++ /dev/null @@ -1,22 +0,0 @@ -#include -#include - -using namespace metal; - -struct main0_out -{ - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]]) -{ - main0_out out = {}; - out.gl_Position = float4(in.aPos, 1.0); - return out; -} - diff --git a/shaders/metal/simple/texture.frag.metal b/shaders/metal/simple/texture.frag.metal deleted file mode 100644 index 03dd9fc1..00000000 --- a/shaders/metal/simple/texture.frag.metal +++ /dev/null @@ -1,164 +0,0 @@ -#pragma clang diagnostic ignored "-Wmissing-prototypes" - -#include -#include - -using namespace metal; - -struct UBO -{ - uint useTexture; - uint onlyTexture; - int textureCount; -}; - -struct main0_out -{ - float4 FragColor [[color(0)]]; -}; - -struct main0_in -{ - float2 TexCoord [[user(locn0)]]; - float4 outColor [[user(locn1)]]; -}; - -static inline __attribute__((always_inline)) -float4 calculateAllTextures(constant UBO& _28, texture2d texture1, sampler texture1Smplr, thread float2& TexCoord, texture2d texture2, sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, texture2d texture4, sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, texture2d texture6, sampler texture6Smplr, texture2d texture7, sampler texture7Smplr, texture2d texture8, sampler texture8Smplr, texture2d texture9, sampler texture9Smplr, texture2d texture10, sampler texture10Smplr, texture2d texture11, sampler texture11Smplr, texture2d texture12, sampler texture12Smplr, texture2d texture13, sampler texture13Smplr, texture2d texture14, sampler texture14Smplr, texture2d texture15, sampler texture15Smplr, texture2d texture16, sampler texture16Smplr) -{ - float4 color = float4(0.0); - for (int i = 0; i < _28.textureCount; i++) - { - if (i == 0) - { - color += texture1.sample(texture1Smplr, TexCoord); - } - else - { - if (i == 1) - { - color += texture2.sample(texture2Smplr, TexCoord); - } - else - { - if (i == 2) - { - color += texture3.sample(texture3Smplr, TexCoord); - } - else - { - if (i == 3) - { - color += texture4.sample(texture4Smplr, TexCoord); - } - else - { - if (i == 4) - { - color += texture5.sample(texture5Smplr, TexCoord); - } - else - { - if (i == 5) - { - color += texture6.sample(texture6Smplr, TexCoord); - } - else - { - if (i == 6) - { - color += texture7.sample(texture7Smplr, TexCoord); - } - else - { - if (i == 7) - { - color += texture8.sample(texture8Smplr, TexCoord); - } - else - { - if (i == 8) - { - color += texture9.sample(texture9Smplr, TexCoord); - } - else - { - if (i == 9) - { - color += texture10.sample(texture10Smplr, TexCoord); - } - else - { - if (i == 10) - { - color += texture11.sample(texture11Smplr, TexCoord); - } - else - { - if (i == 11) - { - color += texture12.sample(texture12Smplr, TexCoord); - } - else - { - if (i == 12) - { - color += texture13.sample(texture13Smplr, TexCoord); - } - else - { - if (i == 13) - { - color += texture14.sample(texture14Smplr, TexCoord); - } - else - { - if (i == 14) - { - color += texture15.sample(texture15Smplr, TexCoord); - } - else - { - if (i == 15) - { - color += texture16.sample(texture16Smplr, TexCoord); - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - color /= float4(float(_28.textureCount)); - return color; -} - -fragment main0_out main0(main0_in in [[stage_in]], constant UBO& _28 [[buffer(0)]], texture2d texture1 [[texture(0)]], texture2d texture2 [[texture(1)]], texture2d texture3 [[texture(2)]], texture2d texture4 [[texture(3)]], texture2d texture5 [[texture(4)]], texture2d texture6 [[texture(5)]], texture2d texture7 [[texture(6)]], texture2d texture8 [[texture(7)]], texture2d texture9 [[texture(8)]], texture2d texture10 [[texture(9)]], texture2d texture11 [[texture(10)]], texture2d texture12 [[texture(11)]], texture2d texture13 [[texture(12)]], texture2d texture14 [[texture(13)]], texture2d texture15 [[texture(14)]], texture2d texture16 [[texture(15)]], sampler texture1Smplr [[sampler(0)]], sampler texture2Smplr [[sampler(1)]], sampler texture3Smplr [[sampler(2)]], sampler texture4Smplr [[sampler(3)]], sampler texture5Smplr [[sampler(4)]], sampler texture6Smplr [[sampler(5)]], sampler texture7Smplr [[sampler(6)]], sampler texture8Smplr [[sampler(7)]], sampler texture9Smplr [[sampler(8)]], sampler texture10Smplr [[sampler(9)]], sampler texture11Smplr [[sampler(10)]], sampler texture12Smplr [[sampler(11)]], sampler texture13Smplr [[sampler(12)]], sampler texture14Smplr [[sampler(13)]], sampler texture15Smplr [[sampler(14)]], sampler texture16Smplr [[sampler(15)]]) -{ - main0_out out = {}; - if (_28.onlyTexture != 0u) - { - out.FragColor = calculateAllTextures(_28, texture1, texture1Smplr, in.TexCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr, texture11, texture11Smplr, texture12, texture12Smplr, texture13, texture13Smplr, texture14, texture14Smplr, texture15, texture15Smplr, texture16, texture16Smplr); - return out; - } - if (_28.useTexture != 0u) - { - out.FragColor = calculateAllTextures(_28, texture1, texture1Smplr, in.TexCoord, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr, texture11, texture11Smplr, texture12, texture12Smplr, texture13, texture13Smplr, texture14, texture14Smplr, texture15, texture15Smplr, texture16, texture16Smplr) * in.outColor; - } - else - { - out.FragColor = in.outColor; - } - return out; -} - diff --git a/shaders/metal/simple/texture.vert.metal b/shaders/metal/simple/texture.vert.metal deleted file mode 100644 index 6d02de27..00000000 --- a/shaders/metal/simple/texture.vert.metal +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include - -using namespace metal; - -struct UBO -{ - float4x4 model; - float4x4 view; - float4x4 projection; -}; - -struct main0_out -{ - float2 TexCoord [[user(locn0)]]; - float4 outColor [[user(locn1)]]; - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; - float4 aColor [[attribute(1)]]; - float2 aTexCoord [[attribute(2)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]], constant UBO& _13 [[buffer(0)]]) -{ - main0_out out = {}; - float4x4 mvp = (_13.projection * _13.view) * _13.model; - out.gl_Position = mvp * float4(in.aPos, 1.0); - out.TexCoord = in.aTexCoord; - out.outColor = in.aColor; - return out; -} - diff --git a/shaders/metal/terrain/fluid.frag.metal b/shaders/metal/terrain/fluid.frag.metal deleted file mode 100644 index f7a2cc6e..00000000 --- a/shaders/metal/terrain/fluid.frag.metal +++ /dev/null @@ -1,226 +0,0 @@ -#include -#include - -using namespace metal; - -struct Uniforms -{ - float4 waterColor; - packed_float3 cameraPos; - float time; - float4x4 projection; - float4x4 view; - float4x4 invProjection; - float4x4 invView; - float3 lightDirection; - float3 lightColor; -}; - -struct Parameters -{ - float refractionStrength; - float reflectionStrength; - float depthFade; - int hasNormalTexture; - int hasMovementTexture; - float3 windForce; -}; - -struct main0_out -{ - float4 FragColor [[color(0)]]; - float4 BrightColor [[color(1)]]; -}; - -struct main0_in -{ - float2 TexCoord [[user(locn0)]]; - float3 WorldPos [[user(locn1)]]; - float3 WorldNormal [[user(locn2)]]; - float3 WorldTangent [[user(locn3)]]; - float3 WorldBitangent [[user(locn4)]]; -}; - -fragment main0_out main0(main0_in in [[stage_in]], constant Uniforms& _19 [[buffer(0)]], constant Parameters& _68 [[buffer(1)]], texture2d movementTexture [[texture(0)]], texture2d normalTexture [[texture(1)]], texture2d reflectionTexture [[texture(2)]], texture2d refractionTexture [[texture(3)]], texture2d sceneTexture [[texture(4)]], sampler movementTextureSmplr [[sampler(0)]], sampler normalTextureSmplr [[sampler(1)]], sampler reflectionTextureSmplr [[sampler(2)]], sampler refractionTextureSmplr [[sampler(3)]], sampler sceneTextureSmplr [[sampler(4)]]) -{ - main0_out out = {}; - float3 normal = fast::normalize(in.WorldNormal); - float3 viewDir = fast::normalize(float3(_19.cameraPos) - in.WorldPos); - float4 clipSpace = (_19.projection * _19.view) * float4(in.WorldPos, 1.0); - float3 ndc = clipSpace.xyz / float3(clipSpace.w); - float2 screenUV = (ndc.xy * 0.5) + float2(0.5); - float windStrength = length(_68.windForce); - float2 _78; - if (windStrength > 0.001000000047497451305389404296875) - { - _78 = fast::normalize(_68.windForce.xy); - } - else - { - _78 = float2(1.0, 0.0); - } - float2 windDir = _78; - float waveSpeed = 0.1500000059604644775390625 + (windStrength * 0.300000011920928955078125); - float waveAmplitude = 0.00999999977648258209228515625 + (windStrength * 0.0199999995529651641845703125); - float waveFrequency = 30.0 + (windStrength * 10.0); - float2 waveOffset; - waveOffset.x = sin(((in.TexCoord.x * windDir.x) + (_19.time * waveSpeed)) * waveFrequency); - waveOffset.y = cos(((in.TexCoord.y * windDir.y) - (_19.time * waveSpeed)) * waveFrequency); - waveOffset *= waveAmplitude; - float2 flowOffset = float2(0.0); - if (_68.hasMovementTexture == 1) - { - float2 windUV = (_68.windForce.xy * _19.time) * 0.0500000007450580596923828125; - float2 movementUV = (in.TexCoord * 2.0) + windUV; - float2 movementSample = movementTexture.sample(movementTextureSmplr, movementUV).xy; - movementSample = (movementSample * 2.0) - float2(1.0); - flowOffset = (movementSample * windStrength) * 0.1500000059604644775390625; - waveOffset += (flowOffset * 0.5); - } - if (_68.hasNormalTexture == 1) - { - float3 T = fast::normalize(in.WorldTangent); - float3 B = fast::normalize(in.WorldBitangent); - float3 N = fast::normalize(in.WorldNormal); - float3x3 TBN = float3x3(float3(T), float3(B), float3(N)); - float normalSpeed = 0.02999999932944774627685546875 + (windStrength * 0.0500000007450580596923828125); - float2 normalUV1 = ((in.TexCoord * 5.0) + (waveOffset * 10.0)) + ((_68.windForce.xy * _19.time) * normalSpeed); - float2 normalUV2 = ((in.TexCoord * 3.0) - (waveOffset * 8.0)) - (((_68.windForce.xy * _19.time) * normalSpeed) * 0.800000011920928955078125); - float3 normalMap1 = normalTexture.sample(normalTextureSmplr, normalUV1).xyz; - float3 normalMap2 = normalTexture.sample(normalTextureSmplr, normalUV2).xyz; - normalMap1 = (normalMap1 * 2.0) - float3(1.0); - normalMap2 = (normalMap2 * 2.0) - float3(1.0); - float3 blendedNormal = fast::normalize(normalMap1 + normalMap2); - float3 worldSpaceNormal = fast::normalize(TBN * blendedNormal); - float normalStrength = 0.5 + (windStrength * 0.300000011920928955078125); - normal = fast::normalize(mix(N, worldSpaceNormal, float3(normalStrength))); - } - float2 reflectionUV = screenUV; - reflectionUV.y = 1.0 - reflectionUV.y; - reflectionUV += (waveOffset * 0.300000011920928955078125); - float2 refractionUV = screenUV - (waveOffset * 0.20000000298023223876953125); - bool _324 = reflectionUV.x >= 0.0; - bool _330; - if (_324) - { - _330 = reflectionUV.x <= 1.0; - } - else - { - _330 = _324; - } - bool _336; - if (_330) - { - _336 = reflectionUV.y >= 0.0; - } - else - { - _336 = _330; - } - bool _342; - if (_336) - { - _342 = reflectionUV.y <= 1.0; - } - else - { - _342 = _336; - } - bool reflectionInBounds = _342; - bool _346 = refractionUV.x >= 0.0; - bool _352; - if (_346) - { - _352 = refractionUV.x <= 1.0; - } - else - { - _352 = _346; - } - bool _358; - if (_352) - { - _358 = refractionUV.y >= 0.0; - } - else - { - _358 = _352; - } - bool _364; - if (_358) - { - _364 = refractionUV.y <= 1.0; - } - else - { - _364 = _358; - } - bool refractionInBounds = _364; - reflectionUV = fast::clamp(reflectionUV, float2(0.0500000007450580596923828125), float2(0.949999988079071044921875)); - refractionUV = fast::clamp(refractionUV, float2(0.0500000007450580596923828125), float2(0.949999988079071044921875)); - float2 reflectionEdgeFade = smoothstep(float2(0.0), float2(0.1500000059604644775390625), reflectionUV) * smoothstep(float2(1.0), float2(0.85000002384185791015625), reflectionUV); - float reflectionFadeFactor = reflectionEdgeFade.x * reflectionEdgeFade.y; - float2 refractionEdgeFade = smoothstep(float2(0.0), float2(0.1500000059604644775390625), refractionUV) * smoothstep(float2(1.0), float2(0.85000002384185791015625), refractionUV); - float refractionFadeFactor = refractionEdgeFade.x * refractionEdgeFade.y; - if (!reflectionInBounds) - { - reflectionFadeFactor *= 0.300000011920928955078125; - } - if (!refractionInBounds) - { - refractionFadeFactor *= 0.300000011920928955078125; - } - float4 reflectionSample = reflectionTexture.sample(reflectionTextureSmplr, reflectionUV); - float4 refractionSample = refractionTexture.sample(refractionTextureSmplr, refractionUV); - float4 sceneFallback = sceneTexture.sample(sceneTextureSmplr, screenUV); - bool validReflection = length(reflectionSample.xyz) > 0.00999999977648258209228515625; - bool validRefraction = length(refractionSample.xyz) > 0.00999999977648258209228515625; - if (!validReflection) - { - reflectionSample = sceneFallback; - } - if (!validRefraction) - { - refractionSample = sceneFallback; - } - float fresnel = powr(1.0 - fast::clamp(dot(normal, viewDir), 0.0, 1.0), 3.0); - fresnel = mix(0.0199999995529651641845703125, 1.0, fresnel); - fresnel *= _68.reflectionStrength; - float3 combined = mix(refractionSample.xyz, reflectionSample.xyz, float3(fresnel)); - float waterTint = fast::clamp(_68.depthFade * 0.300000011920928955078125, 0.0, 0.5); - combined = mix(combined, _19.waterColor.xyz, float3(waterTint)); - float foamAmount = 0.0; - if (_68.hasMovementTexture == 1) - { - float foamFactor = smoothstep(0.699999988079071044921875, 1.0, length(flowOffset) * windStrength); - foamAmount = foamFactor * 0.20000000298023223876953125; - combined = mix(combined, float3(1.0), float3(foamAmount)); - } - float3 lightDir = fast::normalize(-_19.lightDirection); - float diffuse = fast::max(dot(normal, lightDir), 0.0); - diffuse *= 0.300000011920928955078125; - float3 halfDir = fast::normalize(lightDir + viewDir); - float specAngle = fast::max(dot(normal, halfDir), 0.0); - float specular = powr(specAngle, 128.0); - specular *= ((fresnel * 0.5) + 0.5); - float waveVariation = (sin((in.TexCoord.x * 50.0) + (_19.time * 2.0)) * 0.5) + 0.5; - waveVariation *= ((cos((in.TexCoord.y * 50.0) - (_19.time * 1.5)) * 0.5) + 0.5); - specular *= (0.699999988079071044921875 + (waveVariation * 0.300000011920928955078125)); - float3 lighting = _19.lightColor * (diffuse + (specular * 2.0)); - combined += lighting; - float3 specularHighlight = (_19.lightColor * specular) * 2.5; - specularHighlight += float3(foamAmount * 2.0); - float alpha = mix(0.699999988079071044921875, 0.949999988079071044921875, fresnel); - out.FragColor = float4(combined, alpha); - float luminance = fast::max(fast::max(combined.x, combined.y), combined.z); - float3 bloomColor = float3(0.0); - if (luminance > 1.0) - { - bloomColor = combined - float3(1.0); - } - bloomColor += specularHighlight; - out.BrightColor = float4(bloomColor, alpha); - return out; -} - diff --git a/shaders/metal/terrain/fluid.vert.metal b/shaders/metal/terrain/fluid.vert.metal deleted file mode 100644 index 574ce50b..00000000 --- a/shaders/metal/terrain/fluid.vert.metal +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include - -using namespace metal; - -struct UBO -{ - float4x4 model; - float4x4 view; - float4x4 projection; -}; - -struct main0_out -{ - float2 TexCoord [[user(locn0)]]; - float3 WorldPos [[user(locn1)]]; - float3 WorldNormal [[user(locn2)]]; - float3 WorldTangent [[user(locn3)]]; - float3 WorldBitangent [[user(locn4)]]; - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; - float2 aTexCoord [[attribute(1)]]; - float3 aNormal [[attribute(2)]]; - float3 aTangent [[attribute(3)]]; - float3 aBitangent [[attribute(4)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]], constant UBO& _19 [[buffer(0)]]) -{ - main0_out out = {}; - out.gl_Position = ((_19.projection * _19.view) * _19.model) * float4(in.aPos, 1.0); - out.TexCoord = in.aTexCoord; - out.WorldPos = float3((_19.model * float4(in.aPos, 1.0)).xyz); - out.WorldNormal = fast::normalize(float3x3(_19.model[0].xyz, _19.model[1].xyz, _19.model[2].xyz) * in.aNormal); - out.WorldTangent = fast::normalize(float3x3(_19.model[0].xyz, _19.model[1].xyz, _19.model[2].xyz) * in.aTangent); - out.WorldBitangent = fast::normalize(float3x3(_19.model[0].xyz, _19.model[1].xyz, _19.model[2].xyz) * in.aBitangent); - return out; -} - diff --git a/shaders/metal/terrain/terrain.frag.metal b/shaders/metal/terrain/terrain.frag.metal deleted file mode 100644 index 9457ed63..00000000 --- a/shaders/metal/terrain/terrain.frag.metal +++ /dev/null @@ -1,402 +0,0 @@ -#pragma clang diagnostic ignored "-Wmissing-prototypes" - -#include -#include - -using namespace metal; - -struct PushConstants -{ - uint isFromMap; - float4 directionalColor; - float directionalIntensity; - uint hasLight; - uint useShadowMap; - float3 lightDir; - packed_float3 viewDir; - float ambientStrength; - float shadowBias; - int biomesCount; - float diffuseStrength; - float specularStrength; -}; - -struct TerrainParameters -{ - float maxPeak; - float seaLevel; -}; - -struct Biome -{ - int id; - float4 tintColor; - int useTexture; - int textureId; - float minHeight; - float maxHeight; - float minMoisture; - float maxMoisture; - float minTemperature; - float maxTemperature; -}; - -struct Biome_1 -{ - int id; - float4 tintColor; - int useTexture; - int textureId; - float minHeight; - float maxHeight; - float minMoisture; - float maxMoisture; - float minTemperature; - float maxTemperature; -}; - -struct BiomeBuffer -{ - Biome_1 biomes[1]; -}; - -struct main0_out -{ - float4 FragColor [[color(0)]]; - float4 BrightColor [[color(1)]]; -}; - -struct main0_in -{ - float2 TexCoord [[user(locn0)]]; - float3 FragPos [[user(locn1)]]; - float Height [[user(locn2)]]; - float4 FragPosLightSpace [[user(locn3)]]; -}; - -static inline __attribute__((always_inline)) -float3 calculateNormal(texture2d heightMap, sampler heightMapSmplr, thread const float2& texCoord, thread const float& heightScale) -{ - float h = heightMap.sample(heightMapSmplr, texCoord).x * heightScale; - float dx = dfdx(h); - float dy = dfdy(h); - float3 n = fast::normalize(float3(-dx, 1.0, -dy)); - return n; -} - -static inline __attribute__((always_inline)) -float smoothStepRange(thread const float& value, thread const float& minV, thread const float& maxV) -{ - return smoothstep(minV, maxV, value); -} - -static inline __attribute__((always_inline)) -float4 sampleBiomeTexture(thread const int& id, thread const float2& uv, texture2d texture0, sampler texture0Smplr, texture2d texture1, sampler texture1Smplr, texture2d texture2, sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, texture2d texture4, sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, texture2d texture6, sampler texture6Smplr, texture2d texture7, sampler texture7Smplr, texture2d texture8, sampler texture8Smplr, texture2d texture9, sampler texture9Smplr, texture2d texture10, sampler texture10Smplr, texture2d texture11, sampler texture11Smplr) -{ - if (id == 0) - { - return texture0.sample(texture0Smplr, uv); - } - if (id == 1) - { - return texture1.sample(texture1Smplr, uv); - } - if (id == 2) - { - return texture2.sample(texture2Smplr, uv); - } - if (id == 3) - { - return texture3.sample(texture3Smplr, uv); - } - if (id == 4) - { - return texture4.sample(texture4Smplr, uv); - } - if (id == 5) - { - return texture5.sample(texture5Smplr, uv); - } - if (id == 6) - { - return texture6.sample(texture6Smplr, uv); - } - if (id == 7) - { - return texture7.sample(texture7Smplr, uv); - } - if (id == 8) - { - return texture8.sample(texture8Smplr, uv); - } - if (id == 9) - { - return texture9.sample(texture9Smplr, uv); - } - if (id == 10) - { - return texture10.sample(texture10Smplr, uv); - } - if (id == 11) - { - return texture11.sample(texture11Smplr, uv); - } - return float4(1.0, 0.0, 1.0, 1.0); -} - -static inline __attribute__((always_inline)) -float4 triplanarBlend(thread const int& idx, thread const float3& normal, thread const float3& worldPos, thread const float& scale, texture2d texture0, sampler texture0Smplr, texture2d texture1, sampler texture1Smplr, texture2d texture2, sampler texture2Smplr, texture2d texture3, sampler texture3Smplr, texture2d texture4, sampler texture4Smplr, texture2d texture5, sampler texture5Smplr, texture2d texture6, sampler texture6Smplr, texture2d texture7, sampler texture7Smplr, texture2d texture8, sampler texture8Smplr, texture2d texture9, sampler texture9Smplr, texture2d texture10, sampler texture10Smplr, texture2d texture11, sampler texture11Smplr) -{ - float3 blend = abs(normal); - blend = (blend - float3(0.20000000298023223876953125)) * 7.0; - blend = fast::clamp(blend, float3(0.0), float3(1.0)); - blend /= float3((blend.x + blend.y) + blend.z); - int param = idx; - float2 param_1 = worldPos.yz * scale; - float4 xProj = sampleBiomeTexture(param, param_1, texture0, texture0Smplr, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr, texture11, texture11Smplr); - int param_2 = idx; - float2 param_3 = worldPos.xz * scale; - float4 yProj = sampleBiomeTexture(param_2, param_3, texture0, texture0Smplr, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr, texture11, texture11Smplr); - int param_4 = idx; - float2 param_5 = worldPos.xy * scale; - float4 zProj = sampleBiomeTexture(param_4, param_5, texture0, texture0Smplr, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr, texture11, texture11Smplr); - return ((xProj * blend.x) + (yProj * blend.y)) + (zProj * blend.z); -} - -static inline __attribute__((always_inline)) -float calculateShadow(thread const float4& fragPosLightSpace, thread const float3& normal, constant PushConstants& _331, texture2d shadowMap, sampler shadowMapSmplr) -{ - float3 projCoords = fragPosLightSpace.xyz / float3(fragPosLightSpace.w); - projCoords = (projCoords * 0.5) + float3(0.5); - bool _293 = projCoords.z > 1.0; - bool _300; - if (!_293) - { - _300 = projCoords.x < 0.0; - } - else - { - _300 = _293; - } - bool _307; - if (!_300) - { - _307 = projCoords.x > 1.0; - } - else - { - _307 = _300; - } - bool _314; - if (!_307) - { - _314 = projCoords.y < 0.0; - } - else - { - _314 = _307; - } - bool _321; - if (!_314) - { - _321 = projCoords.y > 1.0; - } - else - { - _321 = _314; - } - if (_321) - { - return 0.0; - } - float currentDepth = projCoords.z; - float bias0 = fast::max(_331.shadowBias * (1.0 - dot(normal, _331.lightDir)), _331.shadowBias * 0.100000001490116119384765625); - float shadow = 0.0; - float2 texelSize = float2(1.0) / float2(int2(shadowMap.get_width(), shadowMap.get_height())); - for (int x = -1; x <= 1; x++) - { - for (int y = -1; y <= 1; y++) - { - float pcfDepth = shadowMap.sample(shadowMapSmplr, (projCoords.xy + (float2(float(x), float(y)) * texelSize))).x; - shadow += float((currentDepth - bias0) > pcfDepth); - } - } - shadow /= 9.0; - return shadow; -} - -static inline __attribute__((always_inline)) -float3 acesToneMapping(thread const float3& color) -{ - return fast::clamp((color * ((color * 2.5099999904632568359375) + float3(0.02999999932944774627685546875))) / ((color * ((color * 2.4300000667572021484375) + float3(0.589999973773956298828125))) + float3(0.14000000059604644775390625)), float3(0.0), float3(1.0)); -} - -fragment main0_out main0(main0_in in [[stage_in]], constant PushConstants& _331 [[buffer(0)]], constant TerrainParameters& _444 [[buffer(1)]], device BiomeBuffer& _534 [[buffer(2)]], texture2d texture0 [[texture(0)]], texture2d texture1 [[texture(1)]], texture2d texture2 [[texture(2)]], texture2d texture3 [[texture(3)]], texture2d texture4 [[texture(4)]], texture2d texture5 [[texture(5)]], texture2d texture6 [[texture(6)]], texture2d texture7 [[texture(7)]], texture2d texture8 [[texture(8)]], texture2d texture9 [[texture(9)]], texture2d texture10 [[texture(10)]], texture2d texture11 [[texture(11)]], texture2d shadowMap [[texture(12)]], texture2d heightMap [[texture(13)]], texture2d moistureMap [[texture(14)]], texture2d temperatureMap [[texture(15)]], sampler texture0Smplr [[sampler(0)]], sampler texture1Smplr [[sampler(1)]], sampler texture2Smplr [[sampler(2)]], sampler texture3Smplr [[sampler(3)]], sampler texture4Smplr [[sampler(4)]], sampler texture5Smplr [[sampler(5)]], sampler texture6Smplr [[sampler(6)]], sampler texture7Smplr [[sampler(7)]], sampler texture8Smplr [[sampler(8)]], sampler texture9Smplr [[sampler(9)]], sampler texture10Smplr [[sampler(10)]], sampler texture11Smplr [[sampler(11)]], sampler shadowMapSmplr [[sampler(12)]], sampler heightMapSmplr [[sampler(13)]], sampler moistureMapSmplr [[sampler(14)]], sampler temperatureMapSmplr [[sampler(15)]]) -{ - main0_out out = {}; - if (_331.biomesCount <= 0) - { - out.FragColor = float4(float3((in.Height + _444.seaLevel) / _444.maxPeak), 1.0); - return out; - } - float _463; - if (_331.isFromMap != 0u) - { - _463 = heightMap.sample(heightMapSmplr, in.TexCoord).x * 255.0; - } - else - { - _463 = ((in.Height + _444.seaLevel) / _444.maxPeak) * 255.0; - } - float h = _463; - float m = moistureMap.sample(moistureMapSmplr, in.TexCoord).x * 255.0; - float t = temperatureMap.sample(temperatureMapSmplr, in.TexCoord).x * 255.0; - float texelSize = 1.0 / float(int2(heightMap.get_width(), heightMap.get_height()).x); - float heightScale = 64.0; - float2 param = in.TexCoord; - float param_1 = heightScale; - float3 normal = calculateNormal(heightMap, heightMapSmplr, param, param_1); - float4 baseColor = float4(0.0); - float totalWeight = 0.0; - float _550; - float _574; - float _598; - float4 _628; - for (int i = 0; i < _331.biomesCount; i++) - { - Biome _539; - _539.id = _534.biomes[i].id; - _539.tintColor = _534.biomes[i].tintColor; - _539.useTexture = _534.biomes[i].useTexture; - _539.textureId = _534.biomes[i].textureId; - _539.minHeight = _534.biomes[i].minHeight; - _539.maxHeight = _534.biomes[i].maxHeight; - _539.minMoisture = _534.biomes[i].minMoisture; - _539.maxMoisture = _534.biomes[i].maxMoisture; - _539.minTemperature = _534.biomes[i].minTemperature; - _539.maxTemperature = _534.biomes[i].maxTemperature; - Biome b = _539; - bool _543 = b.minHeight < 0.0; - bool _549; - if (_543) - { - _549 = b.maxHeight < 0.0; - } - else - { - _549 = _543; - } - if (_549) - { - _550 = 1.0; - } - else - { - float param_2 = h; - float param_3 = b.minHeight; - float param_4 = b.maxHeight; - _550 = smoothStepRange(param_2, param_3, param_4); - } - float hW = _550; - bool _567 = b.minMoisture < 0.0; - bool _573; - if (_567) - { - _573 = b.maxMoisture < 0.0; - } - else - { - _573 = _567; - } - if (_573) - { - _574 = 1.0; - } - else - { - float param_5 = m; - float param_6 = b.minMoisture; - float param_7 = b.maxMoisture; - _574 = smoothStepRange(param_5, param_6, param_7); - } - float mW = _574; - bool _591 = b.minTemperature < 0.0; - bool _597; - if (_591) - { - _597 = b.maxTemperature < 0.0; - } - else - { - _597 = _591; - } - if (_597) - { - _598 = 1.0; - } - else - { - float param_8 = t; - float param_9 = b.minTemperature; - float param_10 = b.maxTemperature; - _598 = smoothStepRange(param_8, param_9, param_10); - } - float tW = _598; - float weight = ((1.0 - hW) * mW) * tW; - if (weight > 0.001000000047497451305389404296875) - { - if (b.useTexture == 1) - { - int param_11 = i; - float3 param_12 = normal; - float3 param_13 = in.FragPos; - float param_14 = 0.100000001490116119384765625; - _628 = triplanarBlend(param_11, param_12, param_13, param_14, texture0, texture0Smplr, texture1, texture1Smplr, texture2, texture2Smplr, texture3, texture3Smplr, texture4, texture4Smplr, texture5, texture5Smplr, texture6, texture6Smplr, texture7, texture7Smplr, texture8, texture8Smplr, texture9, texture9Smplr, texture10, texture10Smplr, texture11, texture11Smplr); - } - else - { - _628 = b.tintColor; - } - float4 texColor = _628; - baseColor += (texColor * weight); - totalWeight += weight; - } - } - baseColor /= float4(fast::max(totalWeight, 0.001000000047497451305389404296875)); - float detail = (heightMap.sample(heightMapSmplr, (in.TexCoord * 64.0)).x * 0.100000001490116119384765625) + 0.89999997615814208984375; - float4 _670 = baseColor; - float3 _672 = _670.xyz * detail; - baseColor.x = _672.x; - baseColor.y = _672.y; - baseColor.z = _672.z; - float3 finalColor; - if (_331.hasLight != 0u) - { - float3 L = fast::normalize(-_331.lightDir); - float3 N = fast::normalize(normal); - float3 V = fast::normalize(float3(_331.viewDir)); - float3 ambient = baseColor.xyz * _331.ambientStrength; - float diff = fast::max(dot(N, L), 0.0); - float3 diffuse = ((_331.directionalColor.xyz * (_331.diffuseStrength * diff)) * _331.directionalIntensity) * baseColor.xyz; - float3 H = fast::normalize(L + V); - float spec = powr(fast::max(dot(N, H), 0.0), 32.0); - float3 specular = (_331.directionalColor.xyz * (_331.specularStrength * spec)) * _331.directionalIntensity; - float shadow = 0.0; - if (_331.useShadowMap != 0u) - { - float4 param_15 = in.FragPosLightSpace; - float3 param_16 = N; - shadow = calculateShadow(param_15, param_16, _331, shadowMap, shadowMapSmplr); - } - finalColor = ambient + ((diffuse + specular) * (1.0 - shadow)); - } - else - { - finalColor = baseColor.xyz * _331.ambientStrength; - } - float3 param_17 = finalColor; - out.FragColor = float4(acesToneMapping(param_17), 1.0); - out.BrightColor = float4(0.0); - return out; -} - diff --git a/shaders/metal/terrain/terrain.vert.metal b/shaders/metal/terrain/terrain.vert.metal deleted file mode 100644 index 6adf5c42..00000000 --- a/shaders/metal/terrain/terrain.vert.metal +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include - -using namespace metal; - -struct UBO -{ - float4x4 model; - float4x4 view; - float4x4 projection; -}; - -struct main0_out -{ - float2 TexCoord [[user(locn0)]]; - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; - float2 aTexCoord [[attribute(1)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]], constant UBO& _19 [[buffer(0)]]) -{ - main0_out out = {}; - out.gl_Position = ((_19.projection * _19.view) * _19.model) * float4(in.aPos, 1.0); - out.TexCoord = in.aTexCoord; - return out; -} - diff --git a/shaders/metal/terrain/terrain_control.tesc.metal b/shaders/metal/terrain/terrain_control.tesc.metal deleted file mode 100644 index 7be26b88..00000000 --- a/shaders/metal/terrain/terrain_control.tesc.metal +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include - -using namespace metal; - -struct UBO -{ - float4x4 model; - float4x4 view; - float4x4 projection; -}; - -struct main0_out -{ - float2 TextureCoord; - float4 gl_Position; -}; - -struct main0_in -{ - float2 TexCoord [[attribute(0)]]; - float4 gl_Position [[attribute(1)]]; -}; - -kernel void main0(main0_in in [[stage_in]], constant UBO& _56 [[buffer(0)]], uint gl_InvocationID [[thread_index_in_threadgroup]], uint gl_PrimitiveID [[threadgroup_position_in_grid]], device main0_out* spvOut [[buffer(28)]], constant uint* spvIndirectParams [[buffer(29)]], device MTLQuadTessellationFactorsHalf* spvTessLevel [[buffer(26)]], threadgroup main0_in* gl_in [[threadgroup(0)]]) -{ - device main0_out* gl_out = &spvOut[gl_PrimitiveID * 4]; - if (gl_InvocationID < spvIndirectParams[0]) - gl_in[gl_InvocationID] = in; - threadgroup_barrier(mem_flags::mem_threadgroup); - if (gl_InvocationID >= 4) - return; - gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; - gl_out[gl_InvocationID].TextureCoord = gl_in[gl_InvocationID].TexCoord; - if (gl_InvocationID == 0) - { - float4 eyeSpacePos00 = (_56.view * _56.model) * gl_in[0].gl_Position; - float4 eyeSpacePos01 = (_56.view * _56.model) * gl_in[1].gl_Position; - float4 eyeSpacePos10 = (_56.view * _56.model) * gl_in[2].gl_Position; - float4 eyeSpacePos11 = (_56.view * _56.model) * gl_in[3].gl_Position; - float dist00 = fast::clamp((abs(eyeSpacePos00.z) - 20.0) / 780.0, 0.0, 1.0); - float dist01 = fast::clamp((abs(eyeSpacePos01.z) - 20.0) / 780.0, 0.0, 1.0); - float dist10 = fast::clamp((abs(eyeSpacePos10.z) - 20.0) / 780.0, 0.0, 1.0); - float dist11 = fast::clamp((abs(eyeSpacePos11.z) - 20.0) / 780.0, 0.0, 1.0); - float tessLevel0 = mix(64.0, 4.0, fast::min(dist10, dist00)); - float tessLevel1 = mix(64.0, 4.0, fast::min(dist00, dist01)); - float tessLevel2 = mix(64.0, 4.0, fast::min(dist01, dist11)); - float tessLevel3 = mix(64.0, 4.0, fast::min(dist11, dist10)); - spvTessLevel[gl_PrimitiveID].edgeTessellationFactor[0] = half(tessLevel0); - spvTessLevel[gl_PrimitiveID].edgeTessellationFactor[1] = half(tessLevel1); - spvTessLevel[gl_PrimitiveID].edgeTessellationFactor[2] = half(tessLevel2); - spvTessLevel[gl_PrimitiveID].edgeTessellationFactor[3] = half(tessLevel3); - spvTessLevel[gl_PrimitiveID].insideTessellationFactor[0] = half(fast::max(tessLevel1, tessLevel3)); - spvTessLevel[gl_PrimitiveID].insideTessellationFactor[1] = half(fast::max(tessLevel0, tessLevel2)); - } -} - diff --git a/shaders/metal/terrain/terrain_eval.tese.metal b/shaders/metal/terrain/terrain_eval.tese.metal deleted file mode 100644 index a189e6d0..00000000 --- a/shaders/metal/terrain/terrain_eval.tese.metal +++ /dev/null @@ -1,69 +0,0 @@ -#include -#include - -using namespace metal; - -struct Uniforms -{ - float4x4 lightViewProj; - float maxPeak; - float seaLevel; - uint isFromMap; -}; - -struct UBO -{ - float4x4 model; - float4x4 view; - float4x4 projection; -}; - -struct main0_out -{ - float2 TexCoord [[user(locn0)]]; - float3 FragPos [[user(locn1)]]; - float Height [[user(locn2)]]; - float4 FragPosLightSpace [[user(locn3)]]; - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float2 TextureCoord [[attribute(0)]]; - float4 gl_Position [[attribute(1)]]; -}; - -struct main0_patchIn -{ - patch_control_point gl_in; -}; - -[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]], constant Uniforms& _84 [[buffer(0)]], constant UBO& _145 [[buffer(1)]], texture2d heightMap [[texture(0)]], sampler heightMapSmplr [[sampler(0)]], float2 gl_TessCoordIn [[position_in_patch]]) -{ - main0_out out = {}; - float3 gl_TessCoord = float3(gl_TessCoordIn.x, gl_TessCoordIn.y, 0.0); - float u = gl_TessCoord.x; - float v = gl_TessCoord.y; - float2 t00 = patchIn.gl_in[0].TextureCoord; - float2 t01 = patchIn.gl_in[1].TextureCoord; - float2 t10 = patchIn.gl_in[2].TextureCoord; - float2 t11 = patchIn.gl_in[3].TextureCoord; - float2 t0 = ((t01 - t00) * u) + t00; - float2 t1 = ((t11 - t10) * u) + t10; - float2 texCoord = ((t1 - t0) * v) + t0; - out.Height = (heightMap.sample(heightMapSmplr, texCoord, level(0.0)).x * _84.maxPeak) - _84.seaLevel; - float4 p00 = patchIn.gl_in[0].gl_Position; - float4 p01 = patchIn.gl_in[1].gl_Position; - float4 p10 = patchIn.gl_in[2].gl_Position; - float4 p11 = patchIn.gl_in[3].gl_Position; - float4 p0 = ((p01 - p00) * u) + p00; - float4 p1 = ((p11 - p10) * u) + p10; - float4 position = ((p1 - p0) * v) + p0; - position.y += out.Height; - out.gl_Position = ((_145.projection * _145.view) * _145.model) * position; - out.TexCoord = texCoord; - out.FragPos = float3((_145.model * position).xyz); - out.FragPosLightSpace = (_84.lightViewProj * _145.model) * position; - return out; -} - diff --git a/shaders/metal/ui/text.frag.metal b/shaders/metal/ui/text.frag.metal deleted file mode 100644 index 43e02bde..00000000 --- a/shaders/metal/ui/text.frag.metal +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include - -using namespace metal; - -struct TextColor -{ - float3 textColor; -}; - -struct main0_out -{ - float4 color [[color(0)]]; -}; - -struct main0_in -{ - float2 texCoords [[user(locn0)]]; -}; - -fragment main0_out main0(main0_in in [[stage_in]], constant TextColor& _30 [[buffer(0)]], texture2d text [[texture(0)]], sampler textSmplr [[sampler(0)]]) -{ - main0_out out = {}; - float4 sampled = float4(1.0, 1.0, 1.0, text.sample(textSmplr, in.texCoords).x); - out.color = float4(_30.textColor, 1.0) * sampled; - return out; -} - diff --git a/shaders/metal/ui/text.vert.metal b/shaders/metal/ui/text.vert.metal deleted file mode 100644 index 72bf4452..00000000 --- a/shaders/metal/ui/text.vert.metal +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include - -using namespace metal; - -struct Uniforms -{ - float4x4 projection; -}; - -struct main0_out -{ - float2 texCoords [[user(locn0)]]; - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float4 vertex0 [[attribute(0)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]], constant Uniforms& _19 [[buffer(0)]]) -{ - main0_out out = {}; - out.gl_Position = _19.projection * float4(in.vertex0.xy, 0.0, 1.0); - out.texCoords = in.vertex0.zw; - return out; -} - diff --git a/shaders/metal/volumetric/volumetric.frag.metal b/shaders/metal/volumetric/volumetric.frag.metal deleted file mode 100644 index 90d0a87b..00000000 --- a/shaders/metal/volumetric/volumetric.frag.metal +++ /dev/null @@ -1,99 +0,0 @@ -#pragma clang diagnostic ignored "-Wmissing-prototypes" - -#include -#include - -using namespace metal; - -struct Sun -{ - float2 sunPos; -}; - -struct VolumetricParameters -{ - float density; - float weight; - float decay; - float exposure; -}; - -struct DirectionalLight -{ - float3 color; -}; - -struct main0_out -{ - float4 FragColor [[color(0)]]; -}; - -struct main0_in -{ - float2 TexCoords [[user(locn0)]]; -}; - -static inline __attribute__((always_inline)) -float3 computeVolumetricLighting(thread const float2& uv, constant Sun& _21, constant VolumetricParameters& _31, texture2d sceneTexture, sampler sceneTextureSmplr, constant DirectionalLight& directionalLight) -{ - float3 color = float3(0.0); - float2 deltaTexCoord = (_21.sunPos - uv) * _31.density; - float2 coord = uv; - float illuminationDecay = 1.0; - for (int i = 0; i < 48; i++) - { - coord += deltaTexCoord; - bool _59 = coord.x < 0.0; - bool _66; - if (!_59) - { - _66 = coord.x > 1.0; - } - else - { - _66 = _59; - } - bool _74; - if (!_66) - { - _74 = coord.y < 0.0; - } - else - { - _74 = _66; - } - bool _81; - if (!_74) - { - _81 = coord.y > 1.0; - } - else - { - _81 = _74; - } - if (_81) - { - break; - } - float3 sampled = sceneTexture.sample(sceneTextureSmplr, coord).xyz; - float brightness = dot(sampled, float3(0.2989999949932098388671875, 0.58700001239776611328125, 0.114000000059604644775390625)); - float3 atmosphere = directionalLight.color * 0.0199999995529651641845703125; - if (brightness > 0.5) - { - atmosphere += (sampled * 0.5); - } - atmosphere *= (illuminationDecay * _31.weight); - color += atmosphere; - illuminationDecay *= _31.decay; - } - return color * 5.0; -} - -fragment main0_out main0(main0_in in [[stage_in]], constant Sun& _21 [[buffer(0)]], constant VolumetricParameters& _31 [[buffer(1)]], constant DirectionalLight& directionalLight [[buffer(2)]], texture2d sceneTexture [[texture(0)]], sampler sceneTextureSmplr [[sampler(0)]]) -{ - main0_out out = {}; - float2 param = in.TexCoords; - float3 rays = computeVolumetricLighting(param, _21, _31, sceneTexture, sceneTextureSmplr, directionalLight); - out.FragColor = float4(rays, 1.0); - return out; -} diff --git a/shaders/metal/volumetric/volumetric.vert.metal b/shaders/metal/volumetric/volumetric.vert.metal deleted file mode 100644 index b6d321ab..00000000 --- a/shaders/metal/volumetric/volumetric.vert.metal +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include - -using namespace metal; - -struct main0_out -{ - float2 TexCoords [[user(locn0)]]; - float4 gl_Position [[position]]; -}; - -struct main0_in -{ - float3 aPos [[attribute(0)]]; - float2 aTexCoords [[attribute(2)]]; -}; - -vertex main0_out main0(main0_in in [[stage_in]]) -{ - main0_out out = {}; - out.gl_Position = float4(in.aPos, 1.0); - out.TexCoords = in.aTexCoords; - return out; -} diff --git a/shaders/opengl/deferred/deferred.frag b/shaders/opengl/deferred/deferred.frag deleted file mode 100644 index 83a45aa1..00000000 --- a/shaders/opengl/deferred/deferred.frag +++ /dev/null @@ -1,220 +0,0 @@ -#version 410 core -layout(location = 0) out vec4 gPosition; -layout(location = 1) out vec4 gNormal; -layout(location = 2) out vec4 gAlbedoSpec; -layout(location = 3) out vec4 gMaterial; - -in vec2 TexCoord; -in vec4 outColor; -in vec3 Normal; -in vec3 FragPos; -in mat3 TBN; - -const int TEXTURE_COLOR = 0; -const int TEXTURE_SPECULAR = 1; -const int TEXTURE_NORMAL = 5; -const int TEXTURE_PARALLAX = 6; -const int TEXTURE_METALLIC = 9; -const int TEXTURE_ROUGHNESS = 10; -const int TEXTURE_AO = 11; -const int TEXTURE_OPACITY = 12; -const int TEXTURE_PBR_PACK = 14; - -struct Material { - vec3 albedo; - float metallic; - float roughness; - float ao; - float reflectivity; -}; - -uniform sampler2D texture1; -uniform sampler2D texture2; -uniform sampler2D texture3; -uniform sampler2D texture4; -uniform sampler2D texture5; -uniform sampler2D texture6; -uniform sampler2D texture7; -uniform sampler2D texture8; -uniform sampler2D texture9; -uniform sampler2D texture10; - -uniform int textureTypes[16]; -uniform int textureCount; -uniform Material material; -uniform vec3 cameraPosition; -uniform vec2 textureScale; -uniform vec2 textureOffset; -uniform bool useTexture; -uniform bool useColor; - -vec2 texCoord; - -vec4 enableTextures(int type) { - vec4 color = vec4(0.0); - int count = 0; - for (int i = 0; i < textureCount; i++) { - if (textureTypes[i] == type) { - if (i == 0) color += texture(texture1, texCoord); - else if (i == 1) color += texture(texture2, texCoord); - else if (i == 2) color += texture(texture3, texCoord); - else if (i == 3) color += texture(texture4, texCoord); - else if (i == 4) color += texture(texture5, texCoord); - else if (i == 5) color += texture(texture6, texCoord); - else if (i == 6) color += texture(texture7, texCoord); - else if (i == 7) color += texture(texture8, texCoord); - else if (i == 8) color += texture(texture9, texCoord); - else if (i == 9) color += texture(texture10, texCoord); - count++; - } - } - if (count > 0) color /= float(count); - if (count == 0) return vec4(-1.0); - return color; -} - -vec4 sampleTextureAt(int textureIndex, vec2 uv) { - if (textureIndex == 0) return texture(texture1, uv); - else if (textureIndex == 1) return texture(texture2, uv); - else if (textureIndex == 2) return texture(texture3, uv); - else if (textureIndex == 3) return texture(texture4, uv); - else if (textureIndex == 4) return texture(texture5, uv); - else if (textureIndex == 5) return texture(texture6, uv); - else if (textureIndex == 6) return texture(texture7, uv); - else if (textureIndex == 7) return texture(texture8, uv); - else if (textureIndex == 8) return texture(texture9, uv); - else if (textureIndex == 9) return texture(texture10, uv); - return vec4(0.0); -} - -vec2 parallaxMapping(vec2 texCoords, vec3 viewDir) { - const float minLayers = 8.0; - const float maxLayers = 32.0; - vec3 v = normalize(viewDir); - float numLayers = mix(maxLayers, minLayers, abs(dot(vec3(0.0, 0.0, 1.0), v))); - float layerDepth = 1.0 / numLayers; - float currentLayerDepth = 0.0; - - const float heightScale = 0.04; - vec2 P = (v.xy / max(v.z, 0.05)) * heightScale; - vec2 deltaTexCoords = P / numLayers; - - vec2 currentTexCoords = texCoords; - int textureIndex = -1; - for (int i = 0; i < textureCount; i++) { - if (textureTypes[i] == TEXTURE_PARALLAX) { - textureIndex = i; - break; - } - } - if (textureIndex == -1) return currentTexCoords; - - float currentDepthMapValue = 1.0 - sampleTextureAt(textureIndex, currentTexCoords).r; - - while (currentLayerDepth < currentDepthMapValue) { - currentTexCoords -= deltaTexCoords; - currentDepthMapValue = 1.0 - sampleTextureAt(textureIndex, currentTexCoords).r; - currentLayerDepth += layerDepth; - } - - vec2 prevTexCoords = currentTexCoords + deltaTexCoords; - float afterDepth = currentDepthMapValue - currentLayerDepth; - float beforeDepth = 1.0 - sampleTextureAt(textureIndex, prevTexCoords).r - (currentLayerDepth - layerDepth); - float denom = afterDepth - beforeDepth; - float weight = abs(denom) > 1e-4 - ? clamp(afterDepth / denom, 0.0, 1.0) - : 0.0; - currentTexCoords = prevTexCoords * weight + currentTexCoords * (1.0 - weight); - - return currentTexCoords; -} - -void main() { - texCoord = TexCoord * textureScale + textureOffset; - - vec3 tangentViewDir = normalize(transpose(TBN) * (cameraPosition - FragPos)); - texCoord = parallaxMapping(texCoord, tangentViewDir); - - vec4 sampledColor = enableTextures(TEXTURE_COLOR); - bool hasColorTexture = sampledColor != vec4(-1.0); - - vec4 baseColor = vec4(material.albedo, 1.0); - vec4 albedoTex = enableTextures(TEXTURE_COLOR); - if (albedoTex != vec4(-1.0)) { - baseColor *= albedoTex; - } - vec4 opacityTex = enableTextures(TEXTURE_OPACITY); - if (opacityTex != vec4(-1.0)) { - if (opacityTex.r < 0.1) { - discard; - } - } else if (baseColor.a < 0.1) { - discard; - } - - - vec4 normTexture = enableTextures(TEXTURE_NORMAL); - vec3 normal; - if (normTexture.r != -1.0 && normTexture.g != -1.0 && normTexture.b != -1.0) { - vec3 tangentNormal = normalize(normTexture.rgb * 2.0 - 1.0); - normal = normalize(TBN * tangentNormal); - } else { - normal = normalize(Normal); - } - - vec3 albedo = baseColor.rgb; - - vec4 pbrPackTex = enableTextures(TEXTURE_PBR_PACK); - bool hasPbrPack = pbrPackTex != vec4(-1.0); - - float metallic = material.metallic; - if (hasPbrPack) { - metallic *= pbrPackTex.b; - } else { - vec4 metallicTex = enableTextures(TEXTURE_METALLIC); - if (metallicTex != vec4(-1.0)) { - metallic *= metallicTex.r; - } - } - - float roughness = material.roughness; - if (hasPbrPack) { - roughness *= pbrPackTex.g; - } else { - vec4 roughnessTex = enableTextures(TEXTURE_ROUGHNESS); - if (roughnessTex != vec4(-1.0)) { - roughness *= roughnessTex.r; - } - } - - float ao = material.ao; - if (hasPbrPack) { - ao *= pbrPackTex.r; - } else { - vec4 aoTex = enableTextures(TEXTURE_AO); - if (aoTex != vec4(-1.0)) { - ao *= aoTex.r; - } - } - - metallic = clamp(metallic, 0.0, 1.0); - roughness = clamp(roughness, 0.0, 1.0); - ao = clamp(ao, 0.0, 1.0); - - float nonlinearDepth = gl_FragCoord.z; - gPosition = vec4(FragPos, nonlinearDepth); - - vec3 n = normalize(normal); - if (!all(equal(n, n)) || length(n) < 1e-4) { - n = normalize(Normal); - } - gNormal = vec4(n, 1.0); - - vec3 a = clamp(albedo, 0.0, 1.0); - if (!all(equal(a, a))) { - a = vec3(0.0); - } - gAlbedoSpec = vec4(a, ao); - - gMaterial = vec4(metallic, roughness, ao, clamp(material.reflectivity, 0.0, 1.0)); -} diff --git a/shaders/opengl/deferred/deferred.vert b/shaders/opengl/deferred/deferred.vert deleted file mode 100644 index 26ef6302..00000000 --- a/shaders/opengl/deferred/deferred.vert +++ /dev/null @@ -1,43 +0,0 @@ -#version 410 core -layout(location = 0) in vec3 aPos; -layout(location = 1) in vec4 aColor; -layout(location = 2) in vec2 aTexCoord; -layout(location = 3) in vec3 aNormal; -layout(location = 4) in vec3 aTangent; -layout(location = 5) in vec3 aBitangent; -layout(location = 6) in mat4 instanceModel; - -uniform mat4 model; -uniform mat4 view; -uniform mat4 projection; -uniform bool isInstanced = true; - -out vec4 outColor; -out vec2 TexCoord; -out vec3 Normal; -out vec3 FragPos; -out mat3 TBN; - -void main() { - mat4 finalModel; - if (isInstanced) { - finalModel = instanceModel; - } else { - finalModel = model; - } - - vec4 worldPos = finalModel * vec4(aPos, 1.0); - FragPos = worldPos.xyz; - gl_Position = projection * view * worldPos; - - TexCoord = aTexCoord; - outColor = aColor; - - mat3 normalMatrix = mat3(transpose(inverse(finalModel))); - Normal = normalize(normalMatrix * aNormal); - - vec3 T = normalize(normalMatrix * aTangent); - vec3 B = normalize(normalMatrix * aBitangent); - vec3 N = normalize(normalMatrix * aNormal); - TBN = mat3(T, B, N); -} \ No newline at end of file diff --git a/shaders/opengl/deferred/light.frag b/shaders/opengl/deferred/light.frag deleted file mode 100644 index f80b7ee2..00000000 --- a/shaders/opengl/deferred/light.frag +++ /dev/null @@ -1,490 +0,0 @@ -#version 410 core -layout(location = 0) out vec4 FragColor; -layout(location = 1) out vec4 BrightColor; - -in vec2 TexCoord; - -uniform sampler2D gPosition; -uniform sampler2D gNormal; -uniform sampler2D gAlbedoSpec; -uniform sampler2D gMaterial; -uniform sampler2D ssao; - -uniform sampler2D texture1; -uniform sampler2D texture2; -uniform sampler2D texture3; -uniform sampler2D texture4; -uniform sampler2D texture5; -uniform samplerCube cubeMap1; -uniform samplerCube cubeMap2; -uniform samplerCube cubeMap3; -uniform samplerCube cubeMap4; -uniform samplerCube cubeMap5; -uniform samplerCube skybox; - -struct AmbientLight { - vec4 color; - float intensity; -}; - -struct DirectionalLight { - vec3 direction; - vec3 diffuse; - vec3 specular; - float intensity; -}; - -struct PointLight { - vec3 position; - vec3 diffuse; - vec3 specular; - float intensity; - float constant; - float linear; - float quadratic; - float radius; -}; - -struct SpotLight { - vec3 position; - vec3 direction; - float cutOff; - float outerCutOff; - float intensity; - float range; - vec3 diffuse; - vec3 specular; -}; - -struct AreaLight { - vec3 position; - vec3 right; - vec3 up; - vec2 size; - vec3 diffuse; - vec3 specular; - float angle; - float intensity; - float range; - int castsBothSides; -}; - -struct ShadowParameters { - mat4 lightView; - mat4 lightProjection; - float bias; - int textureIndex; - float farPlane; - int lightIndex; - vec3 lightPos; - int lightType; -}; - -struct Environment { - float rimLightIntensity; - vec3 rimLightColor; - float bloomThreshold; -}; - -uniform AmbientLight ambientLight; -uniform DirectionalLight directionalLights[4]; -uniform int directionalLightCount; -uniform PointLight pointLights[32]; -uniform int pointLightCount; -uniform SpotLight spotlights[32]; -uniform int spotlightCount; -uniform AreaLight areaLights[32]; -uniform int areaLightCount; -uniform ShadowParameters shadowParams[10]; -uniform int shadowParamCount; -uniform vec3 cameraPosition; -uniform bool useIBL; - -uniform Environment environment; - -const float PI = 3.14159265; - -vec4 sampleTextureAt(int textureIndex, vec2 uv) { - if (textureIndex == 0) return texture(texture1, uv); - else if (textureIndex == 1) return texture(texture2, uv); - else if (textureIndex == 2) return texture(texture3, uv); - else if (textureIndex == 3) return texture(texture4, uv); - else if (textureIndex == 4) return texture(texture5, uv); - return vec4(0.0); -} - -vec4 sampleCubeTextureAt(int textureIndex, vec3 direction) { - if (textureIndex == 0) return texture(cubeMap1, direction); - else if (textureIndex == 1) return texture(cubeMap2, direction); - else if (textureIndex == 2) return texture(cubeMap3, direction); - else if (textureIndex == 3) return texture(cubeMap4, direction); - else if (textureIndex == 4) return texture(cubeMap5, direction); - return vec4(0.0); -} - -vec2 getTextureDimensions(int textureIndex) { - if (textureIndex == 0) return vec2(textureSize(texture1, 0)); - else if (textureIndex == 1) return vec2(textureSize(texture2, 0)); - else if (textureIndex == 2) return vec2(textureSize(texture3, 0)); - else if (textureIndex == 3) return vec2(textureSize(texture4, 0)); - else if (textureIndex == 4) return vec2(textureSize(texture5, 0)); - return vec2(0); -} - -float distributionGGX(vec3 N, vec3 H, float roughness) { - float a = roughness * roughness; - float a2 = a * a; - float NdotH = max(dot(N, H), 0.0); - float NdotH2 = NdotH * NdotH; - - float num = a2; - float denom = (NdotH2 * (a2 - 1.0) + 1.0); - denom = PI * denom * denom; - - return num / max(denom, 0.0001); -} - -float geometrySchlickGGX(float NdotV, float roughness) { - float r = roughness + 1.0; - float k = (r * r) / 8.0; - - float num = NdotV; - float denom = NdotV * (1.0 - k) + k; - - return num / max(denom, 0.0001); -} - -float geometrySmith(vec3 N, vec3 V, vec3 L, float roughness) { - float NdotV = max(dot(N, V), 0.0); - float NdotL = max(dot(N, L), 0.0); - float ggx2 = geometrySchlickGGX(NdotV, roughness); - float ggx1 = geometrySchlickGGX(NdotL, roughness); - return ggx1 * ggx2; -} - -vec3 fresnelSchlick(float cosTheta, vec3 F0) { - return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); -} - -float calculateShadow(ShadowParameters shadowParam, vec3 fragPos, vec3 normal) { - vec4 fragPosLightSpace = shadowParam.lightProjection * shadowParam.lightView * vec4(fragPos, 1.0); - vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; - projCoords = projCoords * 0.5 + 0.5; - - if (projCoords.x < 0.0 || projCoords.x > 1.0 || - projCoords.y < 0.0 || projCoords.y > 1.0 || - projCoords.z > 1.0) { - return 0.0; - } - - float currentDepth = projCoords.z; - - vec3 lightDirWorld = normalize((inverse(shadowParam.lightView) * vec4(0.0, 0.0, -1.0, 0.0)).xyz); - float biasValue = shadowParam.bias; - float ndotl = max(dot(normal, lightDirWorld), 0.0); - float minBias = 0.0005; - float bias = max(biasValue * (1.0 - ndotl), minBias); - - float shadow = 0.0; - vec2 texelSize = 1.0 / getTextureDimensions(shadowParam.textureIndex); - - float distance = length(cameraPosition - fragPos); - vec2 shadowMapSize = getTextureDimensions(shadowParam.textureIndex); - float avgDim = 0.5 * (shadowMapSize.x + shadowMapSize.y); - float resFactor = clamp(1024.0 / max(avgDim, 1.0), 0.75, 1.25); - float distFactor = clamp(distance / 800.0, 0.0, 1.0); - float desiredKernel = mix(1.0, 1.5, distFactor) * resFactor; - int kernelSize = int(clamp(floor(desiredKernel + 0.5), 1.0, 2.0)); - - const vec2 poissonDisk[8] = vec2[]( - vec2(-0.326, -0.406), vec2(-0.840, -0.074), vec2(-0.696, 0.457), - vec2(-0.203, 0.621), vec2(0.962, -0.195), vec2(0.473, -0.480), - vec2(0.519, 0.767), vec2(0.185, -0.893) - ); - float texelRadius = mix(1.0, 3.0, distFactor) * resFactor; - vec2 filterRadius = texelSize * texelRadius; - - int sampleCount = 0; - for (int i = 0; i < 8; ++i) { - vec2 offset = poissonDisk[i] * filterRadius; - vec2 uv = projCoords.xy + offset; - if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) { - continue; - } - float pcfDepth = sampleTextureAt(shadowParam.textureIndex, uv).r; - shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0; - sampleCount++; - } - if (sampleCount > 0) { - shadow /= float(sampleCount); - } - - return shadow; -} - -float calculatePointShadow(ShadowParameters shadowParam, vec3 fragPos) { - vec3 fragToLight = fragPos - shadowParam.lightPos; - float currentDepth = length(fragToLight); - if (currentDepth >= shadowParam.farPlane) return 0.0; - - float bias = 0.05; - float shadow = 0.0; - float diskRadius = (1.0 + (currentDepth / shadowParam.farPlane)) * 0.05; - - const int samples = 8; - const vec3 sampleOffsetDirections[] = vec3[]( - vec3(0.5381, 0.1856, -0.4319), vec3(0.1379, 0.2486, 0.4430), - vec3(0.3371, 0.5679, -0.0057), vec3(-0.6999, -0.0451, -0.0019), - vec3(0.0689, -0.1598, -0.8547), vec3(0.0560, 0.0069, -0.1843), - vec3(-0.0146, 0.1402, 0.0762), vec3(0.0100, -0.1924, -0.0344), - vec3(-0.3577, -0.5301, -0.4358), vec3(-0.3169, 0.1063, 0.0158), - vec3(0.0103, -0.5869, 0.0046), vec3(-0.0897, -0.4940, 0.3287), - vec3(0.7119, -0.0154, -0.0918), vec3(-0.0533, 0.0596, -0.5411), - vec3(0.0352, -0.0631, 0.5460), vec3(-0.4776, 0.2847, -0.0271), - vec3(-0.1120, 0.1234, -0.7446), vec3(-0.2130, -0.0782, -0.1379), - vec3(0.2944, -0.3112, -0.2645), vec3(-0.4564, 0.4175, -0.1843) - ); - - for (int i = 0; i < samples; ++i) { - vec3 sampleDir = normalize(fragToLight + sampleOffsetDirections[i] * diskRadius); - float closestDepth = sampleCubeTextureAt(shadowParam.textureIndex, sampleDir).r * shadowParam.farPlane; - if (currentDepth - bias > closestDepth) { - shadow += 1.0; - } - } - - shadow /= float(samples); - return shadow; -} - -float shadowForLight(int lightType, int lightIndex, vec3 fragPos, vec3 normal) { - for (int i = 0; i < shadowParamCount; ++i) { - if (shadowParams[i].lightType != lightType || - shadowParams[i].lightIndex != lightIndex) continue; - float shadow = lightType == 3 - ? calculatePointShadow(shadowParams[i], fragPos) - : calculateShadow(shadowParams[i], fragPos, normal); - return clamp(shadow * 0.85, 0.0, 1.0); - } - return 0.0; -} - -vec3 evaluateBRDF(vec3 L, vec3 radiance, vec3 N, vec3 V, vec3 F0, vec3 albedo, float metallic, float roughness) { - vec3 H = normalize(V + L); - - float NDF = distributionGGX(N, H, roughness); - float G = geometrySmith(N, V, L, roughness); - vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); - - vec3 kS = F; - vec3 kD = (vec3(1.0) - kS) * (1.0 - metallic); - - float NdotV = max(dot(N, V), 0.0); - float NdotL = max(dot(N, L), 0.0); - - vec3 numerator = NDF * G * F; - float denominator = max(4.0 * NdotV * NdotL, 0.0001); - vec3 specular = numerator / denominator; - - return (kD * albedo / PI + specular) * radiance * NdotL; -} - -vec3 calcDirectionalLight(DirectionalLight light, vec3 N, vec3 V, vec3 F0, vec3 albedo, float metallic, float roughness) { - vec3 L = normalize(-light.direction); - vec3 radiance = light.diffuse * max(light.intensity, 0.0); - return evaluateBRDF(L, radiance, N, V, F0, albedo, metallic, roughness); -} - -vec3 calcPointLight(PointLight light, vec3 fragPos, vec3 N, vec3 V, vec3 F0, vec3 albedo, float metallic, float roughness) { - vec3 L = light.position - fragPos; - float distance = length(L); - vec3 direction = distance > 0.0 ? (L / distance) : vec3(0.0, 0.0, 1.0); - float attenuation = 1.0 / max(light.constant + light.linear * distance + light.quadratic * distance * distance, 0.0001); - float fade = 1.0 - smoothstep(light.radius * 0.9, light.radius, distance); - vec3 radiance = light.diffuse * max(light.intensity, 0.0) * attenuation * fade; - return evaluateBRDF(direction, radiance, N, V, F0, albedo, metallic, roughness); -} - -vec3 calcSpotLight(SpotLight light, vec3 fragPos, vec3 N, vec3 V, vec3 F0, vec3 albedo, float metallic, float roughness) { - vec3 L = light.position - fragPos; - float distance = length(L); - vec3 direction = normalize(L); - - vec3 spotDirection = normalize(light.direction); - float theta = dot(direction, -spotDirection); - float epsilon = max(light.cutOff - light.outerCutOff, 0.0001); - float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0); - - float range = max(light.range, 0.001); - float attenuation = 1.0 / (1.0 + (distance / range) + (distance * distance) / (range * range)); - float fade = 1.0 - smoothstep(range * 0.9, range, distance); - vec3 radiance = light.diffuse * max(light.intensity, 0.0) * attenuation * intensity * fade; - return evaluateBRDF(direction, radiance, N, V, F0, albedo, metallic, roughness); -} - -vec3 sampleEnvironmentRadiance(vec3 direction) { - return texture(skybox, direction).rgb; -} - -vec3 acesToneMapping(vec3 color) { - float a = 2.51; - float b = 0.03; - float c = 2.43; - float d = 0.59; - float e = 0.14; - color = (color * (a * color + b)) / (color * (c * color + d) + e); - color = pow(clamp(color, 0.0, 1.0), vec3(1.0 / 2.2)); - return color; -} - -vec3 getRimLight( - vec3 fragPos, - vec3 N, - vec3 V, - vec3 F0, - vec3 albedo, - float metallic, - float roughness -) { - N = normalize(N); - V = normalize(V); - - float rim = pow(1.0 - max(dot(N, V), 0.0), 3.0); - - rim *= mix(1.2, 0.3, roughness); - - vec3 rimColor = mix(vec3(1.0), albedo, metallic) * environment.rimLightColor; - rimColor = mix(rimColor, F0, 0.5); - - float rimIntensity = environment.rimLightIntensity; - - vec3 rimLight = rimColor * rim * rimIntensity; - - float dist = length(cameraPosition - fragPos); - rimLight /= (1.0 + dist * 0.1); - - return rimLight; -} - -void main() { - vec3 FragPos = texture(gPosition, TexCoord).xyz; - vec3 N = normalize(texture(gNormal, TexCoord).xyz); - vec4 albedoAo = texture(gAlbedoSpec, TexCoord); - vec3 albedo = albedoAo.rgb; - vec4 matData = texture(gMaterial, TexCoord); - float metallic = clamp(matData.r, 0.0, 1.0); - float roughness = clamp(matData.g, 0.0, 1.0); - float ao = clamp(matData.b, 0.0, 1.0); - - float viewDistance = max(length(cameraPosition - FragPos), 1e-6); - vec3 V = (cameraPosition - FragPos) / viewDistance; - - vec3 F0 = mix(vec3(0.04), albedo, metallic); - - float ssaoFactor = clamp(texture(ssao, TexCoord).r, 0.0, 1.0); - float ssaoDesaturated = mix(1.0, ssaoFactor, 0.35); - float occlusion = clamp(ao * (0.2 + 0.8 * ssaoDesaturated), 0.0, 1.0); - float lightingOcclusion = clamp(ssaoDesaturated, 0.2, 1.0); - - vec3 directionalResult = vec3(0.0); - for (int i = 0; i < directionalLightCount; ++i) { - float shadow = shadowForLight(0, i, FragPos, N); - directionalResult += calcDirectionalLight(directionalLights[i], N, V, F0, albedo, metallic, roughness) * (1.0 - shadow); - } - - vec3 pointResult = vec3(0.0); - for (int i = 0; i < pointLightCount; ++i) { - if (length(pointLights[i].position - FragPos) >= pointLights[i].radius) continue; - float shadow = shadowForLight(3, i, FragPos, N); - pointResult += calcPointLight(pointLights[i], FragPos, N, V, F0, albedo, metallic, roughness) * (1.0 - shadow); - } - - vec3 spotResult = vec3(0.0); - for (int i = 0; i < spotlightCount; ++i) { - if (length(spotlights[i].position - FragPos) >= spotlights[i].range) continue; - float shadow = shadowForLight(1, i, FragPos, N); - spotResult += calcSpotLight(spotlights[i], FragPos, N, V, F0, albedo, metallic, roughness) * (1.0 - shadow); - } - - vec3 areaResult = vec3(0.0); - for (int i = 0; i < areaLightCount; ++i) { - vec3 P = areaLights[i].position; - vec3 R = normalize(areaLights[i].right); - vec3 U = normalize(areaLights[i].up); - vec2 halfSize = areaLights[i].size * 0.5; - - vec3 toPoint = FragPos - P; - float s = clamp(dot(toPoint, R), -halfSize.x, halfSize.x); - float t = clamp(dot(toPoint, U), -halfSize.y, halfSize.y); - vec3 Q = P + R * s + U * t; - - vec3 Lvec = Q - FragPos; - float dist = length(Lvec); - if (dist > 0.0001) { - vec3 L = Lvec / dist; - vec3 Nl = normalize(cross(R, U)); - float ndotl = dot(Nl, -L); - - float facing = (areaLights[i].castsBothSides != 0) ? abs(ndotl) : max(ndotl, 0.0); - float cosTheta = cos(radians(areaLights[i].angle)); - - if (facing >= cosTheta && facing > 0.0) { - float range = max(areaLights[i].range, 0.001); - float attenuation = 1.0 / (1.0 + (dist / range) + (dist * dist) / (range * range)); - float fade = 1.0 - smoothstep(range * 0.9, range, dist); - vec3 radiance = areaLights[i].diffuse * max(areaLights[i].intensity, 0.0) * attenuation * facing * fade; - float shadow = shadowForLight(2, i, FragPos, N); - areaResult += evaluateBRDF(L, radiance, N, V, F0, albedo, metallic, roughness) * (1.0 - shadow); - } - } - } - vec3 rimResult = getRimLight(FragPos, N, V, F0, albedo, metallic, roughness); - vec3 lighting = (directionalResult + pointResult + spotResult + areaResult + rimResult) * lightingOcclusion; - - vec3 ambient = ambientLight.color.rgb * ambientLight.intensity * albedo * occlusion; - - vec3 iblContribution = vec3(0.0); - if (useIBL) { - vec3 irradiance = sampleEnvironmentRadiance(N); - vec3 diffuseIBL = irradiance * albedo; - - vec3 reflection = reflect(-V, N); - vec3 specularEnv = sampleEnvironmentRadiance(reflection); - - vec3 F = fresnelSchlick(max(dot(N, V), 0.0), F0); - vec3 kS = F; - vec3 kD = (vec3(1.0) - kS) * (1.0 - metallic); - - float roughnessAttenuation = mix(1.0, 0.15, clamp(roughness, 0.0, 1.0)); - vec3 specularIBL = specularEnv * roughnessAttenuation; - - iblContribution = (kD * diffuseIBL + kS * specularIBL) * occlusion; - } - - vec3 finalColor = ambient + lighting + iblContribution; - - if (!useIBL) { - vec3 I = normalize(FragPos - cameraPosition); - vec3 R = reflect(-I, N); - - vec3 F = fresnelSchlick(max(dot(N, -I), 0.0), F0); - vec3 kS = F; - vec3 kD = (vec3(1.0) - kS) * (1.0 - metallic); - - vec3 envColor = texture(skybox, R).rgb; - vec3 reflection = envColor * kS; - - finalColor = mix(finalColor, reflection, F0); - } - - FragColor = vec4(finalColor, 1.0); - - float brightness = dot(FragColor.rgb, vec3(0.2126, 0.7152, 0.0722)); - if (brightness > environment.bloomThreshold) { - BrightColor = vec4(FragColor.rgb, 1.0); - } else { - BrightColor = vec4(0.0, 0.0, 0.0, 1.0); - } - - FragColor.rgb = acesToneMapping(FragColor.rgb); -} diff --git a/shaders/opengl/deferred/light.vert b/shaders/opengl/deferred/light.vert deleted file mode 100644 index c1f5967f..00000000 --- a/shaders/opengl/deferred/light.vert +++ /dev/null @@ -1,10 +0,0 @@ -#version 410 core -layout(location = 0) in vec3 aPos; -layout(location = 2) in vec2 aTexCoord; - -out vec2 TexCoord; - -void main() { - TexCoord = aTexCoord; - gl_Position = vec4(aPos, 1.0); -} diff --git a/shaders/opengl/effects/downsample.frag b/shaders/opengl/effects/downsample.frag deleted file mode 100644 index a39c80ca..00000000 --- a/shaders/opengl/effects/downsample.frag +++ /dev/null @@ -1,36 +0,0 @@ -#version 410 core - -uniform sampler2D srcTexture; -uniform vec2 srcResolution; - -in vec2 TexCoord; -layout(location = 0) out vec3 downsample; - -void main() { - vec2 srcTexelSize = 1.0 / srcResolution; - float x = srcTexelSize.x; - float y = srcTexelSize.y; - vec2 texCoord = TexCoord; - - vec3 a = texture(srcTexture, vec2(texCoord.x - 2 * x, texCoord.y + 2 * y)).rgb; - vec3 b = texture(srcTexture, vec2(texCoord.x, texCoord.y + 2 * y)).rgb; - vec3 c = texture(srcTexture, vec2(texCoord.x + 2 * x, texCoord.y + 2 * y)).rgb; - - vec3 d = texture(srcTexture, vec2(texCoord.x - 2 * x, texCoord.y)).rgb; - vec3 e = texture(srcTexture, vec2(texCoord.x, texCoord.y)).rgb; - vec3 f = texture(srcTexture, vec2(texCoord.x + 2 * x, texCoord.y)).rgb; - - vec3 g = texture(srcTexture, vec2(texCoord.x - 2 * x, texCoord.y - 2 * y)).rgb; - vec3 h = texture(srcTexture, vec2(texCoord.x, texCoord.y - 2 * y)).rgb; - vec3 i = texture(srcTexture, vec2(texCoord.x + 2 * x, texCoord.y - 2 * y)).rgb; - - vec3 j = texture(srcTexture, vec2(texCoord.x - x, texCoord.y + y)).rgb; - vec3 k = texture(srcTexture, vec2(texCoord.x + x, texCoord.y + y)).rgb; - vec3 l = texture(srcTexture, vec2(texCoord.x - x, texCoord.y - y)).rgb; - vec3 m = texture(srcTexture, vec2(texCoord.x + x, texCoord.y - y)).rgb; - - downsample = e * 0.125; - downsample += (a + c + g + i) * 0.03125; - downsample += (b + d + f + h) * 0.0625; - downsample += (j + k + l + m) * 0.125; -} diff --git a/shaders/opengl/effects/gaussian.frag b/shaders/opengl/effects/gaussian.frag deleted file mode 100644 index 2ec5a9c3..00000000 --- a/shaders/opengl/effects/gaussian.frag +++ /dev/null @@ -1,32 +0,0 @@ -#version 410 core -out vec4 FragColor; - -in vec2 TexCoord; - -uniform sampler2D image; - -uniform bool horizontal; -uniform float weight[5] = float[](0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216); -uniform float radius = 1.0; - -void main() { - vec2 tex_offset = 1.0 / textureSize(image, 0) * radius; - vec3 result = texture(image, TexCoord).rgb * weight[0]; - if(horizontal) - { - for(int i = 1; i < 5; ++i) - { - result += texture(image, TexCoord + vec2(tex_offset.x * i, 0.0)).rgb * weight[i]; - result += texture(image, TexCoord - vec2(tex_offset.x * i, 0.0)).rgb * weight[i]; - } - } - else - { - for(int i = 1; i < 5; ++i) - { - result += texture(image, TexCoord + vec2(0.0, tex_offset.y * i)).rgb * weight[i]; - result += texture(image, TexCoord - vec2(0.0, tex_offset.y * i)).rgb * weight[i]; - } - } - FragColor = vec4(result, 1.0); -} \ No newline at end of file diff --git a/shaders/opengl/effects/particle.frag b/shaders/opengl/effects/particle.frag deleted file mode 100644 index 086fcfb1..00000000 --- a/shaders/opengl/effects/particle.frag +++ /dev/null @@ -1,23 +0,0 @@ -#version 410 core -in vec2 fragTexCoord; -in vec4 fragColor; -out vec4 FragColor; -uniform sampler2D particleTexture; -uniform bool useTexture; - -void main() { - if (useTexture) { - vec4 texColor = texture(particleTexture, fragTexCoord); - if (texColor.a < 0.01) discard; - FragColor = texColor * fragColor; - } else { - vec2 center = vec2(0.5, 0.5); - float dist = distance(fragTexCoord, center); - - float alpha = 1.0 - smoothstep(0.3, 0.5, dist); - - FragColor = vec4(fragColor.rgb, fragColor.a * alpha); - - if (FragColor.a < 0.01) discard; - } -} \ No newline at end of file diff --git a/shaders/opengl/effects/particle.vert b/shaders/opengl/effects/particle.vert deleted file mode 100644 index 64fbefe8..00000000 --- a/shaders/opengl/effects/particle.vert +++ /dev/null @@ -1,40 +0,0 @@ -#version 410 core - -layout(location = 0) in vec3 quadVertex; -layout(location = 1) in vec2 texCoord; - -layout(location = 2) in vec3 particlePos; -layout(location = 3) in vec4 particleColor; -layout(location = 4) in float particleSize; - -uniform mat4 view; -uniform mat4 projection; -uniform mat4 model; -uniform bool isAmbient; - -out vec2 fragTexCoord; -out vec4 fragColor; - -void main() { - if (isAmbient) { - vec4 viewParticlePos = view * vec4(particlePos, 1.0); - - vec3 viewPosition = - viewParticlePos.xyz + - vec3(quadVertex.x * particleSize, quadVertex.y * particleSize, 0.0); - - gl_Position = projection * model * vec4(viewPosition, 1.0); - } else { - vec3 cameraRight = vec3(view[0][0], view[1][0], view[2][0]); - vec3 cameraUp = vec3(view[0][1], view[1][1], view[2][1]); - - vec3 worldPosition = particlePos + - (quadVertex.x * cameraRight * particleSize) + - (quadVertex.y * cameraUp * particleSize); - - gl_Position = projection * view * vec4(worldPosition, 1.0); - } - - fragTexCoord = texCoord; - fragColor = particleColor; -} \ No newline at end of file diff --git a/shaders/opengl/effects/skybox.frag b/shaders/opengl/effects/skybox.frag deleted file mode 100644 index 7a492468..00000000 --- a/shaders/opengl/effects/skybox.frag +++ /dev/null @@ -1,231 +0,0 @@ -#version 410 core -out vec4 FragColor; -in vec3 TexCoords; -uniform samplerCube skybox; -uniform vec3 sunDirection; -uniform vec4 sunColor; -uniform vec3 moonDirection; -uniform vec4 moonColor; -uniform int hasDayNight; - -uniform float sunTintStrength; -uniform float moonTintStrength; -uniform float sunSizeMultiplier; -uniform float moonSizeMultiplier; -uniform float starDensity; - -float hash21(vec2 p) { - p = fract(p * vec2(123.34, 456.21)); - p += dot(p, p + 45.32); - return fract(p.x * p.y); -} - -float valueNoise(vec2 p) { - vec2 i = floor(p); - vec2 f = fract(p); - f = f * f * (3.0 - 2.0 * f); - - float a = hash21(i); - float b = hash21(i + vec2(1.0, 0.0)); - float c = hash21(i + vec2(0.0, 1.0)); - float d = hash21(i + vec2(1.0, 1.0)); - - return mix(mix(a, b, f.x), mix(c, d, f.x), f.y); -} - -float layeredNoise(vec2 p) { - float total = valueNoise(p) + valueNoise(p * 2.0) * 0.5; - return total / 1.5; -} - -float hash13(vec3 p) { - p = fract(p * 443.897); - p += dot(p, p.yzx + 19.19); - return fract((p.x + p.y) * p.z); -} - -vec3 generateStars(vec3 dir, float density, float nightFactor) { - if (density <= 0.0 || nightFactor <= 0.0) { - return vec3(0.0); - } - - vec3 starSpace = dir * 50.0; - vec3 cell = floor(starSpace); - vec3 localPos = fract(starSpace); - - float rand = hash13(cell); - - if (rand < density * 0.3) { - float randX = hash13(cell + vec3(12.34, 56.78, 90.12)); - float randY = hash13(cell + vec3(23.45, 67.89, 1.23)); - float randZ = hash13(cell + vec3(34.56, 78.90, 12.34)); - - vec3 starPos = vec3(randX, randY, randZ); - float dist = length(localPos - starPos); - - float starSize = 0.02 + hash13(cell + vec3(45.67, 89.01, 23.45)) * 0.03; - float brightness = 0.5 + hash13(cell + vec3(56.78, 90.12, 34.56)) * 0.5; - - float star = smoothstep(starSize, 0.0, dist) * brightness; - float twinkle = 0.8 + 0.2 * sin(hash13(cell + vec3(67.89, 1.23, 45.67)) * 100.0); - star *= twinkle * nightFactor; - - vec3 starColor = vec3(1.0); - if (rand > 0.9) starColor = vec3(0.8, 0.9, 1.0); - else if (rand > 0.8) starColor = vec3(1.0, 0.9, 0.8); - - return starColor * star; - } - - return vec3(0.0); -} - -vec3 generateMoonTexture(vec2 uv, float distanceFromCenter, vec3 tintColor) { - float angle = 0.5; - float ca = cos(angle); - float sa = sin(angle); - uv = vec2(ca * uv.x - sa * uv.y, sa * uv.x + ca * uv.y); - - float largeFeatures = valueNoise(uv * 2.0); - largeFeatures = smoothstep(0.3, 0.7, largeFeatures); - - float mediumCraters = valueNoise(uv * 8.0); - - vec2 craterUV = uv * 6.0; - vec2 craterCell = floor(craterUV); - vec2 craterLocal = fract(craterUV); - - float craters = 1.0; - for (int i = 0; i < 4; i++) { - vec2 neighbor = vec2(float(i % 2), float(i / 2)); - vec2 cellPoint = craterCell + neighbor; - - vec2 craterCenter = vec2(hash21(cellPoint), hash21(cellPoint + vec2(13.7, 27.3))); - float dist = length(craterLocal - neighbor - craterCenter); - - float craterSize = 0.15 + 0.25 * hash21(cellPoint + vec2(5.3, 9.7)); - - if (dist < craterSize) { - float crater = smoothstep(craterSize, craterSize * 0.3, dist); - craters = min(craters, 1.0 - crater * 0.7); - } - } - - float surface = largeFeatures * 0.5 + mediumCraters * 0.5; - surface *= craters; - - float intensity = mix(0.30, 0.75, surface); - - float limb = 1.0 - smoothstep(0.6, 1.0, distanceFromCenter); - intensity *= 0.4 + 0.6 * limb; - intensity *= 1.3; - - return clamp(tintColor * intensity, 0.0, 1.0); -} - -void main() -{ - vec3 dir = normalize(TexCoords); - vec3 color = texture(skybox, TexCoords).rgb; - - if (hasDayNight == 1) { - vec3 normSunDir = normalize(sunDirection); - vec3 normMoonDir = normalize(moonDirection); - - float sunDot = dot(dir, normSunDir); - float moonDot = dot(dir, normMoonDir); - - float nightFactor = smoothstep(0.15, -0.2, sunDirection.y); - - if (starDensity > 0.0) { - color += generateStars(dir, starDensity, nightFactor); - } - - float sunHorizonFade = smoothstep(-0.15, 0.05, sunDirection.y); - - if (sunDirection.y > -0.15) { - float sizeAdjust = 1.0 - (sunSizeMultiplier - 1.0) * 0.001; - float sunSize = 0.9995 * sizeAdjust; - float sunGlowSize = 0.998 * (1.0 - (sunSizeMultiplier - 1.0) * 0.003); - float sunHaloSize = 0.99 * (1.0 - (sunSizeMultiplier - 1.0) * 0.015); - - float sunDisk = smoothstep(sunSize - 0.0002, sunSize, sunDot); - float sunGlow = smoothstep(sunGlowSize, sunSize, sunDot) * (1.0 - sunDisk); - float sunHalo = smoothstep(sunHaloSize, sunSize, sunDot) * - (1.0 - smoothstep(sunSize, sunGlowSize, sunDot)); - - float horizonBoost = smoothstep(0.1, -0.05, sunDirection.y) * 2.0; - sunHalo *= (0.3 + horizonBoost); - - color += sunColor.rgb * (sunDisk * 5.0 + sunGlow * 0.5 + sunHalo) * sunHorizonFade; - } - - float moonHorizonFade = smoothstep(-0.15, 0.05, moonDirection.y); - - if (moonDirection.y > -0.15) { - float sizeAdjust = 1.0 - (moonSizeMultiplier - 1.0) * 0.001; - float moonSize = 0.9996 * sizeAdjust; - float moonGlowSize = 0.9985 * (1.0 - (moonSizeMultiplier - 1.0) * 0.003); - float moonHaloSize = 0.992 * (1.0 - (moonSizeMultiplier - 1.0) * 0.015); - - float moonDisk = smoothstep(moonSize - 0.0002, moonSize, moonDot); - - if (moonDisk > 0.01) { - vec3 up = abs(normMoonDir.y) < 0.999 ? vec3(0.0, 1.0, 0.0) : vec3(1.0, 0.0, 0.0); - vec3 right = normalize(cross(up, normMoonDir)); - vec3 actualUp = cross(normMoonDir, right); - - vec3 relativeDir = dir - normMoonDir * moonDot; - float u = dot(relativeDir, right); - float v = dot(relativeDir, actualUp); - - float distFromCenter = length(vec2(u, v)) / sqrt(1.0 - moonSize * moonSize); - - if (distFromCenter < 1.0) { - vec2 moonUV = vec2(u, v) * 200.0; - vec3 moonTexture = generateMoonTexture(moonUV, distFromCenter, moonColor.rgb); - color += moonTexture * moonDisk * 1.5 * moonHorizonFade; - } else { - color += moonColor.rgb * moonDisk * 1.5 * moonHorizonFade; - } - } - - float moonGlow = smoothstep(moonGlowSize, moonSize, moonDot) * (1.0 - moonDisk); - float moonHalo = smoothstep(moonHaloSize, moonSize, moonDot) * - (1.0 - smoothstep(moonSize, moonGlowSize, moonDot)); - - float moonHorizonBoost = smoothstep(0.1, -0.05, moonDirection.y) * 2.0; - moonHalo *= (0.2 + moonHorizonBoost); - - color += moonColor.rgb * (moonGlow * 0.3 + moonHalo) * moonHorizonFade; - } - - if (sunDirection.y > -0.1 && sunTintStrength > 0.0) { - float sunSkyInfluence = smoothstep(0.7, 0.95, sunDot) * - smoothstep(-0.1, 0.2, sunDirection.y); - color = mix(color, color * sunColor.rgb, sunSkyInfluence * 0.3 * sunTintStrength); - - float sunProximity = smoothstep(0.3, 0.8, sunDot) * - smoothstep(-0.1, 0.3, sunDirection.y); - color += sunColor.rgb * sunProximity * 0.15 * sunTintStrength; - - float globalSunTint = smoothstep(-0.1, 0.5, sunDirection.y); - color = mix(color, sunColor.rgb, globalSunTint * sunTintStrength * 0.08); - } - - if (moonDirection.y > -0.1 && moonTintStrength > 0.0) { - float moonSkyInfluence = smoothstep(0.8, 0.95, moonDot) * - smoothstep(-0.1, 0.2, moonDirection.y); - color = mix(color, color * moonColor.rgb, moonSkyInfluence * 0.2 * moonTintStrength); - - float moonProximity = smoothstep(0.5, 0.85, moonDot) * - smoothstep(-0.1, 0.3, moonDirection.y); - color += moonColor.rgb * moonProximity * 0.08 * moonTintStrength; - - float globalMoonTint = smoothstep(-0.1, 0.5, moonDirection.y); - color = mix(color, moonColor.rgb, globalMoonTint * moonTintStrength * 0.05); - } - } - - FragColor = vec4(color, 1.0); -} \ No newline at end of file diff --git a/shaders/opengl/effects/skybox.vert b/shaders/opengl/effects/skybox.vert deleted file mode 100644 index f88f99d4..00000000 --- a/shaders/opengl/effects/skybox.vert +++ /dev/null @@ -1,15 +0,0 @@ -#version 410 core -layout(location = 0) in vec3 aPos; - -out vec3 TexCoords; - -uniform mat4 projection; -uniform mat4 view; - -void main() { - TexCoords = aPos; - // Drop translation so the cube stays centered on the camera - mat4 viewNoTranslation = mat4(mat3(view)); - vec4 pos = projection * viewNoTranslation * vec4(aPos, 1.0); - gl_Position = pos.xyww; -} diff --git a/shaders/opengl/effects/ssr.frag b/shaders/opengl/effects/ssr.frag deleted file mode 100644 index ec4ad15c..00000000 --- a/shaders/opengl/effects/ssr.frag +++ /dev/null @@ -1,263 +0,0 @@ -#version 410 core -out vec4 FragColor; - -in vec2 TexCoord; - -uniform sampler2D gPosition; -uniform sampler2D gNormal; -uniform sampler2D gAlbedoSpec; -uniform sampler2D gMaterial; -uniform sampler2D sceneColor; -uniform sampler2D gDepth; -uniform sampler2D historyTexture; -uniform samplerCube skybox; - -uniform mat4 projection; -uniform mat4 view; -uniform mat4 inverseProjection; -uniform mat4 inverseView; -uniform vec3 cameraPosition; - -uniform float maxDistance = 30.0; -uniform float resolution = 0.5; -uniform int steps = 64; -uniform float thickness = 2.0; -uniform float maxRoughness = 0.5; -uniform float historyWeight = 0.0; -uniform int debugMode = 0; - -const float PI = 3.14159265359; - -float LinearizeDepth(float depth, float near, float far) { - float z = depth * 2.0 - 1.0; - return (2.0 * near * far) / (far + near - z * (far - near)); -} - -float hash(vec2 p) { - vec3 p3 = fract(vec3(p.xyx) * 0.1031); - p3 += dot(p3, p3.yzx + 33.33); - return fract((p3.x + p3.y) * p3.z); -} - -vec3 fresnelSchlick(float cosTheta, vec3 F0) { - return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); -} - -vec3 sampleSkyReflection(vec3 normal, vec3 viewDir, vec3 albedo, float metallic) { - vec3 reflected = reflect(-normalize(viewDir), normalize(normal)); - vec3 skyColor = texture(skybox, reflected).rgb; - float skyLuma = dot(skyColor, vec3(0.2126, 0.7152, 0.0722)); - if (skyLuma < 0.001) { - float t = clamp(reflected.y * 0.5 + 0.5, 0.0, 1.0); - vec3 horizon = vec3(0.74, 0.79, 0.88); - vec3 zenith = vec3(0.50, 0.64, 0.84); - skyColor = mix(horizon, zenith, t); - } - float tintStrength = metallic * 0.35; - vec3 tint = mix(vec3(1.0), albedo, tintStrength); - return skyColor * tint; -} - -vec4 SSR(vec3 worldPos, vec3 normal, vec3 viewDir, float roughness, float metallic, float reflectivity, vec3 albedo) { - vec3 viewPos = (view * vec4(worldPos, 1.0)).xyz; - vec3 viewNormal = normalize((view * vec4(normal, 0.0)).xyz); - float mirrorFactor = clamp(max(metallic, reflectivity) * (1.0 - roughness), 0.0, 1.0); - vec3 skyReflection = sampleSkyReflection(normal, viewDir, albedo, metallic); - - vec3 viewDirection = normalize(viewPos); - vec3 viewReflect = normalize(reflect(viewDirection, viewNormal)); - - if (viewReflect.z > 0.0) { - return vec4(0.0); - } - - vec3 rayOrigin = viewPos + viewNormal * 0.01; - vec3 rayDir = viewReflect; - - float stepSize = maxDistance / float(steps); - vec3 currentPos = rayOrigin; - - float jitter = hash(gl_FragCoord.xy) * roughness * 0.25; - currentPos += rayDir * stepSize * jitter; - - vec2 hitUV = vec2(-1.0); - float hitDepth = 0.0; - bool hit = false; - vec2 fallbackUV = TexCoord; - bool hasFallbackUV = false; - - vec3 lastPos = currentPos; - - for (int i = 0; i < steps; i++) { - float t = float(i) / float(steps); - float adaptiveStep = mix(0.3, 1.0, t); - currentPos += rayDir * stepSize * adaptiveStep; - - vec4 projectedPos = projection * vec4(currentPos, 1.0); - projectedPos.xyz /= projectedPos.w; - vec2 screenUV = projectedPos.xy * 0.5 + 0.5; - - if (screenUV.x >= 0.0 && screenUV.x <= 1.0 && - screenUV.y >= 0.0 && screenUV.y <= 1.0) { - fallbackUV = screenUV; - hasFallbackUV = true; - } else { - break; - } - - float hierarchyLevel = clamp(floor(log2(1.0 + float(i) * 0.25)), - 0.0, 5.0); - float rawDepth = textureLod(gDepth, screenUV, hierarchyLevel).r; - if (rawDepth >= 0.9999) { - currentPos += rayDir * stepSize * (exp2(hierarchyLevel) - 1.0); - lastPos = currentPos; - continue; - } - - vec3 sampleWorldPos = texture(gPosition, screenUV).xyz; - vec3 sampleNormal = texture(gNormal, screenUV).xyz; - if (dot(sampleNormal, sampleNormal) < 0.01) { - lastPos = currentPos; - continue; - } - if (length(sampleWorldPos - worldPos) < 0.08) { - lastPos = currentPos; - continue; - } - vec3 sampleViewPos = (view * vec4(sampleWorldPos, 1.0)).xyz; - - float sampleDepth = -sampleViewPos.z; - float currentDepth = -currentPos.z; - vec3 sampleViewNormal = normalize((view * vec4(sampleNormal, 0.0)).xyz); - if (dot(sampleViewNormal, viewNormal) > 0.92 && - abs(sampleDepth - currentDepth) < thickness * 1.5) { - lastPos = currentPos; - continue; - } - - float depthDiff = sampleDepth - currentDepth; - - if (depthDiff > 0.0 && depthDiff < thickness) { - vec3 binarySearchStart = lastPos; - vec3 binarySearchEnd = currentPos; - - for (int j = 0; j < 8; j++) { - vec3 midPoint = (binarySearchStart + binarySearchEnd) * 0.5; - - vec4 midProj = projection * vec4(midPoint, 1.0); - midProj.xyz /= midProj.w; - vec2 midUV = midProj.xy * 0.5 + 0.5; - if (midUV.x < 0.0 || midUV.x > 1.0 || midUV.y < 0.0 || midUV.y > 1.0) { - break; - } - - float midRawDepth = texture(gDepth, midUV).r; - if (midRawDepth >= 0.9999) { - binarySearchStart = midPoint; - continue; - } - - vec3 midSampleWorldPos = texture(gPosition, midUV).xyz; - vec3 midSampleViewPos = (view * vec4(midSampleWorldPos, 1.0)).xyz; - float midSampleDepth = -midSampleViewPos.z; - float midCurrentDepth = -midPoint.z; - - if (midCurrentDepth < midSampleDepth) { - binarySearchStart = midPoint; - } else { - binarySearchEnd = midPoint; - } - } - - vec4 finalProj = projection * vec4(binarySearchEnd, 1.0); - finalProj.xyz /= finalProj.w; - hitUV = finalProj.xy * 0.5 + 0.5; - hitDepth = length(currentPos - rayOrigin); - hit = true; - break; - } - - lastPos = currentPos; - } - - if (!hit) { - return vec4(0.0); - } - - vec3 hitColor = texture(sceneColor, hitUV).rgb; - float tintStrength = metallic * 0.35; - vec3 metalTint = mix(vec3(1.0), albedo, tintStrength); - hitColor *= metalTint; - float hitDepthRaw = texture(gDepth, hitUV).r; - vec3 hitNormalSample = texture(gNormal, hitUV).xyz; - float hitNormalLenSq = dot(hitNormalSample, hitNormalSample); - vec3 hitNormalDir = hitNormalLenSq > 1e-5 - ? hitNormalSample * inversesqrt(hitNormalLenSq) - : -rayDir; - float geometryValidity = 1.0 - smoothstep(0.998, 1.0, hitDepthRaw); - geometryValidity *= smoothstep(0.01, 0.1, hitNormalLenSq); - float normalFacing = max(dot(hitNormalDir, -rayDir), 0.0); - geometryValidity *= smoothstep(0.05, 0.25, normalFacing); - float hitLuma = dot(hitColor, vec3(0.2126, 0.7152, 0.0722)); - float skyLuma = dot(skyReflection, vec3(0.2126, 0.7152, 0.0722)); - float luminanceValidity = smoothstep(0.002, 0.03, hitLuma + skyLuma * 0.1); - - vec2 edgeFade = smoothstep(0.0, 0.15, hitUV) * (1.0 - smoothstep(0.85, 1.0, hitUV)); - float edgeFactor = edgeFade.x * edgeFade.y; - - float distanceFade = 1.0 - smoothstep(maxDistance * 0.5, maxDistance, hitDepth); - - float roughnessFade = 1.0 - smoothstep(0.0, maxRoughness, roughness); - float hitConfidence = edgeFactor * distanceFade * roughnessFade; - hitConfidence *= geometryValidity * luminanceValidity; - - vec3 F0 = mix(vec3(0.04), albedo, metallic); - vec3 V = normalize(viewDir); - float cosTheta = max(dot(normal, V), 0.0); - vec3 fresnel = fresnelSchlick(cosTheta, F0); - float fresnelFactor = (fresnel.r + fresnel.g + fresnel.b) / 3.0; - float fresnelWeight = mix(fresnelFactor, 1.0, mirrorFactor); - - vec3 reflectionColor = mix(skyReflection, hitColor, hitConfidence); - float finalFade = mix(hitConfidence * fresnelWeight, 1.0, mirrorFactor); - finalFade = clamp(finalFade, 0.0, 1.0); - - return vec4(reflectionColor, finalFade); -} - -void main() { - vec3 worldPos = texture(gPosition, TexCoord).xyz; - vec3 normal = normalize(texture(gNormal, TexCoord).xyz); - vec3 albedo = texture(gAlbedoSpec, TexCoord).rgb; - vec4 material = texture(gMaterial, TexCoord); - - float metallic = material.r; - float roughness = material.g; - float reflectivity = material.a; - - if (length(normal) < 0.001) { - FragColor = vec4(0.0, 0.0, 0.0, 0.0); - return; - } - - if (roughness > maxRoughness || max(metallic, reflectivity) < 0.02) { - FragColor = vec4(0.0, 0.0, 0.0, 0.0); - return; - } - - vec3 viewDir = normalize(cameraPosition - worldPos); - - vec4 reflection = SSR(worldPos, normal, viewDir, roughness, metallic, reflectivity, albedo); - if (debugMode != 0) { - FragColor = vec4(1.0 - reflection.a, reflection.a, 0.0, 1.0); - return; - } - if (reflection.a > 0.0 && historyWeight > 0.0) { - vec4 history = texture(historyTexture, TexCoord); - float validHistory = step(0.001, history.a); - reflection = mix(reflection, history, - historyWeight * validHistory * reflection.a); - } - - FragColor = reflection; -} diff --git a/shaders/opengl/effects/ssr_blur.frag b/shaders/opengl/effects/ssr_blur.frag deleted file mode 100644 index e69de29b..00000000 diff --git a/shaders/opengl/effects/upsample.frag b/shaders/opengl/effects/upsample.frag deleted file mode 100644 index bf4aaa73..00000000 --- a/shaders/opengl/effects/upsample.frag +++ /dev/null @@ -1,28 +0,0 @@ -#version 410 core -uniform sampler2D srcTexture; -uniform float filterRadius; -uniform vec2 srcResolution; -in vec2 TexCoord; -layout(location = 0) out vec3 upsample; - -void main() { - vec2 texelSize = 1.0 / srcResolution; - float x = filterRadius * texelSize.x; - float y = filterRadius * texelSize.y; - - vec2 texCoord = TexCoord; - vec3 a = texture(srcTexture, vec2(texCoord.x - x, texCoord.y + y)).rgb; - vec3 b = texture(srcTexture, vec2(texCoord.x, texCoord.y + y)).rgb; - vec3 c = texture(srcTexture, vec2(texCoord.x + x, texCoord.y + y)).rgb; - vec3 d = texture(srcTexture, vec2(texCoord.x - x, texCoord.y)).rgb; - vec3 e = texture(srcTexture, vec2(texCoord.x, texCoord.y)).rgb; - vec3 f = texture(srcTexture, vec2(texCoord.x + x, texCoord.y)).rgb; - vec3 g = texture(srcTexture, vec2(texCoord.x - x, texCoord.y - y)).rgb; - vec3 h = texture(srcTexture, vec2(texCoord.x, texCoord.y - y)).rgb; - vec3 i = texture(srcTexture, vec2(texCoord.x + x, texCoord.y - y)).rgb; - - upsample = e * 4.0; - upsample += (b + d + f + h) * 2.0; - upsample += (a + c + g + i); - upsample *= 1.0 / 16.0; -} diff --git a/shaders/opengl/fullscreen.frag b/shaders/opengl/fullscreen.frag deleted file mode 100644 index 31b90f4f..00000000 --- a/shaders/opengl/fullscreen.frag +++ /dev/null @@ -1,876 +0,0 @@ -#version 410 core - -in vec2 TexCoord; -out vec4 FragColor; - -const int TEXTURE_COLOR = 0; -const int TEXTURE_DEPTH = 3; -const int TEXTURE_CUBE_DEPTH = 4; - -const int EFFECT_INVERSION = 0; -const int EFFECT_GRAYSCALE = 1; -const int EFFECT_SHARPEN = 2; -const int EFFECT_BLUR = 3; -const int EFFECT_EDGE_DETECTION = 4; -const int EFFECT_COLOR_CORRECTION = 5; -const int EFFECT_MOTION_BLUR = 6; -const int EFFECT_CHROMATIC_ABERRATION = 7; -const int EFFECT_POSTERIZATION = 8; -const int EFFECT_PIXELATION = 9; -const int EFFECT_DILATION = 10; -const int EFFECT_FILM_GRAIN = 11; - -const float offset = 1.0 / 300.0; -const float exposure = 1.0; - -vec3 reinhardToneMapping(vec3 hdrColor) { - vec3 color = vec3(1.0) - exp(-hdrColor * 1.0); - color = pow(color, vec3(1.0 / 2.2)); - return color; -} - -vec3 acesToneMapping(vec3 color) { - float a = 2.51; - float b = 0.03; - float c = 2.43; - float d = 0.59; - float e = 0.14; - return clamp((color * (a * color + b)) / (color * (c * color + d) + e), 0.0, 1.0); -} - -vec4 sharpen(sampler2D image) { - vec2 offsets[9] = vec2[]( - vec2(-offset, offset), - vec2(0.0f, offset), - vec2(offset, offset), - vec2(-offset, 0.0f), - vec2(0.0f, 0.0f), - vec2(offset, 0.0f), - vec2(-offset, -offset), - vec2(0.0f, -offset), - vec2(offset, -offset) - ); - - float kernel[9] = float[]( - -1, -1, -1, - -1, 9, -1, - -1, -1, -1 - ); - - vec3 sampleTex[9]; - for (int i = 0; i < 9; i++) { - sampleTex[i] = vec3(texture(image, TexCoord.st + offsets[i])); - } - - vec3 col = vec3(0.0); - for (int i = 0; i < 9; i++) { - col += sampleTex[i] * kernel[i]; - } - - return vec4(col, 1.0); -} - -vec4 blur(sampler2D image, float radius) { - vec2 texelSize = 1.0 / textureSize(image, 0); - vec3 result = vec3(0.0); - float total = 0.0; - - float sigma = radius * 0.5; - float twoSigmaSq = 2.0 * sigma * sigma; - - for (int x = -int(radius); x <= int(radius); x++) { - float weight = exp(-(x * x) / twoSigmaSq); - vec2 offset = vec2(x, 0.0) * texelSize; - result += texture(image, TexCoord + offset).rgb * weight; - total += weight; - } - - result /= total; - - return vec4(result, 1.0); -} - -vec4 edgeDetection(sampler2D image) { - vec2 offsets[9] = vec2[]( - vec2(-offset, offset), - vec2(0.0f, offset), - vec2(offset, offset), - vec2(-offset, 0.0f), - vec2(0.0f, 0.0f), - vec2(offset, 0.0f), - vec2(-offset, -offset), - vec2(0.0f, -offset), - vec2(offset, -offset) - ); - - float kernel[9] = float[]( - 1, 1, 1, - 1, -8, 1, - 1, 1, 1 - ); - - vec3 sampleTex[9]; - for (int i = 0; i < 9; i++) { - sampleTex[i] = vec3(texture(image, TexCoord.st + offsets[i])); - } - - vec3 col = vec3(0.0); - for (int i = 0; i < 9; i++) { - col += sampleTex[i] * kernel[i]; - } - - return vec4(col, 1.0); -} - -uniform sampler2D Texture; -uniform sampler2D BrightTexture; -uniform sampler2D DepthTexture; -uniform sampler2D VolumetricLightTexture; -uniform sampler2D PositionTexture; -uniform sampler2D LUTTexture; -uniform sampler2D SSRTexture; -uniform int hasBrightTexture; -uniform int hasDepthTexture; -uniform int hasVolumetricLightTexture; -uniform int hasPositionTexture; -uniform int hasLUTTexture; -uniform int hasSSRTexture; -uniform float lutSize; -uniform samplerCube cubeMap; -uniform bool isCubeMap; -uniform int TextureType; -uniform int EffectCount; -uniform int Effects[10]; -uniform float EffectFloat1[10]; -uniform float EffectFloat2[10]; -uniform float EffectFloat3[10]; -uniform float EffectFloat4[10]; -uniform float EffectFloat5[10]; -uniform float EffectFloat6[10]; - -struct Environment { - vec3 fogColor; - float fogIntensity; -}; - -uniform Environment environment; - -uniform mat4 invProjectionMatrix; -uniform mat4 projectionMatrix; -uniform mat4 viewMatrix; -uniform mat4 invViewMatrix; -uniform mat4 lastViewMatrix; - -uniform float nearPlane = 0.1; -uniform float farPlane = 100.0; - -uniform float focusDepth; -uniform float focusRange; - -uniform int maxMipLevel; -uniform float deltaTime; -uniform float time; - -uniform sampler3D cloudsTexture; -uniform vec3 cloudPosition; -uniform vec3 cloudSize; -uniform vec3 cameraPosition; -uniform float cloudScale; -uniform vec3 cloudOffset; -uniform float cloudDensityThreshold; -uniform float cloudDensityMultiplier; -uniform float cloudAbsorption; -uniform float cloudScattering; -uniform float cloudPhaseG; -uniform float cloudClusterStrength; -uniform int cloudPrimarySteps; -uniform int cloudLightSteps; -uniform float cloudLightStepMultiplier; -uniform float cloudMinStepLength; -uniform vec3 sunDirection; -uniform vec3 sunColor; -uniform float sunIntensity; -uniform vec3 cloudAmbientColor; -uniform int hasClouds; - -vec4 sampleColor(vec2 uv) { - for (int i = 0; i < EffectCount; i++) { - if (Effects[i] == EFFECT_CHROMATIC_ABERRATION) { - float redOffset = EffectFloat1[i]; - float greenOffset = EffectFloat2[i]; - float blueOffset = EffectFloat3[i]; - vec2 focusPoint = vec2(EffectFloat4[i], EffectFloat5[i]); - vec2 sampleCoord = uv; - vec2 direction = sampleCoord - focusPoint; - float red = texture(Texture, sampleCoord + (direction * redOffset)).r; - float green = texture(Texture, sampleCoord + (direction * greenOffset)).g; - vec2 blue = texture(Texture, sampleCoord + (direction * blueOffset)).ba; - return vec4(red, green, blue); - } else if (Effects[i] == EFFECT_PIXELATION) { - float pixelSizeInPixels = EffectFloat1[i]; - vec2 texSize = vec2(textureSize(Texture, 0)); - - vec2 pixelSize = vec2(pixelSizeInPixels) / texSize; - - vec2 pixelated = floor(uv / pixelSize) * pixelSize; - - return texture(Texture, pixelated); - } else if (Effects[i] == EFFECT_DILATION) { - float radius = EffectFloat1[i]; - float separation = EffectFloat2[i]; - vec2 texelSize = 1.0 / vec2(textureSize(Texture, 0)); - - vec3 maxColor = texture(Texture, uv).rgb; - int range = int(radius); - float radiusSq = radius * radius; - - for (int x = -range; x <= range; x++) { - for (int y = -range; y <= range; y++) { - float distSq = float(x * x + y * y); - if (distSq <= radiusSq) { - vec2 offset = vec2(float(x), float(y)) * texelSize * separation; - vec3 sampled = texture(Texture, uv + offset).rgb; - maxColor = max(maxColor, sampled); - } - } - } - - return vec4(maxColor, texture(Texture, uv).a); - } - } - - return texture(Texture, uv); -} - -vec4 sampleBright(vec2 uv) { - for (int i = 0; i < EffectCount; i++) { - if (Effects[i] == EFFECT_CHROMATIC_ABERRATION) { - float redOffset = EffectFloat1[i]; - float greenOffset = EffectFloat2[i]; - float blueOffset = EffectFloat3[i]; - vec2 focusPoint = vec2(EffectFloat4[i], EffectFloat5[i]); - vec2 sampleCoord = uv; - vec2 direction = sampleCoord - focusPoint; - float red = texture(BrightTexture, sampleCoord + (direction * redOffset)).r; - float green = texture(BrightTexture, sampleCoord + (direction * greenOffset)).g; - vec2 blue = texture(BrightTexture, sampleCoord + (direction * blueOffset)).ba; - return vec4(red, green, blue); - } else if (Effects[i] == EFFECT_PIXELATION) { - float pixelSizeInPixels = EffectFloat1[i]; - vec2 texSize = vec2(textureSize(BrightTexture, 0)); - - vec2 pixelSize = vec2(pixelSizeInPixels) / texSize; - - vec2 pixelated = floor(uv / pixelSize) * pixelSize; - vec4 color = texture(BrightTexture, pixelated); - return color; - } else if (Effects[i] == EFFECT_DILATION) { - float radius = EffectFloat1[i]; - float separation = EffectFloat2[i]; - vec2 texelSize = 1.0 / vec2(textureSize(BrightTexture, 0)); - - vec3 maxColor = texture(BrightTexture, uv).rgb; - int range = int(radius); - float radiusSq = radius * radius; - - for (int x = -range; x <= range; x++) { - for (int y = -range; y <= range; y++) { - float distSq = float(x * x + y * y); - if (distSq <= radiusSq) { - vec2 offset = vec2(float(x), float(y)) * texelSize * separation; - vec3 sampled = texture(BrightTexture, uv + offset).rgb; - maxColor = max(maxColor, sampled); - } - } - } - - return vec4(maxColor, texture(BrightTexture, uv).a); - } - } - - return texture(BrightTexture, uv); -} - -float LinearizeDepth(float depth) { - float z = depth * 2.0 - 1.0; - float linear = (2.0 * nearPlane * farPlane) / - (farPlane + nearPlane - z * (farPlane - nearPlane)); - return linear / farPlane; -} - -vec3 reconstructViewPos(vec2 uv, float depth) { - float z = depth * 2.0 - 1.0; - vec4 clipPos = vec4(uv * 2.0 - 1.0, z, 1.0); - vec4 viewPos = invProjectionMatrix * clipPos; - viewPos /= viewPos.w; - return viewPos.xyz; -} - -struct ChromaticAberrationSettings { - float redOffset; - float greenOffset; - float blueOffset; - vec2 focusPoint; - bool enabled; -}; - -struct ColorCorrection { - float exposure; - float contrast; - float saturation; - float gamma; - float temperature; - float tint; -}; - -vec4 applyColorCorrection(vec4 color, ColorCorrection cc) { - vec3 linearColor = color.rgb; - - linearColor *= pow(2.0, cc.exposure); - - linearColor = (linearColor - 0.5) * cc.contrast + 0.5; - - linearColor.r += cc.temperature * 0.05; - linearColor.g += cc.tint * 0.05; - - float luminance = dot(linearColor, vec3(0.2126, 0.7152, 0.0722)); - linearColor = mix(vec3(luminance), linearColor, cc.saturation); - - linearColor = clamp(linearColor, 0.0, 1.0); - - return vec4(linearColor, color.a); -} - -vec4 applyColorEffects(vec4 color) { - for (int i = 0; i < EffectCount; i++) { - if (Effects[i] == EFFECT_INVERSION) { - color = vec4(1.0 - color.rgb, color.a); - } else if (Effects[i] == EFFECT_GRAYSCALE) { - float average = 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b; - color = vec4(average, average, average, color.a); - } else if (Effects[i] == EFFECT_COLOR_CORRECTION) { - ColorCorrection cc; - cc.exposure = EffectFloat1[i]; - cc.contrast = EffectFloat2[i]; - cc.saturation = EffectFloat3[i]; - cc.gamma = EffectFloat4[i]; - cc.temperature = EffectFloat5[i]; - cc.tint = EffectFloat6[i]; - color = applyColorCorrection(color, cc); - } else if (Effects[i] == EFFECT_POSTERIZATION) { - float levels = max(EffectFloat1[i], 1.0); - float grayscale = max(color.r, max(color.g, color.b)); - if (grayscale > 1e-4) { - float lower = floor(grayscale * levels) / levels; - float lowerDiff = abs(grayscale - lower); - float upper = ceil(grayscale * levels) / levels; - float upperDiff = abs(upper - grayscale); - float level = lowerDiff <= upperDiff ? lower : upper; - float adjustment = level / max(grayscale, 1e-4); - color = adjustment * color; - } - } else if (Effects[i] == EFFECT_FILM_GRAIN) { - float amount = EffectFloat1[i]; - - vec3 seed = vec3(gl_FragCoord.xy, deltaTime * 100.0); - - float n = dot(seed, vec3(12.9898, 78.233, 45.164)); - float noise = fract(sin(n) * 43758.5453); - float grain = (noise - 0.5) * 2.0 * amount; - - float luminance = dot(color.rgb, vec3(0.299, 0.587, 0.114)); - float visibility = 1.0 - abs(luminance - 0.5) * 0.5; - - color.rgb += vec3(grain * visibility); - color.rgb = clamp(color.rgb, 0.0, 1.0); - } - } - - return color; -} - -vec4 applyFXAA(sampler2D tex, vec2 texCoord) { - vec2 texelSize = 1.0 / textureSize(tex, 0); - - float FXAA_SPAN_MAX = 8.0; - float FXAA_REDUCE_MUL = 1.0 / 8.0; - float FXAA_REDUCE_MIN = 1.0 / 128.0; - - vec3 rgbNW = sampleColor(texCoord + vec2(-1.0, -1.0) * texelSize).rgb; - vec3 rgbNE = sampleColor(texCoord + vec2(1.0, -1.0) * texelSize).rgb; - vec3 rgbSW = sampleColor(texCoord + vec2(-1.0, 1.0) * texelSize).rgb; - vec3 rgbSE = sampleColor(texCoord + vec2(1.0, 1.0) * texelSize).rgb; - vec3 rgbM = sampleColor(texCoord).rgb; - - vec3 luma = vec3(0.299, 0.587, 0.114); - float lumaNW = dot(rgbNW, luma); - float lumaNE = dot(rgbNE, luma); - float lumaSW = dot(rgbSW, luma); - float lumaSE = dot(rgbSE, luma); - float lumaM = dot(rgbM, luma); - - float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); - float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); - - vec2 dir; - dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); - dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); - - float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * - (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN); - - float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce); - dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), - max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), - dir * rcpDirMin)) * texelSize; - - vec3 rgbA = 0.5 * ( - sampleColor(texCoord + dir * (1.0 / 3.0 - 0.5)).rgb + - sampleColor(texCoord + dir * (2.0 / 3.0 - 0.5)).rgb); - - vec3 rgbB = rgbA * 0.5 + 0.25 * ( - sampleColor(texCoord + dir * -0.5).rgb + - sampleColor(texCoord + dir * 0.5).rgb); - - float lumaB = dot(rgbB, luma); - - if ((lumaB < lumaMin) || (lumaB > lumaMax)) { - return vec4(rgbA, 1.0); - } else { - return vec4(rgbB, 1.0); - } -} - -vec4 composeSSR(vec4 color, vec2 uv) { - if (hasSSRTexture != 1) { - return color; - } - vec4 ssr = texture(SSRTexture, uv); - float reflectionWeight = clamp(ssr.a, 0.0, 1.0); - float baseWeight = 1.0 - reflectionWeight; - color.rgb = color.rgb * baseWeight + ssr.rgb * reflectionWeight; - return color; -} - -vec4 composeLighting(vec2 uv, vec4 baseColor) { - vec4 color = baseColor; - if (hasBrightTexture == 1) { - color += sampleBright(uv); - } - if (hasVolumetricLightTexture == 1) { - color += texture(VolumetricLightTexture, uv); - } - return composeSSR(color, uv); -} - -vec4 applyMotionBlur(vec2 texCoord, float size, float separation, vec4 color) { - vec4 fallbackColor = composeLighting(texCoord, color); - if (size <= 0.0 || separation <= 0.0) { - return fallbackColor; - } - if (hasPositionTexture != 1) { - return fallbackColor; - } - - vec4 worldPos = texture(PositionTexture, texCoord); - if (worldPos.a <= 0.0) { - return fallbackColor; - } - - vec3 viewSpacePos = (viewMatrix * worldPos).xyz; - float distanceToCamera = length(viewSpacePos); - - if (distanceToCamera < nearPlane * 2.0) { - return fallbackColor; - } - - vec4 currentClipPos = projectionMatrix * viewMatrix * worldPos; - currentClipPos.xyz /= currentClipPos.w; - vec2 currentUV = currentClipPos.xy * 0.5 + 0.5; - - vec4 prevClipPos = projectionMatrix * lastViewMatrix * worldPos; - prevClipPos.xyz /= prevClipPos.w; - vec2 prevUV = prevClipPos.xy * 0.5 + 0.5; - - vec2 velocity = (currentUV - prevUV) * separation; - float velocityLength = length(velocity); - - float maxVelocity = 0.12; - if (velocityLength > maxVelocity) { - velocity = normalize(velocity) * maxVelocity; - velocityLength = maxVelocity; - } - if (hasSSRTexture == 1) { - float mirrorWeight = clamp(texture(SSRTexture, texCoord).a, 0.0, 1.0); - float blurDamp = mix(1.0, 0.2, mirrorWeight); - velocity *= blurDamp; - velocityLength *= blurDamp; - } - - if (velocityLength < 0.0001) { - return fallbackColor; - } - - int baseSamples = clamp(int(size), 2, 32); - float sampleScale = - mix(0.75, 1.75, clamp(velocityLength / maxVelocity, 0.0, 1.0)); - int samples = clamp(int(float(baseSamples) * sampleScale), 3, 48); - - float centerDepth = 0.0; - float depthSoftness = 1.0; - if (hasDepthTexture == 1) { - centerDepth = LinearizeDepth(texture(DepthTexture, texCoord).r); - depthSoftness = max(0.002, centerDepth * 0.02); - } - - float jitter = (fract(sin(dot(texCoord * vec2(173.3, 97.1), - vec2(12.9898, 78.233))) * - 43758.5453) - - 0.5) * - 0.35; - - vec4 result = vec4(0.0); - float totalWeight = 0.0; - - for (int i = 0; i < samples; i++) { - float t = ((float(i) + 0.5) / float(samples)) * 2.0 - 1.0; - t += jitter / float(samples); - vec2 sampleCoord = texCoord + velocity * t; - - if (sampleCoord.x < 0.0 || sampleCoord.x > 1.0 || - sampleCoord.y < 0.0 || sampleCoord.y > 1.0) { - continue; - } - - float depthWeight = 1.0; - if (hasDepthTexture == 1) { - float sampleDepth = LinearizeDepth(texture(DepthTexture, sampleCoord).r); - float depthDelta = abs(sampleDepth - centerDepth); - depthWeight = - 1.0 - smoothstep(depthSoftness, depthSoftness * 2.5, depthDelta); - if (depthWeight <= 0.0) { - continue; - } - } - - vec4 sampled = composeLighting(sampleCoord, sampleColor(sampleCoord)); - float gaussian = exp(-4.0 * t * t); - float weight = gaussian * depthWeight; - result += sampled * weight; - totalWeight += weight; - } - - if (totalWeight > 0.0) { - return result / totalWeight; - } - - return fallbackColor; -} - -vec3 sampleLUT(vec3 rgb, float blueSlice, float sliceSize, float slicePixelOffset) { - float sliceY = floor(blueSlice / lutSize); - float sliceX = mod(blueSlice, lutSize); - - vec2 uv; - uv.x = sliceX * sliceSize + slicePixelOffset + rgb.r * sliceSize; - uv.y = sliceY * sliceSize + slicePixelOffset + rgb.g * sliceSize; - - return texture(LUTTexture, uv).rgb; -} - -vec4 mapToLUT(vec4 color) { - if (hasLUTTexture != 1) { - return color; - } - - float sliceSize = 1.0 / lutSize; - float slicePixelOffset = sliceSize * 0.5; - - float blueIndex = color.b * (lutSize - 1.0); - float sliceLow = floor(blueIndex); - float sliceHigh = min(sliceLow + 1.0, lutSize - 1.0); - float t = blueIndex - sliceLow; - - vec3 lowColor = sampleLUT(color.rgb, sliceLow, sliceSize, slicePixelOffset); - vec3 highColor = sampleLUT(color.rgb, sliceHigh, sliceSize, slicePixelOffset); - - vec3 finalRGB = mix(lowColor, highColor, t); - - return vec4(finalRGB, color.a); -} - -vec2 rayBoxDst(vec3 boundsMin, vec3 boundsMax, vec3 rayOrigin, vec3 rayDir) { - vec3 t0 = (boundsMin - rayOrigin) / rayDir; - vec3 t1 = (boundsMax - rayOrigin) / rayDir; - vec3 tMin = min(t0, t1); - vec3 tMax = max(t0, t1); - - float dstA = max(max(tMin.x, tMin.y), tMin.z); - float dstB = min(tMax.x, min(tMax.y, tMax.z)); - - float dstToContainer = max(0.0, dstA); - float dstInsideContainer = max(0.0, dstB - dstToContainer); - - return vec2(dstToContainer, dstInsideContainer); -} - -float saturate(float v) { return clamp(v, 0.0, 1.0); } - -float hashNoise(vec3 p) { - return fract(sin(dot(p, vec3(12.9898, 78.233, 37.719))) * 43758.5453); -} - -float henyeyGreenstein(float cosTheta, float g) { - const float PI = 3.14159265359; - float g2 = g * g; - float denom = pow(1.0 + g2 - 2.0 * g * cosTheta, 1.5); - return (1.0 - g2) / (4.0 * PI * max(denom, 1e-4)); -} - -float calculateCloudDensity(vec3 worldPos) { - vec3 halfExtents = max(cloudSize * 0.5, vec3(1e-4)); - vec3 localPos = (worldPos - cloudPosition) / halfExtents; - - if (any(lessThan(localPos, vec3(-1.0))) || - any(greaterThan(localPos, vec3(1.0)))) { - return 0.0; - } - - vec3 uvw = localPos * 0.5 + 0.5; - float scale = max(cloudScale, 0.001); - vec3 noiseCoord = fract(uvw * scale + cloudOffset); - - vec4 shape = texture(cloudsTexture, noiseCoord); - - float cluster = saturate(cloudClusterStrength); - - float lowerFade = smoothstep(-0.95, -0.6, localPos.y); - float upperFade = 1.0 - smoothstep(0.35, 0.95, localPos.y); - float verticalMask = lowerFade * upperFade; - - float coverageThreshold = mix(0.6, 0.28, cluster); - float coverageSoftness = mix(0.22, 0.34, cluster); - float coverageNoise = mix(shape.r, shape.a, 0.4 + cluster * 0.35); - float coverage = smoothstep(coverageThreshold, - coverageThreshold + coverageSoftness, - coverageNoise); - coverage = pow(coverage, mix(2.0, 0.7, cluster)); - - float detail = mix(smoothstep(0.25, 0.75, shape.g), - smoothstep(0.2, 0.9, shape.a), 0.55); - detail = pow(detail, mix(1.6, 0.85, cluster)); - - float cavityNoise = smoothstep(0.22, 0.85, shape.b); - float gapMask = clamp(1.0 - cavityNoise * mix(0.25, 0.7, cluster), 0.0, 1.0); - - float density = coverage * mix(detail, 1.0, cluster * 0.35); - density = max(density * gapMask * verticalMask - 0.02, 0.0); - density *= max(cloudDensityMultiplier, 0.0); - - return density; -} - -float sampleSunTransmittance(vec3 worldPos, float stepSize) { - vec3 lightDir = -sunDirection; - float dirLength = length(lightDir); - if (dirLength < 1e-3) { - lightDir = vec3(0.0, 1.0, 0.0); - } else { - lightDir /= dirLength; - } - - float maxDistance = length(cloudSize) * 1.5; - float travel = 0.0; - float attenuation = 1.0; - float lightStep = max(stepSize * cloudLightStepMultiplier, cloudMinStepLength); - - int steps = max(cloudLightSteps, 1); - for (int i = 0; i < steps && attenuation > 0.05; ++i) { - travel += lightStep; - if (travel > maxDistance) - break; - - vec3 samplePos = worldPos + lightDir * travel; - float density = calculateCloudDensity(samplePos); - attenuation *= exp(-density * lightStep * cloudAbsorption); - lightStep = max(lightStep * cloudLightStepMultiplier, cloudMinStepLength); - } - - return attenuation; -} - -vec4 cloudRendering(vec4 inColor) { - if (hasClouds != 1) { - return inColor; - } - - float nonLinearDepth = hasDepthTexture == 1 - ? texture(DepthTexture, TexCoord).r - : 1.0; - bool depthAvailable = hasDepthTexture == 1 && nonLinearDepth < 1.0; - float depthSample = depthAvailable ? nonLinearDepth : 1.0; - - vec3 rayOrigin = cameraPosition; - - vec4 clipSpace = vec4(TexCoord * 2.0 - 1.0, depthSample * 2.0 - 1.0, 1.0); - vec4 viewSpace = invProjectionMatrix * clipSpace; - viewSpace /= viewSpace.w; - vec3 worldPos = (invViewMatrix * vec4(viewSpace.xyz, 1.0)).xyz; - - vec3 rayDir = normalize(worldPos - rayOrigin); - - float sceneDistance = depthAvailable ? length(worldPos - rayOrigin) : 1e6; - - vec3 boundsMin = cloudPosition - cloudSize * 0.5; - vec3 boundsMax = cloudPosition + cloudSize * 0.5; - vec2 rayBoxInfo = rayBoxDst(boundsMin, boundsMax, rayOrigin, rayDir); - - float distToContainer = rayBoxInfo.x; - float distInContainer = rayBoxInfo.y; - - if (distInContainer <= 0.0) { - return inColor; - } - - float dstLimit = min(sceneDistance - distToContainer, distInContainer); - dstLimit = max(dstLimit, 0.0); - if (dstLimit <= 1e-4) { - return inColor; - } - - int steps = max(cloudPrimarySteps, 8); - float baseStep = dstLimit / float(steps); - float stepSize = max(baseStep, cloudMinStepLength); - - float jitter = hashNoise(vec3(TexCoord, time)) - 0.5; - float travelled = clamp(jitter, -0.35, 0.35) * stepSize; - travelled = max(travelled, 0.0); - - vec3 accumulatedLight = vec3(0.0); - float transmittance = 1.0; - - vec3 sunDir = sunDirection; - float sunLen = length(sunDir); - if (sunLen > 1e-3) { - sunDir /= sunLen; - } else { - sunDir = vec3(0.0, 1.0, 0.0); - } - - float phaseG = clamp(cloudPhaseG, -0.95, 0.95); - - for (int step = 0; step < steps && travelled < dstLimit; - ++step) { - if (transmittance <= 0.01) { - break; - } - - float remainingDistance = dstLimit - travelled; - if (remainingDistance <= 1e-5) { - break; - } - - float current = distToContainer + travelled; - vec3 samplePos = rayOrigin + rayDir * current; - - float density = calculateCloudDensity(samplePos); - if (density > 1e-4) { - float adaptiveStep = stepSize; - if (density < 0.02) { - adaptiveStep = stepSize * 2.5; - } else if (density < 0.05) { - adaptiveStep = stepSize * 1.6; - } - adaptiveStep = min(adaptiveStep, remainingDistance); - float sampleWeight = density * adaptiveStep; - - float lightTrans = sampleSunTransmittance(samplePos, adaptiveStep); - float cosTheta = clamp(dot(rayDir, -sunDir), -1.0, 1.0); - float phase = henyeyGreenstein(cosTheta, phaseG); - - vec3 directLight = sunColor * sunIntensity * lightTrans * phase; - vec3 ambientLight = cloudAmbientColor; - - vec3 lighting = (ambientLight * 0.35 + directLight) * - sampleWeight * cloudScattering; - - accumulatedLight += lighting * transmittance; - transmittance *= exp(-density * adaptiveStep * cloudAbsorption); - travelled += adaptiveStep; - continue; - } - - float emptyAdvance = min(stepSize * 2.25, remainingDistance); - float minAdvance = min(stepSize * 0.5, remainingDistance); - travelled += max(emptyAdvance, minAdvance); - } - - vec3 finalColor = inColor.rgb * transmittance + accumulatedLight; - return vec4(clamp(finalColor, 0.0, 1.0), inColor.a); -} - -void main() { - vec4 color = sampleColor(TexCoord); - float depth = texture(DepthTexture, TexCoord).r; - vec3 viewPos = reconstructViewPos(TexCoord, depth); - float distance = length(viewPos); - - bool useMotionBlur = false; - float motionBlurSize = 0.0; - float motionBlurSeparation = 0.0; - - for (int i = 0; i < EffectCount; i++) { - if (Effects[i] == EFFECT_MOTION_BLUR) { - useMotionBlur = true; - motionBlurSize = EffectFloat1[i]; - motionBlurSeparation = EffectFloat2[i]; - } - } - - for (int i = 0; i < EffectCount; i++) { - if (Effects[i] == EFFECT_SHARPEN) { - color = sharpen(Texture); - } else if (Effects[i] == EFFECT_BLUR) { - float radius = EffectFloat1[i]; - color = blur(Texture, radius); - } else if (Effects[i] == EFFECT_EDGE_DETECTION) { - color = edgeDetection(Texture); - } - } - - color = applyFXAA(Texture, TexCoord); - - color = applyColorEffects(color); - - if (hasDepthTexture == 1) { - float depthValue = texture(DepthTexture, TexCoord).r; - float linearDepth = LinearizeDepth(depthValue); - float coc = clamp(abs(linearDepth - focusDepth) / focusRange, 0.0, 1.0); - float mip = coc * float(maxMipLevel) * 1.2; - vec3 blurred = applyColorEffects(textureLod(Texture, TexCoord, mip)).rgb; - vec3 sharp = color.rgb; - color = cloudRendering(color); - } else { - color = cloudRendering(color); - } - - vec4 hdrColor; - if (useMotionBlur) { - vec4 motionBlurred = applyMotionBlur(TexCoord, motionBlurSize, motionBlurSeparation, color); - FragColor = motionBlurred; - return; - } else { - hdrColor = composeLighting(TexCoord, color); - } - - hdrColor = mapToLUT(hdrColor); - - - hdrColor.rgb = acesToneMapping(hdrColor.rgb); - - - float fogFactor = 1.0 - exp(-distance * environment.fogIntensity); - vec3 finalColor = mix(hdrColor.rgb, environment.fogColor, fogFactor); - - FragColor = vec4(finalColor, 1.0); -} diff --git a/shaders/opengl/fullscreen.vert b/shaders/opengl/fullscreen.vert deleted file mode 100644 index 8212a5d5..00000000 --- a/shaders/opengl/fullscreen.vert +++ /dev/null @@ -1,13 +0,0 @@ -#version 410 core - -layout (location = 0) in vec3 aPos; -layout (location = 1) in vec4 aColor; -layout (location = 2) in vec2 aTexCoord; -layout (location = 3) in vec3 aNormal; - -out vec2 TexCoord; - -void main() { - gl_Position = vec4(aPos.xy, 0.0, 1.0); - TexCoord = aTexCoord; -} diff --git a/shaders/opengl/lighting/binn_phong.vert b/shaders/opengl/lighting/binn_phong.vert deleted file mode 100644 index 8ddcd461..00000000 --- a/shaders/opengl/lighting/binn_phong.vert +++ /dev/null @@ -1,38 +0,0 @@ -#version 410 core -layout(location = 0) in vec3 aPos; -layout(location = 1) in vec4 aColor; -layout(location = 2) in vec2 aTexCoord; -layout(location = 3) in vec3 aNormal; -layout(location = 4) in vec3 aTangent; -layout(location = 5) in vec3 aBitangent; -layout(location = 6) in mat4 instanceModel; - -uniform mat4 model; -uniform mat4 view; -uniform mat4 projection; -uniform bool isInstanced = true; - -out vec4 outColor; -out vec2 TexCoord; -out vec3 Normal; -out vec3 FragPos; -out mat3 TBN; - -void main() { - mat4 mvp; - if (isInstanced) { - mvp = projection * view * instanceModel; - } else { - mvp = projection * view * model; - } - gl_Position = mvp * vec4(aPos, 1.0); - FragPos = vec3(instanceModel * vec4(aPos, 1.0)); - TexCoord = aTexCoord; - Normal = mat3(transpose(inverse(instanceModel))) * aNormal; - outColor = aColor; - - vec3 T = normalize(vec3(instanceModel * vec4(aTangent, 0.0))); - vec3 B = normalize(vec3(instanceModel * vec4(aBitangent, 0.0))); - vec3 N = normalize(vec3(instanceModel * vec4(aNormal, 0.0))); - TBN = mat3(T, B, N); -} diff --git a/shaders/opengl/lighting/blinn_phong.frag b/shaders/opengl/lighting/blinn_phong.frag deleted file mode 100644 index 1f1cbdbb..00000000 --- a/shaders/opengl/lighting/blinn_phong.frag +++ /dev/null @@ -1,564 +0,0 @@ -#version 410 core -layout (location = 0) out vec4 FragColor; -layout (location = 1) out vec4 BrightColor; - -in vec2 TexCoord; -in vec4 outColor; -in vec3 Normal; -in vec3 FragPos; -in mat3 TBN; - -const int TEXTURE_COLOR = 0; -const int TEXTURE_SPECULAR = 1; -const int TEXTURE_DEPTH_CUBE = 4; -const int TEXTURE_NORMAL = 5; -const int TEXTURE_PARALLAX = 6; - -vec2 texCoord; - -// ----- Structures ----- -struct AmbientLight { - vec4 color; - float intensity; -}; - -struct Material { - vec3 ambient; - vec3 diffuse; - vec3 specular; - float shininess; - float reflectivity; -}; - -struct DirectionalLight { - vec3 direction; - vec3 diffuse; - vec3 specular; -}; - -struct PointLight { - vec3 position; - - vec3 diffuse; - vec3 specular; - - float constant; - float linear; - float quadratic; -}; - -struct SpotLight { - vec3 position; - vec3 direction; - float cutOff; - float outerCutOff; - - vec3 diffuse; - vec3 specular; -}; - -struct ShadowParameters { - mat4 lightView; - mat4 lightProjection; - float bias; - int textureIndex; - float farPlane; - vec3 lightPos; - int lightType; -}; - -// ----- Textures ----- -uniform sampler2D texture1; -uniform sampler2D texture2; -uniform sampler2D texture3; -uniform sampler2D texture4; -uniform sampler2D texture5; -uniform sampler2D texture6; -uniform sampler2D texture7; -uniform sampler2D texture8; -uniform sampler2D texture9; -uniform sampler2D texture10; -uniform samplerCube skybox; -uniform samplerCube cubeMap1; -uniform samplerCube cubeMap2; -uniform samplerCube cubeMap3; -uniform samplerCube cubeMap4; -uniform samplerCube cubeMap5; - -// ----- Uniforms ----- -uniform int textureTypes[16]; -uniform int textureCount; - -uniform AmbientLight ambientLight; -uniform Material material; - -uniform DirectionalLight directionalLights[4]; -uniform int directionalLightCount; - -uniform PointLight pointLights[32]; -uniform int pointLightCount; - -uniform SpotLight spotlights[32]; -uniform int spotlightCount; - -uniform ShadowParameters shadowParams[10]; -uniform int shadowParamCount; - -uniform vec3 cameraPosition; -uniform vec2 textureScale; -uniform vec2 textureOffset; - -uniform bool useTexture; -uniform bool useColor; - -// ----- Helper Functions ----- -vec4 enableTextures(int type) { - vec4 color = vec4(0.0); - int count = 0; - for (int i = 0; i < textureCount; i++) { - if (textureTypes[i] == type) { - if (i == 0) color += texture(texture1, texCoord); - else if (i == 1) color += texture(texture2, texCoord); - else if (i == 2) color += texture(texture3, texCoord); - else if (i == 3) color += texture(texture4, texCoord); - else if (i == 4) color += texture(texture5, texCoord); - else if (i == 5) color += texture(texture6, texCoord); - else if (i == 6) color += texture(texture7, texCoord); - else if (i == 7) color += texture(texture8, texCoord); - else if (i == 8) color += texture(texture9, texCoord); - else if (i == 9) color += texture(texture10, texCoord); - count++; - } - } - if (count > 0) color /= float(count); - if (count == 0) return vec4(-1.0); - return color; -} - -vec4 enableCubeMaps(int type, vec3 direction) { - vec4 color = vec4(0.0); - int count = 0; - for (int i = 0; i < 8; i++) { - if (type == i + 10) { - if (i == 0) color += texture(cubeMap1, direction); - else if (i == 1) color += texture(cubeMap2, direction); - else if (i == 2) color += texture(cubeMap3, direction); - else if (i == 3) color += texture(cubeMap4, direction); - else if (i == 4) color += texture(cubeMap5, direction); - count++; - } - } - if (count > 0) color /= float(count); - if (count == 0) return vec4(-1.0); - return color; -} - -vec4 sampleCubeTextureAt(int textureIndex, vec3 direction) { - if (textureIndex == 0) return texture(cubeMap1, direction); - else if (textureIndex == 1) return texture(cubeMap2, direction); - else if (textureIndex == 2) return texture(cubeMap3, direction); - else if (textureIndex == 3) return texture(cubeMap4, direction); - else if (textureIndex == 4) return texture(cubeMap5, direction); - return vec4(0.0); -} - -vec2 getTextureDimensions(int textureIndex) { - if (textureIndex == 0) return vec2(textureSize(texture1, 0)); - else if (textureIndex == 1) return vec2(textureSize(texture2, 0)); - else if (textureIndex == 2) return vec2(textureSize(texture3, 0)); - else if (textureIndex == 3) return vec2(textureSize(texture4, 0)); - else if (textureIndex == 4) return vec2(textureSize(texture5, 0)); - else if (textureIndex == 5) return vec2(textureSize(texture6, 0)); - else if (textureIndex == 6) return vec2(textureSize(texture7, 0)); - else if (textureIndex == 7) return vec2(textureSize(texture8, 0)); - else if (textureIndex == 8) return vec2(textureSize(texture9, 0)); - else if (textureIndex == 9) return vec2(textureSize(texture10, 0)); - return vec2(0); -} - -vec4 sampleTextureAt(int textureIndex, vec2 uv) { - if (textureIndex == 0) return texture(texture1, uv); - else if (textureIndex == 1) return texture(texture2, uv); - else if (textureIndex == 2) return texture(texture3, uv); - else if (textureIndex == 3) return texture(texture4, uv); - else if (textureIndex == 4) return texture(texture5, uv); - else if (textureIndex == 5) return texture(texture6, uv); - else if (textureIndex == 6) return texture(texture7, uv); - else if (textureIndex == 7) return texture(texture8, uv); - else if (textureIndex == 8) return texture(texture9, uv); - else if (textureIndex == 9) return texture(texture10, uv); - return vec4(0.0); -} - -vec3 getSpecularColor() { - vec4 specTex = enableTextures(TEXTURE_SPECULAR); - vec3 specColor = material.specular; - if (specTex.r != -1.0 || specTex.g != -1.0 || specTex.b != -1.0) { - specColor *= specTex.rgb; - } - return specColor; -} - -vec4 applyGammaCorrection(vec4 color, float gamma) { - return vec4(pow(color.rgb, vec3(1.0 / gamma)), color.a); -} - -vec2 parallaxMapping(vec2 texCoords, vec3 viewDir) { - const float minLayers = 8.0; - const float maxLayers = 32.0; - float numLayers = mix(maxLayers, minLayers, abs(dot(vec3(0.0, 0.0, 1.0), viewDir))); - float layerDepth = 1.0 / numLayers; - float currentLayerDepth = 0.0; - - vec2 P = viewDir.xy * 0.1; - vec2 deltaTexCoords = P / numLayers; - - vec2 currentTexCoords = texCoords; - int textureIndex = -1; - for (int i = 0; i < textureCount; i++) { - if (textureTypes[i] == TEXTURE_PARALLAX) { - textureIndex = i; - break; - } - } - if (textureIndex == -1) return texCoords; - float currentDepthMapValue = 1.0 - sampleTextureAt(textureIndex, currentTexCoords).r; - - while (currentLayerDepth < currentDepthMapValue) { - currentTexCoords -= deltaTexCoords; - currentDepthMapValue = 1.0 - sampleTextureAt(textureIndex, currentTexCoords).r; - currentLayerDepth += layerDepth; - } - - vec2 prevTexCoords = currentTexCoords + deltaTexCoords; - float afterDepth = currentDepthMapValue - currentLayerDepth; - float beforeDepth = 1.0 - sampleTextureAt(textureIndex, prevTexCoords).r - (currentLayerDepth - layerDepth); - float weight = afterDepth / (afterDepth - beforeDepth); - currentTexCoords = prevTexCoords * weight + currentTexCoords * (1.0 - weight); - - return currentTexCoords; -} - -vec3 reinhardToneMapping(vec3 hdrColor) { - vec3 color = vec3(1.0) - exp(-hdrColor * 1.0); - color = pow(color, vec3(1.0 / 2.2)); - return color; -} - -vec3 acesToneMapping(vec3 color) { - float a = 2.51; - float b = 0.03; - float c = 2.43; - float d = 0.59; - float e = 0.14; - color = (color * (a * color + b)) / (color * (c * color + d) + e); - color = pow(clamp(color, 0.0, 1.0), vec3(1.0 / 2.2)); - return color; -} - -// ----- Environment Mapping ----- -vec4 getEnvironmentReflected(vec4 color) { - vec3 I = normalize(FragPos - cameraPosition); - vec3 R = reflect(I, normalize(Normal)); - return mix(color, vec4(texture(skybox, R).rgb, 1.0), material.reflectivity); -} - -// ----- Directional Light ----- -vec3 calcDirectionalDiffuse(DirectionalLight light, vec3 norm) { - vec3 lightDir = normalize(-light.direction); - float diff = max(dot(norm, lightDir), 0.0); - return diff * light.diffuse; -} - -vec3 calcDirectionalSpecular(DirectionalLight light, vec3 norm, vec3 viewDir, vec3 specColor, float shininess) { - vec3 lightDir = normalize(-light.direction); - vec3 halfwayDir = normalize(lightDir + viewDir); - float spec = pow(max(dot(Normal, halfwayDir), 0.0), shininess); - return spec * specColor * light.specular; -} - -vec3 calcAllDirectionalLights(vec3 norm, vec3 viewDir) { - vec3 diffuseSum = vec3(0.0); - vec3 specularSum = vec3(0.0); - vec3 specColor = getSpecularColor(); - - for (int i = 0; i < directionalLightCount; i++) { - diffuseSum += calcDirectionalDiffuse(directionalLights[i], norm); - specularSum += calcDirectionalSpecular(directionalLights[i], norm, viewDir, specColor, material.shininess); - } - - diffuseSum *= material.diffuse; - return diffuseSum + specularSum; -} - -// ----- Point Light ----- -vec3 calcPointDiffuse(PointLight light, vec3 norm, vec3 fragPos) { - vec3 lightDir = normalize(light.position - fragPos); - float diff = max(dot(norm, lightDir), 0.0); - return diff * light.diffuse; -} - -vec3 calcPointSpecular(PointLight light, vec3 norm, vec3 fragPos, vec3 viewDir, vec3 specColor, float shininess) { - vec3 lightDir = normalize(light.position - fragPos); - vec3 halfwayDir = normalize(lightDir + viewDir); - float spec = pow(max(dot(Normal, halfwayDir), 0.0), shininess); - return spec * specColor * light.specular; -} - -float calcAttenuation(PointLight light, vec3 fragPos) { - float distance = length(light.position - fragPos); - return 1.0 / (light.constant + light.linear * distance + light.quadratic * distance); -} - -vec3 calcAllPointLights(vec3 norm, vec3 fragPos, vec3 viewDir) { - vec3 diffuseSum = vec3(0.0); - vec3 specularSum = vec3(0.0); - vec3 specColor = getSpecularColor(); - - for (int i = 0; i < pointLightCount; i++) { - float attenuation = calcAttenuation(pointLights[i], fragPos); - diffuseSum += calcPointDiffuse(pointLights[i], norm, fragPos) * attenuation; - specularSum += calcPointSpecular(pointLights[i], norm, fragPos, viewDir, specColor, material.shininess) * attenuation; - } - - diffuseSum *= material.diffuse; - return diffuseSum + specularSum; -} - -// ----- Spot Light ----- -vec3 calcSpotDiffuse(SpotLight light, vec3 norm, vec3 fragPos) { - vec3 lightDir = normalize(light.position - fragPos); - float diff = max(dot(norm, lightDir), 0.0); - - vec3 spotDirection = normalize(light.direction); - float theta = dot(lightDir, -spotDirection); - - float intensity = smoothstep(light.outerCutOff, light.cutOff, theta); - - return diff * light.diffuse * intensity; -} - -vec3 calcSpotSpecular(SpotLight light, vec3 norm, vec3 fragPos, vec3 viewDir, vec3 specColor, float shininess) { - vec3 lightDir = normalize(light.position - fragPos); - vec3 halfwayDir = normalize(lightDir + viewDir); - float spec = pow(max(dot(Normal, halfwayDir), 0.0), shininess); - - vec3 spotDirection = normalize(light.direction); - float theta = dot(lightDir, -spotDirection); - - float intensity = smoothstep(light.outerCutOff, light.cutOff, theta); - - return spec * specColor * light.specular * intensity; -} - -float calcSpotAttenuation(SpotLight light, vec3 fragPos) { - float distance = length(light.position - fragPos); - return 1.0 / (1.0 + 0.09 * distance + 0.032 * distance); -} - -vec3 calcAllSpotLights(vec3 norm, vec3 fragPos, vec3 viewDir) { - vec3 diffuseSum = vec3(0.0); - vec3 specularSum = vec3(0.0); - vec3 specColor = getSpecularColor(); - - for (int i = 0; i < spotlightCount; i++) { - float attenuation = calcSpotAttenuation(spotlights[i], fragPos); - diffuseSum += calcSpotDiffuse(spotlights[i], norm, fragPos) * attenuation; - specularSum += calcSpotSpecular(spotlights[i], norm, fragPos, viewDir, specColor, material.shininess) * attenuation; - } - - diffuseSum *= material.diffuse; - return diffuseSum + specularSum; -} - -// ----- Shadow Calculations ----- -float calculateShadow(ShadowParameters shadowParam, vec4 fragPosLightSpace) { - vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; - projCoords = projCoords * 0.5 + 0.5; - - if (projCoords.x < 0.0 || projCoords.x > 1.0 || - projCoords.y < 0.0 || projCoords.y > 1.0 || - projCoords.z > 1.0) { - return 0.0; - } - - float currentDepth = projCoords.z; - - vec3 lightDir = normalize(-directionalLights[0].direction); - vec3 normal = normalize(Normal); - float biasValue = shadowParam.bias; - float bias = max(biasValue * (1.0 - dot(normal, lightDir)), biasValue); - - float shadow = 0.0; - vec2 texelSize = 1.0 / getTextureDimensions(shadowParam.textureIndex); - - float distance = length(cameraPosition - FragPos); - int kernelSize = int(mix(1.0, 3.0, clamp(distance / 100.0, 0.0, 1.0))); - - int sampleCount = 0; - for (int x = -kernelSize; x <= kernelSize; ++x) { - for (int y = -kernelSize; y <= kernelSize; ++y) { - float pcfDepth = sampleTextureAt(shadowParam.textureIndex, - projCoords.xy + vec2(x, y) * texelSize).r; - shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0; - sampleCount++; - } - } - shadow /= float(sampleCount); - - return shadow; -} - -float calculateShadowRaw(ShadowParameters shadowParam, vec4 fragPosLightSpace) { - vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; - projCoords = projCoords * 0.5 + 0.5; - - if (projCoords.x < 0.0 || projCoords.x > 1.0 || - projCoords.y < 0.0 || projCoords.y > 1.0 || - projCoords.z < 0.0 || projCoords.z > 1.0) { - return 0.0; - } - - float currentDepth = projCoords.z; - float closestDepth = sampleTextureAt(shadowParam.textureIndex, projCoords.xy).r; - - return currentDepth > closestDepth ? 1.0 : 0.0; -} - -float calculateAllShadows() { - float totalShadow = 0.0; - for (int i = 0; i < shadowParamCount; i++) { - vec4 fragPosLightSpace = shadowParams[i].lightProjection * shadowParams[i].lightView * vec4(FragPos, 1.0); - float shadow = calculateShadow(shadowParams[i], fragPosLightSpace); - totalShadow = max(totalShadow, shadow); - } - return totalShadow; -} - -float calculatePointShadow(ShadowParameters shadowParam, vec3 fragPos) -{ - vec3 fragToLight = fragPos - shadowParam.lightPos; - float currentDepth = length(fragToLight); - - float bias = 0.05; - float shadow = 0.0; - - float diskRadius = (1.0 + (currentDepth / shadowParam.farPlane)) * 0.05; - - const int samples = 54; - const vec3 sampleOffsetDirections[] = vec3[]( - vec3(0.5381, 0.1856, -0.4319), vec3(0.1379, 0.2486, 0.4430), - vec3(0.3371, 0.5679, -0.0057), vec3(-0.6999, -0.0451, -0.0019), - vec3(0.0689, -0.1598, -0.8547), vec3(0.0560, 0.0069, -0.1843), - vec3(-0.0146, 0.1402, 0.0762), vec3(0.0100, -0.1924, -0.0344), - vec3(-0.3577, -0.5301, -0.4358), vec3(-0.3169, 0.1063, 0.0158), - vec3(0.0103, -0.5869, 0.0046), vec3(-0.0897, -0.4940, 0.3287), - vec3(0.7119, -0.0154, -0.0918), vec3(-0.0533, 0.0596, -0.5411), - vec3(0.0352, -0.0631, 0.5460), vec3(-0.4776, 0.2847, -0.0271), - vec3(-0.1120, 0.1234, -0.7446), vec3(-0.2130, -0.0782, -0.1379), - vec3(0.2944, -0.3112, -0.2645), vec3(-0.4564, 0.4175, -0.1843), - // remaining random-ish points - vec3(0.1234, -0.5678, 0.7890), vec3(-0.6789, 0.2345, -0.4567), - vec3(0.3456, -0.7890, 0.1234), vec3(-0.2345, 0.5678, -0.6789), - vec3(0.7890, 0.1234, 0.5678), vec3(-0.5678, -0.6789, 0.2345), - vec3(0.4567, 0.7890, -0.2345), vec3(-0.7890, 0.3456, -0.5678), - vec3(0.6789, -0.2345, 0.7890), vec3(-0.1234, 0.6789, -0.4567), - vec3(0.2345, -0.5678, 0.6789), vec3(-0.3456, 0.7890, -0.1234), - vec3(0.5678, 0.2345, -0.7890), vec3(-0.6789, -0.5678, 0.3456), - vec3(0.7890, -0.3456, 0.4567), vec3(-0.2345, 0.1234, -0.6789), - vec3(0.4567, 0.7890, -0.5678), vec3(-0.5678, 0.2345, 0.6789), - vec3(0.3456, -0.7890, -0.1234), vec3(-0.7890, 0.5678, -0.2345), - vec3(0.6789, -0.1234, 0.3456), vec3(-0.4567, 0.7890, 0.2345), - vec3(0.5678, -0.6789, 0.7890), vec3(-0.3456, 0.5678, -0.6789), - vec3(0.2345, -0.7890, 0.5678), vec3(-0.6789, 0.2345, -0.1234), - vec3(0.7890, -0.3456, -0.5678), vec3(-0.5678, 0.6789, 0.2345), - vec3(0.4567, -0.7890, 0.3456), vec3(-0.2345, 0.1234, -0.7890), - vec3(0.3456, -0.5678, 0.6789), vec3(-0.7890, 0.4567, -0.3456), - vec3(0.6789, -0.1234, -0.5678), vec3(-0.4567, 0.2345, 0.7890) - ); - - for (int i = 0; i < samples; ++i) - { - vec3 sampleDir = normalize(fragToLight + sampleOffsetDirections[i] * diskRadius); - float closestDepth = sampleCubeTextureAt(shadowParam.textureIndex, sampleDir).r * shadowParam.farPlane; - if (currentDepth - bias > closestDepth) - shadow += 1.0; - } - - shadow /= float(samples); - return shadow; -} - -float calculateAllPointShadows(vec3 fragPos) { - float totalShadow = 0.0; - for (int i = 0; i < shadowParamCount; i++) { - if (shadowParams[i].lightType == 3) { - float shadow = calculatePointShadow(shadowParams[i], fragPos); - totalShadow = max(totalShadow, shadow); - } - } - return totalShadow; -} - -// ----- Main ----- -void main() { - texCoord = TexCoord * textureScale + textureOffset; - vec4 baseColor; - - vec3 tangentViewDir = normalize((TBN * cameraPosition) - (TBN * FragPos)); - texCoord = parallaxMapping(texCoord, tangentViewDir); - - if (useTexture && !useColor) - baseColor = enableTextures(TEXTURE_COLOR); - else if (useTexture && useColor) - baseColor = enableTextures(TEXTURE_COLOR) * outColor; - else if (!useTexture && useColor) - baseColor = vec4(1.0, 0.0, 0.0, 1.0); - else - baseColor = vec4(1.0); - - FragColor = baseColor; - - vec4 normTexture = enableTextures(TEXTURE_NORMAL); - vec3 norm = vec3(0.0); - if (normTexture.r != -1.0 || normTexture.g != -1.0 || normTexture.b != -1.0) { - norm = normalize(normTexture.rgb * 2.0 - 1.0); - norm = normalize(TBN * norm); - } else { - norm = normalize(Normal); - } - vec3 viewDir = normalize(cameraPosition - FragPos); - - vec3 ambient = ambientLight.color.rgb * ambientLight.intensity * material.ambient; - float dirShadow = 0.0; - for (int i = 0; i < shadowParamCount; i++) { - if (shadowParams[i].lightType != 3) { - vec4 fragPosLightSpace = shadowParams[i].lightProjection * - shadowParams[i].lightView * - vec4(FragPos, 1.0); - dirShadow = max(dirShadow, calculateShadow(shadowParams[i], fragPosLightSpace)); - } - } - - float pointShadow = calculateAllPointShadows(FragPos); - - vec3 directionalLights = calcAllDirectionalLights(norm, viewDir) * (1.0 - dirShadow); - vec3 pointLights = calcAllPointLights(norm, FragPos, viewDir) * (1.0 - pointShadow); - vec3 spotLightsContrib = calcAllSpotLights(norm, FragPos, viewDir); - - vec3 finalColor = (ambient + directionalLights + pointLights + spotLightsContrib) * baseColor.rgb; - - FragColor = vec4(finalColor, baseColor.a); - FragColor = getEnvironmentReflected(FragColor); - - if (FragColor.a < 0.1) - discard; - - float brightness = dot(FragColor.rgb, vec3(0.2126, 0.7152, 0.0722)); - if (brightness > 1.0) - BrightColor = vec4(FragColor.rgb, 1.0); - else - BrightColor = vec4(0.0, 0.0, 0.0, 1.0); - - FragColor.rgb = acesToneMapping(FragColor.rgb); -} diff --git a/shaders/opengl/main.frag b/shaders/opengl/main.frag deleted file mode 100644 index 01c61739..00000000 --- a/shaders/opengl/main.frag +++ /dev/null @@ -1,845 +0,0 @@ -#version 410 core -layout(location = 0) out vec4 FragColor; -layout(location = 1) out vec4 BrightColor; - -in vec2 TexCoord; -in vec4 outColor; -in vec3 Normal; -in vec3 FragPos; -in mat3 TBN; - -const int TEXTURE_COLOR = 0; -const int TEXTURE_SPECULAR = 1; -const int TEXTURE_DEPTH_CUBE = 4; -const int TEXTURE_NORMAL = 5; -const int TEXTURE_PARALLAX = 6; -const int TEXTURE_METALLIC = 9; -const int TEXTURE_ROUGHNESS = 10; -const int TEXTURE_AO = 11; -const int TEXTURE_OPACITY = 12; -const int TEXTURE_HDR_ENVIRONMENT = 13; -const int TEXTURE_PBR_PACK = 14; - -const float PI = 3.14159265; - -vec2 texCoord; - -// ----- Structures ----- -struct AmbientLight { - vec4 color; - float intensity; -}; - -struct Material { - vec3 albedo; - float metallic; - float roughness; - float ao; - float reflectivity; -}; - -struct DirectionalLight { - vec3 direction; - vec3 diffuse; - vec3 specular; - float intensity; -}; - -struct PointLight { - vec3 position; - - vec3 diffuse; - vec3 specular; - - float constant; - float linear; - float quadratic; - float intensity; - float range; -}; - -struct SpotLight { - vec3 position; - vec3 direction; - float cutOff; - float outerCutOff; - float intensity; - float range; - - vec3 diffuse; - vec3 specular; -}; - -struct AreaLight { - vec3 position; - vec3 right; - vec3 up; - vec2 size; - vec3 diffuse; - vec3 specular; - float angle; - float intensity; - float range; - int castsBothSides; -}; - -struct ShadowParameters { - mat4 lightView; - mat4 lightProjection; - float bias; - int textureIndex; - float farPlane; - vec3 lightPos; - int lightType; -}; - -struct Environment { - float rimLightIntensity; - vec3 rimLightColor; -}; - -// ----- Textures ----- -uniform sampler2D texture1; -uniform sampler2D texture2; -uniform sampler2D texture3; -uniform sampler2D texture4; -uniform sampler2D texture5; -uniform sampler2D texture6; -uniform sampler2D texture7; -uniform sampler2D texture8; -uniform sampler2D texture9; -uniform sampler2D texture10; -uniform samplerCube skybox; -uniform samplerCube cubeMap1; -uniform samplerCube cubeMap2; -uniform samplerCube cubeMap3; -uniform samplerCube cubeMap4; -uniform samplerCube cubeMap5; - -// ----- Uniforms ----- -uniform int textureTypes[16]; -uniform int textureCount; - -uniform AmbientLight ambientLight; -uniform Material material; - -uniform DirectionalLight directionalLights[4]; -uniform int directionalLightCount; - -uniform PointLight pointLights[32]; -uniform int pointLightCount; - -uniform SpotLight spotlights[32]; -uniform int spotlightCount; - -uniform AreaLight areaLights[32]; -uniform int areaLightCount; - -uniform ShadowParameters shadowParams[10]; -uniform int shadowParamCount; - -uniform vec3 cameraPosition; -uniform vec2 textureScale; -uniform vec2 textureOffset; - -uniform bool useTexture; -uniform bool useColor; -uniform bool useIBL; - -uniform Environment environment; - -// ----- Helper Functions ----- -vec4 enableTextures(int type) { - vec4 color = vec4(0.0); - int count = 0; - for (int i = 0; i < textureCount; i++) { - if (textureTypes[i] == type) { - if (i == 0) color += texture(texture1, texCoord); - else if (i == 1) color += texture(texture2, texCoord); - else if (i == 2) color += texture(texture3, texCoord); - else if (i == 3) color += texture(texture4, texCoord); - else if (i == 4) color += texture(texture5, texCoord); - else if (i == 5) color += texture(texture6, texCoord); - else if (i == 6) color += texture(texture7, texCoord); - else if (i == 7) color += texture(texture8, texCoord); - else if (i == 8) color += texture(texture9, texCoord); - else if (i == 9) color += texture(texture10, texCoord); - count++; - } - } - if (count > 0) color /= float(count); - if (count == 0) return vec4(-1.0); - return color; -} - -vec4 enableCubeMaps(int type, vec3 direction) { - vec4 color = vec4(0.0); - int count = 0; - for (int i = 0; i < 8; i++) { - if (type == i + 10) { - if (i == 0) color += texture(cubeMap1, direction); - else if (i == 1) color += texture(cubeMap2, direction); - else if (i == 2) color += texture(cubeMap3, direction); - else if (i == 3) color += texture(cubeMap4, direction); - else if (i == 4) color += texture(cubeMap5, direction); - count++; - } - } - if (count > 0) color /= float(count); - if (count == 0) return vec4(-1.0); - return color; -} - -vec4 sampleCubeTextureAt(int textureIndex, vec3 direction) { - if (textureIndex == 0) return texture(cubeMap1, direction); - else if (textureIndex == 1) return texture(cubeMap2, direction); - else if (textureIndex == 2) return texture(cubeMap3, direction); - else if (textureIndex == 3) return texture(cubeMap4, direction); - else if (textureIndex == 4) return texture(cubeMap5, direction); - return vec4(0.0); -} - -vec2 getTextureDimensions(int textureIndex) { - if (textureIndex == 0) return vec2(textureSize(texture1, 0)); - else if (textureIndex == 1) return vec2(textureSize(texture2, 0)); - else if (textureIndex == 2) return vec2(textureSize(texture3, 0)); - else if (textureIndex == 3) return vec2(textureSize(texture4, 0)); - else if (textureIndex == 4) return vec2(textureSize(texture5, 0)); - else if (textureIndex == 5) return vec2(textureSize(texture6, 0)); - else if (textureIndex == 6) return vec2(textureSize(texture7, 0)); - else if (textureIndex == 7) return vec2(textureSize(texture8, 0)); - else if (textureIndex == 8) return vec2(textureSize(texture9, 0)); - else if (textureIndex == 9) return vec2(textureSize(texture10, 0)); - return vec2(0); -} - -vec4 sampleTextureAt(int textureIndex, vec2 uv) { - if (textureIndex == 0) return texture(texture1, uv); - else if (textureIndex == 1) return texture(texture2, uv); - else if (textureIndex == 2) return texture(texture3, uv); - else if (textureIndex == 3) return texture(texture4, uv); - else if (textureIndex == 4) return texture(texture5, uv); - else if (textureIndex == 5) return texture(texture6, uv); - else if (textureIndex == 6) return texture(texture7, uv); - else if (textureIndex == 7) return texture(texture8, uv); - else if (textureIndex == 8) return texture(texture9, uv); - else if (textureIndex == 9) return texture(texture10, uv); - return vec4(0.0); -} - -vec3 getSpecularColor() { - vec4 specTex = enableTextures(TEXTURE_SPECULAR); - vec3 specColor = material.albedo; - if (specTex.r != -1.0 || specTex.g != -1.0 || specTex.b != -1.0) { - specColor *= specTex.rgb; - } - return specColor; -} - -vec4 applyGammaCorrection(vec4 color, float gamma) { - return vec4(pow(color.rgb, vec3(1.0 / gamma)), color.a); -} - -vec2 directionToEquirect(vec3 direction) { - vec3 dir = normalize(direction); - float phi = atan(dir.z, dir.x); - float theta = acos(clamp(dir.y, -1.0, 1.0)); - return vec2((phi + PI) / (2.0 * PI), theta / PI); -} - -vec3 sampleHDRTexture(int textureIndex, vec3 direction) { - vec2 uv = directionToEquirect(direction); - return sampleTextureAt(textureIndex, uv).rgb; -} - -vec3 sampleEnvironmentRadiance(vec3 direction) { - vec3 envColor = vec3(0.0); - int count = 0; - for (int i = 0; i < textureCount; i++) { - if (textureTypes[i] == TEXTURE_HDR_ENVIRONMENT) { - envColor += sampleHDRTexture(i, direction); - count++; - } - } - if (count == 0) { - return vec3(0.0); - } - return envColor / float(count); -} - -vec2 parallaxMapping(vec2 texCoords, vec3 viewDir) { - const float minLayers = 8.0; - const float maxLayers = 32.0; - vec3 v = normalize(viewDir); - float numLayers = mix(maxLayers, minLayers, abs(dot(vec3(0.0, 0.0, 1.0), v))); - float layerDepth = 1.0 / numLayers; - float currentLayerDepth = 0.0; - - const float heightScale = 0.04; - vec2 P = (v.xy / max(v.z, 0.05)) * heightScale; - vec2 deltaTexCoords = P / numLayers; - - vec2 currentTexCoords = texCoords; - int textureIndex = -1; - for (int i = 0; i < textureCount; i++) { - if (textureTypes[i] == TEXTURE_PARALLAX) { - textureIndex = i; - break; - } - } - if (textureIndex == -1) return texCoords; - float currentDepthMapValue = 1.0 - sampleTextureAt(textureIndex, currentTexCoords).r; - - while (currentLayerDepth < currentDepthMapValue) { - currentTexCoords -= deltaTexCoords; - currentDepthMapValue = 1.0 - sampleTextureAt(textureIndex, currentTexCoords).r; - currentLayerDepth += layerDepth; - } - - vec2 prevTexCoords = currentTexCoords + deltaTexCoords; - float afterDepth = currentDepthMapValue - currentLayerDepth; - float beforeDepth = 1.0 - sampleTextureAt(textureIndex, prevTexCoords).r - (currentLayerDepth - layerDepth); - float weight = afterDepth / (afterDepth - beforeDepth); - currentTexCoords = prevTexCoords * weight + currentTexCoords * (1.0 - weight); - - return currentTexCoords; -} - -vec3 reinhardToneMapping(vec3 hdrColor) { - vec3 color = vec3(1.0) - exp(-hdrColor * 1.0); - color = pow(color, vec3(1.0 / 2.2)); - return color; -} - -vec3 acesToneMapping(vec3 color) { - float a = 2.51; - float b = 0.03; - float c = 2.43; - float d = 0.59; - float e = 0.14; - color = (color * (a * color + b)) / (color * (c * color + d) + e); - color = pow(clamp(color, 0.0, 1.0), vec3(1.0 / 2.2)); - return color; -} - -// ----- Environment Mapping ----- -vec4 getEnvironmentReflected(vec4 color) { - vec3 I = normalize(FragPos - cameraPosition); - vec3 R = reflect(I, normalize(Normal)); - return mix(color, vec4(texture(skybox, R).rgb, 1.0), material.reflectivity); -} - -// ----- Rim Light ----- -vec3 getRimLight( - vec3 fragPos, - vec3 N, - vec3 V, - vec3 F0, - vec3 albedo, - float metallic, - float roughness -) { - N = normalize(N); - V = normalize(V); - - float rim = pow(1.0 - max(dot(N, V), 0.0), 3.0); - - rim *= mix(1.2, 0.3, roughness); - - vec3 rimColor = mix(vec3(1.0), albedo, metallic) * environment.rimLightColor; - rimColor = mix(rimColor, F0, 0.5); - - float rimIntensity = environment.rimLightIntensity; - - vec3 rimLight = rimColor * rim * rimIntensity; - - float dist = length(cameraPosition - fragPos); - rimLight /= (1.0 + dist * 0.1); - - return rimLight; -} - -// ----- PBR ----- -float distributionGGX(vec3 N, vec3 H, float roughness) { - float a = roughness * roughness; - float a2 = a * a; - float NdotH = max(dot(N, H), 0.0); - float NdotH2 = NdotH * NdotH; - - float num = a2; - float denom = (NdotH2 * (a2 - 1.0) + 1.0); - denom = 3.14159265 * denom * denom; - - return num / denom; -} - -float geometrySchlickGGX(float NdotV, float roughness) { - float r = (roughness + 1.0); - float k = (r * r) / 8.0; - - float num = NdotV; - float denom = NdotV * (1.0 - k) + k; - - return num / denom; -} - -float geometrySmith(vec3 N, vec3 V, vec3 L, float roughness) { - float NdotV = max(dot(N, V), 0.0); - float NdotL = max(dot(N, L), 0.0); - float ggx2 = geometrySchlickGGX(NdotV, roughness); - float ggx1 = geometrySchlickGGX(NdotL, roughness); - - return ggx1 * ggx2; -} - -vec3 fresnelSchlick(float cosTheta, vec3 F0) { - return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); -} - -vec3 calculatePBR(vec3 N, vec3 V, vec3 L, vec3 F0, vec3 radiance, vec3 albedo, float metallic, float roughness, float reflectivity) { - vec3 H = normalize(V + L); - - float NDF = distributionGGX(N, H, roughness); - float G = geometrySmith(N, V, L, roughness); - vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); - - vec3 kS = F; - vec3 kD = vec3(1.0) - kS; - kD *= 1.0 - metallic; - - vec3 numerator = NDF * G * F; - float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001; - vec3 specular = numerator / denominator; - - float NdotL = max(dot(N, L), 0.0); - - vec3 Lo = (kD * albedo / 3.14159265 + specular) * radiance * NdotL; - return Lo; -} - -vec3 calculatePBRWithAttenuation(vec3 N, vec3 V, vec3 L, vec3 F0, vec3 radianceAttenuated, vec3 albedo, float metallic, float roughness, float reflectivity) { - vec3 H = normalize(V + L); - - float NDF = distributionGGX(N, H, roughness); - float G = geometrySmith(N, V, L, roughness); - vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); - - vec3 kS = F; - vec3 kD = vec3(1.0) - kS; - kD *= 1.0 - metallic; - - vec3 numerator = NDF * G * F; - float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001; - vec3 specular = numerator / denominator; - - float NdotL = max(dot(N, L), 0.0); - - vec3 Lo = (kD * albedo / 3.14159265 + specular) * radianceAttenuated * NdotL; - return Lo; -} - -// ----- Directional Light ----- -vec3 calcAllDirectionalLights(vec3 N, vec3 V, vec3 albedo, float metallic, float roughness, vec3 F0, float reflectivity) { - vec3 Lo = vec3(0.0); - - for (int i = 0; i < directionalLightCount; i++) { - vec3 L = normalize(-directionalLights[i].direction); - vec3 radiance = directionalLights[i].diffuse * max(directionalLights[i].intensity, 0.0); - Lo += calculatePBR(N, V, L, F0, radiance, albedo, metallic, roughness, reflectivity); - } - - return Lo; -} - -// ----- Point Light ----- -float calcAttenuation(PointLight light, vec3 fragPos) { - float distance = length(light.position - fragPos); - return 1.0 / (light.constant + light.linear * distance + light.quadratic * distance); -} - -vec3 calcAllPointLights(vec3 fragPos, vec3 N, vec3 V, vec3 albedo, float metallic, float roughness, vec3 F0, float reflectivity) { - vec3 Lo = vec3(0.0); - for (int i = 0; i < pointLightCount; i++) { - vec3 L = pointLights[i].position - fragPos; - float distance = length(L); - - distance = max(distance, 0.001); - - L = normalize(L); - - float range = max(pointLights[i].range, 0.001); - vec3 radiance = pointLights[i].diffuse * max(pointLights[i].intensity, 0.0); - float attenuation = 1.0 / (1.0 + (distance / range) + (distance * distance) / (range * range)); - float fade = 1.0 - smoothstep(range * 0.9, range, distance); - vec3 radianceAttenuated = radiance * attenuation; - radianceAttenuated *= fade; - - vec3 H = normalize(V + L); - - float NDF = distributionGGX(N, H, roughness); - float G = geometrySmith(N, V, L, roughness); - vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); - - vec3 kS = F; - vec3 kD = vec3(1.0) - kS; - kD *= 1.0 - metallic; - - vec3 numerator = NDF * G * F; - float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001; - vec3 specular = numerator / denominator; - - float NdotL = max(dot(N, L), 0.0); - - Lo += (kD * albedo / 3.14159265 + specular) * radianceAttenuated * NdotL; - } - return Lo; -} - -// ----- Spot Light ----- -vec3 calcAllSpotLights(vec3 N, vec3 fragPos, vec3 L, vec3 viewDir, vec3 albedo, float metallic, float roughness, vec3 F0, float reflectivity) { - vec3 Lo = vec3(0.0); - - for (int i = 0; i < spotlightCount; i++) { - vec3 L = normalize(spotlights[i].position - fragPos); - - vec3 spotDirection = normalize(spotlights[i].direction); - float theta = dot(L, -spotDirection); - float intensity = smoothstep(spotlights[i].outerCutOff, spotlights[i].cutOff, theta); - - float distance = length(spotlights[i].position - fragPos); - distance = max(distance, 0.001); - float range = max(spotlights[i].range, 0.001); - float attenuation = 1.0 / (1.0 + (distance / range) + (distance * distance) / (range * range)); - float fade = 1.0 - smoothstep(range * 0.9, range, distance); - - vec3 radiance = spotlights[i].diffuse * max(spotlights[i].intensity, 0.0) * attenuation * intensity * fade; - - Lo += calculatePBR(N, viewDir, L, F0, radiance, albedo, metallic, roughness, reflectivity); - } - - return Lo; -} - -// ----- Shadow Calculations ----- -float calculateShadow(ShadowParameters shadowParam, vec4 fragPosLightSpace) { - vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; - projCoords = projCoords * 0.5 + 0.5; - - if (projCoords.x < 0.0 || projCoords.x > 1.0 || - projCoords.y < 0.0 || projCoords.y > 1.0 || - projCoords.z > 1.0) { - return 0.0; - } - - float currentDepth = projCoords.z; - - vec3 lightDir = normalize((inverse(shadowParam.lightView) * vec4(0.0, 0.0, -1.0, 0.0)).xyz); - vec3 normal = normalize(Normal); - float biasValue = shadowParam.bias; - float bias = max(biasValue * (1.0 - dot(normal, lightDir)), biasValue); - - float shadow = 0.0; - vec2 texelSize = 1.0 / getTextureDimensions(shadowParam.textureIndex); - - float distance = length(cameraPosition - FragPos); - int kernelSize = int(mix(1.0, 3.0, clamp(distance / 100.0, 0.0, 1.0))); - - int sampleCount = 0; - for (int x = -kernelSize; x <= kernelSize; ++x) { - for (int y = -kernelSize; y <= kernelSize; ++y) { - float pcfDepth = sampleTextureAt(shadowParam.textureIndex, - projCoords.xy + vec2(x, y) * texelSize).r; - shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0; - sampleCount++; - } - } - shadow /= float(sampleCount); - - return shadow; -} - -float calculateShadowRaw(ShadowParameters shadowParam, vec4 fragPosLightSpace) { - vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; - projCoords = projCoords * 0.5 + 0.5; - - if (projCoords.x < 0.0 || projCoords.x > 1.0 || - projCoords.y < 0.0 || projCoords.y > 1.0 || - projCoords.z < 0.0 || projCoords.z > 1.0) { - return 0.0; - } - - float currentDepth = projCoords.z; - float closestDepth = sampleTextureAt(shadowParam.textureIndex, projCoords.xy).r; - - return currentDepth > closestDepth ? 1.0 : 0.0; -} - -float calculateAllShadows() { - float totalShadow = 0.0; - for (int i = 0; i < shadowParamCount; i++) { - vec4 fragPosLightSpace = shadowParams[i].lightProjection * shadowParams[i].lightView * vec4(FragPos, 1.0); - float shadow = calculateShadow(shadowParams[i], fragPosLightSpace); - totalShadow = max(totalShadow, shadow); - } - return totalShadow; -} - -float calculatePointShadow(ShadowParameters shadowParam, vec3 fragPos) -{ - vec3 fragToLight = fragPos - shadowParam.lightPos; - float currentDepth = length(fragToLight); - - float bias = 0.05; - float shadow = 0.0; - - float diskRadius = (1.0 + (currentDepth / shadowParam.farPlane)) * 0.05; - - const int samples = 54; - const vec3 sampleOffsetDirections[] = vec3[]( - vec3(0.5381, 0.1856, -0.4319), vec3(0.1379, 0.2486, 0.4430), - vec3(0.3371, 0.5679, -0.0057), vec3(-0.6999, -0.0451, -0.0019), - vec3(0.0689, -0.1598, -0.8547), vec3(0.0560, 0.0069, -0.1843), - vec3(-0.0146, 0.1402, 0.0762), vec3(0.0100, -0.1924, -0.0344), - vec3(-0.3577, -0.5301, -0.4358), vec3(-0.3169, 0.1063, 0.0158), - vec3(0.0103, -0.5869, 0.0046), vec3(-0.0897, -0.4940, 0.3287), - vec3(0.7119, -0.0154, -0.0918), vec3(-0.0533, 0.0596, -0.5411), - vec3(0.0352, -0.0631, 0.5460), vec3(-0.4776, 0.2847, -0.0271), - vec3(-0.1120, 0.1234, -0.7446), vec3(-0.2130, -0.0782, -0.1379), - vec3(0.2944, -0.3112, -0.2645), vec3(-0.4564, 0.4175, -0.1843), - // remaining random-ish points - vec3(0.1234, -0.5678, 0.7890), vec3(-0.6789, 0.2345, -0.4567), - vec3(0.3456, -0.7890, 0.1234), vec3(-0.2345, 0.5678, -0.6789), - vec3(0.7890, 0.1234, 0.5678), vec3(-0.5678, -0.6789, 0.2345), - vec3(0.4567, 0.7890, -0.2345), vec3(-0.7890, 0.3456, -0.5678), - vec3(0.6789, -0.2345, 0.7890), vec3(-0.1234, 0.6789, -0.4567), - vec3(0.2345, -0.5678, 0.6789), vec3(-0.3456, 0.7890, -0.1234), - vec3(0.5678, 0.2345, -0.7890), vec3(-0.6789, -0.5678, 0.3456), - vec3(0.7890, -0.3456, 0.4567), vec3(-0.2345, 0.1234, -0.6789), - vec3(0.4567, 0.7890, -0.5678), vec3(-0.5678, 0.2345, 0.6789), - vec3(0.3456, -0.7890, -0.1234), vec3(-0.7890, 0.5678, -0.2345), - vec3(0.6789, -0.1234, 0.3456), vec3(-0.4567, 0.7890, 0.2345), - vec3(0.5678, -0.6789, 0.7890), vec3(-0.3456, 0.5678, -0.6789), - vec3(0.2345, -0.7890, 0.5678), vec3(-0.6789, 0.2345, -0.1234), - vec3(0.7890, -0.3456, -0.5678), vec3(-0.5678, 0.6789, 0.2345), - vec3(0.4567, -0.7890, 0.3456), vec3(-0.2345, 0.1234, -0.7890), - vec3(0.3456, -0.5678, 0.6789), vec3(-0.7890, 0.4567, -0.3456), - vec3(0.6789, -0.1234, -0.5678), vec3(-0.4567, 0.2345, 0.7890) - ); - - for (int i = 0; i < samples; ++i) - { - vec3 sampleDir = normalize(fragToLight + sampleOffsetDirections[i] * diskRadius); - float closestDepth = sampleCubeTextureAt(shadowParam.textureIndex, sampleDir).r * shadowParam.farPlane; - if (currentDepth - bias > closestDepth) - shadow += 1.0; - } - - shadow /= float(samples); - return shadow; -} - -float calculateAllPointShadows(vec3 fragPos) { - float totalShadow = 0.0; - for (int i = 0; i < shadowParamCount; i++) { - if (shadowParams[i].lightType == 3) { - float shadow = calculatePointShadow(shadowParams[i], fragPos); - totalShadow = max(totalShadow, shadow); - } - } - return totalShadow; -} - -// ----- Main ----- -void main() { - texCoord = TexCoord * textureScale + textureOffset; - - bool hasParallaxMap = false; - for (int i = 0; i < textureCount; i++) { - if (textureTypes[i] == TEXTURE_PARALLAX) { - hasParallaxMap = true; - break; - } - } - - if (hasParallaxMap) { - vec3 tangentViewDir = normalize(transpose(TBN) * (cameraPosition - FragPos)); - texCoord = parallaxMapping(texCoord, tangentViewDir); - } - - vec4 normTexture = enableTextures(TEXTURE_NORMAL); - vec3 N; - - if (normTexture.r != -1.0 && normTexture.g != -1.0 && normTexture.b != -1.0) { - vec3 tangentNormal = normalize(normTexture.rgb * 2.0 - 1.0); - N = normalize(TBN * tangentNormal); - } else { - N = normalize(Normal); - } - - N = normalize(N); - vec3 V = normalize(cameraPosition - FragPos); - - vec3 albedo = material.albedo; - vec4 albedoTex = enableTextures(TEXTURE_COLOR); - if (albedoTex != vec4(-1.0)) { - albedo *= albedoTex.rgb; - } - vec4 opacityTex = enableTextures(TEXTURE_OPACITY); - if (opacityTex != vec4(-1.0)) { - if (opacityTex.r < 0.1) { - discard; - } - } else if (albedoTex != vec4(-1.0) && albedoTex.a < 0.1) { - discard; - } - - vec4 pbrPackTex = enableTextures(TEXTURE_PBR_PACK); - bool hasPbrPack = pbrPackTex != vec4(-1.0); - - float metallic = material.metallic; - if (hasPbrPack) { - metallic *= pbrPackTex.b; - } else { - vec4 metallicTex = enableTextures(TEXTURE_METALLIC); - if (metallicTex != vec4(-1.0)) { - metallic *= metallicTex.r; - } - } - - float roughness = material.roughness; - if (hasPbrPack) { - roughness *= pbrPackTex.g; - } else { - vec4 roughnessTex = enableTextures(TEXTURE_ROUGHNESS); - if (roughnessTex != vec4(-1.0)) { - roughness *= roughnessTex.r; - } - } - - float ao = material.ao; - if (hasPbrPack) { - ao *= pbrPackTex.r; - } else { - vec4 aoTex = enableTextures(TEXTURE_AO); - if (aoTex != vec4(-1.0)) { - ao *= aoTex.r; - } - } - - vec3 F0 = vec3(0.04); - F0 = mix(F0, albedo, metallic); - - float directionalShadow = 0.0; - float spotShadow = 0.0; - float areaShadow = 0.0; - float pointShadow = 0.0; - - if (shadowParamCount > 0) { - for (int i = 0; i < shadowParamCount; i++) { - if (shadowParams[i].lightType == 0) { - vec4 fragPosLightSpace = shadowParams[i].lightProjection * - shadowParams[i].lightView * - vec4(FragPos, 1.0); - directionalShadow = max(directionalShadow, calculateShadow(shadowParams[i], fragPosLightSpace)); - } else if (shadowParams[i].lightType == 1) { - vec4 fragPosLightSpace = shadowParams[i].lightProjection * - shadowParams[i].lightView * - vec4(FragPos, 1.0); - spotShadow = max(spotShadow, calculateShadow(shadowParams[i], fragPosLightSpace)); - } else if (shadowParams[i].lightType == 2) { - vec4 fragPosLightSpace = shadowParams[i].lightProjection * - shadowParams[i].lightView * - vec4(FragPos, 1.0); - areaShadow = max(areaShadow, calculateShadow(shadowParams[i], fragPosLightSpace)); - } else if (shadowParams[i].lightType == 3) { - pointShadow = max(pointShadow, calculatePointShadow(shadowParams[i], FragPos)); - } - } - } - - float reflectivity = material.reflectivity; - vec3 viewDir = normalize(cameraPosition - FragPos); - - vec3 lighting = vec3(0.0); - - lighting += calcAllDirectionalLights(N, V, albedo, metallic, roughness, F0, reflectivity) * (1.0 - directionalShadow); - lighting += calcAllPointLights(FragPos, N, V, albedo, metallic, roughness, F0, reflectivity) * (1.0 - pointShadow); - lighting += calcAllSpotLights(N, FragPos, V, viewDir, albedo, metallic, roughness, F0, reflectivity) * (1.0 - spotShadow); - lighting += getRimLight(FragPos, N, V, F0, albedo, metallic, roughness); - - { - vec3 areaResult = vec3(0.0); - for (int i = 0; i < areaLightCount; ++i) { - vec3 P = areaLights[i].position; - vec3 R = normalize(areaLights[i].right); - vec3 U = normalize(areaLights[i].up); - vec2 halfSize = areaLights[i].size * 0.5; - - vec3 toPoint = FragPos - P; - float s = clamp(dot(toPoint, R), -halfSize.x, halfSize.x); - float t = clamp(dot(toPoint, U), -halfSize.y, halfSize.y); - vec3 Q = P + R * s + U * t; - - vec3 Lvec = Q - FragPos; - float dist = length(Lvec); - if (dist > 0.0001) { - vec3 L = Lvec / dist; - vec3 Nl = normalize(cross(R, U)); - float ndotl = dot(Nl, -L); - float facing = (areaLights[i].castsBothSides != 0) ? abs(ndotl) : max(ndotl, 0.0); - float cosTheta = cos(radians(areaLights[i].angle)); - if (facing >= cosTheta && facing > 0.0) { - float range = max(areaLights[i].range, 0.001); - float attenuation = 1.0 / (1.0 + (dist / range) + (dist * dist) / (range * range)); - float fade = 1.0 - smoothstep(range * 0.9, range, dist); - vec3 radiance = areaLights[i].diffuse * max(areaLights[i].intensity, 0.0) * attenuation * facing * fade; - vec3 H = normalize(V + L); - float NDF = distributionGGX(N, H, roughness); - float G = geometrySmith(N, V, L, roughness); - vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); - vec3 kS = F; - vec3 kD = (vec3(1.0) - kS) * (1.0 - metallic); - vec3 numerator = NDF * G * F; - float denominator = max(4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0), 0.0001); - vec3 specular = numerator / denominator; - float NdotL = max(dot(N, L), 0.0); - areaResult += (kD * albedo / PI + specular) * radiance * NdotL; - } - } - } - lighting += areaResult * (1.0 - areaShadow); - } - - vec3 ambient = albedo * ambientLight.intensity * ambientLight.color.rgb * ao; - - vec3 iblContribution = vec3(0.0); - if (useIBL) { - vec3 irradiance = sampleEnvironmentRadiance(N); - vec3 diffuseIBL = irradiance * albedo; - - vec3 reflection = reflect(-V, N); - vec3 specularEnv = sampleEnvironmentRadiance(reflection); - - vec3 F = fresnelSchlick(max(dot(N, V), 0.0), F0); - vec3 kS = F; - vec3 kD = vec3(1.0) - kS; - kD *= 1.0 - metallic; - - float roughnessAttenuation = mix(1.0, 0.15, clamp(roughness, 0.0, 1.0)); - vec3 specularIBL = specularEnv * roughnessAttenuation; - - iblContribution = (kD * diffuseIBL + kS * specularIBL) * ao; - } - - vec3 color = ambient + lighting + iblContribution; - - FragColor = vec4(color, 1.0); - - float brightness = dot(color, vec3(0.2126, 0.7152, 0.0722)); - if (brightness > 1.0) - BrightColor = vec4(color, 1.0); - else - BrightColor = vec4(0.0, 0.0, 0.0, 1.0); - - FragColor.rgb = acesToneMapping(FragColor.rgb); -} diff --git a/shaders/opengl/main.vert b/shaders/opengl/main.vert deleted file mode 100644 index 6c18e36c..00000000 --- a/shaders/opengl/main.vert +++ /dev/null @@ -1,40 +0,0 @@ -#version 410 core -layout(location = 0) in vec3 aPos; -layout(location = 1) in vec4 aColor; -layout(location = 2) in vec2 aTexCoord; -layout(location = 3) in vec3 aNormal; -layout(location = 4) in vec3 aTangent; -layout(location = 5) in vec3 aBitangent; -layout(location = 6) in mat4 instanceModel; - -uniform mat4 model; -uniform mat4 view; -uniform mat4 projection; -uniform bool isInstanced = true; - -out vec4 outColor; -out vec2 TexCoord; -out vec3 Normal; -out vec3 FragPos; -out mat3 TBN; - -void main() { - mat4 modelMatrix = model; - if (isInstanced) { - modelMatrix = instanceModel; - } - - mat4 mvp = projection * view * modelMatrix; - gl_Position = mvp * vec4(aPos, 1.0); - - FragPos = vec3(modelMatrix * vec4(aPos, 1.0)); - TexCoord = aTexCoord; - outColor = aColor; - - mat3 normalMatrix = transpose(inverse(mat3(modelMatrix))); - Normal = normalize(normalMatrix * aNormal); - vec3 N = Normal; - vec3 T = normalize(normalMatrix * aTangent); - vec3 B = normalize(normalMatrix * aBitangent); - TBN = mat3(T, B, N); -} diff --git a/shaders/opengl/shadows/depth.vert b/shaders/opengl/shadows/depth.vert deleted file mode 100644 index 5ffa5e85..00000000 --- a/shaders/opengl/shadows/depth.vert +++ /dev/null @@ -1,16 +0,0 @@ -#version 410 core -layout(location = 0) in vec3 aPos; -layout(location = 6) in mat4 instanceModel; - -uniform mat4 projection; // the light space matrix -uniform mat4 view; -uniform mat4 model; -uniform bool isInstanced = true; - -void main() { - if (isInstanced) { - gl_Position = projection * view * instanceModel * vec4(aPos, 1.0); - } else { - gl_Position = projection * view * model * vec4(aPos, 1.0); - } -} diff --git a/shaders/opengl/shadows/empty.frag b/shaders/opengl/shadows/empty.frag deleted file mode 100644 index 4ac3e287..00000000 --- a/shaders/opengl/shadows/empty.frag +++ /dev/null @@ -1,3 +0,0 @@ -#version 410 core - -void main() {} diff --git a/shaders/opengl/shadows/point_depth.frag b/shaders/opengl/shadows/point_depth.frag deleted file mode 100644 index f0ed7bcd..00000000 --- a/shaders/opengl/shadows/point_depth.frag +++ /dev/null @@ -1,13 +0,0 @@ -#version 410 core -in vec4 FragPos; - -uniform vec3 lightPos; -uniform float far_plane; - -void main() { - float lightDistance = length(FragPos.xyz - lightPos); - - lightDistance = lightDistance / far_plane; - - gl_FragDepth = lightDistance; -} \ No newline at end of file diff --git a/shaders/opengl/shadows/point_depth.geom b/shaders/opengl/shadows/point_depth.geom deleted file mode 100644 index 427cffaf..00000000 --- a/shaders/opengl/shadows/point_depth.geom +++ /dev/null @@ -1,19 +0,0 @@ -#version 410 core -layout(triangles) in; -layout(triangle_strip, max_vertices = 18) out; - -uniform mat4 shadowMatrices[6]; - -out vec4 FragPos; - -void main() { - for (int face = 0; face < 6; face++) { - gl_Layer = face; - for (int i = 0; i < 3; i++) { - FragPos = gl_in[i].gl_Position; - gl_Position = shadowMatrices[face] * FragPos; - EmitVertex(); - } - EndPrimitive(); - } -} diff --git a/shaders/opengl/shadows/point_depth.vert b/shaders/opengl/shadows/point_depth.vert deleted file mode 100644 index 90898dd4..00000000 --- a/shaders/opengl/shadows/point_depth.vert +++ /dev/null @@ -1,14 +0,0 @@ -#version 410 core -layout(location = 0) in vec3 aPos; -layout(location = 6) in mat4 instanceModel; - -uniform mat4 model; -uniform bool isInstanced = true; - -void main() { - if (isInstanced) { - gl_Position = model * instanceModel * vec4(aPos, 1.0); - } else { - gl_Position = model * vec4(aPos, 1.0); - } -} \ No newline at end of file diff --git a/shaders/opengl/shadows/ssao.frag b/shaders/opengl/shadows/ssao.frag deleted file mode 100644 index 1a1f0fcd..00000000 --- a/shaders/opengl/shadows/ssao.frag +++ /dev/null @@ -1,66 +0,0 @@ -#version 410 core -out float FragColor; -in vec2 TexCoord; - -uniform sampler2D gPosition; -uniform sampler2D gNormal; -uniform sampler2D texNoise; -uniform vec3 samples[64]; -uniform mat4 projection; -uniform mat4 view; -uniform vec2 noiseScale; - -const int kernelSize = 64; -const float radius = 0.5; -const float bias = 0.025; - -void main() { - vec3 fragPosWorld = texture(gPosition, TexCoord).xyz; - vec3 normalWorld = texture(gNormal, TexCoord).rgb; - - if (length(normalWorld) < 0.001) { - // Treat missing/invalid normals as fully lit (no occlusion) - FragColor = 1.0; - return; - } - - vec3 fragPos = (view * vec4(fragPosWorld, 1.0)).xyz; - vec3 normal = normalize((view * vec4(normalWorld, 0.0)).xyz); - - vec3 randomVec = normalize(texture(texNoise, TexCoord * noiseScale).xyz * 2.0 - 1.0); - vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal)); - vec3 bitangent = cross(normal, tangent); - mat3 TBN = mat3(tangent, bitangent, normal); - - float occlusion = 0.0; - int validSamples = 0; - - for (int i = 0; i < kernelSize; i++) { - vec3 samplePos = TBN * samples[i]; - samplePos = fragPos + samplePos * radius; - - vec4 offset = projection * vec4(samplePos, 1.0); - offset.xyz /= offset.w; - offset.xy = offset.xy * 0.5 + 0.5; - - if (offset.x < 0.0 || offset.x > 1.0 || offset.y < 0.0 || offset.y > 1.0) { - continue; - } - - vec3 samplePosWorld = texture(gPosition, offset.xy).xyz; - float sampleDepth = (view * vec4(samplePosWorld, 1.0)).z; - - float rangeCheck = smoothstep(0.0, 1.0, radius / (abs(fragPos.z - sampleDepth) + 0.001)); - - occlusion += (sampleDepth >= samplePos.z + bias ? 1.0 : 0.0) * rangeCheck; - validSamples++; - } - - if (validSamples > 0) { - occlusion = 1.0 - (occlusion / float(validSamples)); - } else { - occlusion = 1.0; - } - - FragColor = occlusion; -} \ No newline at end of file diff --git a/shaders/opengl/shadows/ssao_blur.frag b/shaders/opengl/shadows/ssao_blur.frag deleted file mode 100644 index ede4257c..00000000 --- a/shaders/opengl/shadows/ssao_blur.frag +++ /dev/null @@ -1,18 +0,0 @@ -#version 410 core -out float FragColor; - -in vec2 TexCoord; - -uniform sampler2D inSSAO; - -void main() { - vec2 texelSize = 1.0 / vec2(textureSize(inSSAO, 0)); - float result = 0.0; - for (int x = -2; x <= 2; x++) { - for (int y = -2; y <= 2; y++) { - vec2 offset = vec2(float(x), float(y)) * texelSize; - result += texture(inSSAO, TexCoord + offset).r; - } - } - FragColor = result / 25.0; -} \ No newline at end of file diff --git a/shaders/opengl/simple/color.frag b/shaders/opengl/simple/color.frag deleted file mode 100644 index 47ac4ada..00000000 --- a/shaders/opengl/simple/color.frag +++ /dev/null @@ -1,12 +0,0 @@ -#version 410 core -layout (location = 0) out vec4 FragColor; -layout (location = 1) out vec4 BrightColor; -in vec4 vertexColor; - -void main() { - vec3 color = vertexColor.rgb / (vertexColor.rgb + vec3(1.0)); - FragColor = vec4(color, vertexColor.a); - if (length(color) > 1.0) { - BrightColor = vec4(color, vertexColor.a); - } -} \ No newline at end of file diff --git a/shaders/opengl/simple/color.vert b/shaders/opengl/simple/color.vert deleted file mode 100644 index f9bc09c9..00000000 --- a/shaders/opengl/simple/color.vert +++ /dev/null @@ -1,22 +0,0 @@ -#version 410 core -layout(location = 0) in vec3 aPos; -layout(location = 1) in vec4 aColor; -layout(location = 6) in mat4 instanceModel; - -out vec4 vertexColor; - -uniform mat4 model; -uniform mat4 view; -uniform mat4 projection; -uniform bool isInstanced = true; - -void main() { - mat4 mvp; - if (isInstanced) { - mvp = projection * view * instanceModel; - } else { - mvp = projection * view * model; - } - gl_Position = mvp * vec4(aPos, 1.0); - vertexColor = aColor; -} diff --git a/shaders/opengl/simple/debug.frag b/shaders/opengl/simple/debug.frag deleted file mode 100644 index 53ae1bea..00000000 --- a/shaders/opengl/simple/debug.frag +++ /dev/null @@ -1,6 +0,0 @@ -#version 410 core -out vec4 FragColor; - -void main() { - FragColor = vec4(1.0, 0.0, 1.0, 1.0); -} diff --git a/shaders/opengl/simple/debug.vert b/shaders/opengl/simple/debug.vert deleted file mode 100644 index 347af555..00000000 --- a/shaders/opengl/simple/debug.vert +++ /dev/null @@ -1,6 +0,0 @@ -#version 410 core -layout (location = 0) in vec3 aPos; - -void main() { - gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0); -} diff --git a/shaders/opengl/simple/texture.frag b/shaders/opengl/simple/texture.frag deleted file mode 100644 index f85352b0..00000000 --- a/shaders/opengl/simple/texture.frag +++ /dev/null @@ -1,36 +0,0 @@ -#version 410 core -out vec4 FragColor; - -in vec2 TexCoord; -in vec4 outColor; - -uniform sampler2D textures[16]; - -uniform bool useTexture; -uniform bool onlyTexture; -uniform int textureCount; - -vec4 calculateAllTextures() { - vec4 color = vec4(0.0); - - for (int i = 0; i <= textureCount; i++) { - color += texture(textures[i], TexCoord); - } - - color /= float(textureCount + 1); - - return color; -} - -void main() { - if (onlyTexture) { - FragColor = calculateAllTextures(); - return; - } - - if (useTexture) { - FragColor = calculateAllTextures() * outColor; - } else { - FragColor = outColor; - } -} diff --git a/shaders/opengl/simple/texture.vert b/shaders/opengl/simple/texture.vert deleted file mode 100644 index 3f33f493..00000000 --- a/shaders/opengl/simple/texture.vert +++ /dev/null @@ -1,18 +0,0 @@ -#version 410 core -layout(location = 0) in vec3 aPos; -layout(location = 1) in vec4 aColor; -layout(location = 2) in vec2 aTexCoord; - -uniform mat4 model; -uniform mat4 view; -uniform mat4 projection; - -out vec4 outColor; -out vec2 TexCoord; - -void main() { - mat4 mvp = projection * view * model; - gl_Position = mvp * vec4(aPos, 1.0); - TexCoord = aTexCoord; - outColor = aColor; -} diff --git a/shaders/opengl/terrain/fluid.frag b/shaders/opengl/terrain/fluid.frag deleted file mode 100644 index 1593f37f..00000000 --- a/shaders/opengl/terrain/fluid.frag +++ /dev/null @@ -1,184 +0,0 @@ -#version 410 core -layout(location = 0) out vec4 FragColor; -layout(location = 1) out vec4 BrightColor; - -in vec2 TexCoord; -in vec3 WorldPos; -in vec3 WorldNormal; -in vec3 WorldTangent; -in vec3 WorldBitangent; - -uniform vec4 waterColor; -uniform sampler2D sceneTexture; -uniform sampler2D sceneDepth; -uniform vec3 cameraPos; -uniform float time; -uniform float refractionStrength; -uniform float reflectionStrength; -uniform float depthFade; -uniform mat4 projection; -uniform mat4 view; -uniform mat4 invProjection; -uniform mat4 invView; -uniform sampler2D reflectionTexture; -uniform sampler2D refractionTexture; -uniform vec3 lightDirection; -uniform vec3 lightColor; -uniform sampler2D movementTexture; -uniform sampler2D normalTexture; -uniform int hasNormalTexture; -uniform int hasMovementTexture; -uniform vec3 windForce; - -void main() -{ - vec3 normal = normalize(WorldNormal); - vec3 viewDir = normalize(cameraPos - WorldPos); - - vec4 clipSpace = projection * view * vec4(WorldPos, 1.0); - vec3 ndc = clipSpace.xyz / clipSpace.w; - vec2 screenUV = ndc.xy * 0.5 + 0.5; - - float windStrength = length(windForce); - vec2 windDir = windStrength > 0.001 ? normalize(windForce.xy) : vec2(1.0, 0.0); - - float waveSpeed = 0.15 + windStrength * 0.3; - float waveAmplitude = 0.01 + windStrength * 0.02; - float waveFrequency = 30.0 + windStrength * 10.0; - - vec2 waveOffset; - waveOffset.x = sin((TexCoord.x * windDir.x + time * waveSpeed) * waveFrequency); - waveOffset.y = cos((TexCoord.y * windDir.y - time * waveSpeed) * waveFrequency); - waveOffset *= waveAmplitude; - - vec2 flowOffset = vec2(0.0); - if (hasMovementTexture == 1) { - vec2 windUV = windForce.xy * time * 0.05; - vec2 movementUV = TexCoord * 2.0 + windUV; - vec2 movementSample = texture(movementTexture, movementUV).rg; - - movementSample = movementSample * 2.0 - 1.0; - - flowOffset = movementSample * windStrength * 0.15; - - waveOffset += flowOffset * 0.5; - } - - if (hasNormalTexture == 1) { - vec3 T = normalize(WorldTangent); - vec3 B = normalize(WorldBitangent); - vec3 N = normalize(WorldNormal); - mat3 TBN = mat3(T, B, N); - - float normalSpeed = 0.03 + windStrength * 0.05; - vec2 normalUV1 = TexCoord * 5.0 + waveOffset * 10.0 + windForce.xy * time * normalSpeed; - vec2 normalUV2 = TexCoord * 3.0 - waveOffset * 8.0 - windForce.xy * time * normalSpeed * 0.8; - - vec3 normalMap1 = texture(normalTexture, normalUV1).rgb; - vec3 normalMap2 = texture(normalTexture, normalUV2).rgb; - - normalMap1 = normalMap1 * 2.0 - 1.0; - normalMap2 = normalMap2 * 2.0 - 1.0; - - vec3 blendedNormal = normalize(normalMap1 + normalMap2); - - vec3 worldSpaceNormal = normalize(TBN * blendedNormal); - - float normalStrength = 0.5 + windStrength * 0.3; - normal = normalize(mix(N, worldSpaceNormal, normalStrength)); - } - - vec2 reflectionUV = screenUV; - reflectionUV.y = 1.0 - reflectionUV.y; - reflectionUV += waveOffset * 0.3; - - vec2 refractionUV = screenUV - waveOffset * 0.2; - - bool reflectionInBounds = (reflectionUV.x >= 0.0 && reflectionUV.x <= 1.0 && - reflectionUV.y >= 0.0 && reflectionUV.y <= 1.0); - bool refractionInBounds = (refractionUV.x >= 0.0 && refractionUV.x <= 1.0 && - refractionUV.y >= 0.0 && refractionUV.y <= 1.0); - - reflectionUV = clamp(reflectionUV, 0.05, 0.95); - refractionUV = clamp(refractionUV, 0.05, 0.95); - - vec2 reflectionEdgeFade = smoothstep(0.0, 0.15, reflectionUV) * smoothstep(1.0, 0.85, reflectionUV); - float reflectionFadeFactor = reflectionEdgeFade.x * reflectionEdgeFade.y; - - vec2 refractionEdgeFade = smoothstep(0.0, 0.15, refractionUV) * smoothstep(1.0, 0.85, refractionUV); - float refractionFadeFactor = refractionEdgeFade.x * refractionEdgeFade.y; - - if (!reflectionInBounds) { - reflectionFadeFactor *= 0.3; - } - if (!refractionInBounds) { - refractionFadeFactor *= 0.3; - } - - vec4 reflectionSample = texture(reflectionTexture, reflectionUV); - vec4 refractionSample = texture(refractionTexture, refractionUV); - vec4 sceneFallback = texture(sceneTexture, screenUV); - - bool validReflection = (length(reflectionSample.rgb) > 0.01); - bool validRefraction = (length(refractionSample.rgb) > 0.01); - - if (!validReflection) { - reflectionSample = sceneFallback; - } - if (!validRefraction) { - refractionSample = sceneFallback; - } - - float fresnel = pow(1.0 - clamp(dot(normal, viewDir), 0.0, 1.0), 3.0); - fresnel = mix(0.02, 1.0, fresnel); - fresnel *= reflectionStrength; - - vec3 combined = mix(refractionSample.rgb, reflectionSample.rgb, fresnel); - - float waterTint = clamp(depthFade * 0.3, 0.0, 0.5); - combined = mix(combined, waterColor.rgb, waterTint); - - float foamAmount = 0.0; - if (hasMovementTexture == 1) { - float foamFactor = smoothstep(0.7, 1.0, length(flowOffset) * windStrength); - foamAmount = foamFactor * 0.2; - combined = mix(combined, vec3(1.0), foamAmount); - } - - vec3 lightDir = normalize(-lightDirection); - - float diffuse = max(dot(normal, lightDir), 0.0); - diffuse = diffuse * 0.3; - - vec3 halfDir = normalize(lightDir + viewDir); - float specAngle = max(dot(normal, halfDir), 0.0); - float specular = pow(specAngle, 128.0); - - specular *= (fresnel * 0.5 + 0.5); - - float waveVariation = sin(TexCoord.x * 50.0 + time * 2.0) * 0.5 + 0.5; - waveVariation *= cos(TexCoord.y * 50.0 - time * 1.5) * 0.5 + 0.5; - specular *= (0.7 + waveVariation * 0.3); - - vec3 lighting = lightColor * (diffuse + specular * 2.0); - combined += lighting; - - vec3 specularHighlight = lightColor * specular * 2.5; - - specularHighlight += vec3(foamAmount * 2.0); - - float alpha = mix(0.7, 0.95, fresnel); - - FragColor = vec4(combined, alpha); - - float luminance = max(max(combined.r, combined.g), combined.b); - vec3 bloomColor = vec3(0.0); - - if (luminance > 1.0) { - bloomColor = combined - 1.0; - } - - bloomColor += specularHighlight; - - BrightColor = vec4(bloomColor, alpha); -} \ No newline at end of file diff --git a/shaders/opengl/terrain/fluid.vert b/shaders/opengl/terrain/fluid.vert deleted file mode 100644 index 2ef36819..00000000 --- a/shaders/opengl/terrain/fluid.vert +++ /dev/null @@ -1,25 +0,0 @@ -#version 410 core -layout(location = 0) in vec3 aPos; -layout(location = 1) in vec2 aTexCoord; -layout(location = 2) in vec3 aNormal; -layout(location = 3) in vec3 aTangent; -layout(location = 4) in vec3 aBitangent; - -uniform mat4 model; -uniform mat4 view; -uniform mat4 projection; - -out vec2 TexCoord; -out vec3 WorldPos; -out vec3 WorldNormal; -out vec3 WorldTangent; -out vec3 WorldBitangent; - -void main() { - gl_Position = projection * view * model * vec4(aPos, 1.0); - TexCoord = aTexCoord; - WorldPos = vec3(model * vec4(aPos, 1.0)); - WorldNormal = normalize(mat3(model) * aNormal); - WorldTangent = normalize(mat3(model) * aTangent); - WorldBitangent = normalize(mat3(model) * aBitangent); -} diff --git a/shaders/opengl/terrain/terrain.frag b/shaders/opengl/terrain/terrain.frag deleted file mode 100644 index e4ea862b..00000000 --- a/shaders/opengl/terrain/terrain.frag +++ /dev/null @@ -1,207 +0,0 @@ -#version 410 core - -in vec3 FragPos; -in float Height; -in vec2 TexCoord; -in vec4 FragPosLightSpace; - -uniform sampler2D heightMap; -uniform sampler2D moistureMap; -uniform sampler2D temperatureMap; -uniform sampler2D shadowMap; - -uniform sampler2D texture0; -uniform sampler2D texture1; -uniform sampler2D texture2; -uniform sampler2D texture3; -uniform sampler2D texture4; -uniform sampler2D texture5; -uniform sampler2D texture6; -uniform sampler2D texture7; -uniform sampler2D texture8; -uniform sampler2D texture9; -uniform sampler2D texture10; -uniform sampler2D texture11; - -uniform float maxPeak; -uniform float seaLevel; -uniform bool isFromMap; - -uniform vec4 directionalColor; -uniform float directionalIntensity; - -struct Biome { - int id; - vec4 tintColor; - int useTexture; - int textureId; - float minHeight; - float maxHeight; - float minMoisture; - float maxMoisture; - float minTemperature; - float maxTemperature; -}; - -uniform Biome biomes[12]; -uniform int biomesCount; - -layout (location = 0) out vec4 FragColor; -layout (location = 1) out vec4 BrightColor; - -uniform bool hasLight = false; -uniform bool useShadowMap = false; -uniform vec3 lightDir = normalize(vec3(0.4, 1.0, 0.3)); -uniform vec3 viewDir = normalize(vec3(0.0, 1.0, 1.0)); -uniform float ambientStrength = 0.3; -const float diffuseStrength = 0.8; -const float specularStrength = 0.2; -uniform float shadowBias = 0.005; - -vec4 sampleBiomeTexture(int id, vec2 uv) { - if (id == 0) return texture(texture0, uv); - if (id == 1) return texture(texture1, uv); - if (id == 2) return texture(texture2, uv); - if (id == 3) return texture(texture3, uv); - if (id == 4) return texture(texture4, uv); - if (id == 5) return texture(texture5, uv); - if (id == 6) return texture(texture6, uv); - if (id == 7) return texture(texture7, uv); - if (id == 8) return texture(texture8, uv); - if (id == 9) return texture(texture9, uv); - if (id == 10) return texture(texture10, uv); - if (id == 11) return texture(texture11, uv); - return vec4(1,0,1,1); -} - -vec4 triplanarBlend(int idx, vec3 normal, vec3 worldPos, float scale) { - vec3 blend = abs(normal); - blend = (blend - 0.2) * 7.0; - blend = clamp(blend, 0.0, 1.0); - blend /= (blend.x + blend.y + blend.z); - - vec4 xProj = sampleBiomeTexture(idx, worldPos.yz * scale); - vec4 yProj = sampleBiomeTexture(idx, worldPos.xz * scale); - vec4 zProj = sampleBiomeTexture(idx, worldPos.xy * scale); - - return xProj * blend.x + yProj * blend.y + zProj * blend.z; -} - -vec3 calculateNormal(sampler2D heightMap, vec2 texCoord, float heightScale) -{ - float h = texture(heightMap, texCoord).r * heightScale; - - float dx = dFdx(h); - float dy = dFdy(h); - - vec3 n = normalize(vec3(-dx, 1.0, -dy)); - return n; -} - -float smoothStepRange(float value, float minV, float maxV) { - return smoothstep(minV, maxV, value); -} - -float calculateShadow(vec4 fragPosLightSpace, vec3 normal) { - vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; - projCoords = projCoords * 0.5 + 0.5; - - if(projCoords.z > 1.0 || projCoords.x < 0.0 || projCoords.x > 1.0 || - projCoords.y < 0.0 || projCoords.y > 1.0) - return 0.0; - - float currentDepth = projCoords.z; - float bias = max(shadowBias * (1.0 - dot(normal, lightDir)), shadowBias * 0.1); - - float shadow = 0.0; - vec2 texelSize = 1.0 / textureSize(shadowMap, 0); - for(int x = -1; x <= 1; ++x) { - for(int y = -1; y <= 1; ++y) { - float pcfDepth = texture(shadowMap, projCoords.xy + vec2(x, y) * texelSize).r; - shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0; - } - } - shadow /= 9.0; - - return shadow; -} - -vec3 acesToneMapping(vec3 color) { - const float a = 2.51; - const float b = 0.03; - const float c = 2.43; - const float d = 0.59; - const float e = 0.14; - return clamp((color * (a * color + b)) / (color * (c * color + d) + e), 0.0, 1.0); -} - -void main() { - if (biomesCount <= 0) { - FragColor = vec4(vec3((Height + seaLevel) / maxPeak), 1.0); - return; - } - - float h = isFromMap ? texture(heightMap, TexCoord).r * 255.0 : (Height + seaLevel) / maxPeak * 255.0; - float m = texture(moistureMap, TexCoord).r * 255.0; - float t = texture(temperatureMap, TexCoord).r * 255.0; - - float texelSize = 1.0 / textureSize(heightMap, 0).x; - float heightScale = 64.0; - vec3 normal = calculateNormal(heightMap, TexCoord, heightScale); - - // === BIOME BLENDING === - vec4 baseColor = vec4(0.0); - float totalWeight = 0.0; - - for (int i = 0; i < biomesCount; i++) { - Biome b = biomes[i]; - - float hW = (b.minHeight < 0.0 && b.maxHeight < 0.0) ? 1.0 : smoothStepRange(h, b.minHeight, b.maxHeight); - float mW = (b.minMoisture < 0.0 && b.maxMoisture < 0.0) ? 1.0 : smoothStepRange(m, b.minMoisture, b.maxMoisture); - float tW = (b.minTemperature < 0.0 && b.maxTemperature < 0.0) ? 1.0 : smoothStepRange(t, b.minTemperature, b.maxTemperature); - - float weight = (1.0 - hW) * mW * tW; - if (weight > 0.001) { - vec4 texColor = (b.useTexture == 1) - ? triplanarBlend(i, normal, FragPos, 0.1) - : b.tintColor; - baseColor += texColor * weight; - totalWeight += weight; - } - } - - baseColor /= max(totalWeight, 0.001); - - float detail = texture(heightMap, TexCoord * 64.0).r * 0.1 + 0.9; - baseColor.rgb *= detail; - - vec3 finalColor; - - if (hasLight) { - vec3 L = normalize(-lightDir); - vec3 N = normalize(normal); - vec3 V = normalize(viewDir); - - vec3 ambient = ambientStrength * baseColor.rgb; - - float diff = max(dot(N, L), 0.0); - vec3 diffuse = diffuseStrength * diff * directionalColor.rgb * directionalIntensity * baseColor.rgb; - - vec3 H = normalize(L + V); - float spec = pow(max(dot(N, H), 0.0), 32.0); - vec3 specular = specularStrength * spec * directionalColor.rgb * directionalIntensity; - - float shadow = 0.0; - if (useShadowMap) { - shadow = calculateShadow(FragPosLightSpace, N); - } - - finalColor = ambient + (1.0 - shadow) * (diffuse + specular); - - } else { - finalColor = ambientStrength * baseColor.rgb; - } - - FragColor = vec4(acesToneMapping(finalColor), 1.0); - BrightColor = vec4(0.0); -} \ No newline at end of file diff --git a/shaders/opengl/terrain/terrain.vert b/shaders/opengl/terrain/terrain.vert deleted file mode 100644 index d82b889e..00000000 --- a/shaders/opengl/terrain/terrain.vert +++ /dev/null @@ -1,14 +0,0 @@ -#version 410 core -layout(location = 0) in vec3 aPos; -layout(location = 1) in vec2 aTexCoord; - -uniform mat4 model; -uniform mat4 view; -uniform mat4 projection; - -out vec2 TexCoord; - -void main() { - gl_Position = vec4(aPos, 1.0); - TexCoord = aTexCoord; -} \ No newline at end of file diff --git a/shaders/opengl/terrain/terrain_control.tesc b/shaders/opengl/terrain/terrain_control.tesc deleted file mode 100644 index dc206fb5..00000000 --- a/shaders/opengl/terrain/terrain_control.tesc +++ /dev/null @@ -1,63 +0,0 @@ -#version 410 core - -layout(vertices = 4) out; - -uniform mat4 model; -uniform mat4 view; - -in vec2 TexCoord[]; -out vec2 TextureCoord[]; - -in gl_PerVertex { - vec4 gl_Position; - float gl_PointSize; - float gl_ClipDistance[]; -} -gl_in[gl_MaxPatchVertices]; - -void main() { - gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; - TextureCoord[gl_InvocationID] = TexCoord[gl_InvocationID]; - - if (gl_InvocationID == 0) { - const int MIN_TESS_LEVEL = 4; - const int MAX_TESS_LEVEL = 64; - const float MIN_DISTANCE = 20; - const float MAX_DISTANCE = 800; - - vec4 eyeSpacePos00 = view * model * gl_in[0].gl_Position; - vec4 eyeSpacePos01 = view * model * gl_in[1].gl_Position; - vec4 eyeSpacePos10 = view * model * gl_in[2].gl_Position; - vec4 eyeSpacePos11 = view * model * gl_in[3].gl_Position; - - float dist00 = clamp((abs(eyeSpacePos00.z) - MIN_DISTANCE) / - (MAX_DISTANCE - MIN_DISTANCE), - 0.0, 1.0); - float dist01 = clamp((abs(eyeSpacePos01.z) - MIN_DISTANCE) / - (MAX_DISTANCE - MIN_DISTANCE), - 0.0, 1.0); - float dist10 = clamp((abs(eyeSpacePos10.z) - MIN_DISTANCE) / - (MAX_DISTANCE - MIN_DISTANCE), - 0.0, 1.0); - float dist11 = clamp((abs(eyeSpacePos11.z) - MIN_DISTANCE) / - (MAX_DISTANCE - MIN_DISTANCE), - 0.0, 1.0); - - float tessLevel0 = mix(float(MAX_TESS_LEVEL), float(MIN_TESS_LEVEL), - min(dist10, dist00)); - float tessLevel1 = mix(float(MAX_TESS_LEVEL), float(MIN_TESS_LEVEL), - min(dist00, dist01)); - float tessLevel2 = mix(float(MAX_TESS_LEVEL), float(MIN_TESS_LEVEL), - min(dist01, dist11)); - float tessLevel3 = mix(float(MAX_TESS_LEVEL), float(MIN_TESS_LEVEL), - min(dist11, dist10)); - - gl_TessLevelOuter[0] = tessLevel0; - gl_TessLevelOuter[1] = tessLevel1; - gl_TessLevelOuter[2] = tessLevel2; - gl_TessLevelOuter[3] = tessLevel3; - - gl_TessLevelInner[0] = max(tessLevel1, tessLevel3); - gl_TessLevelInner[1] = max(tessLevel0, tessLevel2); - } -} \ No newline at end of file diff --git a/shaders/opengl/terrain/terrain_eval.tese b/shaders/opengl/terrain/terrain_eval.tese deleted file mode 100644 index 1e2e6552..00000000 --- a/shaders/opengl/terrain/terrain_eval.tese +++ /dev/null @@ -1,51 +0,0 @@ -#version 410 core -layout(quads, fractional_odd_spacing, ccw) in; - -uniform sampler2D heightMap; -uniform mat4 model; -uniform mat4 view; -uniform mat4 projection; -uniform mat4 lightViewProj = mat4(1.0); -uniform float maxPeak = 48.0; -uniform float seaLevel = 16.0; -uniform bool isFromMap = false; - -in vec2 TextureCoord[]; - -out float Height; -out vec2 TexCoord; -out vec3 FragPos; -out vec4 FragPosLightSpace; - -void main() { - float u = gl_TessCoord.x; - float v = gl_TessCoord.y; - - vec2 t00 = TextureCoord[0]; - vec2 t01 = TextureCoord[1]; - vec2 t10 = TextureCoord[2]; - vec2 t11 = TextureCoord[3]; - - vec2 t0 = (t01 - t00) * u + t00; - vec2 t1 = (t11 - t10) * u + t10; - vec2 texCoord = (t1 - t0) * v + t0; - - Height = texture(heightMap, texCoord).r * maxPeak - seaLevel; - - vec4 p00 = gl_in[0].gl_Position; - vec4 p01 = gl_in[1].gl_Position; - vec4 p10 = gl_in[2].gl_Position; - vec4 p11 = gl_in[3].gl_Position; - - vec4 p0 = (p01 - p00) * u + p00; - vec4 p1 = (p11 - p10) * u + p10; - vec4 position = (p1 - p0) * v + p0; - - position.y += Height; - - gl_Position = projection * view * model * position; - - TexCoord = texCoord; - FragPos = vec3(model * position); - FragPosLightSpace = lightViewProj * model * position; -} \ No newline at end of file diff --git a/shaders/opengl/ui/text.frag b/shaders/opengl/ui/text.frag deleted file mode 100644 index 97ea6374..00000000 --- a/shaders/opengl/ui/text.frag +++ /dev/null @@ -1,12 +0,0 @@ -#version 410 core - -in vec2 texCoords; -out vec4 color; - -uniform sampler2D text; -uniform vec3 textColor; - -void main() { - vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, texCoords).r); - color = vec4(textColor, 1.0) * sampled; -} \ No newline at end of file diff --git a/shaders/opengl/ui/text.vert b/shaders/opengl/ui/text.vert deleted file mode 100644 index 3eb59025..00000000 --- a/shaders/opengl/ui/text.vert +++ /dev/null @@ -1,10 +0,0 @@ -#version 410 core -layout(location = 0) in vec4 vertex; // -out vec2 texCoords; - -uniform mat4 projection; - -void main() { - gl_Position = projection * vec4(vertex.xy, 0.0, 1.0); - texCoords = vertex.zw; -} \ No newline at end of file diff --git a/shaders/opengl/volumetric/volumetric.frag b/shaders/opengl/volumetric/volumetric.frag deleted file mode 100644 index 6ab81e3b..00000000 --- a/shaders/opengl/volumetric/volumetric.frag +++ /dev/null @@ -1,56 +0,0 @@ -#version 410 core -in vec2 TexCoords; -out vec4 FragColor; - -uniform sampler2D sceneTexture; -uniform vec2 sunPos; - -struct DirectionalLight { - vec3 color; -}; - -uniform DirectionalLight directionalLight; -uniform float density; -uniform float weight; -uniform float decay; -uniform float exposure; - -vec3 computeVolumetricLighting(vec2 uv) { - vec3 color = vec3(0.0); - - vec2 deltaTexCoord = (sunPos - uv) * density; - vec2 coord = uv; - float illuminationDecay = 1.0; - - const int NUM_SAMPLES = 100; - - for (int i = 0; i < NUM_SAMPLES; i++) { - coord += deltaTexCoord; - - if (coord.x < 0.0 || coord.x > 1.0 || coord.y < 0.0 || coord.y > 1.0) { - break; - } - - vec3 sampled = texture(sceneTexture, coord).rgb; - float brightness = dot(sampled, vec3(0.299, 0.587, 0.114)); - - vec3 atmosphere = directionalLight.color * 0.02; - - if (brightness > 0.5) { - atmosphere += sampled * 0.5; - } - - atmosphere *= illuminationDecay * weight; - color += atmosphere; - - illuminationDecay *= decay; - } - - return color * 5.0; -} - -void main() { - vec3 rays = computeVolumetricLighting(TexCoords); - - FragColor = vec4(rays, 1.0); -} diff --git a/shaders/opengl/volumetric/volumetric.vert b/shaders/opengl/volumetric/volumetric.vert deleted file mode 100644 index 1dc5069d..00000000 --- a/shaders/opengl/volumetric/volumetric.vert +++ /dev/null @@ -1,11 +0,0 @@ -#version 410 core - -layout(location = 0) in vec3 aPos; -layout(location = 2) in vec2 aTexCoords; - -out vec2 TexCoords; - -void main() { - gl_Position = vec4(aPos, 1.0); - TexCoords = aTexCoords; -} diff --git a/shaders/metal/gi/ddgi.metal b/shaders/photon/metal/ddgi.metal similarity index 100% rename from shaders/metal/gi/ddgi.metal rename to shaders/photon/metal/ddgi.metal diff --git a/shaders/metal/gi/ddgi_write.metal b/shaders/photon/metal/ddgi_write.metal similarity index 100% rename from shaders/metal/gi/ddgi_write.metal rename to shaders/photon/metal/ddgi_write.metal diff --git a/shaders/photon/metal/manifest.json b/shaders/photon/metal/manifest.json new file mode 100644 index 00000000..856af638 --- /dev/null +++ b/shaders/photon/metal/manifest.json @@ -0,0 +1,16 @@ +{ + "native": [ + { + "source": "photon/metal/path.metal", + "symbol": "PATH" + }, + { + "source": "photon/metal/ddgi.metal", + "symbol": "DDGI" + }, + { + "source": "photon/metal/ddgi_write.metal", + "symbol": "DDGI_WRITE" + } + ] +} diff --git a/shaders/photon/metal/path.metal b/shaders/photon/metal/path.metal new file mode 100644 index 00000000..d0ce4d0b --- /dev/null +++ b/shaders/photon/metal/path.metal @@ -0,0 +1,215 @@ +#include +#include +using namespace metal; +using namespace raytracing; + +#include "path/types.metal" +#include "path/sampling.metal" +#include "path/environment.metal" +#include "path/geometry.metal" +#include "path/materials.metal" +#include "path/visibility.metal" +#include "path/brdf.metal" +#include "path/lighting.metal" +#include "path/integrator.metal" +kernel void main0(texture2d outTex [[texture(0)]], + texture2d historyTex [[texture(1)]], + texture2d brightTex [[texture(2)]], + texture2d albedoRoughnessTex [[texture(3)]], + texture2d normalDepthTex [[texture(4)]], + texture2d motionObjectTex [[texture(5)]], + texture2d historyMomentsTex [[texture(6)]], + texture2d historyGuideTex [[texture(7)]], + texture2d historyOutTex [[texture(8)]], + texture2d historyGuideOutTex [[texture(9)]], + texture2d historyMomentsOutTex [[texture(10)]], + primitive_acceleration_structure sceneAS [[buffer(0)]], + constant CameraUniforms &cam [[buffer(1)]], + constant Material *materials [[buffer(2)]], + constant uint *primitiveObjects [[buffer(3)]], + constant VertexData *vertices [[buffer(4)]], + constant uint *indices [[buffer(5)]], + constant InstanceData *instanceData [[buffer(6)]], + constant DirectionalLightData &dirLight [[buffer(7)]], + constant SceneData &sceneData [[buffer(8)]], + constant PointLight *pointLights [[buffer(9)]], + constant SpotLight *spotLights [[buffer(10)]], + constant AreaLight *areaLights [[buffer(11)]], + constant EmissiveTriangle *emissiveTriangles [[buffer(14)]], + PT_MATERIAL_TEXTURE_BINDINGS, + constant uint *blasPrimitiveOffsets [[buffer(13)]], + texturecube skybox [[texture(60)]], + uint2 gid [[thread_position_in_grid]]) { + uint w = outTex.get_width(); + uint h = outTex.get_height(); + uint pixelStride = max(sceneData.pixelStride, 1u); + gid *= pixelStride; + if (gid.x >= w || gid.y >= h) + return; + + float2 uv = (float2(gid) + 0.5) / float2(w, h); + float3 ro = cam.camPos; + + intersector isect; + isect.assume_geometry_type(geometry_type::triangle); + isect.set_triangle_cull_mode(triangle_cull_mode::none); + + float3 color = float3(0.0); + float3 primaryAlbedo = float3(0.0); + float3 primaryNormal = float3(0.0); + float3 primaryPosition = float3(0.0); + float primaryDepth = 0.0; + float primaryRoughness = 1.0; + float primaryHitDistance = 0.0; + uint primaryObjectId = 0xFFFFFFFFu; + + uint spp = max(sceneData.raysPerPixel, 1u); + for (uint s = 0; s < spp; ++s) { + uint cameraRng = seedBase(gid, w, sceneData.frameIndex, + s + 0x9E3779B9u); + float2 pixelJitter = s == 0 + ? float2(0.0) + : float2(rand(cameraRng), rand(cameraRng)) - + 0.5; + float2 sampleUv = (float2(gid) + 0.5 + pixelJitter) / float2(w, h); + float2 sampleNdc = sampleUv * 2.0 - 1.0; + sampleNdc.y = -sampleNdc.y; + float4 sampleClip = float4(sampleNdc, 1.0, 1.0); + float4 sampleWorldH = cam.invViewProj * sampleClip; + float3 sampleWorldP = sampleWorldH.xyz / sampleWorldH.w; + + ray primaryRay; + primaryRay.origin = ro; + primaryRay.direction = normalize(sampleWorldP - ro); + primaryRay.min_distance = 0.001; + primaryRay.max_distance = 1.0e30; + + float3 sampleAlbedo = float3(0.0); + float3 sampleNormal = float3(0.0); + float3 samplePosition = float3(0.0); + float sampleDepth = 0.0; + float sampleRoughness = 1.0; + float sampleHitDistance = 0.0; + uint sampleObjectId = 0xFFFFFFFFu; + + float3 sample = sampleRadiance( + gid, s, w, isect, sceneAS, primaryRay, materials, primitiveObjects, + blasPrimitiveOffsets, vertices, indices, instanceData, dirLight, + sceneData, pointLights, spotLights, areaLights, + emissiveTriangles, PT_MATERIAL_TEXTURE_ARGS, skybox, sampleAlbedo, + sampleNormal, samplePosition, sampleDepth, sampleRoughness, + sampleHitDistance, sampleObjectId); + if (!all(isfinite(sample))) { + sample = float3(0.0); + } + color += clampLuminance(max(sample, float3(0.0)), + max(sceneData.fireflyClamp, 1.0)); + if (s == 0) { + primaryAlbedo = sampleAlbedo; + primaryNormal = sampleNormal; + primaryPosition = samplePosition; + primaryDepth = sampleDepth; + primaryRoughness = sampleRoughness; + primaryHitDistance = sampleHitDistance; + primaryObjectId = sampleObjectId; + } + } + + color /= float(spp); + if (!all(isfinite(color))) { + color = float3(0.0); + } + + float objectIdValue = primaryObjectId == 0xFFFFFFFFu + ? -1.0 + : float(primaryObjectId); + float2 encodedNormal = encodeNormal(primaryNormal); + float4 currentGuide = + float4(encodedNormal, primaryDepth, objectIdValue); + float4 previousClip = cam.prevViewProj * float4(primaryPosition, 1.0); + float2 previousNdc = previousClip.xy / max(abs(previousClip.w), 0.0001); + float2 previousUv = float2(previousNdc.x * 0.5 + 0.5, + 0.5 - previousNdc.y * 0.5); + bool previousUvValid = previousClip.w > 0.0 && + all(previousUv >= float2(0.0)) && + all(previousUv <= float2(1.0)); + uint2 previousPixel = gid; + if (primaryObjectId != 0xFFFFFFFFu && previousUvValid) { + previousPixel = uint2(clamp(previousUv * float2(w, h), float2(0.0), + float2(w - 1, h - 1))); + } + float4 prevColor = historyTex.read(previousPixel); + float4 previousGuide = historyGuideTex.read(previousPixel); + float4 previousMoments = historyMomentsTex.read(previousPixel); + bool historyValid = sceneData.frameIndex > 0 && prevColor.w > 0.0 && + abs(previousGuide.z - primaryDepth) < + max(0.02, primaryDepth * 0.01) && + distance(previousGuide.xy, encodedNormal) < 0.04 && + abs(previousGuide.w - objectIdValue) < 0.5; + if (!historyValid) { + prevColor = float4(0.0); + previousMoments = float4(0.0); + } + float previousMean = historyValid ? previousMoments.x : 0.0; + float previousVariance = + historyValid + ? max(previousMoments.y - previousMean * previousMean, 0.0) + : 0.0; + float sampleLuminanceLimit = max(sceneData.fireflyClamp, 1.0); + if (historyValid && prevColor.w >= 4.0) { + float statisticalLimit = previousMean + + max(0.5, 6.0 * sqrt(previousVariance)); + sampleLuminanceLimit = + min(sampleLuminanceLimit, max(4.0, statisticalLimit)); + } + color = clampLuminance(color, sampleLuminanceLimit); + float historyLimit = max(float(sceneData.accumulationFrameLimit), 1.0); + float previousWeight = + historyValid ? min(prevColor.w, max(historyLimit - 1.0, 0.0)) : 0.0; + float newHistoryLength = min(previousWeight + 1.0, historyLimit); + float accumulationDenominator = max(previousWeight + 1.0, 1.0); + float3 accum = + (prevColor.xyz * previousWeight + color) / accumulationDenominator; + float moment = luminance(color); + float accumulatedMoment = + (previousMoments.x * previousWeight + moment) / + accumulationDenominator; + float accumulatedMomentSquared = + (previousMoments.y * previousWeight + moment * moment) / + accumulationDenominator; + float variance = max(accumulatedMomentSquared - + accumulatedMoment * accumulatedMoment, + 0.0); + + constexpr float bloomKnee = 0.35; + + float brightness = luminance(accum); + float soft = clamp(brightness - sceneData.bloomThreshold + bloomKnee, 0.0, + bloomKnee * 2.0); + soft = soft * soft / max(bloomKnee * 4.0, 0.00001); + float contribution = max(brightness - sceneData.bloomThreshold, soft) / + max(brightness, 0.00001); + float3 brightColor = accum * contribution; + float2 motion = previousUvValid ? uv - previousUv : float2(0.0); + + for (uint y = 0; y < pixelStride; ++y) { + for (uint x = 0; x < pixelStride; ++x) { + uint2 pixel = gid + uint2(x, y); + if (pixel.x >= w || pixel.y >= h) { + continue; + } + historyOutTex.write(float4(accum, newHistoryLength), pixel); + historyGuideOutTex.write(currentGuide, pixel); + albedoRoughnessTex.write(float4(primaryAlbedo, primaryRoughness), + pixel); + normalDepthTex.write(float4(primaryNormal, primaryDepth), pixel); + motionObjectTex.write(float4(motion, objectIdValue, 1.0), pixel); + historyMomentsOutTex.write( + float4(accumulatedMoment, accumulatedMomentSquared, variance, + primaryHitDistance), + pixel); + outTex.write(float4(accum, 1.0), pixel); + brightTex.write(float4(brightColor, 1.0), pixel); + } + } +} diff --git a/shaders/photon/metal/path/brdf.metal b/shaders/photon/metal/path/brdf.metal new file mode 100644 index 00000000..037123b3 --- /dev/null +++ b/shaders/photon/metal/path/brdf.metal @@ -0,0 +1,143 @@ +float D_GGX(float NdotH, float roughness) { + float a = max(roughness * roughness, 1e-4); + float a2 = a * a; + float d = (NdotH * NdotH) * (a2 - 1.0) + 1.0; + return a2 / max(M_PI_F * d * d, 1e-6); +} + +float3 F_Schlick(float cosTheta, float3 F0) { + float c = clamp(1.0 - cosTheta, 0.0, 1.0); + return F0 + (1.0 - F0) * pow5(c); +} + +float3 materialF0(float3 albedo, float metallic, float reflectivity, + float ior) { + float dielectricF0 = pow((max(ior, 1.0001) - 1.0) / + (max(ior, 1.0001) + 1.0), + 2.0); + float dielectricScale = mix(0.5, 1.5, clamp(reflectivity, 0.0, 1.0)); + return mix(float3(clamp(dielectricF0 * dielectricScale, 0.0, 0.16)), + albedo, clamp(metallic, 0.0, 1.0)); +} + +float G_Smith(float NdotV, float NdotL, float roughness) { + float r = roughness + 1.0; + float k = (r * r) / 8.0; + float gV = NdotV / (NdotV * (1.0 - k) + k); + float gL = NdotL / (NdotL * (1.0 - k) + k); + return gV * gL; +} + +float G1_SmithGGX(float NdotX, float roughness) { + float alpha = max(roughness * roughness, 1e-4); + float alphaSquared = alpha * alpha; + float cosineSquared = NdotX * NdotX; + return (2.0 * NdotX) / + max(NdotX + + sqrt(alphaSquared + (1.0 - alphaSquared) * cosineSquared), + 1e-6); +} + +float disneyDiffuseFactor(float NdotV, float NdotL, float LdotH, + float roughness) { + float fd90 = 0.5 + 2.0 * LdotH * LdotH * roughness; + float lightScatter = 1.0 + (fd90 - 1.0) * pow5(1.0 - NdotL); + float viewScatter = 1.0 + (fd90 - 1.0) * pow5(1.0 - NdotV); + return lightScatter * viewScatter; +} + +// GGX importance-sampled microfacet half-vector (in local TBN space, Z=up) +float3 sampleGGX(float2 u, float roughness) { + float a = roughness * roughness; + float phi = 2.0 * M_PI_F * u.x; + float cosTheta = sqrt((1.0 - u.y) / max(1.0 + (a * a - 1.0) * u.y, 1e-7)); + float sinTheta = sqrt(max(0.0, 1.0 - cosTheta * cosTheta)); + return float3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); +} + +float3 sampleGGXVNDF(float3 localView, float roughness, float2 u) { + float alpha = max(roughness * roughness, 1e-3); + float3 stretchedView = + normalizeOr(float3(alpha * localView.x, alpha * localView.y, + max(localView.z, 1e-5)), + float3(0.0, 0.0, 1.0)); + float lensq = stretchedView.x * stretchedView.x + + stretchedView.y * stretchedView.y; + float3 tangentX = lensq > 1e-7 + ? float3(-stretchedView.y, stretchedView.x, 0.0) * + rsqrt(lensq) + : float3(1.0, 0.0, 0.0); + float3 tangentY = cross(stretchedView, tangentX); + float radius = sqrt(u.x); + float phi = 2.0 * M_PI_F * u.y; + float diskX = radius * cos(phi); + float diskY = radius * sin(phi); + float blend = 0.5 * (1.0 + stretchedView.z); + diskY = mix(sqrt(max(0.0, 1.0 - diskX * diskX)), diskY, blend); + float diskZ = sqrt(max(0.0, 1.0 - diskX * diskX - diskY * diskY)); + float3 visibleNormal = diskX * tangentX + diskY * tangentY + + diskZ * stretchedView; + return normalizeOr(float3(alpha * visibleNormal.x, + alpha * visibleNormal.y, + max(visibleNormal.z, 0.0)), + float3(0.0, 0.0, 1.0)); +} + +// Full Cook-Torrance PBR for a single analytic light +float3 evalPBR(float3 albedo, float metallic, float roughness, + float reflectivity, float ior, float transmittance, float3 N, + float3 V, float3 L, float3 lightColor, float intensity) { + float3 H = normalize(V + L); + float NdotL = max(dot(N, L), 0.0); + float NdotV = max(dot(N, V), 1e-4); + float NdotH = max(dot(N, H), 0.0); + float VdotH = max(dot(V, H), 0.0); + + float clampedRoughness = clamp(roughness, 0.045, 1.0); + float3 F0 = materialF0(albedo, metallic, reflectivity, ior); + float3 F = F_Schlick(VdotH, F0); + float D = D_GGX(NdotH, clampedRoughness); + float G = G_Smith(NdotV, NdotL, clampedRoughness); + + float3 specular = (D * G * F) / max(4.0 * NdotV * NdotL, 1e-4); + float3 kD = (1.0 - F) * (1.0 - clamp(metallic, 0.0, 1.0)) * + (1.0 - clamp(transmittance, 0.0, 1.0)); + float diffuseFactor = disneyDiffuseFactor(NdotV, NdotL, max(dot(L, H), 0.0), + clampedRoughness); + float3 diffuse = (kD * albedo * diffuseFactor) / M_PI_F; + + return (diffuse + specular) * lightColor * intensity * NdotL; +} + +float3 evalSubsurface(float3 albedo, float3 N, float3 V, float3 L, + float3 lightColor, float intensity, float roughness, + float sssStrength, float sssThickness) { + float NdotL = dot(N, L); + float NdotV = max(dot(N, V), 0.0); + float backLit = clamp(-NdotL, 0.0, 1.0); + float wrapAmount = mix(0.2, 0.7, clamp(roughness, 0.0, 1.0)); + float wrapped = clamp((NdotL + wrapAmount) / (1.0 + wrapAmount), 0.0, 1.0); + float viewScatter = pow(clamp(1.0 - max(dot(V, L), 0.0), 0.0, 1.0), 2.0); + float transmission = backLit * (0.35 + 0.65 * viewScatter); + float diffuseBleed = wrapped * (0.5 + 0.5 * (1.0 - NdotV)); + float profile = mix(diffuseBleed, transmission, 0.65); + float thicknessFalloff = exp(-max(sssThickness, 0.01) * (1.0 - backLit)); + return (albedo * lightColor * intensity * sssStrength * profile * + thicknessFalloff) / + M_PI_F; +} + +float3 evalTransmission(float3 albedo, float3 N, float3 V, float3 L, + float3 lightColor, float intensity, float roughness, + float ior) { + float backLighting = max(dot(N, -L), 0.0); + float forwardAlignment = max(dot(-V, L), 0.0); + float3 F0 = float3(pow((ior - 1.0) / (ior + 1.0), 2.0)); + float3 F = F_Schlick(max(dot(N, V), 0.0), F0); + float3 transmitTint = mix(float3(1.0), albedo, 0.1); + float lobeExponent = mix(96.0, 2.0, sqrt(clamp(roughness, 0.0, 1.0))); + float transmissionLobe = pow(forwardAlignment, lobeExponent); + return (1.0 - F) * transmitTint * lightColor * intensity * backLighting * + transmissionLobe; +} + diff --git a/shaders/photon/metal/path/environment.metal b/shaders/photon/metal/path/environment.metal new file mode 100644 index 00000000..5d603aa9 --- /dev/null +++ b/shaders/photon/metal/path/environment.metal @@ -0,0 +1,54 @@ +constexpr sampler skyboxSampler(coord::normalized, address::clamp_to_edge, + filter::linear, mip_filter::linear); + +float3 skyColor(float3 dir, float intensity, texturecube skybox, + constant SceneData &sceneData) { + float3 sampleDir = dir; + float len2 = dot(sampleDir, sampleDir); + if (len2 > 1e-10) { + sampleDir *= rsqrt(len2); + } else { + sampleDir = float3(0.0, 1.0, 0.0); + } + float3 sky = skybox.sample(skyboxSampler, sampleDir).xyz; + if (sceneData.atmosphereEnabled != 0) { + float horizon = pow(clamp(1.0 - abs(sampleDir.y), 0.0, 1.0), 4.0); + float daylight = smoothstep(-0.2, 0.15, + sceneData.atmosphereSunDirection.y); + float3 zenith = float3(0.08, 0.28, 0.65); + float3 horizonColor = float3(0.58, 0.72, 0.92); + float3 proceduralSky = mix(zenith, horizonColor, horizon) * + max(daylight, 0.08); + sky = max(sky, proceduralSky); + } + if (sceneData.atmosphereEnabled != 0 && + sceneData.atmosphereSunDirection.y > -0.15) { + float3 sunDirection = sceneData.atmosphereSunDirection; + float sunDirectionLength = dot(sunDirection, sunDirection); + sunDirection = sunDirectionLength > 1e-10 + ? sunDirection * rsqrt(sunDirectionLength) + : float3(0.0, 1.0, 0.0); + float sunDot = dot(sampleDir, sunDirection); + float sizeAdjust = + 1.0 - (sceneData.atmosphereSunSize - 1.0) * 0.001; + float sunSize = 0.9995 * sizeAdjust; + float sunGlowSize = + 0.998 * (1.0 - (sceneData.atmosphereSunSize - 1.0) * 0.003); + float sunHaloSize = + 0.99 * (1.0 - (sceneData.atmosphereSunSize - 1.0) * 0.015); + float sunDisk = smoothstep(sunSize - 0.0002, sunSize, sunDot); + float sunGlow = + smoothstep(sunGlowSize, sunSize, sunDot) * (1.0 - sunDisk); + float sunHalo = smoothstep(sunHaloSize, sunSize, sunDot) * + (1.0 - smoothstep(sunSize, sunGlowSize, sunDot)); + float horizonFade = smoothstep( + -0.15, 0.05, sceneData.atmosphereSunDirection.y); + float sunIntensity = max(sceneData.atmosphereSunIntensity, 0.05); + sky += sceneData.atmosphereSunColor * + (sunDisk * 5.0 + sunGlow * 0.5 + sunHalo) * horizonFade * + sunIntensity; + } + float scale = intensity > 0.0 ? intensity : 1.0; + return sky * scale; +} + diff --git a/shaders/photon/metal/path/geometry.metal b/shaders/photon/metal/path/geometry.metal new file mode 100644 index 00000000..75fb4d17 --- /dev/null +++ b/shaders/photon/metal/path/geometry.metal @@ -0,0 +1,48 @@ +float3 cosineSampleHemisphere(float2 u) { + float r = sqrt(u.x); + float theta = 2.0 * M_PI_F * u.y; + + float x = r * cos(theta); + float y = r * sin(theta); + float z = sqrt(max(0.0, 1.0 - u.x)); + + return float3(x, y, z); +} + +float3x3 buildOrthonormalBasis(float3 N) { + float3 T = normalize(abs(N.x) > 0.1 ? cross(float3(0, 1, 0), N) + : cross(float3(1, 0, 0), N)); + float3 B = cross(N, T); + return float3x3(T, B, N); +} + +float3 normalizeOr(float3 v, float3 fallback) { + float len2 = dot(v, v); + if (len2 > 1e-10) { + return v * rsqrt(len2); + } + return fallback; +} + +float rayOffsetDistance(float3 position) { + float positionScale = + max(abs(position.x), max(abs(position.y), abs(position.z))); + return max(0.0002, positionScale * 0.000002); +} + +float3 offsetRayOrigin(float3 position, float3 geometricNormal, + float3 direction) { + float side = dot(direction, geometricNormal) >= 0.0 ? 1.0 : -1.0; + return position + geometricNormal * (rayOffsetDistance(position) * side); +} + +float2 encodeNormal(float3 normal) { + normal /= max(abs(normal.x) + abs(normal.y) + abs(normal.z), 1e-6); + float2 encoded = normal.xy; + if (normal.z < 0.0) { + float2 signValue = select(float2(-1.0), float2(1.0), encoded >= 0.0); + encoded = (1.0 - abs(encoded.yx)) * signValue; + } + return encoded; +} + diff --git a/shaders/photon/metal/path/integrator.metal b/shaders/photon/metal/path/integrator.metal new file mode 100644 index 00000000..8cf34a9b --- /dev/null +++ b/shaders/photon/metal/path/integrator.metal @@ -0,0 +1,381 @@ +float3 sampleRadiance(uint2 gid, uint sampleIndex, uint w, + intersector isect, + primitive_acceleration_structure sceneAS, ray primaryRay, + constant Material *materials, + constant uint *primitiveObjects, + constant uint *blasPrimitiveOffsets, + constant VertexData *vertices, constant uint *indices, + constant InstanceData *instanceData, + constant DirectionalLightData &dirLight, + constant SceneData &sceneData, + constant PointLight *pointLights, + constant SpotLight *spotLights, + constant AreaLight *areaLights, + constant EmissiveTriangle *emissiveTriangles, + PT_MATERIAL_TEXTURE_PARAMS, texturecube skybox, + thread float3 &primaryAlbedo, + thread float3 &primaryNormal, + thread float3 &primaryPosition, + thread float &primaryDepth, + thread float &primaryRoughness, + thread float &primaryHitDistance, + thread uint &primaryObjectId) { + uint rng = seedBase(gid, w, sceneData.frameIndex, sampleIndex); + uint bounceLimit = min(sceneData.maxBounces, 16u); + ray surfaceRay = primaryRay; + float3 radiance = float3(0.0); + float3 throughput = float3(1.0); + float previousBsdfPdf = 0.0; + float previousEnvironmentPdf = 0.0; + bool previousEventWasDelta = true; + + for (uint depth = 0; depth <= bounceLimit; ++depth) { + auto hit = isect.intersect(surfaceRay, sceneAS); + Material mat{}; + InstanceData inst{}; + uint surfaceObjectIndex = 0xFFFFFFFFu; + float2 texUV = float2(0.0); + float3 localN = float3(0.0, 1.0, 0.0); + float3 localT = float3(1.0, 0.0, 0.0); + float3 localB = float3(0.0, 0.0, 1.0); + float3 geometricNormal = float3(0.0, 1.0, 0.0); + bool foundSurface = false; + + for (uint alphaStep = 0; alphaStep < 16; ++alphaStep) { + if (hit.type == intersection_type::none) { + break; + } + + uint primitiveIndex = + blasPrimitiveOffsets[hit.geometry_id] + hit.primitive_id; + surfaceObjectIndex = primitiveObjects[primitiveIndex]; + mat = materials[surfaceObjectIndex]; + inst = instanceData[surfaceObjectIndex]; + + uint i0 = indices[primitiveIndex * 3 + 0]; + uint i1 = indices[primitiveIndex * 3 + 1]; + uint i2 = indices[primitiveIndex * 3 + 2]; + float2 bary = hit.triangle_barycentric_coord; + float b0 = 1.0 - bary.x - bary.y; + float b1 = bary.x; + float b2 = bary.y; + + texUV = float2(vertices[i0].uv) * b0 + + float2(vertices[i1].uv) * b1 + + float2(vertices[i2].uv) * b2; + texUV = texUV * float2(mat.textureScale) + + float2(mat.textureOffset); + localN = normalizeOr(float3(vertices[i0].normal) * b0 + + float3(vertices[i1].normal) * b1 + + float3(vertices[i2].normal) * b2, + float3(0.0, 1.0, 0.0)); + localT = normalizeOr(float3(vertices[i0].tangent) * b0 + + float3(vertices[i1].tangent) * b1 + + float3(vertices[i2].tangent) * b2, + float3(1.0, 0.0, 0.0)); + localB = normalizeOr(float3(vertices[i0].bitangent) * b0 + + float3(vertices[i1].bitangent) * b1 + + float3(vertices[i2].bitangent) * b2, + float3(0.0, 0.0, 1.0)); + float3 p0 = float3(vertices[i0].position); + float3 p1 = float3(vertices[i1].position); + float3 p2 = float3(vertices[i2].position); + float3x3 normalMatrix = float3x3( + inst.normalCol0.xyz, inst.normalCol1.xyz, inst.normalCol2.xyz); + geometricNormal = normalizeOr( + cross(p1 - p0, p2 - p0), + normalizeOr(normalMatrix * localN, float3(0.0, 1.0, 0.0))); + + float alpha = resolveMaterialOpacity( + mat, texUV, sceneData.materialTextureCount, + PT_MATERIAL_TEXTURE_ARGS); + if (alpha >= 0.999 || rand(rng) < alpha) { + foundSurface = true; + break; + } + + float3 rejectedPosition = + surfaceRay.origin + surfaceRay.direction * hit.distance; + surfaceRay.origin = + rejectedPosition + surfaceRay.direction * + rayOffsetDistance(rejectedPosition); + surfaceRay.min_distance = 0.0; + hit = isect.intersect(surfaceRay, sceneAS); + } + + if (!foundSurface) { + float misWeight = previousEventWasDelta + ? 1.0 + : powerHeuristic(previousBsdfPdf, + previousEnvironmentPdf); + radiance += throughput * misWeight * + skyColor(surfaceRay.direction, 0.0, skybox, sceneData); + break; + } + + float3 shadingNormal = resolveShadingNormal( + mat, texUV, localN, localT, localB, inst, + sceneData.materialTextureCount, PT_MATERIAL_TEXTURE_ARGS); + float3 P = surfaceRay.origin + surfaceRay.direction * hit.distance; + float3 V = normalize(-surfaceRay.direction); + bool frontFace = dot(geometricNormal, V) >= 0.0; + float3 Ng = frontFace ? geometricNormal : -geometricNormal; + float3 N = dot(shadingNormal, Ng) >= 0.0 ? shadingNormal : -shadingNormal; + float shadingNormalCosine = dot(N, Ng); + if (shadingNormalCosine < 0.1) { + N = normalizeOr(N + Ng * (0.1 - shadingNormalCosine), Ng); + } + + float3 albedo; + float metallic; + float roughness; + float ao; + float3 emissive; + float ior; + float transmittance; + resolveMaterialParameters(mat, texUV, sceneData.materialTextureCount, + PT_MATERIAL_TEXTURE_ARGS, albedo, metallic, + roughness, ao, emissive, ior, transmittance); + + if (depth == 0) { + primaryAlbedo = albedo; + primaryNormal = N; + primaryPosition = P; + primaryDepth = length(P - primaryRay.origin); + primaryRoughness = roughness; + primaryHitDistance = hit.distance; + primaryObjectId = surfaceObjectIndex; + } + + float reflectivity = clamp(mat.reflectivity, 0.0, 1.0); + float sssStrength = 0.0; + float sssThickness = mix(0.25, 1.75, ao); + float3 direct = evalDirectLightingPBR( + isect, sceneAS, P, N, Ng, V, albedo, metallic, roughness, + reflectivity, ior, transmittance, sssStrength, sssThickness, rng, + dirLight, sceneData, pointLights, spotLights, areaLights, + emissiveTriangles, materials, primitiveObjects, + blasPrimitiveOffsets, vertices, indices, instanceData, + PT_MATERIAL_TEXTURE_ARGS); + radiance += throughput * direct; + if (depth == 0 || previousEventWasDelta || + sceneData.numEmissiveTriangles == 0) { + radiance += throughput * emissive; + } + + if (depth == 0 && sceneData.ambientIntensity > 0.0) { + float aoVisibility = mix(0.2, 1.0, ao); + float dielectricF0 = pow((ior - 1.0) / (ior + 1.0), 2.0); + float3 ambientF0 = mix(float3(dielectricF0), albedo, metallic); + float3 ambientF = F_Schlick(max(dot(N, V), 0.0), ambientF0); + float3 ambientDiffuse = (1.0 - ambientF) * (1.0 - metallic) * + albedo * (1.0 - transmittance); + float3 ambientSpecular = ambientF * mix(1.0, 0.35, roughness) * + (1.0 - transmittance); + float3 ambient = (ambientDiffuse + ambientSpecular) * + sceneData.ambientColor * + sceneData.ambientIntensity * aoVisibility; + radiance += throughput * ambient; + } + + float dielectricF0 = pow((ior - 1.0) / (ior + 1.0), 2.0); + float3 F0 = materialF0(albedo, metallic, mat.reflectivity, ior); + float NdotV = max(dot(N, V), 1e-4); + float3 viewFresnel = F_Schlick(NdotV, F0); + float fresnelProbability = clamp(luminance(viewFresnel), 0.001, 0.999); + float specProb = fresnelProbability; + float transmitProb = transmittance * (1.0 - metallic) * + (1.0 - fresnelProbability); + float diffuseProb = (1.0 - metallic) * (1.0 - transmittance) * + (1.0 - fresnelProbability); + float eta = frontFace ? 1.0 / ior : ior; + float3 idealRefractedDirection = refract(-V, N, eta); + bool totalInternalReflection = + dot(idealRefractedDirection, idealRefractedDirection) < 1e-8; + if (totalInternalReflection) { + specProb += transmitProb; + transmitProb = 0.0; + } + float probabilitySum = + max(specProb + transmitProb + diffuseProb, 1e-4); + specProb /= probabilitySum; + transmitProb /= probabilitySum; + diffuseProb /= probabilitySum; + + float3x3 basis = buildOrthonormalBasis(N); + if (sceneData.environmentEnabled != 0 && + diffuseProb + specProb > 1e-4) { + float3 localEnvironmentDirection = + cosineSampleHemisphere(float2(rand(rng), rand(rng))); + float3 environmentDirection = + normalizeOr(basis * localEnvironmentDirection, N); + float NdotEnvironment = dot(N, environmentDirection); + if (NdotEnvironment > 0.0 && + dot(Ng, environmentDirection) > 0.0) { + float3 visibility = traceShadowVisibility( + isect, sceneAS, P, Ng, environmentDirection, 1e30, rng, + materials, primitiveObjects, blasPrimitiveOffsets, + vertices, indices, instanceData, sceneData, + PT_MATERIAL_TEXTURE_ARGS); + if (luminance(visibility) <= 0.001) { + visibility = float3(0.0); + } + float3 H = normalizeOr(V + environmentDirection, N); + float NdotH = max(dot(N, H), 1e-5); + float VdotH = max(dot(V, H), 1e-5); + float3 F = F_Schlick(VdotH, F0); + float3 kD = (1.0 - F) * (1.0 - metallic) * + (1.0 - transmittance); + float diffuseFactor = disneyDiffuseFactor( + NdotV, NdotEnvironment, + max(dot(environmentDirection, H), 0.0), roughness); + float3 reflectionBsdf = + kD * albedo * diffuseFactor / M_PI_F; + float environmentPdf = NdotEnvironment / M_PI_F; + float bsdfPdf = diffuseProb * environmentPdf; + if (roughness > 0.025 && specProb > 1e-4) { + float D = D_GGX(NdotH, roughness); + float G1V = G1_SmithGGX(NdotV, roughness); + float G1L = + G1_SmithGGX(NdotEnvironment, roughness); + reflectionBsdf += + D * G1V * G1L * F / + max(4.0 * NdotV * NdotEnvironment, 1e-6); + bsdfPdf += specProb * D * G1V / + max(4.0 * NdotV, 1e-6); + } + float competingBsdfPdf = depth < bounceLimit ? bsdfPdf : 0.0; + float misWeight = + powerHeuristic(environmentPdf, competingBsdfPdf); + float3 environmentRadiance = skyColor( + environmentDirection, 0.0, skybox, sceneData); + radiance += throughput * reflectionBsdf * + environmentRadiance * visibility * NdotEnvironment * + misWeight / max(environmentPdf, 1e-6); + } + } + + if (depth == bounceLimit) { + break; + } + + float choice = rand(rng); + float3 bounceWeight = float3(0.0); + float3 nextDirection = N; + float sampledBsdfPdf = 0.0; + float sampledEnvironmentPdf = 0.0; + bool sampledEventWasDelta = true; + + if (choice < specProb && specProb > 1e-4) { + if (roughness <= 0.025 || totalInternalReflection) { + nextDirection = reflect(-V, N); + float3 F = totalInternalReflection + ? float3(1.0) + : F_Schlick(NdotV, F0); + bounceWeight = F / max(specProb, 1e-4); + } else { + float3 localView = + float3(dot(V, basis[0]), dot(V, basis[1]), dot(V, N)); + float3 localH = sampleGGXVNDF( + localView, roughness, float2(rand(rng), rand(rng))); + float3 H = normalizeOr(basis * localH, N); + float VdotH = max(dot(V, H), 1e-5); + nextDirection = reflect(-V, H); + float NdotL = dot(N, nextDirection); + if (NdotL > 0.0 && dot(nextDirection, Ng) > 0.0) { + float NdotH = max(dot(N, H), 1e-5); + float D = D_GGX(NdotH, roughness); + float G1V = G1_SmithGGX(NdotV, roughness); + float G1L = G1_SmithGGX(NdotL, roughness); + float3 F = F_Schlick(VdotH, F0); + float3 specularBsdf = + D * G1V * G1L * F / + max(4.0 * NdotV * NdotL, 1e-6); + float conditionalPdf = + D * G1V / max(4.0 * NdotV, 1e-6); + float combinedPdf = specProb * conditionalPdf; + bounceWeight = specularBsdf * NdotL / + max(combinedPdf, 1e-6); + sampledBsdfPdf = combinedPdf; + sampledEnvironmentPdf = NdotL / M_PI_F; + sampledEventWasDelta = false; + } + } + } else if (choice < specProb + transmitProb && + transmitProb > 1e-4) { + nextDirection = idealRefractedDirection; + float fresnelCosine = NdotV; + if (roughness > 0.025) { + float3 localView = + float3(dot(V, basis[0]), dot(V, basis[1]), dot(V, N)); + float3 localH = sampleGGXVNDF( + localView, roughness, float2(rand(rng), rand(rng))); + float3 H = normalizeOr(basis * localH, N); + float3 roughRefractedDirection = refract(-V, H, eta); + if (dot(roughRefractedDirection, roughRefractedDirection) > + 1e-8 && + dot(roughRefractedDirection, Ng) < 0.0) { + nextDirection = roughRefractedDirection; + fresnelCosine = max(dot(V, H), 0.0); + } + } + float3 F = F_Schlick(fresnelCosine, float3(dielectricF0)); + float3 tint = mix(float3(1.0), albedo, 0.15); + bounceWeight = (1.0 - F) * tint / + max(transmitProb, 1e-4); + } else { + float3 localDirection = + cosineSampleHemisphere(float2(rand(rng), rand(rng))); + nextDirection = normalizeOr(basis * localDirection, N); + float NdotL = max(dot(N, nextDirection), 0.0); + float3 H = normalizeOr(V + nextDirection, N); + float3 F = F_Schlick(max(dot(V, H), 0.0), F0); + float3 kD = (1.0 - F) * (1.0 - metallic) * + (1.0 - transmittance); + float diffuseFactor = disneyDiffuseFactor( + NdotV, NdotL, max(dot(nextDirection, H), 0.0), roughness); + float3 diffuseBsdf = kD * albedo * diffuseFactor / M_PI_F; + float conditionalPdf = NdotL / M_PI_F; + float combinedPdf = diffuseProb * conditionalPdf; + bounceWeight = diffuseBsdf * NdotL / + max(combinedPdf, 1e-6); + sampledBsdfPdf = combinedPdf; + sampledEnvironmentPdf = conditionalPdf; + sampledEventWasDelta = false; + } + + bounceWeight = clampLuminance(max(bounceWeight, float3(0.0)), 16.0); + throughput *= bounceWeight; + throughput = clampLuminance(throughput, 32.0); + if (depth == 0) { + throughput *= max(sceneData.indirectStrength, 0.0); + } + if (!all(isfinite(throughput)) || max(throughput.x, + max(throughput.y, throughput.z)) < + 1e-5) { + break; + } + + if (depth >= 2) { + float survival = clamp(max(throughput.x, + max(throughput.y, throughput.z)), + 0.05, 0.95); + if (rand(rng) > survival) { + break; + } + throughput /= survival; + } + + previousBsdfPdf = sampledBsdfPdf; + previousEnvironmentPdf = sampledEnvironmentPdf; + previousEventWasDelta = sampledEventWasDelta; + + surfaceRay.origin = offsetRayOrigin(P, Ng, nextDirection); + surfaceRay.direction = normalizeOr(nextDirection, N); + surfaceRay.min_distance = 0.0; + surfaceRay.max_distance = 1.0e30; + } + + return radiance; +} + diff --git a/shaders/photon/metal/path/lighting.metal b/shaders/photon/metal/path/lighting.metal new file mode 100644 index 00000000..4d36f74b --- /dev/null +++ b/shaders/photon/metal/path/lighting.metal @@ -0,0 +1,200 @@ +float3 evalEmissiveTriangleLighting( + intersector isect, + primitive_acceleration_structure sceneAS, float3 P, float3 N, float3 Ng, + float3 V, float3 albedo, float metallic, float roughness, + float reflectivity, float ior, float transmittance, thread uint &rng, + constant SceneData &sceneData, + constant EmissiveTriangle *emissiveTriangles, + constant Material *materials, constant uint *primitiveObjects, + constant uint *blasPrimitiveOffsets, constant VertexData *vertices, + constant uint *indices, constant InstanceData *instanceData, + PT_MATERIAL_TEXTURE_PARAMS) { + if (sceneData.numEmissiveTriangles == 0) { + return float3(0.0); + } + float selector = rand(rng); + uint first = 0; + uint last = sceneData.numEmissiveTriangles - 1; + while (first < last) { + uint middle = first + (last - first) / 2; + if (selector <= emissiveTriangles[middle].cdf) { + last = middle; + } else { + first = middle + 1; + } + } + EmissiveTriangle light = emissiveTriangles[first]; + float sqrtU = sqrt(rand(rng)); + float barycentricV = rand(rng); + float b0 = 1.0 - sqrtU; + float b1 = sqrtU * (1.0 - barycentricV); + float b2 = sqrtU * barycentricV; + float3 lightPosition = light.p0.xyz * b0 + light.p1.xyz * b1 + + light.p2.xyz * b2; + float3 toLight = lightPosition - P; + float distanceSquared = dot(toLight, toLight); + if (distanceSquared <= 1e-8) { + return float3(0.0); + } + float distanceToLight = sqrt(distanceSquared); + float3 L = toLight / distanceToLight; + float surfaceCosine = dot(N, L); + float lightCosine = abs(dot(light.normal.xyz, -L)); + if (surfaceCosine <= 0.0 || dot(Ng, L) <= 0.0 || + lightCosine <= 1e-5 || light.area <= 1e-8 || + light.selectionPdf <= 1e-8) { + return float3(0.0); + } + float solidAnglePdf = light.selectionPdf * distanceSquared / + max(lightCosine * light.area, 1e-8); + float3 visibility = traceShadowVisibility( + isect, sceneAS, P, Ng, L, distanceToLight, rng, materials, + primitiveObjects, blasPrimitiveOffsets, vertices, indices, + instanceData, sceneData, PT_MATERIAL_TEXTURE_ARGS); + return evalPBR(albedo, metallic, roughness, reflectivity, ior, + transmittance, N, V, L, light.emission, + 1.0 / max(solidAnglePdf, 1e-8)) * + visibility; +} + +// --------------------------------------------------------------------------- +// Direct lighting with full PBR (replaces old evalDirectLighting) +// --------------------------------------------------------------------------- + +float3 evalDirectLightingPBR(intersector isect, + primitive_acceleration_structure sceneAS, float3 P, + float3 N, float3 Ng, float3 V, float3 albedo, + float metallic, float roughness, float reflectivity, + float ior, float transmittance, float sssStrength, + float sssThickness, + thread uint &rng, + constant DirectionalLightData &dirLight, + constant SceneData &sceneData, + constant PointLight *pointLights, + constant SpotLight *spotLights, + constant AreaLight *areaLights, + constant EmissiveTriangle *emissiveTriangles, + constant Material *materials, + constant uint *primitiveObjects, + constant uint *blasPrimitiveOffsets, + constant VertexData *vertices, + constant uint *indices, + constant InstanceData *instanceData, + PT_MATERIAL_TEXTURE_PARAMS) { + float3 lighting = float3(0.0); + // Directional + if (sceneData.numDirectionalLights > 0) { + float3 L = sampleDirectionalLightDirection(dirLight, rng); + float3 c = evalPBR(albedo, metallic, roughness, reflectivity, ior, + transmittance, N, V, L, dirLight.color, + max(dirLight.intensity, 0.0)); + float3 s = evalSubsurface(albedo, N, V, L, dirLight.color, + max(dirLight.intensity, 0.0), roughness, + sssStrength, sssThickness); + float3 visibility = traceShadowVisibility( + isect, sceneAS, P, Ng, L, 1e30, rng, materials, primitiveObjects, + blasPrimitiveOffsets, vertices, indices, instanceData, sceneData, + PT_MATERIAL_TEXTURE_ARGS); + lighting += (c + s * (1.0 - transmittance)) * visibility; + } + + // Point lights + for (uint i = 0; i < sceneData.numPointLights; ++i) { + float3 sampledPosition = pointLights[i].position; + float3 toLight = sampledPosition - P; + float dist = max(length(toLight), 1e-4); + float3 L = toLight / dist; + float lightRange = max(pointLights[i].range, 1e-4); + float minDist = max(lightRange * 0.08, 0.15); + float distSq = dist * dist + minDist * minDist; + float rangeFade = 1.0 - smoothstep(lightRange * 0.75, lightRange, dist); + float atten = rangeFade / max(distSq, 1e-4); + float intensity = max(pointLights[i].intensity, 0.0) * atten; + float3 c = evalPBR(albedo, metallic, roughness, reflectivity, ior, + transmittance, N, V, L, pointLights[i].color, + intensity); + float3 s = + evalSubsurface(albedo, N, V, L, pointLights[i].color, intensity, + roughness, sssStrength, sssThickness); + float3 visibility = traceShadowVisibility( + isect, sceneAS, P, Ng, L, dist, rng, materials, primitiveObjects, + blasPrimitiveOffsets, vertices, indices, instanceData, sceneData, + PT_MATERIAL_TEXTURE_ARGS); + lighting += (c + s * (1.0 - transmittance)) * visibility; + } + + // Spot lights + for (uint i = 0; i < sceneData.numSpotLights; ++i) { + float3 sampledPosition = spotLights[i].position; + float3 toLight = sampledPosition - P; + float dist = max(length(toLight), 1e-4); + float3 L = toLight / dist; + float3 fwd = normalize(spotLights[i].direction); + float spotCos = dot(-L, fwd); + float spot = + smoothstep(spotLights[i].outerCos, spotLights[i].innerCos, spotCos); + float lightRange = max(spotLights[i].range, 1e-4); + float minDist = max(lightRange * 0.08, 0.15); + float distSq = dist * dist + minDist * minDist; + float rangeFade = 1.0 - smoothstep(lightRange * 0.75, lightRange, dist); + float atten = rangeFade / max(distSq, 1e-4); + float intensity = max(spotLights[i].intensity, 0.0) * atten * spot; + float3 c = evalPBR(albedo, metallic, roughness, reflectivity, ior, + transmittance, N, V, L, spotLights[i].color, + intensity); + float3 s = + evalSubsurface(albedo, N, V, L, spotLights[i].color, intensity, + roughness, sssStrength, sssThickness); + float3 visibility = traceShadowVisibility( + isect, sceneAS, P, Ng, L, dist, rng, materials, primitiveObjects, + blasPrimitiveOffsets, vertices, indices, instanceData, sceneData, + PT_MATERIAL_TEXTURE_ARGS); + lighting += (c + s * (1.0 - transmittance)) * visibility; + } + + // Area lights + for (uint i = 0; i < sceneData.numAreaLights; ++i) { + float2 lightSample = float2(rand(rng), rand(rng)) * 2.0 - 1.0; + float3 sampledPosition = + areaLights[i].position + + areaLights[i].right * (lightSample.x * areaLights[i].halfWidth) + + areaLights[i].up * (lightSample.y * areaLights[i].halfHeight); + float3 toLight = sampledPosition - P; + float dist = max(length(toLight), 1e-4); + float3 L = toLight / dist; + float3 lightNorm = + normalize(cross(areaLights[i].right, areaLights[i].up)); + float cosLight = areaLights[i].twoSided > 0.5 + ? abs(dot(lightNorm, -L)) + : max(dot(lightNorm, -L), 0.0); + float area = 4.0 * areaLights[i].halfWidth * areaLights[i].halfHeight; + float lightPdfArea = 1.0 / max(area, 1e-6); + float distSq = max(dist * dist, 1e-6); + float atten = cosLight / max(distSq * lightPdfArea, 1e-6); + float intensity = max(areaLights[i].intensity, 0.0) * atten; + float3 c = evalPBR(albedo, metallic, roughness, reflectivity, ior, + transmittance, N, V, L, areaLights[i].color, + intensity); + float3 s = + evalSubsurface(albedo, N, V, L, areaLights[i].color, intensity, + roughness, sssStrength, sssThickness); + float3 visibility = traceShadowVisibility( + isect, sceneAS, P, Ng, L, dist, rng, materials, primitiveObjects, + blasPrimitiveOffsets, vertices, indices, instanceData, sceneData, + PT_MATERIAL_TEXTURE_ARGS); + lighting += (c + s * (1.0 - transmittance)) * visibility; + } + + lighting += evalEmissiveTriangleLighting( + isect, sceneAS, P, N, Ng, V, albedo, metallic, roughness, + reflectivity, ior, transmittance, rng, sceneData, emissiveTriangles, + materials, primitiveObjects, blasPrimitiveOffsets, vertices, indices, + instanceData, PT_MATERIAL_TEXTURE_ARGS); + + return lighting; +} + +// --------------------------------------------------------------------------- +// sampleRadiance — iterative path with GGX importance-sampled indirect bounces +// --------------------------------------------------------------------------- + diff --git a/shaders/photon/metal/path/materials.metal b/shaders/photon/metal/path/materials.metal new file mode 100644 index 00000000..76c6122f --- /dev/null +++ b/shaders/photon/metal/path/materials.metal @@ -0,0 +1,346 @@ +constexpr sampler materialTexSampler(coord::normalized, address::repeat, + filter::linear, mip_filter::linear); + +#define PT_MATERIAL_TEXTURE_PARAMS \ + texture2d materialTexture0, texture2d materialTexture1, \ + texture2d materialTexture2, texture2d materialTexture3, \ + texture2d materialTexture4, texture2d materialTexture5, \ + texture2d materialTexture6, texture2d materialTexture7, \ + texture2d materialTexture8, texture2d materialTexture9, \ + texture2d materialTexture10, \ + texture2d materialTexture11, \ + texture2d materialTexture12, \ + texture2d materialTexture13, \ + texture2d materialTexture14, \ + texture2d materialTexture15, \ + texture2d materialTexture16, \ + texture2d materialTexture17, \ + texture2d materialTexture18, \ + texture2d materialTexture19, \ + texture2d materialTexture20, \ + texture2d materialTexture21, \ + texture2d materialTexture22, \ + texture2d materialTexture23, \ + texture2d materialTexture24, \ + texture2d materialTexture25, \ + texture2d materialTexture26, \ + texture2d materialTexture27, \ + texture2d materialTexture28, \ + texture2d materialTexture29, \ + texture2d materialTexture30, \ + texture2d materialTexture31, \ + texture2d materialTexture32, \ + texture2d materialTexture33, \ + texture2d materialTexture34, \ + texture2d materialTexture35, \ + texture2d materialTexture36, \ + texture2d materialTexture37, \ + texture2d materialTexture38, \ + texture2d materialTexture39, \ + texture2d materialTexture40, \ + texture2d materialTexture41, \ + texture2d materialTexture42, \ + texture2d materialTexture43, \ + texture2d materialTexture44, \ + texture2d materialTexture45, \ + texture2d materialTexture46, texture2d materialTexture47 + +#define PT_MATERIAL_TEXTURE_ARGS \ + materialTexture0, materialTexture1, materialTexture2, materialTexture3, \ + materialTexture4, materialTexture5, materialTexture6, \ + materialTexture7, materialTexture8, materialTexture9, \ + materialTexture10, materialTexture11, materialTexture12, \ + materialTexture13, materialTexture14, materialTexture15, \ + materialTexture16, materialTexture17, materialTexture18, \ + materialTexture19, materialTexture20, materialTexture21, \ + materialTexture22, materialTexture23, materialTexture24, \ + materialTexture25, materialTexture26, materialTexture27, \ + materialTexture28, materialTexture29, materialTexture30, \ + materialTexture31, materialTexture32, materialTexture33, \ + materialTexture34, materialTexture35, materialTexture36, \ + materialTexture37, materialTexture38, materialTexture39, \ + materialTexture40, materialTexture41, materialTexture42, \ + materialTexture43, materialTexture44, materialTexture45, \ + materialTexture46, materialTexture47 + +#define PT_MATERIAL_TEXTURE_BINDINGS \ + texture2d materialTexture0 [[texture(12)]], \ + texture2d materialTexture1 [[texture(13)]], \ + texture2d materialTexture2 [[texture(14)]], \ + texture2d materialTexture3 [[texture(15)]], \ + texture2d materialTexture4 [[texture(16)]], \ + texture2d materialTexture5 [[texture(17)]], \ + texture2d materialTexture6 [[texture(18)]], \ + texture2d materialTexture7 [[texture(19)]], \ + texture2d materialTexture8 [[texture(20)]], \ + texture2d materialTexture9 [[texture(21)]], \ + texture2d materialTexture10 [[texture(22)]], \ + texture2d materialTexture11 [[texture(23)]], \ + texture2d materialTexture12 [[texture(24)]], \ + texture2d materialTexture13 [[texture(25)]], \ + texture2d materialTexture14 [[texture(26)]], \ + texture2d materialTexture15 [[texture(27)]], \ + texture2d materialTexture16 [[texture(28)]], \ + texture2d materialTexture17 [[texture(29)]], \ + texture2d materialTexture18 [[texture(30)]], \ + texture2d materialTexture19 [[texture(31)]], \ + texture2d materialTexture20 [[texture(32)]], \ + texture2d materialTexture21 [[texture(33)]], \ + texture2d materialTexture22 [[texture(34)]], \ + texture2d materialTexture23 [[texture(35)]], \ + texture2d materialTexture24 [[texture(36)]], \ + texture2d materialTexture25 [[texture(37)]], \ + texture2d materialTexture26 [[texture(38)]], \ + texture2d materialTexture27 [[texture(39)]], \ + texture2d materialTexture28 [[texture(40)]], \ + texture2d materialTexture29 [[texture(41)]], \ + texture2d materialTexture30 [[texture(42)]], \ + texture2d materialTexture31 [[texture(43)]], \ + texture2d materialTexture32 [[texture(44)]], \ + texture2d materialTexture33 [[texture(45)]], \ + texture2d materialTexture34 [[texture(46)]], \ + texture2d materialTexture35 [[texture(47)]], \ + texture2d materialTexture36 [[texture(48)]], \ + texture2d materialTexture37 [[texture(49)]], \ + texture2d materialTexture38 [[texture(50)]], \ + texture2d materialTexture39 [[texture(51)]], \ + texture2d materialTexture40 [[texture(52)]], \ + texture2d materialTexture41 [[texture(53)]], \ + texture2d materialTexture42 [[texture(54)]], \ + texture2d materialTexture43 [[texture(55)]], \ + texture2d materialTexture44 [[texture(56)]], \ + texture2d materialTexture45 [[texture(57)]], \ + texture2d materialTexture46 [[texture(58)]], \ + texture2d materialTexture47 [[texture(59)]] + +float4 sampleMaterialTexture(int textureIndex, float2 uv, + PT_MATERIAL_TEXTURE_PARAMS) { + switch (textureIndex) { + case 0: + return materialTexture0.sample(materialTexSampler, uv); + case 1: + return materialTexture1.sample(materialTexSampler, uv); + case 2: + return materialTexture2.sample(materialTexSampler, uv); + case 3: + return materialTexture3.sample(materialTexSampler, uv); + case 4: + return materialTexture4.sample(materialTexSampler, uv); + case 5: + return materialTexture5.sample(materialTexSampler, uv); + case 6: + return materialTexture6.sample(materialTexSampler, uv); + case 7: + return materialTexture7.sample(materialTexSampler, uv); + case 8: + return materialTexture8.sample(materialTexSampler, uv); + case 9: + return materialTexture9.sample(materialTexSampler, uv); + case 10: + return materialTexture10.sample(materialTexSampler, uv); + case 11: + return materialTexture11.sample(materialTexSampler, uv); + case 12: + return materialTexture12.sample(materialTexSampler, uv); + case 13: + return materialTexture13.sample(materialTexSampler, uv); + case 14: + return materialTexture14.sample(materialTexSampler, uv); + case 15: + return materialTexture15.sample(materialTexSampler, uv); + case 16: + return materialTexture16.sample(materialTexSampler, uv); + case 17: + return materialTexture17.sample(materialTexSampler, uv); + case 18: + return materialTexture18.sample(materialTexSampler, uv); + case 19: + return materialTexture19.sample(materialTexSampler, uv); + case 20: + return materialTexture20.sample(materialTexSampler, uv); + case 21: + return materialTexture21.sample(materialTexSampler, uv); + case 22: + return materialTexture22.sample(materialTexSampler, uv); + case 23: + return materialTexture23.sample(materialTexSampler, uv); + case 24: + return materialTexture24.sample(materialTexSampler, uv); + case 25: + return materialTexture25.sample(materialTexSampler, uv); + case 26: + return materialTexture26.sample(materialTexSampler, uv); + case 27: + return materialTexture27.sample(materialTexSampler, uv); + case 28: + return materialTexture28.sample(materialTexSampler, uv); + case 29: + return materialTexture29.sample(materialTexSampler, uv); + case 30: + return materialTexture30.sample(materialTexSampler, uv); + case 31: + return materialTexture31.sample(materialTexSampler, uv); + case 32: + return materialTexture32.sample(materialTexSampler, uv); + case 33: + return materialTexture33.sample(materialTexSampler, uv); + case 34: + return materialTexture34.sample(materialTexSampler, uv); + case 35: + return materialTexture35.sample(materialTexSampler, uv); + case 36: + return materialTexture36.sample(materialTexSampler, uv); + case 37: + return materialTexture37.sample(materialTexSampler, uv); + case 38: + return materialTexture38.sample(materialTexSampler, uv); + case 39: + return materialTexture39.sample(materialTexSampler, uv); + case 40: + return materialTexture40.sample(materialTexSampler, uv); + case 41: + return materialTexture41.sample(materialTexSampler, uv); + case 42: + return materialTexture42.sample(materialTexSampler, uv); + case 43: + return materialTexture43.sample(materialTexSampler, uv); + case 44: + return materialTexture44.sample(materialTexSampler, uv); + case 45: + return materialTexture45.sample(materialTexSampler, uv); + case 46: + return materialTexture46.sample(materialTexSampler, uv); + case 47: + return materialTexture47.sample(materialTexSampler, uv); + default: + break; + } + return float4(0.0); +} + +struct MaterialTextureArguments { + array, 256> textures [[id(0)]]; +}; + +float4 sampleMaterialTexture( + int textureIndex, float2 uv, + constant MaterialTextureArguments &materialTextureArguments) { + return materialTextureArguments.textures[textureIndex].sample( + materialTexSampler, uv); +} + +#undef PT_MATERIAL_TEXTURE_PARAMS +#undef PT_MATERIAL_TEXTURE_ARGS +#undef PT_MATERIAL_TEXTURE_BINDINGS +#define PT_MATERIAL_TEXTURE_PARAMS \ + constant MaterialTextureArguments &materialTextureArguments +#define PT_MATERIAL_TEXTURE_ARGS materialTextureArguments +#define PT_MATERIAL_TEXTURE_BINDINGS \ + constant MaterialTextureArguments &materialTextureArguments [[buffer(12)]] + +float resolveMaterialOpacity(Material mat, float2 uv, uint textureCount, + PT_MATERIAL_TEXTURE_PARAMS) { + float opacity = clamp(mat.albedo.w, 0.0, 1.0); + if (mat.opacityTextureIndex >= 0 && + uint(mat.opacityTextureIndex) < textureCount) { + float4 opacitySample = sampleMaterialTexture( + mat.opacityTextureIndex, uv, PT_MATERIAL_TEXTURE_ARGS); + opacity *= mat.opacityTextureIndex == mat.albedoTextureIndex + ? opacitySample.w + : opacitySample.x; + } + return clamp(opacity, 0.0, 1.0); +} + +void resolveMaterialParameters(Material mat, float2 uv, uint textureCount, + PT_MATERIAL_TEXTURE_PARAMS, + thread float3 &albedo, thread float &metallic, + thread float &roughness, thread float &ao, + thread float3 &emissive, thread float &outIor, + thread float &outTransmittance) { + albedo = clamp(mat.albedo.xyz, float3(0.0), float3(1.0)); + metallic = mat.metallic; + roughness = mat.roughness; + ao = mat.ao; + emissive = max(float3(mat.emissiveColor) * + max(mat.emissiveIntensity, 0.0), + float3(0.0)); + + outIor = max(mat.ior, 1.0); + outTransmittance = clamp(mat.transmittance, 0.0, 1.0); + + if (mat.albedoTextureIndex >= 0 && + uint(mat.albedoTextureIndex) < textureCount) { + albedo *= clamp(sampleMaterialTexture(mat.albedoTextureIndex, uv, + PT_MATERIAL_TEXTURE_ARGS) + .xyz, + float3(0.0), float3(1.0)); + } + if (mat.metallicTextureIndex >= 0 && + uint(mat.metallicTextureIndex) < textureCount) { + float4 metallicSample = sampleMaterialTexture( + mat.metallicTextureIndex, uv, PT_MATERIAL_TEXTURE_ARGS); + float metallicValue = metallicSample.x; + if (mat.roughnessTextureIndex == mat.metallicTextureIndex) { + metallicValue = metallicSample.z; + } + metallic *= clamp(metallicValue, 0.0, 1.0); + } + if (mat.roughnessTextureIndex >= 0 && + uint(mat.roughnessTextureIndex) < textureCount) { + float4 roughnessSample = sampleMaterialTexture( + mat.roughnessTextureIndex, uv, PT_MATERIAL_TEXTURE_ARGS); + float roughnessValue = roughnessSample.x; + if (mat.roughnessTextureIndex == mat.metallicTextureIndex) { + roughnessValue = roughnessSample.y; + } + roughness *= clamp(roughnessValue, 0.0, 1.0); + } + if (mat.aoTextureIndex >= 0 && uint(mat.aoTextureIndex) < textureCount) { + ao *= clamp(sampleMaterialTexture(mat.aoTextureIndex, uv, + PT_MATERIAL_TEXTURE_ARGS) + .x, + 0.0, 1.0); + } + + albedo = clamp(albedo, float3(0.0), float3(1.0)); + metallic = clamp(metallic, 0.0, 1.0); + roughness = clamp(roughness, 0.001, 1.0); + ao = clamp(ao, 0.0, 1.0); +} + +float3 resolveShadingNormal(Material mat, float2 uv, float3 localN, + float3 localT, float3 localB, InstanceData inst, + uint textureCount, PT_MATERIAL_TEXTURE_PARAMS) { + float3x3 normalMatrix = + float3x3(inst.normalCol0.xyz, inst.normalCol1.xyz, inst.normalCol2.xyz); + float3 N = normalizeOr(normalMatrix * localN, float3(0.0, 1.0, 0.0)); + + float3 T = normalizeOr((inst.model * float4(localT, 0.0)).xyz, + float3(1.0, 0.0, 0.0)); + float3 B = normalizeOr((inst.model * float4(localB, 0.0)).xyz, + float3(0.0, 0.0, 1.0)); + T = normalizeOr(T - N * dot(N, T), float3(1.0, 0.0, 0.0)); + B = normalizeOr(B - N * dot(N, B), cross(N, T)); + if (dot(cross(T, B), cross(T, B)) <= 1e-10) { + float3x3 basis = buildOrthonormalBasis(N); + T = basis[0]; + B = basis[1]; + } + + bool useNormalMap = mat._pad1[0] != 0; + float normalStrength = max(mat._pad0, 0.0f); + if (useNormalMap && normalStrength > 0.0 && mat.normalTextureIndex >= 0 && + uint(mat.normalTextureIndex) < textureCount) { + float3 tangentNormal = sampleMaterialTexture(mat.normalTextureIndex, uv, + PT_MATERIAL_TEXTURE_ARGS) + .xyz; + tangentNormal = tangentNormal * 2.0 - 1.0; + tangentNormal.xy *= normalStrength; + tangentNormal = normalizeOr(tangentNormal, float3(0.0, 0.0, 1.0)); + N = normalizeOr(float3x3(T, B, N) * tangentNormal, N); + } + + return N; +} + diff --git a/shaders/photon/metal/path/sampling.metal b/shaders/photon/metal/path/sampling.metal new file mode 100644 index 00000000..c62bb551 --- /dev/null +++ b/shaders/photon/metal/path/sampling.metal @@ -0,0 +1,39 @@ +float pow5(float x) { + float x2 = x * x; + return x2 * x2 * x; +} + +float luminance(float3 c) { return dot(c, float3(0.2126, 0.7152, 0.0722)); } + +float powerHeuristic(float pdfA, float pdfB) { + float a2 = pdfA * pdfA; + float b2 = pdfB * pdfB; + return a2 / max(a2 + b2, 1e-8); +} + +float3 clampLuminance(float3 c, float maxL) { + float l = luminance(c); + if (l > maxL && l > 1e-6) { + c *= maxL / l; + } + return c; +} + +uint wang_hash(uint s) { + s = (s ^ 61u) ^ (s >> 16u); + s *= 9u; + s = s ^ (s >> 4u); + s *= 0x27d4eb2du; + s = s ^ (s >> 15u); + return s; +} + +float rand(thread uint &state) { + state = wang_hash(state); + return float(state) / 4294967296.0; +} + +uint seedBase(uint2 gid, uint w, uint frame, uint sampleIndex) { + return gid.x + gid.y * w + frame * 9781u + sampleIndex * 6271u + 1u; +} + diff --git a/shaders/photon/metal/path/types.metal b/shaders/photon/metal/path/types.metal new file mode 100644 index 00000000..5ea0ab2a --- /dev/null +++ b/shaders/photon/metal/path/types.metal @@ -0,0 +1,143 @@ +struct CameraUniforms { + float4x4 invViewProj; + float4x4 prevViewProj; + float3 camPos; + float _pad0; +}; + +struct Material { + float4 albedo; + float metallic; + float roughness; + float ao; + float emissiveIntensity; + packed_float3 emissiveColor; + float _pad0; + int albedoTextureIndex; + int normalTextureIndex; + int metallicTextureIndex; + int roughnessTextureIndex; + int aoTextureIndex; + int opacityTextureIndex; + float _pad1[2]; + + float transmittance; + float ior; + float reflectivity; + float _pad2; + packed_float2 textureScale; + packed_float2 textureOffset; +}; + +static_assert(sizeof(Material) == 112); +static_assert(__builtin_offsetof(Material, emissiveColor) == 32); +static_assert(__builtin_offsetof(Material, albedoTextureIndex) == 48); +static_assert(__builtin_offsetof(Material, transmittance) == 80); +static_assert(__builtin_offsetof(Material, textureScale) == 96); + +struct VertexData { + packed_float3 position; + packed_float3 normal; + packed_float2 uv; + packed_float3 tangent; + packed_float3 bitangent; +}; + +struct InstanceData { + float4x4 model; + float4 normalCol0; + float4 normalCol1; + float4 normalCol2; +}; + +struct DirectionalLightData { + float3 direction; + float intensity; + float3 color; + float _pad0; +}; + +struct PointLight { + packed_float3 position; + float intensity; + packed_float3 color; + float range; +}; + +struct SpotLight { + packed_float3 position; + float intensity; + + packed_float3 direction; + float innerCos; + packed_float3 color; + float outerCos; + + float range; + float _pad0[3]; +}; + +struct AreaLight { + packed_float3 position; + float intensity; + + packed_float3 right; + float halfWidth; + + packed_float3 up; + float halfHeight; + + packed_float3 color; + float twoSided; +}; + +struct EmissiveTriangle { + float4 p0; + float4 p1; + float4 p2; + float4 normal; + packed_float3 emission; + float area; + float cdf; + float selectionPdf; + float2 _pad; +}; + +static_assert(sizeof(EmissiveTriangle) == 96); + +struct SceneData { + uint numDirectionalLights; + uint numPointLights; + uint numSpotLights; + uint numAreaLights; + + uint frameIndex; + uint raysPerPixel; + uint maxBounces; + float indirectStrength; + float ambientIntensity; + uint materialTextureCount; + uint atmosphereEnabled; + float atmosphereSunSize; + float3 atmosphereSunDirection; + float atmosphereSunIntensity; + float3 atmosphereSunColor; + uint pixelStride; + float3 ambientColor; + uint environmentEnabled; + uint accumulationFrameLimit; + float fireflyClamp; + uint numEmissiveTriangles; + float bloomThreshold; +}; + +static_assert(sizeof(SceneData) == 160); +static_assert(__builtin_offsetof(SceneData, atmosphereSunDirection) == 48); +static_assert(__builtin_offsetof(SceneData, atmosphereSunIntensity) == 64); +static_assert(__builtin_offsetof(SceneData, atmosphereSunColor) == 80); +static_assert(__builtin_offsetof(SceneData, pixelStride) == 96); +static_assert(__builtin_offsetof(SceneData, ambientColor) == 112); +static_assert(__builtin_offsetof(SceneData, accumulationFrameLimit) == 132); +static_assert(__builtin_offsetof(SceneData, numEmissiveTriangles) == 140); +static_assert(__builtin_offsetof(SceneData, bloomThreshold) == 144); + diff --git a/shaders/photon/metal/path/visibility.metal b/shaders/photon/metal/path/visibility.metal new file mode 100644 index 00000000..6345e20a --- /dev/null +++ b/shaders/photon/metal/path/visibility.metal @@ -0,0 +1,115 @@ +float3 traceShadowVisibility(intersector isect, + primitive_acceleration_structure sceneAS, + float3 P, float3 Ng, float3 L, + float maxDistance, thread uint &rng, + constant Material *materials, + constant uint *primitiveObjects, + constant uint *blasPrimitiveOffsets, + constant VertexData *vertices, + constant uint *indices, + constant InstanceData *instanceData, + constant SceneData &sceneData, + PT_MATERIAL_TEXTURE_PARAMS) { + float shadowBias = rayOffsetDistance(P); + float3 visibility = float3(1.0); + float causticGain = 1.0; + float3 entryNormal = float3(0.0); + uint dielectricObject = 0xFFFFFFFFu; + ray shadowRay; + shadowRay.origin = offsetRayOrigin(P, Ng, L); + shadowRay.direction = L; + shadowRay.min_distance = 0.0; + shadowRay.max_distance = max(maxDistance - shadowBias, shadowBias + 1e-4); + + for (uint alphaStep = 0; alphaStep < 32; ++alphaStep) { + auto shadowHit = isect.intersect(shadowRay, sceneAS); + if (shadowHit.type == intersection_type::none) { + return clampLuminance(visibility * causticGain, 2.5); + } + + uint primitiveIndex = + blasPrimitiveOffsets[shadowHit.geometry_id] + shadowHit.primitive_id; + uint objectIndex = primitiveObjects[primitiveIndex]; + Material material = materials[objectIndex]; + uint i0 = indices[primitiveIndex * 3 + 0]; + uint i1 = indices[primitiveIndex * 3 + 1]; + uint i2 = indices[primitiveIndex * 3 + 2]; + float2 bary = shadowHit.triangle_barycentric_coord; + float b0 = 1.0 - bary.x - bary.y; + float2 uv = float2(vertices[i0].uv) * b0 + + float2(vertices[i1].uv) * bary.x + + float2(vertices[i2].uv) * bary.y; + uv = uv * float2(material.textureScale) + + float2(material.textureOffset); + float opacity = resolveMaterialOpacity( + material, uv, sceneData.materialTextureCount, + PT_MATERIAL_TEXTURE_ARGS); + if (opacity >= 0.999 || rand(rng) < opacity) { + float transmission = clamp(material.transmittance, 0.0, 1.0) * + (1.0 - clamp(material.metallic, 0.0, 1.0)); + if (transmission <= 0.001) { + return float3(0.0); + } + + float3 p0 = float3(vertices[i0].position); + float3 p1 = float3(vertices[i1].position); + float3 p2 = float3(vertices[i2].position); + float3 hitNormal = normalizeOr(cross(p1 - p0, p2 - p0), -L); + hitNormal = dot(hitNormal, L) < 0.0 ? hitNormal : -hitNormal; + float ior = max(material.ior, 1.0); + float dielectricF0 = pow((ior - 1.0) / (ior + 1.0), 2.0); + float fresnel = dielectricF0 + + (1.0 - dielectricF0) * + pow5(1.0 - abs(dot(hitNormal, L))); + float3 tint = mix(float3(1.0), + clamp(material.albedo.xyz, float3(0.0), + float3(1.0)), + 0.15); + visibility *= tint * transmission * (1.0 - fresnel); + if (dielectricObject == objectIndex) { + float curvature = + 1.0 - clamp(abs(dot(entryNormal, hitNormal)), 0.0, 1.0); + float smoothness = + 1.0 - clamp(material.roughness, 0.0, 1.0); + float focus = 1.0 + transmission * max(ior - 1.0, 0.0) * + smoothness * smoothness * + (0.35 + curvature * 3.0); + causticGain *= clamp(focus, 1.0, 2.5); + dielectricObject = 0xFFFFFFFFu; + } else { + dielectricObject = objectIndex; + entryNormal = hitNormal; + } + if (luminance(visibility) <= 0.001) { + return float3(0.0); + } + } + + float advance = shadowHit.distance + rayOffsetDistance(shadowRay.origin); + shadowRay.origin += shadowRay.direction * advance; + shadowRay.max_distance -= advance; + if (shadowRay.max_distance <= shadowBias) { + return clampLuminance(visibility * causticGain, 2.5); + } + } + + return float3(0.0); +} + +float3 sampleDirectionalLightDirection(DirectionalLightData light, + thread uint &rng) { + float3 baseL = normalize(-light.direction); + float3x3 basis = buildOrthonormalBasis(baseL); + float sunRadius = 0.0025; + float2 u = float2(rand(rng), rand(rng)); + float r = sunRadius * sqrt(u.x); + float phi = 2.0 * M_PI_F * u.y; + float3 jittered = + baseL + basis[0] * (r * cos(phi)) + basis[1] * (r * sin(phi)); + return normalize(jittered); +} + +// --------------------------------------------------------------------------- +// PBR helpers: GGX / Cook-Torrance +// --------------------------------------------------------------------------- + diff --git a/shaders/metal/path_tracing/path_denoise.metal b/shaders/photon/path_denoise.slang similarity index 69% rename from shaders/metal/path_tracing/path_denoise.metal rename to shaders/photon/path_denoise.slang index 319c30e6..eff37ec3 100644 --- a/shaders/metal/path_tracing/path_denoise.metal +++ b/shaders/photon/path_denoise.slang @@ -1,34 +1,34 @@ -#include -using namespace metal; - struct DenoiseParameters { int stepWidth; float bloomThreshold; }; -kernel void main0(texture2d inputTexture [[texture(0)]], - texture2d outputTexture [[texture(1)]], - texture2d brightTexture [[texture(2)]], - texture2d guideTexture [[texture(3)]], - texture2d albedoRoughnessTexture - [[texture(4)]], - texture2d momentsTexture [[texture(5)]], - constant DenoiseParameters ¶meters [[buffer(0)]], - uint2 gid [[thread_position_in_grid]]) { - uint width = outputTexture.get_width(); - uint height = outputTexture.get_height(); +[[vk::binding(0, 2)]] Texture2D inputTexture; +[[vk::binding(1, 2)]] RWTexture2D outputTexture; +[[vk::binding(2, 2)]] RWTexture2D brightTexture; +[[vk::binding(3, 2)]] Texture2D guideTexture; +[[vk::binding(4, 2)]] Texture2D albedoRoughnessTexture; +[[vk::binding(5, 2)]] Texture2D momentsTexture; +[[vk::binding(0, 0)]] ConstantBuffer parameters; + +[shader("compute")] +[numthreads(8, 8, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) { + uint2 gid = dispatchThreadID.xy; + uint width, height; + outputTexture.GetDimensions(width, height); if (gid.x >= width || gid.y >= height) return; - constexpr int2 offsets[9] = {int2(0, 0), int2(1, 0), int2(-1, 0), + const int2 offsets[9] = {int2(0, 0), int2(1, 0), int2(-1, 0), int2(0, 1), int2(0, -1), int2(1, 1), int2(-1, 1), int2(1, -1), int2(-1, -1)}; - constexpr float weights[9] = {0.28, 0.12, 0.12, 0.12, 0.12, + const float weights[9] = {0.28, 0.12, 0.12, 0.12, 0.12, 0.06, 0.06, 0.06, 0.06}; - float3 center = inputTexture.read(gid).xyz; - float4 centerGuide = guideTexture.read(gid); - float4 centerAlbedoRoughness = albedoRoughnessTexture.read(gid); - float4 centerMoments = momentsTexture.read(gid); + float3 center = inputTexture.Load(int3(gid, 0)).xyz; + float4 centerGuide = guideTexture.Load(int3(gid, 0)); + float4 centerAlbedoRoughness = albedoRoughnessTexture.Load(int3(gid, 0)); + float4 centerMoments = momentsTexture.Load(int3(gid, 0)); bool centerSurface = centerGuide.w > 0.0; float centerNormalLength = dot(centerGuide.xyz, centerGuide.xyz); float centerLuminance = dot(center, float3(0.2126, 0.7152, 0.0722)); @@ -38,12 +38,12 @@ kernel void main0(texture2d inputTexture [[texture(0)]], int2 samplePosition = clamp(int2(gid) + offsets[i] * parameters.stepWidth, int2(0), int2(width - 1, height - 1)); - float4 sampleGuide = guideTexture.read(uint2(samplePosition)); + float4 sampleGuide = guideTexture.Load(int3(uint2(samplePosition), 0)); bool sampleSurface = sampleGuide.w > 0.0; if (sampleSurface != centerSurface) continue; float sampleLuminance = dot( - inputTexture.read(uint2(samplePosition)).xyz, + inputTexture.Load(int3(uint2(samplePosition), 0)).xyz, float3(0.2126, 0.7152, 0.0722)); neighborLuminance += sampleLuminance; neighborWeight += 1.0; @@ -61,14 +61,14 @@ kernel void main0(texture2d inputTexture [[texture(0)]], int2 samplePosition = clamp(int2(gid) + offsets[i] * parameters.stepWidth, int2(0), int2(width - 1, height - 1)); - float3 sampleColor = inputTexture.read(uint2(samplePosition)).xyz; - float4 sampleGuide = guideTexture.read(uint2(samplePosition)); + float3 sampleColor = inputTexture.Load(int3(uint2(samplePosition), 0)).xyz; + float4 sampleGuide = guideTexture.Load(int3(uint2(samplePosition), 0)); float4 sampleAlbedoRoughness = - albedoRoughnessTexture.read(uint2(samplePosition)); + albedoRoughnessTexture.Load(int3(uint2(samplePosition), 0)); float sampleLuminance = dot(sampleColor, float3(0.2126, 0.7152, 0.0722)); float roughness = clamp(centerAlbedoRoughness.w, 0.0, 1.0); - float luminanceScale = mix(2.5, 7.0, roughness); + float luminanceScale = lerp(2.5, 7.0, roughness); float luminanceDifference = abs(sampleLuminance - centerLuminance) / max(1.0, max(sampleLuminance, centerLuminance)); @@ -106,18 +106,18 @@ kernel void main0(texture2d inputTexture [[texture(0)]], float relativeNoise = sqrt(max(centerMoments.z, 0.0)) / max(centerLuminance, 0.05); float filterStrength = clamp(relativeNoise * 1.5, 0.02, 1.0) * - mix(0.12, 1.0, roughness * roughness); + lerp(0.12, 1.0, roughness * roughness); if (!centerSurface) { filterStrength *= 0.25; } - float3 result = mix(center, spatialResult, filterStrength); + float3 result = lerp(center, spatialResult, filterStrength); float brightness = dot(result, float3(0.2126, 0.7152, 0.0722)); - constexpr float bloomKnee = 0.35; + const float bloomKnee = 0.35; float soft = clamp(brightness - parameters.bloomThreshold + bloomKnee, 0.0, bloomKnee * 2.0); soft = soft * soft / max(bloomKnee * 4.0, 0.00001); float contribution = max(brightness - parameters.bloomThreshold, soft) / max(brightness, 0.00001); - outputTexture.write(float4(result, 1.0), gid); - brightTexture.write(float4(result * contribution, 1.0), gid); + outputTexture[gid] = float4(result, 1.0); + brightTexture[gid] = float4(result * contribution, 1.0); } diff --git a/shaders/shadows/depth.slang b/shaders/shadows/depth.slang new file mode 100644 index 00000000..ebf525f0 --- /dev/null +++ b/shaders/shadows/depth.slang @@ -0,0 +1,53 @@ +#if defined(ATLAS_VERTEX) +struct UBO +{ + row_major float4x4 model; + row_major float4x4 view; + row_major float4x4 projection; + uint isInstanced; +}; + +struct VertexOutput +{ + float4 gl_Position : SV_Position; +}; + +struct VertexInput +{ + [[vk::location(0)]] float3 aPos : TEXCOORD0; + [[vk::location(6)]] float4 instanceModel_0 : TEXCOORD6; + [[vk::location(7)]] float4 instanceModel_1 : TEXCOORD7; + [[vk::location(8)]] float4 instanceModel_2 : TEXCOORD8; + [[vk::location(9)]] float4 instanceModel_3 : TEXCOORD9; +}; + +[[vk::binding(0, 0)]] ConstantBuffer uniforms; +[shader("vertex")] +VertexOutput vertexMain(VertexInput input) +{ + VertexOutput output = {}; + row_major float4x4 instanceModel = {}; + instanceModel[0] = input.instanceModel_0; + instanceModel[1] = input.instanceModel_1; + instanceModel[2] = input.instanceModel_2; + instanceModel[3] = input.instanceModel_3; + bool hasInstanceMatrix = abs(instanceModel[3].w) > 0.5; + if ((uniforms.isInstanced != 0u) && hasInstanceMatrix) + { + row_major float4x4 _36 = mul(uniforms.view, uniforms.projection); + row_major float4x4 _40 = mul(instanceModel, _36); + float4 _49 = float4(input.aPos, 1.0); + float4 _50 = mul(_49, _40); + output.gl_Position = _50; + } + else + { + row_major float4x4 _58 = mul(uniforms.view, uniforms.projection); + row_major float4x4 _61 = mul(uniforms.model, _58); + float4 _66 = float4(input.aPos, 1.0); + float4 _67 = mul(_66, _61); + output.gl_Position = _67; + } + return output; +} +#endif diff --git a/shaders/shadows/empty.slang b/shaders/shadows/empty.slang new file mode 100644 index 00000000..23363b2e --- /dev/null +++ b/shaders/shadows/empty.slang @@ -0,0 +1,6 @@ +#if defined(ATLAS_FRAGMENT) +[shader("fragment")] +void fragmentMain() +{ +} +#endif diff --git a/shaders/shadows/point_depth_nogeom.slang b/shaders/shadows/point_depth_nogeom.slang new file mode 100644 index 00000000..a982d06a --- /dev/null +++ b/shaders/shadows/point_depth_nogeom.slang @@ -0,0 +1,83 @@ +#if defined(ATLAS_VERTEX) +struct UBO +{ + row_major float4x4 model; + uint isInstanced; +}; + +struct ShadowUniforms +{ + row_major float4x4 shadowMatrix; + int faceIndex; +}; + +struct VertexOutput +{ + [[vk::location(0)]] float4 FragPos : TEXCOORD0; + float4 gl_Position : SV_Position; +}; + +struct VertexInput +{ + [[vk::location(0)]] float3 aPos : TEXCOORD0; + [[vk::location(6)]] float4 instanceModel_0 : TEXCOORD6; + [[vk::location(7)]] float4 instanceModel_1 : TEXCOORD7; + [[vk::location(8)]] float4 instanceModel_2 : TEXCOORD8; + [[vk::location(9)]] float4 instanceModel_3 : TEXCOORD9; +}; + +[[vk::binding(0, 0)]] ConstantBuffer uniforms; +[[vk::binding(0, 2)]] ConstantBuffer shadow; +[shader("vertex")] +VertexOutput vertexMain(VertexInput input) +{ + VertexOutput output = {}; + row_major float4x4 instanceModel = {}; + instanceModel[0] = input.instanceModel_0; + instanceModel[1] = input.instanceModel_1; + instanceModel[2] = input.instanceModel_2; + instanceModel[3] = input.instanceModel_3; + float4 worldPos; + bool hasInstanceMatrix = abs(instanceModel[3].w) > 0.5; + if ((uniforms.isInstanced != 0u) && hasInstanceMatrix) + { + worldPos = mul(float4(input.aPos, 1.0), (mul(instanceModel, uniforms.model))); + } + else + { + worldPos = mul(float4(input.aPos, 1.0), uniforms.model); + } + output.FragPos = worldPos; + output.gl_Position = mul(worldPos, shadow.shadowMatrix); + return output; +} +#endif + +#if defined(ATLAS_FRAGMENT) +struct Uniforms +{ + float3 lightPos; + float far_plane; +}; + +struct FragmentOutput +{ + float gl_FragDepth : SV_Depth; +}; + +struct FragmentInput +{ + [[vk::location(0)]] float4 FragPos : TEXCOORD0; +}; + +[[vk::binding(0, 1)]] ConstantBuffer uniforms; +[shader("fragment")] +FragmentOutput fragmentMain(FragmentInput input) +{ + FragmentOutput output = {}; + float lightDistance = length(input.FragPos.xyz - float3(uniforms.lightPos)); + lightDistance /= uniforms.far_plane; + output.gl_FragDepth = lightDistance; + return output; +} +#endif diff --git a/shaders/metal/shadows/ssao.frag.metal b/shaders/shadows/ssao.slang similarity index 51% rename from shaders/metal/shadows/ssao.frag.metal rename to shaders/shadows/ssao.slang index 2354cb52..1e87f35b 100644 --- a/shaders/metal/shadows/ssao.frag.metal +++ b/shaders/shadows/ssao.slang @@ -1,12 +1,8 @@ -#include -#include - -using namespace metal; - +#if defined(ATLAS_FRAGMENT) struct Paramters { - float4x4 projection; - float4x4 inverseProjection; - float4x4 view; + row_major float4x4 projection; + row_major float4x4 inverseProjection; + row_major float4x4 view; float2 noiseScale; }; @@ -14,87 +10,85 @@ struct Samples { float3 samples[64]; }; -struct main0_out { - float FragColor [[color(0)]]; +struct FragmentOutput { + float FragColor : SV_Target0; }; -struct main0_in { - float2 TexCoord [[user(locn0)]]; +struct FragmentInput { + [[vk::location(0)]] float2 TexCoord : TEXCOORD0; }; -static inline float3 reconstructViewPos(float2 uv, float depth, - float4x4 inverseProjection) { +float3 reconstructViewPos(float2 uv, float depth, + row_major float4x4 inverseProjection) { float2 ndc; ndc.x = uv.x * 2.0 - 1.0; ndc.y = (1.0 - uv.y) * 2.0 - 1.0; float ndcZ = depth * 2.0 - 1.0; float4 clip = float4(ndc, ndcZ, 1.0); - float4 viewPos = inverseProjection * clip; + float4 viewPos = mul(clip, inverseProjection); float invW = 1.0 / max(abs(viewPos.w), 1e-6); return viewPos.xyz * invW; } -fragment main0_out main0(main0_in in [[stage_in]], - constant Paramters &_43 [[buffer(0)]], - constant Samples &_137 [[buffer(1)]], - texture2d gPosition [[texture(0)]], - texture2d gNormal [[texture(1)]], - texture2d texNoise [[texture(2)]], - sampler gPositionSmplr [[sampler(0)]], - sampler gNormalSmplr [[sampler(1)]], - sampler texNoiseSmplr [[sampler(2)]]) { - main0_out out = {}; - float3 sampledNormalWorld = gNormal.sample(gNormalSmplr, in.TexCoord).xyz; +[[vk::binding(0, 1)]] ConstantBuffer paramters; +[[vk::binding(1, 1)]] ConstantBuffer samples; +[[vk::binding(0, 2)]] Sampler2D gPosition; +[[vk::binding(1, 2)]] Sampler2D gNormal; +[[vk::binding(2, 2)]] Sampler2D texNoise; +[shader("fragment")] +FragmentOutput fragmentMain(FragmentInput input) { + FragmentOutput output = {}; + float3 sampledNormalWorld = gNormal.Sample(input.TexCoord).xyz; float sampledNormalLength = length(sampledNormalWorld); if (!all(isfinite(sampledNormalWorld)) || - sampledNormalLength <= 0.001000000047497451305389404296875) { - out.FragColor = 1.0; - return out; + sampledNormalLength <= 0.00100000005) { + output.FragColor = 1.0; + return output; } - float4 gPositionCenter = gPosition.sample(gPositionSmplr, in.TexCoord); + float4 gPositionCenter = gPosition.Sample(input.TexCoord); float centerDepth = gPositionCenter.w; if (!isfinite(centerDepth)) { - out.FragColor = 1.0; - return out; + output.FragColor = 1.0; + return output; } centerDepth = clamp(centerDepth, 0.0, 1.0); - float3 fragPos = reconstructViewPos(in.TexCoord, centerDepth, - _43.inverseProjection); + float3 fragPos = reconstructViewPos(input.TexCoord, centerDepth, + paramters.inverseProjection); float3 normalWorld = sampledNormalWorld / sampledNormalLength; - float3 normal = fast::normalize((_43.view * float4(normalWorld, 0.0)).xyz); - float3 randomVec = fast::normalize( - (texNoise.sample(texNoiseSmplr, (in.TexCoord * _43.noiseScale)).xyz * + float3 normal = normalize((mul(float4(normalWorld, 0.0), paramters.view)).xyz); + float3 randomVec = normalize( + (texNoise.Sample((input.TexCoord * paramters.noiseScale)).xyz * 2.0) - float3(1.0)); float3 tangent = - fast::normalize(randomVec - (normal * dot(randomVec, normal))); + normalize(randomVec - (normal * dot(randomVec, normal))); float3 bitangent = cross(normal, tangent); - float3x3 TBN = float3x3(float3(tangent), float3(bitangent), float3(normal)); + row_major float3x3 TBN = float3x3(float3(tangent), float3(bitangent), float3(normal)); float viewDepth = abs(fragPos.z); float baseRadius = - mix(0.550000011920928955078125, 2.2000000476837158203125, + lerp(0.550000012, 2.20000005, clamp(viewDepth / 140.0, 0.0, 1.0)); - float3 dPosDx = dfdx(fragPos); - float3 dPosDy = dfdy(fragPos); + float3 dPosDx = ddx(fragPos); + float3 dPosDy = ddy(fragPos); float pixelWorldScale = max(length(dPosDx), length(dPosDy)); if (!isfinite(pixelWorldScale)) { pixelWorldScale = 0.0; } float sampleRadius = - clamp(max(baseRadius, pixelWorldScale * 6.0), 0.3499999940395355, + clamp(max(baseRadius, pixelWorldScale * 6.0), 0.349999994, 12.0); float depthBias = clamp( - max(mix(0.006000000052154064178466796875, - 0.0240000002086162567138671875, + max(lerp(0.00600000005, + 0.0240000002, clamp(viewDepth / 180.0, 0.0, 1.0)), - sampleRadius * 0.009999999776482582), - 0.003000000026077032, 0.07999999821186066); + sampleRadius * 0.00999999978), + 0.00300000003, 0.0799999982); float occlusion = 0.0; int validSamples = 0; for (int i = 0; i < 64; i++) { - float3 samplePos = TBN * _137.samples[i]; + float3 samplePos = mul(samples.samples[i], TBN); samplePos = fragPos + (samplePos * sampleRadius); - float4 offset = _43.projection * float4(samplePos, 1.0); + float4 offset = mul(float4(samplePos, 1.0), paramters.projection); float _160 = offset.w; float4 _161 = offset; float3 _164 = _161.xyz / float3(_160); @@ -127,17 +121,17 @@ fragment main0_out main0(main0_in in [[stage_in]], if (_206) { continue; } - float sampleDepth = gPosition.sample(gPositionSmplr, offset.xy).w; + float sampleDepth = gPosition.Sample(offset.xy).w; if (!isfinite(sampleDepth)) { continue; } sampleDepth = clamp(sampleDepth, 0.0, 1.0); float3 sampleViewPos = - reconstructViewPos(offset.xy, sampleDepth, _43.inverseProjection); + reconstructViewPos(offset.xy, sampleDepth, paramters.inverseProjection); float rangeCheck = smoothstep(0.0, 1.0, sampleRadius / (abs(fragPos.z - sampleViewPos.z) + - 0.0005000000237487256526947021484375)); + 0.000500000024)); occlusion += (float(sampleViewPos.z >= (samplePos.z + depthBias)) * rangeCheck); validSamples++; @@ -147,6 +141,7 @@ fragment main0_out main0(main0_in in [[stage_in]], } else { occlusion = 1.0; } - out.FragColor = occlusion; - return out; + output.FragColor = occlusion; + return output; } +#endif diff --git a/shaders/shadows/ssao_blur.slang b/shaders/shadows/ssao_blur.slang new file mode 100644 index 00000000..c487a663 --- /dev/null +++ b/shaders/shadows/ssao_blur.slang @@ -0,0 +1,32 @@ +#if defined(ATLAS_FRAGMENT) +#include "utils/image.slang" + +struct FragmentOutput +{ + float FragColor : SV_Target0; +}; + +struct FragmentInput +{ + [[vk::location(0)]] float2 TexCoord : TEXCOORD0; +}; + +[[vk::binding(0, 2)]] Sampler2D inSSAO; +[shader("fragment")] +FragmentOutput fragmentMain(FragmentInput input) +{ + FragmentOutput output = {}; + float2 texelSize = float2(1.0) / float2(int2(textureSize(inSSAO).x, textureSize(inSSAO).y)); + float result = 0.0; + for (int x = -2; x <= 2; x++) + { + for (int y = -2; y <= 2; y++) + { + float2 offset = float2(float(x), float(y)) * texelSize; + result += inSSAO.Sample((input.TexCoord + offset)).x; + } + } + output.FragColor = result / 25.0; + return output; +} +#endif diff --git a/shaders/simple/color.slang b/shaders/simple/color.slang new file mode 100644 index 00000000..4658ac03 --- /dev/null +++ b/shaders/simple/color.slang @@ -0,0 +1,76 @@ +#if defined(ATLAS_VERTEX) +struct UBO +{ + row_major float4x4 model; + row_major float4x4 view; + row_major float4x4 projection; + uint isInstanced; +}; + +struct VertexOutput +{ + [[vk::location(0)]] float4 vertexColor : TEXCOORD0; + float4 gl_Position : SV_Position; +}; + +struct VertexInput +{ + [[vk::location(0)]] float3 aPos : TEXCOORD0; + [[vk::location(1)]] float4 aColor : TEXCOORD1; + [[vk::location(6)]] float4 instanceModel_0 : TEXCOORD6; + [[vk::location(7)]] float4 instanceModel_1 : TEXCOORD7; + [[vk::location(8)]] float4 instanceModel_2 : TEXCOORD8; + [[vk::location(9)]] float4 instanceModel_3 : TEXCOORD9; +}; + +[[vk::binding(0, 0)]] ConstantBuffer uniforms; +[shader("vertex")] +VertexOutput vertexMain(VertexInput input) +{ + VertexOutput output = {}; + row_major float4x4 instanceModel = {}; + instanceModel[0] = input.instanceModel_0; + instanceModel[1] = input.instanceModel_1; + instanceModel[2] = input.instanceModel_2; + instanceModel[3] = input.instanceModel_3; + row_major float4x4 mvp; + bool hasInstanceMatrix = abs(instanceModel[3].w) > 0.5; + if ((uniforms.isInstanced != 0u) && hasInstanceMatrix) + { + mvp = mul(instanceModel, (mul(uniforms.view, uniforms.projection))); + } + else + { + mvp = mul(uniforms.model, (mul(uniforms.view, uniforms.projection))); + } + output.gl_Position = mul(float4(input.aPos, 1.0), mvp); + output.vertexColor = input.aColor; + return output; +} +#endif + +#if defined(ATLAS_FRAGMENT) +struct FragmentOutput +{ + float4 FragColor : SV_Target0; + float4 BrightColor : SV_Target1; +}; + +struct FragmentInput +{ + [[vk::location(0)]] float4 vertexColor : TEXCOORD0; +}; + +[shader("fragment")] +FragmentOutput fragmentMain(FragmentInput input) +{ + FragmentOutput output = {}; + float3 color = input.vertexColor.xyz / (input.vertexColor.xyz + float3(1.0)); + output.FragColor = float4(color, input.vertexColor.w); + if (length(color) > 1.0) + { + output.BrightColor = float4(color, input.vertexColor.w); + } + return output; +} +#endif diff --git a/shaders/simple/debug.slang b/shaders/simple/debug.slang new file mode 100644 index 00000000..22f6ef24 --- /dev/null +++ b/shaders/simple/debug.slang @@ -0,0 +1,34 @@ +#if defined(ATLAS_VERTEX) +struct VertexOutput +{ + float4 gl_Position : SV_Position; +}; + +struct VertexInput +{ + [[vk::location(0)]] float3 aPos : TEXCOORD0; +}; + +[shader("vertex")] +VertexOutput vertexMain(VertexInput input) +{ + VertexOutput output = {}; + output.gl_Position = float4(input.aPos, 1.0); + return output; +} +#endif + +#if defined(ATLAS_FRAGMENT) +struct FragmentOutput +{ + float4 FragColor : SV_Target0; +}; + +[shader("fragment")] +FragmentOutput fragmentMain() +{ + FragmentOutput output = {}; + output.FragColor = float4(1.0, 0.0, 1.0, 1.0); + return output; +} +#endif diff --git a/shaders/simple/texture.slang b/shaders/simple/texture.slang new file mode 100644 index 00000000..23d84307 --- /dev/null +++ b/shaders/simple/texture.slang @@ -0,0 +1,210 @@ +#if defined(ATLAS_VERTEX) +struct UBO +{ + row_major float4x4 model; + row_major float4x4 view; + row_major float4x4 projection; +}; + +struct VertexOutput +{ + [[vk::location(0)]] float2 TexCoord : TEXCOORD0; + [[vk::location(1)]] float4 outColor : TEXCOORD1; + float4 gl_Position : SV_Position; +}; + +struct VertexInput +{ + [[vk::location(0)]] float3 aPos : TEXCOORD0; + [[vk::location(1)]] float4 aColor : TEXCOORD1; + [[vk::location(2)]] float2 aTexCoord : TEXCOORD2; +}; + +[[vk::binding(0, 0)]] ConstantBuffer uniforms; +[shader("vertex")] +VertexOutput vertexMain(VertexInput input) +{ + VertexOutput output = {}; + row_major float4x4 mvp = mul(uniforms.model, (mul(uniforms.view, uniforms.projection))); + output.gl_Position = mul(float4(input.aPos, 1.0), mvp); + output.TexCoord = input.aTexCoord; + output.outColor = input.aColor; + return output; +} +#endif + +#if defined(ATLAS_FRAGMENT) +struct UBO +{ + uint useTexture; + uint onlyTexture; + int textureCount; +}; + +struct FragmentOutput +{ + float4 FragColor : SV_Target0; +}; + +struct FragmentInput +{ + [[vk::location(0)]] float2 TexCoord : TEXCOORD0; + [[vk::location(1)]] float4 outColor : TEXCOORD1; +}; + +float4 calculateAllTextures(UBO uniforms, Sampler2D texture1, inout float2 TexCoord, Sampler2D texture2, Sampler2D texture3, Sampler2D texture4, Sampler2D texture5, Sampler2D texture6, Sampler2D texture7, Sampler2D texture8, Sampler2D texture9, Sampler2D texture10, Sampler2D texture11, Sampler2D texture12, Sampler2D texture13, Sampler2D texture14, Sampler2D texture15, Sampler2D texture16) +{ + float4 color = float4(0.0); + for (int i = 0; i < uniforms.textureCount; i++) + { + if (i == 0) + { + color += texture1.Sample(TexCoord); + } + else + { + if (i == 1) + { + color += texture2.Sample(TexCoord); + } + else + { + if (i == 2) + { + color += texture3.Sample(TexCoord); + } + else + { + if (i == 3) + { + color += texture4.Sample(TexCoord); + } + else + { + if (i == 4) + { + color += texture5.Sample(TexCoord); + } + else + { + if (i == 5) + { + color += texture6.Sample(TexCoord); + } + else + { + if (i == 6) + { + color += texture7.Sample(TexCoord); + } + else + { + if (i == 7) + { + color += texture8.Sample(TexCoord); + } + else + { + if (i == 8) + { + color += texture9.Sample(TexCoord); + } + else + { + if (i == 9) + { + color += texture10.Sample(TexCoord); + } + else + { + if (i == 10) + { + color += texture11.Sample(TexCoord); + } + else + { + if (i == 11) + { + color += texture12.Sample(TexCoord); + } + else + { + if (i == 12) + { + color += texture13.Sample(TexCoord); + } + else + { + if (i == 13) + { + color += texture14.Sample(TexCoord); + } + else + { + if (i == 14) + { + color += texture15.Sample(TexCoord); + } + else + { + if (i == 15) + { + color += texture16.Sample(TexCoord); + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + color /= float4(float(uniforms.textureCount)); + return color; +} + +[[vk::binding(0, 1)]] ConstantBuffer uniforms; +[[vk::binding(0, 2)]] Sampler2D texture1; +[[vk::binding(1, 2)]] Sampler2D texture2; +[[vk::binding(2, 2)]] Sampler2D texture3; +[[vk::binding(3, 2)]] Sampler2D texture4; +[[vk::binding(4, 2)]] Sampler2D texture5; +[[vk::binding(5, 2)]] Sampler2D texture6; +[[vk::binding(6, 2)]] Sampler2D texture7; +[[vk::binding(7, 2)]] Sampler2D texture8; +[[vk::binding(8, 2)]] Sampler2D texture9; +[[vk::binding(9, 2)]] Sampler2D texture10; +[[vk::binding(10, 2)]] Sampler2D texture11; +[[vk::binding(11, 2)]] Sampler2D texture12; +[[vk::binding(12, 2)]] Sampler2D texture13; +[[vk::binding(13, 2)]] Sampler2D texture14; +[[vk::binding(14, 2)]] Sampler2D texture15; +[[vk::binding(15, 2)]] Sampler2D texture16; +[shader("fragment")] +FragmentOutput fragmentMain(FragmentInput input) +{ + FragmentOutput output = {}; + if (uniforms.onlyTexture != 0u) + { + output.FragColor = calculateAllTextures(uniforms, texture1, input.TexCoord, texture2, texture3, texture4, texture5, texture6, texture7, texture8, texture9, texture10, texture11, texture12, texture13, texture14, texture15, texture16); + return output; + } + if (uniforms.useTexture != 0u) + { + output.FragColor = calculateAllTextures(uniforms, texture1, input.TexCoord, texture2, texture3, texture4, texture5, texture6, texture7, texture8, texture9, texture10, texture11, texture12, texture13, texture14, texture15, texture16) * input.outColor; + } + else + { + output.FragColor = input.outColor; + } + return output; +} +#endif diff --git a/shaders/ui/text.slang b/shaders/ui/text.slang new file mode 100644 index 00000000..35aec1ed --- /dev/null +++ b/shaders/ui/text.slang @@ -0,0 +1,55 @@ +#if defined(ATLAS_VERTEX) +struct Uniforms +{ + row_major float4x4 projection; +}; + +struct VertexOutput +{ + [[vk::location(0)]] float2 texCoords : TEXCOORD0; + float4 gl_Position : SV_Position; +}; + +struct VertexInput +{ + [[vk::location(0)]] float4 vertex0 : TEXCOORD0; +}; + +[[vk::binding(0, 0)]] ConstantBuffer uniforms; +[shader("vertex")] +VertexOutput vertexMain(VertexInput input) +{ + VertexOutput output = {}; + output.gl_Position = mul(float4(input.vertex0.xy, 0.0, 1.0), uniforms.projection); + output.texCoords = input.vertex0.zw; + return output; +} +#endif + +#if defined(ATLAS_FRAGMENT) +struct TextColor +{ + float3 textColor; +}; + +struct FragmentOutput +{ + float4 color : SV_Target0; +}; + +struct FragmentInput +{ + [[vk::location(0)]] float2 texCoords : TEXCOORD0; +}; + +[[vk::binding(0, 1)]] ConstantBuffer textColor; +[[vk::binding(0, 2)]] Sampler2D text; +[shader("fragment")] +FragmentOutput fragmentMain(FragmentInput input) +{ + FragmentOutput output = {}; + float4 sampled = float4(1.0, 1.0, 1.0, text.Sample(input.texCoords).x); + output.color = float4(textColor.textColor, 1.0) * sampled; + return output; +} +#endif diff --git a/shaders/utils/ddgi.slang b/shaders/utils/ddgi.slang new file mode 100644 index 00000000..ce8fc149 --- /dev/null +++ b/shaders/utils/ddgi.slang @@ -0,0 +1,260 @@ +float2 octEncode(float3 n) { + n /= (fabs(n.x) + fabs(n.y) + fabs(n.z) + 1e-6f); + float2 e = n.xy; + + if (n.z < 0.0f) { + float2 signNotZero = + float2(e.x >= 0.0f ? 1.0f : -1.0f, e.y >= 0.0f ? 1.0f : -1.0f); + e = (1.0f - fabs(e.yx)) * signNotZero; + } + return e; +} + +float3 safeNormalizeDDGI(float3 v, float3 fallback) { + float len2 = dot(v, v); + if (len2 > 1e-10f) { + return v * rsqrt(len2); + } + return fallback; +} + +uint probeIndexFromCoord(uint3 c, uint3 counts) { + return c.x + counts.x * (c.y + counts.y * c.z); +} + +float2 ddgiAtlasUV(uint probeIndex, float3 dirWS, + ProbeSpace ps, uint atlasW, + uint atlasH) { + if (atlasW == 0u || atlasH == 0u) { + return float2(0.5f); + } + + uint border = (uint)ps.atlasParams.x; + uint innerRes = (uint)ps.atlasParams.y; + uint probesPerRow = (uint)ps.atlasParams.z; + if (innerRes == 0u || probesPerRow == 0u) { + return float2(0.5f); + } + + uint tileRes = innerRes + 2u * border; + + uint tileX = probeIndex % probesPerRow; + uint tileY = probeIndex / probesPerRow; + + float dirLen = length(dirWS); + float3 safeDir = + (dirLen > 1e-6f) ? (dirWS / float3(dirLen)) : float3(0.0f, 1.0f, 0.0f); + float2 e = octEncode(safeDir); + float2 innerUV = e * 0.5f + 0.5f; + + float2 innerPx = float2((float)(tileX * tileRes + border), + (float)(tileY * tileRes + border)) + + innerUV * float(innerRes - 1u); + + return (innerPx + 0.5f) / float2((float)atlasW, (float)atlasH); +} + +float4 sampleDDGITextureBilinear(Texture2D tex, + float2 uv) { + uint w = textureSize(tex).x; + uint h = textureSize(tex).y; + if (w == 0u || h == 0u) { + return float4(0.0f); + } + + float2 pixel = uv * float2((float)w, (float)h) - 0.5f; + int2 p0 = int2(floor(pixel)); + int2 p1 = p0 + int2(1, 0); + int2 p2 = p0 + int2(0, 1); + int2 p3 = p0 + int2(1, 1); + + int maxX = int(w) - 1; + int maxY = int(h) - 1; + p0 = int2(clamp(p0.x, 0, maxX), clamp(p0.y, 0, maxY)); + p1 = int2(clamp(p1.x, 0, maxX), clamp(p1.y, 0, maxY)); + p2 = int2(clamp(p2.x, 0, maxX), clamp(p2.y, 0, maxY)); + p3 = int2(clamp(p3.x, 0, maxX), clamp(p3.y, 0, maxY)); + + float2 f = frac(pixel); + float4 c00 = tex.Load(int3(uint2((uint)p0.x, (uint)p0.y), 0)); + float4 c10 = tex.Load(int3(uint2((uint)p1.x, (uint)p1.y), 0)); + float4 c01 = tex.Load(int3(uint2((uint)p2.x, (uint)p2.y), 0)); + float4 c11 = tex.Load(int3(uint2((uint)p3.x, (uint)p3.y), 0)); + float4 cx0 = lerp(c00, c10, f.x); + float4 cx1 = lerp(c01, c11, f.x); + return lerp(cx0, cx1, f.y); +} + +float4 +sampleProbeDirectionalRadiance(Texture2D ddgiTexture, + ProbeSpace ps, uint probeIndex, + uint atlasW, uint atlasH, float3 dirWS) { + float2 uv = ddgiAtlasUV(probeIndex, dirWS, ps, atlasW, atlasH); + return sampleDDGITextureBilinear(ddgiTexture, uv); +} + +float3 sampleDDGIIrradiance(Texture2D ddgiTexture, + Texture2D ddgiDistance, + ProbeSpace ps, float3 posWS, + float3 normalWS) { + uint3 counts = uint3((uint)ps.probeCount.x, (uint)ps.probeCount.y, + (uint)ps.probeCount.z); + + if (counts.x == 0u || counts.y == 0u || counts.z == 0u) + return float3(0.0); + + uint atlasW = textureSize(ddgiTexture).x; + uint atlasH = textureSize(ddgiTexture).y; + if (atlasW == 0u || atlasH == 0u) { + return float3(0.0); + } + + float normalLen = length(normalWS); + float3 safeNormal = (normalLen > 1e-6f) ? (normalWS / float3(normalLen)) + : float3(0.0f, 1.0f, 0.0f); + + float3 safeSpacing = max(ps.spacing, float3(1e-4f)); + float spacingScale = + max(max(safeSpacing.x, max(safeSpacing.y, safeSpacing.z)), 1e-4f); + float3 grid = (posWS - ps.origin) / safeSpacing; + + if (counts.x < 2u || counts.y < 2u || counts.z < 2u) { + float3 maxCoord = max(float3(0.0f), float3((float)counts.x - 1.0f, + (float)counts.y - 1.0f, + (float)counts.z - 1.0f)); + float3 clampedGrid = clamp(grid, float3(0.0f), maxCoord); + uint3 nearest = uint3( + (uint)clamp(int(floor(clampedGrid.x + 0.5f)), 0, int(counts.x) - 1), + (uint)clamp(int(floor(clampedGrid.y + 0.5f)), 0, int(counts.y) - 1), + (uint)clamp(int(floor(clampedGrid.z + 0.5f)), 0, + int(counts.z) - 1)); + uint pIndex = probeIndexFromCoord(nearest, counts); + float4 nearestSample = sampleProbeDirectionalRadiance( + ddgiTexture, ps, pIndex, atlasW, atlasH, safeNormal); + float3 nearestProbePos = ps.origin + float3(nearest) * safeSpacing; + float3 nearestDirection = safeNormalizeDDGI( + posWS - nearestProbePos, safeNormal); + float4 nearestMoments = sampleProbeDirectionalRadiance( + ddgiDistance, ps, pIndex, atlasW, atlasH, nearestDirection); + float nearestDistance = length(posWS - nearestProbePos); + float nearestVariance = max(nearestMoments.y - nearestMoments.x * + nearestMoments.x, + 0.0001f); + float nearestDelta = max(nearestDistance - nearestMoments.x, 0.0f); + float nearestVisibility = nearestDelta <= 0.0f + ? 1.0f + : nearestVariance / + (nearestVariance + nearestDelta * + nearestDelta); + float nearestValidity = isfinite(nearestSample.w) + ? clamp(nearestSample.w, 0.0f, 1.0f) + : 0.0f; + float3 nearestIrr = + all(isfinite(nearestSample.xyz)) ? nearestSample.xyz : float3(0.0f); + nearestIrr *= nearestValidity * nearestVisibility; + return max(nearestIrr, float3(0.0f)); + } + + float3 maxGrid = + float3((float)counts.x - 1.0001f, (float)counts.y - 1.0001f, + (float)counts.z - 1.0001f); + float3 clampedGrid = clamp(grid, float3(0.0f), maxGrid); + + float3 baseF = floor(clampedGrid); + float3 frac = clampedGrid - baseF; + int3 baseI = int3(baseF); + int3 maxBase = + int3(int(counts.x) - 2, int(counts.y) - 2, int(counts.z) - 2); + baseI = clamp(baseI, int3(0), maxBase); + + float3 result = float3(0.0f); + float weightSum = 0.0f; + float3 resultNoBackface = float3(0.0f); + float weightSumNoBackface = 0.0f; + + for (uint dz = 0; dz <= 1u; dz++) { + for (uint dy = 0; dy <= 1u; dy++) { + for (uint dx = 0; dx <= 1u; dx++) { + + uint3 pc = uint3(uint(baseI.x) + dx, uint(baseI.y) + dy, + uint(baseI.z) + dz); + uint pIndex = probeIndexFromCoord(pc, counts); + + float trilinearW = ((dx == 0u) ? (1.0f - frac.x) : frac.x) * + ((dy == 0u) ? (1.0f - frac.y) : frac.y) * + ((dz == 0u) ? (1.0f - frac.z) : frac.z); + + float3 probePos = ps.origin + float3(pc) * safeSpacing; + float3 surfaceToProbe = probePos - posWS; + float sDist = length(surfaceToProbe); + float3 dirToProbe = (sDist > 1e-4f) ? surfaceToProbe / sDist + : float3(0.0f, 1.0f, 0.0f); + float frontW = max(dot(safeNormal, dirToProbe), 0.0f); + float backfaceW = + lerp(0.180000007, 1.0f, frontW * frontW); + float distNorm = sDist / spacingScale; + float distNorm2 = distNorm * distNorm; + float distanceW = + 1.0f / (1.0f + distNorm2 * 0.850000024); + + float w = trilinearW * backfaceW * distanceW; + + float4 irrSample = sampleProbeDirectionalRadiance( + ddgiTexture, ps, pIndex, atlasW, atlasH, safeNormal); + float3 probeToSurface = -surfaceToProbe; + float4 distanceSample = sampleProbeDirectionalRadiance( + ddgiDistance, ps, pIndex, atlasW, atlasH, + safeNormalizeDDGI(probeToSurface, safeNormal)); + float variance = max(distanceSample.y - + distanceSample.x * distanceSample.x, + 0.0001f); + float delta = max(sDist - distanceSample.x, 0.0f); + float visibility = delta <= 0.0f + ? 1.0f + : variance / (variance + delta * delta); + visibility = visibility * visibility * visibility; + float probeValidity = isfinite(irrSample.w) + ? clamp(irrSample.w, 0.0f, 1.0f) + : 0.0f; + float validityW = probeValidity; + float3 irr = irrSample.xyz; + if (!all(isfinite(irr))) { + irr = float3(0.0f); + validityW = 0.0f; + } + irr = max(irr, float3(0.0f)); + float weightedW = w * validityW * max(visibility, 0.001f); + result += irr * weightedW; + weightSum += weightedW; + float noBackfaceW = trilinearW * distanceW * validityW * + max(visibility, 0.001f); + resultNoBackface += irr * noBackfaceW; + weightSumNoBackface += noBackfaceW; + } + } + } + + if (weightSum > 1e-5f) { + return result / weightSum; + } + if (weightSumNoBackface > 1e-5f) { + return resultNoBackface / weightSumNoBackface; + } + + uint3 nearest = uint3( + (uint)clamp(int(floor(clampedGrid.x + 0.5f)), 0, int(counts.x) - 1), + (uint)clamp(int(floor(clampedGrid.y + 0.5f)), 0, int(counts.y) - 1), + (uint)clamp(int(floor(clampedGrid.z + 0.5f)), 0, int(counts.z) - 1)); + uint nearestIndex = probeIndexFromCoord(nearest, counts); + float4 fallbackSample = sampleProbeDirectionalRadiance( + ddgiTexture, ps, nearestIndex, atlasW, atlasH, safeNormal); + float fallbackValidity = + isfinite(fallbackSample.w) ? clamp(fallbackSample.w, 0.0f, 1.0f) : 0.0f; + float3 fallback = + all(isfinite(fallbackSample.xyz)) ? fallbackSample.xyz : float3(0.0f); + fallback *= fallbackValidity; + if (!all(isfinite(fallback))) { + fallback = float3(0.0f); + } + return max(fallback, float3(0.0f)); +} diff --git a/shaders/utils/deferred_lighting.slang b/shaders/utils/deferred_lighting.slang new file mode 100644 index 00000000..a13908a7 --- /dev/null +++ b/shaders/utils/deferred_lighting.slang @@ -0,0 +1,465 @@ +float2 getTextureDimensions( + int textureIndex, Sampler2D texture1, Sampler2D texture2, + Sampler2D texture3, Sampler2D texture4, Sampler2D texture5) { + if (textureIndex == 0) { + return float2(int2(textureSize(texture1).x, textureSize(texture1).y)); + } else { + if (textureIndex == 1) { + return float2(int2(textureSize(texture2).x, textureSize(texture2).y)); + } else { + if (textureIndex == 2) { + return float2( + int2(textureSize(texture3).x, textureSize(texture3).y)); + } else { + if (textureIndex == 3) { + return float2( + int2(textureSize(texture4).x, textureSize(texture4).y)); + } else { + if (textureIndex == 4) { + return float2( + int2(textureSize(texture5).x, textureSize(texture5).y)); + } + } + } + } + } + return float2(0.0); +} + +float4 sampleCubeTextureAt( + int textureIndex, float3 direction, + SamplerCube cubeMap1, + SamplerCube cubeMap2, + SamplerCube cubeMap3, + SamplerCube cubeMap4, + SamplerCube cubeMap5) { + if (textureIndex == 0) { + return cubeMap1.Sample(direction); + } else { + if (textureIndex == 1) { + return cubeMap2.Sample(direction); + } else { + if (textureIndex == 2) { + return cubeMap3.Sample(direction); + } else { + if (textureIndex == 3) { + return cubeMap4.Sample(direction); + } else { + if (textureIndex == 4) { + return cubeMap5.Sample(direction); + } + } + } + } + } + return float4(0.0); +} + +float calculatePointShadow( + ShadowParameters shadowParam, float3 fragPos, + Sampler2D texture1, Sampler2D texture2, Sampler2D texture3, + Sampler2D texture4, Sampler2D texture5, SamplerCube cubeMap1, + SamplerCube cubeMap2, + SamplerCube cubeMap3, + SamplerCube cubeMap4, + SamplerCube cubeMap5) { + int param = shadowParam.textureIndex; + float2 dims = getTextureDimensions( + param, texture1, texture2, texture3, texture4, texture5); + bool _739 = dims.x == 0.0; + bool _746; + if (!_739) { + _746 = dims.y == 0.0; + } else { + _746 = _739; + } + if (_746) { + return 0.0; + } + float3 fragToLight = fragPos - shadowParam.lightPos; + float currentDepth = length(fragToLight); + if (currentDepth >= shadowParam.farPlane) { + return 0.0; + } + float bias0 = 0.0500000007; + float shadow = 0.0; + float diskRadius = (1.0 + (currentDepth / shadowParam.farPlane)) * + 0.0500000007; + for (int i = 0; i < 10; i++) { + float3 sampleDir = + normalize(fragToLight + (_861[i] * diskRadius)); + int param_1 = shadowParam.textureIndex; + float3 param_2 = sampleDir; + float closestDepth = + sampleCubeTextureAt(param_1, param_2, cubeMap1, + cubeMap2, cubeMap3, cubeMap4, + cubeMap5) + .x * + shadowParam.farPlane; + if ((currentDepth - bias0) > closestDepth) { + shadow += 1.0; + } + } + shadow /= 10.0; + return shadow; +} + +float4 sampleTextureAt( + int textureIndex, float2 uv, + Sampler2D texture1, Sampler2D texture2, Sampler2D texture3, + Sampler2D texture4, Sampler2D texture5) { + if (textureIndex == 0) { + return texture1.Sample(uv); + } else { + if (textureIndex == 1) { + return texture2.Sample(uv); + } else { + if (textureIndex == 2) { + return texture3.Sample(uv); + } else { + if (textureIndex == 3) { + return texture4.Sample(uv); + } else { + if (textureIndex == 4) { + return texture5.Sample(uv); + } + } + } + } + } + return float4(0.0); +} + +float calculateShadow( + ShadowParameters shadowParam, float3 fragPos, + float3 normal, Sampler2D texture1, Sampler2D texture2, + Sampler2D texture3, Sampler2D texture4, Sampler2D texture5, + UBO uniforms) { + int param = shadowParam.textureIndex; + float2 dims = getTextureDimensions( + param, texture1, texture2, texture3, texture4, texture5); + bool _411 = dims.x == 0.0; + bool _419; + if (!_411) { + _419 = dims.y == 0.0; + } else { + _419 = _411; + } + if (_419) { + return 0.0; + } + float4 fragPosLightSpace = + mul(float4(fragPos, 1.0), (mul(shadowParam.lightView, shadowParam.lightProjection))); + if (fragPosLightSpace.w == 0.0) { + return 0.0; + } + float3 clipCoords = fragPosLightSpace.xyz / float3(fragPosLightSpace.w); + float2 projCoordsXY = (clipCoords.xy * 0.5) + float2(0.5); + float3 projCoords = float3(projCoordsXY, clipCoords.z); + bool _456 = projCoords.x < 0.0; + bool _463; + if (!_456) { + _463 = projCoords.x > 1.0; + } else { + _463 = _456; + } + bool _470; + if (!_463) { + _470 = projCoords.y < 0.0; + } else { + _470 = _463; + } + bool _477; + if (!_470) { + _477 = projCoords.y > 1.0; + } else { + _477 = _470; + } + bool _485; + if (!_477) { + _485 = projCoords.z < 0.0; + } else { + _485 = _477; + } + bool _493; + if (!_485) { + _493 = projCoords.z > 1.0; + } else { + _493 = _485; + } + if (_493) { + return 0.0; + } + float currentDepth = projCoords.z; + bool isAreaShadow = shadowParam.lightType == 2; + float3 lightDirWorld = normalize( + -(mul(float4(0.0, 0.0, -1.0, 0.0), inverseMatrix(shadowParam.lightView))) + .xyz); + float biasValue = shadowParam.bias0; + if (isAreaShadow) { + biasValue = max(biasValue, 0.00120000006); + } + float ndotl = max(dot(normal, lightDirWorld), 0.0); + float minBias = + max(isAreaShadow ? 0.000250000012 + : 4.99999987e-05, + biasValue * (isAreaShadow ? 0.850000024 : 0.25)); + float bias0 = max(biasValue * (1.0 - ndotl), minBias); + if (isAreaShadow) { + bias0 += 0.000250000012; + } + float shadow = 0.0; + float2 texelSize = float2(1.0) / dims; + float _distance = length(float3(uniforms.cameraPosition) - fragPos); + float2 shadowMapSize = dims; + float avgDim = 0.5 * (shadowMapSize.x + shadowMapSize.y); + float resFactor = clamp(1024.0 / max(avgDim, 1.0), 0.75, 1.25); + float distFactor = clamp(_distance / 800.0, 0.0, 1.0); + float texelRadius = + lerp(isAreaShadow ? 1.79999995 : 1.0, + isAreaShadow ? 4.19999981 : 3.0, distFactor) * + resFactor; + float2 filterRadius = texelSize * texelRadius; + int kernelSamples = isAreaShadow ? 6 : 8; + int sampleCount = 0; + for (int i = 0; i < kernelSamples; i++) { + float2 offset = _660[i] * filterRadius; + float2 uv = projCoords.xy + offset; + bool _676 = uv.x < 0.0; + bool _683; + if (!_676) { + _683 = uv.x > 1.0; + } else { + _683 = _676; + } + bool _690; + if (!_683) { + _690 = uv.y < 0.0; + } else { + _690 = _683; + } + bool _697; + if (!_690) { + _697 = uv.y > 1.0; + } else { + _697 = _690; + } + if (_697) { + continue; + } + int param_1 = shadowParam.textureIndex; + float2 param_2 = uv; + float pcfDepth = + sampleTextureAt(param_1, param_2, texture1, texture2, texture3, texture4, texture5) + .x; + shadow += float((currentDepth - bias0) > pcfDepth); + sampleCount++; + } + if (sampleCount > 0) { + shadow /= float(sampleCount); + } + if (isAreaShadow) { + shadow = smoothstep(0.180000007, 0.920000017, shadow); + } + return shadow; +} + +float +distributionGGX(float3 N, float3 H, + float roughness) { + float a = roughness * roughness; + float a2 = a * a; + float NdotH = max(dot(N, H), 0.0); + float NdotH2 = NdotH * NdotH; + float num = a2; + float denom = (NdotH2 * (a2 - 1.0)) + 1.0; + denom = (3.14159274 * denom) * denom; + return num / max(denom, 9.99999975e-05); +} + +float +geometrySchlickGGX(float NdotV, float roughness) { + float r = roughness + 1.0; + float k = (r * r) / 8.0; + float num = NdotV; + float denom = (NdotV * (1.0 - k)) + k; + return num / max(denom, 9.99999975e-05); +} + +float +geometrySmith(float3 N, float3 V, + float3 L, float roughness) { + float NdotV = max(dot(N, V), 0.0); + float NdotL = max(dot(N, L), 0.0); + float param = NdotV; + float param_1 = roughness; + float ggx2 = geometrySchlickGGX(param, param_1); + float param_2 = NdotL; + float param_3 = roughness; + float ggx1 = geometrySchlickGGX(param_2, param_3); + return ggx1 * ggx2; +} + +float3 +fresnelSchlick(float cosTheta, float3 F0) { + return F0 + ((float3(1.0) - F0) * powr(1.0 - cosTheta, 5.0)); +} + +float3 +evaluateBRDF(float3 L, float3 radiance, + float3 N, float3 V, + float3 F0, float3 albedo, + float metallic, float roughness) { + float3 H = normalize(V + L); + float3 param = N; + float3 param_1 = H; + float param_2 = roughness; + float NDF = distributionGGX(param, param_1, param_2); + float3 param_3 = N; + float3 param_4 = V; + float3 param_5 = L; + float param_6 = roughness; + float G = geometrySmith(param_3, param_4, param_5, param_6); + float param_7 = max(dot(H, V), 0.0); + float3 param_8 = F0; + float3 F = fresnelSchlick(param_7, param_8); + float3 kS = F; + float3 kD = (float3(1.0) - kS) * (1.0 - metallic); + float NdotV = max(dot(N, V), 0.0); + float NdotL = max(dot(N, L), 0.0); + float3 numerator = F * (NDF * G); + float denominator = + max((4.0 * NdotV) * NdotL, 9.99999975e-05); + float3 specular = numerator / float3(denominator); + return ((((kD * albedo) / float3(3.14159274)) + specular) * + radiance) * + NdotL; +} + +float3 calcDirectionalLight( + DirectionalLight light, float3 N, + float3 V, float3 F0, + float3 albedo, float metallic, + float roughness) { + float3 L = normalize(-light.direction); + float3 radiance = light.diffuse * max(light.intensity, 0.0); + float3 param = L; + float3 param_1 = radiance; + float3 param_2 = N; + float3 param_3 = V; + float3 param_4 = F0; + float3 param_5 = albedo; + float param_6 = metallic; + float param_7 = roughness; + return evaluateBRDF(param, param_1, param_2, param_3, param_4, param_5, + param_6, param_7); +} + +float3 +calcPointLight(PointLight light, float3 fragPos, + float3 N, float3 V, + float3 F0, float3 albedo, + float metallic, float roughness) { + float3 L = light.position - fragPos; + float _distance = length(L); + float3 _1019; + if (_distance > 0.0) { + _1019 = L / float3(_distance); + } else { + _1019 = float3(0.0, 0.0, 1.0); + } + float3 direction = _1019; + float attenuation = + 1.0 / max((light.constant0 + (light.linear * _distance)) + + ((light.quadratic * _distance) * _distance), + 9.99999975e-05); + float fade = 1.0 - smoothstep(light.radius * 0.899999976, + light.radius, _distance); + float3 radiance = + ((light.diffuse * max(light.intensity, 0.0)) * attenuation) * + fade; + float3 param = direction; + float3 param_1 = radiance; + float3 param_2 = N; + float3 param_3 = V; + float3 param_4 = F0; + float3 param_5 = albedo; + float param_6 = metallic; + float param_7 = roughness; + return evaluateBRDF(param, param_1, param_2, param_3, param_4, param_5, + param_6, param_7); +} + +float3 +calcSpotLight(SpotLight light, float3 fragPos, + float3 N, float3 V, + float3 F0, float3 albedo, + float metallic, float roughness) { + float3 L = light.position - fragPos; + float _distance = length(L); + float3 direction = normalize(L); + float3 spotDirection = normalize(light.direction); + float theta = dot(direction, -spotDirection); + float epsilon = max(light.cutOff - light.outerCutOff, + 9.99999975e-05); + float intensity = + clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0); + float range = max(light.range, 0.00100000005); + float attenuation = 1.0 / ((1.0 + (_distance / range)) + + ((_distance * _distance) / (range * range))); + float fade = + 1.0 - smoothstep(range * 0.899999976, range, _distance); + float3 radiance = + (((light.diffuse * max(light.intensity, 0.0)) * attenuation) * + intensity) * + fade; + float3 param = direction; + float3 param_1 = radiance; + float3 param_2 = N; + float3 param_3 = V; + float3 param_4 = F0; + float3 param_5 = albedo; + float param_6 = metallic; + float param_7 = roughness; + return evaluateBRDF(param, param_1, param_2, param_3, param_4, param_5, + param_6, param_7); +} + +float3 +getRimLight(float3 fragPos, inout float3 N, inout float3 V, + float3 F0, float3 albedo, + float metallic, float roughness, + UBO uniforms, Environment environment) { + N = normalize(N); + V = normalize(V); + float rim = powr(1.0 - max(dot(N, V), 0.0), 3.0); + rim *= lerp(1.20000005, 0.300000012, roughness); + float3 rimColor = + lerp(float3(1.0), albedo, float3(metallic)) * environment.rimLightColor; + rimColor = lerp(rimColor, F0, float3(0.5)); + float rimIntensity = environment.rimLightIntensity; + float3 rimLight = (rimColor * rim) * rimIntensity; + float dist = length(float3(uniforms.cameraPosition) - fragPos); + rimLight /= float3(1.0 + (dist * 0.100000001)); + return rimLight; +} + +float3 +sampleEnvironmentRadiance(float3 direction, + SamplerCube skybox) { + return skybox.Sample(direction).xyz; +} + +float3 +acesToneMapping(inout float3 color) { + float a = 2.50999999; + float b = 0.0299999993; + float c = 2.43000007; + float d = 0.589999974; + float e = 0.140000001; + color = (color * ((color * a) + float3(b))) / + ((color * ((color * c) + float3(d))) + float3(e)); + color = powr(clamp(color, float3(0.0), float3(1.0)), + float3(0.454545468)); + return color; +} diff --git a/shaders/utils/fullscreen.slang b/shaders/utils/fullscreen.slang new file mode 100644 index 00000000..1c3058fc --- /dev/null +++ b/shaders/utils/fullscreen.slang @@ -0,0 +1,19 @@ +struct ScreenVertexInput { + [[vk::location(0)]] float3 position : TEXCOORD0; + [[vk::location(2)]] float2 texCoord : TEXCOORD2; +}; + +struct ScreenVertexOutput { + float4 position : SV_Position; + [[vk::location(0)]] float2 texCoord : TEXCOORD0; +}; + +[shader("vertex")] +ScreenVertexOutput vertexMain(ScreenVertexInput input) { + return {float4(input.position.xy, 0.0, 1.0), input.texCoord}; +} + +[shader("vertex")] +ScreenVertexOutput screenVertexMain(ScreenVertexInput input) { + return {float4(input.position, 1.0), input.texCoord}; +} diff --git a/shaders/utils/image.slang b/shaders/utils/image.slang new file mode 100644 index 00000000..3f49c317 --- /dev/null +++ b/shaders/utils/image.slang @@ -0,0 +1,3 @@ +uint2 textureSize(Sampler2D tex) { uint w, h; tex.GetDimensions(w, h); return uint2(w, h); } + +uint2 textureSize(Texture2D tex) { uint w, h; tex.GetDimensions(w, h); return uint2(w, h); } diff --git a/shaders/utils/matrix.slang b/shaders/utils/matrix.slang new file mode 100644 index 00000000..f47f57fa --- /dev/null +++ b/shaders/utils/matrix.slang @@ -0,0 +1,39 @@ +float determinant2(float a1, float a2, float b1, float b2) +{ + return a1 * b2 - b1 * a2; +} + +float determinant3(float a1, float a2, float a3, float b1, float b2, float b3, float c1, float c2, float c3) +{ + return a1 * determinant2(b2, b3, c2, c3) - b1 * determinant2(a2, a3, c2, c3) + c1 * determinant2(a2, a3, b2, b3); +} + +float4x4 inverseMatrix(row_major float4x4 m) +{ + row_major float4x4 adj; + + adj[0][0] = determinant3(m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], m[2][3], m[3][1], m[3][2], m[3][3]); + adj[0][1] = -determinant3(m[0][1], m[0][2], m[0][3], m[2][1], m[2][2], m[2][3], m[3][1], m[3][2], m[3][3]); + adj[0][2] = determinant3(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], m[3][1], m[3][2], m[3][3]); + adj[0][3] = -determinant3(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], m[2][3]); + + adj[1][0] = -determinant3(m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][2], m[3][3]); + adj[1][1] = determinant3(m[0][0], m[0][2], m[0][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][2], m[3][3]); + adj[1][2] = -determinant3(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], m[3][0], m[3][2], m[3][3]); + adj[1][3] = determinant3(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], m[2][3]); + + adj[2][0] = determinant3(m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], m[2][3], m[3][0], m[3][1], m[3][3]); + adj[2][1] = -determinant3(m[0][0], m[0][1], m[0][3], m[2][0], m[2][1], m[2][3], m[3][0], m[3][1], m[3][3]); + adj[2][2] = determinant3(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], m[3][0], m[3][1], m[3][3]); + adj[2][3] = -determinant3(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], m[2][3]); + + adj[3][0] = -determinant3(m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2], m[3][0], m[3][1], m[3][2]); + adj[3][1] = determinant3(m[0][0], m[0][1], m[0][2], m[2][0], m[2][1], m[2][2], m[3][0], m[3][1], m[3][2]); + adj[3][2] = -determinant3(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[3][0], m[3][1], m[3][2]); + adj[3][3] = determinant3(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2]); + + float det = (adj[0][0] * m[0][0]) + (adj[0][1] * m[1][0]) + (adj[0][2] * m[2][0]) + (adj[0][3] * m[3][0]); + + if (det != 0.0f) return adj * (1.0f / det); + return m; +} diff --git a/shaders/utils/post_processing.slang b/shaders/utils/post_processing.slang new file mode 100644 index 00000000..5ea2bbce --- /dev/null +++ b/shaders/utils/post_processing.slang @@ -0,0 +1,530 @@ +float4 sampleColor(float2 uv) +{ + for (int i = 0; i < parameters.EffectCount; i++) + { + if (EffectBuffer[i] == 7) + { + float redOffset = EffectFloat1Buffer[i]; + float greenOffset = EffectFloat2Buffer[i]; + float blueOffset = EffectFloat3Buffer[i]; + float2 focusPoint = float2(EffectFloat4Buffer[i], EffectFloat5Buffer[i]); + float2 sampleCoord = uv; + float2 direction = sampleCoord - focusPoint; + float red = Texture.Sample((sampleCoord + (direction * redOffset))).x; + float green = Texture.Sample((sampleCoord + (direction * greenOffset))).y; + float2 blue = Texture.Sample((sampleCoord + (direction * blueOffset))).zw; + return float4(red, green, blue); + } + else + { + if (EffectBuffer[i] == 9) + { + float pixelSizeInPixels = EffectFloat1Buffer[i]; + float2 texSize = float2(int2(textureSize(Texture).x, textureSize(Texture).y)); + float2 pixelSize = float2(pixelSizeInPixels) / texSize; + float2 pixelated = floor(uv / pixelSize) * pixelSize; + return Texture.Sample(pixelated); + } + else + { + if (EffectBuffer[i] == 10) + { + float radius = EffectFloat1Buffer[i]; + float separation = EffectFloat2Buffer[i]; + float2 texelSize = float2(1.0) / float2(int2(textureSize(Texture).x, textureSize(Texture).y)); + float3 maxColor = Texture.Sample(uv).xyz; + int range = int(radius); + float radiusSq = radius * radius; + int _543 = -range; + for (int x = _543; x <= range; x++) + { + int _554 = -range; + for (int y = _554; y <= range; y++) + { + float distSq = float((x * x) + (y * y)); + if (distSq <= radiusSq) + { + float2 offset = (float2(float(x), float(y)) * texelSize) * separation; + float3 sampled = Texture.Sample((uv + offset)).xyz; + maxColor = max(maxColor, sampled); + } + } + } + return float4(maxColor, Texture.Sample(uv).w); + } + } + } + } + return Texture.Sample(uv); +} + +float3 reconstructViewPos(float2 uv, float depth) +{ + float z = (depth * 2.0) - 1.0; + float4 clipPos = float4((uv * 2.0) - float2(1.0), z, 1.0); + float4 viewPos = mul(clipPos, uniforms.invProjectionMatrix); + viewPos /= float4(viewPos.w); + return viewPos.xyz; +} + +float4 sharpen(Sampler2D image, inout float2 TexCoord) +{ + float3 sampleTex[9]; + for (int i = 0; i < 9; i++) + { + sampleTex[i] = float3(image.Sample((TexCoord + _165[i])).xyz); + } + float3 col = float3(0.0); + for (int i_1 = 0; i_1 < 9; i_1++) + { + col += (sampleTex[i_1] * _171[i_1]); + } + return float4(col, 1.0); +} + +float4 blur(Sampler2D image, float radius, inout float2 TexCoord) +{ + float2 texelSize = float2(1.0) / float2(int2(textureSize(image).x, textureSize(image).y)); + float3 result = float3(0.0); + float total = 0.0; + float sigma = radius * 0.5; + float twoSigmaSq = (2.0 * sigma) * sigma; + int _257 = -int(radius); + for (int x = _257; x <= int(radius); x++) + { + float weight = exp(float(-(x * x)) / twoSigmaSq); + float2 offset = float2(float(x), 0.0) * texelSize; + result += (image.Sample((TexCoord + offset)).xyz * weight); + total += weight; + } + result /= float3(total); + return float4(result, 1.0); +} + +float4 edgeDetection(Sampler2D image, inout float2 TexCoord) +{ + float3 sampleTex[9]; + for (int i = 0; i < 9; i++) + { + sampleTex[i] = float3(image.Sample((TexCoord + _165[i])).xyz); + } + float3 col = float3(0.0); + for (int i_1 = 0; i_1 < 9; i_1++) + { + col += (sampleTex[i_1] * _311[i_1]); + } + return float4(col, 1.0); +} + +float4 applyFXAA(Sampler2D tex, float2 texCoord) +{ + float2 texelSize = float2(1.0) / float2(int2(textureSize(tex).x, textureSize(tex).y)); + float FXAA_SPAN_MAX = 8.0; + float FXAA_REDUCE_MUL = 0.125; + float FXAA_REDUCE_MIN = 0.0078125; + float2 param = texCoord + (float2(-1.0) * texelSize); + float3 rgbNW = sampleColor(param).xyz; + float2 param_1 = texCoord + (float2(1.0, -1.0) * texelSize); + float3 rgbNE = sampleColor(param_1).xyz; + float2 param_2 = texCoord + (float2(-1.0, 1.0) * texelSize); + float3 rgbSW = sampleColor(param_2).xyz; + float2 param_3 = texCoord + (float2(1.0) * texelSize); + float3 rgbSE = sampleColor(param_3).xyz; + float2 param_4 = texCoord; + float3 rgbM = sampleColor(param_4).xyz; + float3 luma = float3(0.298999995, 0.587000012, 0.114); + float lumaNW = dot(rgbNW, luma); + float lumaNE = dot(rgbNE, luma); + float lumaSW = dot(rgbSW, luma); + float lumaSE = dot(rgbSE, luma); + float lumaM = dot(rgbM, luma); + float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); + float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); + float2 dir; + dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); + dir.y = (lumaNW + lumaSW) - (lumaNE + lumaSE); + float dirReduce = max((((lumaNW + lumaNE) + lumaSW) + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN); + float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce); + dir = min(float2(FXAA_SPAN_MAX), max(float2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin)) * texelSize; + float2 param_5 = texCoord + (dir * (-0.166666672)); + float2 param_6 = texCoord + (dir * 0.166666672); + float3 rgbA = (sampleColor(param_5).xyz + sampleColor(param_6).xyz) * 0.5; + float2 param_7 = texCoord + (dir * (-0.5)); + float2 param_8 = texCoord + (dir * 0.5); + float3 rgbB = (rgbA * 0.5) + ((sampleColor(param_7).xyz + sampleColor(param_8).xyz) * 0.25); + float lumaB = dot(rgbB, luma); + if ((lumaB < lumaMin) || (lumaB > lumaMax)) + { + return float4(rgbA, 1.0); + } + else + { + return float4(rgbB, 1.0); + } +} + +float4 applyColorCorrection(float4 color, ColorCorrection cc) +{ + float3 linearColor = color.xyz; + linearColor *= powr(2.0, cc.exposure); + linearColor = ((linearColor - float3(0.5)) * cc.contrast) + float3(0.5); + linearColor.x += (cc.temperature * 0.0500000007); + linearColor.y += (cc.tint * 0.0500000007); + float luminance = dot(linearColor, float3(0.212599993, 0.715200007, 0.0722000003)); + linearColor = lerp(float3(luminance), linearColor, float3(cc.saturation)); + linearColor = clamp(linearColor, float3(0.0), float3(1.0)); + return float4(linearColor, color.w); +} + +float4 applyColorEffects(inout float4 color, inout float4 gl_FragCoord) +{ + ColorCorrection cc; + for (int i = 0; i < parameters.EffectCount; i++) + { + if (EffectBuffer[i] == 0) + { + color = float4(float3(1.0) - color.xyz, color.w); + } + else + { + if (EffectBuffer[i] == 1) + { + float average = ((0.212599993 * color.x) + (0.715200007 * color.y)) + (0.0722000003 * color.z); + color = float4(average, average, average, color.w); + } + else + { + if (EffectBuffer[i] == 5) + { + cc.exposure = EffectFloat1Buffer[i]; + cc.contrast = EffectFloat2Buffer[i]; + cc.saturation = EffectFloat3Buffer[i]; + cc.gamma = EffectFloat4Buffer[i]; + cc.temperature = EffectFloat5Buffer[i]; + cc.tint = EffectFloat6Buffer[i]; + float4 param = color; + ColorCorrection param_1 = cc; + color = applyColorCorrection(param, param_1); + } + else + { + if (EffectBuffer[i] == 8) + { + float levels = max(EffectFloat1Buffer[i], 1.0); + float grayscale = max(color.x, max(color.y, color.z)); + if (grayscale > 9.99999975e-05) + { + float lower = floor(grayscale * levels) / levels; + float lowerDiff = abs(grayscale - lower); + float upper = ceil(grayscale * levels) / levels; + float upperDiff = abs(upper - grayscale); + float level0 = (lowerDiff <= upperDiff) ? lower : upper; + float adjustment = level0 / max(grayscale, 9.99999975e-05); + color *= adjustment; + } + } + else + { + if (EffectBuffer[i] == 11) + { + float amount = EffectFloat1Buffer[i]; + float3 seed = float3(gl_FragCoord.xy, uniforms.deltaTime * 100.0); + float n = dot(seed, float3(12.9898005, 78.2330017, 45.1640015)); + float noise = frac(sin(n) * 43758.546875); + float grain = ((noise - 0.5) * 2.0) * amount; + float luminance = dot(color.xyz, float3(0.298999995, 0.587000012, 0.114)); + float visibility = 1.0 - (abs(luminance - 0.5) * 0.5); + float4 _1210 = color; + float3 _1212 = _1210.xyz + float3(grain * visibility); + color.x = _1212.x; + color.y = _1212.y; + color.z = _1212.z; + float4 _1219 = color; + float3 _1223 = clamp(_1219.xyz, float3(0.0), float3(1.0)); + color.x = _1223.x; + color.y = _1223.y; + color.z = _1223.z; + } + } + } + } + } + } + return color; +} + +float LinearizeDepth(float depth) +{ + float z = (depth * 2.0) - 1.0; + float linear = ((2.0 * uniforms.nearPlane) * uniforms.farPlane) / ((uniforms.farPlane + uniforms.nearPlane) - (z * (uniforms.farPlane - uniforms.nearPlane))); + return linear / uniforms.farPlane; +} + +float4 sampleBright(float2 uv) +{ + for (int i = 0; i < parameters.EffectCount; i++) + { + if (EffectBuffer[i] == 7) + { + float redOffset = EffectFloat1Buffer[i]; + float greenOffset = EffectFloat2Buffer[i]; + float blueOffset = EffectFloat3Buffer[i]; + float2 focusPoint = float2(EffectFloat4Buffer[i], EffectFloat5Buffer[i]); + float2 sampleCoord = uv; + float2 direction = sampleCoord - focusPoint; + float red = BrightTexture.Sample((sampleCoord + (direction * redOffset))).x; + float green = BrightTexture.Sample((sampleCoord + (direction * greenOffset))).y; + float2 blue = BrightTexture.Sample((sampleCoord + (direction * blueOffset))).zw; + return float4(red, green, blue); + } + else + { + if (EffectBuffer[i] == 9) + { + float pixelSizeInPixels = EffectFloat1Buffer[i]; + float2 texSize = float2(int2(textureSize(BrightTexture).x, textureSize(BrightTexture).y)); + float2 pixelSize = float2(pixelSizeInPixels) / texSize; + float2 pixelated = floor(uv / pixelSize) * pixelSize; + float4 color = BrightTexture.Sample(pixelated); + return color; + } + else + { + if (EffectBuffer[i] == 10) + { + float radius = EffectFloat1Buffer[i]; + float separation = EffectFloat2Buffer[i]; + float2 texelSize = float2(1.0) / float2(int2(textureSize(BrightTexture).x, textureSize(BrightTexture).y)); + float3 maxColor = BrightTexture.Sample(uv).xyz; + int range = int(radius); + float radiusSq = radius * radius; + int _766 = -range; + for (int x = _766; x <= range; x++) + { + int _777 = -range; + for (int y = _777; y <= range; y++) + { + float distSq = float((x * x) + (y * y)); + if (distSq <= radiusSq) + { + float2 offset = (float2(float(x), float(y)) * texelSize) * separation; + float3 sampled = BrightTexture.Sample((uv + offset)).xyz; + maxColor = max(maxColor, sampled); + } + } + } + return float4(maxColor, BrightTexture.Sample(uv).w); + } + } + } + } + return BrightTexture.Sample(uv); +} + +float4 composeSSR(float4 color, float2 uv) +{ + if (parameters.hasSSRTexture != 1) + { + return color; + } + float4 ssr = SSRTexture.Sample(uv); + float reflectionWeight = clamp(ssr.w, 0.0, 1.0); + float baseWeight = 1.0 - reflectionWeight; + float4 result = color; + result.xyz = (result.xyz * baseWeight) + (ssr.xyz * reflectionWeight); + return result; +} + +float4 composeLighting(float2 uv, float4 baseColor) +{ + float4 color = baseColor; + if (parameters.hasBrightTexture == 1) + { + color += sampleBright(uv); + } + if (parameters.hasVolumetricLightTexture == 1) + { + color += VolumetricLightTexture.Sample(uv); + } + return composeSSR(color, uv); +} + +float4 applyMotionBlur(float2 texCoord, float size, float separation, float4 color) +{ + float4 fallbackColor = composeLighting(texCoord, color); + if ((size <= 0.0) || (separation <= 0.0)) + { + return fallbackColor; + } + if (parameters.hasPositionTexture != 1) + { + return fallbackColor; + } + float4 worldPos = PositionTexture.Sample(texCoord); + if (worldPos.w <= 0.0) + { + return fallbackColor; + } + float3 viewSpacePos = (mul(worldPos, uniforms.viewMatrix)).xyz; + float distanceToCamera = length(viewSpacePos); + if (distanceToCamera < (uniforms.nearPlane * 2.0)) + { + return fallbackColor; + } + float4 currentClipPos = mul(worldPos, (mul(uniforms.viewMatrix, uniforms.projectionMatrix))); + float _1543 = currentClipPos.w; + float4 _1544 = currentClipPos; + float3 _1547 = _1544.xyz / float3(_1543); + currentClipPos.x = _1547.x; + currentClipPos.y = _1547.y; + currentClipPos.z = _1547.z; + float2 currentUV = (currentClipPos.xy * 0.5) + float2(0.5); + float4 prevClipPos = mul(worldPos, (mul(uniforms.lastViewMatrix, uniforms.projectionMatrix))); + float _1569 = prevClipPos.w; + float4 _1570 = prevClipPos; + float3 _1573 = _1570.xyz / float3(_1569); + prevClipPos.x = _1573.x; + prevClipPos.y = _1573.y; + prevClipPos.z = _1573.z; + float2 prevUV = (prevClipPos.xy * 0.5) + float2(0.5); + float2 velocity = (currentUV - prevUV) * separation; + float velocityLength = length(velocity); + float maxVelocity = 0.119999997; + if (velocityLength > maxVelocity) + { + velocity = normalize(velocity) * maxVelocity; + velocityLength = maxVelocity; + } + if (parameters.hasSSRTexture == 1) + { + float mirrorWeight = clamp(SSRTexture.Sample(texCoord).w, 0.0, 1.0); + float blurDamp = lerp(1.0, 0.200000003, mirrorWeight); + velocity *= blurDamp; + velocityLength *= blurDamp; + } + if (velocityLength < 9.99999975e-05) + { + return fallbackColor; + } + int baseSamples = clamp(int(size), 2, 32); + float sampleScale = lerp(0.75, 1.75, clamp(velocityLength / maxVelocity, 0.0, 1.0)); + int samples = clamp(int(float(baseSamples) * sampleScale), 3, 48); + float centerDepth = 0.0; + float depthSoftness = 1.0; + if (parameters.hasDepthTexture == 1) + { + float centerDepthRaw = DepthTexture.Sample(texCoord).x; + centerDepth = LinearizeDepth(centerDepthRaw); + depthSoftness = max(0.00200000009, centerDepth * 0.0199999996); + } + float jitter = (frac(sin(dot(texCoord * float2(173.300003, 97.0999985), float2(12.9898005, 78.2330017))) * 43758.546875) - 0.5) * 0.349999994; + float4 result = float4(0.0); + float totalWeight = 0.0; + for (int i = 0; i < samples; i++) + { + float t = (((float(i) + 0.5) / float(samples)) * 2.0) - 1.0; + t += jitter / float(samples); + float2 sampleCoord = texCoord + (velocity * t); + bool _1642 = sampleCoord.x < 0.0; + bool _1648; + if (!_1642) + { + _1648 = sampleCoord.x > 1.0; + } + else + { + _1648 = _1642; + } + bool _1654; + if (!_1648) + { + _1654 = sampleCoord.y < 0.0; + } + else + { + _1654 = _1648; + } + bool _1660; + if (!_1654) + { + _1660 = sampleCoord.y > 1.0; + } + else + { + _1660 = _1654; + } + if (_1660) + { + continue; + } + float depthWeight = 1.0; + if (parameters.hasDepthTexture == 1) + { + float sampleDepthRaw = DepthTexture.Sample(sampleCoord).x; + float sampleDepth = LinearizeDepth(sampleDepthRaw); + float depthDelta = abs(sampleDepth - centerDepth); + depthWeight = 1.0 - smoothstep(depthSoftness, depthSoftness * 2.5, depthDelta); + if (depthWeight <= 0.0) + { + continue; + } + } + float4 sampled = sampleColor(sampleCoord); + sampled = composeLighting(sampleCoord, sampled); + float gaussian = exp((-4.0) * t * t); + float weight = gaussian * depthWeight; + result += (sampled * weight); + totalWeight += weight; + } + if (totalWeight > 0.0) + { + return result / float4(totalWeight); + } + return fallbackColor; +} + +float3 sampleLUT(float3 rgb, float blueSlice, float sliceSize, float slicePixelOffset) +{ + float sliceY = floor(blueSlice / parameters.lutSize); + float sliceX = mod(blueSlice, parameters.lutSize); + float2 uv; + uv.x = ((sliceX * sliceSize) + slicePixelOffset) + (rgb.x * sliceSize); + uv.y = ((sliceY * sliceSize) + slicePixelOffset) + (rgb.y * sliceSize); + return LUTTexture.Sample(uv).xyz; +} + +float4 mapToLUT(float4 color) +{ + if (parameters.hasLUTTexture != 1) + { + return color; + } + float sliceSize = 1.0 / parameters.lutSize; + float slicePixelOffset = sliceSize * 0.5; + float blueIndex = color.z * (parameters.lutSize - 1.0); + float sliceLow = floor(blueIndex); + float sliceHigh = min(sliceLow + 1.0, parameters.lutSize - 1.0); + float t = blueIndex - sliceLow; + float3 param = color.xyz; + float param_1 = sliceLow; + float param_2 = sliceSize; + float param_3 = slicePixelOffset; + float3 lowColor = sampleLUT(param, param_1, param_2, param_3); + float3 param_4 = color.xyz; + float param_5 = sliceHigh; + float param_6 = sliceSize; + float param_7 = slicePixelOffset; + float3 highColor = sampleLUT(param_4, param_5, param_6, param_7); + float3 finalRGB = lerp(lowColor, highColor, float3(t)); + return float4(finalRGB, color.w); +} + +float3 acesToneMapping(float3 color) +{ + float a = 2.50999999; + float b = 0.0299999993; + float c = 2.43000007; + float d = 0.589999974; + float e = 0.140000001; + return clamp((color * ((color * a) + float3(b))) / ((color * ((color * c) + float3(d))) + float3(e)), float3(0.0), float3(1.0)); +} diff --git a/shaders/volumetric/volumetric.slang b/shaders/volumetric/volumetric.slang new file mode 100644 index 00000000..e1d1476a --- /dev/null +++ b/shaders/volumetric/volumetric.slang @@ -0,0 +1,102 @@ +#if defined(ATLAS_VERTEX) +#include "utils/fullscreen.slang" +#endif + +#if defined(ATLAS_FRAGMENT) +struct Sun +{ + float2 sunPos; +}; + +struct VolumetricParameters +{ + float density; + float weight; + float decay; + float exposure; +}; + +struct DirectionalLight +{ + float3 color; +}; + +struct FragmentOutput +{ + float4 FragColor : SV_Target0; +}; + +struct FragmentInput +{ + [[vk::location(0)]] float2 TexCoords : TEXCOORD0; +}; + +float3 computeVolumetricLighting(float2 uv, Sun sun, VolumetricParameters volumetricParameters, Sampler2D sceneTexture, DirectionalLight directionalLight) +{ + float3 color = float3(0.0); + float2 deltaTexCoord = (sun.sunPos - uv) * volumetricParameters.density; + float2 coord = uv; + float illuminationDecay = 1.0; + for (int i = 0; i < 48; i++) + { + coord += deltaTexCoord; + bool _59 = coord.x < 0.0; + bool _66; + if (!_59) + { + _66 = coord.x > 1.0; + } + else + { + _66 = _59; + } + bool _74; + if (!_66) + { + _74 = coord.y < 0.0; + } + else + { + _74 = _66; + } + bool _81; + if (!_74) + { + _81 = coord.y > 1.0; + } + else + { + _81 = _74; + } + if (_81) + { + break; + } + float3 sampled = sceneTexture.Sample(coord).xyz; + float brightness = dot(sampled, float3(0.298999995, 0.587000012, 0.114)); + float3 atmosphere = directionalLight.color * 0.0199999996; + if (brightness > 0.5) + { + atmosphere += (sampled * 0.5); + } + atmosphere *= (illuminationDecay * volumetricParameters.weight); + color += atmosphere; + illuminationDecay *= volumetricParameters.decay; + } + return color * 5.0; +} + +[[vk::binding(0, 1)]] ConstantBuffer sun; +[[vk::binding(2, 1)]] ConstantBuffer volumetricParameters; +[[vk::binding(1, 1)]] ConstantBuffer directionalLight; +[[vk::binding(0, 2)]] Sampler2D sceneTexture; +[shader("fragment")] +FragmentOutput fragmentMain(FragmentInput input) +{ + FragmentOutput output = {}; + float2 param = input.TexCoords; + float3 rays = computeVolumetricLighting(param, sun, volumetricParameters, sceneTexture, directionalLight); + output.FragColor = float4(rays, 1.0); + return output; +} +#endif diff --git a/shaders/vulkan/deferred/deferred.frag b/shaders/vulkan/deferred/deferred.frag deleted file mode 100644 index 3f882505..00000000 --- a/shaders/vulkan/deferred/deferred.frag +++ /dev/null @@ -1,232 +0,0 @@ -#version 450 -layout(location = 0) out vec4 gPosition; -layout(location = 1) out vec4 gNormal; -layout(location = 2) out vec4 gAlbedoSpec; -layout(location = 3) out vec4 gMaterial; - -layout(location = 0) in vec4 outColor; -layout(location = 1) in vec2 TexCoord; -layout(location = 2) in vec3 Normal; -layout(location = 3) in vec3 FragPos; -layout(location = 4) in mat3 TBN; - -const int TEXTURE_COLOR = 0; -const int TEXTURE_SPECULAR = 1; -const int TEXTURE_NORMAL = 5; -const int TEXTURE_PARALLAX = 6; -const int TEXTURE_METALLIC = 9; -const int TEXTURE_ROUGHNESS = 10; -const int TEXTURE_AO = 11; -const int TEXTURE_OPACITY = 12; -const int TEXTURE_PBR_PACK = 14; - -layout(set = 2, binding = 0) uniform sampler2D texture1; -layout(set = 2, binding = 1) uniform sampler2D texture2; -layout(set = 2, binding = 2) uniform sampler2D texture3; -layout(set = 2, binding = 3) uniform sampler2D texture4; -layout(set = 2, binding = 4) uniform sampler2D texture5; -layout(set = 2, binding = 5) uniform sampler2D texture6; -layout(set = 2, binding = 6) uniform sampler2D texture7; -layout(set = 2, binding = 7) uniform sampler2D texture8; -layout(set = 2, binding = 8) uniform sampler2D texture9; -layout(set = 2, binding = 9) uniform sampler2D texture10; - -layout(set = 1, binding = 0) uniform UBO { - int textureTypes[16]; - int textureCount; - bool useTexture; - bool useColor; - vec3 cameraPosition; - vec2 textureScale; - vec2 textureOffset; -}; - -layout(push_constant) uniform MaterialPush { - vec3 albedo; - float metallic; - float roughness; - float ao; - float reflectivity; -} material; - -vec2 texCoord; - -vec4 enableTextures(int type) { - vec4 color = vec4(0.0); - int count = 0; - for (int i = 0; i < textureCount; i++) { - if (textureTypes[i] == type) { - if (i == 0) color += texture(texture1, texCoord); - else if (i == 1) color += texture(texture2, texCoord); - else if (i == 2) color += texture(texture3, texCoord); - else if (i == 3) color += texture(texture4, texCoord); - else if (i == 4) color += texture(texture5, texCoord); - else if (i == 5) color += texture(texture6, texCoord); - else if (i == 6) color += texture(texture7, texCoord); - else if (i == 7) color += texture(texture8, texCoord); - else if (i == 8) color += texture(texture9, texCoord); - else if (i == 9) color += texture(texture10, texCoord); - count++; - } - } - if (count > 0) color /= float(count); - if (count == 0) return vec4(-1.0); - return color; -} - -vec4 sampleTextureAt(int textureIndex, vec2 uv) { - if (textureIndex == 0) return texture(texture1, uv); - else if (textureIndex == 1) return texture(texture2, uv); - else if (textureIndex == 2) return texture(texture3, uv); - else if (textureIndex == 3) return texture(texture4, uv); - else if (textureIndex == 4) return texture(texture5, uv); - else if (textureIndex == 5) return texture(texture6, uv); - else if (textureIndex == 6) return texture(texture7, uv); - else if (textureIndex == 7) return texture(texture8, uv); - else if (textureIndex == 8) return texture(texture9, uv); - else if (textureIndex == 9) return texture(texture10, uv); - return vec4(0.0); -} - -vec2 parallaxMapping(vec2 texCoords, vec3 viewDir) { - const float minLayers = 8.0; - const float maxLayers = 32.0; - vec3 v = normalize(viewDir); - float numLayers = mix(maxLayers, minLayers, abs(dot(vec3(0.0, 0.0, 1.0), v))); - float layerDepth = 1.0 / numLayers; - float currentLayerDepth = 0.0; - - const float heightScale = 0.04; - vec2 P = (v.xy / max(v.z, 0.05)) * heightScale; - vec2 deltaTexCoords = P / numLayers; - - vec2 currentTexCoords = texCoords; - int textureIndex = -1; - for (int i = 0; i < textureCount; i++) { - if (textureTypes[i] == TEXTURE_PARALLAX) { - textureIndex = i; - break; - } - } - if (textureIndex == -1) return currentTexCoords; - - float currentDepthMapValue = 1.0 - sampleTextureAt(textureIndex, currentTexCoords).r; - - while (currentLayerDepth < currentDepthMapValue) { - currentTexCoords -= deltaTexCoords; - currentDepthMapValue = 1.0 - sampleTextureAt(textureIndex, currentTexCoords).r; - currentLayerDepth += layerDepth; - } - - vec2 prevTexCoords = currentTexCoords + deltaTexCoords; - float afterDepth = currentDepthMapValue - currentLayerDepth; - float beforeDepth = 1.0 - sampleTextureAt(textureIndex, prevTexCoords).r - (currentLayerDepth - layerDepth); - float denom = afterDepth - beforeDepth; - float weight = abs(denom) > 1e-4 - ? clamp(afterDepth / denom, 0.0, 1.0) - : 0.0; - currentTexCoords = prevTexCoords * weight + currentTexCoords * (1.0 - weight); - - return currentTexCoords; -} - -void main() { - texCoord = TexCoord * textureScale + textureOffset; - - // Only apply parallax mapping if a parallax texture exists - bool hasParallaxMap = false; - for (int i = 0; i < textureCount; i++) { - if (textureTypes[i] == TEXTURE_PARALLAX) { - hasParallaxMap = true; - break; - } - } - - if (hasParallaxMap) { - vec3 tangentViewDir = normalize(transpose(TBN) * (cameraPosition - FragPos)); - texCoord = parallaxMapping(texCoord, tangentViewDir); - } - - vec4 sampledColor = enableTextures(TEXTURE_COLOR); - bool hasColorTexture = sampledColor != vec4(-1.0); - - vec4 baseColor = vec4(material.albedo, 1.0); - vec4 albedoTex = enableTextures(TEXTURE_COLOR); - if (albedoTex != vec4(-1.0)) { - baseColor *= albedoTex; - } - vec4 opacityTex = enableTextures(TEXTURE_OPACITY); - if (opacityTex != vec4(-1.0)) { - if (opacityTex.r < 0.1) { - discard; - } - } else if (baseColor.a < 0.1) { - discard; - } - - - vec4 normTexture = enableTextures(TEXTURE_NORMAL); - vec3 normal; - if (normTexture.r != -1.0 && normTexture.g != -1.0 && normTexture.b != -1.0) { - vec3 tangentNormal = normalize(normTexture.rgb * 2.0 - 1.0); - normal = normalize(TBN * tangentNormal); - } else { - normal = normalize(Normal); - } - - vec3 albedoColor = baseColor.rgb; - - vec4 pbrPackTex = enableTextures(TEXTURE_PBR_PACK); - bool hasPbrPack = pbrPackTex != vec4(-1.0); - - float metallicValue = material.metallic; - if (hasPbrPack) { - metallicValue *= pbrPackTex.b; - } else { - vec4 metallicTex = enableTextures(TEXTURE_METALLIC); - if (metallicTex != vec4(-1.0)) { - metallicValue *= metallicTex.r; - } - } - - float roughnessValue = material.roughness; - if (hasPbrPack) { - roughnessValue *= pbrPackTex.g; - } else { - vec4 roughnessTex = enableTextures(TEXTURE_ROUGHNESS); - if (roughnessTex != vec4(-1.0)) { - roughnessValue *= roughnessTex.r; - } - } - - float aoValue = material.ao; - if (hasPbrPack) { - aoValue *= pbrPackTex.r; - } else { - vec4 aoTex = enableTextures(TEXTURE_AO); - if (aoTex != vec4(-1.0)) { - aoValue *= aoTex.r; - } - } - - metallicValue = clamp(metallicValue, 0.0, 1.0); - roughnessValue = clamp(roughnessValue, 0.0, 1.0); - aoValue = clamp(aoValue, 0.0, 1.0); - - float nonlinearDepth = gl_FragCoord.z; - gPosition = vec4(FragPos, nonlinearDepth); - - vec3 n = normalize(normal); - if (!all(equal(n, n)) || length(n) < 1e-4) { - n = normalize(Normal); - } - gNormal = vec4(n, 1.0); - - vec3 a = clamp(albedoColor, 0.0, 1.0); - if (!all(equal(a, a))) { - a = vec3(0.0); - } - gAlbedoSpec = vec4(a, aoValue); - - gMaterial = vec4(metallicValue, roughnessValue, aoValue, clamp(material.reflectivity, 0.0, 1.0)); -} diff --git a/shaders/vulkan/deferred/deferred.vert b/shaders/vulkan/deferred/deferred.vert deleted file mode 100644 index 2dd26dd0..00000000 --- a/shaders/vulkan/deferred/deferred.vert +++ /dev/null @@ -1,46 +0,0 @@ -#version 450 -layout(location = 0) in vec3 aPos; -layout(location = 1) in vec4 aColor; -layout(location = 2) in vec2 aTexCoord; -layout(location = 3) in vec3 aNormal; -layout(location = 4) in vec3 aTangent; -layout(location = 5) in vec3 aBitangent; -layout(location = 6) in mat4 instanceModel; - -layout(set = 0, binding = 0) uniform UBO { - mat4 model; - mat4 view; - mat4 projection; - bool isInstanced; -}; - -layout(location = 0) out vec4 outColor; -layout(location = 1) out vec2 TexCoord; -layout(location = 2) out vec3 Normal; -layout(location = 3) out vec3 FragPos; -layout(location = 4) out mat3 TBN; - -void main() { - mat4 finalModel; - if (isInstanced) { - finalModel = instanceModel; - } else { - finalModel = model; - } - - vec4 worldPos = finalModel * vec4(aPos, 1.0); - FragPos = worldPos.xyz; - gl_Position = projection * view * worldPos; - - // Textures are already flipped on load; keep UVs as-is for Vulkan - TexCoord = aTexCoord; - outColor = aColor; - - mat3 normalMatrix = mat3(transpose(inverse(finalModel))); - Normal = normalize(normalMatrix * aNormal); - - vec3 T = normalize(normalMatrix * aTangent); - vec3 B = normalize(normalMatrix * aBitangent); - vec3 N = normalize(normalMatrix * aNormal); - TBN = mat3(T, B, N); -} \ No newline at end of file diff --git a/shaders/vulkan/deferred/light.frag b/shaders/vulkan/deferred/light.frag deleted file mode 100644 index bc13ffc1..00000000 --- a/shaders/vulkan/deferred/light.frag +++ /dev/null @@ -1,538 +0,0 @@ -#version 450 -layout(location = 0) out vec4 FragColor; -layout(location = 1) out vec4 BrightColor; - -layout(location = 0) in vec2 TexCoord; - -layout(set = 2, binding = 0) uniform sampler2D gPosition; -layout(set = 2, binding = 1) uniform sampler2D gNormal; -layout(set = 2, binding = 2) uniform sampler2D gAlbedoSpec; -layout(set = 2, binding = 3) uniform sampler2D gMaterial; -layout(set = 2, binding = 4) uniform sampler2D ssao; - -layout(set = 2, binding = 5) uniform sampler2D texture1; -layout(set = 2, binding = 6) uniform sampler2D texture2; -layout(set = 2, binding = 7) uniform sampler2D texture3; -layout(set = 2, binding = 8) uniform sampler2D texture4; -layout(set = 2, binding = 9) uniform sampler2D texture5; - -layout(set = 3, binding = 0) uniform samplerCube cubeMap1; -layout(set = 3, binding = 1) uniform samplerCube cubeMap2; -layout(set = 3, binding = 2) uniform samplerCube cubeMap3; -layout(set = 3, binding = 3) uniform samplerCube cubeMap4; -layout(set = 3, binding = 4) uniform samplerCube cubeMap5; -layout(set = 3, binding = 5) uniform samplerCube skybox; - -struct DirectionalLight { - vec3 direction; - float _pad1; - vec3 diffuse; - float _pad2; - vec3 specular; - float intensity; -}; - -struct PointLight { - vec3 position; - float _pad1; - vec3 diffuse; - float _pad2; - vec3 specular; - float intensity; - float constant; - float linear; - float quadratic; - float radius; - float _pad3; -}; - -struct SpotLight { - vec3 position; - float _pad1; - vec3 direction; - float cutOff; - float outerCutOff; - float intensity; - float range; - float _pad4; - vec3 diffuse; - float _pad5; - vec3 specular; - float _pad6; -}; - -struct AreaLight { - vec3 position; - float _pad1; - vec3 right; - float _pad2; - vec3 up; - float _pad3; - vec2 size; - float _pad4; - float _pad5; - vec3 diffuse; - float _pad6; - vec3 specular; - float angle; - int castsBothSides; - float intensity; - float range; - float _pad9; -}; - -struct ShadowParameters { - mat4 lightView; - mat4 lightProjection; - float bias; - int textureIndex; - float farPlane; - int lightIndex; - vec3 lightPos; - int lightType; -}; - -layout(set = 1, binding = 1) uniform Environment { - float rimLightIntensity; - vec3 rimLightColor; - float bloomThreshold; -} environment; - -layout(set = 4, binding = 0) buffer DirectionalLights { - DirectionalLight directionalLights[]; -}; - -layout(set = 4, binding = 1) buffer PointLights { - PointLight pointLights[]; -}; - -layout(set = 4, binding = 2) buffer SpotLights { - SpotLight spotlights[]; -}; - -layout(set = 4, binding = 3) buffer AreaLights { - AreaLight areaLights[]; -}; - -layout(set = 5, binding = 0) buffer ShadowParams { - ShadowParameters shadowParams[]; -}; - -layout(push_constant) uniform PushConstants { - int directionalLightCount; - int pointLightCount; - int spotlightCount; - int areaLightCount; - int shadowParamCount; -}; - -layout(set = 1, binding = 0) uniform UBO { - vec3 cameraPosition; - bool useIBL; -}; - -layout(set = 1, binding = 2) uniform AmbientLight { - vec4 color; - float intensity; - vec3 _pad0; -} ambientLight; - -const float PI = 3.14159265; - -vec4 sampleTextureAt(int textureIndex, vec2 uv) { - if (textureIndex == 0) return texture(texture1, uv); - else if (textureIndex == 1) return texture(texture2, uv); - else if (textureIndex == 2) return texture(texture3, uv); - else if (textureIndex == 3) return texture(texture4, uv); - else if (textureIndex == 4) return texture(texture5, uv); - return vec4(0.0); -} - -vec4 sampleCubeTextureAt(int textureIndex, vec3 direction) { - if (textureIndex == 0) return texture(cubeMap1, direction); - else if (textureIndex == 1) return texture(cubeMap2, direction); - else if (textureIndex == 2) return texture(cubeMap3, direction); - else if (textureIndex == 3) return texture(cubeMap4, direction); - else if (textureIndex == 4) return texture(cubeMap5, direction); - return vec4(0.0); -} - -vec2 getTextureDimensions(int textureIndex) { - if (textureIndex == 0) return vec2(textureSize(texture1, 0)); - else if (textureIndex == 1) return vec2(textureSize(texture2, 0)); - else if (textureIndex == 2) return vec2(textureSize(texture3, 0)); - else if (textureIndex == 3) return vec2(textureSize(texture4, 0)); - else if (textureIndex == 4) return vec2(textureSize(texture5, 0)); - return vec2(0); -} - -float distributionGGX(vec3 N, vec3 H, float roughness) { - float a = roughness * roughness; - float a2 = a * a; - float NdotH = max(dot(N, H), 0.0); - float NdotH2 = NdotH * NdotH; - - float num = a2; - float denom = (NdotH2 * (a2 - 1.0) + 1.0); - denom = PI * denom * denom; - - return num / max(denom, 0.0001); -} - -float geometrySchlickGGX(float NdotV, float roughness) { - float r = roughness + 1.0; - float k = (r * r) / 8.0; - - float num = NdotV; - float denom = NdotV * (1.0 - k) + k; - - return num / max(denom, 0.0001); -} - -float geometrySmith(vec3 N, vec3 V, vec3 L, float roughness) { - float NdotV = max(dot(N, V), 0.0); - float NdotL = max(dot(N, L), 0.0); - float ggx2 = geometrySchlickGGX(NdotV, roughness); - float ggx1 = geometrySchlickGGX(NdotL, roughness); - return ggx1 * ggx2; -} - -vec3 fresnelSchlick(float cosTheta, vec3 F0) { - return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); -} - -float calculateShadow(ShadowParameters shadowParam, vec3 fragPos, vec3 normal) { - vec2 dims = getTextureDimensions(shadowParam.textureIndex); - if (dims.x == 0.0 || dims.y == 0.0) { - return 0.0; // No valid shadow map bound - } - - vec4 fragPosLightSpace = shadowParam.lightProjection * shadowParam.lightView * vec4(fragPos, 1.0); - vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; - // Transform from [-1,1] to [0,1] for texture sampling - projCoords = projCoords * 0.5 + 0.5; - // Flip Y because shadow map was rendered with OpenGL-style projection but sampled in Vulkan - projCoords.y = 1.0 - projCoords.y; - // Note: Shadow maps are rendered without Y-flip projection, so no Y-flip needed here - - if (projCoords.x < 0.0 || projCoords.x > 1.0 || - projCoords.y < 0.0 || projCoords.y > 1.0 || - projCoords.z > 1.0) { - return 0.0; - } - - float currentDepth = projCoords.z; - - vec3 lightDirWorld = normalize((inverse(shadowParam.lightView) * vec4(0.0, 0.0, -1.0, 0.0)).xyz); - float biasValue = shadowParam.bias; - float ndotl = max(dot(normal, lightDirWorld), 0.0); - float minBias = 0.0005; - float bias = max(biasValue * (1.0 - ndotl), minBias); - - float shadow = 0.0; - vec2 texelSize = 1.0 / dims; - - float distance = length(cameraPosition - fragPos); - vec2 shadowMapSize = dims; - float avgDim = 0.5 * (shadowMapSize.x + shadowMapSize.y); - float resFactor = clamp(1024.0 / max(avgDim, 1.0), 0.75, 1.25); - float distFactor = clamp(distance / 800.0, 0.0, 1.0); - float desiredKernel = mix(1.0, 1.5, distFactor) * resFactor; - int kernelSize = int(clamp(floor(desiredKernel + 0.5), 1.0, 2.0)); - - const vec2 poissonDisk[8] = vec2[]( - vec2(-0.326, -0.406), vec2(-0.840, -0.074), vec2(-0.696, 0.457), - vec2(-0.203, 0.621), vec2(0.962, -0.195), vec2(0.473, -0.480), - vec2(0.519, 0.767), vec2(0.185, -0.893) - ); - float texelRadius = mix(1.0, 3.0, distFactor) * resFactor; - vec2 filterRadius = texelSize * texelRadius; - - int sampleCount = 0; - for (int i = 0; i < 8; ++i) { - vec2 offset = poissonDisk[i] * filterRadius; - vec2 uv = projCoords.xy + offset; - if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) { - continue; - } - float pcfDepth = sampleTextureAt(shadowParam.textureIndex, uv).r; - shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0; - sampleCount++; - } - if (sampleCount > 0) { - shadow /= float(sampleCount); - } - - return shadow; -} - -float calculatePointShadow(ShadowParameters shadowParam, vec3 fragPos) { - vec2 dims = getTextureDimensions(shadowParam.textureIndex); - if (dims.x == 0.0 || dims.y == 0.0) { - return 0.0; // No valid shadow cubemap bound - } - vec3 fragToLight = fragPos - shadowParam.lightPos; - float currentDepth = length(fragToLight); - if (currentDepth >= shadowParam.farPlane) return 0.0; - - float bias = 0.05; - float shadow = 0.0; - float diskRadius = (1.0 + (currentDepth / shadowParam.farPlane)) * 0.05; - - const int samples = 8; - const vec3 sampleOffsetDirections[] = vec3[]( - vec3(0.5381, 0.1856, -0.4319), vec3(0.1379, 0.2486, 0.4430), - vec3(0.3371, 0.5679, -0.0057), vec3(-0.6999, -0.0451, -0.0019), - vec3(0.0689, -0.1598, -0.8547), vec3(0.0560, 0.0069, -0.1843), - vec3(-0.0146, 0.1402, 0.0762), vec3(0.0100, -0.1924, -0.0344), - vec3(-0.3577, -0.5301, -0.4358), vec3(-0.3169, 0.1063, 0.0158), - vec3(0.0103, -0.5869, 0.0046), vec3(-0.0897, -0.4940, 0.3287), - vec3(0.7119, -0.0154, -0.0918), vec3(-0.0533, 0.0596, -0.5411), - vec3(0.0352, -0.0631, 0.5460), vec3(-0.4776, 0.2847, -0.0271), - vec3(-0.1120, 0.1234, -0.7446), vec3(-0.2130, -0.0782, -0.1379), - vec3(0.2944, -0.3112, -0.2645), vec3(-0.4564, 0.4175, -0.1843) - ); - - for (int i = 0; i < samples; ++i) { - vec3 sampleDir = normalize(fragToLight + sampleOffsetDirections[i] * diskRadius); - float closestDepth = sampleCubeTextureAt(shadowParam.textureIndex, sampleDir).r * shadowParam.farPlane; - if (currentDepth - bias > closestDepth) { - shadow += 1.0; - } - } - - shadow /= float(samples); - return shadow; -} - -float shadowForLight(int lightType, int lightIndex, vec3 fragPos, vec3 normal) { - for (int i = 0; i < shadowParamCount; ++i) { - if (shadowParams[i].lightType != lightType || - shadowParams[i].lightIndex != lightIndex) continue; - float shadow = lightType == 3 - ? calculatePointShadow(shadowParams[i], fragPos) - : calculateShadow(shadowParams[i], fragPos, normal); - return clamp(shadow * 0.85, 0.0, 1.0); - } - return 0.0; -} - -vec3 evaluateBRDF(vec3 L, vec3 radiance, vec3 N, vec3 V, vec3 F0, vec3 albedo, float metallic, float roughness) { - vec3 H = normalize(V + L); - - float NDF = distributionGGX(N, H, roughness); - float G = geometrySmith(N, V, L, roughness); - vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); - - vec3 kS = F; - vec3 kD = (vec3(1.0) - kS) * (1.0 - metallic); - - float NdotV = max(dot(N, V), 0.0); - float NdotL = max(dot(N, L), 0.0); - - vec3 numerator = NDF * G * F; - float denominator = max(4.0 * NdotV * NdotL, 0.0001); - vec3 specular = numerator / denominator; - - return (kD * albedo / PI + specular) * radiance * NdotL; -} - -vec3 calcDirectionalLight(DirectionalLight light, vec3 N, vec3 V, vec3 F0, vec3 albedo, float metallic, float roughness) { - vec3 L = normalize(-light.direction); - vec3 radiance = light.diffuse * max(light.intensity, 0.0); - return evaluateBRDF(L, radiance, N, V, F0, albedo, metallic, roughness); -} - -vec3 calcPointLight(PointLight light, vec3 fragPos, vec3 N, vec3 V, vec3 F0, vec3 albedo, float metallic, float roughness) { - vec3 L = light.position - fragPos; - float distance = length(L); - vec3 direction = distance > 0.0 ? (L / distance) : vec3(0.0, 0.0, 1.0); - float attenuation = 1.0 / max(light.constant + light.linear * distance + light.quadratic * distance * distance, 0.0001); - float fade = 1.0 - smoothstep(light.radius * 0.9, light.radius, distance); - vec3 radiance = light.diffuse * max(light.intensity, 0.0) * attenuation * fade; - return evaluateBRDF(direction, radiance, N, V, F0, albedo, metallic, roughness); -} - -vec3 calcSpotLight(SpotLight light, vec3 fragPos, vec3 N, vec3 V, vec3 F0, vec3 albedo, float metallic, float roughness) { - vec3 L = light.position - fragPos; - float distance = length(L); - vec3 direction = normalize(L); - - vec3 spotDirection = normalize(light.direction); - float theta = dot(direction, -spotDirection); - float epsilon = max(light.cutOff - light.outerCutOff, 0.0001); - float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0); - - float range = max(light.range, 0.001); - float attenuation = 1.0 / (1.0 + (distance / range) + (distance * distance) / (range * range)); - float fade = 1.0 - smoothstep(range * 0.9, range, distance); - vec3 radiance = light.diffuse * max(light.intensity, 0.0) * attenuation * intensity * fade; - return evaluateBRDF(direction, radiance, N, V, F0, albedo, metallic, roughness); -} - -vec3 sampleEnvironmentRadiance(vec3 direction) { - return texture(skybox, direction).rgb; -} - -vec3 acesToneMapping(vec3 color) { - float a = 2.51; - float b = 0.03; - float c = 2.43; - float d = 0.59; - float e = 0.14; - color = (color * (a * color + b)) / (color * (c * color + d) + e); - color = pow(clamp(color, 0.0, 1.0), vec3(1.0 / 2.2)); - return color; -} - -vec3 getRimLight( - vec3 fragPos, - vec3 N, - vec3 V, - vec3 F0, - vec3 albedo, - float metallic, - float roughness -) { - N = normalize(N); - V = normalize(V); - - float rim = pow(1.0 - max(dot(N, V), 0.0), 3.0); - - rim *= mix(1.2, 0.3, roughness); - - vec3 rimColor = mix(vec3(1.0), albedo, metallic) * environment.rimLightColor; - rimColor = mix(rimColor, F0, 0.5); - - float rimIntensity = environment.rimLightIntensity; - - vec3 rimLight = rimColor * rim * rimIntensity; - - float dist = length(cameraPosition - fragPos); - rimLight /= (1.0 + dist * 0.1); - - return rimLight; -} - -void main() { - vec3 FragPos = texture(gPosition, TexCoord).xyz; - vec3 N = normalize(texture(gNormal, TexCoord).xyz); - vec4 albedoAo = texture(gAlbedoSpec, TexCoord); - vec3 albedo = albedoAo.rgb; - vec4 matData = texture(gMaterial, TexCoord); - float metallic = clamp(matData.r, 0.0, 1.0); - float roughness = clamp(matData.g, 0.0, 1.0); - float ao = clamp(matData.b, 0.0, 1.0); - - float viewDistance = max(length(cameraPosition - FragPos), 1e-6); - vec3 V = (cameraPosition - FragPos) / viewDistance; - - vec3 F0 = mix(vec3(0.04), albedo, metallic); - - float ssaoFactor = clamp(texture(ssao, TexCoord).r, 0.0, 1.0); - float ssaoDesaturated = mix(1.0, ssaoFactor, 0.35); - float occlusion = clamp(ao * (0.2 + 0.8 * ssaoDesaturated), 0.0, 1.0); - float lightingOcclusion = clamp(ssaoDesaturated, 0.25, 1.0); - - vec3 directionalResult = vec3(0.0); - for (int i = 0; i < directionalLightCount; ++i) { - float shadow = shadowForLight(0, i, FragPos, N); - directionalResult += calcDirectionalLight(directionalLights[i], N, V, F0, albedo, metallic, roughness) * (1.0 - shadow); - } - - vec3 pointResult = vec3(0.0); - for (int i = 0; i < pointLightCount; ++i) { - if (length(pointLights[i].position - FragPos) >= pointLights[i].radius) continue; - float shadow = shadowForLight(3, i, FragPos, N); - pointResult += calcPointLight(pointLights[i], FragPos, N, V, F0, albedo, metallic, roughness) * (1.0 - shadow); - } - - vec3 spotResult = vec3(0.0); - for (int i = 0; i < spotlightCount; ++i) { - if (length(spotlights[i].position - FragPos) >= spotlights[i].range) continue; - float shadow = shadowForLight(1, i, FragPos, N); - spotResult += calcSpotLight(spotlights[i], FragPos, N, V, F0, albedo, metallic, roughness) * (1.0 - shadow); - } - - vec3 areaResult = vec3(0.0); - for (int i = 0; i < areaLightCount; ++i) { - vec3 P = areaLights[i].position; - vec3 R = normalize(areaLights[i].right); - vec3 U = normalize(areaLights[i].up); - vec2 halfSize = areaLights[i].size * 0.5; - - vec3 toPoint = FragPos - P; - float s = clamp(dot(toPoint, R), -halfSize.x, halfSize.x); - float t = clamp(dot(toPoint, U), -halfSize.y, halfSize.y); - vec3 Q = P + R * s + U * t; - - vec3 Lvec = Q - FragPos; - float dist = length(Lvec); - if (dist > 0.0001) { - vec3 L = Lvec / dist; - vec3 Nl = normalize(cross(R, U)); - float ndotl = dot(Nl, -L); - - float facing = (areaLights[i].castsBothSides != 0) ? abs(ndotl) : max(ndotl, 0.0); - float cosTheta = cos(radians(areaLights[i].angle)); - - if (facing >= cosTheta && facing > 0.0) { - float range = max(areaLights[i].range, 0.001); - float attenuation = 1.0 / (1.0 + (dist / range) + (dist * dist) / (range * range)); - float fade = 1.0 - smoothstep(range * 0.9, range, dist); - vec3 radiance = areaLights[i].diffuse * max(areaLights[i].intensity, 0.0) * attenuation * facing * fade; - float shadow = shadowForLight(2, i, FragPos, N); - areaResult += evaluateBRDF(L, radiance, N, V, F0, albedo, metallic, roughness) * (1.0 - shadow); - } - } - } - vec3 rimResult = getRimLight(FragPos, N, V, F0, albedo, metallic, roughness); - vec3 lighting = (directionalResult + pointResult + spotResult + areaResult + rimResult) * lightingOcclusion; - - vec3 ambient = ambientLight.color.rgb * ambientLight.intensity * albedo * occlusion; - - vec3 iblContribution = vec3(0.0); - if (useIBL) { - vec3 irradiance = sampleEnvironmentRadiance(N); - vec3 diffuseIBL = irradiance * albedo; - - vec3 reflection = reflect(-V, N); - vec3 specularEnv = sampleEnvironmentRadiance(reflection); - - vec3 F = fresnelSchlick(max(dot(N, V), 0.0), F0); - vec3 kS = F; - vec3 kD = (vec3(1.0) - kS) * (1.0 - metallic); - - float roughnessAttenuation = mix(1.0, 0.15, clamp(roughness, 0.0, 1.0)); - vec3 specularIBL = specularEnv * roughnessAttenuation; - - iblContribution = (kD * diffuseIBL + kS * specularIBL) * occlusion; - } - - vec3 finalColor = ambient + lighting + iblContribution; - - if (!useIBL) { - vec3 I = normalize(FragPos - cameraPosition); - vec3 R = reflect(-I, N); - - vec3 F = fresnelSchlick(max(dot(N, -I), 0.0), F0); - vec3 kS = F; - vec3 kD = (vec3(1.0) - kS) * (1.0 - metallic); - - vec3 envColor = texture(skybox, R).rgb; - vec3 reflection = envColor * kS; - - finalColor = mix(finalColor, reflection, F0); - } - - FragColor = vec4(finalColor, 1.0); - - float brightness = dot(FragColor.rgb, vec3(0.2126, 0.7152, 0.0722)); - if (brightness > environment.bloomThreshold) { - BrightColor = vec4(FragColor.rgb, 1.0); - } else { - BrightColor = vec4(0.0, 0.0, 0.0, 1.0); - } - - FragColor.rgb = acesToneMapping(FragColor.rgb); -} diff --git a/shaders/vulkan/deferred/light.vert b/shaders/vulkan/deferred/light.vert deleted file mode 100644 index a08bedf5..00000000 --- a/shaders/vulkan/deferred/light.vert +++ /dev/null @@ -1,11 +0,0 @@ -#version 450 -layout(location = 0) in vec3 aPos; -layout(location = 2) in vec2 aTexCoord; - -layout(location = 0) out vec2 TexCoord; - -void main() { - // Pass through UVs; G-buffer was rendered with the same orientation - TexCoord = aTexCoord; - gl_Position = vec4(aPos, 1.0); -} diff --git a/shaders/vulkan/effects/downsample.frag b/shaders/vulkan/effects/downsample.frag deleted file mode 100644 index bfcbcde4..00000000 --- a/shaders/vulkan/effects/downsample.frag +++ /dev/null @@ -1,38 +0,0 @@ -#version 450 - -layout(set = 2, binding = 0) uniform sampler2D srcTexture; -layout(set = 1, binding = 0) uniform Params { - vec2 srcResolution; -}; - -layout(location = 0) in vec2 TexCoord; -layout(location = 0) out vec3 downsample; - -void main() { - vec2 srcTexelSize = 1.0 / srcResolution; - float x = srcTexelSize.x; - float y = srcTexelSize.y; - vec2 texCoord = TexCoord; - - vec3 a = texture(srcTexture, vec2(texCoord.x - 2 * x, texCoord.y + 2 * y)).rgb; - vec3 b = texture(srcTexture, vec2(texCoord.x, texCoord.y + 2 * y)).rgb; - vec3 c = texture(srcTexture, vec2(texCoord.x + 2 * x, texCoord.y + 2 * y)).rgb; - - vec3 d = texture(srcTexture, vec2(texCoord.x - 2 * x, texCoord.y)).rgb; - vec3 e = texture(srcTexture, vec2(texCoord.x, texCoord.y)).rgb; - vec3 f = texture(srcTexture, vec2(texCoord.x + 2 * x, texCoord.y)).rgb; - - vec3 g = texture(srcTexture, vec2(texCoord.x - 2 * x, texCoord.y - 2 * y)).rgb; - vec3 h = texture(srcTexture, vec2(texCoord.x, texCoord.y - 2 * y)).rgb; - vec3 i = texture(srcTexture, vec2(texCoord.x + 2 * x, texCoord.y - 2 * y)).rgb; - - vec3 j = texture(srcTexture, vec2(texCoord.x - x, texCoord.y + y)).rgb; - vec3 k = texture(srcTexture, vec2(texCoord.x + x, texCoord.y + y)).rgb; - vec3 l = texture(srcTexture, vec2(texCoord.x - x, texCoord.y - y)).rgb; - vec3 m = texture(srcTexture, vec2(texCoord.x + x, texCoord.y - y)).rgb; - - downsample = e * 0.125; - downsample += (a + c + g + i) * 0.03125; - downsample += (b + d + f + h) * 0.0625; - downsample += (j + k + l + m) * 0.125; -} diff --git a/shaders/vulkan/effects/gaussian.frag b/shaders/vulkan/effects/gaussian.frag deleted file mode 100644 index b6c8d9e5..00000000 --- a/shaders/vulkan/effects/gaussian.frag +++ /dev/null @@ -1,34 +0,0 @@ -#version 450 -layout(location = 0) out vec4 FragColor; - -layout(location = 0) in vec2 TexCoord; - -layout(set = 2, binding = 0) uniform sampler2D image; - -layout(set = 1, binding = 0) uniform Params { - bool horizontal; - float weight[5]; - float radius; -}; - -void main() { - vec2 tex_offset = 1.0 / textureSize(image, 0) * radius; - vec3 result = texture(image, TexCoord).rgb * weight[0]; - if(horizontal) - { - for(int i = 1; i < 5; ++i) - { - result += texture(image, TexCoord + vec2(tex_offset.x * i, 0.0)).rgb * weight[i]; - result += texture(image, TexCoord - vec2(tex_offset.x * i, 0.0)).rgb * weight[i]; - } - } - else - { - for(int i = 1; i < 5; ++i) - { - result += texture(image, TexCoord + vec2(0.0, tex_offset.y * i)).rgb * weight[i]; - result += texture(image, TexCoord - vec2(0.0, tex_offset.y * i)).rgb * weight[i]; - } - } - FragColor = vec4(result, 1.0); -} \ No newline at end of file diff --git a/shaders/vulkan/effects/particle.frag b/shaders/vulkan/effects/particle.frag deleted file mode 100644 index 1a2272f9..00000000 --- a/shaders/vulkan/effects/particle.frag +++ /dev/null @@ -1,27 +0,0 @@ -#version 450 -layout(location = 0) in vec2 fragTexCoord; -layout(location = 1) in vec4 fragColor; - -layout(location = 0) out vec4 FragColor; - -layout(set = 2, binding = 0) uniform sampler2D particleTexture; -layout(set = 1, binding = 0) uniform Params { - bool useTexture; -}; - -void main() { - if (useTexture) { - vec4 texColor = texture(particleTexture, fragTexCoord); - if (texColor.a < 0.01) discard; - FragColor = texColor * fragColor; - } else { - vec2 center = vec2(0.5, 0.5); - float dist = distance(fragTexCoord, center); - - float alpha = 1.0 - smoothstep(0.3, 0.5, dist); - - FragColor = vec4(fragColor.rgb, fragColor.a * alpha); - - if (FragColor.a < 0.01) discard; - } -} \ No newline at end of file diff --git a/shaders/vulkan/effects/particle.vert b/shaders/vulkan/effects/particle.vert deleted file mode 100644 index 952ebdd1..00000000 --- a/shaders/vulkan/effects/particle.vert +++ /dev/null @@ -1,42 +0,0 @@ -#version 450 - -layout(location = 0) in vec3 quadVertex; -layout(location = 1) in vec2 texCoord; - -layout(location = 2) in vec3 particlePos; -layout(location = 3) in vec4 particleColor; -layout(location = 4) in float particleSize; - -layout(set = 0, binding = 0) uniform UniformBufferObject { - mat4 view; - mat4 projection; - mat4 model; - bool isAmbient; -}; - -layout(location = 0) out vec2 fragTexCoord; -layout(location = 1) out vec4 fragColor; - -void main() { - if (isAmbient) { - vec4 viewParticlePos = view * vec4(particlePos, 1.0); - - vec3 viewPosition = - viewParticlePos.xyz + - vec3(quadVertex.x * particleSize, quadVertex.y * particleSize, 0.0); - - gl_Position = projection * model * vec4(viewPosition, 1.0); - } else { - vec3 cameraRight = vec3(view[0][0], view[1][0], view[2][0]); - vec3 cameraUp = vec3(view[0][1], view[1][1], view[2][1]); - - vec3 worldPosition = particlePos + - (quadVertex.x * cameraRight * particleSize) + - (quadVertex.y * cameraUp * particleSize); - - gl_Position = projection * view * vec4(worldPosition, 1.0); - } - - fragTexCoord = texCoord; - fragColor = particleColor; -} \ No newline at end of file diff --git a/shaders/vulkan/effects/skybox.frag b/shaders/vulkan/effects/skybox.frag deleted file mode 100644 index 1fb5624f..00000000 --- a/shaders/vulkan/effects/skybox.frag +++ /dev/null @@ -1,237 +0,0 @@ -#version 450 -layout(location = 0) out vec4 FragColor; -layout(location = 0) in vec3 TexCoords; - -layout(set = 2, binding = 0) uniform samplerCube skybox; - -layout(set = 1, binding = 0) uniform Params { - vec3 sunDirection; - vec4 sunColor; - vec3 moonDirection; - vec4 moonColor; - int hasDayNight; -}; - -layout(set = 1, binding = 1) uniform AtmosphereParams { - float sunTintStrength; - float moonTintStrength; - float sunSizeMultiplier; - float moonSizeMultiplier; - float starDensity; -}; - -float hash21(vec2 p) { - p = fract(p * vec2(123.34, 456.21)); - p += dot(p, p + 45.32); - return fract(p.x * p.y); -} - -float valueNoise(vec2 p) { - vec2 i = floor(p); - vec2 f = fract(p); - f = f * f * (3.0 - 2.0 * f); - - float a = hash21(i); - float b = hash21(i + vec2(1.0, 0.0)); - float c = hash21(i + vec2(0.0, 1.0)); - float d = hash21(i + vec2(1.0, 1.0)); - - return mix(mix(a, b, f.x), mix(c, d, f.x), f.y); -} - -float layeredNoise(vec2 p) { - float total = valueNoise(p) + valueNoise(p * 2.0) * 0.5; - return total / 1.5; -} - -float hash13(vec3 p) { - p = fract(p * 443.897); - p += dot(p, p.yzx + 19.19); - return fract((p.x + p.y) * p.z); -} - -vec3 generateStars(vec3 dir, float density, float nightFactor) { - if (density <= 0.0 || nightFactor <= 0.0) { - return vec3(0.0); - } - - vec3 starSpace = dir * 50.0; - vec3 cell = floor(starSpace); - vec3 localPos = fract(starSpace); - - float rand = hash13(cell); - - if (rand < density * 0.3) { - float randX = hash13(cell + vec3(12.34, 56.78, 90.12)); - float randY = hash13(cell + vec3(23.45, 67.89, 1.23)); - float randZ = hash13(cell + vec3(34.56, 78.90, 12.34)); - - vec3 starPos = vec3(randX, randY, randZ); - float dist = length(localPos - starPos); - - float starSize = 0.02 + hash13(cell + vec3(45.67, 89.01, 23.45)) * 0.03; - float brightness = 0.5 + hash13(cell + vec3(56.78, 90.12, 34.56)) * 0.5; - - float star = smoothstep(starSize, 0.0, dist) * brightness; - float twinkle = 0.8 + 0.2 * sin(hash13(cell + vec3(67.89, 1.23, 45.67)) * 100.0); - star *= twinkle * nightFactor; - - vec3 starColor = vec3(1.0); - if (rand > 0.9) starColor = vec3(0.8, 0.9, 1.0); - else if (rand > 0.8) starColor = vec3(1.0, 0.9, 0.8); - - return starColor * star; - } - - return vec3(0.0); -} - -vec3 generateMoonTexture(vec2 uv, float distanceFromCenter, vec3 tintColor) { - float angle = 0.5; - float ca = cos(angle); - float sa = sin(angle); - uv = vec2(ca * uv.x - sa * uv.y, sa * uv.x + ca * uv.y); - - float largeFeatures = valueNoise(uv * 2.0); - largeFeatures = smoothstep(0.3, 0.7, largeFeatures); - - float mediumCraters = valueNoise(uv * 8.0); - - vec2 craterUV = uv * 6.0; - vec2 craterCell = floor(craterUV); - vec2 craterLocal = fract(craterUV); - - float craters = 1.0; - for (int i = 0; i < 4; i++) { - vec2 neighbor = vec2(float(i % 2), float(i / 2)); - vec2 cellPoint = craterCell + neighbor; - - vec2 craterCenter = vec2(hash21(cellPoint), hash21(cellPoint + vec2(13.7, 27.3))); - float dist = length(craterLocal - neighbor - craterCenter); - - float craterSize = 0.15 + 0.25 * hash21(cellPoint + vec2(5.3, 9.7)); - - if (dist < craterSize) { - float crater = smoothstep(craterSize, craterSize * 0.3, dist); - craters = min(craters, 1.0 - crater * 0.7); - } - } - - float surface = largeFeatures * 0.5 + mediumCraters * 0.5; - surface *= craters; - - float intensity = mix(0.30, 0.75, surface); - - float limb = 1.0 - smoothstep(0.6, 1.0, distanceFromCenter); - intensity *= 0.4 + 0.6 * limb; - intensity *= 1.3; - - return clamp(tintColor * intensity, 0.0, 1.0); -} - -void main() -{ - vec3 dir = normalize(TexCoords); - vec3 color = texture(skybox, TexCoords).rgb; - - if (hasDayNight == 1) { - vec3 normSunDir = normalize(sunDirection); - vec3 normMoonDir = normalize(moonDirection); - - float sunDot = dot(dir, normSunDir); - float moonDot = dot(dir, normMoonDir); - - float nightFactor = smoothstep(0.15, -0.2, sunDirection.y); - - if (starDensity > 0.0) { - color += generateStars(dir, starDensity, nightFactor); - } - - float sunHorizonFade = smoothstep(-0.15, 0.05, sunDirection.y); - - if (sunDirection.y > -0.15) { - float sizeAdjust = 1.0 - (sunSizeMultiplier - 1.0) * 0.001; - float sunSize = 0.9995 * sizeAdjust; - float sunGlowSize = 0.998 * (1.0 - (sunSizeMultiplier - 1.0) * 0.003); - float sunHaloSize = 0.99 * (1.0 - (sunSizeMultiplier - 1.0) * 0.015); - - float sunDisk = smoothstep(sunSize - 0.0002, sunSize, sunDot); - float sunGlow = smoothstep(sunGlowSize, sunSize, sunDot) * (1.0 - sunDisk); - float sunHalo = smoothstep(sunHaloSize, sunSize, sunDot) * - (1.0 - smoothstep(sunSize, sunGlowSize, sunDot)); - - float horizonBoost = smoothstep(0.1, -0.05, sunDirection.y) * 2.0; - sunHalo *= (0.3 + horizonBoost); - - color += sunColor.rgb * (sunDisk * 5.0 + sunGlow * 0.5 + sunHalo) * sunHorizonFade; - } - - float moonHorizonFade = smoothstep(-0.15, 0.05, moonDirection.y); - - if (moonDirection.y > -0.15) { - float sizeAdjust = 1.0 - (moonSizeMultiplier - 1.0) * 0.001; - float moonSize = 0.9996 * sizeAdjust; - float moonGlowSize = 0.9985 * (1.0 - (moonSizeMultiplier - 1.0) * 0.003); - float moonHaloSize = 0.992 * (1.0 - (moonSizeMultiplier - 1.0) * 0.015); - - float moonDisk = smoothstep(moonSize - 0.0002, moonSize, moonDot); - - if (moonDisk > 0.01) { - vec3 up = abs(normMoonDir.y) < 0.999 ? vec3(0.0, 1.0, 0.0) : vec3(1.0, 0.0, 0.0); - vec3 right = normalize(cross(up, normMoonDir)); - vec3 actualUp = cross(normMoonDir, right); - - vec3 relativeDir = dir - normMoonDir * moonDot; - float u = dot(relativeDir, right); - float v = dot(relativeDir, actualUp); - - float distFromCenter = length(vec2(u, v)) / sqrt(1.0 - moonSize * moonSize); - - if (distFromCenter < 1.0) { - vec2 moonUV = vec2(u, v) * 200.0; - vec3 moonTexture = generateMoonTexture(moonUV, distFromCenter, moonColor.rgb); - color += moonTexture * moonDisk * 1.5 * moonHorizonFade; - } else { - color += moonColor.rgb * moonDisk * 1.5 * moonHorizonFade; - } - } - - float moonGlow = smoothstep(moonGlowSize, moonSize, moonDot) * (1.0 - moonDisk); - float moonHalo = smoothstep(moonHaloSize, moonSize, moonDot) * - (1.0 - smoothstep(moonSize, moonGlowSize, moonDot)); - - float moonHorizonBoost = smoothstep(0.1, -0.05, moonDirection.y) * 2.0; - moonHalo *= (0.2 + moonHorizonBoost); - - color += moonColor.rgb * (moonGlow * 0.3 + moonHalo) * moonHorizonFade; - } - - if (sunDirection.y > -0.1 && sunTintStrength > 0.0) { - float sunSkyInfluence = smoothstep(0.7, 0.95, sunDot) * - smoothstep(-0.1, 0.2, sunDirection.y); - color = mix(color, color * sunColor.rgb, sunSkyInfluence * 0.3 * sunTintStrength); - - float sunProximity = smoothstep(0.3, 0.8, sunDot) * - smoothstep(-0.1, 0.3, sunDirection.y); - color += sunColor.rgb * sunProximity * 0.15 * sunTintStrength; - - float globalSunTint = smoothstep(-0.1, 0.5, sunDirection.y); - color = mix(color, sunColor.rgb, globalSunTint * sunTintStrength * 0.08); - } - - if (moonDirection.y > -0.1 && moonTintStrength > 0.0) { - float moonSkyInfluence = smoothstep(0.8, 0.95, moonDot) * - smoothstep(-0.1, 0.2, moonDirection.y); - color = mix(color, color * moonColor.rgb, moonSkyInfluence * 0.2 * moonTintStrength); - - float moonProximity = smoothstep(0.5, 0.85, moonDot) * - smoothstep(-0.1, 0.3, moonDirection.y); - color += moonColor.rgb * moonProximity * 0.08 * moonTintStrength; - - float globalMoonTint = smoothstep(-0.1, 0.5, moonDirection.y); - color = mix(color, moonColor.rgb, globalMoonTint * moonTintStrength * 0.05); - } - } - - FragColor = vec4(color, 1.0); -} \ No newline at end of file diff --git a/shaders/vulkan/effects/skybox.vert b/shaders/vulkan/effects/skybox.vert deleted file mode 100644 index 6a81ed63..00000000 --- a/shaders/vulkan/effects/skybox.vert +++ /dev/null @@ -1,17 +0,0 @@ -#version 450 -layout(location = 0) in vec3 aPos; - -layout(location = 0) out vec3 TexCoords; - -layout(set = 0, binding = 0) uniform UniformBufferObject { - mat4 projection; - mat4 view; -}; - -void main() { - TexCoords = aPos; - // Drop translation so the cube stays centered on the camera - mat4 viewNoTranslation = mat4(mat3(view)); - vec4 pos = projection * viewNoTranslation * vec4(aPos, 1.0); - gl_Position = pos.xyww; -} diff --git a/shaders/vulkan/effects/ssr.frag b/shaders/vulkan/effects/ssr.frag deleted file mode 100644 index 24034f79..00000000 --- a/shaders/vulkan/effects/ssr.frag +++ /dev/null @@ -1,266 +0,0 @@ -#version 450 -layout(location = 0) in vec2 TexCoord; - -layout(location = 0) out vec4 FragColor; - -layout(set = 2, binding = 0) uniform sampler2D gPosition; -layout(set = 2, binding = 1) uniform sampler2D gNormal; -layout(set = 2, binding = 2) uniform sampler2D gAlbedoSpec; -layout(set = 2, binding = 3) uniform sampler2D gMaterial; -layout(set = 2, binding = 4) uniform sampler2D sceneColor; -layout(set = 2, binding = 5) uniform sampler2D gDepth; -layout(set = 2, binding = 6) uniform sampler2D historyTexture; -layout(set = 3, binding = 0) uniform samplerCube skybox; - -layout(set = 1, binding = 0) uniform Uniforms { - mat4 inverseProjection; - mat4 inverseView; - mat4 projection; - mat4 view; - vec3 cameraPosition; -}; - -layout(set = 1, binding = 1) uniform SSRParameters { - float maxDistance; - float resolution; - int steps; - float thickness; - float maxRoughness; - float historyWeight; - int debugMode; -}; - -const float PI = 3.14159265359; - -float LinearizeDepth(float depth, float near, float far) { - float z = depth * 2.0 - 1.0; - return (2.0 * near * far) / (far + near - z * (far - near)); -} - -float hash(vec2 p) { - vec3 p3 = fract(vec3(p.xyx) * 0.1031); - p3 += dot(p3, p3.yzx + 33.33); - return fract((p3.x + p3.y) * p3.z); -} - -vec3 fresnelSchlick(float cosTheta, vec3 F0) { - return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); -} - -vec3 sampleSkyReflection(vec3 normal, vec3 viewDir, vec3 albedo, float metallic) { - vec3 reflected = reflect(-normalize(viewDir), normalize(normal)); - vec3 skyColor = texture(skybox, reflected).rgb; - float skyLuma = dot(skyColor, vec3(0.2126, 0.7152, 0.0722)); - if (skyLuma < 0.001) { - float t = clamp(reflected.y * 0.5 + 0.5, 0.0, 1.0); - vec3 horizon = vec3(0.74, 0.79, 0.88); - vec3 zenith = vec3(0.50, 0.64, 0.84); - skyColor = mix(horizon, zenith, t); - } - float tintStrength = metallic * 0.35; - vec3 tint = mix(vec3(1.0), albedo, tintStrength); - return skyColor * tint; -} - -vec4 SSR(vec3 worldPos, vec3 normal, vec3 viewDir, float roughness, float metallic, float reflectivity, vec3 albedo) { - vec3 viewPos = (view * vec4(worldPos, 1.0)).xyz; - vec3 viewNormal = normalize((view * vec4(normal, 0.0)).xyz); - float mirrorFactor = clamp(max(metallic, reflectivity) * (1.0 - roughness), 0.0, 1.0); - vec3 skyReflection = sampleSkyReflection(normal, viewDir, albedo, metallic); - - vec3 viewDirection = normalize(viewPos); - vec3 viewReflect = normalize(reflect(viewDirection, viewNormal)); - - if (viewReflect.z > 0.0) { - return vec4(0.0); - } - - vec3 rayOrigin = viewPos + viewNormal * 0.01; - vec3 rayDir = viewReflect; - - float stepSize = maxDistance / float(steps); - vec3 currentPos = rayOrigin; - - float jitter = hash(gl_FragCoord.xy) * roughness * 0.25; - currentPos += rayDir * stepSize * jitter; - - vec2 hitUV = vec2(-1.0); - float hitDepth = 0.0; - bool hit = false; - vec2 fallbackUV = TexCoord; - bool hasFallbackUV = false; - - vec3 lastPos = currentPos; - - for (int i = 0; i < steps; i++) { - float t = float(i) / float(steps); - float adaptiveStep = mix(0.3, 1.0, t); - currentPos += rayDir * stepSize * adaptiveStep; - - vec4 projectedPos = projection * vec4(currentPos, 1.0); - projectedPos.xyz /= projectedPos.w; - vec2 screenUV = projectedPos.xy * 0.5 + 0.5; - - if (screenUV.x >= 0.0 && screenUV.x <= 1.0 && - screenUV.y >= 0.0 && screenUV.y <= 1.0) { - fallbackUV = screenUV; - hasFallbackUV = true; - } else { - break; - } - - float hierarchyLevel = 0.0; - float rawDepth = texture(gDepth, screenUV).r; - if (rawDepth >= 0.9999) { - currentPos += rayDir * stepSize * (exp2(hierarchyLevel) - 1.0); - lastPos = currentPos; - continue; - } - - vec3 sampleWorldPos = texture(gPosition, screenUV).xyz; - vec3 sampleNormal = texture(gNormal, screenUV).xyz; - if (dot(sampleNormal, sampleNormal) < 0.01) { - lastPos = currentPos; - continue; - } - if (length(sampleWorldPos - worldPos) < 0.08) { - lastPos = currentPos; - continue; - } - vec3 sampleViewPos = (view * vec4(sampleWorldPos, 1.0)).xyz; - - float sampleDepth = -sampleViewPos.z; - float currentDepth = -currentPos.z; - vec3 sampleViewNormal = normalize((view * vec4(sampleNormal, 0.0)).xyz); - if (dot(sampleViewNormal, viewNormal) > 0.92 && - abs(sampleDepth - currentDepth) < thickness * 1.5) { - lastPos = currentPos; - continue; - } - - float depthDiff = sampleDepth - currentDepth; - - if (depthDiff > 0.0 && depthDiff < thickness) { - vec3 binarySearchStart = lastPos; - vec3 binarySearchEnd = currentPos; - - for (int j = 0; j < 8; j++) { - vec3 midPoint = (binarySearchStart + binarySearchEnd) * 0.5; - - vec4 midProj = projection * vec4(midPoint, 1.0); - midProj.xyz /= midProj.w; - vec2 midUV = midProj.xy * 0.5 + 0.5; - if (midUV.x < 0.0 || midUV.x > 1.0 || midUV.y < 0.0 || midUV.y > 1.0) { - break; - } - - float midRawDepth = texture(gDepth, midUV).r; - if (midRawDepth >= 0.9999) { - binarySearchStart = midPoint; - continue; - } - - vec3 midSampleWorldPos = texture(gPosition, midUV).xyz; - vec3 midSampleViewPos = (view * vec4(midSampleWorldPos, 1.0)).xyz; - float midSampleDepth = -midSampleViewPos.z; - float midCurrentDepth = -midPoint.z; - - if (midCurrentDepth < midSampleDepth) { - binarySearchStart = midPoint; - } else { - binarySearchEnd = midPoint; - } - } - - vec4 finalProj = projection * vec4(binarySearchEnd, 1.0); - finalProj.xyz /= finalProj.w; - hitUV = finalProj.xy * 0.5 + 0.5; - hitDepth = length(currentPos - rayOrigin); - hit = true; - break; - } - - lastPos = currentPos; - } - - if (!hit) { - return vec4(0.0); - } - - vec3 hitColor = texture(sceneColor, hitUV).rgb; - float tintStrength = metallic * 0.35; - vec3 metalTint = mix(vec3(1.0), albedo, tintStrength); - hitColor *= metalTint; - float hitDepthRaw = texture(gDepth, hitUV).r; - vec3 hitNormalSample = texture(gNormal, hitUV).xyz; - float hitNormalLenSq = dot(hitNormalSample, hitNormalSample); - vec3 hitNormalDir = hitNormalLenSq > 1e-5 - ? hitNormalSample * inversesqrt(hitNormalLenSq) - : -rayDir; - float geometryValidity = 1.0 - smoothstep(0.998, 1.0, hitDepthRaw); - geometryValidity *= smoothstep(0.01, 0.1, hitNormalLenSq); - float normalFacing = max(dot(hitNormalDir, -rayDir), 0.0); - geometryValidity *= smoothstep(0.05, 0.25, normalFacing); - float hitLuma = dot(hitColor, vec3(0.2126, 0.7152, 0.0722)); - float skyLuma = dot(skyReflection, vec3(0.2126, 0.7152, 0.0722)); - float luminanceValidity = smoothstep(0.002, 0.03, hitLuma + skyLuma * 0.1); - - vec2 edgeFade = smoothstep(0.0, 0.15, hitUV) * (1.0 - smoothstep(0.85, 1.0, hitUV)); - float edgeFactor = edgeFade.x * edgeFade.y; - - float distanceFade = 1.0 - smoothstep(maxDistance * 0.5, maxDistance, hitDepth); - - float roughnessFade = 1.0 - smoothstep(0.0, maxRoughness, roughness); - float hitConfidence = edgeFactor * distanceFade * roughnessFade; - hitConfidence *= geometryValidity * luminanceValidity; - - vec3 F0 = mix(vec3(0.04), albedo, metallic); - vec3 V = normalize(viewDir); - float cosTheta = max(dot(normal, V), 0.0); - vec3 fresnel = fresnelSchlick(cosTheta, F0); - float fresnelFactor = (fresnel.r + fresnel.g + fresnel.b) / 3.0; - float fresnelWeight = mix(fresnelFactor, 1.0, mirrorFactor); - - vec3 reflectionColor = mix(skyReflection, hitColor, hitConfidence); - float finalFade = mix(hitConfidence * fresnelWeight, 1.0, mirrorFactor); - finalFade = clamp(finalFade, 0.0, 1.0); - - return vec4(reflectionColor, finalFade); -} - -void main() { - vec3 worldPos = texture(gPosition, TexCoord).xyz; - vec3 normal = normalize(texture(gNormal, TexCoord).xyz); - vec3 albedo = texture(gAlbedoSpec, TexCoord).rgb; - vec4 material = texture(gMaterial, TexCoord); - - float metallic = material.r; - float roughness = material.g; - float reflectivity = material.a; - - if (length(normal) < 0.001) { - FragColor = vec4(0.0, 0.0, 0.0, 0.0); - return; - } - - if (roughness > maxRoughness || max(metallic, reflectivity) < 0.02) { - FragColor = vec4(0.0, 0.0, 0.0, 0.0); - return; - } - - vec3 viewDir = normalize(cameraPosition - worldPos); - - vec4 reflection = SSR(worldPos, normal, viewDir, roughness, metallic, reflectivity, albedo); - if (debugMode != 0) { - FragColor = vec4(1.0 - reflection.a, reflection.a, 0.0, 1.0); - return; - } - if (reflection.a > 0.0 && historyWeight > 0.0) { - vec4 history = texture(historyTexture, TexCoord); - float validHistory = step(0.001, history.a); - reflection = mix(reflection, history, - historyWeight * validHistory * reflection.a); - } - - FragColor = reflection; -} diff --git a/shaders/vulkan/effects/ssr_blur.frag b/shaders/vulkan/effects/ssr_blur.frag deleted file mode 100644 index 54666ce5..00000000 --- a/shaders/vulkan/effects/ssr_blur.frag +++ /dev/null @@ -1,3 +0,0 @@ -#version 450 - -void main() {} \ No newline at end of file diff --git a/shaders/vulkan/effects/upsample.frag b/shaders/vulkan/effects/upsample.frag deleted file mode 100644 index 005051aa..00000000 --- a/shaders/vulkan/effects/upsample.frag +++ /dev/null @@ -1,32 +0,0 @@ -#version 450 - -layout(set = 2, binding = 0) uniform sampler2D srcTexture; -layout(set = 1, binding = 0) uniform Params { - vec2 srcResolution; - float filterRadius; -}; - -layout(location = 0) in vec2 TexCoord; -layout(location = 0) out vec3 upsample; - -void main() { - vec2 texelSize = 1.0 / srcResolution; - float x = filterRadius * texelSize.x; - float y = filterRadius * texelSize.y; - - vec2 texCoord = TexCoord; - vec3 a = texture(srcTexture, vec2(texCoord.x - x, texCoord.y + y)).rgb; - vec3 b = texture(srcTexture, vec2(texCoord.x, texCoord.y + y)).rgb; - vec3 c = texture(srcTexture, vec2(texCoord.x + x, texCoord.y + y)).rgb; - vec3 d = texture(srcTexture, vec2(texCoord.x - x, texCoord.y)).rgb; - vec3 e = texture(srcTexture, vec2(texCoord.x, texCoord.y)).rgb; - vec3 f = texture(srcTexture, vec2(texCoord.x + x, texCoord.y)).rgb; - vec3 g = texture(srcTexture, vec2(texCoord.x - x, texCoord.y - y)).rgb; - vec3 h = texture(srcTexture, vec2(texCoord.x, texCoord.y - y)).rgb; - vec3 i = texture(srcTexture, vec2(texCoord.x + x, texCoord.y - y)).rgb; - - upsample = e * 4.0; - upsample += (b + d + f + h) * 2.0; - upsample += (a + c + g + i); - upsample *= 1.0 / 16.0; -} diff --git a/shaders/vulkan/fullscreen.frag b/shaders/vulkan/fullscreen.frag deleted file mode 100644 index 543afc35..00000000 --- a/shaders/vulkan/fullscreen.frag +++ /dev/null @@ -1,902 +0,0 @@ -#version 450 - -layout(location = 0) in vec2 TexCoord; - -layout(location = 0) out vec4 FragColor; - -const int TEXTURE_COLOR = 0; -const int TEXTURE_DEPTH = 3; -const int TEXTURE_CUBE_DEPTH = 4; - -const int EFFECT_INVERSION = 0; -const int EFFECT_GRAYSCALE = 1; -const int EFFECT_SHARPEN = 2; -const int EFFECT_BLUR = 3; -const int EFFECT_EDGE_DETECTION = 4; -const int EFFECT_COLOR_CORRECTION = 5; -const int EFFECT_MOTION_BLUR = 6; -const int EFFECT_CHROMATIC_ABERRATION = 7; -const int EFFECT_POSTERIZATION = 8; -const int EFFECT_PIXELATION = 9; -const int EFFECT_DILATION = 10; -const int EFFECT_FILM_GRAIN = 11; - -const float offset = 1.0 / 300.0; -const float exposure = 1.0; - -vec3 reinhardToneMapping(vec3 hdrColor) { - vec3 color = vec3(1.0) - exp(-hdrColor * 1.0); - color = pow(color, vec3(1.0 / 2.2)); - return color; -} - -vec3 acesToneMapping(vec3 color) { - float a = 2.51; - float b = 0.03; - float c = 2.43; - float d = 0.59; - float e = 0.14; - return clamp((color * (a * color + b)) / (color * (c * color + d) + e), 0.0, 1.0); -} - -vec4 sharpen(sampler2D image) { - vec2 offsets[9] = vec2[]( - vec2(-offset, offset), - vec2(0.0f, offset), - vec2(offset, offset), - vec2(-offset, 0.0f), - vec2(0.0f, 0.0f), - vec2(offset, 0.0f), - vec2(-offset, -offset), - vec2(0.0f, -offset), - vec2(offset, -offset) - ); - - float kernel[9] = float[]( - -1, -1, -1, - -1, 9, -1, - -1, -1, -1 - ); - - vec3 sampleTex[9]; - for (int i = 0; i < 9; i++) { - sampleTex[i] = vec3(texture(image, TexCoord.st + offsets[i])); - } - - vec3 col = vec3(0.0); - for (int i = 0; i < 9; i++) { - col += sampleTex[i] * kernel[i]; - } - - return vec4(col, 1.0); -} - -vec4 blur(sampler2D image, float radius) { - vec2 texelSize = 1.0 / textureSize(image, 0); - vec3 result = vec3(0.0); - float total = 0.0; - - float sigma = radius * 0.5; - float twoSigmaSq = 2.0 * sigma * sigma; - - for (int x = -int(radius); x <= int(radius); x++) { - float weight = exp(-(x * x) / twoSigmaSq); - vec2 offset = vec2(x, 0.0) * texelSize; - result += texture(image, TexCoord + offset).rgb * weight; - total += weight; - } - - result /= total; - - return vec4(result, 1.0); -} - -vec4 edgeDetection(sampler2D image) { - vec2 offsets[9] = vec2[]( - vec2(-offset, offset), - vec2(0.0f, offset), - vec2(offset, offset), - vec2(-offset, 0.0f), - vec2(0.0f, 0.0f), - vec2(offset, 0.0f), - vec2(-offset, -offset), - vec2(0.0f, -offset), - vec2(offset, -offset) - ); - - float kernel[9] = float[]( - 1, 1, 1, - 1, -8, 1, - 1, 1, 1 - ); - - vec3 sampleTex[9]; - for (int i = 0; i < 9; i++) { - sampleTex[i] = vec3(texture(image, TexCoord.st + offsets[i])); - } - - vec3 col = vec3(0.0); - for (int i = 0; i < 9; i++) { - col += sampleTex[i] * kernel[i]; - } - - return vec4(col, 1.0); -} - -// Uniforms - -layout(set = 2, binding = 0) uniform sampler2D Texture; -layout(set = 2, binding = 1) uniform sampler2D BrightTexture; -layout(set = 2, binding = 2) uniform sampler2D DepthTexture; -layout(set = 2, binding = 3) uniform sampler2D VolumetricLightTexture; -layout(set = 2, binding = 4) uniform sampler2D PositionTexture; -layout(set = 2, binding = 5) uniform sampler2D LUTTexture; -layout(set = 2, binding = 6) uniform sampler2D SSRTexture; -layout(set = 2, binding = 7) uniform sampler3D cloudsTexture; - -layout(push_constant) uniform PushConstants { - int hasBrightTexture; - int hasDepthTexture; - int hasVolumetricLightTexture; - int hasPositionTexture; - int hasLUTTexture; - int hasSSRTexture; - int TextureType; - float lutSize; - - int EffectCount; -}; - -layout(std430, set = 3, binding = 0) buffer EffectBuffer { - int Effects[]; -}; - -layout(std430, set = 3, binding = 1) buffer EffectFloat1Buffer { - float EffectFloat1[]; -}; - -layout(std430, set = 3, binding = 2) buffer EffectFloat2Buffer { - float EffectFloat2[]; -}; - -layout(std430, set = 3, binding = 3) buffer EffectFloat3Buffer { - float EffectFloat3[]; -}; - -layout(std430, set = 3, binding = 4) buffer EffectFloat4Buffer { - float EffectFloat4[]; -}; - -layout(std430, set = 3, binding = 5) buffer EffectFloat5Buffer { - float EffectFloat5[]; -}; - -layout(std430, set = 3, binding = 6) buffer EffectFloat6Buffer { - float EffectFloat6[]; -}; - -layout(set = 1, binding = 0) uniform Environment { - vec3 fogColor; - float fogIntensity; -} environment; - -layout(set = 1, binding = 1) uniform Uniforms { - mat4 invProjectionMatrix; - mat4 projectionMatrix; - mat4 viewMatrix; - mat4 invViewMatrix; - mat4 lastViewMatrix; - float nearPlane; - float farPlane; - float focusDepth; - float focusRange; - - int maxMipLevel; - float deltaTime; - float time; -}; - -layout(set = 4, binding = 0) uniform Clouds { - vec3 cloudPosition; - vec3 cloudSize; - vec3 cameraPosition; - float cloudScale; - vec3 cloudOffset; - float cloudDensityThreshold; - float cloudDensityMultiplier; - float cloudAbsorption; - float cloudScattering; - float cloudPhaseG; - float cloudClusterStrength; - int cloudPrimarySteps; - int cloudLightSteps; - float cloudLightStepMultiplier; - float cloudMinStepLength; - vec3 sunDirection; - vec3 sunColor; - float sunIntensity; - vec3 cloudAmbientColor; - int hasClouds; -}; - -vec4 sampleColor(vec2 uv) { - for (int i = 0; i < EffectCount; i++) { - if (Effects[i] == EFFECT_CHROMATIC_ABERRATION) { - float redOffset = EffectFloat1[i]; - float greenOffset = EffectFloat2[i]; - float blueOffset = EffectFloat3[i]; - vec2 focusPoint = vec2(EffectFloat4[i], EffectFloat5[i]); - vec2 sampleCoord = uv; - vec2 direction = sampleCoord - focusPoint; - float red = texture(Texture, sampleCoord + (direction * redOffset)).r; - float green = texture(Texture, sampleCoord + (direction * greenOffset)).g; - vec2 blue = texture(Texture, sampleCoord + (direction * blueOffset)).ba; - return vec4(red, green, blue); - } else if (Effects[i] == EFFECT_PIXELATION) { - float pixelSizeInPixels = EffectFloat1[i]; - vec2 texSize = vec2(textureSize(Texture, 0)); - - vec2 pixelSize = vec2(pixelSizeInPixels) / texSize; - - vec2 pixelated = floor(uv / pixelSize) * pixelSize; - - return texture(Texture, pixelated); - } else if (Effects[i] == EFFECT_DILATION) { - float radius = EffectFloat1[i]; - float separation = EffectFloat2[i]; - vec2 texelSize = 1.0 / vec2(textureSize(Texture, 0)); - - vec3 maxColor = texture(Texture, uv).rgb; - int range = int(radius); - float radiusSq = radius * radius; - - for (int x = -range; x <= range; x++) { - for (int y = -range; y <= range; y++) { - float distSq = float(x * x + y * y); - if (distSq <= radiusSq) { - vec2 offset = vec2(float(x), float(y)) * texelSize * separation; - vec3 sampled = texture(Texture, uv + offset).rgb; - maxColor = max(maxColor, sampled); - } - } - } - - return vec4(maxColor, texture(Texture, uv).a); - } - } - - return texture(Texture, uv); -} - -vec4 sampleBright(vec2 uv) { - for (int i = 0; i < EffectCount; i++) { - if (Effects[i] == EFFECT_CHROMATIC_ABERRATION) { - float redOffset = EffectFloat1[i]; - float greenOffset = EffectFloat2[i]; - float blueOffset = EffectFloat3[i]; - vec2 focusPoint = vec2(EffectFloat4[i], EffectFloat5[i]); - vec2 sampleCoord = uv; - vec2 direction = sampleCoord - focusPoint; - float red = texture(BrightTexture, sampleCoord + (direction * redOffset)).r; - float green = texture(BrightTexture, sampleCoord + (direction * greenOffset)).g; - vec2 blue = texture(BrightTexture, sampleCoord + (direction * blueOffset)).ba; - return vec4(red, green, blue); - } else if (Effects[i] == EFFECT_PIXELATION) { - float pixelSizeInPixels = EffectFloat1[i]; - vec2 texSize = vec2(textureSize(BrightTexture, 0)); - - vec2 pixelSize = vec2(pixelSizeInPixels) / texSize; - - vec2 pixelated = floor(uv / pixelSize) * pixelSize; - vec4 color = texture(BrightTexture, pixelated); - return color; - } else if (Effects[i] == EFFECT_DILATION) { - float radius = EffectFloat1[i]; - float separation = EffectFloat2[i]; - vec2 texelSize = 1.0 / vec2(textureSize(BrightTexture, 0)); - - vec3 maxColor = texture(BrightTexture, uv).rgb; - int range = int(radius); - float radiusSq = radius * radius; - - for (int x = -range; x <= range; x++) { - for (int y = -range; y <= range; y++) { - float distSq = float(x * x + y * y); - if (distSq <= radiusSq) { - vec2 offset = vec2(float(x), float(y)) * texelSize * separation; - vec3 sampled = texture(BrightTexture, uv + offset).rgb; - maxColor = max(maxColor, sampled); - } - } - } - - return vec4(maxColor, texture(BrightTexture, uv).a); - } - } - - return texture(BrightTexture, uv); -} - -float LinearizeDepth(float depth) { - float z = depth * 2.0 - 1.0; - float linear = (2.0 * nearPlane * farPlane) / - (farPlane + nearPlane - z * (farPlane - nearPlane)); - return linear / farPlane; -} - -vec3 reconstructViewPos(vec2 uv, float depth) { - float z = depth * 2.0 - 1.0; - vec4 clipPos = vec4(uv * 2.0 - 1.0, z, 1.0); - vec4 viewPos = invProjectionMatrix * clipPos; - viewPos /= viewPos.w; - return viewPos.xyz; -} - -struct ChromaticAberrationSettings { - float redOffset; - float greenOffset; - float blueOffset; - vec2 focusPoint; - bool enabled; -}; - -struct ColorCorrection { - float exposure; - float contrast; - float saturation; - float gamma; - float temperature; - float tint; -}; - -vec4 applyColorCorrection(vec4 color, ColorCorrection cc) { - vec3 linearColor = color.rgb; - - linearColor *= pow(2.0, cc.exposure); - - linearColor = (linearColor - 0.5) * cc.contrast + 0.5; - - linearColor.r += cc.temperature * 0.05; - linearColor.g += cc.tint * 0.05; - - float luminance = dot(linearColor, vec3(0.2126, 0.7152, 0.0722)); - linearColor = mix(vec3(luminance), linearColor, cc.saturation); - - linearColor = clamp(linearColor, 0.0, 1.0); - - return vec4(linearColor, color.a); -} - -vec4 applyColorEffects(vec4 color) { - for (int i = 0; i < EffectCount; i++) { - if (Effects[i] == EFFECT_INVERSION) { - color = vec4(1.0 - color.rgb, color.a); - } else if (Effects[i] == EFFECT_GRAYSCALE) { - float average = 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b; - color = vec4(average, average, average, color.a); - } else if (Effects[i] == EFFECT_COLOR_CORRECTION) { - ColorCorrection cc; - cc.exposure = EffectFloat1[i]; - cc.contrast = EffectFloat2[i]; - cc.saturation = EffectFloat3[i]; - cc.gamma = EffectFloat4[i]; - cc.temperature = EffectFloat5[i]; - cc.tint = EffectFloat6[i]; - color = applyColorCorrection(color, cc); - } else if (Effects[i] == EFFECT_POSTERIZATION) { - float levels = max(EffectFloat1[i], 1.0); - float grayscale = max(color.r, max(color.g, color.b)); - if (grayscale > 1e-4) { - float lower = floor(grayscale * levels) / levels; - float lowerDiff = abs(grayscale - lower); - float upper = ceil(grayscale * levels) / levels; - float upperDiff = abs(upper - grayscale); - float level = lowerDiff <= upperDiff ? lower : upper; - float adjustment = level / max(grayscale, 1e-4); - color = adjustment * color; - } - } else if (Effects[i] == EFFECT_FILM_GRAIN) { - float amount = EffectFloat1[i]; - - vec3 seed = vec3(gl_FragCoord.xy, deltaTime * 100.0); - - float n = dot(seed, vec3(12.9898, 78.233, 45.164)); - float noise = fract(sin(n) * 43758.5453); - float grain = (noise - 0.5) * 2.0 * amount; - - float luminance = dot(color.rgb, vec3(0.299, 0.587, 0.114)); - float visibility = 1.0 - abs(luminance - 0.5) * 0.5; - - color.rgb += vec3(grain * visibility); - color.rgb = clamp(color.rgb, 0.0, 1.0); - } - } - - return color; -} - -vec4 applyFXAA(sampler2D tex, vec2 texCoord) { - vec2 texelSize = 1.0 / textureSize(tex, 0); - - float FXAA_SPAN_MAX = 8.0; - float FXAA_REDUCE_MUL = 1.0 / 8.0; - float FXAA_REDUCE_MIN = 1.0 / 128.0; - - vec3 rgbNW = sampleColor(texCoord + vec2(-1.0, -1.0) * texelSize).rgb; - vec3 rgbNE = sampleColor(texCoord + vec2(1.0, -1.0) * texelSize).rgb; - vec3 rgbSW = sampleColor(texCoord + vec2(-1.0, 1.0) * texelSize).rgb; - vec3 rgbSE = sampleColor(texCoord + vec2(1.0, 1.0) * texelSize).rgb; - vec3 rgbM = sampleColor(texCoord).rgb; - - vec3 luma = vec3(0.299, 0.587, 0.114); - float lumaNW = dot(rgbNW, luma); - float lumaNE = dot(rgbNE, luma); - float lumaSW = dot(rgbSW, luma); - float lumaSE = dot(rgbSE, luma); - float lumaM = dot(rgbM, luma); - - float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); - float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); - - vec2 dir; - dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); - dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); - - float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * - (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN); - - float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce); - dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), - max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), - dir * rcpDirMin)) * texelSize; - - vec3 rgbA = 0.5 * ( - sampleColor(texCoord + dir * (1.0 / 3.0 - 0.5)).rgb + - sampleColor(texCoord + dir * (2.0 / 3.0 - 0.5)).rgb); - - vec3 rgbB = rgbA * 0.5 + 0.25 * ( - sampleColor(texCoord + dir * -0.5).rgb + - sampleColor(texCoord + dir * 0.5).rgb); - - float lumaB = dot(rgbB, luma); - - if ((lumaB < lumaMin) || (lumaB > lumaMax)) { - return vec4(rgbA, 1.0); - } else { - return vec4(rgbB, 1.0); - } -} - -vec4 composeSSR(vec4 color, vec2 uv) { - if (hasSSRTexture != 1) { - return color; - } - vec4 ssr = texture(SSRTexture, uv); - float reflectionWeight = clamp(ssr.a, 0.0, 1.0); - float baseWeight = 1.0 - reflectionWeight; - color.rgb = color.rgb * baseWeight + ssr.rgb * reflectionWeight; - return color; -} - -vec4 composeLighting(vec2 uv, vec4 baseColor) { - vec4 color = baseColor; - if (hasBrightTexture == 1) { - color += sampleBright(uv); - } - if (hasVolumetricLightTexture == 1) { - color += texture(VolumetricLightTexture, uv); - } - return composeSSR(color, uv); -} - -vec4 applyMotionBlur(vec2 texCoord, float size, float separation, vec4 color) { - vec4 fallbackColor = composeLighting(texCoord, color); - if (size <= 0.0 || separation <= 0.0) { - return fallbackColor; - } - if (hasPositionTexture != 1) { - return fallbackColor; - } - - vec4 worldPos = texture(PositionTexture, texCoord); - if (worldPos.a <= 0.0) { - return fallbackColor; - } - - vec3 viewSpacePos = (viewMatrix * worldPos).xyz; - float distanceToCamera = length(viewSpacePos); - - if (distanceToCamera < nearPlane * 2.0) { - return fallbackColor; - } - - vec4 currentClipPos = projectionMatrix * viewMatrix * worldPos; - currentClipPos.xyz /= currentClipPos.w; - vec2 currentUV = currentClipPos.xy * 0.5 + 0.5; - - vec4 prevClipPos = projectionMatrix * lastViewMatrix * worldPos; - prevClipPos.xyz /= prevClipPos.w; - vec2 prevUV = prevClipPos.xy * 0.5 + 0.5; - - vec2 velocity = (currentUV - prevUV) * separation; - float velocityLength = length(velocity); - - float maxVelocity = 0.12; - if (velocityLength > maxVelocity) { - velocity = normalize(velocity) * maxVelocity; - velocityLength = maxVelocity; - } - if (hasSSRTexture == 1) { - float mirrorWeight = clamp(texture(SSRTexture, texCoord).a, 0.0, 1.0); - float blurDamp = mix(1.0, 0.2, mirrorWeight); - velocity *= blurDamp; - velocityLength *= blurDamp; - } - - if (velocityLength < 0.0001) { - return fallbackColor; - } - - int baseSamples = clamp(int(size), 2, 32); - float sampleScale = - mix(0.75, 1.75, clamp(velocityLength / maxVelocity, 0.0, 1.0)); - int samples = clamp(int(float(baseSamples) * sampleScale), 3, 48); - - float centerDepth = 0.0; - float depthSoftness = 1.0; - if (hasDepthTexture == 1) { - centerDepth = LinearizeDepth(texture(DepthTexture, texCoord).r); - depthSoftness = max(0.002, centerDepth * 0.02); - } - - float jitter = (fract(sin(dot(texCoord * vec2(173.3, 97.1), - vec2(12.9898, 78.233))) * - 43758.5453) - - 0.5) * - 0.35; - - vec4 result = vec4(0.0); - float totalWeight = 0.0; - - for (int i = 0; i < samples; i++) { - float t = ((float(i) + 0.5) / float(samples)) * 2.0 - 1.0; - t += jitter / float(samples); - vec2 sampleCoord = texCoord + velocity * t; - - if (sampleCoord.x < 0.0 || sampleCoord.x > 1.0 || - sampleCoord.y < 0.0 || sampleCoord.y > 1.0) { - continue; - } - - float depthWeight = 1.0; - if (hasDepthTexture == 1) { - float sampleDepth = LinearizeDepth(texture(DepthTexture, sampleCoord).r); - float depthDelta = abs(sampleDepth - centerDepth); - depthWeight = - 1.0 - smoothstep(depthSoftness, depthSoftness * 2.5, depthDelta); - if (depthWeight <= 0.0) { - continue; - } - } - - vec4 sampled = composeLighting(sampleCoord, sampleColor(sampleCoord)); - float gaussian = exp(-4.0 * t * t); - float weight = gaussian * depthWeight; - result += sampled * weight; - totalWeight += weight; - } - - if (totalWeight > 0.0) { - return result / totalWeight; - } - - return fallbackColor; -} - -vec3 sampleLUT(vec3 rgb, float blueSlice, float sliceSize, float slicePixelOffset) { - float sliceY = floor(blueSlice / lutSize); - float sliceX = mod(blueSlice, lutSize); - - vec2 uv; - uv.x = sliceX * sliceSize + slicePixelOffset + rgb.r * sliceSize; - uv.y = sliceY * sliceSize + slicePixelOffset + rgb.g * sliceSize; - - return texture(LUTTexture, uv).rgb; -} - -vec4 mapToLUT(vec4 color) { - if (hasLUTTexture != 1) { - return color; - } - - float sliceSize = 1.0 / lutSize; - float slicePixelOffset = sliceSize * 0.5; - - float blueIndex = color.b * (lutSize - 1.0); - float sliceLow = floor(blueIndex); - float sliceHigh = min(sliceLow + 1.0, lutSize - 1.0); - float t = blueIndex - sliceLow; - - vec3 lowColor = sampleLUT(color.rgb, sliceLow, sliceSize, slicePixelOffset); - vec3 highColor = sampleLUT(color.rgb, sliceHigh, sliceSize, slicePixelOffset); - - vec3 finalRGB = mix(lowColor, highColor, t); - - return vec4(finalRGB, color.a); -} - -vec2 rayBoxDst(vec3 boundsMin, vec3 boundsMax, vec3 rayOrigin, vec3 rayDir) { - vec3 t0 = (boundsMin - rayOrigin) / rayDir; - vec3 t1 = (boundsMax - rayOrigin) / rayDir; - vec3 tMin = min(t0, t1); - vec3 tMax = max(t0, t1); - - float dstA = max(max(tMin.x, tMin.y), tMin.z); - float dstB = min(tMax.x, min(tMax.y, tMax.z)); - - float dstToContainer = max(0.0, dstA); - float dstInsideContainer = max(0.0, dstB - dstToContainer); - - return vec2(dstToContainer, dstInsideContainer); -} - -float saturate(float v) { return clamp(v, 0.0, 1.0); } - -float hashNoise(vec3 p) { - return fract(sin(dot(p, vec3(12.9898, 78.233, 37.719))) * 43758.5453); -} - -float henyeyGreenstein(float cosTheta, float g) { - const float PI = 3.14159265359; - float g2 = g * g; - float denom = pow(1.0 + g2 - 2.0 * g * cosTheta, 1.5); - return (1.0 - g2) / (4.0 * PI * max(denom, 1e-4)); -} - -float calculateCloudDensity(vec3 worldPos) { - vec3 halfExtents = max(cloudSize * 0.5, vec3(1e-4)); - vec3 localPos = (worldPos - cloudPosition) / halfExtents; - - if (any(lessThan(localPos, vec3(-1.0))) || - any(greaterThan(localPos, vec3(1.0)))) { - return 0.0; - } - - vec3 uvw = localPos * 0.5 + 0.5; - float scale = max(cloudScale, 0.001); - vec3 noiseCoord = fract(uvw * scale + cloudOffset); - - vec4 shape = texture(cloudsTexture, noiseCoord); - - float cluster = saturate(cloudClusterStrength); - - float lowerFade = smoothstep(-0.95, -0.6, localPos.y); - float upperFade = 1.0 - smoothstep(0.35, 0.95, localPos.y); - float verticalMask = lowerFade * upperFade; - - float coverageThreshold = mix(0.6, 0.28, cluster); - float coverageSoftness = mix(0.22, 0.34, cluster); - float coverageNoise = mix(shape.r, shape.a, 0.4 + cluster * 0.35); - float coverage = smoothstep(coverageThreshold, - coverageThreshold + coverageSoftness, - coverageNoise); - coverage = pow(coverage, mix(2.0, 0.7, cluster)); - - float detail = mix(smoothstep(0.25, 0.75, shape.g), - smoothstep(0.2, 0.9, shape.a), 0.55); - detail = pow(detail, mix(1.6, 0.85, cluster)); - - float cavityNoise = smoothstep(0.22, 0.85, shape.b); - float gapMask = clamp(1.0 - cavityNoise * mix(0.25, 0.7, cluster), 0.0, 1.0); - - float density = coverage * mix(detail, 1.0, cluster * 0.35); - density = max(density * gapMask * verticalMask - 0.02, 0.0); - density *= max(cloudDensityMultiplier, 0.0); - - return density; -} - -float sampleSunTransmittance(vec3 worldPos, float stepSize) { - vec3 lightDir = -sunDirection; - float dirLength = length(lightDir); - if (dirLength < 1e-3) { - lightDir = vec3(0.0, 1.0, 0.0); - } else { - lightDir /= dirLength; - } - - float maxDistance = length(cloudSize) * 1.5; - float travel = 0.0; - float attenuation = 1.0; - float lightStep = max(stepSize * cloudLightStepMultiplier, cloudMinStepLength); - - int steps = max(cloudLightSteps, 1); - for (int i = 0; i < steps && attenuation > 0.05; ++i) { - travel += lightStep; - if (travel > maxDistance) - break; - - vec3 samplePos = worldPos + lightDir * travel; - float density = calculateCloudDensity(samplePos); - attenuation *= exp(-density * lightStep * cloudAbsorption); - lightStep = max(lightStep * cloudLightStepMultiplier, cloudMinStepLength); - } - - return attenuation; -} - -vec4 cloudRendering(vec4 inColor) { - if (hasClouds != 1) { - return inColor; - } - - float nonLinearDepth = hasDepthTexture == 1 - ? texture(DepthTexture, TexCoord).r - : 1.0; - bool depthAvailable = hasDepthTexture == 1 && nonLinearDepth < 1.0; - float depthSample = depthAvailable ? nonLinearDepth : 1.0; - - vec3 rayOrigin = cameraPosition; - - vec4 clipSpace = vec4(TexCoord * 2.0 - 1.0, depthSample * 2.0 - 1.0, 1.0); - vec4 viewSpace = invProjectionMatrix * clipSpace; - viewSpace /= viewSpace.w; - vec3 worldPos = (invViewMatrix * vec4(viewSpace.xyz, 1.0)).xyz; - - vec3 rayDir = normalize(worldPos - rayOrigin); - - float sceneDistance = depthAvailable ? length(worldPos - rayOrigin) : 1e6; - - vec3 boundsMin = cloudPosition - cloudSize * 0.5; - vec3 boundsMax = cloudPosition + cloudSize * 0.5; - vec2 rayBoxInfo = rayBoxDst(boundsMin, boundsMax, rayOrigin, rayDir); - - float distToContainer = rayBoxInfo.x; - float distInContainer = rayBoxInfo.y; - - if (distInContainer <= 0.0) { - return inColor; - } - - float dstLimit = min(sceneDistance - distToContainer, distInContainer); - dstLimit = max(dstLimit, 0.0); - if (dstLimit <= 1e-4) { - return inColor; - } - - int steps = max(cloudPrimarySteps, 8); - float baseStep = dstLimit / float(steps); - float stepSize = max(baseStep, cloudMinStepLength); - - float jitter = hashNoise(vec3(TexCoord, time)) - 0.5; - float travelled = clamp(jitter, -0.35, 0.35) * stepSize; - travelled = max(travelled, 0.0); - - vec3 accumulatedLight = vec3(0.0); - float transmittance = 1.0; - - vec3 sunDir = sunDirection; - float sunLen = length(sunDir); - if (sunLen > 1e-3) { - sunDir /= sunLen; - } else { - sunDir = vec3(0.0, 1.0, 0.0); - } - - float phaseG = clamp(cloudPhaseG, -0.95, 0.95); - - for (int step = 0; step < steps && travelled < dstLimit; - ++step) { - if (transmittance <= 0.01) { - break; - } - - float remainingDistance = dstLimit - travelled; - if (remainingDistance <= 1e-5) { - break; - } - - float current = distToContainer + travelled; - vec3 samplePos = rayOrigin + rayDir * current; - - float density = calculateCloudDensity(samplePos); - if (density > 1e-4) { - float adaptiveStep = stepSize; - if (density < 0.02) { - adaptiveStep = stepSize * 2.5; - } else if (density < 0.05) { - adaptiveStep = stepSize * 1.6; - } - adaptiveStep = min(adaptiveStep, remainingDistance); - float sampleWeight = density * adaptiveStep; - - float lightTrans = sampleSunTransmittance(samplePos, adaptiveStep); - float cosTheta = clamp(dot(rayDir, -sunDir), -1.0, 1.0); - float phase = henyeyGreenstein(cosTheta, phaseG); - - vec3 directLight = sunColor * sunIntensity * lightTrans * phase; - vec3 ambientLight = cloudAmbientColor; - - vec3 lighting = (ambientLight * 0.35 + directLight) * - sampleWeight * cloudScattering; - - accumulatedLight += lighting * transmittance; - transmittance *= exp(-density * adaptiveStep * cloudAbsorption); - travelled += adaptiveStep; - continue; - } - - float emptyAdvance = min(stepSize * 2.25, remainingDistance); - float minAdvance = min(stepSize * 0.5, remainingDistance); - travelled += max(emptyAdvance, minAdvance); - } - - vec3 finalColor = inColor.rgb * transmittance + accumulatedLight; - return vec4(clamp(finalColor, 0.0, 1.0), inColor.a); -} - -void main() { - vec4 color = sampleColor(TexCoord); - float depth = texture(DepthTexture, TexCoord).r; - vec3 viewPos = reconstructViewPos(TexCoord, depth); - float distance = length(viewPos); - - bool useMotionBlur = false; - float motionBlurSize = 0.0; - float motionBlurSeparation = 0.0; - - for (int i = 0; i < EffectCount; i++) { - if (Effects[i] == EFFECT_MOTION_BLUR) { - useMotionBlur = true; - motionBlurSize = EffectFloat1[i]; - motionBlurSeparation = EffectFloat2[i]; - } - } - - for (int i = 0; i < EffectCount; i++) { - if (Effects[i] == EFFECT_SHARPEN) { - color = sharpen(Texture); - } else if (Effects[i] == EFFECT_BLUR) { - float radius = EffectFloat1[i]; - color = blur(Texture, radius); - } else if (Effects[i] == EFFECT_EDGE_DETECTION) { - color = edgeDetection(Texture); - } - } - - color = applyFXAA(Texture, TexCoord); - - color = applyColorEffects(color); - - if (hasDepthTexture == 1) { - float depthValue = texture(DepthTexture, TexCoord).r; - float linearDepth = LinearizeDepth(depthValue); - float coc = clamp(abs(linearDepth - focusDepth) / focusRange, 0.0, 1.0); - float mip = coc * float(maxMipLevel) * 1.2; - vec3 blurred = applyColorEffects(textureLod(Texture, TexCoord, mip)).rgb; - vec3 sharp = color.rgb; - color = cloudRendering(color); - } else { - color = cloudRendering(color); - } - - vec4 hdrColor; - if (useMotionBlur) { - vec4 motionBlurred = applyMotionBlur(TexCoord, motionBlurSize, motionBlurSeparation, color); - FragColor = motionBlurred; - return; - } else { - hdrColor = composeLighting(TexCoord, color); - } - - hdrColor = mapToLUT(hdrColor); - - - hdrColor.rgb = acesToneMapping(hdrColor.rgb); - - - float fogFactor = 1.0 - exp(-distance * environment.fogIntensity); - vec3 finalColor = mix(hdrColor.rgb, environment.fogColor, fogFactor); - - FragColor = vec4(finalColor, 1.0); -} diff --git a/shaders/vulkan/fullscreen.vert b/shaders/vulkan/fullscreen.vert deleted file mode 100644 index ea61fdaf..00000000 --- a/shaders/vulkan/fullscreen.vert +++ /dev/null @@ -1,13 +0,0 @@ -#version 450 - -layout(location = 0) in vec3 aPos; -layout(location = 1) in vec4 aColor; -layout(location = 2) in vec2 aTexCoord; -layout(location = 3) in vec3 aNormal; - -layout(location = 0) out vec2 TexCoord; - -void main() { - gl_Position = vec4(aPos.xy, 0.0, 1.0); - TexCoord = aTexCoord; -} \ No newline at end of file diff --git a/shaders/vulkan/main.frag b/shaders/vulkan/main.frag deleted file mode 100644 index 1e23e992..00000000 --- a/shaders/vulkan/main.frag +++ /dev/null @@ -1,887 +0,0 @@ -#version 450 - -layout(location = 0) out vec4 FragColor; -layout(location = 1) out vec4 BrightColor; - -layout(location = 0) in vec2 TexCoord; -layout(location = 1) in vec4 outColor; -layout(location = 2) in vec3 Normal; -layout(location = 3) in vec3 FragPos; -layout(location = 4) in mat3 TBN; - -const int TEXTURE_COLOR = 0; -const int TEXTURE_SPECULAR = 1; -const int TEXTURE_DEPTH_CUBE = 4; -const int TEXTURE_NORMAL = 5; -const int TEXTURE_PARALLAX = 6; -const int TEXTURE_METALLIC = 9; -const int TEXTURE_ROUGHNESS = 10; -const int TEXTURE_AO = 11; -const int TEXTURE_OPACITY = 12; -const int TEXTURE_HDR_ENVIRONMENT = 13; -const int TEXTURE_PBR_PACK = 14; - -const float PI = 3.14159265; - -vec2 texCoord; - -// ----- Structures ----- -struct DirectionalLight { - vec3 direction; - float _pad1; - vec3 diffuse; - float _pad2; - vec3 specular; - float intensity; -}; - -struct PointLight { - vec3 position; - float _pad1; - vec3 diffuse; - float _pad2; - vec3 specular; - float intensity; - float constant; - float linear; - float quadratic; - float radius; - float _pad3; -}; - -struct SpotLight { - vec3 position; - float _pad1; - vec3 direction; - float cutOff; - float outerCutOff; - float intensity; - float range; - float _pad4; - vec3 diffuse; - float _pad5; - vec3 specular; - float _pad6; -}; - -struct AreaLight { - vec3 position; - float _pad1; - vec3 right; - float _pad2; - vec3 up; - float _pad3; - vec2 size; - float _pad4; - float _pad5; - vec3 diffuse; - float _pad6; - vec3 specular; - float angle; - int castsBothSides; - float intensity; - float range; - float _pad9; -}; - -struct ShadowParameters { - mat4 lightView; - mat4 lightProjection; - float bias; - int textureIndex; - float farPlane; - float _pad1; - vec3 lightPos; - int lightType; -}; - -// ----- Textures ----- -layout(set = 2, binding = 0) uniform sampler2D texture1; -layout(set = 2, binding = 1) uniform sampler2D texture2; -layout(set = 2, binding = 2) uniform sampler2D texture3; -layout(set = 2, binding = 3) uniform sampler2D texture4; -layout(set = 2, binding = 4) uniform sampler2D texture5; -layout(set = 2, binding = 5) uniform sampler2D texture6; -layout(set = 2, binding = 6) uniform sampler2D texture7; -layout(set = 2, binding = 7) uniform sampler2D texture8; -layout(set = 2, binding = 8) uniform sampler2D texture9; -layout(set = 2, binding = 9) uniform sampler2D texture10; -layout(set = 2, binding = 10) uniform samplerCube skybox; -layout(set = 2, binding = 11) uniform samplerCube cubeMap1; -layout(set = 2, binding = 12) uniform samplerCube cubeMap2; -layout(set = 2, binding = 13) uniform samplerCube cubeMap3; -layout(set = 2, binding = 14) uniform samplerCube cubeMap4; -layout(set = 2, binding = 15) uniform samplerCube cubeMap5; - -// ----- Uniforms ----- -layout(set = 1, binding = 0) uniform Uniforms { - int textureTypes[16]; - int textureCount; - vec3 cameraPosition; - vec2 textureScale; - vec2 textureOffset; -}; - -layout(push_constant) uniform PushConstants { - bool useTexture; - bool useColor; - bool useIBL; - - int directionalLightCount; - int pointLightCount; - int spotlightCount; - int areaLightCount; - int shadowParamCount; -}; - -layout(set = 1, binding = 1) uniform Material { - vec3 albedo; - float metallic; - float roughness; - float ao; - float reflectivity; -} material; - -layout(set = 1, binding = 2) uniform Environment { - float rimLightIntensity; - vec3 rimLightColor; -} environment; - -layout(set = 1, binding = 3) uniform AmbientLight { - vec4 color; - float intensity; - vec3 _pad0; -} ambientLight; - -layout(set = 3, binding = 1) buffer DirectionalLightsUBO { - DirectionalLight directionalLights[]; -}; - -layout(set = 3, binding = 2) buffer PointLightsUBO { - PointLight pointLights[]; -}; - -layout(set = 3, binding = 3) buffer SpotLightsUBO { - SpotLight spotlights[]; -}; - -layout(set = 3, binding = 4) buffer AreaLightsUBO { - AreaLight areaLights[]; -}; - -layout(set = 3, binding = 5) buffer ShadowParametersUBO { - ShadowParameters shadowParams[]; -}; - -// ----- Helper Functions ----- -vec4 enableTextures(int type) { - vec4 color = vec4(0.0); - int count = 0; - for (int i = 0; i < textureCount; i++) { - if (textureTypes[i] == type) { - if (i == 0) color += texture(texture1, texCoord); - else if (i == 1) color += texture(texture2, texCoord); - else if (i == 2) color += texture(texture3, texCoord); - else if (i == 3) color += texture(texture4, texCoord); - else if (i == 4) color += texture(texture5, texCoord); - else if (i == 5) color += texture(texture6, texCoord); - else if (i == 6) color += texture(texture7, texCoord); - else if (i == 7) color += texture(texture8, texCoord); - else if (i == 8) color += texture(texture9, texCoord); - else if (i == 9) color += texture(texture10, texCoord); - count++; - } - } - if (count > 0) color /= float(count); - if (count == 0) return vec4(-1.0); - return color; -} - -vec4 enableCubeMaps(int type, vec3 direction) { - vec4 color = vec4(0.0); - int count = 0; - for (int i = 0; i < 8; i++) { - if (type == i + 10) { - if (i == 0) color += texture(cubeMap1, direction); - else if (i == 1) color += texture(cubeMap2, direction); - else if (i == 2) color += texture(cubeMap3, direction); - else if (i == 3) color += texture(cubeMap4, direction); - else if (i == 4) color += texture(cubeMap5, direction); - count++; - } - } - if (count > 0) color /= float(count); - if (count == 0) return vec4(-1.0); - return color; -} - -vec4 sampleCubeTextureAt(int textureIndex, vec3 direction) { - if (textureIndex == 0) return texture(cubeMap1, direction); - else if (textureIndex == 1) return texture(cubeMap2, direction); - else if (textureIndex == 2) return texture(cubeMap3, direction); - else if (textureIndex == 3) return texture(cubeMap4, direction); - else if (textureIndex == 4) return texture(cubeMap5, direction); - return vec4(0.0); -} - -vec2 getTextureDimensions(int textureIndex) { - if (textureIndex == 0) return vec2(textureSize(texture1, 0)); - else if (textureIndex == 1) return vec2(textureSize(texture2, 0)); - else if (textureIndex == 2) return vec2(textureSize(texture3, 0)); - else if (textureIndex == 3) return vec2(textureSize(texture4, 0)); - else if (textureIndex == 4) return vec2(textureSize(texture5, 0)); - else if (textureIndex == 5) return vec2(textureSize(texture6, 0)); - else if (textureIndex == 6) return vec2(textureSize(texture7, 0)); - else if (textureIndex == 7) return vec2(textureSize(texture8, 0)); - else if (textureIndex == 8) return vec2(textureSize(texture9, 0)); - else if (textureIndex == 9) return vec2(textureSize(texture10, 0)); - return vec2(0); -} - -vec4 sampleTextureAt(int textureIndex, vec2 uv) { - if (textureIndex == 0) return texture(texture1, uv); - else if (textureIndex == 1) return texture(texture2, uv); - else if (textureIndex == 2) return texture(texture3, uv); - else if (textureIndex == 3) return texture(texture4, uv); - else if (textureIndex == 4) return texture(texture5, uv); - else if (textureIndex == 5) return texture(texture6, uv); - else if (textureIndex == 6) return texture(texture7, uv); - else if (textureIndex == 7) return texture(texture8, uv); - else if (textureIndex == 8) return texture(texture9, uv); - else if (textureIndex == 9) return texture(texture10, uv); - return vec4(0.0); -} - -vec3 getSpecularColor() { - vec4 specTex = enableTextures(TEXTURE_SPECULAR); - vec3 specColor = material.albedo; - if (specTex.r != -1.0 || specTex.g != -1.0 || specTex.b != -1.0) { - specColor *= specTex.rgb; - } - return specColor; -} - -vec4 applyGammaCorrection(vec4 color, float gamma) { - return vec4(pow(color.rgb, vec3(1.0 / gamma)), color.a); -} - -vec2 directionToEquirect(vec3 direction) { - vec3 dir = normalize(direction); - float phi = atan(dir.z, dir.x); - float theta = acos(clamp(dir.y, -1.0, 1.0)); - return vec2((phi + PI) / (2.0 * PI), theta / PI); -} - -vec3 sampleHDRTexture(int textureIndex, vec3 direction) { - vec2 uv = directionToEquirect(direction); - return sampleTextureAt(textureIndex, uv).rgb; -} - -vec3 sampleEnvironmentRadiance(vec3 direction) { - vec3 envColor = vec3(0.0); - int count = 0; - for (int i = 0; i < textureCount; i++) { - if (textureTypes[i] == TEXTURE_HDR_ENVIRONMENT) { - envColor += sampleHDRTexture(i, direction); - count++; - } - } - if (count == 0) { - return vec3(0.0); - } - return envColor / float(count); -} - -vec2 parallaxMapping(vec2 texCoords, vec3 viewDir) { - const float minLayers = 8.0; - const float maxLayers = 32.0; - vec3 v = normalize(viewDir); - float numLayers = mix(maxLayers, minLayers, abs(dot(vec3(0.0, 0.0, 1.0), v))); - float layerDepth = 1.0 / numLayers; - float currentLayerDepth = 0.0; - - const float heightScale = 0.04; - vec2 P = (v.xy / max(v.z, 0.05)) * heightScale; - vec2 deltaTexCoords = P / numLayers; - - vec2 currentTexCoords = texCoords; - int textureIndex = -1; - for (int i = 0; i < textureCount; i++) { - if (textureTypes[i] == TEXTURE_PARALLAX) { - textureIndex = i; - break; - } - } - if (textureIndex == -1) return texCoords; - float currentDepthMapValue = 1.0 - sampleTextureAt(textureIndex, currentTexCoords).r; - - while (currentLayerDepth < currentDepthMapValue) { - currentTexCoords -= deltaTexCoords; - currentDepthMapValue = 1.0 - sampleTextureAt(textureIndex, currentTexCoords).r; - currentLayerDepth += layerDepth; - } - - vec2 prevTexCoords = currentTexCoords + deltaTexCoords; - float afterDepth = currentDepthMapValue - currentLayerDepth; - float beforeDepth = 1.0 - sampleTextureAt(textureIndex, prevTexCoords).r - (currentLayerDepth - layerDepth); - float weight = afterDepth / (afterDepth - beforeDepth); - currentTexCoords = prevTexCoords * weight + currentTexCoords * (1.0 - weight); - - return currentTexCoords; -} - -vec3 reinhardToneMapping(vec3 hdrColor) { - vec3 color = vec3(1.0) - exp(-hdrColor * 1.0); - color = pow(color, vec3(1.0 / 2.2)); - return color; -} - -vec3 acesToneMapping(vec3 color) { - float a = 2.51; - float b = 0.03; - float c = 2.43; - float d = 0.59; - float e = 0.14; - color = (color * (a * color + b)) / (color * (c * color + d) + e); - color = pow(clamp(color, 0.0, 1.0), vec3(1.0 / 2.2)); - return color; -} - -// ----- Environment Mapping ----- -vec4 getEnvironmentReflected(vec4 color) { - vec3 I = normalize(FragPos - cameraPosition); - vec3 R = reflect(I, normalize(Normal)); - return mix(color, vec4(texture(skybox, R).rgb, 1.0), material.reflectivity); -} - -// ----- Rim Light ----- -vec3 getRimLight( - vec3 fragPos, - vec3 N, - vec3 V, - vec3 F0, - vec3 albedo, - float metallic, - float roughness -) { - N = normalize(N); - V = normalize(V); - - float rim = pow(1.0 - max(dot(N, V), 0.0), 3.0); - - rim *= mix(1.2, 0.3, roughness); - - vec3 rimColor = mix(vec3(1.0), albedo, metallic) * environment.rimLightColor; - rimColor = mix(rimColor, F0, 0.5); - - float rimIntensity = environment.rimLightIntensity; - - vec3 rimLight = rimColor * rim * rimIntensity; - - float dist = length(cameraPosition - fragPos); - rimLight /= (1.0 + dist * 0.1); - - return rimLight; -} - -// ----- PBR ----- -float distributionGGX(vec3 N, vec3 H, float roughness) { - float a = roughness * roughness; - float a2 = a * a; - float NdotH = max(dot(N, H), 0.0); - float NdotH2 = NdotH * NdotH; - - float num = a2; - float denom = (NdotH2 * (a2 - 1.0) + 1.0); - denom = 3.14159265 * denom * denom; - - return num / denom; -} - -float geometrySchlickGGX(float NdotV, float roughness) { - float r = (roughness + 1.0); - float k = (r * r) / 8.0; - - float num = NdotV; - float denom = NdotV * (1.0 - k) + k; - - return num / denom; -} - -float geometrySmith(vec3 N, vec3 V, vec3 L, float roughness) { - float NdotV = max(dot(N, V), 0.0); - float NdotL = max(dot(N, L), 0.0); - float ggx2 = geometrySchlickGGX(NdotV, roughness); - float ggx1 = geometrySchlickGGX(NdotL, roughness); - - return ggx1 * ggx2; -} - -vec3 fresnelSchlick(float cosTheta, vec3 F0) { - return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); -} - -vec3 calculatePBR(vec3 N, vec3 V, vec3 L, vec3 F0, vec3 radiance, vec3 albedo, float metallic, float roughness, float reflectivity) { - vec3 H = normalize(V + L); - - float NDF = distributionGGX(N, H, roughness); - float G = geometrySmith(N, V, L, roughness); - vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); - - vec3 kS = F; - vec3 kD = vec3(1.0) - kS; - kD *= 1.0 - metallic; - - vec3 numerator = NDF * G * F; - float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001; - vec3 specular = numerator / denominator; - - float NdotL = max(dot(N, L), 0.0); - - vec3 Lo = (kD * albedo / 3.14159265 + specular) * radiance * NdotL; - return Lo; -} - -vec3 calculatePBRWithAttenuation(vec3 N, vec3 V, vec3 L, vec3 F0, vec3 radianceAttenuated, vec3 albedo, float metallic, float roughness, float reflectivity) { - vec3 H = normalize(V + L); - - float NDF = distributionGGX(N, H, roughness); - float G = geometrySmith(N, V, L, roughness); - vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); - - vec3 kS = F; - vec3 kD = vec3(1.0) - kS; - kD *= 1.0 - metallic; - - vec3 numerator = NDF * G * F; - float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001; - vec3 specular = numerator / denominator; - - float NdotL = max(dot(N, L), 0.0); - - vec3 Lo = (kD * albedo / 3.14159265 + specular) * radianceAttenuated * NdotL; - return Lo; -} - -// ----- Directional Light ----- -vec3 calcAllDirectionalLights(vec3 N, vec3 V, vec3 albedo, float metallic, float roughness, vec3 F0, float reflectivity) { - vec3 Lo = vec3(0.0); - - for (int i = 0; i < directionalLightCount; i++) { - vec3 L = normalize(-directionalLights[i].direction); - vec3 radiance = directionalLights[i].diffuse * max(directionalLights[i].intensity, 0.0); - Lo += calculatePBR(N, V, L, F0, radiance, albedo, metallic, roughness, reflectivity); - } - - return Lo; -} - -// ----- Point Light ----- -float calcAttenuation(PointLight light, vec3 fragPos) { - float distance = length(light.position - fragPos); - return 1.0 / (light.constant + light.linear * distance + light.quadratic * distance); -} - -vec3 calcAllPointLights(vec3 fragPos, vec3 N, vec3 V, vec3 albedo, float metallic, float roughness, vec3 F0, float reflectivity) { - vec3 Lo = vec3(0.0); - for (int i = 0; i < pointLightCount; i++) { - vec3 L = pointLights[i].position - fragPos; - float distance = length(L); - - distance = max(distance, 0.001); - - L = normalize(L); - - float range = max(pointLights[i].radius, 0.001); - vec3 radiance = pointLights[i].diffuse * max(pointLights[i].intensity, 0.0); - float attenuation = 1.0 / (1.0 + (distance / range) + (distance * distance) / (range * range)); - float fade = 1.0 - smoothstep(range * 0.9, range, distance); - vec3 radianceAttenuated = radiance * attenuation; - radianceAttenuated *= fade; - - vec3 H = normalize(V + L); - - float NDF = distributionGGX(N, H, roughness); - float G = geometrySmith(N, V, L, roughness); - vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); - - vec3 kS = F; - vec3 kD = vec3(1.0) - kS; - kD *= 1.0 - metallic; - - vec3 numerator = NDF * G * F; - float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001; - vec3 specular = numerator / denominator; - - float NdotL = max(dot(N, L), 0.0); - - Lo += (kD * albedo / 3.14159265 + specular) * radianceAttenuated * NdotL; - } - return Lo; -} - -// ----- Spot Light ----- -vec3 calcAllSpotLights(vec3 N, vec3 fragPos, vec3 L, vec3 viewDir, vec3 albedo, float metallic, float roughness, vec3 F0, float reflectivity) { - vec3 Lo = vec3(0.0); - - for (int i = 0; i < spotlightCount; i++) { - vec3 L = normalize(spotlights[i].position - fragPos); - - vec3 spotDirection = normalize(spotlights[i].direction); - float theta = dot(L, -spotDirection); - float intensity = smoothstep(spotlights[i].outerCutOff, spotlights[i].cutOff, theta); - - float distance = length(spotlights[i].position - fragPos); - distance = max(distance, 0.001); - float range = max(spotlights[i].range, 0.001); - float attenuation = 1.0 / (1.0 + (distance / range) + (distance * distance) / (range * range)); - float fade = 1.0 - smoothstep(range * 0.9, range, distance); - - vec3 radiance = spotlights[i].diffuse * max(spotlights[i].intensity, 0.0) * attenuation * intensity * fade; - - Lo += calculatePBR(N, viewDir, L, F0, radiance, albedo, metallic, roughness, reflectivity); - } - - return Lo; -} - -// ----- Shadow Calculations ----- -float calculateShadow(ShadowParameters shadowParam, vec4 fragPosLightSpace) { - vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; - // Transform from [-1,1] to [0,1] for texture sampling - projCoords = projCoords * 0.5 + 0.5; - // Flip Y because shadow map was rendered with OpenGL-style projection but sampled in Vulkan - projCoords.y = 1.0 - projCoords.y; - // Note: Shadow maps are rendered without Y-flip projection, so no Y-flip needed here - - if (projCoords.x < 0.0 || projCoords.x > 1.0 || - projCoords.y < 0.0 || projCoords.y > 1.0 || - projCoords.z > 1.0) { - return 0.0; - } - - float currentDepth = projCoords.z; - - vec3 lightDir = normalize((inverse(shadowParam.lightView) * vec4(0.0, 0.0, -1.0, 0.0)).xyz); - vec3 normal = normalize(Normal); - float biasValue = shadowParam.bias; - float bias = max(biasValue * (1.0 - dot(normal, lightDir)), biasValue); - - float shadow = 0.0; - vec2 texelSize = 1.0 / getTextureDimensions(shadowParam.textureIndex); - - float distance = length(cameraPosition - FragPos); - int kernelSize = int(mix(1.0, 3.0, clamp(distance / 100.0, 0.0, 1.0))); - - int sampleCount = 0; - for (int x = -kernelSize; x <= kernelSize; ++x) { - for (int y = -kernelSize; y <= kernelSize; ++y) { - float pcfDepth = sampleTextureAt(shadowParam.textureIndex, - projCoords.xy + vec2(x, y) * texelSize).r; - shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0; - sampleCount++; - } - } - shadow /= float(sampleCount); - - return shadow; -} - -float calculateShadowRaw(ShadowParameters shadowParam, vec4 fragPosLightSpace) { - vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; - projCoords = projCoords * 0.5 + 0.5; - projCoords.y = 1.0 - projCoords.y; - - if (projCoords.x < 0.0 || projCoords.x > 1.0 || - projCoords.y < 0.0 || projCoords.y > 1.0 || - projCoords.z < 0.0 || projCoords.z > 1.0) { - return 0.0; - } - - float currentDepth = projCoords.z; - float closestDepth = sampleTextureAt(shadowParam.textureIndex, projCoords.xy).r; - - return currentDepth > closestDepth ? 1.0 : 0.0; -} - -float calculateAllShadows() { - float totalShadow = 0.0; - for (int i = 0; i < shadowParamCount; i++) { - vec4 fragPosLightSpace = shadowParams[i].lightProjection * shadowParams[i].lightView * vec4(FragPos, 1.0); - float shadow = calculateShadow(shadowParams[i], fragPosLightSpace); - totalShadow = max(totalShadow, shadow); - } - return totalShadow; -} - -float calculatePointShadow(ShadowParameters shadowParam, vec3 fragPos) -{ - vec3 fragToLight = fragPos - shadowParam.lightPos; - float currentDepth = length(fragToLight); - - float bias = 0.05; - float shadow = 0.0; - - float diskRadius = (1.0 + (currentDepth / shadowParam.farPlane)) * 0.05; - - const int samples = 54; - const vec3 sampleOffsetDirections[] = vec3[]( - vec3(0.5381, 0.1856, -0.4319), vec3(0.1379, 0.2486, 0.4430), - vec3(0.3371, 0.5679, -0.0057), vec3(-0.6999, -0.0451, -0.0019), - vec3(0.0689, -0.1598, -0.8547), vec3(0.0560, 0.0069, -0.1843), - vec3(-0.0146, 0.1402, 0.0762), vec3(0.0100, -0.1924, -0.0344), - vec3(-0.3577, -0.5301, -0.4358), vec3(-0.3169, 0.1063, 0.0158), - vec3(0.0103, -0.5869, 0.0046), vec3(-0.0897, -0.4940, 0.3287), - vec3(0.7119, -0.0154, -0.0918), vec3(-0.0533, 0.0596, -0.5411), - vec3(0.0352, -0.0631, 0.5460), vec3(-0.4776, 0.2847, -0.0271), - vec3(-0.1120, 0.1234, -0.7446), vec3(-0.2130, -0.0782, -0.1379), - vec3(0.2944, -0.3112, -0.2645), vec3(-0.4564, 0.4175, -0.1843), - // remaining random-ish points - vec3(0.1234, -0.5678, 0.7890), vec3(-0.6789, 0.2345, -0.4567), - vec3(0.3456, -0.7890, 0.1234), vec3(-0.2345, 0.5678, -0.6789), - vec3(0.7890, 0.1234, 0.5678), vec3(-0.5678, -0.6789, 0.2345), - vec3(0.4567, 0.7890, -0.2345), vec3(-0.7890, 0.3456, -0.5678), - vec3(0.6789, -0.2345, 0.7890), vec3(-0.1234, 0.6789, -0.4567), - vec3(0.2345, -0.5678, 0.6789), vec3(-0.3456, 0.7890, -0.1234), - vec3(0.5678, 0.2345, -0.7890), vec3(-0.6789, -0.5678, 0.3456), - vec3(0.7890, -0.3456, 0.4567), vec3(-0.2345, 0.1234, -0.6789), - vec3(0.4567, 0.7890, -0.5678), vec3(-0.5678, 0.2345, 0.6789), - vec3(0.3456, -0.7890, -0.1234), vec3(-0.7890, 0.5678, -0.2345), - vec3(0.6789, -0.1234, 0.3456), vec3(-0.4567, 0.7890, 0.2345), - vec3(0.5678, -0.6789, 0.7890), vec3(-0.3456, 0.5678, -0.6789), - vec3(0.2345, -0.7890, 0.5678), vec3(-0.6789, 0.2345, -0.1234), - vec3(0.7890, -0.3456, -0.5678), vec3(-0.5678, 0.6789, 0.2345), - vec3(0.4567, -0.7890, 0.3456), vec3(-0.2345, 0.1234, -0.7890), - vec3(0.3456, -0.5678, 0.6789), vec3(-0.7890, 0.4567, -0.3456), - vec3(0.6789, -0.1234, -0.5678), vec3(-0.4567, 0.2345, 0.7890) - ); - - for (int i = 0; i < samples; ++i) - { - vec3 sampleDir = normalize(fragToLight + sampleOffsetDirections[i] * diskRadius); - float closestDepth = sampleCubeTextureAt(shadowParam.textureIndex, sampleDir).r * shadowParam.farPlane; - if (currentDepth - bias > closestDepth) - shadow += 1.0; - } - - shadow /= float(samples); - return shadow; -} - -float calculateAllPointShadows(vec3 fragPos) { - float totalShadow = 0.0; - for (int i = 0; i < shadowParamCount; i++) { - if (shadowParams[i].lightType == 3) { - float shadow = calculatePointShadow(shadowParams[i], fragPos); - totalShadow = max(totalShadow, shadow); - } - } - return totalShadow; -} - -// ----- Main ----- -void main() { - texCoord = TexCoord * textureScale + textureOffset; - - bool hasParallaxMap = false; - for (int i = 0; i < textureCount; i++) { - if (textureTypes[i] == TEXTURE_PARALLAX) { - hasParallaxMap = true; - break; - } - } - - if (hasParallaxMap) { - vec3 tangentViewDir = normalize(transpose(TBN) * (cameraPosition - FragPos)); - texCoord = parallaxMapping(texCoord, tangentViewDir); - } - - vec4 normTexture = enableTextures(TEXTURE_NORMAL); - vec3 N; - - if (normTexture.r != -1.0 && normTexture.g != -1.0 && normTexture.b != -1.0) { - vec3 tangentNormal = normalize(normTexture.rgb * 2.0 - 1.0); - N = normalize(TBN * tangentNormal); - } else { - N = normalize(Normal); - } - - N = normalize(N); - vec3 V = normalize(cameraPosition - FragPos); - - vec3 albedo = material.albedo; - vec4 albedoTex = enableTextures(TEXTURE_COLOR); - if (albedoTex != vec4(-1.0)) { - albedo *= albedoTex.rgb; - } - vec4 opacityTex = enableTextures(TEXTURE_OPACITY); - if (opacityTex != vec4(-1.0)) { - if (opacityTex.r < 0.1) { - discard; - } - } else if (albedoTex != vec4(-1.0) && albedoTex.a < 0.1) { - discard; - } - - vec4 pbrPackTex = enableTextures(TEXTURE_PBR_PACK); - bool hasPbrPack = pbrPackTex != vec4(-1.0); - - float metallic = material.metallic; - if (hasPbrPack) { - metallic *= pbrPackTex.b; - } else { - vec4 metallicTex = enableTextures(TEXTURE_METALLIC); - if (metallicTex != vec4(-1.0)) { - metallic *= metallicTex.r; - } - } - - float roughness = material.roughness; - if (hasPbrPack) { - roughness *= pbrPackTex.g; - } else { - vec4 roughnessTex = enableTextures(TEXTURE_ROUGHNESS); - if (roughnessTex != vec4(-1.0)) { - roughness *= roughnessTex.r; - } - } - - float ao = material.ao; - if (hasPbrPack) { - ao *= pbrPackTex.r; - } else { - vec4 aoTex = enableTextures(TEXTURE_AO); - if (aoTex != vec4(-1.0)) { - ao *= aoTex.r; - } - } - - vec3 F0 = vec3(0.04); - F0 = mix(F0, albedo, metallic); - - float directionalShadow = 0.0; - float spotShadow = 0.0; - float areaShadow = 0.0; - float pointShadow = 0.0; - - if (shadowParamCount > 0) { - for (int i = 0; i < shadowParamCount; i++) { - if (shadowParams[i].lightType == 0) { - vec4 fragPosLightSpace = shadowParams[i].lightProjection * - shadowParams[i].lightView * - vec4(FragPos, 1.0); - directionalShadow = max(directionalShadow, calculateShadow(shadowParams[i], fragPosLightSpace)); - } else if (shadowParams[i].lightType == 1) { - vec4 fragPosLightSpace = shadowParams[i].lightProjection * - shadowParams[i].lightView * - vec4(FragPos, 1.0); - spotShadow = max(spotShadow, calculateShadow(shadowParams[i], fragPosLightSpace)); - } else if (shadowParams[i].lightType == 2) { - vec4 fragPosLightSpace = shadowParams[i].lightProjection * - shadowParams[i].lightView * - vec4(FragPos, 1.0); - areaShadow = max(areaShadow, calculateShadow(shadowParams[i], fragPosLightSpace)); - } else if (shadowParams[i].lightType == 3) { - pointShadow = max(pointShadow, calculatePointShadow(shadowParams[i], FragPos)); - } - } - } - - float reflectivity = material.reflectivity; - vec3 viewDir = normalize(cameraPosition - FragPos); - - vec3 lighting = vec3(0.0); - - lighting += calcAllDirectionalLights(N, V, albedo, metallic, roughness, F0, reflectivity) * (1.0 - directionalShadow); - lighting += calcAllPointLights(FragPos, N, V, albedo, metallic, roughness, F0, reflectivity) * (1.0 - pointShadow); - lighting += calcAllSpotLights(N, FragPos, V, viewDir, albedo, metallic, roughness, F0, reflectivity) * (1.0 - spotShadow); - lighting += getRimLight(FragPos, N, V, F0, albedo, metallic, roughness); - - { - vec3 areaResult = vec3(0.0); - for (int i = 0; i < areaLightCount; ++i) { - vec3 P = areaLights[i].position; - vec3 R = normalize(areaLights[i].right); - vec3 U = normalize(areaLights[i].up); - vec2 halfSize = areaLights[i].size * 0.5; - - vec3 toPoint = FragPos - P; - float s = clamp(dot(toPoint, R), -halfSize.x, halfSize.x); - float t = clamp(dot(toPoint, U), -halfSize.y, halfSize.y); - vec3 Q = P + R * s + U * t; - - vec3 Lvec = Q - FragPos; - float dist = length(Lvec); - if (dist > 0.0001) { - vec3 L = Lvec / dist; - vec3 Nl = normalize(cross(R, U)); - float ndotl = dot(Nl, -L); - float facing = (areaLights[i].castsBothSides != 0) ? abs(ndotl) : max(ndotl, 0.0); - float cosTheta = cos(radians(areaLights[i].angle)); - if (facing >= cosTheta && facing > 0.0) { - float range = max(areaLights[i].range, 0.001); - float attenuation = 1.0 / (1.0 + (dist / range) + (dist * dist) / (range * range)); - float fade = 1.0 - smoothstep(range * 0.9, range, dist); - vec3 radiance = areaLights[i].diffuse * max(areaLights[i].intensity, 0.0) * attenuation * facing * fade; - vec3 H = normalize(V + L); - float NDF = distributionGGX(N, H, roughness); - float G = geometrySmith(N, V, L, roughness); - vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); - vec3 kS = F; - vec3 kD = (vec3(1.0) - kS) * (1.0 - metallic); - vec3 numerator = NDF * G * F; - float denominator = max(4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0), 0.0001); - vec3 specular = numerator / denominator; - float NdotL = max(dot(N, L), 0.0); - areaResult += (kD * albedo / PI + specular) * radiance * NdotL; - } - } - } - lighting += areaResult * (1.0 - areaShadow); - } - - float aoClamped = clamp(ao, 0.0, 1.0); - float aoWithFloor = max(aoClamped, 0.2); - - float ambientIntensity = ambientLight.intensity; - vec3 ambientColor = ambientLight.color.rgb; - if (ambientIntensity <= 0.0001) { - ambientIntensity = 0.03; - } - if (dot(ambientColor, ambientColor) <= 1e-6) { - ambientColor = vec3(1.0); - } - - vec3 ambient = albedo * ambientIntensity * ambientColor * aoWithFloor; - - vec3 iblContribution = vec3(0.0); - if (useIBL) { - vec3 irradiance = sampleEnvironmentRadiance(N); - vec3 diffuseIBL = irradiance * albedo; - - vec3 reflection = reflect(-V, N); - vec3 specularEnv = sampleEnvironmentRadiance(reflection); - - vec3 F = fresnelSchlick(max(dot(N, V), 0.0), F0); - vec3 kS = F; - vec3 kD = vec3(1.0) - kS; - kD *= 1.0 - metallic; - - float roughnessAttenuation = mix(1.0, 0.15, clamp(roughness, 0.0, 1.0)); - vec3 specularIBL = specularEnv * roughnessAttenuation; - - iblContribution = (kD * diffuseIBL + kS * specularIBL) * aoWithFloor; - } - - vec3 color = ambient + lighting + iblContribution; - - FragColor = vec4(color, 1.0); - - float brightness = dot(color, vec3(0.2126, 0.7152, 0.0722)); - if (brightness > 1.0) - BrightColor = vec4(color, 1.0); - else - BrightColor = vec4(0.0, 0.0, 0.0, 1.0); - - FragColor.rgb = acesToneMapping(FragColor.rgb); -} diff --git a/shaders/vulkan/main.vert b/shaders/vulkan/main.vert deleted file mode 100644 index 2da26f92..00000000 --- a/shaders/vulkan/main.vert +++ /dev/null @@ -1,47 +0,0 @@ -#version 450 -layout(location = 0) in vec3 aPos; -layout(location = 1) in vec4 aColor; -layout(location = 2) in vec2 aTexCoord; -layout(location = 3) in vec3 aNormal; -layout(location = 4) in vec3 aTangent; -layout(location = 5) in vec3 aBitangent; -layout(location = 6) in mat4 instanceModel; - -layout(set = 0, binding = 0) uniform UBO { - mat4 model; - mat4 view; - mat4 projection; - bool isInstanced; -} -uniforms; - -layout(location = 0) out vec2 TexCoord; -layout(location = 1) out vec4 outColor; -layout(location = 2) out vec3 Normal; -layout(location = 3) out vec3 FragPos; -layout(location = 4) out mat3 TBN; - -invariant gl_Position; - -void main() { - mat4 modelMatrix = uniforms.model; - if (uniforms.isInstanced) { - modelMatrix = instanceModel; - } - - mat4 mvp = uniforms.projection * uniforms.view * modelMatrix; - gl_Position = mvp * vec4(aPos, 1.0); - - FragPos = vec3(modelMatrix * vec4(aPos, 1.0)); - // Flip V coordinate to match texture orientation (textures are flipped on - // load) - TexCoord = vec2(aTexCoord.x, 1.0 - aTexCoord.y); - outColor = aColor; - - mat3 normalMatrix = transpose(inverse(mat3(modelMatrix))); - Normal = normalize(normalMatrix * aNormal); - vec3 N = Normal; - vec3 T = normalize(normalMatrix * aTangent); - vec3 B = normalize(normalMatrix * aBitangent); - TBN = mat3(T, B, N); -} diff --git a/shaders/vulkan/shadows/depth.vert b/shaders/vulkan/shadows/depth.vert deleted file mode 100644 index dc03515d..00000000 --- a/shaders/vulkan/shadows/depth.vert +++ /dev/null @@ -1,20 +0,0 @@ -#version 450 -layout(location = 0) in vec3 aPos; -layout(location = 6) in mat4 instanceModel; - -layout(set = 0, binding = 0) uniform UBO { - mat4 model; - mat4 view; - mat4 projection; - bool isInstanced; -}; - -invariant gl_Position; - -void main() { - if (isInstanced) { - gl_Position = projection * view * instanceModel * vec4(aPos, 1.0); - } else { - gl_Position = projection * view * model * vec4(aPos, 1.0); - } -} diff --git a/shaders/vulkan/shadows/empty.frag b/shaders/vulkan/shadows/empty.frag deleted file mode 100644 index 54666ce5..00000000 --- a/shaders/vulkan/shadows/empty.frag +++ /dev/null @@ -1,3 +0,0 @@ -#version 450 - -void main() {} \ No newline at end of file diff --git a/shaders/vulkan/shadows/point_depth.frag b/shaders/vulkan/shadows/point_depth.frag deleted file mode 100644 index 73605e00..00000000 --- a/shaders/vulkan/shadows/point_depth.frag +++ /dev/null @@ -1,15 +0,0 @@ -#version 450 -layout(location = 0) in vec4 FragPos; - -layout(set = 1, binding = 0) uniform Uniforms { - vec3 lightPos; - float far_plane; -}; - -void main() { - float lightDistance = length(FragPos.xyz - lightPos); - - lightDistance = lightDistance / far_plane; - - gl_FragDepth = lightDistance; -} \ No newline at end of file diff --git a/shaders/vulkan/shadows/point_depth.geom b/shaders/vulkan/shadows/point_depth.geom deleted file mode 100644 index ab3a492f..00000000 --- a/shaders/vulkan/shadows/point_depth.geom +++ /dev/null @@ -1,19 +0,0 @@ -#version 450 core -layout(triangles) in; -layout(triangle_strip, max_vertices = 18) out; - -layout(set = 2, binding = 0) uniform ShadowMatrices { mat4 shadowMatrices[6]; }; - -layout(location = 0) out vec4 FragPos; - -void main() { - for (int face = 0; face < 6; face++) { - gl_Layer = face; - for (int i = 0; i < 3; i++) { - FragPos = gl_in[i].gl_Position; - gl_Position = shadowMatrices[face] * FragPos; - EmitVertex(); - } - EndPrimitive(); - } -} diff --git a/shaders/vulkan/shadows/point_depth.vert b/shaders/vulkan/shadows/point_depth.vert deleted file mode 100644 index 322d9721..00000000 --- a/shaders/vulkan/shadows/point_depth.vert +++ /dev/null @@ -1,16 +0,0 @@ -#version 450 -layout(location = 0) in vec3 aPos; -layout(location = 6) in mat4 instanceModel; - -layout(set = 0, binding = 0) uniform UBO { - mat4 model; - bool isInstanced; -}; - -void main() { - if (isInstanced) { - gl_Position = model * instanceModel * vec4(aPos, 1.0); - } else { - gl_Position = model * vec4(aPos, 1.0); - } -} \ No newline at end of file diff --git a/shaders/vulkan/shadows/point_depth_nogeom.frag b/shaders/vulkan/shadows/point_depth_nogeom.frag deleted file mode 100644 index 07c9b639..00000000 --- a/shaders/vulkan/shadows/point_depth_nogeom.frag +++ /dev/null @@ -1,15 +0,0 @@ -#version 450 -layout(location = 0) in vec4 FragPos; - -layout(set = 1, binding = 0) uniform Uniforms { - vec3 lightPos; - float far_plane; -}; - -void main() { - float lightDistance = length(FragPos.xyz - lightPos); - - lightDistance = lightDistance / far_plane; - - gl_FragDepth = lightDistance; -} diff --git a/shaders/vulkan/shadows/point_depth_nogeom.vert b/shaders/vulkan/shadows/point_depth_nogeom.vert deleted file mode 100644 index f8e8f649..00000000 --- a/shaders/vulkan/shadows/point_depth_nogeom.vert +++ /dev/null @@ -1,27 +0,0 @@ -#version 450 -layout(location = 0) in vec3 aPos; -layout(location = 6) in mat4 instanceModel; - -layout(set = 0, binding = 0) uniform UBO { - mat4 model; - bool isInstanced; -}; - -layout(set = 2, binding = 0) uniform ShadowUniforms { - mat4 shadowMatrix; // Single shadow matrix for current face - int faceIndex; // Which cubemap face we're rendering (0-5) -}; - -layout(location = 0) out vec4 FragPos; - -void main() { - vec4 worldPos; - if (isInstanced) { - worldPos = model * instanceModel * vec4(aPos, 1.0); - } else { - worldPos = model * vec4(aPos, 1.0); - } - - FragPos = worldPos; - gl_Position = shadowMatrix * worldPos; -} diff --git a/shaders/vulkan/shadows/ssao.frag b/shaders/vulkan/shadows/ssao.frag deleted file mode 100644 index 472c8d4f..00000000 --- a/shaders/vulkan/shadows/ssao.frag +++ /dev/null @@ -1,73 +0,0 @@ -#version 450 -layout(location = 0) out float FragColor; - -layout(location = 0) in vec2 TexCoord; - -layout(set = 1, binding = 0) uniform Paramters { - mat4 projection; - mat4 view; - vec2 noiseScale; -}; - -layout(set = 1, binding = 1) uniform Samples { - vec3 samples[64]; -}; - -layout(set = 2, binding = 0) uniform sampler2D gPosition; -layout(set = 2, binding = 1) uniform sampler2D gNormal; -layout(set = 2, binding = 2) uniform sampler2D texNoise; - -const int kernelSize = 64; -const float radius = 0.5; -const float bias = 0.025; - -void main() { - vec3 fragPosWorld = texture(gPosition, TexCoord).xyz; - vec3 normalWorld = texture(gNormal, TexCoord).rgb; - - if (length(normalWorld) < 0.001) { - // Treat missing/invalid normals as fully lit (no occlusion) - FragColor = 1.0; - return; - } - - vec3 fragPos = (view * vec4(fragPosWorld, 1.0)).xyz; - vec3 normal = normalize((view * vec4(normalWorld, 0.0)).xyz); - - vec3 randomVec = normalize(texture(texNoise, TexCoord * noiseScale).xyz * 2.0 - 1.0); - vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal)); - vec3 bitangent = cross(normal, tangent); - mat3 TBN = mat3(tangent, bitangent, normal); - - float occlusion = 0.0; - int validSamples = 0; - - for (int i = 0; i < kernelSize; i++) { - vec3 samplePos = TBN * samples[i]; - samplePos = fragPos + samplePos * radius; - - vec4 offset = projection * vec4(samplePos, 1.0); - offset.xyz /= offset.w; - offset.xy = offset.xy * 0.5 + 0.5; - - if (offset.x < 0.0 || offset.x > 1.0 || offset.y < 0.0 || offset.y > 1.0) { - continue; - } - - vec3 samplePosWorld = texture(gPosition, offset.xy).xyz; - float sampleDepth = (view * vec4(samplePosWorld, 1.0)).z; - - float rangeCheck = smoothstep(0.0, 1.0, radius / (abs(fragPos.z - sampleDepth) + 0.001)); - - occlusion += (sampleDepth >= samplePos.z + bias ? 1.0 : 0.0) * rangeCheck; - validSamples++; - } - - if (validSamples > 0) { - occlusion = 1.0 - (occlusion / float(validSamples)); - } else { - occlusion = 1.0; - } - - FragColor = occlusion; -} \ No newline at end of file diff --git a/shaders/vulkan/shadows/ssao_blur.frag b/shaders/vulkan/shadows/ssao_blur.frag deleted file mode 100644 index 07151629..00000000 --- a/shaders/vulkan/shadows/ssao_blur.frag +++ /dev/null @@ -1,18 +0,0 @@ -#version 450 -layout(location = 0) out float FragColor; - -layout(location = 0) in vec2 TexCoord; - -layout(set = 2, binding = 0) uniform sampler2D inSSAO; - -void main() { - vec2 texelSize = 1.0 / vec2(textureSize(inSSAO, 0)); - float result = 0.0; - for (int x = -2; x <= 2; x++) { - for (int y = -2; y <= 2; y++) { - vec2 offset = vec2(float(x), float(y)) * texelSize; - result += texture(inSSAO, TexCoord + offset).r; - } - } - FragColor = result / 25.0; -} \ No newline at end of file diff --git a/shaders/vulkan/simple/color.frag b/shaders/vulkan/simple/color.frag deleted file mode 100644 index dbfe33b1..00000000 --- a/shaders/vulkan/simple/color.frag +++ /dev/null @@ -1,13 +0,0 @@ -#version 450 -layout(location = 0) in vec4 vertexColor; - -layout(location = 0) out vec4 FragColor; -layout(location = 1) out vec4 BrightColor; - -void main() { - vec3 color = vertexColor.rgb / (vertexColor.rgb + vec3(1.0)); - FragColor = vec4(color, vertexColor.a); - if (length(color) > 1.0) { - BrightColor = vec4(color, vertexColor.a); - } -} \ No newline at end of file diff --git a/shaders/vulkan/simple/color.vert b/shaders/vulkan/simple/color.vert deleted file mode 100644 index 1ba42f6a..00000000 --- a/shaders/vulkan/simple/color.vert +++ /dev/null @@ -1,24 +0,0 @@ -#version 450 -layout(location = 0) in vec3 aPos; -layout(location = 1) in vec4 aColor; -layout(location = 6) in mat4 instanceModel; - -layout(location = 0) out vec4 vertexColor; - -layout(set = 0, binding = 0) uniform UBO { - mat4 model; - mat4 view; - mat4 projection; - bool isInstanced; -}; - -void main() { - mat4 mvp; - if (isInstanced) { - mvp = projection * view * instanceModel; - } else { - mvp = projection * view * model; - } - gl_Position = mvp * vec4(aPos, 1.0); - vertexColor = aColor; -} diff --git a/shaders/vulkan/simple/debug.frag b/shaders/vulkan/simple/debug.frag deleted file mode 100644 index 914c5794..00000000 --- a/shaders/vulkan/simple/debug.frag +++ /dev/null @@ -1,6 +0,0 @@ -#version 450 -layout(location = 0) out vec4 FragColor; - -void main() { - FragColor = vec4(1.0, 0.0, 1.0, 1.0); -} \ No newline at end of file diff --git a/shaders/vulkan/simple/debug.vert b/shaders/vulkan/simple/debug.vert deleted file mode 100644 index a2146e95..00000000 --- a/shaders/vulkan/simple/debug.vert +++ /dev/null @@ -1,4 +0,0 @@ -#version 450 -layout(location = 0) in vec3 aPos; - -void main() { gl_Position = vec4(aPos, 1.0); } \ No newline at end of file diff --git a/shaders/vulkan/simple/texture.frag b/shaders/vulkan/simple/texture.frag deleted file mode 100644 index 3c962896..00000000 --- a/shaders/vulkan/simple/texture.frag +++ /dev/null @@ -1,85 +0,0 @@ -#version 450 -layout(location = 0) in vec2 TexCoord; -layout(location = 1) in vec4 outColor; - -layout(location = 0) out vec4 FragColor; - -layout(set = 2, binding = 0) uniform sampler2D texture1; -layout(set = 2, binding = 1) uniform sampler2D texture2; -layout(set = 2, binding = 2) uniform sampler2D texture3; -layout(set = 2, binding = 3) uniform sampler2D texture4; -layout(set = 2, binding = 4) uniform sampler2D texture5; -layout(set = 2, binding = 5) uniform sampler2D texture6; -layout(set = 2, binding = 6) uniform sampler2D texture7; -layout(set = 2, binding = 7) uniform sampler2D texture8; -layout(set = 2, binding = 8) uniform sampler2D texture9; -layout(set = 2, binding = 9) uniform sampler2D texture10; -layout(set = 2, binding = 10) uniform sampler2D texture11; -layout(set = 2, binding = 11) uniform sampler2D texture12; -layout(set = 2, binding = 12) uniform sampler2D texture13; -layout(set = 2, binding = 13) uniform sampler2D texture14; -layout(set = 2, binding = 14) uniform sampler2D texture15; -layout(set = 2, binding = 15) uniform sampler2D texture16; - -layout(set = 1, binding = 0) uniform UBO { - bool useTexture; - bool onlyTexture; - int textureCount; -}; - -vec4 calculateAllTextures() { - vec4 color = vec4(0.0); - - for (int i = 0; i < textureCount; i++) { - if (i == 0) { - color += texture(texture1, TexCoord); - } else if (i == 1) { - color += texture(texture2, TexCoord); - } else if (i == 2) { - color += texture(texture3, TexCoord); - } else if (i == 3) { - color += texture(texture4, TexCoord); - } else if (i == 4) { - color += texture(texture5, TexCoord); - } else if (i == 5) { - color += texture(texture6, TexCoord); - } else if (i == 6) { - color += texture(texture7, TexCoord); - } else if (i == 7) { - color += texture(texture8, TexCoord); - } else if (i == 8) { - color += texture(texture9, TexCoord); - } else if (i == 9) { - color += texture(texture10, TexCoord); - } else if (i == 10) { - color += texture(texture11, TexCoord); - } else if (i == 11) { - color += texture(texture12, TexCoord); - } else if (i == 12) { - color += texture(texture13, TexCoord); - } else if (i == 13) { - color += texture(texture14, TexCoord); - } else if (i == 14) { - color += texture(texture15, TexCoord); - } else if (i == 15) { - color += texture(texture16, TexCoord); - } - } - - color /= float(textureCount); - - return color; -} - -void main() { - if (onlyTexture) { - FragColor = calculateAllTextures(); - return; - } - - if (useTexture) { - FragColor = calculateAllTextures() * outColor; - } else { - FragColor = outColor; - } -} \ No newline at end of file diff --git a/shaders/vulkan/simple/texture.vert b/shaders/vulkan/simple/texture.vert deleted file mode 100644 index 5a4a361a..00000000 --- a/shaders/vulkan/simple/texture.vert +++ /dev/null @@ -1,20 +0,0 @@ -#version 450 -layout(location = 0) in vec3 aPos; -layout(location = 1) in vec4 aColor; -layout(location = 2) in vec2 aTexCoord; - -layout(set = 0, binding = 0) uniform UBO { - mat4 model; - mat4 view; - mat4 projection; -}; - -layout(location = 0) out vec2 TexCoord; -layout(location = 1) out vec4 outColor; - -void main() { - mat4 mvp = projection * view * model; - gl_Position = mvp * vec4(aPos, 1.0); - TexCoord = aTexCoord; - outColor = aColor; -} diff --git a/shaders/vulkan/terrain/fluid.frag b/shaders/vulkan/terrain/fluid.frag deleted file mode 100644 index 2ab747bc..00000000 --- a/shaders/vulkan/terrain/fluid.frag +++ /dev/null @@ -1,189 +0,0 @@ -#version 450 -layout(location = 0) in vec2 TexCoord; -layout(location = 1) in vec3 WorldPos; -layout(location = 2) in vec3 WorldNormal; -layout(location = 3) in vec3 WorldTangent; -layout(location = 4) in vec3 WorldBitangent; - -layout(location = 0) out vec4 FragColor; -layout(location = 1) out vec4 BrightColor; - -layout(set = 2, binding = 0) uniform sampler2D sceneTexture; -layout(set = 2, binding = 1) uniform sampler2D sceneDepth; -layout(set = 2, binding = 2) uniform sampler2D reflectionTexture; -layout(set = 2, binding = 3) uniform sampler2D refractionTexture; -layout(set = 2, binding = 4) uniform sampler2D movementTexture; -layout(set = 2, binding = 5) uniform sampler2D normalTexture; - -layout(set = 1, binding = 0) uniform Uniforms { - vec4 waterColor; - vec3 cameraPos; - float time; - mat4 projection; - mat4 view; - mat4 invProjection; - mat4 invView; - vec3 lightDirection; - vec3 lightColor; -}; - -layout(set = 1, binding = 1) uniform Parameters { - float refractionStrength; - float reflectionStrength; - float depthFade; - int hasNormalTexture; - int hasMovementTexture; - vec3 windForce; -}; - -void main() { - vec3 normal = normalize(WorldNormal); - vec3 viewDir = normalize(cameraPos - WorldPos); - - vec4 clipSpace = projection * view * vec4(WorldPos, 1.0); - vec3 ndc = clipSpace.xyz / clipSpace.w; - vec2 screenUV = ndc.xy * 0.5 + 0.5; - - float windStrength = length(windForce); - vec2 windDir = windStrength > 0.001 ? normalize(windForce.xy) : vec2(1.0, 0.0); - - float waveSpeed = 0.15 + windStrength * 0.3; - float waveAmplitude = 0.01 + windStrength * 0.02; - float waveFrequency = 30.0 + windStrength * 10.0; - - vec2 waveOffset; - waveOffset.x = sin((TexCoord.x * windDir.x + time * waveSpeed) * waveFrequency); - waveOffset.y = cos((TexCoord.y * windDir.y - time * waveSpeed) * waveFrequency); - waveOffset *= waveAmplitude; - - vec2 flowOffset = vec2(0.0); - if (hasMovementTexture == 1) { - vec2 windUV = windForce.xy * time * 0.05; - vec2 movementUV = TexCoord * 2.0 + windUV; - vec2 movementSample = texture(movementTexture, movementUV).rg; - - movementSample = movementSample * 2.0 - 1.0; - - flowOffset = movementSample * windStrength * 0.15; - - waveOffset += flowOffset * 0.5; - } - - if (hasNormalTexture == 1) { - vec3 T = normalize(WorldTangent); - vec3 B = normalize(WorldBitangent); - vec3 N = normalize(WorldNormal); - mat3 TBN = mat3(T, B, N); - - float normalSpeed = 0.03 + windStrength * 0.05; - vec2 normalUV1 = TexCoord * 5.0 + waveOffset * 10.0 + windForce.xy * time * normalSpeed; - vec2 normalUV2 = TexCoord * 3.0 - waveOffset * 8.0 - windForce.xy * time * normalSpeed * 0.8; - - vec3 normalMap1 = texture(normalTexture, normalUV1).rgb; - vec3 normalMap2 = texture(normalTexture, normalUV2).rgb; - - normalMap1 = normalMap1 * 2.0 - 1.0; - normalMap2 = normalMap2 * 2.0 - 1.0; - - vec3 blendedNormal = normalize(normalMap1 + normalMap2); - - vec3 worldSpaceNormal = normalize(TBN * blendedNormal); - - float normalStrength = 0.5 + windStrength * 0.3; - normal = normalize(mix(N, worldSpaceNormal, normalStrength)); - } - - vec2 reflectionUV = screenUV; - reflectionUV.y = 1.0 - reflectionUV.y; - reflectionUV += waveOffset * 0.3; - - vec2 refractionUV = screenUV - waveOffset * 0.2; - - bool reflectionInBounds = (reflectionUV.x >= 0.0 && reflectionUV.x <= 1.0 && - reflectionUV.y >= 0.0 && reflectionUV.y <= 1.0); - bool refractionInBounds = (refractionUV.x >= 0.0 && refractionUV.x <= 1.0 && - refractionUV.y >= 0.0 && refractionUV.y <= 1.0); - - reflectionUV = clamp(reflectionUV, 0.05, 0.95); - refractionUV = clamp(refractionUV, 0.05, 0.95); - - vec2 reflectionEdgeFade = smoothstep(0.0, 0.15, reflectionUV) * smoothstep(1.0, 0.85, reflectionUV); - float reflectionFadeFactor = reflectionEdgeFade.x * reflectionEdgeFade.y; - - vec2 refractionEdgeFade = smoothstep(0.0, 0.15, refractionUV) * smoothstep(1.0, 0.85, refractionUV); - float refractionFadeFactor = refractionEdgeFade.x * refractionEdgeFade.y; - - if (!reflectionInBounds) { - reflectionFadeFactor *= 0.3; - } - if (!refractionInBounds) { - refractionFadeFactor *= 0.3; - } - - vec4 reflectionSample = texture(reflectionTexture, reflectionUV); - vec4 refractionSample = texture(refractionTexture, refractionUV); - vec4 sceneFallback = texture(sceneTexture, screenUV); - - bool validReflection = (length(reflectionSample.rgb) > 0.01); - bool validRefraction = (length(refractionSample.rgb) > 0.01); - - if (!validReflection) { - reflectionSample = sceneFallback; - } - if (!validRefraction) { - refractionSample = sceneFallback; - } - - float fresnel = pow(1.0 - clamp(dot(normal, viewDir), 0.0, 1.0), 3.0); - fresnel = mix(0.02, 1.0, fresnel); - fresnel *= reflectionStrength; - - vec3 combined = mix(refractionSample.rgb, reflectionSample.rgb, fresnel); - - float waterTint = clamp(depthFade * 0.3, 0.0, 0.5); - combined = mix(combined, waterColor.rgb, waterTint); - - float foamAmount = 0.0; - if (hasMovementTexture == 1) { - float foamFactor = smoothstep(0.7, 1.0, length(flowOffset) * windStrength); - foamAmount = foamFactor * 0.2; - combined = mix(combined, vec3(1.0), foamAmount); - } - - vec3 lightDir = normalize(-lightDirection); - - float diffuse = max(dot(normal, lightDir), 0.0); - diffuse = diffuse * 0.3; - - vec3 halfDir = normalize(lightDir + viewDir); - float specAngle = max(dot(normal, halfDir), 0.0); - float specular = pow(specAngle, 128.0); - - specular *= (fresnel * 0.5 + 0.5); - - float waveVariation = sin(TexCoord.x * 50.0 + time * 2.0) * 0.5 + 0.5; - waveVariation *= cos(TexCoord.y * 50.0 - time * 1.5) * 0.5 + 0.5; - specular *= (0.7 + waveVariation * 0.3); - - vec3 lighting = lightColor * (diffuse + specular * 2.0); - combined += lighting; - - vec3 specularHighlight = lightColor * specular * 2.5; - - specularHighlight += vec3(foamAmount * 2.0); - - float alpha = mix(0.7, 0.95, fresnel); - - FragColor = vec4(combined, alpha); - - float luminance = max(max(combined.r, combined.g), combined.b); - vec3 bloomColor = vec3(0.0); - - if (luminance > 1.0) { - bloomColor = combined - 1.0; - } - - bloomColor += specularHighlight; - - BrightColor = vec4(bloomColor, alpha); -} \ No newline at end of file diff --git a/shaders/vulkan/terrain/fluid.vert b/shaders/vulkan/terrain/fluid.vert deleted file mode 100644 index 670ad966..00000000 --- a/shaders/vulkan/terrain/fluid.vert +++ /dev/null @@ -1,27 +0,0 @@ -#version 450 -layout(location = 0) in vec3 aPos; -layout(location = 1) in vec2 aTexCoord; -layout(location = 2) in vec3 aNormal; -layout(location = 3) in vec3 aTangent; -layout(location = 4) in vec3 aBitangent; - -layout(set = 0, binding = 0) uniform UBO { - mat4 model; - mat4 view; - mat4 projection; -}; - -layout(location = 0) out vec2 TexCoord; -layout(location = 1) out vec3 WorldPos; -layout(location = 2) out vec3 WorldNormal; -layout(location = 3) out vec3 WorldTangent; -layout(location = 4) out vec3 WorldBitangent; - -void main() { - gl_Position = projection * view * model * vec4(aPos, 1.0); - TexCoord = aTexCoord; - WorldPos = vec3(model * vec4(aPos, 1.0)); - WorldNormal = normalize(mat3(model) * aNormal); - WorldTangent = normalize(mat3(model) * aTangent); - WorldBitangent = normalize(mat3(model) * aBitangent); -} \ No newline at end of file diff --git a/shaders/vulkan/terrain/terrain.frag b/shaders/vulkan/terrain/terrain.frag deleted file mode 100644 index e0262ab7..00000000 --- a/shaders/vulkan/terrain/terrain.frag +++ /dev/null @@ -1,211 +0,0 @@ -#version 450 -layout(location = 0) in vec2 TexCoord; -layout(location = 1) in vec3 FragPos; -layout(location = 2) in float Height; -layout(location = 3) in vec4 FragPosLightSpace; - -layout(location = 0) out vec4 FragColor; -layout(location = 1) out vec4 BrightColor; - -layout(set = 2, binding = 0) uniform sampler2D heightMap; -layout(set = 2, binding = 1) uniform sampler2D moistureMap; -layout(set = 2, binding = 2) uniform sampler2D temperatureMap; -layout(set = 2, binding = 3) uniform sampler2D shadowMap; - -layout(set = 2, binding = 4) uniform sampler2D texture0; -layout(set = 2, binding = 5) uniform sampler2D texture1; -layout(set = 2, binding = 6) uniform sampler2D texture2; -layout(set = 2, binding = 7) uniform sampler2D texture3; -layout(set = 2, binding = 8) uniform sampler2D texture4; -layout(set = 2, binding = 9) uniform sampler2D texture5; -layout(set = 2, binding = 10) uniform sampler2D texture6; -layout(set = 2, binding = 11) uniform sampler2D texture7; -layout(set = 2, binding = 12) uniform sampler2D texture8; -layout(set = 2, binding = 13) uniform sampler2D texture9; -layout(set = 2, binding = 14) uniform sampler2D texture10; -layout(set = 2, binding = 15) uniform sampler2D texture11; - -layout(push_constant) uniform PushConstants { - bool isFromMap; - vec4 directionalColor; - float directionalIntensity; - bool hasLight; - bool useShadowMap; - vec3 lightDir; - vec3 viewDir; - float ambientStrength; - float shadowBias; - int biomesCount; - float diffuseStrength; - float specularStrength; -} ; - -layout(set = 1, binding = 0) uniform TerrainParameters { - float maxPeak; - float seaLevel; -}; - -struct Biome { - int id; - vec4 tintColor; - int useTexture; - int textureId; - float minHeight; - float maxHeight; - float minMoisture; - float maxMoisture; - float minTemperature; - float maxTemperature; -}; - -layout(std430, set = 3, binding = 0) buffer BiomeBuffer { - Biome biomes[]; -}; - -vec4 sampleBiomeTexture(int id, vec2 uv) { - if (id == 0) return texture(texture0, uv); - if (id == 1) return texture(texture1, uv); - if (id == 2) return texture(texture2, uv); - if (id == 3) return texture(texture3, uv); - if (id == 4) return texture(texture4, uv); - if (id == 5) return texture(texture5, uv); - if (id == 6) return texture(texture6, uv); - if (id == 7) return texture(texture7, uv); - if (id == 8) return texture(texture8, uv); - if (id == 9) return texture(texture9, uv); - if (id == 10) return texture(texture10, uv); - if (id == 11) return texture(texture11, uv); - return vec4(1,0,1,1); -} - -vec4 triplanarBlend(int idx, vec3 normal, vec3 worldPos, float scale) { - vec3 blend = abs(normal); - blend = (blend - 0.2) * 7.0; - blend = clamp(blend, 0.0, 1.0); - blend /= (blend.x + blend.y + blend.z); - - vec4 xProj = sampleBiomeTexture(idx, worldPos.yz * scale); - vec4 yProj = sampleBiomeTexture(idx, worldPos.xz * scale); - vec4 zProj = sampleBiomeTexture(idx, worldPos.xy * scale); - - return xProj * blend.x + yProj * blend.y + zProj * blend.z; -} - -vec3 calculateNormal(sampler2D heightMap, vec2 texCoord, float heightScale) -{ - float h = texture(heightMap, texCoord).r * heightScale; - - float dx = dFdx(h); - float dy = dFdy(h); - - vec3 n = normalize(vec3(-dx, 1.0, -dy)); - return n; -} - -float smoothStepRange(float value, float minV, float maxV) { - return smoothstep(minV, maxV, value); -} - -float calculateShadow(vec4 fragPosLightSpace, vec3 normal) { - vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; - projCoords = projCoords * 0.5 + 0.5; - - if(projCoords.z > 1.0 || projCoords.x < 0.0 || projCoords.x > 1.0 || - projCoords.y < 0.0 || projCoords.y > 1.0) - return 0.0; - - float currentDepth = projCoords.z; - float bias = max(shadowBias * (1.0 - dot(normal, lightDir)), shadowBias * 0.1); - - float shadow = 0.0; - vec2 texelSize = 1.0 / textureSize(shadowMap, 0); - for(int x = -1; x <= 1; ++x) { - for(int y = -1; y <= 1; ++y) { - float pcfDepth = texture(shadowMap, projCoords.xy + vec2(x, y) * texelSize).r; - shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0; - } - } - shadow /= 9.0; - - return shadow; -} - -vec3 acesToneMapping(vec3 color) { - const float a = 2.51; - const float b = 0.03; - const float c = 2.43; - const float d = 0.59; - const float e = 0.14; - return clamp((color * (a * color + b)) / (color * (c * color + d) + e), 0.0, 1.0); -} - -void main() { - if (biomesCount <= 0) { - FragColor = vec4(vec3((Height + seaLevel) / maxPeak), 1.0); - return; - } - - float h = isFromMap ? texture(heightMap, TexCoord).r * 255.0 : (Height + seaLevel) / maxPeak * 255.0; - float m = texture(moistureMap, TexCoord).r * 255.0; - float t = texture(temperatureMap, TexCoord).r * 255.0; - - float texelSize = 1.0 / textureSize(heightMap, 0).x; - float heightScale = 64.0; - vec3 normal = calculateNormal(heightMap, TexCoord, heightScale); - - // === BIOME BLENDING === - vec4 baseColor = vec4(0.0); - float totalWeight = 0.0; - - for (int i = 0; i < biomesCount; i++) { - Biome b = biomes[i]; - - float hW = (b.minHeight < 0.0 && b.maxHeight < 0.0) ? 1.0 : smoothStepRange(h, b.minHeight, b.maxHeight); - float mW = (b.minMoisture < 0.0 && b.maxMoisture < 0.0) ? 1.0 : smoothStepRange(m, b.minMoisture, b.maxMoisture); - float tW = (b.minTemperature < 0.0 && b.maxTemperature < 0.0) ? 1.0 : smoothStepRange(t, b.minTemperature, b.maxTemperature); - - float weight = (1.0 - hW) * mW * tW; - if (weight > 0.001) { - vec4 texColor = (b.useTexture == 1) - ? triplanarBlend(i, normal, FragPos, 0.1) - : b.tintColor; - baseColor += texColor * weight; - totalWeight += weight; - } - } - - baseColor /= max(totalWeight, 0.001); - - float detail = texture(heightMap, TexCoord * 64.0).r * 0.1 + 0.9; - baseColor.rgb *= detail; - - vec3 finalColor; - - if (hasLight) { - vec3 L = normalize(-lightDir); - vec3 N = normalize(normal); - vec3 V = normalize(viewDir); - - vec3 ambient = ambientStrength * baseColor.rgb; - - float diff = max(dot(N, L), 0.0); - vec3 diffuse = diffuseStrength * diff * directionalColor.rgb * directionalIntensity * baseColor.rgb; - - vec3 H = normalize(L + V); - float spec = pow(max(dot(N, H), 0.0), 32.0); - vec3 specular = specularStrength * spec * directionalColor.rgb * directionalIntensity; - - float shadow = 0.0; - if (useShadowMap) { - shadow = calculateShadow(FragPosLightSpace, N); - } - - finalColor = ambient + (1.0 - shadow) * (diffuse + specular); - - } else { - finalColor = ambientStrength * baseColor.rgb; - } - - FragColor = vec4(acesToneMapping(finalColor), 1.0); - BrightColor = vec4(0.0); -} \ No newline at end of file diff --git a/shaders/vulkan/terrain/terrain.vert b/shaders/vulkan/terrain/terrain.vert deleted file mode 100644 index f12421d6..00000000 --- a/shaders/vulkan/terrain/terrain.vert +++ /dev/null @@ -1,16 +0,0 @@ -#version 450 -layout(location = 0) in vec3 aPos; -layout(location = 1) in vec2 aTexCoord; - -layout(set = 0, binding = 0) uniform UBO { - mat4 model; - mat4 view; - mat4 projection; -}; - -layout(location = 0) out vec2 TexCoord; - -void main() { - gl_Position = projection * view * model * vec4(aPos, 1.0); - TexCoord = aTexCoord; -} \ No newline at end of file diff --git a/shaders/vulkan/terrain/terrain_control.tesc b/shaders/vulkan/terrain/terrain_control.tesc deleted file mode 100644 index 01a414da..00000000 --- a/shaders/vulkan/terrain/terrain_control.tesc +++ /dev/null @@ -1,66 +0,0 @@ -#version 450 - -layout(vertices = 4) out; - -layout(location = 0) in vec2 TexCoord[]; -layout(location = 0) out vec2 TextureCoord[]; - -layout(set = 0, binding = 0) uniform UBO { - mat4 model; - mat4 view; - mat4 projection; -}; - -in gl_PerVertex { - vec4 gl_Position; - float gl_PointSize; - float gl_ClipDistance[]; -} -gl_in[gl_MaxPatchVertices]; - -void main() { - gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; - TextureCoord[gl_InvocationID] = TexCoord[gl_InvocationID]; - - if (gl_InvocationID == 0) { - const int MIN_TESS_LEVEL = 4; - const int MAX_TESS_LEVEL = 64; - const float MIN_DISTANCE = 20; - const float MAX_DISTANCE = 800; - - vec4 eyeSpacePos00 = view * model * gl_in[0].gl_Position; - vec4 eyeSpacePos01 = view * model * gl_in[1].gl_Position; - vec4 eyeSpacePos10 = view * model * gl_in[2].gl_Position; - vec4 eyeSpacePos11 = view * model * gl_in[3].gl_Position; - - float dist00 = clamp((abs(eyeSpacePos00.z) - MIN_DISTANCE) / - (MAX_DISTANCE - MIN_DISTANCE), - 0.0, 1.0); - float dist01 = clamp((abs(eyeSpacePos01.z) - MIN_DISTANCE) / - (MAX_DISTANCE - MIN_DISTANCE), - 0.0, 1.0); - float dist10 = clamp((abs(eyeSpacePos10.z) - MIN_DISTANCE) / - (MAX_DISTANCE - MIN_DISTANCE), - 0.0, 1.0); - float dist11 = clamp((abs(eyeSpacePos11.z) - MIN_DISTANCE) / - (MAX_DISTANCE - MIN_DISTANCE), - 0.0, 1.0); - - float tessLevel0 = mix(float(MAX_TESS_LEVEL), float(MIN_TESS_LEVEL), - min(dist10, dist00)); - float tessLevel1 = mix(float(MAX_TESS_LEVEL), float(MIN_TESS_LEVEL), - min(dist00, dist01)); - float tessLevel2 = mix(float(MAX_TESS_LEVEL), float(MIN_TESS_LEVEL), - min(dist01, dist11)); - float tessLevel3 = mix(float(MAX_TESS_LEVEL), float(MIN_TESS_LEVEL), - min(dist11, dist10)); - - gl_TessLevelOuter[0] = tessLevel0; - gl_TessLevelOuter[1] = tessLevel1; - gl_TessLevelOuter[2] = tessLevel2; - gl_TessLevelOuter[3] = tessLevel3; - - gl_TessLevelInner[0] = max(tessLevel1, tessLevel3); - gl_TessLevelInner[1] = max(tessLevel0, tessLevel2); - } -} \ No newline at end of file diff --git a/shaders/vulkan/terrain/terrain_eval.tese b/shaders/vulkan/terrain/terrain_eval.tese deleted file mode 100644 index 6ebf6e0c..00000000 --- a/shaders/vulkan/terrain/terrain_eval.tese +++ /dev/null @@ -1,55 +0,0 @@ -#version 450 -layout(quads, fractional_odd_spacing, ccw) in; - -layout(location = 0) in vec2 TextureCoord[]; - -layout(location = 0) out vec2 TexCoord; -layout(location = 1) out vec3 FragPos; -layout(location = 2) out float Height; -layout(location = 3) out vec4 FragPosLightSpace; - -layout(set = 5, binding = 0) uniform sampler2D heightMap; -layout(set = 0, binding = 0) uniform UBO { - mat4 model; - mat4 view; - mat4 projection; -}; -layout(set = 5, binding = 1) uniform Uniforms { - mat4 lightViewProj; - float maxPeak; - float seaLevel; - bool isFromMap; -}; - -void main() { - float u = gl_TessCoord.x; - float v = gl_TessCoord.y; - - vec2 t00 = TextureCoord[0]; - vec2 t01 = TextureCoord[1]; - vec2 t10 = TextureCoord[2]; - vec2 t11 = TextureCoord[3]; - - vec2 t0 = (t01 - t00) * u + t00; - vec2 t1 = (t11 - t10) * u + t10; - vec2 texCoord = (t1 - t0) * v + t0; - - Height = texture(heightMap, texCoord).r * maxPeak - seaLevel; - - vec4 p00 = gl_in[0].gl_Position; - vec4 p01 = gl_in[1].gl_Position; - vec4 p10 = gl_in[2].gl_Position; - vec4 p11 = gl_in[3].gl_Position; - - vec4 p0 = (p01 - p00) * u + p00; - vec4 p1 = (p11 - p10) * u + p10; - vec4 position = (p1 - p0) * v + p0; - - position.y += Height; - - gl_Position = projection * view * model * position; - - TexCoord = texCoord; - FragPos = vec3(model * position); - FragPosLightSpace = lightViewProj * model * position; -} \ No newline at end of file diff --git a/shaders/vulkan/ui/text.frag b/shaders/vulkan/ui/text.frag deleted file mode 100644 index 1d477c57..00000000 --- a/shaders/vulkan/ui/text.frag +++ /dev/null @@ -1,14 +0,0 @@ -#version 450 - -layout(location = 0) in vec2 texCoords; -layout(location = 0) out vec4 color; - -layout(set = 2, binding = 0) uniform sampler2D text; -layout(set = 1, binding = 0) uniform TextColor { - vec3 textColor; -}; - -void main() { - vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, texCoords).r); - color = vec4(textColor, 1.0) * sampled; -} \ No newline at end of file diff --git a/shaders/vulkan/ui/text.vert b/shaders/vulkan/ui/text.vert deleted file mode 100644 index 2f4ef201..00000000 --- a/shaders/vulkan/ui/text.vert +++ /dev/null @@ -1,11 +0,0 @@ -#version 450 -layout(location = 0) in vec4 vertex; // - -layout(location = 0) out vec2 texCoords; - -layout(set = 0, binding = 0) uniform Uniforms { mat4 projection; }; - -void main() { - gl_Position = projection * vec4(vertex.xy, 0.0, 1.0); - texCoords = vertex.zw; -} \ No newline at end of file diff --git a/shaders/vulkan/volumetric/volumetric.frag b/shaders/vulkan/volumetric/volumetric.frag deleted file mode 100644 index ef065003..00000000 --- a/shaders/vulkan/volumetric/volumetric.frag +++ /dev/null @@ -1,60 +0,0 @@ -#version 450 -layout(location = 0) in vec2 TexCoords; - -layout(location = 0) out vec4 FragColor; - -layout(set = 2, binding = 0) uniform sampler2D sceneTexture; -layout(set = 1, binding = 0) uniform Sun { - vec2 sunPos; -}; - -layout(set = 1, binding = 1) uniform DirectionalLight { - vec3 color; -} directionalLight; - -layout(set = 1, binding = 2) uniform VolumetricParameters { - float density; - float weight; - float decay; - float exposure; -}; - -vec3 computeVolumetricLighting(vec2 uv) { - vec3 color = vec3(0.0); - - vec2 deltaTexCoord = (sunPos - uv) * density; - vec2 coord = uv; - float illuminationDecay = 1.0; - - const int NUM_SAMPLES = 100; - - for (int i = 0; i < NUM_SAMPLES; i++) { - coord += deltaTexCoord; - - if (coord.x < 0.0 || coord.x > 1.0 || coord.y < 0.0 || coord.y > 1.0) { - break; - } - - vec3 sampled = texture(sceneTexture, coord).rgb; - float brightness = dot(sampled, vec3(0.299, 0.587, 0.114)); - - vec3 atmosphere = directionalLight.color * 0.02; - - if (brightness > 0.5) { - atmosphere += sampled * 0.5; - } - - atmosphere *= illuminationDecay * weight; - color += atmosphere; - - illuminationDecay *= decay; - } - - return color * 5.0; -} - -void main() { - vec3 rays = computeVolumetricLighting(TexCoords); - - FragColor = vec4(rays, 1.0); -} diff --git a/shaders/vulkan/volumetric/volumetric.vert b/shaders/vulkan/volumetric/volumetric.vert deleted file mode 100644 index 222d589a..00000000 --- a/shaders/vulkan/volumetric/volumetric.vert +++ /dev/null @@ -1,11 +0,0 @@ -#version 450 - -layout(location = 0) in vec3 aPos; -layout(location = 2) in vec2 aTexCoords; - -layout(location = 0) out vec2 TexCoords; - -void main() { - gl_Position = vec4(aPos, 1.0); - TexCoords = aTexCoords; -}