Vulcan Nightmare

Experimentally bringing up vulcan support
This commit is contained in:
Kelsi 2026-02-21 19:41:21 -08:00
parent 863a786c48
commit 83b576e8d9
189 changed files with 12147 additions and 7820 deletions

View file

@ -34,8 +34,13 @@ endif()
# Find required packages # Find required packages
find_package(SDL2 REQUIRED) find_package(SDL2 REQUIRED)
find_package(OpenGL REQUIRED) find_package(Vulkan REQUIRED)
find_package(GLEW REQUIRED) # GL/GLEW kept temporarily for unconverted sub-renderers during Vulkan migration.
# These files compile against GL types but their code is never called — the Vulkan
# path is the only active rendering backend. Remove in Phase 7 when all renderers
# are converted and grep confirms zero GL references.
find_package(OpenGL QUIET)
find_package(GLEW QUIET)
find_package(OpenSSL REQUIRED) find_package(OpenSSL REQUIRED)
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
find_package(ZLIB REQUIRED) find_package(ZLIB REQUIRED)
@ -77,13 +82,65 @@ if(NOT glm_FOUND)
message(STATUS "GLM not found, will use system includes or download") message(STATUS "GLM not found, will use system includes or download")
endif() endif()
# GLM GTX extensions (quaternion, norm, etc.) require this flag on newer GLM versions # GLM GTX extensions (quaternion, norm, etc.) require this flag on newer GLM versions
add_compile_definitions(GLM_ENABLE_EXPERIMENTAL) add_compile_definitions(GLM_ENABLE_EXPERIMENTAL GLM_FORCE_DEPTH_ZERO_TO_ONE)
# SPIR-V shader compilation via glslc
find_program(GLSLC glslc HINTS ${Vulkan_GLSLC_EXECUTABLE} "$ENV{VULKAN_SDK}/bin")
if(GLSLC)
message(STATUS "Found glslc: ${GLSLC}")
else()
message(WARNING "glslc not found. Install the Vulkan SDK or vulkan-tools package.")
message(WARNING "Shaders will not be compiled to SPIR-V.")
endif()
# Function to compile GLSL shaders to SPIR-V
function(compile_shaders TARGET_NAME)
set(SHADER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/assets/shaders)
set(SPV_DIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/assets/shaders)
file(MAKE_DIRECTORY ${SPV_DIR})
file(GLOB GLSL_SOURCES "${SHADER_DIR}/*.glsl")
set(SPV_OUTPUTS)
foreach(GLSL_FILE ${GLSL_SOURCES})
get_filename_component(FILE_NAME ${GLSL_FILE} NAME)
# e.g. skybox.vert.glsl -> skybox.vert.spv
string(REGEX REPLACE "\\.glsl$" ".spv" SPV_NAME ${FILE_NAME})
set(SPV_FILE ${SPV_DIR}/${SPV_NAME})
# Determine shader stage from filename
if(FILE_NAME MATCHES "\\.vert\\.glsl$")
set(SHADER_STAGE vertex)
elseif(FILE_NAME MATCHES "\\.frag\\.glsl$")
set(SHADER_STAGE fragment)
elseif(FILE_NAME MATCHES "\\.comp\\.glsl$")
set(SHADER_STAGE compute)
elseif(FILE_NAME MATCHES "\\.geom\\.glsl$")
set(SHADER_STAGE geometry)
else()
message(WARNING "Cannot determine shader stage for: ${FILE_NAME}")
continue()
endif()
add_custom_command(
OUTPUT ${SPV_FILE}
COMMAND ${GLSLC} -fshader-stage=${SHADER_STAGE} -O ${GLSL_FILE} -o ${SPV_FILE}
DEPENDS ${GLSL_FILE}
COMMENT "Compiling SPIR-V: ${FILE_NAME} -> ${SPV_NAME}"
VERBATIM
)
list(APPEND SPV_OUTPUTS ${SPV_FILE})
endforeach()
add_custom_target(${TARGET_NAME}_shaders ALL DEPENDS ${SPV_OUTPUTS})
add_dependencies(${TARGET_NAME} ${TARGET_NAME}_shaders)
endfunction()
# StormLib for MPQ extraction tool (not needed for main executable) # StormLib for MPQ extraction tool (not needed for main executable)
find_library(STORMLIB_LIBRARY NAMES StormLib stormlib storm) find_library(STORMLIB_LIBRARY NAMES StormLib stormlib storm)
find_path(STORMLIB_INCLUDE_DIR StormLib.h PATH_SUFFIXES StormLib) find_path(STORMLIB_INCLUDE_DIR StormLib.h PATH_SUFFIXES StormLib)
# Include ImGui as a static library (we'll add the sources) # Include ImGui as a static library (Vulkan backend)
set(IMGUI_DIR ${CMAKE_CURRENT_SOURCE_DIR}/extern/imgui) set(IMGUI_DIR ${CMAKE_CURRENT_SOURCE_DIR}/extern/imgui)
if(EXISTS ${IMGUI_DIR}) if(EXISTS ${IMGUI_DIR})
add_library(imgui STATIC add_library(imgui STATIC
@ -93,19 +150,30 @@ if(EXISTS ${IMGUI_DIR})
${IMGUI_DIR}/imgui_widgets.cpp ${IMGUI_DIR}/imgui_widgets.cpp
${IMGUI_DIR}/imgui_demo.cpp ${IMGUI_DIR}/imgui_demo.cpp
${IMGUI_DIR}/backends/imgui_impl_sdl2.cpp ${IMGUI_DIR}/backends/imgui_impl_sdl2.cpp
${IMGUI_DIR}/backends/imgui_impl_opengl3.cpp ${IMGUI_DIR}/backends/imgui_impl_vulkan.cpp
) )
target_include_directories(imgui PUBLIC target_include_directories(imgui PUBLIC
${IMGUI_DIR} ${IMGUI_DIR}
${IMGUI_DIR}/backends ${IMGUI_DIR}/backends
) )
target_link_libraries(imgui PUBLIC SDL2::SDL2 OpenGL::GL ${CMAKE_DL_LIBS}) target_link_libraries(imgui PUBLIC SDL2::SDL2 Vulkan::Vulkan ${CMAKE_DL_LIBS})
target_compile_definitions(imgui PUBLIC IMGUI_IMPL_OPENGL_LOADER_GLEW)
else() else()
message(WARNING "ImGui not found in extern/imgui. Clone it with:") message(WARNING "ImGui not found in extern/imgui. Clone it with:")
message(WARNING " git clone https://github.com/ocornut/imgui.git extern/imgui") message(WARNING " git clone https://github.com/ocornut/imgui.git extern/imgui")
endif() endif()
# vk-bootstrap (Vulkan device/instance setup)
set(VK_BOOTSTRAP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/extern/vk-bootstrap)
if(EXISTS ${VK_BOOTSTRAP_DIR})
add_library(vk-bootstrap STATIC
${VK_BOOTSTRAP_DIR}/src/VkBootstrap.cpp
)
target_include_directories(vk-bootstrap PUBLIC ${VK_BOOTSTRAP_DIR}/src)
target_link_libraries(vk-bootstrap PUBLIC Vulkan::Vulkan)
else()
message(FATAL_ERROR "vk-bootstrap not found in extern/vk-bootstrap")
endif()
# Source files # Source files
set(WOWEE_SOURCES set(WOWEE_SOURCES
# Core # Core
@ -180,6 +248,15 @@ set(WOWEE_SOURCES
src/pipeline/terrain_mesh.cpp src/pipeline/terrain_mesh.cpp
# Rendering (Vulkan infrastructure)
src/rendering/vk_context.cpp
src/rendering/vk_utils.cpp
src/rendering/vk_shader.cpp
src/rendering/vk_texture.cpp
src/rendering/vk_buffer.cpp
src/rendering/vk_pipeline.cpp
src/rendering/vk_render_target.cpp
# Rendering # Rendering
src/rendering/renderer.cpp src/rendering/renderer.cpp
src/rendering/shader.cpp src/rendering/shader.cpp
@ -287,6 +364,13 @@ set(WOWEE_HEADERS
include/pipeline/dbc_loader.hpp include/pipeline/dbc_loader.hpp
include/pipeline/terrain_mesh.hpp include/pipeline/terrain_mesh.hpp
include/rendering/vk_context.hpp
include/rendering/vk_utils.hpp
include/rendering/vk_shader.hpp
include/rendering/vk_texture.hpp
include/rendering/vk_buffer.hpp
include/rendering/vk_pipeline.hpp
include/rendering/vk_render_target.hpp
include/rendering/renderer.hpp include/rendering/renderer.hpp
include/rendering/shader.hpp include/rendering/shader.hpp
include/rendering/texture.hpp include/rendering/texture.hpp
@ -343,19 +427,24 @@ if(TARGET opcodes-generate)
add_dependencies(wowee opcodes-generate) add_dependencies(wowee opcodes-generate)
endif() endif()
# Compile GLSL shaders to SPIR-V
if(GLSLC)
compile_shaders(wowee)
endif()
# Include directories # Include directories
target_include_directories(wowee PRIVATE target_include_directories(wowee PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}/src
${CMAKE_CURRENT_SOURCE_DIR}/extern ${CMAKE_CURRENT_SOURCE_DIR}/extern
${CMAKE_CURRENT_SOURCE_DIR}/extern/vk-bootstrap/src
${FFMPEG_INCLUDE_DIRS} ${FFMPEG_INCLUDE_DIRS}
) )
# Link libraries # Link libraries
target_link_libraries(wowee PRIVATE target_link_libraries(wowee PRIVATE
SDL2::SDL2 SDL2::SDL2
OpenGL::GL Vulkan::Vulkan
GLEW::GLEW
OpenSSL::SSL OpenSSL::SSL
OpenSSL::Crypto OpenSSL::Crypto
Threads::Threads Threads::Threads
@ -363,6 +452,14 @@ target_link_libraries(wowee PRIVATE
${CMAKE_DL_LIBS} ${CMAKE_DL_LIBS}
) )
# GL/GLEW linked temporarily for unconverted sub-renderers (removed in Phase 7)
if(TARGET OpenGL::GL)
target_link_libraries(wowee PRIVATE OpenGL::GL)
endif()
if(TARGET GLEW::GLEW)
target_link_libraries(wowee PRIVATE GLEW::GLEW)
endif()
target_link_libraries(wowee PRIVATE ${FFMPEG_LIBRARIES}) target_link_libraries(wowee PRIVATE ${FFMPEG_LIBRARIES})
if (FFMPEG_LIBRARY_DIRS) if (FFMPEG_LIBRARY_DIRS)
target_link_directories(wowee PRIVATE ${FFMPEG_LIBRARY_DIRS}) target_link_directories(wowee PRIVATE ${FFMPEG_LIBRARY_DIRS})
@ -385,6 +482,11 @@ if(TARGET imgui)
target_link_libraries(wowee PRIVATE imgui) target_link_libraries(wowee PRIVATE imgui)
endif() endif()
# Link vk-bootstrap
if(TARGET vk-bootstrap)
target_link_libraries(wowee PRIVATE vk-bootstrap)
endif()
# Link Unicorn if available # Link Unicorn if available
if(HAVE_UNICORN) if(HAVE_UNICORN)
target_link_libraries(wowee PRIVATE ${UNICORN_LIBRARY}) target_link_libraries(wowee PRIVATE ${UNICORN_LIBRARY})
@ -628,7 +730,7 @@ chmod +x /usr/local/bin/wowee
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Wowee") set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Wowee")
set(CPACK_DEBIAN_PACKAGE_SECTION "games") set(CPACK_DEBIAN_PACKAGE_SECTION "games")
set(CPACK_DEBIAN_PACKAGE_DEPENDS set(CPACK_DEBIAN_PACKAGE_DEPENDS
"libsdl2-2.0-0, libglew2.2 | libglew2.1, libssl3, zlib1g") "libsdl2-2.0-0, libvulkan1, libssl3, zlib1g")
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA
"${CMAKE_CURRENT_BINARY_DIR}/packaging/postinst;${CMAKE_CURRENT_BINARY_DIR}/packaging/prerm") "${CMAKE_CURRENT_BINARY_DIR}/packaging/postinst;${CMAKE_CURRENT_BINARY_DIR}/packaging/prerm")
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64") if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64")

