Compare commits
47 Commits
36a0b14cf5
...
v0.1.2
| Author | SHA1 | Date | |
|---|---|---|---|
| 668871e628 | |||
| d989de2816 | |||
| 106cc84e62 | |||
| 1f334567c8 | |||
| c5d90fe82e | |||
| 5a1f2dd239 | |||
| fa38b20a3e | |||
| cb7587857d | |||
| 7244534ac4 | |||
| 199735609f | |||
| eceb1571e4 | |||
| 45e9cbcd52 | |||
| 116dd98712 | |||
| 0c8073d71d | |||
| 9617978dd5 | |||
| e511050399 | |||
| 8591d20e61 | |||
| 643b702aee | |||
| ec9e89886e | |||
| 15a9a749da | |||
| 7461dd766e | |||
| 3d1183e986 | |||
| cb1496fe4b | |||
| 236a2a1a49 | |||
|
|
d6e1e4a50e | ||
|
|
d62b310a21 | ||
|
|
cc2df5e4ec | ||
|
|
03259f323c | ||
|
|
913809a5f0 | ||
|
|
b1341d7da4 | ||
|
|
8a4081cf9c | ||
|
|
0f75144b2f | ||
|
|
30f843ba6b | ||
|
|
d5a12869e6 | ||
|
|
97993b72fe | ||
|
|
7ecdab08fc | ||
|
|
7ffc349eb3 | ||
|
|
5385876a8a | ||
|
|
a8d2ddbacd | ||
|
|
ca3fc5e3bf | ||
|
|
f4114c2699 | ||
|
|
932463663f | ||
|
|
bac3df801b | ||
|
|
d0bc8d627f | ||
|
|
2906106597 | ||
|
|
a0139dd315 | ||
|
|
5901ab7cd9 |
18
.github/workflows/format-check.yml
vendored
@@ -1,4 +1,3 @@
|
||||
# .github/workflows/format-check.yml
|
||||
name: Code Format Check
|
||||
|
||||
on: [push, pull_request]
|
||||
@@ -9,9 +8,22 @@ permissions:
|
||||
jobs:
|
||||
formatting:
|
||||
runs-on: ubuntu-latest
|
||||
container: silkeh/clang:latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install LLVM 22
|
||||
run: |
|
||||
wget https://apt.llvm.org/llvm.sh
|
||||
chmod +x llvm.sh
|
||||
sudo ./llvm.sh 22
|
||||
|
||||
sudo apt-get install -y clang-format-22
|
||||
|
||||
clang-format-22 --version
|
||||
|
||||
- name: Run clang-format
|
||||
run: |
|
||||
find src include -name '*.cpp' -o -name '*.h' -print0 | xargs -0 clang-format --dry-run --Werror
|
||||
find src include \
|
||||
\( -name '*.cpp' -o -name '*.hpp' \) \
|
||||
-print0 | xargs -0 clang-format-22 --dry-run --Werror
|
||||
161
.github/workflows/release-build.yml
vendored
Normal file
@@ -0,0 +1,161 @@
|
||||
name: Release-Build
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: Version
|
||||
required: false
|
||||
default: dev
|
||||
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: windows-2022
|
||||
platform: windows
|
||||
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
VCPKG_BINARY_SOURCES: clear;files,${{ github.workspace }}/.vcpkg-cache,readwrite
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
|
||||
- name: Get Version
|
||||
id: version
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
|
||||
VERSION="${GITHUB_REF_NAME#v}"
|
||||
else
|
||||
VERSION="${{ github.event.inputs.version }}"
|
||||
fi
|
||||
|
||||
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Setup MSVC
|
||||
if: matrix.platform == 'windows'
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
- name: Cache vcpkg
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: .vcpkg-cache
|
||||
key: ${{ runner.os }}-vcpkg-${{ hashFiles('vcpkg.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-vcpkg-
|
||||
- name: Bootstrap vcpkg
|
||||
run: |
|
||||
git clone https://github.com/microsoft/vcpkg.git
|
||||
./vcpkg/bootstrap-vcpkg.bat
|
||||
|
||||
- name: Configure
|
||||
if: matrix.platform == 'windows'
|
||||
run: >
|
||||
cmake
|
||||
-B build
|
||||
-G Ninja
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
-DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake
|
||||
-DVCPKG_TARGET_TRIPLET=x64-windows-release
|
||||
-DVCPKG_BUILD_TYPE=release
|
||||
-DBUILD_TESTING=OFF
|
||||
"-DCUBED_VERSION=${{ steps.version.outputs.version }}"
|
||||
|
||||
- name: Build
|
||||
run: cmake --build build --config Release --target Cubed
|
||||
|
||||
- name: Copy assets
|
||||
if: matrix.platform == 'windows'
|
||||
shell: pwsh
|
||||
run: |
|
||||
if (Test-Path assets) {
|
||||
Copy-Item -Path assets -Destination build/Cubed -Recurse
|
||||
} else {
|
||||
Write-Warning "assets folder not found, skipping copy"
|
||||
}
|
||||
|
||||
- name: Create Zip
|
||||
if: matrix.platform == 'windows'
|
||||
shell: pwsh
|
||||
run: |
|
||||
Compress-Archive `
|
||||
-Path build/Cubed/* `
|
||||
-DestinationPath Cubed-${{ steps.version.outputs.version }}-windows-x64.zip
|
||||
|
||||
####################################################################
|
||||
# Upload
|
||||
####################################################################
|
||||
|
||||
- name: Upload Windows Artifacts
|
||||
if: matrix.platform == 'windows'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: windows
|
||||
path: |
|
||||
*.zip
|
||||
|
||||
##########################################################################
|
||||
# Release
|
||||
##########################################################################
|
||||
|
||||
release:
|
||||
|
||||
needs: build
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Download Artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: artifacts
|
||||
|
||||
- name: Generate SHA256
|
||||
run: |
|
||||
cd artifacts
|
||||
|
||||
find . -type f | while read file
|
||||
do
|
||||
sha256sum "$file"
|
||||
done > SHA256SUMS
|
||||
|
||||
- name: Determine prerelease
|
||||
id: prerelease
|
||||
run: |
|
||||
MAIN_BRANCH="${{ github.event.repository.default_branch }}"
|
||||
git fetch origin "$MAIN_BRANCH" --depth=1 2>/dev/null || true
|
||||
|
||||
if git merge-base --is-ancestor "${{ github.sha }}" "origin/$MAIN_BRANCH"; then
|
||||
echo "is_prerelease=false" >> $GITHUB_OUTPUT
|
||||
echo "is_prerelease=false"
|
||||
else
|
||||
echo "is_prerelease=true" >> $GITHUB_OUTPUT
|
||||
echo "is_prerelease=true"
|
||||
fi
|
||||
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: |
|
||||
artifacts/**/*
|
||||
artifacts/SHA256SUMS
|
||||
generate_release_notes: true
|
||||
draft: false
|
||||
prerelease: ${{ steps.prerelease.outputs.is_prerelease }}
|
||||
4
.gitignore
vendored
@@ -41,3 +41,7 @@ CMakeError.log
|
||||
*~
|
||||
.DS_Store
|
||||
assets/config.toml
|
||||
assets/server-config.toml
|
||||
.venv/
|
||||
pyout/
|
||||
vcpkg_installed/
|
||||
1
.python-version
Normal file
@@ -0,0 +1 @@
|
||||
3.14
|
||||
257
CMakeLists.txt
@@ -1,4 +1,9 @@
|
||||
cmake_minimum_required(VERSION 3.14...3.24)
|
||||
cmake_minimum_required(VERSION 3.21)
|
||||
|
||||
if(APPLE)
|
||||
message(FATAL_ERROR "This game does not support macOS")
|
||||
endif()
|
||||
|
||||
project(Cubed LANGUAGES C CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
@@ -6,154 +11,124 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Debug)
|
||||
if(NOT CMAKE_CONFIGURATION_TYPES
|
||||
AND NOT CMAKE_BUILD_TYPE)
|
||||
|
||||
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
|
||||
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED CUBED_VERSION)
|
||||
set(CUBED_VERSION "dev")
|
||||
endif()
|
||||
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${PROJECT_NAME})
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${PROJECT_NAME})
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||
|
||||
if(MSVC)
|
||||
add_compile_options(/utf-8)
|
||||
endif()
|
||||
|
||||
find_package(OpenGL REQUIRED)
|
||||
|
||||
if (UNIX AND NOT APPLE)
|
||||
find_package(Freetype REQUIRED)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(EGL REQUIRED egl)
|
||||
pkg_check_modules(Wayland REQUIRED wayland-client wayland-egl)
|
||||
find_package(glfw3 REQUIRED)
|
||||
endif()
|
||||
|
||||
add_library(glad STATIC third_party/glad/src/glad.c)
|
||||
target_include_directories(glad PUBLIC third_party/glad/include)
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
if (WIN32)
|
||||
FetchContent_Declare(
|
||||
glfw
|
||||
GIT_REPOSITORY https://github.com/glfw/glfw.git
|
||||
GIT_TAG 3.4
|
||||
list(APPEND CMAKE_MODULE_PATH
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules"
|
||||
)
|
||||
|
||||
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
|
||||
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
||||
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
|
||||
set(GLFW_INSTALL OFF CACHE BOOL "" FORCE)
|
||||
set(GLFW_VULKAN_STATIC ON CACHE BOOL "" FORCE)
|
||||
set(GLFW_STATIC ON CACHE BOOL "" FORCE)
|
||||
include(Dependencies)
|
||||
|
||||
FetchContent_MakeAvailable(glfw)
|
||||
|
||||
FetchContent_Declare(
|
||||
freetype
|
||||
GIT_REPOSITORY https://gitlab.freedesktop.org/freetype/freetype.git
|
||||
GIT_TAG VER-2-14-3
|
||||
)
|
||||
FetchContent_MakeAvailable(freetype)
|
||||
if(TARGET freetype)
|
||||
add_library(Freetype::Freetype ALIAS freetype)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
FetchContent_Declare(
|
||||
glm
|
||||
GIT_REPOSITORY https://github.com/g-truc/glm.git
|
||||
GIT_TAG 1.0.3
|
||||
|
||||
)
|
||||
FetchContent_MakeAvailable(glm)
|
||||
FetchContent_Declare(
|
||||
soil2
|
||||
GIT_REPOSITORY https://github.com/SpartanJ/SOIL2.git
|
||||
GIT_TAG 1.31
|
||||
|
||||
)
|
||||
FetchContent_MakeAvailable(soil2)
|
||||
FetchContent_Declare(
|
||||
tomlplusplus
|
||||
GIT_REPOSITORY https://github.com/marzer/tomlplusplus.git
|
||||
GIT_TAG v3.4.0
|
||||
)
|
||||
FetchContent_MakeAvailable(tomlplusplus)
|
||||
add_subdirectory(third_party/glad)
|
||||
|
||||
add_subdirectory(third_party/imgui)
|
||||
|
||||
add_subdirectory(third_party/dr_libs)
|
||||
|
||||
set(INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include)
|
||||
add_executable(${PROJECT_NAME})
|
||||
|
||||
add_executable(${PROJECT_NAME}
|
||||
src/main.cpp
|
||||
src/app.cpp
|
||||
src/debug_collector.cpp
|
||||
src/camera.cpp
|
||||
src/config.cpp
|
||||
src/dev_panel.cpp
|
||||
src/gameplay/biome.cpp
|
||||
src/gameplay/chunk.cpp
|
||||
src/gameplay/chunk_generator.cpp
|
||||
src/gameplay/player.cpp
|
||||
src/gameplay/tree.cpp
|
||||
src/gameplay/world.cpp
|
||||
src/input.cpp
|
||||
src/map_table.cpp
|
||||
src/renderer.cpp
|
||||
src/shader.cpp
|
||||
src/texture_manager.cpp
|
||||
src/tools/cubed_random.cpp
|
||||
src/tools/math_tools.cpp
|
||||
src/tools/shader_tools.cpp
|
||||
src/tools/font.cpp
|
||||
src/tools/perlin_noise.cpp
|
||||
src/ui/text.cpp
|
||||
src/window.cpp
|
||||
src/gameplay/builders/biome_builder.cpp
|
||||
src/gameplay/builders/plain_builder.cpp
|
||||
src/gameplay/builders/mountain_builder.cpp
|
||||
src/gameplay/builders/river_builder.cpp
|
||||
src/gameplay/builders/desert_builder.cpp
|
||||
src/gameplay/builders/forest_builder.cpp
|
||||
src/gameplay/cave_carver.cpp
|
||||
src/gameplay/cave_path.cpp
|
||||
src/gameplay/builders/snowy_plain_builder.cpp
|
||||
src/gameplay/river_worm.cpp
|
||||
src/gameplay/river_path.cpp
|
||||
add_subdirectory(src)
|
||||
|
||||
file(GLOB_RECURSE PROTO_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/proto/*.proto
|
||||
)
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
message(STATUS "Building with AddressSanitizer enabled for target: ${PROJECT_NAME}")
|
||||
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE
|
||||
#-fsanitize=address
|
||||
#-fsanitize=thread
|
||||
-fno-omit-frame-pointer
|
||||
-g
|
||||
protobuf_generate(
|
||||
TARGET ${PROJECT_NAME}
|
||||
LANGUAGE cpp
|
||||
PROTOS ${PROTO_FILES}
|
||||
IMPORT_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src/proto
|
||||
)
|
||||
|
||||
target_link_options(${PROJECT_NAME} PRIVATE
|
||||
#-fsanitize=address
|
||||
#-fsanitize=thread
|
||||
configure_file(
|
||||
src/version.hpp.in
|
||||
${CMAKE_BINARY_DIR}/generated/version.hpp
|
||||
@ONLY
|
||||
)
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE DEBUG_MODE)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE
|
||||
ASSETS_PATH="${CMAKE_SOURCE_DIR}/assets/"
|
||||
target_compile_options(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
$<$<CONFIG:Debug>:-fno-omit-frame-pointer>
|
||||
$<$<CONFIG:Debug>:-g>
|
||||
#$<$<CONFIG:Debug>:-fsanitize=address>
|
||||
#$<$<CONFIG:Debug>:-fsanitize=thread>
|
||||
|
||||
$<$<CXX_COMPILER_ID:GNU,Clang>:-Wall>
|
||||
$<$<CXX_COMPILER_ID:GNU,Clang>:-Wextra>
|
||||
$<$<CXX_COMPILER_ID:GNU,Clang>:-Wpedantic>
|
||||
|
||||
$<$<CXX_COMPILER_ID:MSVC>:/utf-8>
|
||||
$<$<CXX_COMPILER_ID:MSVC>:/W4>
|
||||
)
|
||||
|
||||
target_link_options(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
#$<$<CONFIG:Debug>:-fsanitize=address>
|
||||
#$<$<CONFIG:Debug>:-fsanitize=thread>
|
||||
)
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
ASIO_STANDALONE
|
||||
ASIO_NO_DEPRECATED
|
||||
$<$<CONFIG:Debug>:DEBUG_MODE>
|
||||
$<$<CXX_COMPILER_ID:MSVC>:
|
||||
WIN32_LEAN_AND_MEAN
|
||||
NOMINMAX
|
||||
_CRT_SECURE_NO_WARNINGS
|
||||
>
|
||||
)
|
||||
|
||||
if(CMAKE_CONFIGURATION_TYPES)
|
||||
# Visual Studio / Xcode multi-configuration generator
|
||||
target_compile_definitions(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
ASSETS_PATH="$<$<CONFIG:Debug>:${PROJECT_SOURCE_DIR}/assets/>$<$<NOT:$<CONFIG:Debug>>:./assets/>"
|
||||
)
|
||||
else()
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE
|
||||
# Ninja / Makefiles single-configuration generator
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
target_compile_definitions(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
ASSETS_PATH="${PROJECT_SOURCE_DIR}/assets/"
|
||||
)
|
||||
else()
|
||||
target_compile_definitions(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
ASSETS_PATH="./assets/"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
${PROJECT_SOURCE_DIR}/include
|
||||
${PROJECT_SOURCE_DIR}/third_party/asio/include
|
||||
${CMAKE_BINARY_DIR}/generated
|
||||
${PROJECT_BINARY_DIR}
|
||||
${PROJECT_BINARY_DIR}/src
|
||||
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${INCLUDE_DIR})
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
glfw
|
||||
SDL3::SDL3
|
||||
glad
|
||||
glm::glm
|
||||
OpenGL::GL
|
||||
@@ -161,26 +136,28 @@ target_link_libraries(${PROJECT_NAME}
|
||||
Freetype::Freetype
|
||||
tomlplusplus::tomlplusplus
|
||||
imgui
|
||||
dr_libs
|
||||
tbb
|
||||
protobuf::libprotobuf
|
||||
absl::log
|
||||
absl::check
|
||||
absl::base
|
||||
absl::strings
|
||||
absl::flat_hash_map
|
||||
zstd::zstd
|
||||
OpenAL::OpenAL
|
||||
harfbuzz::harfbuzz
|
||||
$<$<PLATFORM_ID:Windows>:ws2_32>
|
||||
|
||||
)
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE tbb)
|
||||
endif()
|
||||
|
||||
if (UNIX AND NOT APPLE)
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
${EGL_LIBRARIES}
|
||||
${Wayland_LIBRARIES}
|
||||
)
|
||||
|
||||
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
${EGL_INCLUDE_DIRS}
|
||||
${Wayland_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE ${EGL_CFLAGS_OTHER} ${Wayland_CFLAGS_OTHER})
|
||||
if(WIN32)
|
||||
add_custom_command(
|
||||
TARGET ${PROJECT_NAME}
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
$<TARGET_RUNTIME_DLLS:${PROJECT_NAME}>
|
||||
$<TARGET_FILE_DIR:${PROJECT_NAME}>
|
||||
COMMAND_EXPAND_LISTS
|
||||
)
|
||||
endif()
|
||||
11
assets/data/block/air.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
id = 0
|
||||
is_blend = false
|
||||
is_cross_plane = false
|
||||
is_discard = true
|
||||
is_gas = true
|
||||
is_liquid = false
|
||||
is_passable = true
|
||||
is_transitional = false
|
||||
is_transparent = true
|
||||
name = 'air'
|
||||
roughness = 1.0
|
||||
11
assets/data/block/dirt.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
id = 2
|
||||
is_blend = false
|
||||
is_cross_plane = false
|
||||
is_discard = false
|
||||
is_gas = false
|
||||
is_liquid = false
|
||||
is_passable = false
|
||||
is_transitional = true
|
||||
is_transparent = false
|
||||
name = 'dirt'
|
||||
roughness = 1.0
|
||||
11
assets/data/block/grass.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
id = 9
|
||||
is_blend = false
|
||||
is_cross_plane = true
|
||||
is_discard = true
|
||||
is_gas = false
|
||||
is_liquid = false
|
||||
is_passable = true
|
||||
is_transitional = false
|
||||
is_transparent = true
|
||||
name = 'grass'
|
||||
roughness = 0.9
|
||||
11
assets/data/block/grass_block.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
id = 1
|
||||
is_blend = false
|
||||
is_cross_plane = false
|
||||
is_discard = false
|
||||
is_gas = false
|
||||
is_liquid = false
|
||||
is_passable = false
|
||||
is_transitional = true
|
||||
is_transparent = false
|
||||
name = 'grass_block'
|
||||
roughness = 0.9
|
||||
11
assets/data/block/leaf.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
id = 6
|
||||
is_blend = false
|
||||
is_cross_plane = false
|
||||
is_discard = true
|
||||
is_gas = false
|
||||
is_liquid = false
|
||||
is_passable = false
|
||||
is_transitional = false
|
||||
is_transparent = true
|
||||
name = 'leaf'
|
||||
roughness = 0.7
|
||||
11
assets/data/block/log.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
id = 5
|
||||
is_blend = false
|
||||
is_cross_plane = false
|
||||
is_discard = false
|
||||
is_gas = false
|
||||
is_liquid = false
|
||||
is_passable = false
|
||||
is_transitional = false
|
||||
is_transparent = false
|
||||
name = 'log'
|
||||
roughness = 0.7
|
||||
11
assets/data/block/sand.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
id = 4
|
||||
is_blend = false
|
||||
is_cross_plane = false
|
||||
is_discard = false
|
||||
is_gas = false
|
||||
is_liquid = false
|
||||
is_passable = false
|
||||
is_transitional = true
|
||||
is_transparent = false
|
||||
name = 'sand'
|
||||
roughness = 0.8
|
||||
11
assets/data/block/snowy_grass_block.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
id = 8
|
||||
is_blend = false
|
||||
is_cross_plane = false
|
||||
is_discard = false
|
||||
is_gas = false
|
||||
is_liquid = false
|
||||
is_passable = false
|
||||
is_transitional = true
|
||||
is_transparent = false
|
||||
name = 'snowy_grass_block'
|
||||
roughness = 0.9
|
||||
11
assets/data/block/stone.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
id = 3
|
||||
is_blend = false
|
||||
is_cross_plane = false
|
||||
is_discard = false
|
||||
is_gas = false
|
||||
is_liquid = false
|
||||
is_passable = false
|
||||
is_transitional = true
|
||||
is_transparent = false
|
||||
name = 'stone'
|
||||
roughness = 0.75
|
||||
11
assets/data/block/template.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
name = "template"
|
||||
id = 0
|
||||
is_liquid = false
|
||||
is_gas = false
|
||||
is_passable = false
|
||||
is_cross_plane = false
|
||||
is_transparent = false
|
||||
is_discard = false
|
||||
is_blend = false
|
||||
is_transitional = false
|
||||
roughness = 1.0
|
||||
11
assets/data/block/water.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
id = 7
|
||||
is_blend = true
|
||||
is_cross_plane = false
|
||||
is_discard = false
|
||||
is_gas = false
|
||||
is_liquid = true
|
||||
is_passable = true
|
||||
is_transitional = false
|
||||
is_transparent = true
|
||||
name = 'water'
|
||||
roughness = 0.02
|
||||
90
assets/fonts/OFL-1.1.txt
Normal file
@@ -0,0 +1,90 @@
|
||||
The SIL Open Font License version 1.1 is copied below, and is also
|
||||
available with a FAQ at http://scripts.sil.org/OFL.
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
BIN
assets/fonts/unifont_t-17.0.05.otf
Normal file
34
assets/lang/en_US.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"menu.settings": "Settings",
|
||||
"menu.main.host_game": "Host Game",
|
||||
"menu.main.join_game": "Join Game",
|
||||
"menu.main.credits": "Credits",
|
||||
"menu.main.quit": "Quit",
|
||||
"menu.main.player_name": "Player: {name}",
|
||||
"menu.main.cubed_version": "Cubed: {version}",
|
||||
"menu.pause.pause_menu": "Pause Menu",
|
||||
"menu.pause.back_to_game": "Back To Game",
|
||||
"menu.pause.return_to_main_menu": "Return to Menu",
|
||||
"button.done": "Done",
|
||||
"button.return": "Return",
|
||||
"settings.title": "Settings",
|
||||
"settings.fov": "Fov: {fov}",
|
||||
"settings.mouse_sensitivity": "Sensitivity: {sensitivity}",
|
||||
"settings.distance": "Distance: {distance}",
|
||||
"settings.music_volume": "Music: {music}",
|
||||
"settings.sfx_volume": "SFX: {sfx}",
|
||||
"settings.fullscreen": "fullscreen: {state}",
|
||||
"settings.aniso": "Aniso: {aniso}",
|
||||
"settings.vsync": "V-Sync: {state}",
|
||||
"settings.language": "Language: {lang}",
|
||||
"settings.restart_game_info": "You need to restart the game to apply this changes.",
|
||||
"common.on": "on",
|
||||
"common.off": "off",
|
||||
"hostgame.create_a_new_world": "Create A New World",
|
||||
"hostgame.world_seed": "World Seed",
|
||||
"hostgame.port": "Port",
|
||||
"hostgame.create_world": "Create World",
|
||||
"joingame.join_a_world": "Join A World",
|
||||
"joingame.server_ip": "Server Ip",
|
||||
"joingame.join_world": "Join World"
|
||||
}
|
||||
34
assets/lang/zh_CN.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"menu.settings": "设置",
|
||||
"menu.main.host_game": "创建游戏",
|
||||
"menu.main.join_game": "加入游戏",
|
||||
"menu.main.credits": "制作人员",
|
||||
"menu.main.quit": "退出",
|
||||
"menu.main.player_name": "玩家:{name}",
|
||||
"menu.main.cubed_version": "Cubed:{version}",
|
||||
"menu.pause.pause_menu": "暂停菜单",
|
||||
"menu.pause.back_to_game": "返回游戏",
|
||||
"menu.pause.return_to_main_menu": "返回主菜单",
|
||||
"button.done": "完成",
|
||||
"button.return": "返回",
|
||||
"settings.title": "设置",
|
||||
"settings.fov": "视野:{fov}",
|
||||
"settings.mouse_sensitivity": "灵敏度:{sensitivity}",
|
||||
"settings.distance": "距离:{distance}",
|
||||
"settings.music_volume": "音乐:{music}",
|
||||
"settings.sfx_volume": "音效:{sfx}",
|
||||
"settings.fullscreen": "全屏:{state}",
|
||||
"settings.aniso": "各向异性过滤:{aniso}",
|
||||
"settings.vsync": "垂直同步: {state}",
|
||||
"settings.language": "语言: {lang}",
|
||||
"settings.restart_game_info": "您需要重启游戏以应用这些更改。",
|
||||
"common.on": "开",
|
||||
"common.off": "关",
|
||||
"hostgame.create_a_new_world": "创建新世界",
|
||||
"hostgame.world_seed": "世界种子",
|
||||
"hostgame.port": "端口",
|
||||
"hostgame.create_world": "创建世界",
|
||||
"joingame.join_a_world": "加入世界",
|
||||
"joingame.server_ip": "服务器IP",
|
||||
"joingame.join_world": "加入世界"
|
||||
}
|
||||
BIN
assets/normal/block/dirt/back_n.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
assets/normal/block/dirt/base_n.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
assets/normal/block/dirt/front_n.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
assets/normal/block/dirt/left_n.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
assets/normal/block/dirt/right_n.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
assets/normal/block/dirt/top_n.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
assets/normal/block/grass_block/back_n.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
assets/normal/block/grass_block/base_n.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
assets/normal/block/grass_block/front_n.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
assets/normal/block/grass_block/left_n.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
assets/normal/block/grass_block/right_n.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
assets/normal/block/grass_block/top_n.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
assets/normal/block/log/back_n.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/normal/block/log/base_n.png
Normal file
|
After Width: | Height: | Size: 955 B |
BIN
assets/normal/block/log/front_n.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/normal/block/log/left_n.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/normal/block/log/right_n.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/normal/block/log/top_n.png
Normal file
|
After Width: | Height: | Size: 955 B |
BIN
assets/normal/block/sand/back_n.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
assets/normal/block/sand/base_n.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
assets/normal/block/sand/front_n.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
assets/normal/block/sand/left_n.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
assets/normal/block/sand/right_n.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
assets/normal/block/sand/top_n.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
assets/normal/block/snowy_grass_block/back_n.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
assets/normal/block/snowy_grass_block/base_n.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
assets/normal/block/snowy_grass_block/front_n.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
assets/normal/block/snowy_grass_block/left_n.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
assets/normal/block/snowy_grass_block/right_n.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
assets/normal/block/snowy_grass_block/top_n.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
assets/normal/block/stone/back_n.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
assets/normal/block/stone/base_n.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
assets/normal/block/stone/front_n.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
assets/normal/block/stone/left_n.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
assets/normal/block/stone/right_n.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
assets/normal/block/stone/top_n.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
11
assets/shaders/billboard_f_shader.glsl
Normal file
@@ -0,0 +1,11 @@
|
||||
#version 460
|
||||
|
||||
out vec4 frag_color;
|
||||
|
||||
uniform vec3 color;
|
||||
|
||||
void main(void) {
|
||||
|
||||
frag_color = vec4(color, 1.0);
|
||||
|
||||
}
|
||||
10
assets/shaders/billboard_v_shader.glsl
Normal file
@@ -0,0 +1,10 @@
|
||||
#version 460
|
||||
|
||||
layout (location = 0) in vec3 vertices_pos;
|
||||
|
||||
uniform mat4 mv_matrix;
|
||||
uniform mat4 proj_matrix;
|
||||
|
||||
void main(void) {
|
||||
gl_Position = proj_matrix * mv_matrix * vec4(vertices_pos, 1.0);
|
||||
}
|
||||
103
assets/shaders/block_accumulation_f_shader.glsl
Normal file
@@ -0,0 +1,103 @@
|
||||
#version 460
|
||||
|
||||
layout (location = 0) out vec4 accum;
|
||||
layout (location = 1) out float reveal;
|
||||
|
||||
in vec2 tc;
|
||||
in vec3 normal;
|
||||
in vec3 vert_pos;
|
||||
in float roughness;
|
||||
flat in int tex_layer;
|
||||
in float v_depth;
|
||||
layout (binding = 0) uniform sampler2DArray samp;
|
||||
|
||||
uniform float ambientStrength;
|
||||
uniform vec3 sunlightColor;
|
||||
uniform vec3 ambientColor;
|
||||
uniform vec3 sunlightDir;
|
||||
uniform vec3 cameraPos;
|
||||
uniform bool shader_on;
|
||||
uniform float specularStrength;
|
||||
|
||||
float weight(float z, float a) {
|
||||
float intermediate = 0.03 / (1e-5 + pow(z / 200.0, 4.0));
|
||||
|
||||
return a * clamp(intermediate, 1e-2, 3e2);
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
||||
vec4 objectColor = texture(samp, vec3(tc, tex_layer));
|
||||
|
||||
if (!shader_on) {
|
||||
vec4 color = objectColor;
|
||||
float alpha = color.a;
|
||||
if (alpha < 1e-4) discard;
|
||||
|
||||
|
||||
float w = weight(v_depth, alpha);
|
||||
|
||||
accum = vec4(color.rgb * alpha * w, alpha * w);
|
||||
|
||||
reveal = alpha;
|
||||
return;
|
||||
}
|
||||
|
||||
vec3 lightDir = normalize(-sunlightDir);
|
||||
|
||||
vec3 norm = normalize(normal);
|
||||
|
||||
vec3 V =
|
||||
normalize(cameraPos - vert_pos);
|
||||
|
||||
vec3 H =
|
||||
normalize(lightDir + V);
|
||||
|
||||
vec3 ambient = ambientStrength * ambientColor;
|
||||
|
||||
float diff = max(dot(norm, lightDir), 0.0);
|
||||
|
||||
vec3 diffuse = diff * sunlightColor;
|
||||
|
||||
float r =
|
||||
clamp(roughness, 0.0, 1.0);
|
||||
|
||||
float shininess =
|
||||
mix(
|
||||
512.0,
|
||||
4.0,
|
||||
r
|
||||
);
|
||||
float ks =
|
||||
mix(
|
||||
0.8,
|
||||
0.02,
|
||||
r
|
||||
);
|
||||
|
||||
float spec = 0.0;
|
||||
|
||||
if(diff > 0.0)
|
||||
{
|
||||
spec =
|
||||
ks *
|
||||
pow(
|
||||
max(dot(norm,H),0.0),
|
||||
shininess
|
||||
);
|
||||
}
|
||||
|
||||
vec3 specular = spec * sunlightColor * specularStrength;
|
||||
|
||||
vec4 color = vec4((ambient + diffuse) * objectColor.rgb + specular, objectColor.a);
|
||||
|
||||
float alpha = color.a;
|
||||
if (alpha < 1e-4) discard;
|
||||
|
||||
|
||||
float w = weight(v_depth, alpha);
|
||||
|
||||
accum = vec4(color.rgb * alpha * w, alpha * w);
|
||||
|
||||
reveal = alpha;
|
||||
}
|
||||
30
assets/shaders/block_accumulation_v_shader.glsl
Normal file
@@ -0,0 +1,30 @@
|
||||
#version 460
|
||||
|
||||
layout (location = 0) in vec3 pos;
|
||||
layout (location = 1) in vec2 texCoord;
|
||||
layout (location = 2) in float layer;
|
||||
layout (location = 3) in vec3 aNormal;
|
||||
layout (location = 4) in float Roughness;
|
||||
|
||||
out vec2 tc;
|
||||
out vec3 normal;
|
||||
out vec3 vert_pos;
|
||||
flat out int tex_layer;
|
||||
out float roughness;
|
||||
out float v_depth;
|
||||
|
||||
uniform mat4 mv_matrix;
|
||||
uniform mat4 proj_matrix;
|
||||
uniform mat4 norm_matrix;
|
||||
|
||||
|
||||
void main(void) {
|
||||
vec4 view_pos = mv_matrix * vec4(pos, 1.0);
|
||||
vert_pos = pos;
|
||||
roughness = Roughness;
|
||||
tc = texCoord;
|
||||
tex_layer = int(layer);
|
||||
v_depth = -view_pos.z;
|
||||
normal = mat3(norm_matrix) * aNormal;
|
||||
gl_Position = proj_matrix * view_pos;
|
||||
}
|
||||
19
assets/shaders/block_composite_f_shader.glsl
Normal file
@@ -0,0 +1,19 @@
|
||||
#version 460
|
||||
|
||||
uniform sampler2D u_accumTex;
|
||||
uniform sampler2D u_revealTex;
|
||||
in vec2 TexCoord;
|
||||
out vec4 FragColor;
|
||||
|
||||
void main() {
|
||||
vec4 a = texture(u_accumTex, TexCoord);
|
||||
float r = texture(u_revealTex, TexCoord).r;
|
||||
|
||||
if (a.a < 1e-4) discard;
|
||||
|
||||
vec3 color = a.rgb / max(a.a, 1e-5);
|
||||
float transmittance = r;
|
||||
float opacity = 1.0 - transmittance;
|
||||
|
||||
FragColor = vec4(color * opacity, opacity);
|
||||
}
|
||||
11
assets/shaders/block_composite_v_shader.glsl
Normal file
@@ -0,0 +1,11 @@
|
||||
#version 460
|
||||
|
||||
layout (location = 0) in vec2 pos;
|
||||
layout (location = 1) in vec2 texCoord;
|
||||
|
||||
out vec2 TexCoord;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(pos.x, pos.y, 0.0, 1.0);
|
||||
TexCoord = texCoord;
|
||||
}
|
||||
@@ -1,15 +1,117 @@
|
||||
#version 460
|
||||
|
||||
in vec2 tc;
|
||||
in vec3 normal;
|
||||
in vec3 vert_pos;
|
||||
in vec3 tangent;
|
||||
in vec3 bitangent;
|
||||
in vec4 FragPosLightSpace;
|
||||
in float roughness;
|
||||
flat in int tex_layer;
|
||||
out vec4 color;
|
||||
layout (binding = 0) uniform sampler2D shadowMap;
|
||||
layout (binding = 1) uniform sampler2DArray samp;
|
||||
layout (binding = 2) uniform sampler2DArray normMap;
|
||||
uniform float ambientStrength;
|
||||
uniform vec3 sunlightColor;
|
||||
uniform vec3 ambientColor;
|
||||
uniform vec3 sunlightDir;
|
||||
uniform vec3 cameraPos;
|
||||
uniform bool shader_on;
|
||||
uniform int shadowMode;
|
||||
uniform float specularStrength;
|
||||
uniform float lightSizeUV;
|
||||
uniform float minRadius;
|
||||
uniform float maxRadius;
|
||||
uniform bool enablePBR;
|
||||
uniform bool flipY;
|
||||
|
||||
layout (binding = 0) uniform sampler2DArray samp;
|
||||
uniform int renderDistance;
|
||||
uniform vec3 skyColor;
|
||||
|
||||
#include "shadow.glsl"
|
||||
#include "normal.glsl"
|
||||
|
||||
void main(void) {
|
||||
color = texture(samp, vec3(tc, tex_layer));
|
||||
if (color.a < 0.5) {
|
||||
vec4 objectColor = texture(samp, vec3(tc, tex_layer));
|
||||
|
||||
if (objectColor.a < 0.8) {
|
||||
discard;
|
||||
}
|
||||
//color = varyingColor;
|
||||
if (!shader_on) {
|
||||
color = objectColor;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
vec3 lightDir = normalize(-sunlightDir);
|
||||
vec3 norm;
|
||||
if (enablePBR) {
|
||||
norm = calcNewNormal();
|
||||
} else {
|
||||
norm = normalize(normal);
|
||||
}
|
||||
|
||||
|
||||
vec3 V =
|
||||
normalize(cameraPos - vert_pos);
|
||||
|
||||
vec3 H =
|
||||
normalize(lightDir + V);
|
||||
|
||||
vec3 ambient = ambientStrength * ambientColor;
|
||||
|
||||
float diff = max(dot(norm, lightDir), 0.0);
|
||||
|
||||
vec3 diffuse = diff * sunlightColor;
|
||||
|
||||
float r =
|
||||
clamp(roughness, 0.0, 1.0);
|
||||
|
||||
float shininess =
|
||||
mix(
|
||||
512.0,
|
||||
4.0,
|
||||
r
|
||||
);
|
||||
float ks =
|
||||
mix(
|
||||
0.8,
|
||||
0.02,
|
||||
r
|
||||
);
|
||||
|
||||
float spec = 0.0;
|
||||
|
||||
if(diff > 0.0)
|
||||
{
|
||||
spec =
|
||||
ks *
|
||||
pow(
|
||||
max(dot(norm,H),0.0),
|
||||
shininess
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
vec3 specular = spec * sunlightColor * specularStrength;
|
||||
|
||||
float shadow = ShadowCalculation(FragPosLightSpace, norm, lightDir);
|
||||
|
||||
// fog
|
||||
float dist = length(cameraPos - vert_pos);
|
||||
vec4 fogColor = vec4(skyColor, 1.0);
|
||||
float fogStart = renderDistance * 16 * 0.9;
|
||||
float fogEnd = renderDistance * 16;
|
||||
|
||||
float fogFactor = smoothstep(fogEnd, fogStart, dist);
|
||||
color = vec4((ambient + (1.0 - shadow) * (diffuse)) * objectColor.rgb + (1.0-shadow) * specular * objectColor.rgb, objectColor.a);
|
||||
|
||||
color = mix(fogColor, color, fogFactor);
|
||||
//color = vec4(normal * 0.5 + 0.5, 1.0);
|
||||
//color = vec4(tangent * 0.5 + 0.5, 1.0);;
|
||||
//color = vec4(norm * 0.5 + 0.5, 1.0);
|
||||
//color = vec4(calcNewNormal(), 1.0);
|
||||
}
|
||||
|
||||
@@ -3,8 +3,17 @@
|
||||
layout (location = 0) in vec3 pos;
|
||||
layout (location = 1) in vec2 texCoord;
|
||||
layout (location = 2) in float layer;
|
||||
layout (location = 3) in vec3 aNormal;
|
||||
layout (location = 4) in float Roughness;
|
||||
layout (location = 5) in vec3 aTangent;
|
||||
out vec2 tc;
|
||||
out vec3 normal;
|
||||
out vec3 tangent;
|
||||
out vec3 bitangent;
|
||||
out vec3 vert_pos;
|
||||
flat out int tex_layer;
|
||||
out vec4 FragPosLightSpace;
|
||||
out float roughness;
|
||||
|
||||
mat4 buildRotateX(float rad);
|
||||
mat4 buildRotateY(float rad);
|
||||
@@ -13,13 +22,24 @@ mat4 buildTranslate(float x, float y, float z);
|
||||
|
||||
uniform mat4 mv_matrix;
|
||||
uniform mat4 proj_matrix;
|
||||
|
||||
|
||||
uniform mat4 model_matrix;
|
||||
uniform mat4 norm_matrix;
|
||||
uniform mat4 lightSpaceMatrix;
|
||||
|
||||
void main(void) {
|
||||
gl_Position = proj_matrix * mv_matrix * vec4(pos, 1.0);
|
||||
vec4 viewPos = mv_matrix * vec4(pos, 1.0);
|
||||
|
||||
vert_pos = pos;
|
||||
|
||||
tc = texCoord;
|
||||
|
||||
tex_layer = int(layer);
|
||||
roughness = Roughness;
|
||||
normal = normalize(mat3(norm_matrix) * aNormal);
|
||||
tangent = normalize(mat3(model_matrix) * aTangent);
|
||||
bitangent = cross(normal, tangent);
|
||||
FragPosLightSpace = lightSpaceMatrix * vec4(pos, 1.0);
|
||||
gl_Position = proj_matrix * viewPos;
|
||||
}
|
||||
|
||||
mat4 buildTranslate(float x, float y, float z) {
|
||||
|
||||
46
assets/shaders/compute_sky_color.glsl
Normal file
@@ -0,0 +1,46 @@
|
||||
#include "noise.glsl"
|
||||
|
||||
vec3 computeSkyColor(vec3 dir) {
|
||||
vec3 sund = normalize(sunDir);
|
||||
|
||||
float t =
|
||||
clamp(
|
||||
dir.y * 0.5 + 0.5,
|
||||
0.0,
|
||||
1.0
|
||||
);
|
||||
|
||||
|
||||
vec3 sky =
|
||||
mix(
|
||||
skyBottom,
|
||||
skyTop,
|
||||
pow(t, horizonSharpness)
|
||||
);
|
||||
|
||||
// cloud
|
||||
if (dir.y > 0.0) {
|
||||
vec2 cloud_uv = dir.xz / (dir.y + 0.15) * 0.5 + vec2(time * 0.005, time * 0.002);
|
||||
float cloud_density = fbm(cloud_uv * 2.0);
|
||||
float safeLow = cloudThresholdLow;
|
||||
float safeHigh = max(cloudThresholdHigh, cloudThresholdLow + 0.001);
|
||||
cloud_density = smoothstep(safeLow,safeHigh, cloud_density);
|
||||
|
||||
|
||||
float fade = smoothstep(0.0, 0.3, dir.y) * (1.0 - smoothstep(0.85, 1.0, dir.y));
|
||||
cloud_density *= fade;
|
||||
|
||||
vec3 cloud_color = mix(skyBottom, vec3(1.0), cloudWhiteMix);
|
||||
sky = mix(sky, cloud_color, cloud_density * 0.6);
|
||||
}
|
||||
|
||||
float sunAmount = max(dot(dir, sund), 0.0);
|
||||
|
||||
//float glow = pow(sunAmount, 8.0) * 0.15;
|
||||
|
||||
float glow = pow(sunAmount, 8.0) * 0.15 + pow(sunAmount, 32.0) * 0.3;
|
||||
|
||||
sky += glow * sunColor;
|
||||
|
||||
return sky;
|
||||
}
|
||||
16
assets/shaders/depth_fragment_shader.glsl
Normal file
@@ -0,0 +1,16 @@
|
||||
#version 460
|
||||
|
||||
in vec2 tc;
|
||||
flat in int tex_layer;
|
||||
layout (binding = 1) uniform sampler2DArray samp;
|
||||
|
||||
uniform bool is_discard_tranparent;
|
||||
|
||||
void main() {
|
||||
if (is_discard_tranparent) {
|
||||
vec4 texColor = texture(samp, vec3(tc, tex_layer));
|
||||
if (texColor.a < 0.8)
|
||||
discard;
|
||||
}
|
||||
//gl_FragDepth = gl_FragCoord.z;
|
||||
}
|
||||
7
assets/shaders/depth_player_fragment_shader.glsl
Normal file
@@ -0,0 +1,7 @@
|
||||
#version 460
|
||||
|
||||
in vec2 tc;
|
||||
|
||||
void main() {
|
||||
|
||||
}
|
||||
15
assets/shaders/depth_player_shader.glsl
Normal file
@@ -0,0 +1,15 @@
|
||||
#version 460
|
||||
|
||||
layout (location = 0) in vec3 pos;
|
||||
layout (location = 1) in vec2 texCoord;
|
||||
|
||||
uniform mat4 lightSpaceMatrix;
|
||||
uniform mat4 modelMatrix;
|
||||
|
||||
out vec2 tc;
|
||||
flat out int tex_layer;
|
||||
|
||||
void main() {
|
||||
tc = texCoord;
|
||||
gl_Position = lightSpaceMatrix * modelMatrix * vec4(pos, 1.0);
|
||||
}
|
||||
@@ -1,18 +1,12 @@
|
||||
#version 460
|
||||
|
||||
layout (location = 0) in vec2 pos;
|
||||
layout (location = 0) in vec3 pos;
|
||||
layout (location = 1) in vec2 texCoord;
|
||||
layout (location = 2) in float layer;
|
||||
|
||||
uniform mat4 lightSpaceMatrix;
|
||||
out vec2 tc;
|
||||
|
||||
flat out int tex_layer;
|
||||
|
||||
uniform mat4 m_matrix;
|
||||
uniform mat4 proj_matrix;
|
||||
|
||||
void main(void) {
|
||||
gl_Position = proj_matrix * m_matrix * vec4(pos, 0.0, 1.0);
|
||||
void main() {
|
||||
tc = texCoord;
|
||||
tex_layer = int(layer);
|
||||
gl_Position = lightSpaceMatrix * vec4(pos, 1.0);
|
||||
}
|
||||
11
assets/shaders/image_f_shader.glsl
Normal file
@@ -0,0 +1,11 @@
|
||||
#version 460
|
||||
|
||||
in vec2 tc;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
layout (binding = 0) uniform sampler2D samp;
|
||||
|
||||
void main(void) {
|
||||
color = texture(samp, tc);
|
||||
}
|
||||
14
assets/shaders/image_v_shader.glsl
Normal file
@@ -0,0 +1,14 @@
|
||||
#version 460
|
||||
|
||||
layout (location = 0) in vec2 pos;
|
||||
layout (location = 1) in vec2 texCoord;
|
||||
|
||||
out vec2 tc;
|
||||
|
||||
uniform mat4 model_matrix;
|
||||
uniform mat4 proj_matrix;
|
||||
|
||||
void main(void) {
|
||||
gl_Position = proj_matrix * model_matrix * vec4(pos, 0.0, 1.0);
|
||||
tc = texCoord;
|
||||
}
|
||||
25
assets/shaders/noise.glsl
Normal file
@@ -0,0 +1,25 @@
|
||||
float hash(vec2 p) {
|
||||
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);
|
||||
}
|
||||
|
||||
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 v = 0.0;
|
||||
float amp = 0.5;
|
||||
for (int i = 0; i < 5; i++) {
|
||||
v += amp * noise(p);
|
||||
p *= 2.0;
|
||||
amp *= 0.5;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
10
assets/shaders/normal.glsl
Normal file
@@ -0,0 +1,10 @@
|
||||
vec3 calcNewNormal() {
|
||||
mat3 TBN = mat3(normalize(tangent), normalize(bitangent), normalize(normal));
|
||||
vec3 retrievedNormal = texture(normMap, vec3(tc, tex_layer)).xyz;
|
||||
retrievedNormal = retrievedNormal * 2.0 - 1.0;
|
||||
if (flipY) {
|
||||
retrievedNormal.y = -retrievedNormal.y;
|
||||
}
|
||||
vec3 newNormal = TBN * retrievedNormal;
|
||||
return normalize(newNormal);
|
||||
}
|
||||
47
assets/shaders/player_f_shader.glsl
Normal file
@@ -0,0 +1,47 @@
|
||||
#version 460
|
||||
|
||||
in vec2 tc;
|
||||
in vec3 normal;
|
||||
in vec3 vert_pos;
|
||||
in vec4 FragPosLightSpace;
|
||||
out vec4 color;
|
||||
|
||||
layout (binding = 0) uniform sampler2D shadowMap;
|
||||
layout (binding = 1) uniform sampler2D samp;
|
||||
|
||||
uniform float ambientStrength;
|
||||
uniform vec3 sunlightColor;
|
||||
uniform vec3 ambientColor;
|
||||
uniform vec3 sunlightDir;
|
||||
uniform bool shader_on;
|
||||
uniform int shadowMode;
|
||||
uniform float lightSizeUV;
|
||||
uniform float minRadius;
|
||||
uniform float maxRadius;
|
||||
|
||||
#include "shadow.glsl"
|
||||
|
||||
void main() {
|
||||
vec4 objectColor = texture(samp, tc);
|
||||
|
||||
if (!shader_on) {
|
||||
color = objectColor;
|
||||
return;
|
||||
}
|
||||
|
||||
vec3 lightDir = normalize(-sunlightDir);
|
||||
|
||||
vec3 norm = normalize(normal);
|
||||
|
||||
vec3 ambient = ambientStrength * ambientColor;
|
||||
|
||||
float diff = max(dot(norm, lightDir), 0.0);
|
||||
|
||||
vec3 diffuse = diff * sunlightColor;
|
||||
|
||||
float shadow = ShadowCalculation(FragPosLightSpace, norm, lightDir);
|
||||
//float shadow = 0.0;
|
||||
//color = vec4(vec3(shadow),1);
|
||||
//color = vec4(vec3(diff),1);
|
||||
color = vec4((ambient + (1.0 - shadow) * (diffuse)) * objectColor.rgb, objectColor.a);
|
||||
}
|
||||
27
assets/shaders/player_v_shader.glsl
Normal file
@@ -0,0 +1,27 @@
|
||||
#version 460
|
||||
|
||||
layout (location = 0) in vec3 pos;
|
||||
layout (location = 1) in vec2 texCoord;
|
||||
layout (location = 2) in vec3 aNormal;
|
||||
layout (location = 3) in vec3 aTangent;
|
||||
|
||||
uniform mat4 mv_matrix;
|
||||
uniform mat4 proj_matrix;
|
||||
uniform mat4 norm_matrix;
|
||||
uniform mat4 lightSpaceMatrix;
|
||||
uniform mat4 modelMatrix;
|
||||
out vec4 FragPosLightSpace;
|
||||
out vec3 normal;
|
||||
out vec2 tc;
|
||||
out vec3 vert_pos;
|
||||
|
||||
|
||||
void main() {
|
||||
vec4 worldPos = modelMatrix * vec4(pos, 1.0);
|
||||
FragPosLightSpace = lightSpaceMatrix * worldPos;
|
||||
vec4 viewPos = mv_matrix * vec4(pos, 1.0);
|
||||
tc = texCoord;
|
||||
vert_pos = pos;
|
||||
normal = normalize(mat3(norm_matrix) * aNormal);
|
||||
gl_Position = proj_matrix * viewPos;
|
||||
}
|
||||
9
assets/shaders/rect_f_shader.glsl
Normal file
@@ -0,0 +1,9 @@
|
||||
#version 460
|
||||
|
||||
out vec4 color;
|
||||
|
||||
uniform vec4 inColor;
|
||||
|
||||
void main(void) {
|
||||
color = inColor;
|
||||
}
|
||||
11
assets/shaders/rect_v_shader.glsl
Normal file
@@ -0,0 +1,11 @@
|
||||
#version 460
|
||||
|
||||
layout (location = 0) in vec2 pos;
|
||||
|
||||
|
||||
uniform mat4 model_matrix;
|
||||
uniform mat4 proj_matrix;
|
||||
|
||||
void main(void) {
|
||||
gl_Position = proj_matrix * model_matrix * vec4(pos, 0.0, 1.0);
|
||||
}
|
||||
238
assets/shaders/shadow.glsl
Normal file
@@ -0,0 +1,238 @@
|
||||
const vec2 poissonDisk32[32] = vec2[](
|
||||
vec2(-0.975402, -0.071138),
|
||||
vec2(-0.920347, -0.411420),
|
||||
vec2(-0.883908, 0.217872),
|
||||
vec2(-0.815442, -0.879125),
|
||||
vec2(-0.775043, 0.543896),
|
||||
vec2(-0.698126, -0.227570),
|
||||
vec2(-0.682433, 0.801894),
|
||||
vec2(-0.563905, 0.021517),
|
||||
vec2(-0.443233, -0.975116),
|
||||
vec2(-0.412231, 0.361307),
|
||||
vec2(-0.264969, -0.418930),
|
||||
vec2(-0.241888, 0.997065),
|
||||
vec2(-0.094184, -0.929389),
|
||||
vec2(-0.019101, 0.680997),
|
||||
vec2( 0.143832, -0.141008),
|
||||
vec2( 0.199841, 0.786414),
|
||||
|
||||
vec2( 0.344959, 0.293878),
|
||||
vec2( 0.443233, -0.475115),
|
||||
vec2( 0.537430, -0.473734),
|
||||
vec2( 0.589349, 0.569135),
|
||||
vec2( 0.674281, -0.178897),
|
||||
vec2( 0.791975, 0.190902),
|
||||
vec2( 0.815442, 0.879125),
|
||||
vec2( 0.896420, -0.613392),
|
||||
vec2( 0.945586, -0.768907),
|
||||
vec2( 0.974844, 0.756484),
|
||||
vec2(-0.814100, 0.914376),
|
||||
vec2(-0.382775, 0.276768),
|
||||
vec2(-0.915886, 0.457714),
|
||||
vec2( 0.537800, 0.912200),
|
||||
vec2(-0.620000, -0.650000),
|
||||
vec2( 0.120000, -0.780000)
|
||||
);
|
||||
|
||||
const vec2 poissonDisk16[16] = vec2[](
|
||||
vec2(-0.94201624, -0.39906216), vec2(0.94558609, -0.76890725),
|
||||
vec2(-0.09418410, -0.92938870), vec2(0.34495938, 0.29387760),
|
||||
vec2(-0.91588581, 0.45771432), vec2(-0.81544232, -0.87912464),
|
||||
vec2(-0.38277543, 0.27676845), vec2(0.97484398, 0.75648379),
|
||||
vec2(0.44323325, -0.97511554), vec2(0.53742981, -0.47373420),
|
||||
vec2(-0.26496911, -0.41893023), vec2(0.79197514, 0.19090188),
|
||||
vec2(-0.24188840, 0.99706507), vec2(-0.81409955, 0.91437590),
|
||||
vec2(0.19984126, 0.78641367), vec2(0.14383161, -0.14100790)
|
||||
);
|
||||
const vec2 poissonDisk8[8] = vec2[](
|
||||
vec2( 0.1440, 0.7659), vec2(-0.5761, 0.4479),
|
||||
vec2(-0.3220, -0.6058), vec2( 0.5693, -0.4048),
|
||||
vec2(-0.1276, 0.1657), vec2(-0.0649, -0.0165),
|
||||
vec2( 0.2773, -0.0305), vec2(-0.1134, -0.2122)
|
||||
);
|
||||
uniform int samples;
|
||||
float random(vec3 seed) {
|
||||
return fract(sin(dot(seed, vec3(12.9898,78.233,45.5432))) * 43758.5453);
|
||||
}
|
||||
|
||||
float FindBlocker(vec2 uv,
|
||||
float zReceiver,
|
||||
vec2 texelSize,
|
||||
float bias,
|
||||
float lightSizeUV)
|
||||
{
|
||||
float avgDepth = 0.0;
|
||||
int blockers = 0;
|
||||
|
||||
float searchRadius = lightSizeUV * 0.5;
|
||||
|
||||
for(int i = 0; i < samples; i++)
|
||||
{
|
||||
vec2 offset;
|
||||
if (samples == 32) {
|
||||
offset =
|
||||
poissonDisk32[i]
|
||||
* searchRadius
|
||||
* texelSize;
|
||||
} else if (samples == 16) {
|
||||
offset =
|
||||
poissonDisk16[i]
|
||||
* searchRadius
|
||||
* texelSize;
|
||||
} else if (samples == 8) {
|
||||
offset =
|
||||
poissonDisk8[i]
|
||||
* searchRadius
|
||||
* texelSize;
|
||||
} else {
|
||||
offset =
|
||||
poissonDisk32[i]
|
||||
* searchRadius
|
||||
* texelSize;
|
||||
}
|
||||
float depth =
|
||||
texture(shadowMap, uv + offset).r;
|
||||
|
||||
if(depth < zReceiver - bias)
|
||||
{
|
||||
avgDepth += depth;
|
||||
blockers++;
|
||||
}
|
||||
}
|
||||
|
||||
if(blockers == 0)
|
||||
return -1.0;
|
||||
|
||||
return avgDepth / blockers;
|
||||
}
|
||||
|
||||
float ShadowCalculation(vec4 fragPosLightSpace, vec3 norm, vec3 lightDir)
|
||||
{
|
||||
|
||||
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;
|
||||
vec2 texelSize = 1.0 / vec2(textureSize(shadowMap, 0));
|
||||
float shadow = 0.0;
|
||||
|
||||
float bias =
|
||||
clamp(
|
||||
0.001 * (1.0 - dot(norm, lightDir)),
|
||||
0.0003,
|
||||
0.003
|
||||
);
|
||||
|
||||
if (shadowMode == 0) {
|
||||
vec3 seed = vert_pos * 37.0 + sin(vert_pos * 91.7) * 13.0;
|
||||
float angle = random(seed) * 6.2831853;; // 2*PI
|
||||
float s = sin(angle), c = cos(angle);
|
||||
mat2 rot = mat2(c, -s, s, c);
|
||||
//float radius = 0.7;
|
||||
float radius = mix(1.0, 4.0, currentDepth);
|
||||
|
||||
for (int i = 0; i < samples; ++i) {
|
||||
vec2 offset;
|
||||
if (samples == 32) {
|
||||
offset = rot * poissonDisk32[i] * radius * texelSize;
|
||||
} else if (samples == 16) {
|
||||
offset = rot * poissonDisk16[i] * radius * texelSize;
|
||||
} else if (samples == 8) {
|
||||
offset = rot * poissonDisk8[i] * radius * texelSize;
|
||||
} else {
|
||||
offset = rot * poissonDisk32[i] * radius * texelSize;
|
||||
}
|
||||
float pcfDepth = texture(shadowMap, projCoords.xy + offset).r;
|
||||
shadow += (currentDepth - bias > pcfDepth ? 1.0 : 0.0);
|
||||
}
|
||||
shadow /= float(samples);
|
||||
} else if (shadowMode == 1) {
|
||||
for (int x = -1; x <= 1; ++x) {
|
||||
for (int y = -1; y <= 1; ++y) {
|
||||
vec2 offset = vec2(x, y) * texelSize;
|
||||
float pcfDepth = texture(shadowMap, projCoords.xy + offset).r;
|
||||
shadow += (currentDepth - bias > pcfDepth ? 1.0 : 0.0);
|
||||
}
|
||||
}
|
||||
shadow /= 9.0;
|
||||
} else if (shadowMode == 2) {
|
||||
// pcf off
|
||||
float pcfDepth =
|
||||
texture(shadowMap, projCoords.xy).r;
|
||||
|
||||
shadow =
|
||||
currentDepth - bias > pcfDepth
|
||||
? 1.0
|
||||
: 0.0;
|
||||
} else if (shadowMode == 3) {
|
||||
float avgBlockerDepth =
|
||||
FindBlocker(
|
||||
projCoords.xy,
|
||||
currentDepth,
|
||||
texelSize,
|
||||
bias,
|
||||
lightSizeUV
|
||||
);
|
||||
|
||||
if(avgBlockerDepth < 0.0)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
vec3 seed = vert_pos * 37.0 + sin(vert_pos * 91.7) * 13.0;
|
||||
float angle = random(seed) * 6.2831853;; // 2*PI
|
||||
float s = sin(angle), c = cos(angle);
|
||||
mat2 rot = mat2(c, -s, s, c);
|
||||
/*
|
||||
float penumbraRatio = (currentDepth - avgBlockerDepth);
|
||||
float radius = clamp(
|
||||
penumbraRatio * lightSizeUV,
|
||||
minRadius,
|
||||
maxRadius
|
||||
);
|
||||
*/
|
||||
float radius =
|
||||
mix(
|
||||
minRadius,
|
||||
maxRadius,
|
||||
smoothstep(
|
||||
0.0,
|
||||
0.05,
|
||||
currentDepth - avgBlockerDepth
|
||||
)
|
||||
);
|
||||
for (int i = 0; i < samples; ++i) {
|
||||
vec2 offset;
|
||||
if (samples == 32) {
|
||||
offset = rot * poissonDisk32[i] * radius * texelSize;
|
||||
} else if (samples == 16) {
|
||||
offset = rot * poissonDisk16[i] * radius * texelSize;
|
||||
} else if (samples == 8) {
|
||||
offset = rot * poissonDisk8[i] * radius * texelSize;
|
||||
} else {
|
||||
offset = rot * poissonDisk32[i] * radius * texelSize;
|
||||
}
|
||||
float pcfDepth = texture(shadowMap, projCoords.xy + offset).r;
|
||||
shadow += (currentDepth - bias > pcfDepth ? 1.0 : 0.0);
|
||||
}
|
||||
shadow /= float(samples);
|
||||
|
||||
} else {
|
||||
float pcfDepth =
|
||||
texture(shadowMap, projCoords.xy).r;
|
||||
|
||||
shadow =
|
||||
currentDepth - bias > pcfDepth
|
||||
? 1.0
|
||||
: 0.0;
|
||||
}
|
||||
|
||||
|
||||
return shadow;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,30 @@
|
||||
#version 460
|
||||
|
||||
in vec3 dir;
|
||||
|
||||
out vec4 frag_color;
|
||||
|
||||
|
||||
uniform vec3 skyTop;
|
||||
uniform vec3 skyBottom;
|
||||
|
||||
uniform vec3 sunDir;
|
||||
uniform vec3 sunColor;
|
||||
|
||||
uniform float horizonSharpness;
|
||||
uniform float cloudWhiteMix;
|
||||
|
||||
uniform float cloudThresholdLow;
|
||||
uniform float cloudThresholdHigh;
|
||||
|
||||
uniform float time;
|
||||
|
||||
#include "compute_sky_color.glsl"
|
||||
|
||||
void main(void) {
|
||||
|
||||
frag_color = vec4(0.529, 0.808, 0.922, 1.0);
|
||||
vec3 sky = computeSkyColor(dir);
|
||||
|
||||
frag_color = vec4(sky, 1.0);
|
||||
|
||||
}
|
||||
@@ -5,6 +5,12 @@ layout (location = 0) in vec3 vertices_pos;
|
||||
uniform mat4 mv_matrix;
|
||||
uniform mat4 proj_matrix;
|
||||
|
||||
out vec3 dir;
|
||||
|
||||
void main(void) {
|
||||
// Our skybox mesh uses [0,1] coordinates instead of the usual [-1,1].
|
||||
// Shift to the cube center before normalizing to obtain the correct
|
||||
// view direction for atmospheric calculations.
|
||||
dir = normalize(vertices_pos - vec3(0.5));
|
||||
gl_Position = proj_matrix * mv_matrix * vec4(vertices_pos, 1.0);
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
#version 460
|
||||
|
||||
in vec2 tc;
|
||||
flat in int tex_layer;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
layout (binding = 0) uniform sampler2DArray samp;
|
||||
|
||||
void main(void) {
|
||||
color = texture(samp, vec3(tc, tex_layer));
|
||||
}
|
||||
111
assets/shaders/under_water_f_shader.glsl
Normal file
@@ -0,0 +1,111 @@
|
||||
#version 460
|
||||
|
||||
in vec2 TexCoord;
|
||||
in vec3 rayDir;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
layout (binding = 0) uniform sampler2D u_sceneTexture;
|
||||
layout (binding = 1) uniform sampler2D u_depthTexture;
|
||||
layout (binding = 2) uniform sampler2D u_shadowMap;
|
||||
uniform mat4 u_lightSpaceMatrix;
|
||||
uniform float u_time;
|
||||
uniform bool u_underwater;
|
||||
uniform vec3 u_waterColor;
|
||||
uniform float u_fogDensity;
|
||||
uniform mat4 InverseViewProjection;
|
||||
uniform vec3 cameraPos;
|
||||
uniform vec3 sunDir;
|
||||
uniform vec3 sunColor;
|
||||
uniform float waterDensity;
|
||||
|
||||
#include "noise.glsl"
|
||||
|
||||
float getCausticValue(float x, float y, float z) {
|
||||
float w = 8.0;
|
||||
float strength = 4.0;
|
||||
vec2 coord = vec2(x, y) * w + z * 0.5;
|
||||
|
||||
float n = fbm(coord);
|
||||
|
||||
float caustic = pow(n, 3.0) * strength;
|
||||
return caustic;
|
||||
}
|
||||
|
||||
float getShadow(vec3 worldPos) {
|
||||
vec4 posLightSpace = u_lightSpaceMatrix * vec4(worldPos, 1.0);
|
||||
vec3 projCoords = posLightSpace.xyz / posLightSpace.w;
|
||||
projCoords = projCoords * 0.5 + 0.5;
|
||||
|
||||
if (projCoords.z > 1.0) return 1.0;
|
||||
|
||||
float closestDepth = texture(u_shadowMap, projCoords.xy).r;
|
||||
float currentDepth = projCoords.z;
|
||||
|
||||
return currentDepth - 0.005 > closestDepth ? 0.0 : 1.0;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 original = texture(u_sceneTexture, TexCoord);
|
||||
|
||||
if (!u_underwater) {
|
||||
FragColor = original;
|
||||
return;
|
||||
}
|
||||
|
||||
float rawDepth = texture(u_depthTexture, TexCoord).r;
|
||||
vec3 ndc = vec3(TexCoord * 2.0 - 1.0, rawDepth * 2.0 - 1.0);
|
||||
vec4 worldPosH = InverseViewProjection * vec4(ndc, 1.0);
|
||||
vec3 worldPos = worldPosH.xyz / worldPosH.w;
|
||||
float sceneDistance = distance(cameraPos, worldPos);
|
||||
|
||||
vec2 distoredUV = TexCoord;
|
||||
float strength = 0.003;
|
||||
distoredUV.x += sin(TexCoord.y * 15.0 + u_time * 5.0) * strength;
|
||||
distoredUV.y += cos(TexCoord.x * 15.0 + u_time * 4.3) * strength;
|
||||
distoredUV = clamp(distoredUV, 0.001, 0.999);
|
||||
vec4 distorted = texture(u_sceneTexture, distoredUV);
|
||||
|
||||
float rawCaustic = getCausticValue(TexCoord.x, TexCoord.y, u_time * 0.3);
|
||||
float caustic = 0.5 + rawCaustic * 0.5;
|
||||
vec3 causticLight = vec3(caustic * 0.9, caustic, caustic * 0.7);
|
||||
|
||||
float fogFactor = clamp(1.0 - (TexCoord.y * u_fogDensity * 10.0), 0.0, 1.0);
|
||||
vec3 mixed = mix(u_waterColor, distorted.rgb * causticLight, fogFactor);
|
||||
// Volume Scattering
|
||||
vec3 rayOrigin = cameraPos;
|
||||
vec3 rayDirection = normalize(rayDir);
|
||||
|
||||
float maxDist = 10.0; // Maximum visible distance
|
||||
float stepSize = 0.4;
|
||||
float phasePower = 8.0; // Beam Sharpness
|
||||
|
||||
vec3 scattering = vec3(0.0);
|
||||
float transmittance = 1.0;
|
||||
|
||||
float cosTheta = dot(rayDirection, sunDir);
|
||||
float phase = pow(max(cosTheta, 0.0), phasePower);
|
||||
|
||||
for (float t = 0.0; t < maxDist; t += stepSize) {
|
||||
|
||||
if (t > sceneDistance) break;
|
||||
vec3 pos = rayOrigin + rayDirection * t;
|
||||
|
||||
float shadow = getShadow(pos);
|
||||
|
||||
float density = waterDensity;
|
||||
|
||||
|
||||
vec3 absorption = vec3(0.3, 0.08, 0.02); // Absorption coefficient per meter
|
||||
vec3 sunLightAtPos = sunColor * exp(-absorption * t);
|
||||
|
||||
scattering += density * phase * sunLightAtPos * transmittance * stepSize * shadow;
|
||||
|
||||
float extinction = waterDensity * 1.5; // Extinction coefficient, tunable
|
||||
transmittance *= exp(-extinction * stepSize);
|
||||
if (transmittance < 0.01) break;
|
||||
}
|
||||
|
||||
FragColor.rgb = mixed + scattering;
|
||||
FragColor.a = 1.0;
|
||||
}
|
||||
20
assets/shaders/under_water_v_shader.glsl
Normal file
@@ -0,0 +1,20 @@
|
||||
#version 460
|
||||
|
||||
layout (location = 0) in vec2 pos;
|
||||
layout (location = 1) in vec2 texCoord;
|
||||
|
||||
uniform mat4 InverseViewProjection;
|
||||
uniform vec3 cameraPos;
|
||||
|
||||
out vec2 TexCoord;
|
||||
out vec3 rayDir;
|
||||
void main() {
|
||||
TexCoord = texCoord;
|
||||
vec4 clipPos = vec4(pos, 1.0, 1.0);
|
||||
vec4 worldPosH = InverseViewProjection * clipPos;
|
||||
vec3 worldPos = worldPosH.xyz / worldPosH.w;
|
||||
vec3 RayDir = worldPos - cameraPos;
|
||||
rayDir = normalize(RayDir);
|
||||
gl_Position = clipPos;
|
||||
|
||||
}
|
||||
248
assets/shaders/water_f_shader.glsl
Normal file
@@ -0,0 +1,248 @@
|
||||
#version 460
|
||||
|
||||
layout (location = 0) out vec4 accum;
|
||||
layout (location = 1) out float reveal;
|
||||
|
||||
in vec2 tc;
|
||||
in vec3 normal;
|
||||
in vec3 vert_pos;
|
||||
in vec3 world_pos;
|
||||
in float roughness;
|
||||
flat in int tex_layer;
|
||||
in float v_depth;
|
||||
layout (binding = 0) uniform sampler2DArray samp;
|
||||
uniform sampler2D sceneColorTex; // binding 1
|
||||
uniform sampler2D sceneDepthTex; // binding 2
|
||||
|
||||
uniform mat4 proj_matrix;
|
||||
uniform mat4 inv_proj_matrix;
|
||||
uniform mat4 inv_view_matrix;
|
||||
|
||||
uniform float ambientStrength;
|
||||
uniform vec3 sunlightColor;
|
||||
uniform vec3 ambientColor;
|
||||
uniform vec3 sunlightDir;
|
||||
uniform bool shader_on;
|
||||
uniform float specularStrength;
|
||||
|
||||
uniform vec3 skyTop;
|
||||
uniform vec3 skyBottom;
|
||||
uniform vec3 sunColor;
|
||||
uniform float horizonSharpness;
|
||||
uniform float cloudWhiteMix;
|
||||
uniform float cloudThresholdLow;
|
||||
uniform float cloudThresholdHigh;
|
||||
uniform float time;
|
||||
|
||||
uniform vec3 sunDir; // world!
|
||||
|
||||
uniform bool underwater;
|
||||
|
||||
uniform float refractStrength;
|
||||
|
||||
uniform bool enablePerturb;
|
||||
uniform bool enableDepthFade;
|
||||
|
||||
#include "compute_sky_color.glsl"
|
||||
|
||||
float weight(float z, float a) {
|
||||
float intermediate = 0.03 / (1e-5 + pow(z / 200.0, 4.0));
|
||||
|
||||
return a * clamp(intermediate, 1e-2, 3e2);
|
||||
}
|
||||
|
||||
|
||||
// Reconstruct eye-space coordinates from screen UV and depth buffer value
|
||||
vec3 reconstructViewPos(vec2 uv, float depth) {
|
||||
vec4 clip = vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
|
||||
vec4 view = inv_proj_matrix * clip;
|
||||
return view.xyz / view.w;
|
||||
}
|
||||
// Screen-space ray marching, origin/dir are in eye space
|
||||
bool traceSSR(vec3 origin, vec3 dir, out vec2 hitUV) {
|
||||
const int COARSE_STEPS = 32;
|
||||
const float COARSE_STEP = 0.6;
|
||||
const int REFINE_STEPS = 8;
|
||||
const float THICKNESS = 0.3;
|
||||
|
||||
vec3 pos = origin;
|
||||
vec3 prevPos = origin;
|
||||
bool foundCoarse = false;
|
||||
|
||||
|
||||
for (int i = 0; i < COARSE_STEPS; ++i) {
|
||||
prevPos = pos;
|
||||
pos += dir * COARSE_STEP;
|
||||
|
||||
vec4 clip = proj_matrix * vec4(pos, 1.0);
|
||||
if (clip.w <= 0.0) return false;
|
||||
vec3 ndc = clip.xyz / clip.w;
|
||||
if (abs(ndc.x) > 1.0 || abs(ndc.y) > 1.0) return false;
|
||||
|
||||
vec2 uv = ndc.xy * 0.5 + 0.5;
|
||||
float sceneDepth = texture(sceneDepthTex, uv).r;
|
||||
vec3 scenePos = reconstructViewPos(uv, sceneDepth);
|
||||
|
||||
if (pos.z - scenePos.z < 0.0) {
|
||||
foundCoarse = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundCoarse) return false;
|
||||
|
||||
|
||||
vec3 lo = prevPos;
|
||||
vec3 hi = pos;
|
||||
|
||||
for (int i = 0; i < REFINE_STEPS; ++i) {
|
||||
vec3 mid = (lo + hi) * 0.5;
|
||||
|
||||
vec4 clip = proj_matrix * vec4(mid, 1.0);
|
||||
vec3 ndc = clip.xyz / clip.w;
|
||||
vec2 uv = ndc.xy * 0.5 + 0.5;
|
||||
float sceneDepth = texture(sceneDepthTex, uv).r;
|
||||
vec3 scenePos = reconstructViewPos(uv, sceneDepth);
|
||||
|
||||
if (mid.z - scenePos.z < 0.0) {
|
||||
hi = mid;
|
||||
} else {
|
||||
lo = mid;
|
||||
}
|
||||
}
|
||||
|
||||
vec4 finalClip = proj_matrix * vec4(hi, 1.0);
|
||||
vec3 finalNdc = finalClip.xyz / finalClip.w;
|
||||
vec2 finalUV = finalNdc.xy * 0.5 + 0.5;
|
||||
|
||||
float finalDepth = texture(sceneDepthTex, finalUV).r;
|
||||
vec3 finalScenePos = reconstructViewPos(finalUV, finalDepth);
|
||||
|
||||
if (abs(hi.z - finalScenePos.z) > THICKNESS) return false;
|
||||
|
||||
hitUV = finalUV;
|
||||
return true;
|
||||
}
|
||||
void main() {
|
||||
|
||||
vec4 objectColor = texture(samp, vec3(tc, tex_layer));
|
||||
|
||||
if (!shader_on) {
|
||||
vec4 color = objectColor;
|
||||
float alpha = color.a;
|
||||
if (alpha < 1e-4) discard;
|
||||
|
||||
|
||||
float w = weight(v_depth, alpha);
|
||||
|
||||
accum = vec4(color.rgb * alpha * w, alpha * w);
|
||||
|
||||
reveal = alpha;
|
||||
return;
|
||||
}
|
||||
// Normal perturbation
|
||||
vec3 N;
|
||||
if (enablePerturb) {
|
||||
const float wave_speed_scale = 40.0;
|
||||
vec2 waveUV1 = world_pos.xz * 8.0 + vec2(time * 0.05 * wave_speed_scale, time * 0.03 * wave_speed_scale);
|
||||
vec2 waveUV2 = world_pos.xz * 13.0 + vec2(-time * 0.04 * wave_speed_scale, time * 0.06 * wave_speed_scale);
|
||||
|
||||
float wave1 = noise(waveUV1);
|
||||
float wave2 = noise(waveUV2);
|
||||
|
||||
vec2 normalPerturb = vec2(wave1 - 0.5, wave2 - 0.5) * 0.1;
|
||||
N = normalize(normal + vec3(normalPerturb.x, 0.0, normalPerturb.y));
|
||||
} else {
|
||||
N = normalize(normal);
|
||||
}
|
||||
|
||||
vec3 V = normalize(-vert_pos);
|
||||
|
||||
vec3 reflectColor;
|
||||
vec3 refractColor;
|
||||
float fresnel;
|
||||
|
||||
vec2 screenUV = gl_FragCoord.xy / vec2(textureSize(sceneDepthTex, 0));
|
||||
|
||||
// water depth
|
||||
float sceneDepthRaw = texture(sceneDepthTex, screenUV).r;
|
||||
vec3 sceneViewPos = reconstructViewPos(screenUV, sceneDepthRaw);
|
||||
float waterDepth = vert_pos.z - sceneViewPos.z;
|
||||
waterDepth = max(waterDepth, 0.0);
|
||||
|
||||
const float DEPTH_FADE_DISTANCE = 10;
|
||||
float depthFactor = clamp(waterDepth / DEPTH_FADE_DISTANCE, 0.0, 1.0);
|
||||
|
||||
if (underwater) {
|
||||
reflectColor = vec3(0.0);
|
||||
refractColor = objectColor.rgb;
|
||||
fresnel = 0.0;
|
||||
} else {
|
||||
vec3 R = reflect(-V, N);
|
||||
vec3 origin = vert_pos + N * 0.05;
|
||||
vec2 hitUV;
|
||||
|
||||
if (traceSSR(origin, R, hitUV)) {
|
||||
reflectColor = texture(sceneColorTex, hitUV).rgb;
|
||||
} else {
|
||||
vec3 worldR = mat3(inv_view_matrix) * R;
|
||||
reflectColor = computeSkyColor(worldR);
|
||||
}
|
||||
|
||||
float effectiveRefractStrength = refractStrength * (1.0 - depthFactor * 0.5);
|
||||
vec2 refractOffset = N.xz * effectiveRefractStrength;
|
||||
vec2 refractUV = clamp(screenUV + refractOffset, vec2(0.001), vec2(0.999));
|
||||
|
||||
refractColor = texture(sceneColorTex, refractUV).rgb;
|
||||
|
||||
fresnel = pow(1.0 - max(dot(N, V), 0.0), 5.0);
|
||||
fresnel = mix(0.02, 1.0, fresnel);
|
||||
}
|
||||
|
||||
vec3 lightDir = normalize(-sunlightDir);
|
||||
vec3 H = normalize(lightDir + V);
|
||||
vec3 ambient = ambientStrength * ambientColor;
|
||||
float diff = max(dot(N, lightDir), 0.0);
|
||||
vec3 diffuse = diff * sunlightColor;
|
||||
|
||||
float r = clamp(roughness, 0.0, 1.0);
|
||||
float shininess = mix(512.0, 4.0, r);
|
||||
float ks = mix(0.8, 0.02, r);
|
||||
|
||||
float spec = 0.0;
|
||||
if (diff > 0.0) {
|
||||
spec = ks * pow(max(dot(N, H), 0.0), shininess);
|
||||
}
|
||||
vec3 specular = spec * sunlightColor * specularStrength;
|
||||
|
||||
vec3 tintedRefract;
|
||||
|
||||
if (enableDepthFade) {
|
||||
vec3 shallowColor = vec3(0.4, 0.75, 0.7);
|
||||
vec3 deepColor = vec3(0.0, 0.015, 0.045);
|
||||
|
||||
vec3 waterTint = mix(shallowColor, deepColor, depthFactor);
|
||||
|
||||
tintedRefract = mix(refractColor, refractColor * waterTint, depthFactor);
|
||||
tintedRefract = mix(tintedRefract, objectColor.rgb, 0.4); // Forcefully blend 40% texture color, independent of depth
|
||||
} else {
|
||||
tintedRefract = mix(refractColor, objectColor.rgb, 0.4);
|
||||
}
|
||||
|
||||
//vec3 baseWaterColor = (ambient + diffuse) * objectColor.rgb + specular;
|
||||
vec3 baseWaterColor = (ambient + diffuse) * tintedRefract + specular;
|
||||
|
||||
vec3 finalColor = mix(baseWaterColor, reflectColor, fresnel);
|
||||
|
||||
float alpha = objectColor.a;
|
||||
if (alpha < 1e-4) discard;
|
||||
|
||||
|
||||
float w = weight(v_depth, alpha);
|
||||
|
||||
accum = vec4(finalColor * alpha * w, alpha * w);
|
||||
|
||||
reveal = alpha;
|
||||
|
||||
return;
|
||||
}
|
||||
32
assets/shaders/water_v_shader.glsl
Normal file
@@ -0,0 +1,32 @@
|
||||
#version 460
|
||||
|
||||
layout (location = 0) in vec3 pos;
|
||||
layout (location = 1) in vec2 texCoord;
|
||||
layout (location = 2) in float layer;
|
||||
layout (location = 3) in vec3 aNormal;
|
||||
layout (location = 4) in float Roughness;
|
||||
|
||||
out vec2 tc;
|
||||
out vec3 normal;
|
||||
out vec3 vert_pos;
|
||||
out vec3 world_pos;
|
||||
flat out int tex_layer;
|
||||
out float roughness;
|
||||
out float v_depth;
|
||||
|
||||
uniform mat4 mv_matrix;
|
||||
uniform mat4 proj_matrix;
|
||||
uniform mat4 norm_matrix;
|
||||
|
||||
|
||||
void main(void) {
|
||||
vec4 view_pos = mv_matrix * vec4(pos, 1.0);
|
||||
world_pos = pos;
|
||||
vert_pos = view_pos.xyz;
|
||||
normal = mat3(norm_matrix) * aNormal;
|
||||
roughness = Roughness;
|
||||
tc = texCoord;
|
||||
tex_layer = int(layer);
|
||||
v_depth = -view_pos.z;
|
||||
gl_Position = proj_matrix * view_pos;
|
||||
}
|
||||