Compare commits
17 Commits
36a0b14cf5
...
v0.0.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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
|
||||
154
.github/workflows/release-build.yml
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
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 }}
|
||||
|
||||
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: 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 }}
|
||||
5
.gitignore
vendored
@@ -40,4 +40,7 @@ CMakeError.log
|
||||
*.swo
|
||||
*~
|
||||
.DS_Store
|
||||
assets/config.toml
|
||||
assets/config.toml
|
||||
.venv/
|
||||
pyout/
|
||||
vcpkg_installed/
|
||||
1
.python-version
Normal file
@@ -0,0 +1 @@
|
||||
3.14
|
||||
255
CMakeLists.txt
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.14...3.24)
|
||||
cmake_minimum_required(VERSION 3.21)
|
||||
project(Cubed LANGUAGES C CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
@@ -6,150 +6,118 @@ 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
|
||||
)
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules"
|
||||
)
|
||||
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)
|
||||
|
||||
include(Dependencies)
|
||||
|
||||
add_subdirectory(third_party/glad)
|
||||
|
||||
add_subdirectory(third_party/imgui)
|
||||
|
||||
add_executable(${PROJECT_NAME})
|
||||
|
||||
set(INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include)
|
||||
add_subdirectory(src)
|
||||
|
||||
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
|
||||
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}")
|
||||
protobuf_generate(
|
||||
TARGET ${PROJECT_NAME}
|
||||
LANGUAGE cpp
|
||||
PROTOS ${PROTO_FILES}
|
||||
IMPORT_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src/proto
|
||||
)
|
||||
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE
|
||||
#-fsanitize=address
|
||||
#-fsanitize=thread
|
||||
-fno-omit-frame-pointer
|
||||
-g
|
||||
)
|
||||
configure_file(
|
||||
src/version.hpp.in
|
||||
${CMAKE_BINARY_DIR}/generated/version.hpp
|
||||
@ONLY
|
||||
)
|
||||
|
||||
target_link_options(${PROJECT_NAME} PRIVATE
|
||||
#-fsanitize=address
|
||||
#-fsanitize=thread
|
||||
)
|
||||
target_compile_options(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
$<$<CONFIG:Debug>:-fno-omit-frame-pointer>
|
||||
$<$<CONFIG:Debug>:-g>
|
||||
#$<$<CONFIG:Debug>:-fsanitize=address>
|
||||
#$<$<CONFIG:Debug>:-fsanitize=thread>
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE DEBUG_MODE)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE
|
||||
ASSETS_PATH="${CMAKE_SOURCE_DIR}/assets/"
|
||||
$<$<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
|
||||
ASSETS_PATH="./assets/"
|
||||
)
|
||||
# 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} PUBLIC ${INCLUDE_DIR})
|
||||
|
||||
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_link_libraries(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
@@ -161,26 +129,25 @@ target_link_libraries(${PROJECT_NAME}
|
||||
Freetype::Freetype
|
||||
tomlplusplus::tomlplusplus
|
||||
imgui
|
||||
tbb
|
||||
protobuf::libprotobuf
|
||||
absl::log
|
||||
absl::check
|
||||
absl::base
|
||||
absl::strings
|
||||
absl::flat_hash_map
|
||||
zstd::zstd
|
||||
$<$<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}
|
||||
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
|
||||
)
|
||||
|
||||
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
${EGL_INCLUDE_DIRS}
|
||||
${Wayland_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE ${EGL_CFLAGS_OTHER} ${Wayland_CFLAGS_OTHER})
|
||||
endif()
|
||||
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
|
||||
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);
|
||||
}
|
||||
12
assets/shaders/depth_shader.glsl
Normal file
@@ -0,0 +1,12 @@
|
||||
#version 460
|
||||
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;
|
||||
void main() {
|
||||
tc = texCoord;
|
||||
tex_layer = int(layer);
|
||||
gl_Position = lightSpaceMatrix * vec4(pos, 1.0);
|
||||
}
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 262 B After Width: | Height: | Size: 261 B |
|
Before Width: | Height: | Size: 262 B After Width: | Height: | Size: 261 B |
|
Before Width: | Height: | Size: 262 B After Width: | Height: | Size: 261 B |
|
Before Width: | Height: | Size: 262 B After Width: | Height: | Size: 261 B |
|
Before Width: | Height: | Size: 262 B After Width: | Height: | Size: 261 B |
|
Before Width: | Height: | Size: 262 B After Width: | Height: | Size: 261 B |
BIN
assets/texture/item/block/grass.png
Normal file
|
After Width: | Height: | Size: 277 B |
BIN
assets/texture/skin/player001.png
Normal file
|
After Width: | Height: | Size: 535 B |
79
cmake/Dependencies.cmake
Normal file
@@ -0,0 +1,79 @@
|
||||
include(FetchContent)
|
||||
|
||||
# System packages
|
||||
find_package(OpenGL REQUIRED)
|
||||
find_package(Protobuf REQUIRED)
|
||||
find_package(absl REQUIRED)
|
||||
find_package(zstd REQUIRED)
|
||||
if (UNIX AND NOT APPLE)
|
||||
find_package(Freetype REQUIRED)
|
||||
find_package(glfw3 REQUIRED)
|
||||
endif()
|
||||
|
||||
|
||||
# Third-party libraries
|
||||
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)
|
||||
|
||||
|
||||
if (WIN32)
|
||||
FetchContent_Declare(
|
||||
glfw
|
||||
GIT_REPOSITORY https://github.com/glfw/glfw.git
|
||||
GIT_TAG 3.4
|
||||
)
|
||||
|
||||
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(BUILD_SHARED_LIBS ON CACHE BOOL "" FORCE)
|
||||
|
||||
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()
|
||||
set(_BUILD_SHARED_LIBS_SAVED ${BUILD_SHARED_LIBS})
|
||||
set(BUILD_SHARED_LIBS ON)
|
||||
|
||||
FetchContent_Declare(
|
||||
onetbb
|
||||
GIT_REPOSITORY https://github.com/uxlfoundation/oneTBB.git
|
||||
GIT_TAG v2023.0.0
|
||||
)
|
||||
|
||||
set(BUILD_TESTING OFF CACHE BOOL "Build tests" FORCE)
|
||||
set(TBB_TEST OFF CACHE BOOL "Build TBB tests" FORCE)
|
||||
FetchContent_MakeAvailable(onetbb)
|
||||
|
||||
set(BUILD_SHARED_LIBS ${_BUILD_SHARED_LIBS_SAVED})
|
||||
unset(_BUILD_SHARED_LIBS_SAVED)
|
||||
|
||||
endif()
|
||||
|
||||
22
cmake/modules/Findzstd.cmake
Normal file
@@ -0,0 +1,22 @@
|
||||
find_path(ZSTD_INCLUDE_DIRS
|
||||
NAMES zstd.h
|
||||
HINTS ${zstd_ROOT_DIR}/include)
|
||||
|
||||
find_library(ZSTD_LIBRARIES
|
||||
NAMES zstd
|
||||
HINTS ${zstd_ROOT_DIR}/lib)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(zstd DEFAULT_MSG ZSTD_LIBRARIES ZSTD_INCLUDE_DIRS)
|
||||
|
||||
mark_as_advanced(
|
||||
ZSTD_LIBRARIES
|
||||
ZSTD_INCLUDE_DIRS)
|
||||
|
||||
if(ZSTD_FOUND AND NOT (TARGET zstd::zstd))
|
||||
add_library (zstd::zstd UNKNOWN IMPORTED)
|
||||
set_target_properties(zstd::zstd
|
||||
PROPERTIES
|
||||
IMPORTED_LOCATION ${ZSTD_LIBRARIES}
|
||||
INTERFACE_INCLUDE_DIRECTORIES ${ZSTD_INCLUDE_DIRS})
|
||||
endif()
|
||||
@@ -1,8 +1,10 @@
|
||||
#pragma once
|
||||
#include "Cubed/gameplay/client_world.hpp"
|
||||
#include "Cubed/gameplay/network_server.hpp"
|
||||
#include "Cubed/gameplay/server_world.hpp"
|
||||
#define GLFW_INCLUDE_NONE
|
||||
#include "Cubed/camera.hpp"
|
||||
#include "Cubed/dev_panel.hpp"
|
||||
#include "Cubed/gameplay/world.hpp"
|
||||
#include "Cubed/renderer.hpp"
|
||||
#include "Cubed/texture_manager.hpp"
|
||||
#include "Cubed/window.hpp"
|
||||
@@ -10,6 +12,13 @@ namespace Cubed {
|
||||
|
||||
class App {
|
||||
public:
|
||||
struct Argument {
|
||||
bool is_client = false;
|
||||
int port = 25530;
|
||||
std::string ip{"127.0.0.1"};
|
||||
std::string player{"Unknown"};
|
||||
};
|
||||
|
||||
App();
|
||||
~App();
|
||||
static void cursor_position_callback(GLFWwindow* window, double xpos,
|
||||
@@ -36,14 +45,20 @@ public:
|
||||
Renderer& renderer();
|
||||
TextureManager& texture_manager();
|
||||
Window& window();
|
||||
World& world();
|
||||
ClientWorld& client_world();
|
||||
ServerWorld& server_world();
|
||||
const Argument& argument() const;
|
||||
|
||||
private:
|
||||
Camera m_camera;
|
||||
TextureManager m_texture_manager;
|
||||
World m_world;
|
||||
NetworkServer m_server;
|
||||
std::shared_ptr<NetworkClient> m_client;
|
||||
ClientWorld m_client_world;
|
||||
|
||||
DevPanel m_dev_panel{*this};
|
||||
Renderer m_renderer{m_camera, m_world, m_texture_manager, m_dev_panel};
|
||||
Renderer m_renderer{m_camera, m_client_world, m_texture_manager,
|
||||
m_dev_panel};
|
||||
|
||||
Window m_window{m_renderer};
|
||||
|
||||
@@ -53,9 +68,10 @@ private:
|
||||
inline static double fps_time_count = 0.0f;
|
||||
inline static int frame_count = 0;
|
||||
inline static int fps = 0;
|
||||
|
||||
void init();
|
||||
|
||||
Argument m_argument;
|
||||
void init(int argc, char** argv);
|
||||
void handle_argument(int argc, char** argv);
|
||||
void handle_toml();
|
||||
auto init_camera();
|
||||
auto init_texture();
|
||||
auto init_world();
|
||||
|
||||
@@ -8,27 +8,43 @@
|
||||
|
||||
namespace Cubed {
|
||||
|
||||
class Player;
|
||||
class ClientPlayer;
|
||||
|
||||
class Camera {
|
||||
private:
|
||||
enum class Perspective {
|
||||
FIRST_PERSON,
|
||||
THIRD_PERSON_BACK,
|
||||
THIRD_PERSON_FRONT,
|
||||
};
|
||||
|
||||
bool m_firse_mouse = true;
|
||||
Player* m_player;
|
||||
ClientPlayer* m_player;
|
||||
float m_last_mouse_x, m_last_mouse_y;
|
||||
glm::vec3 m_camera_pos;
|
||||
bool m_under_water = false;
|
||||
Perspective m_perspective = Perspective::FIRST_PERSON;
|
||||
glm::vec3 m_front;
|
||||
glm::vec3 camera_collision(glm::vec3 start, glm::vec3 end,
|
||||
float radius = 0.2f);
|
||||
|
||||
public:
|
||||
Camera();
|
||||
|
||||
void update_move_camera();
|
||||
|
||||
void camera_init(Player* player);
|
||||
void camera_init(ClientPlayer* player);
|
||||
void hot_reload();
|
||||
void reset_camera();
|
||||
void update_cursor_position_camera(double xpos, double ypos);
|
||||
|
||||
const glm::mat4 get_camera_lookat() const;
|
||||
const glm::vec3& get_camera_pos() const;
|
||||
|
||||
bool is_under_water() const;
|
||||
glm::vec3 get_camera_front() const;
|
||||
void change_perspective();
|
||||
bool is_first_person() const;
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
|
||||
@@ -1,17 +1,9 @@
|
||||
#pragma once
|
||||
#include "Cubed/tools/cubed_assert.hpp"
|
||||
|
||||
#include <toml++/toml.hpp>
|
||||
#include "Cubed/tools/toml.utils.hpp"
|
||||
|
||||
namespace Cubed {
|
||||
|
||||
template <typename T>
|
||||
concept TomlValueType =
|
||||
std::same_as<T, int> || std::same_as<T, bool> || std::same_as<T, double> ||
|
||||
std::same_as<T, const char*> || std::same_as<T, toml::date> ||
|
||||
std::same_as<T, toml::time> || std::same_as<T, toml::date_time> ||
|
||||
std::same_as<T, std::string>;
|
||||
|
||||
class Config {
|
||||
public:
|
||||
Config();
|
||||
@@ -24,7 +16,7 @@ public:
|
||||
void load_or_create_config();
|
||||
void save_to_file();
|
||||
|
||||
template <TomlValueType T> T get(std::string_view key) const {
|
||||
template <TOML::TomlValueType T> T get(std::string_view key) const {
|
||||
size_t cur = 0;
|
||||
auto pos = key.find('.');
|
||||
const toml::table* table = &m_tbl;
|
||||
@@ -61,7 +53,7 @@ public:
|
||||
}
|
||||
}
|
||||
template <typename T> void set(std::string_view key, T&& val) {
|
||||
if constexpr (!TomlValueType<std::decay_t<T>>) {
|
||||
if constexpr (!TOML::TomlValueType<std::decay_t<T>>) {
|
||||
static_assert(false, "Type Not Support");
|
||||
}
|
||||
size_t cur = 0;
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
#pragma once
|
||||
#include "Cubed/gameplay/chunk_pos.hpp"
|
||||
|
||||
#include <array>
|
||||
namespace Cubed {
|
||||
|
||||
constexpr int WORLD_SIZE_Y = 256;
|
||||
constexpr int CHUNK_SIZE = 16;
|
||||
constexpr int SEA_LEVEL = 64;
|
||||
constexpr int SEA_LEVEL = 63;
|
||||
|
||||
constexpr int MAX_BLOCK_NUM = 9;
|
||||
constexpr int MAX_UI_NUM = 1;
|
||||
constexpr int MAX_BLOCK_STATUS = 1;
|
||||
constexpr int MAX_BIOME_SUM = 4;
|
||||
@@ -17,19 +15,19 @@ constexpr int MAX_CHARACTER = 128;
|
||||
constexpr int PRE_LOAD_DISTANCE = 24;
|
||||
|
||||
constexpr int MAX_DISTANCE = 128;
|
||||
|
||||
constexpr int CROSS_PLANE_DISTANCE = 8;
|
||||
constexpr float DEFAULT_FOV = 70.0f;
|
||||
constexpr float DEFAULT_MAX_WALK_SPEED = 4.5f;
|
||||
constexpr float DEFAULT_MAX_RUN_SPEED = 7.0f;
|
||||
constexpr float DEFAULT_ACCELERATION = 10.0f;
|
||||
constexpr float DEFAULT_DECELERATION = 15.0f;
|
||||
constexpr float DEFAULT_G = 22.5f;
|
||||
static constexpr int SIZE_X = CHUNK_SIZE;
|
||||
static constexpr int SIZE_Y = WORLD_SIZE_Y;
|
||||
static constexpr int SIZE_Z = CHUNK_SIZE;
|
||||
constexpr int SIZE_X = CHUNK_SIZE;
|
||||
constexpr int SIZE_Y = WORLD_SIZE_Y;
|
||||
constexpr int SIZE_Z = CHUNK_SIZE;
|
||||
constexpr int RESERVED_THREADS = 5;
|
||||
|
||||
constexpr ChunkPos CHUNK_DIR[]{{1, 0}, {-1, 0}, {0, 1}, {0, -1},
|
||||
{1, 1}, {-1, 1}, {1, -1}, {-1, -1}};
|
||||
constexpr float DEFAULT_CAVE_PROBABILITY = 0.035f;
|
||||
|
||||
using HeightMapArray = std::array<std::array<int, CHUNK_SIZE>, CHUNK_SIZE>;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
namespace Cubed {
|
||||
|
||||
class App;
|
||||
class Player;
|
||||
class ClientPlayer;
|
||||
class DevPanel {
|
||||
struct ConfigView {
|
||||
float fov = 70.0f;
|
||||
@@ -26,9 +26,6 @@ class DevPanel {
|
||||
int gait = 0;
|
||||
float pos[3] = {0.0f, 0.0f, 0.0f};
|
||||
};
|
||||
struct TextEditing {
|
||||
bool perlin_seed = false;
|
||||
};
|
||||
|
||||
public:
|
||||
DevPanel(App& app);
|
||||
@@ -38,20 +35,30 @@ public:
|
||||
private:
|
||||
App& m_app;
|
||||
ConfigView m_config;
|
||||
Player* m_player;
|
||||
ClientPlayer* m_player;
|
||||
PlayerProfile m_player_profile;
|
||||
TextEditing m_text_editing;
|
||||
bool m_need_save_config = false;
|
||||
bool m_gen_thread_running = true;
|
||||
int m_theme = 0;
|
||||
int m_pre_set_day_tick = 0;
|
||||
int m_pre_set_tick_speed = 1;
|
||||
bool m_tick_frezze = false;
|
||||
int m_samples_idx = 1;
|
||||
int m_threads = 1;
|
||||
int m_chunk_style = 0;
|
||||
void show_about_table_bar();
|
||||
void show_biome_table_bar();
|
||||
void show_time_table_bar();
|
||||
void show_cave_table_bar();
|
||||
void show_river_table_bar();
|
||||
void show_chunk_table_bar();
|
||||
void show_settings_tab_item();
|
||||
void show_world_tab_item();
|
||||
void show_server_world_table_bar();
|
||||
void show_client_world_table_bar();
|
||||
void show_player_tab_item();
|
||||
void show_items_tab_item();
|
||||
void show_shader_tab_item();
|
||||
|
||||
void update_config_view();
|
||||
void update_player_profile();
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#pragma once
|
||||
#include "Cubed/tools/cubed_assert.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace Cubed {
|
||||
@@ -15,6 +18,7 @@ enum class BiomeType {
|
||||
MOUNTAIN,
|
||||
RIVER,
|
||||
SNOWY_PLAIN,
|
||||
OCEAN,
|
||||
NONE
|
||||
};
|
||||
|
||||
@@ -76,4 +80,32 @@ DesertParams& desert_params();
|
||||
MountainParams& mountain_params();
|
||||
RiverParams& river_params();
|
||||
|
||||
inline BiomeType get_biome_from_id(int id) {
|
||||
using enum BiomeType;
|
||||
auto to = std::to_underlying<BiomeType>;
|
||||
if (id == to(PLAIN)) {
|
||||
return PLAIN;
|
||||
}
|
||||
if (id == to(FOREST)) {
|
||||
return FOREST;
|
||||
}
|
||||
if (id == to(DESERT)) {
|
||||
return DESERT;
|
||||
}
|
||||
if (id == to(MOUNTAIN)) {
|
||||
return MOUNTAIN;
|
||||
}
|
||||
if (id == to(RIVER)) {
|
||||
return RIVER;
|
||||
}
|
||||
if (id == to(SNOWY_PLAIN)) {
|
||||
return SNOWY_PLAIN;
|
||||
}
|
||||
if (id == to(OCEAN)) {
|
||||
return OCEAN;
|
||||
}
|
||||
ASSERT_MSG(false, "Unknown Biome Id");
|
||||
throw std::invalid_argument("Unknown Biome Id");
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
#pragma once
|
||||
#include "Cubed/constants.hpp"
|
||||
#include "Cubed/tools/cubed_assert.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <glad/glad.h>
|
||||
#include <glm/glm.hpp>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Cubed {
|
||||
|
||||
using BlockType = uint8_t;
|
||||
using OptionalBlockVectorArray =
|
||||
std::array<std::optional<std::vector<BlockType>>, 4>;
|
||||
|
||||
struct BlockTexture {
|
||||
std::string name;
|
||||
@@ -40,16 +40,57 @@ struct LookBlock {
|
||||
glm::ivec3 normal;
|
||||
};
|
||||
|
||||
constexpr std::array<std::string_view, MAX_BLOCK_NUM> BLOCK_REISTER{
|
||||
"air", "grass_block", "dirt", "stone", "sand", "log", "leaf",
|
||||
"water", "snowy_grass_block"};
|
||||
struct BlockData {
|
||||
std::string name;
|
||||
BlockType id = 0;
|
||||
|
||||
const std::array<bool, MAX_BLOCK_NUM> TRANSPARENT_MAP{
|
||||
true, false, false, false, false, false, true, false, false};
|
||||
bool is_liquid = false;
|
||||
bool is_gas = false;
|
||||
|
||||
inline bool is_in_transparent_map(unsigned id) {
|
||||
ASSERT_MSG(id < MAX_BLOCK_NUM, "ID is invaild");
|
||||
return TRANSPARENT_MAP[id];
|
||||
bool is_passable = false;
|
||||
bool is_cross_plane = false;
|
||||
bool is_transparent = false;
|
||||
|
||||
bool is_discard = false;
|
||||
bool is_blend = false;
|
||||
bool is_transitional = false;
|
||||
float roughness = 1.0f;
|
||||
BlockData(BlockType b_id, std::string_view b_name, bool liquid,
|
||||
bool passable, bool cross_plane, bool transparent, bool gas,
|
||||
bool discard, bool blend, bool transitional, float r)
|
||||
: name(b_name), id(b_id), is_liquid(liquid), is_gas(gas),
|
||||
is_passable(passable), is_cross_plane(cross_plane),
|
||||
is_transparent(transparent), is_discard(discard), is_blend(blend),
|
||||
is_transitional(transitional), roughness(r) {}
|
||||
};
|
||||
|
||||
class BlockManager {
|
||||
|
||||
public:
|
||||
static const std::vector<BlockData>& datas();
|
||||
static void init();
|
||||
static unsigned sums();
|
||||
static unsigned cross_plane_sum();
|
||||
static const std::string& name_form_id(BlockType id);
|
||||
|
||||
static bool is_gas(BlockType id);
|
||||
static bool is_liquid(BlockType id);
|
||||
|
||||
static bool is_cross_plane(BlockType id);
|
||||
static bool is_transparent(BlockType id);
|
||||
static bool is_passable(BlockType id);
|
||||
|
||||
static bool is_discard(BlockType id);
|
||||
static bool is_blend(BlockType id);
|
||||
static bool is_transitional(BlockType id);
|
||||
static float roughness(BlockType id);
|
||||
static BlockType cross_plane_index(BlockType id);
|
||||
|
||||
private:
|
||||
static void set_up_cross_plane_map();
|
||||
static inline std::vector<BlockData> m_datas;
|
||||
static inline bool is_init = false;
|
||||
static inline std::unordered_map<BlockType, BlockType> m_cross_plane_map;
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -9,8 +9,10 @@ public:
|
||||
virtual ChunkGenerator& get_chunk_generator() = 0;
|
||||
virtual void build_biome() = 0;
|
||||
virtual void build_vegetation() = 0;
|
||||
void ocean_water_build();
|
||||
|
||||
protected:
|
||||
void build_bottom();
|
||||
void place_grass();
|
||||
};
|
||||
} // namespace Cubed
|
||||
23
include/Cubed/gameplay/builders/ocean_builder.hpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/gameplay/builders/biome_builder.hpp"
|
||||
namespace Cubed {
|
||||
|
||||
class ChunkGenerator;
|
||||
|
||||
class OceanBuilder : public BiomeBuilder {
|
||||
public:
|
||||
OceanBuilder(ChunkGenerator& chunk_generator);
|
||||
void build_biome() override;
|
||||
ChunkGenerator& get_chunk_generator() override;
|
||||
void build_vegetation() override;
|
||||
|
||||
private:
|
||||
ChunkGenerator& m_chunk_generator;
|
||||
|
||||
void build_blocks();
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -1,24 +1,26 @@
|
||||
#pragma once
|
||||
#include "Cubed/gameplay/cave_path.hpp"
|
||||
#include "Cubed/constants.hpp"
|
||||
#include "Cubed/gameplay/chunk_pos.hpp"
|
||||
#include "Cubed/gameplay/path.hpp"
|
||||
|
||||
#include <tbb/concurrent_hash_map.h>
|
||||
|
||||
namespace Cubed {
|
||||
class CaveCarver {
|
||||
|
||||
public:
|
||||
CaveCarver();
|
||||
std::unordered_map<unsigned, CavePath>& paths();
|
||||
|
||||
void init(unsigned world_seed);
|
||||
void reload(unsigned world_seed);
|
||||
void add_path(const glm::vec3& pos, unsigned chunk_seed);
|
||||
void try_to_add_path(const ChunkPos& pos, unsigned chunk_seed);
|
||||
void cleanup_finished_caves();
|
||||
|
||||
int cave_sum() const;
|
||||
float& cave_probability();
|
||||
bool has_origin_fast(const ChunkPos& pos) const;
|
||||
float cave_probability() const;
|
||||
PathOrigin get_origin(const ChunkPos& origin_chunk) const;
|
||||
int search_radius() const;
|
||||
unsigned world_seed() const;
|
||||
|
||||
private:
|
||||
std::unordered_map<unsigned, CavePath> m_paths;
|
||||
unsigned m_seed = 0;
|
||||
int m_sum = 0;
|
||||
Random m_random;
|
||||
float m_cave_probability = 0.035f;
|
||||
std::atomic<unsigned> m_world_seed{0};
|
||||
std::atomic<float> m_cave_probability{DEFAULT_CAVE_PROBABILITY};
|
||||
};
|
||||
} // namespace Cubed
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/gameplay/chunk_pos.hpp"
|
||||
#include "Cubed/gameplay/path_point.hpp"
|
||||
#include "Cubed/tools/cubed_random.hpp"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <unordered_set>
|
||||
#include <tbb/concurrent_hash_map.h>
|
||||
namespace Cubed {
|
||||
|
||||
class CavePath {
|
||||
|
||||
public:
|
||||
CavePath(unsigned int world_seed, int path_id, const glm::vec3& start_pos);
|
||||
CavePath(unsigned int chunk_seed, unsigned world_seed,
|
||||
const glm::vec3& start_pos);
|
||||
const std::vector<PathPoint>& points() const;
|
||||
void clear_chunk(const ChunkPos& pos);
|
||||
bool is_finished() const;
|
||||
|
||||
static float& radius_xz_min();
|
||||
static float& radius_xz_max();
|
||||
@@ -23,6 +22,7 @@ public:
|
||||
static float& delta_angle_max();
|
||||
static int& step_min();
|
||||
static int& step_max();
|
||||
static int step_len();
|
||||
|
||||
private:
|
||||
static inline float m_radius_xz_min = 5.0f;
|
||||
@@ -33,19 +33,16 @@ private:
|
||||
static inline float m_delta_angle_max = 5.0f;
|
||||
static inline int m_step_min = 10;
|
||||
static inline int m_step_max = 400;
|
||||
|
||||
int m_path_id = 0;
|
||||
static inline float m_step_len = 4.0f;
|
||||
unsigned int m_seed = 0;
|
||||
float m_yaw = 0.0f;
|
||||
float m_pitch = 0.0f;
|
||||
int m_step = 0;
|
||||
float m_step_len = 1.0f;
|
||||
|
||||
PathPoint m_start_path_point{{0.0f, 0.0f, 0.0f}, 0.0f, 0.0f};
|
||||
Random m_random;
|
||||
|
||||
std::vector<PathPoint> m_points;
|
||||
std::unordered_set<ChunkPos, ChunkPos::Hash> m_pending_chunks;
|
||||
void collect_path_points();
|
||||
void precompute_chunk_coverage();
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -11,11 +11,11 @@
|
||||
#include <optional>
|
||||
namespace Cubed {
|
||||
|
||||
class Chunk;
|
||||
class ServerChunk;
|
||||
|
||||
class ChunkGenerator {
|
||||
public:
|
||||
ChunkGenerator(Chunk& chunk);
|
||||
ChunkGenerator(ServerChunk& chunk);
|
||||
|
||||
static void init();
|
||||
static void reload();
|
||||
@@ -26,7 +26,7 @@ public:
|
||||
void assign_chunk_biome();
|
||||
// Adjust Biome
|
||||
void resolve_biome_adjacency_conflict(
|
||||
const std::array<const Chunk*, 8>& adj_chunks);
|
||||
const std::array<const ServerChunk*, 8>& adj_chunks);
|
||||
// Generate Heightmap
|
||||
void generate_heightmap();
|
||||
// Adjust Height
|
||||
@@ -42,9 +42,10 @@ public:
|
||||
// Generate Structure
|
||||
void generate_vegetation();
|
||||
BiomeType get_biome_at(float world_x, float world_z);
|
||||
Chunk& chunk();
|
||||
ServerChunk& chunk();
|
||||
Random& random();
|
||||
const std::array<BiomeType, 8>& neighbor_biome() const;
|
||||
void ocean_build();
|
||||
void generate_cave();
|
||||
void generate_river();
|
||||
|
||||
@@ -52,7 +53,7 @@ private:
|
||||
static inline std::atomic<bool> is_init{false};
|
||||
static inline unsigned m_generator_seed{0};
|
||||
static inline std::atomic<bool> is_seed_change{false};
|
||||
Chunk& m_chunk;
|
||||
ServerChunk& m_chunk;
|
||||
Random m_random;
|
||||
std::unique_ptr<BiomeBuilder> m_biome_builder{nullptr};
|
||||
bool is_cur_chunk_ins = false;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/constants.hpp"
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace Cubed {
|
||||
@@ -16,7 +18,14 @@ struct ChunkPos {
|
||||
return h1 ^ (h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2));
|
||||
}
|
||||
};
|
||||
|
||||
struct TBBHash {
|
||||
std::size_t hash(const ChunkPos& p) const {
|
||||
return ChunkPos::Hash{}(p);
|
||||
}
|
||||
bool equal(const ChunkPos& a, const ChunkPos& b) const {
|
||||
return a == b;
|
||||
}
|
||||
};
|
||||
ChunkPos operator+(const ChunkPos& pos) const {
|
||||
return ChunkPos{x + pos.x, z + pos.z};
|
||||
}
|
||||
@@ -27,5 +36,29 @@ struct ChunkPos {
|
||||
return *this;
|
||||
};
|
||||
};
|
||||
constexpr ChunkPos CHUNK_DIR[]{{1, 0}, {-1, 0}, {0, 1}, {0, -1},
|
||||
{1, 1}, {-1, 1}, {1, -1}, {-1, -1}};
|
||||
inline ChunkPos get_chunk_pos(int world_x, int world_z) {
|
||||
int chunk_x, chunk_z;
|
||||
if (world_x < 0) {
|
||||
chunk_x = (world_x + 1) / CHUNK_SIZE - 1;
|
||||
}
|
||||
if (world_x >= 0) {
|
||||
chunk_x = world_x / CHUNK_SIZE;
|
||||
}
|
||||
if (world_z < 0) {
|
||||
chunk_z = (world_z + 1) / CHUNK_SIZE - 1;
|
||||
}
|
||||
if (world_z >= 0) {
|
||||
chunk_z = world_z / CHUNK_SIZE;
|
||||
}
|
||||
return {chunk_x, chunk_z};
|
||||
}
|
||||
|
||||
inline float distance2(const ChunkPos& a, const ChunkPos& b) {
|
||||
float dx = static_cast<float>(a.x) - b.x;
|
||||
float dz = static_cast<float>(a.z) - b.z;
|
||||
return dx * dx + dz * dz;
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
133
include/Cubed/gameplay/client_chunk.hpp
Normal file
@@ -0,0 +1,133 @@
|
||||
#pragma once
|
||||
#include "Cubed/constants.hpp"
|
||||
#include "Cubed/gameplay/biome.hpp"
|
||||
#include "Cubed/gameplay/block.hpp"
|
||||
#include "Cubed/gameplay/chunk_pos.hpp"
|
||||
#include "Cubed/gameplay/vertex_data.hpp"
|
||||
#include "world/chunk_data.pb.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <glad/glad.h>
|
||||
#include <glm/glm.hpp>
|
||||
#include <mutex>
|
||||
namespace Cubed {
|
||||
class ClientWorld;
|
||||
struct ChunkRenderSnapshot {
|
||||
GLuint normal_vao;
|
||||
size_t normal_vertices_count;
|
||||
GLuint cross_vao;
|
||||
size_t cross_vertices_count;
|
||||
GLuint normal_discard_vao;
|
||||
size_t normal_discard_vertices_count;
|
||||
GLuint normal_blend_vao;
|
||||
size_t normal_blend_vertices_count;
|
||||
GLuint water_vao;
|
||||
size_t water_vertices_count;
|
||||
glm::vec3 center;
|
||||
glm::vec3 half_extents;
|
||||
};
|
||||
class ClientChunk {
|
||||
public:
|
||||
ClientChunk(ClientWorld& world);
|
||||
~ClientChunk();
|
||||
ClientChunk(const ClientChunk&) = delete;
|
||||
ClientChunk& operator=(const ClientChunk&) = delete;
|
||||
ClientChunk(ClientChunk&&) noexcept;
|
||||
ClientChunk& operator=(ClientChunk&&) noexcept;
|
||||
|
||||
static int index(int x, int y, int z);
|
||||
static int index(const glm::vec3& pos);
|
||||
static std::tuple<int, int, int> world_to_block(int world_x, int world_y,
|
||||
int world_z, int chunk_x,
|
||||
int chunk_z);
|
||||
static std::tuple<int, int, int> world_to_block(const glm::ivec3& block_pos,
|
||||
ChunkPos chunk_pos);
|
||||
static std::tuple<int, int, int> block_to_world(int x, int y, int z,
|
||||
int chunk_x, int chunk_z);
|
||||
static std::tuple<int, int, int> block_to_world(const glm::ivec3& block_pos,
|
||||
ChunkPos chunk_pos);
|
||||
BiomeType get_biome() const;
|
||||
ChunkPos get_chunk_pos() const;
|
||||
const std::vector<BlockType>& get_chunk_blocks() const;
|
||||
void receive_chunk(const ChunkDataRsp& data);
|
||||
void gen_vertex_data(const OptionalBlockVectorArray& neighbor_block);
|
||||
// Can only be called on the render thread
|
||||
void upload_to_gpu();
|
||||
|
||||
GLuint get_normal_vao() const;
|
||||
size_t get_normal_vertices_sum() const;
|
||||
|
||||
GLuint get_cross_vao() const;
|
||||
size_t get_cross_vertices_sum() const;
|
||||
|
||||
GLuint get_normal_discard_vao() const;
|
||||
size_t get_normal_discard_vertices_sum() const;
|
||||
|
||||
GLuint get_normal_blend_vao() const;
|
||||
size_t get_normal_blend_vertices_sum() const;
|
||||
|
||||
GLuint get_water_vao() const;
|
||||
size_t get_water_vertices_sum() const;
|
||||
|
||||
bool is_dirty() const;
|
||||
void mark_dirty();
|
||||
|
||||
bool is_need_upload() const;
|
||||
void need_upload();
|
||||
|
||||
void set_chunk_block(int index, unsigned id);
|
||||
bool is_temp_chunk() const;
|
||||
ChunkPos chunk_pos() const;
|
||||
BiomeType biome() const;
|
||||
void biome(BiomeType b);
|
||||
std::vector<BlockType>& blocks();
|
||||
ClientWorld& world();
|
||||
unsigned seed() const;
|
||||
const ChunkRenderSnapshot* get_render_snapshot() const;
|
||||
|
||||
private:
|
||||
struct FaceKey {
|
||||
BlockType block_id = 0;
|
||||
int face = -1; // 0-5, used to index NORMALS/TANGENTS/TEX_COORDS
|
||||
|
||||
bool valid() const { return block_id != 0; }
|
||||
bool operator==(const FaceKey& o) const {
|
||||
return block_id == o.block_id && face == o.face;
|
||||
}
|
||||
bool operator!=(const FaceKey& o) const { return !(*this == o); }
|
||||
};
|
||||
|
||||
static constexpr int SIZE_X = CHUNK_SIZE;
|
||||
static constexpr int SIZE_Y = WORLD_SIZE_Y;
|
||||
static constexpr int SIZE_Z = CHUNK_SIZE;
|
||||
static constexpr int BLOCK_SIZE = SIZE_X * SIZE_Y * SIZE_Z;
|
||||
static constexpr int VERTEX_DATA_SUM = 5;
|
||||
std::atomic<bool> m_dirty{false};
|
||||
std::atomic<bool> m_need_upload{true};
|
||||
std::atomic<bool> m_is_on_gen_vertex_data{false};
|
||||
std::atomic<BiomeType> m_biome = BiomeType::PLAIN;
|
||||
std::mutex m_vertexs_data_mutex;
|
||||
ChunkPos m_chunk_pos;
|
||||
ClientWorld& m_world;
|
||||
// the index is a array of block id
|
||||
std::vector<BlockType> m_blocks;
|
||||
/*
|
||||
0 - normal
|
||||
1 - cross_plane
|
||||
2 - normal_discard
|
||||
3 - transparent and blend
|
||||
4 - water
|
||||
*/
|
||||
std::vector<VertexData> m_vertex_data;
|
||||
|
||||
ChunkRenderSnapshot m_render_snapshot;
|
||||
|
||||
unsigned m_seed = 0;
|
||||
void clear_dirty();
|
||||
void gen_vertices(const OptionalBlockVectorArray& neighbor_block);
|
||||
void gen_cross_plane_vertices(int world_x, int world_y, int world_z,
|
||||
BlockType id);
|
||||
void emit_quad(int axis, int face_dir, int layer, int i, int j, int w,
|
||||
int h, int u_axis, int v_axis, FaceKey key);
|
||||
};
|
||||
} // namespace Cubed
|
||||