View file

@ -0,0 +1,49 @@
#version 450
layout(set = 0, binding = 0) uniform PerFrame {
mat4 view;
mat4 projection;
mat4 lightSpaceMatrix;
vec4 lightDir;
vec4 lightColor;
vec4 ambientColor;
vec4 viewPos;
vec4 fogColor;
vec4 fogParams;
vec4 shadowParams;
};
layout(set = 1, binding = 0) uniform sampler2D uTexture;
layout(set = 1, binding = 1) uniform BasicMaterial {
vec4 color;
vec3 lightPos;
int useTexture;
};
layout(location = 0) in vec3 FragPos;
layout(location = 1) in vec3 Normal;
layout(location = 2) in vec2 TexCoord;
layout(location = 0) out vec4 outColor;
void main() {
vec3 ambient = 0.3 * vec3(1.0);
vec3 norm = normalize(Normal);
vec3 lightDir2 = normalize(lightPos - FragPos);
float diff = max(dot(norm, lightDir2), 0.0);
vec3 diffuse = diff * vec3(1.0);
vec3 viewDir2 = normalize(viewPos.xyz - FragPos);
vec3 reflectDir = reflect(-lightDir2, norm);
float spec = pow(max(dot(viewDir2, reflectDir), 0.0), 32.0);
vec3 specular = 0.5 * spec * vec3(1.0);
vec3 result = ambient + diffuse + specular;
if (useTexture != 0) {
outColor = texture(uTexture, TexCoord) * vec4(result, 1.0);
} else {
outColor = color * vec4(result, 1.0);
}
}

Binary file not shown.

View file

@ -0,0 +1,34 @@
#version 450
layout(set = 0, binding = 0) uniform PerFrame {
mat4 view;
mat4 projection;
mat4 lightSpaceMatrix;
vec4 lightDir;
vec4 lightColor;
vec4 ambientColor;
vec4 viewPos;
vec4 fogColor;
vec4 fogParams;
vec4 shadowParams;
};
layout(push_constant) uniform Push {
mat4 model;
} push;
layout(location = 0) in vec3 aPosition;
layout(location = 1) in vec3 aNormal;
layout(location = 2) in vec2 aTexCoord;
layout(location = 0) out vec3 FragPos;
layout(location = 1) out vec3 Normal;
layout(location = 2) out vec2 TexCoord;
void main() {
vec4 worldPos = push.model * vec4(aPosition, 1.0);
FragPos = worldPos.xyz;
Normal = mat3(push.model) * aNormal;
TexCoord = aTexCoord;
gl_Position = projection * view * worldPos;
}

Binary file not shown.

View file

