mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-09 02:07:04 +08:00
Compare commits
69 Commits
v0.1.1
...
9fc94c56b5
| Author | SHA1 | Date | |
|---|---|---|---|
| 9fc94c56b5 | |||
| 3d9980314c | |||
| 9de5d13435 | |||
| ff039708c8 | |||
| ea2ab1a53a | |||
| 720f9fe0c1 | |||
| 85db85a737 | |||
| 8faf4c9a81 | |||
| 50a6a8c0ef | |||
| 12b1107923 | |||
| 9788f68b12 | |||
| cbe3548dcd | |||
| 4073664624 | |||
| a016e08a2a | |||
| a5764e901b | |||
| 429520b1f7 | |||
| d2636189a4 | |||
| 3d4c41a76e | |||
| 28b66ee275 | |||
| e1e9efb86c | |||
| 6b79a75b70 | |||
| 426202ba9e | |||
| 20402d1fda | |||
| 3d4490a46b | |||
| d93748e7fb | |||
| 1d4aa48230 | |||
| 65429b22d6 | |||
| 43395d4794 | |||
| 7b6c11e904 | |||
| aace0b4888 | |||
| e3f973284c | |||
| 18090bfd95 | |||
| 09fc46d306 | |||
| 932ef9ace4 | |||
| d31ec68f3c | |||
| c7c6ee9a61 | |||
| db7b67f265 | |||
| 7e42f595c9 | |||
| 11c902d2bf | |||
| e5e84848a9 | |||
| 25e9b0e0d3 | |||
| 48300b5fe2 | |||
| 3c14a4ffe1 | |||
| fbb6fe2fa6 | |||
| a858774b71 | |||
| 4631bbe6d6 | |||
| db10d30dc2 | |||
| 47552a1887 | |||
| d7d47e9e7f | |||
| 2c6dccfb53 | |||
| b782b40133 | |||
| 4a1ef54258 | |||
| cbc04f6ab0 | |||
| df2e26e731 | |||
| c92e2249a4 | |||
| 4e6f29bedd | |||
| 0223fefa6b | |||
| 8d86a71c3f | |||
| af8812916d | |||
| 85341651b3 | |||
| 9d33b240c6 | |||
| 6f39ff771d | |||
| 2953e8a233 | |||
| 678fc02998 | |||
| 4303c1cd32 | |||
| 1acfeef9e6 | |||
| 27e3cd6851 | |||
| d4a25bdf4b | |||
| 7c07110afa |
154
.github/workflows/release-build.yml
vendored
154
.github/workflows/release-build.yml
vendored
@@ -1,154 +0,0 @@
|
||||
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 }}
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -41,7 +41,6 @@ CMakeError.log
|
||||
*~
|
||||
.DS_Store
|
||||
assets/config.toml
|
||||
assets/server-config.toml
|
||||
.venv/
|
||||
pyout/
|
||||
vcpkg_installed/
|
||||
@@ -1,9 +1,4 @@
|
||||
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)
|
||||
@@ -18,10 +13,6 @@ if(NOT CMAKE_CONFIGURATION_TYPES
|
||||
|
||||
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)
|
||||
@@ -37,8 +28,6 @@ add_subdirectory(third_party/glad)
|
||||
|
||||
add_subdirectory(third_party/imgui)
|
||||
|
||||
add_subdirectory(third_party/dr_libs)
|
||||
|
||||
add_executable(${PROJECT_NAME})
|
||||
|
||||
add_subdirectory(src)
|
||||
@@ -54,12 +43,6 @@ protobuf_generate(
|
||||
IMPORT_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src/proto
|
||||
)
|
||||
|
||||
configure_file(
|
||||
src/version.hpp.in
|
||||
${CMAKE_BINARY_DIR}/generated/version.hpp
|
||||
@ONLY
|
||||
)
|
||||
|
||||
target_compile_options(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
$<$<CONFIG:Debug>:-fno-omit-frame-pointer>
|
||||
@@ -119,7 +102,7 @@ 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
|
||||
|
||||
@@ -136,7 +119,6 @@ target_link_libraries(${PROJECT_NAME}
|
||||
Freetype::Freetype
|
||||
tomlplusplus::tomlplusplus
|
||||
imgui
|
||||
dr_libs
|
||||
tbb
|
||||
protobuf::libprotobuf
|
||||
absl::log
|
||||
@@ -145,8 +127,6 @@ target_link_libraries(${PROJECT_NAME}
|
||||
absl::strings
|
||||
absl::flat_hash_map
|
||||
zstd::zstd
|
||||
OpenAL::OpenAL
|
||||
harfbuzz::harfbuzz
|
||||
$<$<PLATFORM_ID:Windows>:ws2_32>
|
||||
|
||||
)
|
||||
|
||||
BIN
assets/fonts/IBMPlexSans-Regular.ttf
Normal file
BIN
assets/fonts/IBMPlexSans-Regular.ttf
Normal file
Binary file not shown.
@@ -1,90 +0,0 @@
|
||||
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.
|
||||
Binary file not shown.
@@ -1,34 +0,0 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
{
|
||||
"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": "加入世界"
|
||||
}
|
||||
@@ -29,8 +29,254 @@ uniform bool flipY;
|
||||
uniform int renderDistance;
|
||||
uniform vec3 skyColor;
|
||||
|
||||
#include "shadow.glsl"
|
||||
#include "normal.glsl"
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
vec4 objectColor = texture(samp, vec3(tc, tex_layer));
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
#version 460
|
||||
|
||||
in vec2 tc;
|
||||
|
||||
void main() {
|
||||
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#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,11 +0,0 @@
|
||||
#version 460
|
||||
|
||||
in vec2 tc;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
layout (binding = 0) uniform sampler2D samp;
|
||||
|
||||
void main(void) {
|
||||
color = texture(samp, tc);
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
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);
|
||||
}
|
||||
@@ -1,47 +1,8 @@
|
||||
#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"
|
||||
in vec2 tc;
|
||||
|
||||
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);
|
||||
}
|
||||
color = vec4(0.0, 0.0, 1.0, 1.0);
|
||||
}
|
||||
@@ -2,26 +2,14 @@
|
||||
|
||||
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;
|
||||
|
||||
out vec2 tc;
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
#version 460
|
||||
|
||||
out vec4 color;
|
||||
|
||||
uniform vec4 inColor;
|
||||
|
||||
void main(void) {
|
||||
color = inColor;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#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);
|
||||
}
|
||||
@@ -1,238 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
12
assets/shaders/ui_f_shader.glsl
Normal file
12
assets/shaders/ui_f_shader.glsl
Normal file
@@ -0,0 +1,12 @@
|
||||
#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));
|
||||
}
|
||||
18
assets/shaders/ui_v_shader.glsl
Normal file
18
assets/shaders/ui_v_shader.glsl
Normal file
@@ -0,0 +1,18 @@
|
||||
#version 460
|
||||
|
||||
layout (location = 0) in vec2 pos;
|
||||
layout (location = 1) in vec2 texCoord;
|
||||
layout (location = 2) in float layer;
|
||||
|
||||
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);
|
||||
tc = texCoord;
|
||||
tex_layer = int(layer);
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 535 B |
Binary file not shown.
|
Before Width: | Height: | Size: 2.3 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 215 B |
Binary file not shown.
|
Before Width: | Height: | Size: 120 B |
Binary file not shown.
|
Before Width: | Height: | Size: 174 B |
Binary file not shown.
|
Before Width: | Height: | Size: 174 B |
@@ -5,10 +5,8 @@ find_package(OpenGL REQUIRED)
|
||||
find_package(Protobuf REQUIRED)
|
||||
find_package(absl REQUIRED)
|
||||
find_package(zstd REQUIRED)
|
||||
find_package(OpenAL REQUIRED)
|
||||
find_package(harfbuzz REQUIRED)
|
||||
find_package(Freetype REQUIRED)
|
||||
if (UNIX AND NOT APPLE)
|
||||
find_package(Freetype REQUIRED)
|
||||
find_package(glfw3 REQUIRED)
|
||||
endif()
|
||||
|
||||
@@ -52,6 +50,15 @@ if (WIN32)
|
||||
|
||||
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)
|
||||
|
||||
|
||||
@@ -1,17 +1,24 @@
|
||||
#pragma once
|
||||
#include "Cubed/audio/audio_engine.hpp"
|
||||
#include "Cubed/gameplay/client_world.hpp"
|
||||
#include "Cubed/gameplay/network_server.hpp"
|
||||
#include "Cubed/gameplay/server_world.hpp"
|
||||
#define GLFW_INCLUDE_NONE
|
||||
#include "Cubed/argument.hpp"
|
||||
#include "Cubed/config.hpp"
|
||||
#include "Cubed/camera.hpp"
|
||||
#include "Cubed/dev_panel.hpp"
|
||||
#include "Cubed/render/renderer.hpp"
|
||||
#include "Cubed/scene/scene_manager.hpp"
|
||||
#include "Cubed/renderer.hpp"
|
||||
#include "Cubed/texture_manager.hpp"
|
||||
#include "Cubed/window.hpp"
|
||||
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,
|
||||
@@ -23,8 +30,6 @@ public:
|
||||
static void window_focus_callback(GLFWwindow* window, int focused);
|
||||
static void window_reshape_callback(GLFWwindow* window, int new_width,
|
||||
int new_height);
|
||||
static void framebuffer_size_callback(GLFWwindow* window, int new_width,
|
||||
int new_height);
|
||||
static void mouse_scroll_callback(GLFWwindow* window, double xoffset,
|
||||
double yoffset);
|
||||
static void cursor_enter_callback(GLFWwindow* window, int entered);
|
||||
@@ -32,40 +37,38 @@ public:
|
||||
static int start_cubed_application(int argc, char** argv);
|
||||
|
||||
static unsigned int seed();
|
||||
static float delta_time();
|
||||
static float delte_time();
|
||||
static float get_fps();
|
||||
|
||||
Camera& camera();
|
||||
DevPanel& dev_panel();
|
||||
Renderer& renderer();
|
||||
TextureManager& texture_manager();
|
||||
Window& window();
|
||||
|
||||
Config& config();
|
||||
ClientWorld& client_world();
|
||||
ServerWorld& server_world();
|
||||
const Argument& argument() const;
|
||||
AudioEngine& audio();
|
||||
|
||||
const char* get_clipboard_text();
|
||||
|
||||
private:
|
||||
Config m_game_config;
|
||||
|
||||
Camera m_camera;
|
||||
TextureManager m_texture_manager;
|
||||
NetworkServer m_server;
|
||||
std::shared_ptr<NetworkClient> m_client;
|
||||
ClientWorld m_client_world;
|
||||
|
||||
AudioEngine m_audio;
|
||||
DevPanel m_dev_panel{*this};
|
||||
Renderer m_renderer{m_camera, m_client_world, m_texture_manager,
|
||||
m_dev_panel};
|
||||
|
||||
Renderer m_renderer;
|
||||
|
||||
Window m_window;
|
||||
|
||||
SceneManager m_scene_manager;
|
||||
Window m_window{m_renderer};
|
||||
|
||||
inline static double last_time = glfwGetTime();
|
||||
inline static double current_time = glfwGetTime();
|
||||
inline static double dt = 0.0f;
|
||||
inline static double delta_time = 0.0f;
|
||||
inline static double fps_time_count = 0.0f;
|
||||
inline static int frame_count = 0;
|
||||
inline static int fps = 0;
|
||||
Argument m_argument;
|
||||
|
||||
void init(int argc, char** argv);
|
||||
void handle_argument(int argc, char** argv);
|
||||
void handle_toml();
|
||||
@@ -76,8 +79,6 @@ private:
|
||||
void render();
|
||||
void run();
|
||||
void update();
|
||||
|
||||
void dispatch_event(const Event& e);
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -1,11 +0,0 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
namespace Cubed {
|
||||
struct Argument {
|
||||
bool is_client = false;
|
||||
int port = 25530;
|
||||
std::string ip{"127.0.0.1"};
|
||||
std::string player{"Unknown"};
|
||||
bool debug_on = true;
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -1,24 +0,0 @@
|
||||
#pragma once
|
||||
#include "Cubed/audio/audio_data.hpp"
|
||||
|
||||
#include <AL/al.h>
|
||||
namespace Cubed {
|
||||
class AudioBuffer {
|
||||
public:
|
||||
AudioBuffer(const AudioData& data);
|
||||
AudioBuffer(const AudioBuffer&) = delete;
|
||||
AudioBuffer(AudioBuffer&&) = delete;
|
||||
AudioBuffer& operator=(const AudioBuffer&) = delete;
|
||||
AudioBuffer& operator=(AudioBuffer&&) = delete;
|
||||
~AudioBuffer();
|
||||
ALuint buffer() const;
|
||||
float duration() const;
|
||||
uint32_t channels() const;
|
||||
|
||||
private:
|
||||
ALuint m_buffer = 0;
|
||||
float m_duration = 0.0f;
|
||||
uint32_t m_channels = 0;
|
||||
void set_data(const AudioData& data);
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
namespace Cubed {
|
||||
struct AudioData {
|
||||
std::vector<int16_t> pcm;
|
||||
uint32_t channels;
|
||||
uint32_t sample_rate;
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -1,19 +0,0 @@
|
||||
#pragma once
|
||||
#include <AL/al.h>
|
||||
namespace Cubed {
|
||||
class AudioEffect {
|
||||
public:
|
||||
AudioEffect();
|
||||
AudioEffect(const AudioEffect&) = delete;
|
||||
AudioEffect(AudioEffect&&) = delete;
|
||||
AudioEffect& operator=(const AudioEffect&) = default;
|
||||
AudioEffect& operator=(AudioEffect&&) = delete;
|
||||
~AudioEffect();
|
||||
void set_reverb(float decay_time, float reverb_gain, float gain_hf,
|
||||
float density = 1.0f, float diffusion = 1.0f);
|
||||
ALuint effect() const;
|
||||
|
||||
private:
|
||||
ALuint m_effect = 0;
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -1,18 +0,0 @@
|
||||
#pragma once
|
||||
#include "Cubed/audio/audio_effect.hpp"
|
||||
namespace Cubed {
|
||||
class AudioEffectSlot {
|
||||
public:
|
||||
AudioEffectSlot();
|
||||
AudioEffectSlot(const AudioEffectSlot&) = delete;
|
||||
AudioEffectSlot(AudioEffectSlot&&) = delete;
|
||||
AudioEffectSlot& operator=(const AudioEffectSlot&) = delete;
|
||||
AudioEffectSlot& operator=(AudioEffectSlot&&) = delete;
|
||||
~AudioEffectSlot();
|
||||
void set_effect(const AudioEffect& effect);
|
||||
ALuint slot() const;
|
||||
|
||||
private:
|
||||
ALuint m_slot = 0;
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -1,63 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/audio/audio_fade.hpp"
|
||||
#include "Cubed/audio/audio_source.hpp"
|
||||
#include "Cubed/audio/sound_manager.hpp"
|
||||
#include "Cubed/audio/source_pool.hpp"
|
||||
#include "Cubed/config.hpp"
|
||||
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
#include <glm/glm.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
namespace Cubed {
|
||||
|
||||
class ClientWorld;
|
||||
|
||||
class AudioEngine {
|
||||
public:
|
||||
AudioEngine(Config& config);
|
||||
AudioEngine(const AudioEngine&) = delete;
|
||||
AudioEngine(AudioEngine&&) = delete;
|
||||
AudioEngine& operator=(const AudioEngine&) = delete;
|
||||
AudioEngine& operator=(AudioEngine&&) = delete;
|
||||
~AudioEngine();
|
||||
|
||||
void init();
|
||||
void play_bgm();
|
||||
void stop_bgm();
|
||||
void change_bgm(const std::string& sound);
|
||||
void play_3d(const std::string& sound, const glm::vec3& pos,
|
||||
bool check = false);
|
||||
void play_2d(const std::string& sound, bool check = false);
|
||||
void update_listener(const glm::vec3& pos, const glm::vec3& forward,
|
||||
const glm::vec3& up);
|
||||
void update();
|
||||
void reload_config();
|
||||
|
||||
void underwater_change(bool underwater);
|
||||
|
||||
float& bgm_target_volume();
|
||||
|
||||
private:
|
||||
using FadeMap = std::unordered_map<std::string, AudioFade>;
|
||||
bool m_init{false};
|
||||
ALCdevice* device{nullptr};
|
||||
ALCcontext* context{nullptr};
|
||||
glm::vec3 listener_pos;
|
||||
std::unique_ptr<AudioSource> m_bgm;
|
||||
FadeMap m_fade_map;
|
||||
SoundManager m_sounds;
|
||||
Config& m_config;
|
||||
std::shared_ptr<SourcePool> m_pool;
|
||||
bool m_efx_supported = false;
|
||||
bool m_underwater = false;
|
||||
float m_music_volume = 1.0f;
|
||||
float m_sfx_volume = 1.0f;
|
||||
std::unique_ptr<AudioFilter> m_low_pass_filter;
|
||||
std::unique_ptr<AudioEffect> m_underwater_effect;
|
||||
std::unique_ptr<AudioEffectSlot> m_underwater_slot;
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -1,15 +0,0 @@
|
||||
#pragma once
|
||||
#include "Cubed/tools/log.hpp"
|
||||
|
||||
#include <AL/al.h>
|
||||
namespace Cubed {
|
||||
inline void check_al_error(
|
||||
std::source_location loaction = std::source_location::current()) {
|
||||
ALenum error = alGetError();
|
||||
if (error != AL_NO_ERROR) {
|
||||
Logger::error("File {} Line {} Function {} OpenAL Error {} ",
|
||||
loaction.file_name(), loaction.line(),
|
||||
loaction.function_name(), alGetString(error));
|
||||
}
|
||||
}
|
||||
} // namespace Cubed
|
||||
@@ -1,19 +0,0 @@
|
||||
#pragma once
|
||||
#include "Cubed/audio/audio_source.hpp"
|
||||
namespace Cubed {
|
||||
class AudioFade {
|
||||
public:
|
||||
AudioFade(AudioSource* source, float fade_in = 0.0f, float fade_out = 0.0f);
|
||||
~AudioFade();
|
||||
void update();
|
||||
void reset();
|
||||
|
||||
private:
|
||||
AudioSource* m_source = nullptr;
|
||||
float m_in_duration = 0.0f;
|
||||
float m_out_duration = 0.0f;
|
||||
float m_start_gain = 0.0f;
|
||||
bool m_fade_in = true;
|
||||
bool m_active = true;
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -1,19 +0,0 @@
|
||||
#pragma once
|
||||
#include <AL/al.h>
|
||||
namespace Cubed {
|
||||
class AudioFilter {
|
||||
public:
|
||||
AudioFilter();
|
||||
AudioFilter(const AudioFilter&) = delete;
|
||||
AudioFilter(AudioFilter&&) = delete;
|
||||
AudioFilter& operator=(const AudioFilter&) = delete;
|
||||
AudioFilter& operator=(AudioFilter&&) = delete;
|
||||
~AudioFilter();
|
||||
|
||||
void set_lowpass(float gain, float gain_hf);
|
||||
ALuint filter() const;
|
||||
|
||||
private:
|
||||
ALuint m_filter = 0;
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
#include "Cubed/audio/audio_data.hpp"
|
||||
|
||||
#include <filesystem>
|
||||
namespace Cubed {
|
||||
|
||||
class AudioLoader {
|
||||
public:
|
||||
static AudioData load(const std::filesystem::path& path);
|
||||
|
||||
private:
|
||||
static AudioData load_wav(const std::filesystem::path& path);
|
||||
static AudioData load_mp3(const std::filesystem::path& path);
|
||||
static AudioData load_flac(const std::filesystem::path& path);
|
||||
static AudioData load_ogg(const std::filesystem::path& path);
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -1,50 +0,0 @@
|
||||
#pragma once
|
||||
#include "Cubed/audio/audio_buffer.hpp"
|
||||
#include "Cubed/audio/audio_effect_slot.hpp"
|
||||
#include "Cubed/audio/audio_filter.hpp"
|
||||
|
||||
#include <AL/al.h>
|
||||
#include <glm/glm.hpp>
|
||||
namespace Cubed {
|
||||
|
||||
enum class AudioState { INITIAL, PLAYING, PAUSED, STOPPED };
|
||||
|
||||
class AudioSource {
|
||||
public:
|
||||
AudioSource(float volume = 1.0f);
|
||||
~AudioSource();
|
||||
|
||||
void set_buffer_2d(const AudioBuffer& buffer);
|
||||
void set_buffer_3d(const AudioBuffer& buffer, const glm::vec3& vec3);
|
||||
void set_loop(bool on = true);
|
||||
void set_volume(float volume);
|
||||
void set_pitch(float pitch);
|
||||
void play();
|
||||
void play_2d(const AudioBuffer& buffer);
|
||||
void play_3d(const AudioBuffer& buffer, const glm::vec3& pos);
|
||||
|
||||
void stop();
|
||||
void pause();
|
||||
float duration() const;
|
||||
float current_time() const;
|
||||
float target_volume() const;
|
||||
float& target_volume();
|
||||
void set_target_volume(float volume);
|
||||
AudioState state() const;
|
||||
|
||||
void mark_in_use();
|
||||
bool in_use() const;
|
||||
void reset();
|
||||
|
||||
void set_filter(const AudioFilter& filter);
|
||||
void clear_filter();
|
||||
void set_effect_slot(const AudioEffectSlot& slot);
|
||||
void clear_effect_slot();
|
||||
|
||||
private:
|
||||
ALuint m_source = 0;
|
||||
float m_target_volume = 1.0f;
|
||||
float m_duration = 0.0f;
|
||||
bool m_using;
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -1,19 +0,0 @@
|
||||
#pragma once
|
||||
#include "Cubed/audio/audio_buffer.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
namespace Cubed {
|
||||
class SoundManager {
|
||||
public:
|
||||
SoundManager();
|
||||
~SoundManager();
|
||||
const AudioBuffer& load(const std::string& name);
|
||||
const AudioBuffer& get_buffer(const std::string& name);
|
||||
void init();
|
||||
void clear();
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, AudioBuffer> m_buffers;
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -1,23 +0,0 @@
|
||||
#pragma once
|
||||
#include "Cubed/audio/audio_source.hpp"
|
||||
|
||||
namespace Cubed {
|
||||
class SourcePool {
|
||||
private:
|
||||
std::vector<AudioSource> m_sources;
|
||||
|
||||
public:
|
||||
explicit SourcePool(size_t size);
|
||||
~SourcePool();
|
||||
SourcePool(const SourcePool&) = delete;
|
||||
SourcePool(SourcePool&&) = delete;
|
||||
SourcePool& operator=(const SourcePool&) = delete;
|
||||
SourcePool& operator=(SourcePool&&) = delete;
|
||||
|
||||
void update();
|
||||
AudioSource* acquire();
|
||||
|
||||
std::vector<AudioSource>& sources();
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/input/event.hpp"
|
||||
#define GLFW_INCLUDE_NONE
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <glm/glm.hpp>
|
||||
@@ -13,24 +12,11 @@ class ClientPlayer;
|
||||
|
||||
class Camera {
|
||||
private:
|
||||
enum class Perspective {
|
||||
FIRST_PERSON,
|
||||
THIRD_PERSON_BACK,
|
||||
THIRD_PERSON_FRONT,
|
||||
};
|
||||
|
||||
bool m_firse_mouse = true;
|
||||
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);
|
||||
|
||||
bool handle_key_event(const KeyEvent& e);
|
||||
bool handle_mouse_move_event(const MouseMoveEvent& e);
|
||||
|
||||
public:
|
||||
Camera();
|
||||
@@ -47,9 +33,6 @@ public:
|
||||
|
||||
bool is_under_water() const;
|
||||
glm::vec3 get_camera_front() const;
|
||||
void change_perspective();
|
||||
bool is_first_person() const;
|
||||
bool handle_event(const Event& e);
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
|
||||
@@ -1,74 +1,99 @@
|
||||
#pragma once
|
||||
#include "Cubed/tools/cubed_assert.hpp"
|
||||
#include "Cubed/tools/toml.utils.hpp"
|
||||
|
||||
namespace Cubed {
|
||||
|
||||
class Config {
|
||||
public:
|
||||
explicit Config(std::string_view path);
|
||||
Config(const Config&) = delete;
|
||||
Config(Config&&) = delete;
|
||||
Config& operator=(const Config&) = delete;
|
||||
Config& operator=(Config&&) = delete;
|
||||
Config();
|
||||
~Config();
|
||||
|
||||
static Config& get();
|
||||
|
||||
toml::table& table();
|
||||
|
||||
void load_config();
|
||||
void load_or_create_config();
|
||||
void save_to_file();
|
||||
|
||||
template <TOML::TomlValueType T>
|
||||
T get(std::string_view key, T default_value) {
|
||||
if (auto* node = find_node(m_tbl, key)) {
|
||||
if (auto value = node->value<T>())
|
||||
return *value;
|
||||
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;
|
||||
while (pos != std::string_view::npos) {
|
||||
std::string_view s = key.substr(cur, pos - cur);
|
||||
if (s.empty()) {
|
||||
Logger::error("Empty key/table name in path '{}'", key);
|
||||
ASSERT(false);
|
||||
std::abort();
|
||||
}
|
||||
cur = pos + 1;
|
||||
pos = key.find('.', cur);
|
||||
if (auto* next = (*table)[s].as_table()) {
|
||||
table = next;
|
||||
} else {
|
||||
Logger::error("Can't find table {}", s);
|
||||
ASSERT(false);
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
set(key, default_value);
|
||||
|
||||
return default_value;
|
||||
}
|
||||
|
||||
template <TOML::TomlValueType T> void set(std::string_view key, T&& value) {
|
||||
auto pos = key.rfind('.');
|
||||
|
||||
toml::table* table;
|
||||
std::string_view name;
|
||||
|
||||
if (pos == std::string_view::npos) {
|
||||
table = &m_tbl;
|
||||
name = key;
|
||||
std::string_view n_key = key.substr(cur);
|
||||
if (n_key.empty()) {
|
||||
Logger::error("Trailing dot in path '{}'", key);
|
||||
ASSERT(false);
|
||||
std::abort();
|
||||
}
|
||||
auto opt = (*table)[n_key].value<T>();
|
||||
if (opt) {
|
||||
return *opt;
|
||||
} else {
|
||||
table = find_or_create_table(key.substr(0, pos));
|
||||
name = key.substr(pos + 1);
|
||||
Logger::error("Can't find key {}", n_key);
|
||||
ASSERT(false);
|
||||
std::abort();
|
||||
}
|
||||
// Insert node at the last level's table
|
||||
table->insert_or_assign(name, std::forward<T>(value));
|
||||
}
|
||||
|
||||
template <typename T> void set(std::string_view key, T&& val) {
|
||||
if constexpr (!TOML::TomlValueType<std::decay_t<T>>) {
|
||||
static_assert(false, "Type Not Support");
|
||||
}
|
||||
size_t cur = 0;
|
||||
auto pos = key.find('.');
|
||||
toml::table* table = &m_tbl;
|
||||
while (pos != std::string_view::npos) {
|
||||
std::string_view s = key.substr(cur, pos - cur);
|
||||
if (s.empty()) {
|
||||
Logger::error("Empty key/table name in path '{}'", key);
|
||||
ASSERT(false);
|
||||
std::abort();
|
||||
}
|
||||
cur = pos + 1;
|
||||
pos = key.find('.', cur);
|
||||
if (auto* next = (*table)[s].as_table()) {
|
||||
table = next;
|
||||
} else {
|
||||
auto [it, inserted] = table->insert_or_assign(s, toml::table{});
|
||||
table = it->second.as_table();
|
||||
}
|
||||
}
|
||||
std::string_view n_key = key.substr(cur);
|
||||
if (n_key.empty()) {
|
||||
Logger::error("Trailing dot in path '{}'", key);
|
||||
ASSERT(false);
|
||||
std::abort();
|
||||
}
|
||||
table->insert_or_assign(n_key, std::forward<T>(val));
|
||||
}
|
||||
template <typename T> void set_and_save(std::string_view key, T&& val) {
|
||||
set(key, std::forward(val));
|
||||
save_to_file();
|
||||
}
|
||||
toml::node_view<toml::node> val_view(std::string_view key);
|
||||
|
||||
private:
|
||||
toml::table m_tbl;
|
||||
const std::string CONGIF_PATH;
|
||||
const toml::node* find_node(const toml::table& root,
|
||||
std::string_view path) const;
|
||||
// Follow the path to find the last-level toml::table, creating it if it
|
||||
// does not exist
|
||||
toml::table* find_or_create_table(std::string_view path);
|
||||
constexpr static inline std::string_view CONGIF_PATH =
|
||||
ASSETS_PATH "config.toml";
|
||||
void create_config();
|
||||
};
|
||||
|
||||
template <>
|
||||
inline float Config::get(std::string_view key, float default_value) {
|
||||
return static_cast<float>(
|
||||
Config::get<double>(key, static_cast<double>(default_value)));
|
||||
}
|
||||
|
||||
template <> inline void Config::set(std::string_view key, float&& value) {
|
||||
Config::set<double>(key, static_cast<double>(value));
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/ui/column_layout.hpp"
|
||||
#include "Cubed/ui/label.hpp"
|
||||
#include "Cubed/ui/widget.hpp"
|
||||
#include "Cubed/ui/text.hpp"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
@@ -13,14 +11,14 @@ public:
|
||||
static DebugCollector& get();
|
||||
DebugCollector();
|
||||
|
||||
void report(const std::string& name, std::string_view content);
|
||||
void init(int width, int height);
|
||||
Widget& get_widget();
|
||||
bool handle_event(const Event& e);
|
||||
std::unordered_map<std::size_t, Text>& all_texts();
|
||||
|
||||
Text& text(std::string_view name);
|
||||
void report(std::string_view name, std::string_view content);
|
||||
void init_text();
|
||||
|
||||
private:
|
||||
ColumnLayout m_widget;
|
||||
std::unordered_map<std::string, Label*> m_component;
|
||||
std::unordered_map<std::size_t, Text> m_texts;
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -1,14 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/config.hpp"
|
||||
|
||||
#include <toml++/toml.hpp>
|
||||
|
||||
namespace Cubed {
|
||||
|
||||
class WorldScene;
|
||||
class ClientPlayer;
|
||||
class App;
|
||||
class ClientPlayer;
|
||||
class DevPanel {
|
||||
struct ConfigView {
|
||||
float fov = 70.0f;
|
||||
@@ -23,27 +20,27 @@ class DevPanel {
|
||||
bool is_enable_aniso = false;
|
||||
bool is_support_aniso = true;
|
||||
bool is_reload = true;
|
||||
float volume_music = 1.0f;
|
||||
float volume_sfx = 1.0f;
|
||||
};
|
||||
struct PlayerProfile {
|
||||
int game_mode = 0;
|
||||
int gait = 0;
|
||||
float pos[3] = {0.0f, 0.0f, 0.0f};
|
||||
};
|
||||
struct TextEditing {
|
||||
bool perlin_seed = false;
|
||||
};
|
||||
|
||||
public:
|
||||
DevPanel(WorldScene& app);
|
||||
DevPanel(App& app);
|
||||
void init();
|
||||
void render();
|
||||
|
||||
private:
|
||||
App& m_app;
|
||||
WorldScene& m_world_scene;
|
||||
Config& m_config;
|
||||
ConfigView m_config_view;
|
||||
ConfigView m_config;
|
||||
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;
|
||||
@@ -53,6 +50,7 @@ private:
|
||||
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();
|
||||
|
||||
@@ -18,7 +18,6 @@ public:
|
||||
ChunkGenerator(ServerChunk& chunk);
|
||||
|
||||
static void init();
|
||||
static void init(unsigned seed);
|
||||
static void reload();
|
||||
static const unsigned& seed();
|
||||
static void seed(unsigned s);
|
||||
|
||||
@@ -51,7 +51,6 @@ public:
|
||||
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;
|
||||
@@ -76,7 +75,6 @@ public:
|
||||
void need_upload();
|
||||
|
||||
void set_chunk_block(int index, unsigned id);
|
||||
BlockType get_chunk_block(int index);
|
||||
bool is_temp_chunk() const;
|
||||
ChunkPos chunk_pos() const;
|
||||
BiomeType biome() const;
|
||||
@@ -84,7 +82,6 @@ public:
|
||||
std::vector<BlockType>& blocks();
|
||||
ClientWorld& world();
|
||||
unsigned seed() const;
|
||||
const ChunkRenderSnapshot* get_render_snapshot() const;
|
||||
|
||||
private:
|
||||
struct FaceKey {
|
||||
@@ -120,9 +117,6 @@ private:
|
||||
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);
|
||||
|
||||
@@ -4,51 +4,41 @@
|
||||
#include "Cubed/gameplay/block.hpp"
|
||||
#include "Cubed/gameplay/chunk_pos.hpp"
|
||||
#include "Cubed/gameplay/game_mode.hpp"
|
||||
#include "Cubed/gameplay/game_time.hpp"
|
||||
#include "Cubed/gameplay/player.hpp"
|
||||
#include "Cubed/input/event.hpp"
|
||||
#include "Cubed/input/input.hpp"
|
||||
#include "Cubed/input.hpp"
|
||||
|
||||
#include <absl/container/flat_hash_set.h>
|
||||
#include <glm/glm.hpp>
|
||||
#include <optional>
|
||||
#include <shared_mutex>
|
||||
namespace Cubed {
|
||||
|
||||
enum class Gait { WALK = 0, RUN };
|
||||
class ClientWorld;
|
||||
class ClientPlayer {
|
||||
public:
|
||||
static constexpr float WALK_SOUND_INTERVAL = 0.45f;
|
||||
static constexpr float RUN_SOUND_INTERVAL = 0.3f;
|
||||
using ChunkPosSet = absl::flat_hash_set<ChunkPos, ChunkPos::Hash>;
|
||||
ClientPlayer(ClientWorld& world);
|
||||
~ClientPlayer();
|
||||
|
||||
bool handle_mouse_button_event(const MouseButtonEvent& e);
|
||||
bool handle_key_event(const KeyEvent& e);
|
||||
bool handle_mouse_wheel_event(const MouseWheelEvent& e);
|
||||
|
||||
void update_front_vec(float offset_x, float offset_y);
|
||||
bool update_player_move_state(Key key, KeyAction action);
|
||||
bool update_scroll(float yoffset);
|
||||
|
||||
void update_chunk_set(const ChunkPosSet& set);
|
||||
const ChunkPosSet& get_chunk_pos_set() const;
|
||||
ChunkPosSet get_chunk_pos_set();
|
||||
ChunkPosSet& get_chunk_pos_set();
|
||||
|
||||
static AABB get_aabb(const glm::vec3& pos);
|
||||
AABB get_aabb(const glm::vec3& pos) const;
|
||||
const glm::vec3& get_front() const;
|
||||
Gait get_gait() const;
|
||||
const Gait& get_gait() const;
|
||||
const std::optional<LookBlock>& get_look_block_pos() const;
|
||||
// thread safe
|
||||
glm::vec3 get_player_pos() const;
|
||||
const MoveState& get_move_state() const;
|
||||
|
||||
void change_mode(GameMode mode);
|
||||
void reload_config();
|
||||
void hot_reload();
|
||||
void set_player_pos(const glm::vec3& pos);
|
||||
void set_place_block(unsigned id);
|
||||
void update(float delta_time);
|
||||
void update_front_vec(float offset_x, float offset_y);
|
||||
void update_player_move_state(int key, int action);
|
||||
void update_scroll(double yoffset);
|
||||
|
||||
float& max_walk_speed();
|
||||
float& max_run_speed();
|
||||
@@ -58,29 +48,18 @@ public:
|
||||
float& g();
|
||||
float& fly_y_speed();
|
||||
|
||||
unsigned get_current_block() const;
|
||||
unsigned place_block() const;
|
||||
|
||||
void set_gait(Gait gait);
|
||||
Gait& gait();
|
||||
GameMode& game_mode();
|
||||
|
||||
ClientWorld& get_world();
|
||||
const ClientWorld& get_world() const;
|
||||
|
||||
void set_uuid(std::string_view uuid);
|
||||
std::string get_uuid() const;
|
||||
const std::string& get_uuid() const;
|
||||
const std::string& get_name() const;
|
||||
void reset_key_status();
|
||||
void init(std::string_view name);
|
||||
|
||||
float yaw() const;
|
||||
float pitch() const;
|
||||
float& angle();
|
||||
float& walk_time();
|
||||
bool ray_cast(const glm::vec3& start, const glm::vec3& dir,
|
||||
glm::ivec3& block_pos, glm::vec3& normal,
|
||||
float distance = 4.0f);
|
||||
bool is_underwater() const;
|
||||
void set_underwater(bool u);
|
||||
void place_block(float dt);
|
||||
void init(std::string_view name);
|
||||
|
||||
private:
|
||||
using enum GameMode;
|
||||
@@ -90,10 +69,9 @@ private:
|
||||
float m_deceleration = DEFAULT_DECELERATION;
|
||||
float m_g = DEFAULT_G;
|
||||
constexpr static float MAX_SPACE_ON_TIME = 0.3f;
|
||||
constexpr static float PLACE_BLOCK_INTERVAL = 0.2f;
|
||||
float m_place_time = PLACE_BLOCK_INTERVAL;
|
||||
std::atomic<float> m_yaw = 0.0f;
|
||||
std::atomic<float> m_pitch = 0.0f;
|
||||
|
||||
float m_yaw = 0.0f;
|
||||
float m_pitch = 0.0f;
|
||||
|
||||
float m_sensitivity = 0.15f;
|
||||
|
||||
@@ -110,10 +88,6 @@ private:
|
||||
|
||||
unsigned m_place_block = 1;
|
||||
|
||||
bool m_moving = false;
|
||||
bool m_sprinting = false;
|
||||
bool m_underwater = false;
|
||||
|
||||
glm::vec3 direction = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
glm::vec3 move_distance{0.0f, 0.0f, 0.0f};
|
||||
// player is tow block tall, the pos is the lower pos
|
||||
@@ -123,39 +97,29 @@ private:
|
||||
|
||||
glm::vec3 m_front{0, 0, -1};
|
||||
glm::vec3 m_right{0, 0, 0};
|
||||
static constexpr glm::vec3 M_SIZE{0.6f, 1.8f, 0.6f};
|
||||
glm::vec3 m_size{0.6f, 1.8f, 0.6f};
|
||||
|
||||
std::atomic<Gait> m_gait = Gait::STOP;
|
||||
Gait m_gait = Gait::WALK;
|
||||
MoveState m_move_state{};
|
||||
MouseState m_mouse_state{};
|
||||
GameMode m_game_mode = CREATIVE;
|
||||
std::optional<LookBlock> m_look_block = std::nullopt;
|
||||
std::string m_name{};
|
||||
mutable std::shared_mutex m_uuid_mutex;
|
||||
std::string m_uuid;
|
||||
ClientWorld& m_world;
|
||||
|
||||
float m_angle{0.0f};
|
||||
float m_walk_time{0.0f};
|
||||
|
||||
std::unordered_map<std::string, Timer> m_timers;
|
||||
|
||||
mutable std::shared_mutex m_player_pos_mutex;
|
||||
mutable std::shared_mutex m_chunk_pos_mutex;
|
||||
ChunkPosSet m_player_chunk_pos_set;
|
||||
bool ray_cast(const glm::vec3& start, const glm::vec3& dir,
|
||||
glm::ivec3& block_pos, glm::vec3& normal,
|
||||
float distance = 4.0f);
|
||||
|
||||
void update_direction();
|
||||
void update_lookup_block();
|
||||
|
||||
void update_move(float delta_time);
|
||||
|
||||
void update_x_move(glm::vec3& player_pos);
|
||||
void update_y_move(glm::vec3& player_pos);
|
||||
void update_z_move(glm::vec3& player_pos);
|
||||
|
||||
void update_player_chunk();
|
||||
|
||||
void play_walk_sound(float dt);
|
||||
Gait compute_gait() const;
|
||||
};
|
||||
} // namespace Cubed
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
#pragma once
|
||||
#include "Cubed/audio/audio_engine.hpp"
|
||||
#include "Cubed/config.hpp"
|
||||
#include "Cubed/gameplay/block.hpp"
|
||||
#include "Cubed/gameplay/chunk_pos.hpp"
|
||||
#include "Cubed/gameplay/client_chunk.hpp"
|
||||
#include "Cubed/gameplay/client_player.hpp"
|
||||
#include "Cubed/gameplay/game_time.hpp"
|
||||
#include "Cubed/gameplay/network_client.hpp"
|
||||
#include "Cubed/input/event.hpp"
|
||||
#include "Cubed/tools/cubed_random.hpp"
|
||||
#include "Cubed/tools/priority_thread_pool.hpp"
|
||||
#include "Cubed/tools/thread_pool.hpp"
|
||||
|
||||
#include <absl/container/flat_hash_set.h>
|
||||
#include <deque>
|
||||
@@ -18,42 +14,26 @@
|
||||
#include <tbb/concurrent_unordered_map.h>
|
||||
namespace Cubed {
|
||||
|
||||
struct PlayerInfo {
|
||||
struct RemotePlayerInfo {
|
||||
std::string name;
|
||||
std::string uuid;
|
||||
glm::vec3 render_pos;
|
||||
glm::vec3 target_pos;
|
||||
float render_yaw;
|
||||
float yaw;
|
||||
float render_pitch;
|
||||
float pitch;
|
||||
Gait gait;
|
||||
float angle = 0.0f;
|
||||
float walk_time = 0.0f;
|
||||
float moving_time = 0.0f;
|
||||
};
|
||||
|
||||
struct PlayerRenderData {
|
||||
struct RemotePlayerRenderData {
|
||||
std::string name;
|
||||
std::string uuid;
|
||||
glm::vec3 render_pos;
|
||||
float yaw;
|
||||
float pitch;
|
||||
Gait gait;
|
||||
float angle;
|
||||
};
|
||||
class WorldScene;
|
||||
|
||||
class ClientWorld {
|
||||
public:
|
||||
ClientWorld(AudioEngine& auido, Config& config, WorldScene& scene);
|
||||
ClientWorld();
|
||||
~ClientWorld();
|
||||
void init(std::string_view player_name,
|
||||
std::shared_ptr<NetworkClient> client);
|
||||
void update(float delta_time);
|
||||
bool handle_event(const Event& e);
|
||||
const std::optional<LookBlock>& get_look_block_pos() const;
|
||||
ClientPlayer& get_player();
|
||||
const ClientPlayer& get_player() const;
|
||||
int get_block(const glm::ivec3& block_pos) const;
|
||||
bool is_solid(const glm::ivec3& block_pos) const;
|
||||
bool can_pass_block(const glm::ivec3& block_pos) const;
|
||||
@@ -61,8 +41,8 @@ public:
|
||||
|
||||
void rebuild_world();
|
||||
|
||||
void push_delete_vbo(std::unique_ptr<VertexBuffer>& vbo);
|
||||
void push_delete_vao(std::unique_ptr<VertexArray>& vao);
|
||||
void push_delete_vbo(GLuint vbo);
|
||||
void push_delete_vao(GLuint vao);
|
||||
// void hot_reload();
|
||||
|
||||
// void rebuild_world();
|
||||
@@ -72,8 +52,6 @@ public:
|
||||
|
||||
void receive_remote_player(const PlayerInfoRsp& rsp);
|
||||
void receive_player_logout(const LogoutRsp& rsp);
|
||||
void receive_player_water_sound(const PlayerWaterSound& rsp);
|
||||
void send_player_water_sound(bool underwater, const glm::vec3& pos);
|
||||
int rendering_distance() const;
|
||||
void rendering_distance(int rendering_distance);
|
||||
int get_chunk_task_id() const;
|
||||
@@ -83,77 +61,55 @@ public:
|
||||
void start_thread_pool();
|
||||
void stop_thread_pool();
|
||||
void change_pool_threads(int threads);
|
||||
void reload_config(bool chunk_build = true);
|
||||
void hot_reload();
|
||||
void request_chunk();
|
||||
void reset_key_status();
|
||||
std::vector<glm::vec4>& planes();
|
||||
const std::vector<const ChunkRenderSnapshot*>& render_snapshots() const;
|
||||
const std::vector<PlayerRenderData>& render_player_data() const;
|
||||
std::vector<PlayerRenderData>& render_player_data();
|
||||
|
||||
const std::vector<ChunkRenderSnapshot>& render_snapshots() const;
|
||||
const std::vector<RemotePlayerRenderData>& render_player_data() const;
|
||||
glm::vec3 sunlight_dir() const;
|
||||
bool sphere_collide_world(glm::vec3 center, float radius) const;
|
||||
void receive_chunk(std::vector<uint8_t> data, PacketHeader header);
|
||||
void request_exit();
|
||||
bool is_receive_exit();
|
||||
int chunk_size() const;
|
||||
static AABB get_block_aabb(const glm::ivec3& pos);
|
||||
AudioEngine& get_audio();
|
||||
Config& get_config();
|
||||
WorldScene& world_scene();
|
||||
template <typename Fn>
|
||||
void register_ticktimer(std::string_view id, TickType threshold, Fn&& f) {
|
||||
m_ticktimers.emplace(
|
||||
std::piecewise_construct, std::forward_as_tuple(std::string(id)),
|
||||
std::forward_as_tuple(threshold, std::forward<Fn>(f)));
|
||||
void register_timer(std::string_view id, TickType threshold, Fn&& f) {
|
||||
m_timers.emplace(std::piecewise_construct,
|
||||
std::forward_as_tuple(std::string(id)),
|
||||
std::forward_as_tuple(threshold, std::forward<Fn>(f)));
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic<bool> m_is_pending_delete_queue_free{false};
|
||||
std::mutex m_delete_vbo_mutex;
|
||||
std::mutex m_delete_vao_mutex;
|
||||
std::vector<std::unique_ptr<VertexBuffer>> m_pending_delete_vbo;
|
||||
std::vector<std::unique_ptr<VertexArray>> m_pending_delete_vao;
|
||||
|
||||
enum class ChunkLoadStyle { RANDOM, CENTER };
|
||||
using ChunkHashMap =
|
||||
tbb::concurrent_hash_map<ChunkPos, std::shared_ptr<ClientChunk>,
|
||||
ChunkPos::TBBHash>;
|
||||
using ChunkPosSet = absl::flat_hash_set<ChunkPos, ChunkPos::Hash>;
|
||||
using ChunkPosVector = std::vector<ChunkPos>;
|
||||
using OtherPlayerHashMap = std::unordered_map<std::string, PlayerInfo>;
|
||||
using OtherPlayerHashMap =
|
||||
std::unordered_map<std::string, RemotePlayerInfo>;
|
||||
using chunk_acc = ChunkHashMap::accessor;
|
||||
using chunk_cacc = ChunkHashMap::const_accessor;
|
||||
|
||||
struct PendingSound {
|
||||
std::string sound;
|
||||
glm::vec3 sound_pos;
|
||||
};
|
||||
|
||||
static constexpr int WORLD_EXIT_TIMEOUT = 200;
|
||||
static constexpr int MAX_UPLOAD_CHUNK_SUM = 16;
|
||||
|
||||
ClientPlayer m_player;
|
||||
OtherPlayerHashMap m_player_info;
|
||||
OtherPlayerHashMap m_other_players;
|
||||
ChunkHashMap m_chunks;
|
||||
AudioEngine& m_audio;
|
||||
Config& m_config;
|
||||
WorldScene& m_world_scene;
|
||||
std::vector<glm::vec4> m_planes;
|
||||
std::jthread m_client_thread;
|
||||
|
||||
mutable std::shared_mutex m_player_info_mutex;
|
||||
std::mutex m_delete_vbo_mutex;
|
||||
std::mutex m_delete_vao_mutex;
|
||||
std::mutex m_other_players_mutex;
|
||||
|
||||
tbb::concurrent_queue<std::unique_ptr<ClientChunk>> m_pending_upload_queue;
|
||||
tbb::concurrent_queue<ChunkPos> m_dirty_chunk_queue;
|
||||
tbb::concurrent_queue<PendingSound> m_pending_sound;
|
||||
|
||||
std::vector<GLuint> m_pending_delete_vbo;
|
||||
std::vector<GLuint> m_pending_delete_vao;
|
||||
|
||||
std::deque<ChunkPos> m_dirty_queue;
|
||||
std::vector<const ChunkRenderSnapshot*> m_render_snapshots;
|
||||
std::vector<PlayerRenderData> m_render_player_data;
|
||||
|
||||
tbb::concurrent_unordered_map<std::string, TickTimer> m_ticktimers;
|
||||
std::unordered_map<std::string, Timer> m_timers;
|
||||
|
||||
std::vector<ChunkRenderSnapshot> m_render_snapshots;
|
||||
std::vector<RemotePlayerRenderData> m_render_player_data;
|
||||
tbb::concurrent_unordered_map<std::string, Timer> m_timers;
|
||||
std::atomic<bool> m_game_running{false};
|
||||
std::atomic<bool> m_receive_exit{false};
|
||||
std::atomic<int> m_rendering_distance{24};
|
||||
@@ -165,13 +121,13 @@ private:
|
||||
std::shared_ptr<NetworkClient> m_client;
|
||||
ChunkLoadStyle m_chunk_load_style{ChunkLoadStyle::CENTER};
|
||||
|
||||
std::atomic<std::shared_ptr<PriorityThreadPool>> m_thread_pool;
|
||||
|
||||
Random m_random;
|
||||
std::atomic<std::shared_ptr<ThreadPool>> m_thread_pool;
|
||||
|
||||
void client_run(std::stop_token token);
|
||||
|
||||
void report_player_info();
|
||||
void set_player_pos();
|
||||
|
||||
void report_player_pos();
|
||||
|
||||
void set_block(const glm::ivec3& pos, unsigned id);
|
||||
|
||||
|
||||
@@ -6,9 +6,7 @@
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
namespace Cubed {
|
||||
|
||||
using TickType = long long;
|
||||
using TimeType = float;
|
||||
|
||||
constexpr int DEFAULT_PER_TICK_TIME = 50;
|
||||
|
||||
@@ -16,10 +14,10 @@ constexpr TickType DAY_TIME = 24000;
|
||||
|
||||
constexpr TickType PER_HOUR = 1000;
|
||||
|
||||
class TickTimer {
|
||||
class Timer {
|
||||
public:
|
||||
template <typename Fn>
|
||||
TickTimer(TickType threshold, Fn&& f)
|
||||
Timer(TickType threshold, Fn&& f)
|
||||
: m_fn(std::forward<Fn>(f)), m_threshold(threshold) {
|
||||
ASSERT_MSG(threshold > 0, "Threshold Must Rreater Than 0");
|
||||
}
|
||||
@@ -39,37 +37,4 @@ private:
|
||||
TickType m_current = 0;
|
||||
};
|
||||
|
||||
class Timer {
|
||||
public:
|
||||
template <typename Fn>
|
||||
Timer(TimeType threshold, Fn&& f)
|
||||
: m_fn(std::forward<Fn>(f)), m_threshold(threshold) {
|
||||
ASSERT_MSG(threshold > 0, "Threshold Must Rreater Than 0");
|
||||
}
|
||||
bool update(TimeType dt) {
|
||||
m_current += dt;
|
||||
|
||||
bool triggered = false;
|
||||
|
||||
while (m_current >= m_threshold) {
|
||||
m_current -= m_threshold;
|
||||
m_fn();
|
||||
triggered = true;
|
||||
}
|
||||
|
||||
return triggered;
|
||||
}
|
||||
void reset() { m_current = 0.0f; }
|
||||
void set_threshold(TimeType threshold) {
|
||||
|
||||
ASSERT_MSG(threshold > 0, "Threshold must be greater than 0");
|
||||
m_threshold = threshold;
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<void()> m_fn;
|
||||
TimeType m_threshold;
|
||||
TimeType m_current = 0;
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "Cubed/gameplay/packet.hpp"
|
||||
|
||||
#include <asio.hpp>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
namespace Cubed {
|
||||
@@ -15,56 +14,29 @@ public:
|
||||
~NetworkClient();
|
||||
void close();
|
||||
void stop();
|
||||
void send(Packet packet, int priority = 10);
|
||||
void send(Packet packet);
|
||||
void start(std::string ip, int port = 25530);
|
||||
bool is_connected() const;
|
||||
bool is_connect_error() const;
|
||||
std::string get_error_string() const;
|
||||
void clear_error();
|
||||
|
||||
private:
|
||||
struct Task {
|
||||
int priority = 10;
|
||||
std::uint64_t sequence = 0;
|
||||
Packet packet;
|
||||
Task(int p, std::uint64_t seq, Packet pac)
|
||||
: priority(p), sequence(seq), packet(std::move(pac)) {}
|
||||
};
|
||||
|
||||
struct TaskCompare {
|
||||
bool operator()(const Task& a, const Task& b) const {
|
||||
|
||||
if (a.priority != b.priority) {
|
||||
return a.priority > b.priority;
|
||||
}
|
||||
|
||||
return a.sequence > b.sequence;
|
||||
}
|
||||
};
|
||||
|
||||
asio::io_context m_io;
|
||||
|
||||
std::thread m_net_thread;
|
||||
static constexpr uint32_t MAX_PACKET_SIZE = 4 * 1024 * 1024;
|
||||
tcp::socket m_socket;
|
||||
std::vector<char> m_read_buffer;
|
||||
|
||||
std::priority_queue<Task, std::vector<Task>, TaskCompare> m_write_queue;
|
||||
|
||||
std::deque<Packet> m_write_queue;
|
||||
asio::strand<asio::io_context::executor_type> m_strand;
|
||||
std::atomic<bool> m_closed{false};
|
||||
std::atomic<bool> m_connected{false};
|
||||
std::atomic<bool> m_connect_error{false};
|
||||
mutable std::mutex m_error_string_mutex;
|
||||
std::string m_error_string;
|
||||
// ClientWorld is managed by App
|
||||
ClientWorld& m_world;
|
||||
std::atomic_uint64_t m_sequence{0};
|
||||
|
||||
asio::awaitable<void> connect(std::string ip, int port);
|
||||
asio::awaitable<void> read_loop();
|
||||
|
||||
std::atomic<bool> m_closed{false};
|
||||
std::atomic<bool> m_connected{false};
|
||||
std::atomic<bool> m_connect_error{false};
|
||||
// ClientWorld is managed by App
|
||||
ClientWorld& m_world;
|
||||
|
||||
void do_write();
|
||||
void set_error(std::string_view error);
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -1,5 +1,4 @@
|
||||
#pragma once
|
||||
#include "Cubed/config.hpp"
|
||||
#include "Cubed/gameplay/server_world.hpp"
|
||||
#include "Cubed/gameplay/session.hpp"
|
||||
|
||||
@@ -9,19 +8,17 @@ namespace Cubed {
|
||||
|
||||
class NetworkServer {
|
||||
public:
|
||||
explicit NetworkServer();
|
||||
NetworkServer(int port = 25530);
|
||||
~NetworkServer();
|
||||
void stop();
|
||||
|
||||
// Run in another thread after initialization is complete
|
||||
void start_server(int port);
|
||||
void start_server();
|
||||
void start_server(int port = 25530);
|
||||
|
||||
int port() const;
|
||||
ServerWorld& server_world();
|
||||
|
||||
private:
|
||||
Config m_config;
|
||||
|
||||
asio::io_context m_io;
|
||||
std::thread m_net_thread;
|
||||
int m_port = 25530;
|
||||
|
||||
@@ -52,9 +52,8 @@ enum class PacketEnum : uint16_t {
|
||||
LOGOUT_REQ = 1003,
|
||||
LOGOUT_RSP = 1004,
|
||||
PLAYER_INFO = 2001,
|
||||
C2S_PLAYER_INFO = 2002,
|
||||
PLAYER_POS = 2002,
|
||||
PLAYER_INFO_RSP = 2003,
|
||||
PLAYER_WATER_SOUND = 2004,
|
||||
CHUNK_DATA_REQ = 3001,
|
||||
CHUNK_DATA_RSP = 3002,
|
||||
BLOCK_CHANGE_REQ = 3003,
|
||||
@@ -88,8 +87,8 @@ template <> constexpr uint16_t get_packet_id<LogoutRsp>() {
|
||||
template <> constexpr uint16_t get_packet_id<PlayerInfo>() {
|
||||
return std::to_underlying(PacketEnum::PLAYER_INFO);
|
||||
}
|
||||
template <> constexpr uint16_t get_packet_id<C2S_PlayerInfo>() {
|
||||
return std::to_underlying(PacketEnum::C2S_PLAYER_INFO);
|
||||
template <> constexpr uint16_t get_packet_id<PlayerPos>() {
|
||||
return std::to_underlying(PacketEnum::PLAYER_POS);
|
||||
}
|
||||
template <> constexpr uint16_t get_packet_id<PlayerInfoRsp>() {
|
||||
return std::to_underlying(PacketEnum::PLAYER_INFO_RSP);
|
||||
@@ -118,9 +117,6 @@ template <> constexpr uint16_t get_packet_id<Ping>() {
|
||||
template <> constexpr uint16_t get_packet_id<Pong>() {
|
||||
return std::to_underlying(PacketEnum::PONG);
|
||||
}
|
||||
template <> constexpr uint16_t get_packet_id<PlayerWaterSound>() {
|
||||
return std::to_underlying(PacketEnum::PLAYER_WATER_SOUND);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires std::derived_from<T, google::protobuf::Message>
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#pragma once
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
namespace Cubed {
|
||||
enum class Gait { STOP = 0, WALK = 1, RUN = 2 };
|
||||
constexpr int get_gait_id(Gait gait) { return std::to_underlying(gait); }
|
||||
|
||||
inline Gait get_gait_from_id(int id) {
|
||||
switch (id) {
|
||||
case std::to_underlying(Gait::STOP):
|
||||
return Gait::STOP;
|
||||
case std::to_underlying(Gait::WALK):
|
||||
return Gait::WALK;
|
||||
case std::to_underlying(Gait::RUN):
|
||||
return Gait::RUN;
|
||||
default:
|
||||
throw std::runtime_error("Unknown Gait");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
#include "Cubed/gameplay/chunk_pos.hpp"
|
||||
#include "Cubed/gameplay/game_time.hpp"
|
||||
#include "Cubed/gameplay/player.hpp"
|
||||
|
||||
#include <absl/container/flat_hash_set.h>
|
||||
#include <atomic>
|
||||
@@ -39,14 +38,6 @@ public:
|
||||
const ChunkPosSet& get_chunk_pos_set() const;
|
||||
ChunkPosSet& get_chunk_pos_set();
|
||||
|
||||
void set_yaw(float yaw);
|
||||
void set_pitch(float pitch);
|
||||
float yaw() const;
|
||||
float pitch() const;
|
||||
|
||||
Gait gait() const;
|
||||
void set_gait(Gait gait);
|
||||
|
||||
private:
|
||||
static constexpr TickType TIMEOUT = 200;
|
||||
std::string m_name;
|
||||
@@ -54,12 +45,9 @@ private:
|
||||
glm::vec3 m_pos{0.0f};
|
||||
ServerWorld& m_world;
|
||||
ChunkPos m_last_chunk_pos{0, 0};
|
||||
std::atomic<std::shared_ptr<Session>> m_session;
|
||||
std::shared_ptr<Session> m_session;
|
||||
std::atomic<TickType> m_last_gametick{0};
|
||||
std::atomic<int> m_chunk_task_id{0};
|
||||
std::atomic<float> m_yaw{0.0f};
|
||||
std::atomic<float> m_pitch{0.0f};
|
||||
std::atomic<Gait> m_gait;
|
||||
mutable std::shared_mutex m_chunk_pos_mutex;
|
||||
ChunkPosSet m_player_chunk_pos_set;
|
||||
};
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/config.hpp"
|
||||
#include "Cubed/gameplay/cave_carver.hpp"
|
||||
#include "Cubed/gameplay/chunk_pos.hpp"
|
||||
#include "Cubed/gameplay/game_time.hpp"
|
||||
#include "Cubed/gameplay/packet.hpp" // IWYU pragma: keep
|
||||
#include "Cubed/gameplay/river_worm.hpp"
|
||||
#include "Cubed/gameplay/server_chunk.hpp"
|
||||
#include "Cubed/gameplay/server_player.hpp"
|
||||
#include "Cubed/tools/priority_thread_pool.hpp"
|
||||
#include "Cubed/tools/recent_queue.hpp"
|
||||
#include "Cubed/tools/thread_pool.hpp"
|
||||
#include "world/block_change.pb.h"
|
||||
@@ -26,7 +23,7 @@ class Session;
|
||||
class ServerWorld {
|
||||
public:
|
||||
enum class ThreadPoolKind { NET, GEN };
|
||||
ServerWorld(Config& config);
|
||||
ServerWorld();
|
||||
~ServerWorld();
|
||||
void stop();
|
||||
void handle_player_exit(const std::string& uuid);
|
||||
@@ -35,6 +32,7 @@ public:
|
||||
void update();
|
||||
void hot_reload();
|
||||
|
||||
void rebuild_world();
|
||||
int rendering_distance() const;
|
||||
void rendering_distance(int rendering_distance);
|
||||
void start_gen_thread();
|
||||
@@ -71,8 +69,7 @@ public:
|
||||
|
||||
bool set_block(const glm::ivec3& block_pos, unsigned id);
|
||||
|
||||
void sync_player_pos(const C2S_PlayerInfo& rsp);
|
||||
void sync_player_water_sound(const PlayerWaterSound& rsp);
|
||||
void sync_player_pos(const std::string& uuid, float x, float y, float z);
|
||||
void handle_player_login(const std::string& player_name,
|
||||
std::shared_ptr<Session> session);
|
||||
glm::vec3 get_player_pos(const std::string& uuid) const;
|
||||
@@ -119,12 +116,10 @@ private:
|
||||
|
||||
using uuid_acc = PlayerUUIDMap::accessor;
|
||||
using uuid_cacc = PlayerUUIDMap::const_accessor;
|
||||
|
||||
Config& m_config;
|
||||
|
||||
// key = uuid
|
||||
PlayerHashMap m_players;
|
||||
ChunkHashMap m_chunks;
|
||||
NewChunkVector m_new_chunks;
|
||||
|
||||
CaveCarver m_cave_carcer;
|
||||
RiverWorm m_river_worm;
|
||||
@@ -136,32 +131,34 @@ private:
|
||||
std::atomic<bool> m_could_gen{true};
|
||||
std::atomic<bool> m_gen_running{false};
|
||||
std::atomic<bool> m_need_gen_chunk{false};
|
||||
std::atomic<bool> m_is_rebuilding{false};
|
||||
std::atomic<bool> m_init{false};
|
||||
std::atomic<bool> m_stopped{false};
|
||||
std::atomic<int> m_rendering_distance{24};
|
||||
std::atomic<int> m_gen_pool_threads{0};
|
||||
std::atomic<int> m_net_pool_threads{0};
|
||||
std::atomic<int> m_max_threads{1};
|
||||
std::atomic<size_t> m_player_sum{0};
|
||||
|
||||
std::atomic<TickType> m_game_ticks{0};
|
||||
std::atomic<TickType> m_day_tick{6000};
|
||||
std::atomic<bool> m_tick_running{true};
|
||||
std::atomic<int> m_per_tick_time = DEFAULT_PER_TICK_TIME; // ms
|
||||
|
||||
std::shared_mutex m_new_chunk_mutex;
|
||||
mutable std::shared_mutex m_player_mutex;
|
||||
std::mutex m_need_gen_queue_mutex;
|
||||
std::condition_variable_any m_gen_cv;
|
||||
|
||||
RecentQueue<std::string> m_need_gen_queue;
|
||||
|
||||
std::atomic<std::shared_ptr<PriorityThreadPool>> m_gen_thread_pool;
|
||||
std::atomic<std::shared_ptr<ThreadPool>> m_gen_thread_pool;
|
||||
std::atomic<std::shared_ptr<ThreadPool>> m_net_thread_pool;
|
||||
|
||||
std::atomic<ChunkLoadStyle> m_chunk_load_style{ChunkLoadStyle::CENTER};
|
||||
|
||||
PlayerUUIDMap m_uuid_to_name;
|
||||
|
||||
tbb::concurrent_unordered_map<std::string, TickTimer> m_timers;
|
||||
tbb::concurrent_unordered_map<std::string, Timer> m_timers;
|
||||
tbb::concurrent_queue<PendingRequest> m_waiting_chunk_requests;
|
||||
tbb::concurrent_queue<std::unique_ptr<ServerChunk>> m_finished_queue;
|
||||
|
||||
@@ -173,7 +170,7 @@ private:
|
||||
const std::optional<std::string>& uuid);
|
||||
void sync_and_collect_missing_chunks(std::vector<ChunkPos>&,
|
||||
const ChunkPosSet&);
|
||||
void submit_new_chunks(const std::string& uuid, NewChunkVector& new_chunks);
|
||||
void submit_new_chunks(const std::string& uuid);
|
||||
// void wait_all_chunk_tasks();
|
||||
|
||||
void update_ref_count(const ChunkPosSet& old, const ChunkPosSet& now);
|
||||
@@ -185,9 +182,6 @@ private:
|
||||
int
|
||||
change_pool_threads(std::atomic<std::shared_ptr<ThreadPool>>& thread_pool,
|
||||
int threads);
|
||||
int change_pool_threads(
|
||||
std::atomic<std::shared_ptr<PriorityThreadPool>>& thread_pool,
|
||||
int threads);
|
||||
void send_server_stop();
|
||||
};
|
||||
} // namespace Cubed
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
#include "Cubed/gameplay/packet.hpp"
|
||||
|
||||
#include <asio.hpp>
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
namespace Cubed {
|
||||
|
||||
@@ -17,44 +17,20 @@ public:
|
||||
asio::io_context& io);
|
||||
~Session();
|
||||
void start();
|
||||
void send(Packet packet, int priority = 10);
|
||||
|
||||
void send(Packet packet);
|
||||
void close();
|
||||
const std::string& uuid() const;
|
||||
|
||||
private:
|
||||
struct Task {
|
||||
int priority = 10;
|
||||
std::uint64_t sequence = 0;
|
||||
Packet packet;
|
||||
Task(int p, std::uint64_t seq, Packet pac)
|
||||
: priority(p), sequence(seq), packet(std::move(pac)) {}
|
||||
};
|
||||
|
||||
struct TaskCompare {
|
||||
bool operator()(const Task& a, const Task& b) const {
|
||||
|
||||
if (a.priority != b.priority) {
|
||||
return a.priority > b.priority;
|
||||
}
|
||||
|
||||
return a.sequence > b.sequence;
|
||||
}
|
||||
};
|
||||
|
||||
static constexpr uint32_t MAX_PACKET_SIZE = 4 * 1024 * 1024;
|
||||
tcp::socket m_socket;
|
||||
std::vector<char> m_read_buffer;
|
||||
std::priority_queue<Task, std::vector<Task>, TaskCompare> m_write_queue;
|
||||
std::deque<Packet> m_write_queue;
|
||||
asio::strand<asio::io_context::executor_type> m_strand;
|
||||
std::string m_uuid;
|
||||
ServerWorld& m_server_world;
|
||||
std::atomic<bool> m_closed{false};
|
||||
|
||||
std::atomic_uint64_t m_sequence{0};
|
||||
|
||||
asio::awaitable<void> read_loop();
|
||||
|
||||
std::atomic<bool> m_closed{false};
|
||||
void do_write();
|
||||
};
|
||||
} // namespace Cubed
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
#pragma once
|
||||
#include "Cubed/primitive_data.hpp"
|
||||
#include "Cubed/render/vertex_array.hpp"
|
||||
#include "Cubed/render/vertex_buffer.hpp"
|
||||
|
||||
#include <atomic>
|
||||
#include <glad/glad.h>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
namespace Cubed {
|
||||
class ClientWorld;
|
||||
struct VertexData {
|
||||
std::vector<Vertex3D> m_vertices;
|
||||
std::unique_ptr<VertexBuffer> m_vbo;
|
||||
std::unique_ptr<VertexArray> m_vao;
|
||||
GLuint m_vbo = 0;
|
||||
GLuint m_vao = 0;
|
||||
std::atomic<std::size_t> m_sum{0};
|
||||
ClientWorld& m_world;
|
||||
VertexData(ClientWorld& world);
|
||||
|
||||
@@ -18,4 +18,19 @@ struct MouseState {
|
||||
bool right = false;
|
||||
};
|
||||
|
||||
struct KeyState {
|
||||
bool r = false;
|
||||
};
|
||||
|
||||
struct InputState {
|
||||
MoveState move_state;
|
||||
MouseState mouse_state;
|
||||
KeyState key_state;
|
||||
};
|
||||
|
||||
namespace Input {
|
||||
InputState& get_input_state();
|
||||
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -1,61 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/input/key.hpp"
|
||||
#include "Cubed/input/mouse.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
namespace Cubed {
|
||||
|
||||
struct MouseMoveEvent {
|
||||
float xpos;
|
||||
float ypos;
|
||||
|
||||
MouseMoveEvent(float x, float y) : xpos(x), ypos(y) {}
|
||||
};
|
||||
|
||||
struct MouseButtonEvent {
|
||||
MouseKey key;
|
||||
KeyAction action;
|
||||
|
||||
MouseButtonEvent(MouseKey k, KeyAction a) : key(k), action(a) {}
|
||||
};
|
||||
|
||||
struct MouseWheelEvent {
|
||||
float offset;
|
||||
|
||||
MouseWheelEvent(float o) : offset(o) {}
|
||||
};
|
||||
|
||||
struct KeyEvent {
|
||||
Key key;
|
||||
KeyAction action;
|
||||
|
||||
KeyEvent(Key k, KeyAction a) : key(k), action(a) {}
|
||||
};
|
||||
|
||||
struct TextInputEvent {
|
||||
std::string text;
|
||||
|
||||
TextInputEvent(std::string t) : text(std::move(t)) {}
|
||||
};
|
||||
|
||||
struct WindowResizeEvent {
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
struct FrameBufferResizeEvent {
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
using Event =
|
||||
std::variant<MouseMoveEvent, MouseButtonEvent, MouseWheelEvent, KeyEvent,
|
||||
TextInputEvent, WindowResizeEvent, FrameBufferResizeEvent>;
|
||||
|
||||
template <class... T> struct Overloaded : T... {
|
||||
using T::operator()...;
|
||||
};
|
||||
template <class... T> Overloaded(T...) -> Overloaded<T...>;
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -1,129 +0,0 @@
|
||||
#pragma once
|
||||
#ifdef DELETE
|
||||
#undef DELETE
|
||||
#endif
|
||||
namespace Cubed {
|
||||
enum class Key {
|
||||
// Letter keys
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
E,
|
||||
F,
|
||||
G,
|
||||
H,
|
||||
I,
|
||||
J,
|
||||
K,
|
||||
L,
|
||||
M,
|
||||
N,
|
||||
O,
|
||||
P,
|
||||
Q,
|
||||
R,
|
||||
S,
|
||||
T,
|
||||
U,
|
||||
V,
|
||||
W,
|
||||
X,
|
||||
Y,
|
||||
Z,
|
||||
|
||||
// Digit keys (main keyboard area)
|
||||
DIGIT_0,
|
||||
DIGIT_1,
|
||||
DIGIT_2,
|
||||
DIGIT_3,
|
||||
DIGIT_4,
|
||||
DIGIT_5,
|
||||
DIGIT_6,
|
||||
DIGIT_7,
|
||||
DIGIT_8,
|
||||
DIGIT_9,
|
||||
|
||||
// Function keys
|
||||
F1,
|
||||
F2,
|
||||
F3,
|
||||
F4,
|
||||
F5,
|
||||
F6,
|
||||
F7,
|
||||
F8,
|
||||
F9,
|
||||
F10,
|
||||
F11,
|
||||
F12,
|
||||
|
||||
// Control keys
|
||||
BACKSPACE,
|
||||
TAB,
|
||||
ENTER,
|
||||
ESCAPE,
|
||||
SPACE,
|
||||
CAPS_LOCK,
|
||||
NUM_LOCK,
|
||||
SCROLL_LOCK,
|
||||
|
||||
// Modifier keys
|
||||
LEFT_SHIFT,
|
||||
RIGHT_SHIFT,
|
||||
LEFT_CTRL,
|
||||
RIGHT_CTRL,
|
||||
LEFT_ALT,
|
||||
RIGHT_ALT,
|
||||
LEFT_SUPER,
|
||||
RIGHT_SUPER, // Windows / Command 键
|
||||
|
||||
// Navigation keys
|
||||
INSERT,
|
||||
DELETE,
|
||||
HOME,
|
||||
END,
|
||||
PAGE_UP,
|
||||
PAGE_DOWN,
|
||||
LEFT,
|
||||
RIGHT,
|
||||
UP,
|
||||
DOWN,
|
||||
|
||||
// Lock and system keys
|
||||
PRINT_SCREEN,
|
||||
PAUSE,
|
||||
|
||||
// Main keyboard area symbol keys
|
||||
GRAVE_ACCENT, // `
|
||||
MINUS, // -
|
||||
EQUALS, // =
|
||||
LEFT_BRACKET, // [
|
||||
RIGHT_BRACKET, // ]
|
||||
BACKSLASH, // \ /
|
||||
SEMICOLON, // ;
|
||||
APOSTROPHE, // '
|
||||
COMMA, // ,
|
||||
PERIOD, // .
|
||||
SLASH, // /
|
||||
|
||||
// Numpad area
|
||||
NUMPAD_0,
|
||||
NUMPAD_1,
|
||||
NUMPAD_2,
|
||||
NUMPAD_3,
|
||||
NUMPAD_4,
|
||||
NUMPAD_5,
|
||||
NUMPAD_6,
|
||||
NUMPAD_7,
|
||||
NUMPAD_8,
|
||||
NUMPAD_9,
|
||||
NUMPAD_ADD, // +
|
||||
NUMPAD_SUBTRACT, // -
|
||||
NUMPAD_MULTIPLY, // *
|
||||
NUMPAD_DIVIDE, // /
|
||||
NUMPAD_DECIMAL, // .
|
||||
NUMPAD_ENTER
|
||||
};
|
||||
enum class KeyAction { PRESS, RELEASE, REPEAT };
|
||||
} // namespace Cubed
|
||||
@@ -1,25 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
namespace Cubed {
|
||||
|
||||
enum class MouseKey {
|
||||
LEFT_BUTTON,
|
||||
RIGHT_BUTTON,
|
||||
MIDDLE_BUTTON,
|
||||
|
||||
BACK_BUTTON, // Side button back
|
||||
FORWARD_BUTTON, // Side button forward
|
||||
|
||||
WHEEL_UP,
|
||||
WHEEL_DOWN,
|
||||
WHEEL_LEFT,
|
||||
WHEEL_RIGHT,
|
||||
|
||||
EXTRA_BUTTON_1, // Additional programmable buttons
|
||||
EXTRA_BUTTON_2,
|
||||
EXTRA_BUTTON_3,
|
||||
EXTRA_BUTTON_4,
|
||||
EXTRA_BUTTON_5
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <format>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
namespace Cubed {
|
||||
|
||||
struct FormatArg {
|
||||
std::string name;
|
||||
std::string value;
|
||||
};
|
||||
template <typename T> FormatArg arg(std::string_view name, T&& value) {
|
||||
return {std::string(name), std::format("{}", std::forward<T>(value))};
|
||||
}
|
||||
|
||||
class Localization {
|
||||
public:
|
||||
Localization();
|
||||
static Localization& instance();
|
||||
|
||||
void load_language(std::string_view language);
|
||||
bool has(const std::string& key) const;
|
||||
template <typename... Args>
|
||||
std::string translate(const std::string& key, Args&&... args) {
|
||||
if constexpr (sizeof...(Args) == 0)
|
||||
return std::string{lookup(key)};
|
||||
std::string fmt{lookup(key)};
|
||||
(replace_all(fmt, "{" + args.name + "}", args.value), ...);
|
||||
return fmt;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, std::string> m_translations;
|
||||
std::string m_current_lang{"en_US"};
|
||||
std::string_view lookup(const std::string& key) const;
|
||||
static void replace_all(std::string& str, std::string_view from,
|
||||
std::string_view to);
|
||||
};
|
||||
|
||||
template <typename... Args>
|
||||
std::string tr(const std::string& key, Args&&... args) {
|
||||
return Localization::instance().translate(key, std::forward<Args>(args)...);
|
||||
}
|
||||
template <typename T>
|
||||
FormatArg tr_arg(const std::string& name, const std::string& key) {
|
||||
return {std::string(name), tr(key)};
|
||||
}
|
||||
} // namespace Cubed
|
||||
26
include/Cubed/map_table.hpp
Normal file
26
include/Cubed/map_table.hpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
// #include <string>
|
||||
// #include <unordered_map>
|
||||
// #include <vector>
|
||||
namespace Cubed {
|
||||
|
||||
class MapTable {
|
||||
private:
|
||||
/*
|
||||
static inline std::unordered_map<unsigned, std::string> id_to_name_map;
|
||||
static inline std::unordered_map<size_t, unsigned> name_to_id_map;
|
||||
static inline std::vector<std::string> item_id_to_name;
|
||||
*/
|
||||
public:
|
||||
// please using reference
|
||||
/*
|
||||
static std::string_view get_name_from_id(unsigned id);
|
||||
static unsigned get_id_from_name(const std::string& name);
|
||||
|
||||
static std::string_view item_name(unsigned id);
|
||||
static const std::vector<std::string>& item_map();
|
||||
*/
|
||||
static void init_map();
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -188,14 +188,13 @@ constexpr float CUBE_VER[24] = {0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0,
|
||||
constexpr int OUTLINE_CUBE_INDICES[24] = {0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6,
|
||||
6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7};
|
||||
|
||||
constexpr float SQUARE_VERTICES_TOP_LEFT[6][2] = {
|
||||
{0.0f, 0.0f}, // top left
|
||||
{0.0f, 1.0f}, // bottom left
|
||||
{1.0f, 1.0f}, // bottom right
|
||||
|
||||
{1.0f, 1.0f}, // bottom right
|
||||
{1.0f, 0.0f}, // top right
|
||||
{0.0f, 0.0f} // top left
|
||||
constexpr float SQUARE_VERTICES[6][2] = {
|
||||
{-0.5f, -0.5f}, // bottom left
|
||||
{-0.5f, 0.5f}, // top left
|
||||
{0.5f, 0.5f}, // top right
|
||||
{0.5f, 0.5f}, // top right
|
||||
{0.5f, -0.5f}, // bottom right
|
||||
{-0.5f, -0.5f} // bottom left
|
||||
};
|
||||
|
||||
constexpr float SQUARE_TEXTURE_POS[6][2] = {
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
#pragma once
|
||||
#include "Cubed/render/texture.hpp"
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <span>
|
||||
|
||||
enum class Attachment : GLenum {
|
||||
COLOR_ATTACHMENT0 = GL_COLOR_ATTACHMENT0,
|
||||
COLOR_ATTACHMENT1 = GL_COLOR_ATTACHMENT1,
|
||||
DEPTH_ATTACHMENT = GL_DEPTH_ATTACHMENT
|
||||
};
|
||||
|
||||
enum class FrameBufferType : GLenum {
|
||||
FRAMEBUFFER = GL_FRAMEBUFFER,
|
||||
READ_FRAMEBUFFER = GL_READ_FRAMEBUFFER,
|
||||
DRAW_FRAMEBUFFER = GL_DRAW_FRAMEBUFFER
|
||||
};
|
||||
|
||||
namespace Cubed {
|
||||
class FrameBuffer {
|
||||
public:
|
||||
FrameBuffer();
|
||||
~FrameBuffer();
|
||||
FrameBuffer(const FrameBuffer&) = delete;
|
||||
FrameBuffer(FrameBuffer&&) noexcept;
|
||||
FrameBuffer& operator=(const FrameBuffer&) = delete;
|
||||
FrameBuffer& operator=(FrameBuffer&&) noexcept;
|
||||
|
||||
void bind(FrameBufferType type = FrameBufferType::FRAMEBUFFER) const;
|
||||
GLuint id() const;
|
||||
|
||||
void attach(Attachment attachment, const Texture& texture,
|
||||
GLint level = 0) const;
|
||||
static void unbind();
|
||||
|
||||
bool check_status() const;
|
||||
|
||||
void draw_buffer(GLenum buf) const;
|
||||
void read_buffer(GLenum src) const;
|
||||
void draw_buffer(GLsizei n, const GLenum* bufs) const;
|
||||
void draw_buffer(std::span<const GLenum> bufs) const;
|
||||
|
||||
private:
|
||||
GLuint m_fbo = 0;
|
||||
};
|
||||
} // namespace Cubed
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user