@ -0,0 +1,49 @@
#version 450
layout(push_constant) uniform Push {
mat4 model;
vec4 celestialColor; // xyz = color, w = unused
float intensity;
float moonPhase;
float animTime;
} push;
layout(location = 0) in vec2 TexCoord;
layout(location = 0) out vec4 outColor;
float valueNoise(vec2 p) {
vec2 i = floor(p);
vec2 f = fract(p);
f = f * f * (3.0 - 2.0 * f);
float a = fract(sin(dot(i, vec2(127.1, 311.7))) * 43758.5453);
float b = fract(sin(dot(i + vec2(1.0, 0.0), vec2(127.1, 311.7))) * 43758.5453);
float c = fract(sin(dot(i + vec2(0.0, 1.0), vec2(127.1, 311.7))) * 43758.5453);
float d = fract(sin(dot(i + vec2(1.0, 1.0), vec2(127.1, 311.7))) * 43758.5453);
return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
}
void main() {
vec2 uv = TexCoord - 0.5;
float dist = length(uv);
float disc = smoothstep(0.42, 0.38, dist);
float glow = exp(-dist * dist * 12.0) * 0.6;
float alpha = max(disc, glow) * push.intensity;
vec3 color = push.celestialColor.rgb;
// Animated haze/turbulence overlay for the sun disc
if (push.intensity > 0.5) {
float noise = valueNoise(uv * 8.0 + vec2(push.animTime * 0.3, push.animTime * 0.2));
float noise2 = valueNoise(uv * 16.0 - vec2(push.animTime * 0.5, push.animTime * 0.15));
float turbulence = (noise * 0.6 + noise2 * 0.4) * disc;
color += vec3(turbulence * 0.3, turbulence * 0.15, 0.0);
}
// Moon phase shadow (only applied when intensity < 0.5, i.e. for moons)
float phaseX = uv.x * 2.0 + push.moonPhase;
float phaseShadow = smoothstep(-0.1, 0.1, phaseX);
alpha *= mix(phaseShadow, 1.0, step(0.5, push.intensity));
if (alpha < 0.001) discard;
outColor = vec4(color, alpha);
}

Binary file not shown.

View file

@ -0,0 +1,34 @@
#version 450
layout(set = 0, binding = 0) uniform PerFrame {
mat4 view;
mat4 projection;
mat4 lightSpaceMatrix;
vec4 lightDir;
vec4 lightColor;
vec4 ambientColor;
vec4 viewPos;
vec4 fogColor;
vec4 fogParams;
vec4 shadowParams;
};
layout(push_constant) uniform Push {
mat4 model;
vec4 celestialColor; // xyz = color, w = unused
float intensity;
float moonPhase;
float animTime;
} push;
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec2 aTexCoord;
layout(location = 0) out vec2 TexCoord;
void main() {
TexCoord = aTexCoord;
// Sky object: remove camera translation so celestial bodies are at infinite distance
mat4 rotView = mat4(mat3(view));
gl_Position = projection * rotView * push.model * vec4(aPos, 1.0);
}

Binary file not shown.

View file

@ -0,0 +1,83 @@
#version 450
layout(set = 0, binding = 0) uniform PerFrame {
mat4 view;
mat4 projection;
mat4 lightSpaceMatrix;
vec4 lightDir;
vec4 lightColor;
vec4 ambientColor;
vec4 viewPos;
vec4 fogColor;
vec4 fogParams;
vec4 shadowParams;
};
layout(set = 1, binding = 0) uniform sampler2D uTexture;
layout(set = 1, binding = 1) uniform CharMaterial {
float opacity;
int alphaTest;
int colorKeyBlack;
int unlit;
float emissiveBoost;
vec3 emissiveTint;
float specularIntensity;
};
layout(set = 0, binding = 1) uniform sampler2DShadow uShadowMap;
layout(location = 0) in vec3 FragPos;
layout(location = 1) in vec3 Normal;
layout(location = 2) in vec2 TexCoord;
layout(location = 0) out vec4 outColor;
void main() {
vec4 texColor = texture(uTexture, TexCoord);
if (alphaTest != 0 && texColor.a < 0.5) discard;
if (colorKeyBlack != 0) {
float lum = dot(texColor.rgb, vec3(0.299, 0.587, 0.114));
float ck = smoothstep(0.12, 0.30, lum);
texColor.a *= ck;
if (texColor.a < 0.01) discard;
}
vec3 norm = normalize(Normal);
if (!gl_FrontFacing) norm = -norm;
vec3 result;
if (unlit != 0) {
vec3 warm = emissiveTint * emissiveBoost;
result = texColor.rgb * (1.0 + warm);
} else {
vec3 ldir = normalize(-lightDir.xyz);
float diff = max(dot(norm, ldir), 0.0);
vec3 viewDir = normalize(viewPos.xyz - FragPos);
vec3 halfDir = normalize(ldir + viewDir);
float spec = pow(max(dot(norm, halfDir), 0.0), 32.0) * specularIntensity;
float shadow = 1.0;
if (shadowParams.x > 0.5) {
vec4 lsPos = lightSpaceMatrix * vec4(FragPos, 1.0);
vec3 proj = lsPos.xyz / lsPos.w * 0.5 + 0.5;
if (proj.z <= 1.0) {
float bias = max(0.005 * (1.0 - dot(norm, ldir)), 0.001);
shadow = texture(uShadowMap, vec3(proj.xy, proj.z - bias));
}
shadow = mix(1.0, shadow, shadowParams.y);
}
result = ambientColor.rgb * texColor.rgb
+ shadow * (diff * lightColor.rgb * texColor.rgb + spec * lightColor.rgb);
}
float dist = length(viewPos.xyz - FragPos);
float fogFactor = clamp((fogParams.y - dist) / (fogParams.y - fogParams.x), 0.0, 1.0);
result = mix(fogColor.rgb, result, fogFactor);
outColor = vec4(result, texColor.a * opacity);
}

Binary file not shown.

View file

@ -0,0 +1,49 @@
#version 450
layout(set = 0, binding = 0) uniform PerFrame {
mat4 view;
mat4 projection;
mat4 lightSpaceMatrix;
vec4 lightDir;
vec4 lightColor;
vec4 ambientColor;
vec4 viewPos;
vec4 fogColor;
vec4 fogParams;
vec4 shadowParams;
};
layout(push_constant) uniform Push {
mat4 model;
} push;
layout(set = 2, binding = 0) readonly buffer BoneSSBO {
mat4 bones[];
};
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec4 aBoneWeights;
layout(location = 2) in ivec4 aBoneIndices;
layout(location = 3) in vec3 aNormal;
layout(location = 4) in vec2 aTexCoord;
layout(location = 0) out vec3 FragPos;
layout(location = 1) out vec3 Normal;
layout(location = 2) out vec2 TexCoord;
void main() {
mat4 skinMat = bones[aBoneIndices.x] * aBoneWeights.x
+ bones[aBoneIndices.y] * aBoneWeights.y
+ bones[aBoneIndices.z] * aBoneWeights.z
+ bones[aBoneIndices.w] * aBoneWeights.w;
vec4 skinnedPos = skinMat * vec4(aPos, 1.0);
vec3 skinnedNorm = mat3(skinMat) * aNormal;
vec4 worldPos = push.model * skinnedPos;
FragPos = worldPos.xyz;
Normal = mat3(push.model) * skinnedNorm;
TexCoord = aTexCoord;
gl_Position = projection * view * worldPos;
}

Binary file not shown.

View file

@ -0,0 +1,19 @@
#version 450
layout(set = 1, binding = 0) uniform sampler2D uTexture;
layout(set = 1, binding = 1) uniform ShadowParams {
int alphaTest;
int colorKeyBlack;
};
layout(location = 0) in vec2 TexCoord;
void main() {
vec4 texColor = texture(uTexture, TexCoord);
if (alphaTest != 0 && texColor.a < 0.5) discard;
if (colorKeyBlack != 0) {
float lum = dot(texColor.rgb, vec3(0.299, 0.587, 0.114));
if (lum < 0.12) discard;
}
}

Binary file not shown.

View file

@ -0,0 +1,27 @@
#version 450
layout(push_constant) uniform Push {
mat4 lightSpaceMatrix;
mat4 model;
} push;
layout(set = 2, binding = 0) readonly buffer BoneSSBO {
mat4 bones[];
};
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec4 aBoneWeights;
layout(location = 2) in ivec4 aBoneIndices;
layout(location = 3) in vec2 aTexCoord;
layout(location = 0) out vec2 TexCoord;
void main() {
mat4 skinMat = bones[aBoneIndices.x] * aBoneWeights.x
+ bones[aBoneIndices.y] * aBoneWeights.y
+ bones[aBoneIndices.z] * aBoneWeights.z
+ bones[aBoneIndices.w] * aBoneWeights.w;
vec4 skinnedPos = skinMat * vec4(aPos, 1.0);
TexCoord = aTexCoord;
gl_Position = push.lightSpaceMatrix * push.model * skinnedPos;
}

Binary file not shown.

View file

@ -0,0 +1,13 @@
#version 450
layout(location = 0) in float vAlpha;
layout(location = 0) out vec4 outColor;
void main() {
vec2 p = gl_PointCoord - vec2(0.5);
float dist = length(p);
if (dist > 0.5) discard;
float alpha = smoothstep(0.5, 0.1, dist) * vAlpha * 0.45;
outColor = vec4(0.65, 0.55, 0.40, alpha);
}

Binary file not shown.

View file

@ -0,0 +1,26 @@
#version 450
layout(set = 0, binding = 0) uniform PerFrame {
mat4 view;
mat4 projection;
mat4 lightSpaceMatrix;
vec4 lightDir;
vec4 lightColor;
vec4 ambientColor;
vec4 viewPos;
vec4 fogColor;
vec4 fogParams;
vec4 shadowParams;
};
layout(location = 0) in vec3 aPos;
layout(location = 1) in float aSize;
layout(location = 2) in float aAlpha;
layout(location = 0) out float vAlpha;
void main() {
gl_PointSize = aSize;
vAlpha = aAlpha;
gl_Position = projection * view * vec4(aPos, 1.0);
}

Binary file not shown.

View file

@ -0,0 +1,16 @@
#version 450
layout(location = 0) in float vAlpha;
layout(location = 1) in float vHeat;
layout(location = 2) in float vHeight;
layout(location = 0) out vec4 outColor;
void main() {
vec3 top = vec3(1.0, 0.2, 0.0);
vec3 mid = vec3(1.0, 0.5, 0.0);
vec3 color = mix(mid, top, vHeight);
color = mix(color, vec3(1.0, 0.8, 0.3), vHeat * 0.5);
float alpha = vAlpha * smoothstep(0.0, 0.3, vHeight);
outColor = vec4(color, alpha);
}

Binary file not shown.

View file

@ -0,0 +1,30 @@
#version 450
layout(set = 0, binding = 0) uniform PerFrame {
mat4 view;
mat4 projection;
mat4 lightSpaceMatrix;
vec4 lightDir;
vec4 lightColor;
vec4 ambientColor;
vec4 viewPos;
vec4 fogColor;
vec4 fogParams;
vec4 shadowParams;
};
layout(location = 0) in vec3 aPos;
layout(location = 1) in float aAlpha;
layout(location = 2) in float aHeat;
layout(location = 3) in float aHeight;
layout(location = 0) out float vAlpha;
layout(location = 1) out float vHeat;
layout(location = 2) out float vHeight;
void main() {
vAlpha = aAlpha;
vHeat = aHeat;
vHeight = aHeight;
gl_Position = projection * view * vec4(aPos, 1.0);
}

Binary file not shown.

View file

@ -0,0 +1,63 @@
#version 450
layout(push_constant) uniform Push {
vec4 cloudColor;
float density;
float windOffset;
} push;
layout(location = 0) in vec3 vWorldDir;
layout(location = 0) out vec4 outColor;
float hash(vec2 p) {
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);
}
float noise(vec2 p) {
vec2 i = floor(p);
vec2 f = fract(p);
f = f * f * (3.0 - 2.0 * f);
float a = hash(i);
float b = hash(i + vec2(1.0, 0.0));
float c = hash(i + vec2(0.0, 1.0));
float d = hash(i + vec2(1.0, 1.0));
return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
}
float fbm(vec2 p) {
float val = 0.0;
float amp = 0.5;
for (int i = 0; i < 4; i++) {
val += amp * noise(p);
p *= 2.0;
amp *= 0.5;
}
return val;
}
void main() {
vec3 dir = normalize(vWorldDir);
float altitude = dir.y;
if (altitude < 0.0) discard;
vec2 uv = dir.xz / (altitude + 0.001);
uv += push.windOffset;
float cloud1 = fbm(uv * 0.8);
float cloud2 = fbm(uv * 1.6 + 5.0);
float cloud = cloud1 * 0.7 + cloud2 * 0.3;
cloud = smoothstep(0.35, 0.65, cloud) * push.density;
float edgeBreak = noise(uv * 4.0);
cloud *= smoothstep(0.2, 0.5, edgeBreak);
float horizonFade = smoothstep(0.0, 0.15, altitude);
cloud *= horizonFade;
float edgeSoftness = smoothstep(0.0, 0.3, cloud);
float alpha = cloud * edgeSoftness;
if (alpha < 0.01) discard;
outColor = vec4(push.cloudColor.rgb, alpha);
}

Binary file not shown.

View file

@ -0,0 +1,25 @@
#version 450
layout(set = 0, binding = 0) uniform PerFrame {
mat4 view;
mat4 projection;
mat4 lightSpaceMatrix;
vec4 lightDir;
vec4 lightColor;
vec4 ambientColor;
vec4 viewPos;
vec4 fogColor;
vec4 fogParams;
vec4 shadowParams;
};
layout(location = 0) in vec3 aPos;
layout(location = 0) out vec3 vWorldDir;
void main() {
vWorldDir = aPos;
mat4 rotView = mat4(mat3(view));
vec4 pos = projection * rotView * vec4(aPos, 1.0);
gl_Position = pos.xyww;
}

Binary file not shown.

View file

@ -0,0 +1,22 @@
#version 450
layout(push_constant) uniform Push {
vec2 position;
float size;
float aspectRatio;
vec4 color; // rgb + brightness in w
} push;
layout(location = 0) in vec2 UV;
layout(location = 0) out vec4 outColor;
void main() {
vec2 center = UV - 0.5;
float dist = length(center);
float alpha = smoothstep(0.5, 0.0, dist);
float glow = exp(-dist * dist * 8.0) * 0.5;
alpha = max(alpha, glow) * push.color.w;
if (alpha < 0.01) discard;
outColor = vec4(push.color.rgb, alpha);
}

Binary file not shown.

View file

@ -0,0 +1,19 @@
#version 450
layout(push_constant) uniform Push {
vec2 position;
float size;
float aspectRatio;
} push;
layout(location = 0) in vec2 aPos;
layout(location = 1) in vec2 aUV;
layout(location = 0) out vec2 UV;
void main() {
UV = aUV;
vec2 scaled = aPos * push.size;
scaled.x /= push.aspectRatio;
gl_Position = vec4(scaled + push.position, 0.0, 1.0);
}

Binary file not shown.

View file

@ -0,0 +1,10 @@
#version 450
layout(location = 0) in float vBrightness;
layout(location = 0) out vec4 outColor;
void main() {
vec3 color = mix(vec3(0.6, 0.8, 1.0), vec3(1.0), vBrightness * 0.5);
outColor = vec4(color, vBrightness);
}

Binary file not shown.

View file

@ -0,0 +1,27 @@
#version 450
layout(set = 0, binding = 0) uniform PerFrame {
mat4 view;
mat4 projection;
mat4 lightSpaceMatrix;
vec4 lightDir;
vec4 lightColor;
vec4 ambientColor;
vec4 viewPos;
vec4 fogColor;
vec4 fogParams;
vec4 shadowParams;
};
layout(push_constant) uniform Push {
float brightness;
} push;
layout(location = 0) in vec3 aPos;
layout(location = 0) out float vBrightness;
void main() {
vBrightness = push.brightness;
gl_Position = projection * view * vec4(aPos, 1.0);
}

Binary file not shown.

View file

@ -0,0 +1,11 @@
#version 450
layout(push_constant) uniform Push {
float intensity;
} push;
layout(location = 0) out vec4 outColor;
void main() {
outColor = vec4(1.0, 1.0, 1.0, push.intensity * 0.6);
}

Binary file not shown.

View file

@ -0,0 +1,7 @@
#version 450
layout(location = 0) in vec2 aPos;
void main() {
gl_Position = vec4(aPos, 0.0, 1.0);
}

Binary file not shown.

View file

@ -0,0 +1,86 @@
#version 450
layout(set = 0, binding = 0) uniform PerFrame {
mat4 view;
mat4 projection;
mat4 lightSpaceMatrix;
vec4 lightDir;
vec4 lightColor;
vec4 ambientColor;
vec4 viewPos;
vec4 fogColor;
vec4 fogParams;
vec4 shadowParams;
};
layout(set = 1, binding = 0) uniform sampler2D uTexture;
layout(set = 1, binding = 2) uniform M2Material {
int hasTexture;
int alphaTest;
int colorKeyBlack;
float colorKeyThreshold;
int unlit;
int blendMode;
float fadeAlpha;
float interiorDarken;
float specularIntensity;
};
layout(set = 0, binding = 1) uniform sampler2DShadow uShadowMap;
layout(location = 0) in vec3 FragPos;
layout(location = 1) in vec3 Normal;
layout(location = 2) in vec2 TexCoord;
layout(location = 0) out vec4 outColor;
void main() {
vec4 texColor = hasTexture != 0 ? texture(uTexture, TexCoord) : vec4(1.0);
if (alphaTest != 0 && texColor.a < 0.5) discard;
if (colorKeyBlack != 0) {
float lum = dot(texColor.rgb, vec3(0.299, 0.587, 0.114));
if (lum < colorKeyThreshold) discard;
}
if (blendMode == 1 && texColor.a < 0.004) discard;
vec3 norm = normalize(Normal);
if (!gl_FrontFacing) norm = -norm;
vec3 ldir = normalize(-lightDir.xyz);
float diff = max(dot(norm, ldir), 0.0);
vec3 result;
if (unlit != 0) {
result = texColor.rgb;
} else {
vec3 viewDir = normalize(viewPos.xyz - FragPos);
vec3 halfDir = normalize(ldir + viewDir);
float spec = pow(max(dot(norm, halfDir), 0.0), 32.0) * specularIntensity;
float shadow = 1.0;
if (shadowParams.x > 0.5) {
vec4 lsPos = lightSpaceMatrix * vec4(FragPos, 1.0);
vec3 proj = lsPos.xyz / lsPos.w * 0.5 + 0.5;
if (proj.z <= 1.0) {
float bias = max(0.005 * (1.0 - dot(norm, ldir)), 0.001);
shadow = texture(uShadowMap, vec3(proj.xy, proj.z - bias));
}
shadow = mix(1.0, shadow, shadowParams.y);
}
result = ambientColor.rgb * texColor.rgb
+ shadow * (diff * lightColor.rgb * texColor.rgb + spec * lightColor.rgb);
if (interiorDarken > 0.0) {
result *= mix(1.0, 0.5, interiorDarken);
}
}
float dist = length(viewPos.xyz - FragPos);
float fogFactor = clamp((fogParams.y - dist) / (fogParams.y - fogParams.x), 0.0, 1.0);
result = mix(fogColor.rgb, result, fogFactor);
outColor = vec4(result, texColor.a * fadeAlpha);
}

BIN
assets/shaders/m2.frag.spv Normal file

Binary file not shown.

View file

@ -0,0 +1,59 @@
#version 450
layout(set = 0, binding = 0) uniform PerFrame {
mat4 view;
mat4 projection;
mat4 lightSpaceMatrix;
vec4 lightDir;
vec4 lightColor;
vec4 ambientColor;
vec4 viewPos;
vec4 fogColor;
vec4 fogParams;
vec4 shadowParams;
};
layout(push_constant) uniform Push {
mat4 model;
vec2 uvOffset;
int texCoordSet;
int useBones;
} push;
layout(set = 2, binding = 0) readonly buffer BoneSSBO {
mat4 bones[];
};
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aNormal;
layout(location = 2) in vec2 aTexCoord;
layout(location = 3) in vec4 aBoneWeights;
layout(location = 4) in vec4 aBoneIndicesF;
layout(location = 5) in vec2 aTexCoord2;
layout(location = 0) out vec3 FragPos;
layout(location = 1) out vec3 Normal;
layout(location = 2) out vec2 TexCoord;
void main() {
vec4 pos = vec4(aPos, 1.0);
vec4 norm = vec4(aNormal, 0.0);
if (push.useBones != 0) {
ivec4 bi = ivec4(aBoneIndicesF);
mat4 skinMat = bones[bi.x] * aBoneWeights.x
+ bones[bi.y] * aBoneWeights.y
+ bones[bi.z] * aBoneWeights.z
+ bones[bi.w] * aBoneWeights.w;
pos = skinMat * pos;
norm = skinMat * norm;
}
vec4 worldPos = push.model * pos;
FragPos = worldPos.xyz;
Normal = mat3(push.model) * norm.xyz;
TexCoord = (push.texCoordSet == 1 ? aTexCoord2 : aTexCoord) + push.uvOffset;
gl_Position = projection * view * worldPos;
}

BIN
assets/shaders/m2.vert.spv Normal file

Binary file not shown.

View file

@ -0,0 +1,30 @@
#version 450
layout(set = 1, binding = 0) uniform sampler2D uTexture;
layout(push_constant) uniform Push {
vec2 tileCount;
int alphaKey;
} push;
layout(location = 0) in vec4 vColor;
layout(location = 1) in float vTile;
layout(location = 0) out vec4 outColor;
void main() {
vec2 p = gl_PointCoord;
float tile = floor(vTile);
float tx = mod(tile, push.tileCount.x);
float ty = floor(tile / push.tileCount.x);
vec2 uv = (vec2(tx, ty) + p) / push.tileCount;
vec4 texColor = texture(uTexture, uv);
if (push.alphaKey != 0) {
float lum = dot(texColor.rgb, vec3(0.299, 0.587, 0.114));
if (lum < 0.05) discard;
}
float edge = smoothstep(0.5, 0.4, length(p - 0.5));
outColor = texColor * vColor * vec4(vec3(1.0), edge);
}

Binary file not shown.

View file

@ -0,0 +1,31 @@
#version 450
layout(set = 0, binding = 0) uniform PerFrame {
mat4 view;
mat4 projection;
mat4 lightSpaceMatrix;
vec4 lightDir;
vec4 lightColor;
vec4 ambientColor;
vec4 viewPos;
vec4 fogColor;
vec4 fogParams;
vec4 shadowParams;
};
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec4 aColor;
layout(location = 2) in float aSize;
layout(location = 3) in float aTile;
layout(location = 0) out vec4 vColor;
layout(location = 1) out float vTile;
void main() {
vec4 viewPos4 = view * vec4(aPos, 1.0);
float dist = -viewPos4.z;
gl_PointSize = clamp(aSize * 500.0 / max(dist, 1.0), 1.0, 128.0);
vColor = aColor;
vTile = aTile;
gl_Position = projection * viewPos4;
}

Binary file not shown.

View file

@ -0,0 +1,25 @@
#version 450
layout(location = 0) in float vLifeRatio;
layout(location = 1) in float vIsSpark;
layout(location = 0) out vec4 outColor;
void main() {
vec2 p = gl_PointCoord - vec2(0.5);
float dist = length(p);
if (dist > 0.5) discard;
if (vIsSpark > 0.5) {
float glow = smoothstep(0.5, 0.0, dist);
float life = 1.0 - vLifeRatio;
vec3 color = mix(vec3(1.0, 0.6, 0.1), vec3(1.0, 0.2, 0.0), vLifeRatio);
outColor = vec4(color * glow, glow * life);
} else {
float edge = smoothstep(0.5, 0.3, dist);
float fadeIn = smoothstep(0.0, 0.2, vLifeRatio);
float fadeOut = 1.0 - smoothstep(0.6, 1.0, vLifeRatio);
float alpha = edge * fadeIn * fadeOut * 0.4;
outColor = vec4(vec3(0.5), alpha);
}
}

Binary file not shown.

View file

@ -0,0 +1,36 @@
#version 450
layout(set = 0, binding = 0) uniform PerFrame {
mat4 view;
mat4 projection;
mat4 lightSpaceMatrix;
vec4 lightDir;
vec4 lightColor;
vec4 ambientColor;
vec4 viewPos;
vec4 fogColor;
vec4 fogParams;
vec4 shadowParams;
};
layout(push_constant) uniform Push {
float screenHeight;
} push;
layout(location = 0) in vec3 aPos;
layout(location = 1) in float aLifeRatio;
layout(location = 2) in float aSize;
layout(location = 3) in float aIsSpark;
layout(location = 0) out float vLifeRatio;
layout(location = 1) out float vIsSpark;
void main() {
vec4 viewPos4 = view * vec4(aPos, 1.0);
float dist = -viewPos4.z;
float scale = aIsSpark > 0.5 ? 0.12 : 0.3;
gl_PointSize = clamp(aSize * scale * push.screenHeight / max(dist, 1.0), 1.0, 64.0);
vLifeRatio = aLifeRatio;
vIsSpark = aIsSpark;
gl_Position = projection * viewPos4;
}

Binary file not shown.

View file

@ -0,0 +1,67 @@
#version 450
layout(set = 0, binding = 0) uniform sampler2D uComposite;
layout(push_constant) uniform Push {
vec4 rect;
vec2 playerUV;
float rotation;
float arrowRotation;
float zoomRadius;
int squareShape;
} push;
layout(location = 0) in vec2 TexCoord;
layout(location = 0) out vec4 outColor;
float cross2d(vec2 a, vec2 b) {
return a.x * b.y - a.y * b.x;
}
bool pointInTriangle(vec2 p, vec2 a, vec2 b, vec2 c) {
float d1 = cross2d(b - a, p - a);
float d2 = cross2d(c - b, p - b);
float d3 = cross2d(a - c, p - c);
bool hasNeg = (d1 < 0.0) || (d2 < 0.0) || (d3 < 0.0);
bool hasPos = (d1 > 0.0) || (d2 > 0.0) || (d3 > 0.0);
return !(hasNeg && hasPos);
}
void main() {
vec2 center = TexCoord - 0.5;
float dist = length(center);
if (push.squareShape == 0) {
if (dist > 0.5) discard;
}
float cs = cos(push.rotation);
float sn = sin(push.rotation);
vec2 rotated = vec2(center.x * cs - center.y * sn, center.x * sn + center.y * cs);
vec2 mapUV = push.playerUV + rotated * push.zoomRadius * 2.0;
vec4 mapColor = texture(uComposite, mapUV);
// Player arrow
float acs = cos(push.arrowRotation);
float asn = sin(push.arrowRotation);
vec2 ac = center;
vec2 arrowPos = vec2(ac.x * acs - ac.y * asn, ac.x * asn + ac.y * acs);
vec2 tip = vec2(0.0, -0.04);
vec2 left = vec2(-0.02, 0.02);
vec2 right = vec2(0.02, 0.02);
if (pointInTriangle(arrowPos, tip, left, right)) {
mapColor = vec4(1.0, 0.8, 0.0, 1.0);
}
// Dark border ring
float border = smoothstep(0.48, 0.5, dist);
if (push.squareShape == 0) {
mapColor.rgb *= 1.0 - border * 0.7;
}
outColor = mapColor;
}

Binary file not shown.

View file

@ -0,0 +1,16 @@
#version 450
layout(push_constant) uniform Push {
vec4 rect; // x, y, w, h in 0..1 screen space
} push;
layout(location = 0) in vec2 aPos;
layout(location = 1) in vec2 aUV;
layout(location = 0) out vec2 TexCoord;
void main() {
TexCoord = aUV;
vec2 screenPos = push.rect.xy + aPos * push.rect.zw;
gl_Position = vec4(screenPos * 2.0 - 1.0, 0.0, 1.0);
}

Binary file not shown.

View file

@ -0,0 +1,11 @@
#version 450
layout(set = 0, binding = 0) uniform sampler2D uTileTexture;
layout(location = 0) in vec2 TexCoord;
layout(location = 0) out vec4 outColor;
void main() {
outColor = texture(uTileTexture, vec2(TexCoord.y, TexCoord.x));
}

Binary file not shown.

View file

@ -0,0 +1,17 @@
#version 450
layout(push_constant) uniform Push {
vec2 gridOffset;
} push;
layout(location = 0) in vec2 aPos;
layout(location = 1) in vec2 aUV;
layout(location = 0) out vec2 TexCoord;
void main() {
TexCoord = aUV;
vec2 pos = (aPos + push.gridOffset) / 3.0;
pos = pos * 2.0 - 1.0;
gl_Position = vec4(pos, 0.0, 1.0);
}

Binary file not shown.

View file

@ -0,0 +1,13 @@
#version 450
layout(location = 0) in float vAlpha;
layout(location = 0) out vec4 outColor;
void main() {
vec2 p = gl_PointCoord - vec2(0.5);
float dist = length(p);
if (dist > 0.5) discard;
float alpha = smoothstep(0.5, 0.1, dist) * vAlpha * 0.4;
outColor = vec4(0.7, 0.65, 0.55, alpha);
}

Binary file not shown.

View file

@ -0,0 +1,26 @@
#version 450
layout(set = 0, binding = 0) uniform PerFrame {
mat4 view;
mat4 projection;
mat4 lightSpaceMatrix;
vec4 lightDir;
vec4 lightColor;
vec4 ambientColor;
vec4 viewPos;
vec4 fogColor;
vec4 fogParams;
vec4 shadowParams;
};
layout(location = 0) in vec3 aPos;
layout(location = 1) in float aSize;
layout(location = 2) in float aAlpha;
layout(location = 0) out float vAlpha;
void main() {
gl_PointSize = aSize;
vAlpha = aAlpha;
gl_Position = projection * view * vec4(aPos, 1.0);
}

Binary file not shown.

View file

@ -0,0 +1,20 @@
#version 450
layout(set = 0, binding = 0) uniform sampler2D uScene;
layout(location = 0) in vec2 TexCoord;
layout(location = 0) out vec4 outColor;
void main() {
vec3 hdr = texture(uScene, TexCoord).rgb;
// Shoulder tone map
vec3 mapped = hdr;
for (int i = 0; i < 3; i++) {
if (mapped[i] > 0.9) {
float excess = mapped[i] - 0.9;
mapped[i] = 0.9 + 0.1 * excess / (excess + 0.1);
}
}
outColor = vec4(mapped, 1.0);
}

Binary file not shown.

View file

@ -0,0 +1,10 @@
#version 450
layout(location = 0) out vec2 TexCoord;
void main() {
// Fullscreen triangle trick: 3 vertices, no vertex buffer
TexCoord = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
gl_Position = vec4(TexCoord * 2.0 - 1.0, 0.0, 1.0);
TexCoord.y = 1.0 - TexCoord.y; // flip Y for Vulkan
}

Binary file not shown.

View file

@ -0,0 +1,18 @@
#version 450
layout(set = 1, binding = 0) uniform sampler2D markerTexture;
layout(push_constant) uniform Push {
mat4 model;
float alpha;
} push;
layout(location = 0) in vec2 TexCoord;
layout(location = 0) out vec4 outColor;
void main() {
vec4 texColor = texture(markerTexture, TexCoord);
if (texColor.a < 0.1) discard;
outColor = vec4(texColor.rgb, texColor.a * push.alpha);
}

Binary file not shown.

View file

@ -0,0 +1,28 @@
#version 450
layout(set = 0, binding = 0) uniform PerFrame {
mat4 view;
mat4 projection;
mat4 lightSpaceMatrix;
vec4 lightDir;
vec4 lightColor;
vec4 ambientColor;
vec4 viewPos;
vec4 fogColor;
vec4 fogParams;
vec4 shadowParams;
};
layout(push_constant) uniform Push {
mat4 model;
} push;
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec2 aTexCoord;
layout(location = 0) out vec2 TexCoord;
void main() {
TexCoord = aTexCoord;
gl_Position = projection * view * push.model * vec4(aPos, 1.0);
}

Binary file not shown.

View file

@ -0,0 +1,19 @@
#version 450
layout(push_constant) uniform Push {
mat4 mvp;
vec4 color;
} push;
layout(location = 0) in vec2 vLocalPos;
layout(location = 0) out vec4 outColor;
void main() {
float r = length(vLocalPos);
float ring = smoothstep(0.93, 0.97, r) * smoothstep(1.0, 0.97, r);
float inward = (1.0 - smoothstep(0.0, 0.93, r)) * 0.15;
float alpha = max(ring, inward);
if (alpha < 0.01) discard;
outColor = vec4(push.color.rgb, alpha);
}

Binary file not shown.

View file

@ -0,0 +1,14 @@
#version 450
layout(push_constant) uniform Push {
mat4 mvp;
} push;
layout(location = 0) in vec3 aPos;
layout(location = 0) out vec2 vLocalPos;
void main() {
vLocalPos = aPos.xz;
gl_Position = push.mvp * vec4(aPos, 1.0);
}

Binary file not shown.

View file

@ -0,0 +1,37 @@
#version 450
layout(set = 1, binding = 0) uniform sampler2D uTexture;
layout(set = 1, binding = 1) uniform ShadowParams {
int useBones;
int useTexture;
int alphaTest;
int foliageSway;
float windTime;
float foliageMotionDamp;
};
layout(location = 0) in vec2 TexCoord;
layout(location = 1) in vec3 WorldPos;
void main() {
if (useTexture != 0) {
vec2 uv = TexCoord;
if (foliageSway != 0) {
float sway = sin(windTime + WorldPos.x * 0.5) * 0.02 * foliageMotionDamp;
uv += vec2(sway, sway * 0.5);
}
vec4 texColor = textureLod(uTexture, uv, 0.0);
if (alphaTest != 0 && texColor.a < 0.5) discard;
if (foliageSway != 0) {
vec2 uv2 = TexCoord + vec2(
sin(windTime * 1.3 + WorldPos.z * 0.7) * 0.015 * foliageMotionDamp,
sin(windTime * 0.9 + WorldPos.x * 0.6) * 0.01 * foliageMotionDamp
);
vec4 texColor2 = textureLod(uTexture, uv2, 0.0);
float blended = (texColor.a + texColor2.a) * 0.5;
if (alphaTest != 0 && blended < 0.5) discard;
}
}
}

Binary file not shown.

View file

@ -0,0 +1,45 @@
#version 450
layout(push_constant) uniform Push {
mat4 lightSpaceMatrix;
mat4 model;
} push;
layout(set = 2, binding = 0) readonly buffer BoneSSBO {
mat4 bones[];
};
layout(set = 1, binding = 1) uniform ShadowParams {
int useBones;
int useTexture;
int alphaTest;
int foliageSway;
float windTime;
float foliageMotionDamp;
};
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec2 aTexCoord;
layout(location = 2) in vec4 aBoneWeights;
layout(location = 3) in vec4 aBoneIndicesF;
layout(location = 0) out vec2 TexCoord;
layout(location = 1) out vec3 WorldPos;
void main() {
vec4 pos = vec4(aPos, 1.0);
if (useBones != 0) {
ivec4 bi = ivec4(aBoneIndicesF);
mat4 skinMat = bones[bi.x] * aBoneWeights.x
+ bones[bi.y] * aBoneWeights.y
+ bones[bi.z] * aBoneWeights.z
+ bones[bi.w] * aBoneWeights.w;
pos = skinMat * pos;
}
vec4 worldPos = push.model * pos;
WorldPos = worldPos.xyz;
TexCoord = aTexCoord;
gl_Position = push.lightSpaceMatrix * worldPos;
}

Binary file not shown.

View file

@ -0,0 +1,34 @@
#version 450
layout(set = 0, binding = 0) uniform PerFrame {
mat4 view;
mat4 projection;
mat4 lightSpaceMatrix;
vec4 lightDir;
vec4 lightColor;
vec4 ambientColor;
vec4 viewPos;
vec4 fogColor;
vec4 fogParams;
vec4 shadowParams;
};
layout(push_constant) uniform Push {
vec4 horizonColor;
vec4 zenithColor;
float timeOfDay;
} push;
layout(location = 0) in vec3 WorldPos;
layout(location = 1) in float Altitude;
layout(location = 0) out vec4 outColor;
void main() {
float t = clamp(Altitude, 0.0, 1.0);
t = pow(t, 1.5);
vec3 sky = mix(push.horizonColor.rgb, push.zenithColor.rgb, t);
float scatter = max(0.0, 1.0 - t * 2.0) * 0.15;
sky += vec3(scatter * 0.8, scatter * 0.4, scatter * 0.1);
outColor = vec4(sky, 1.0);
}

Binary file not shown.

View file

@ -0,0 +1,27 @@
#version 450
layout(set = 0, binding = 0) uniform PerFrame {
mat4 view;
mat4 projection;
mat4 lightSpaceMatrix;
vec4 lightDir;
vec4 lightColor;
vec4 ambientColor;
vec4 viewPos;
vec4 fogColor;
vec4 fogParams; // x=fogStart, y=fogEnd, z=time
vec4 shadowParams; // x=enabled, y=strength
};
layout(location = 0) in vec3 aPos;
layout(location = 0) out vec3 WorldPos;
layout(location = 1) out float Altitude;
void main() {
WorldPos = aPos;
Altitude = aPos.y;
mat4 rotView = mat4(mat3(view)); // strip translation
vec4 pos = projection * rotView * vec4(aPos, 1.0);
gl_Position = pos.xyww; // force far plane
}

Binary file not shown.

View file

@ -0,0 +1,13 @@
#version 450
layout(location = 0) in float vBrightness;
layout(location = 0) out vec4 outColor;
void main() {
vec2 p = gl_PointCoord - vec2(0.5);
float dist = length(p);
if (dist > 0.5) discard;
float alpha = vBrightness * smoothstep(0.5, 0.2, dist);
outColor = vec4(vec3(0.9, 0.95, 1.0) * vBrightness, alpha);
}

Binary file not shown.

View file

@ -0,0 +1,33 @@
#version 450
layout(set = 0, binding = 0) uniform PerFrame {
mat4 view;
mat4 projection;
mat4 lightSpaceMatrix;
vec4 lightDir;
vec4 lightColor;
vec4 ambientColor;
vec4 viewPos;
vec4 fogColor;
vec4 fogParams;
vec4 shadowParams;
};
layout(push_constant) uniform Push {
float time;
float intensity;
} push;
layout(location = 0) in vec3 aPos;
layout(location = 1) in float aBrightness;
layout(location = 2) in float aTwinklePhase;
layout(location = 0) out float vBrightness;
void main() {
mat4 rotView = mat4(mat3(view));
float twinkle = 0.7 + 0.3 * sin(push.time * 1.5 + aTwinklePhase);
vBrightness = aBrightness * twinkle * push.intensity;
gl_PointSize = mix(2.0, 4.0, aBrightness);
gl_Position = projection * rotView * vec4(aPos, 1.0);
}

Binary file not shown.

View file

@ -0,0 +1,15 @@
#version 450
layout(location = 0) in float vAlpha;
layout(location = 0) out vec4 outColor;
void main() {
vec2 p = gl_PointCoord - vec2(0.5);
float dist = length(p);
if (dist > 0.5) discard;
float ring = smoothstep(0.5, 0.4, dist) - smoothstep(0.38, 0.28, dist);
float highlight = smoothstep(0.3, 0.1, length(p - vec2(-0.15, 0.15))) * 0.5;
float alpha = (ring + highlight) * vAlpha;
outColor = vec4(0.8, 0.9, 1.0, alpha);
}

Binary file not shown.

View file

@ -0,0 +1,26 @@
#version 450
layout(set = 0, binding = 0) uniform PerFrame {
mat4 view;
mat4 projection;
mat4 lightSpaceMatrix;
vec4 lightDir;
vec4 lightColor;
vec4 ambientColor;
vec4 viewPos;
vec4 fogColor;
vec4 fogParams;
vec4 shadowParams;
};
layout(location = 0) in vec3 aPos;
layout(location = 1) in float aSize;
layout(location = 2) in float aAlpha;
layout(location = 0) out float vAlpha;
void main() {
gl_PointSize = aSize;
vAlpha = aAlpha;
gl_Position = projection * view * vec4(aPos, 1.0);
}

Binary file not shown.

View file

@ -0,0 +1,13 @@
#version 450
layout(location = 0) in float vAlpha;
layout(location = 0) out vec4 outColor;
void main() {
vec2 p = gl_PointCoord - vec2(0.5);
float dist = length(p);
if (dist > 0.5) discard;
float alpha = smoothstep(0.5, 0.1, dist) * vAlpha;
outColor = vec4(0.85, 0.92, 1.0, alpha);
}

Binary file not shown.

View file

@ -0,0 +1,26 @@
#version 450
layout(set = 0, binding = 0) uniform PerFrame {
mat4 view;
mat4 projection;
mat4 lightSpaceMatrix;
vec4 lightDir;
vec4 lightColor;
vec4 ambientColor;
vec4 viewPos;
vec4 fogColor;
vec4 fogParams;
vec4 shadowParams;
};
layout(location = 0) in vec3 aPos;
layout(location = 1) in float aSize;
layout(location = 2) in float aAlpha;
layout(location = 0) out float vAlpha;
void main() {
gl_PointSize = aSize;
vAlpha = aAlpha;
gl_Position = projection * view * vec4(aPos, 1.0);
}

Binary file not shown.

View file

@ -0,0 +1,96 @@
#version 450
layout(set = 0, binding = 0) uniform PerFrame {
mat4 view;
mat4 projection;
mat4 lightSpaceMatrix;
vec4 lightDir;
vec4 lightColor;
vec4 ambientColor;
vec4 viewPos;
vec4 fogColor;
vec4 fogParams;
vec4 shadowParams;
};
layout(set = 1, binding = 0) uniform sampler2D uBaseTexture;
layout(set = 1, binding = 1) uniform sampler2D uLayer1Texture;
layout(set = 1, binding = 2) uniform sampler2D uLayer2Texture;
layout(set = 1, binding = 3) uniform sampler2D uLayer3Texture;
layout(set = 1, binding = 4) uniform sampler2D uLayer1Alpha;
layout(set = 1, binding = 5) uniform sampler2D uLayer2Alpha;
layout(set = 1, binding = 6) uniform sampler2D uLayer3Alpha;
layout(set = 1, binding = 7) uniform TerrainParams {
int layerCount;
int hasLayer1;
int hasLayer2;
int hasLayer3;
};
layout(set = 0, binding = 1) uniform sampler2DShadow uShadowMap;
layout(location = 0) in vec3 FragPos;
layout(location = 1) in vec3 Normal;
layout(location = 2) in vec2 TexCoord;
layout(location = 3) in vec2 LayerUV;
layout(location = 0) out vec4 outColor;
float sampleAlpha(sampler2D tex, vec2 uv) {
vec2 edge = min(uv, 1.0 - uv);
float border = min(edge.x, edge.y);
float doBlur = step(border, 2.0 / 64.0);
if (doBlur < 0.5) {
return texture(tex, uv).r;
}
vec2 texel = vec2(1.0 / 64.0);
float a = 0.0;
a += texture(tex, uv + vec2(-texel.x, 0.0)).r;
a += texture(tex, uv + vec2(texel.x, 0.0)).r;
a += texture(tex, uv + vec2(0.0, -texel.y)).r;
a += texture(tex, uv + vec2(0.0, texel.y)).r;
return a * 0.25;
}
void main() {
vec4 baseColor = texture(uBaseTexture, TexCoord);
float a1 = hasLayer1 != 0 ? sampleAlpha(uLayer1Alpha, LayerUV) : 0.0;
float a2 = hasLayer2 != 0 ? sampleAlpha(uLayer2Alpha, LayerUV) : 0.0;
float a3 = hasLayer3 != 0 ? sampleAlpha(uLayer3Alpha, LayerUV) : 0.0;
float w0 = 1.0, w1 = a1, w2 = a2, w3 = a3;
float sum = w0 + w1 + w2 + w3;
if (sum > 0.0) { w0 /= sum; w1 /= sum; w2 /= sum; w3 /= sum; }
vec4 finalColor = baseColor * w0;
if (hasLayer1 != 0) finalColor += texture(uLayer1Texture, TexCoord) * w1;
if (hasLayer2 != 0) finalColor += texture(uLayer2Texture, TexCoord) * w2;
if (hasLayer3 != 0) finalColor += texture(uLayer3Texture, TexCoord) * w3;
vec3 norm = normalize(Normal);
vec3 lightDir2 = normalize(-lightDir.xyz);
vec3 ambient = ambientColor.rgb * finalColor.rgb;
float diff = max(abs(dot(norm, lightDir2)), 0.2);
vec3 diffuse = diff * lightColor.rgb * finalColor.rgb;
float shadow = 1.0;
if (shadowParams.x > 0.5) {
vec4 lsPos = lightSpaceMatrix * vec4(FragPos, 1.0);
vec3 proj = lsPos.xyz / lsPos.w;
proj.xy = proj.xy * 0.5 + 0.5;
if (proj.x >= 0.0 && proj.x <= 1.0 && proj.y >= 0.0 && proj.y <= 1.0 && proj.z <= 1.0) {
float bias = 0.002;
shadow = texture(uShadowMap, vec3(proj.xy, proj.z - bias));
shadow = mix(1.0, shadow, shadowParams.y);
}
}
vec3 result = ambient + shadow * diffuse;
float distance = length(viewPos.xyz - FragPos);
float fogFactor = clamp((fogParams.y - distance) / (fogParams.y - fogParams.x), 0.0, 1.0);
result = mix(fogColor.rgb, result, fogFactor);
outColor = vec4(result, 1.0);
}

Binary file not shown.

View file

@ -0,0 +1,37 @@
#version 450
layout(set = 0, binding = 0) uniform PerFrame {
mat4 view;
mat4 projection;
mat4 lightSpaceMatrix;
vec4 lightDir;
vec4 lightColor;
vec4 ambientColor;
vec4 viewPos;
vec4 fogColor;
vec4 fogParams;
vec4 shadowParams;
};
layout(push_constant) uniform Push {
mat4 model;
} push;
layout(location = 0) in vec3 aPosition;
layout(location = 1) in vec3 aNormal;
layout(location = 2) in vec2 aTexCoord;
layout(location = 3) in vec2 aLayerUV;
layout(location = 0) out vec3 FragPos;
layout(location = 1) out vec3 Normal;
layout(location = 2) out vec2 TexCoord;
layout(location = 3) out vec2 LayerUV;
void main() {
vec4 worldPos = push.model * vec4(aPosition, 1.0);
FragPos = worldPos.xyz;
Normal = aNormal;
TexCoord = aTexCoord;
LayerUV = aLayerUV;
gl_Position = projection * view * worldPos;
}

Some files were not shown because too many files have changed in this diff Show more