Compare commits

...

36 Commits

Author SHA1 Message Date
c00f05aafd feat(renderer): smooth shadow sun direction transitions using quantized directions and slerp 2026-06-17 22:09:50 +08:00
dc1ef70231 fix(texture): set texture wrap mode to clamp to edge 2026-06-17 21:13:23 +08:00
e224110452 feat(renderer): add runtime shader and shadow mode controls
Introduce user-controllable shader on/off, shadow mode (rotated Poisson disk, 3x3 grid, or off), light cull face, and discard transparent in depth pass. Expose all settings in new dev panel "shader" tab. Move ambient strength slider to the new tab.
2026-06-17 20:16:20 +08:00
74b0aebc9f chore(world): add missing <numbers> include 2026-06-17 19:16:02 +08:00
be425a705c feat(dev-panel): add tick freeze toggle and fix TickType sign
Add checkbox to freeze tick advancement in dev panel.
Change TickType from unsigned long long to signed long long to prevent underflow.
2026-06-17 19:15:16 +08:00
31bf337f6f perf(shadow): increase depth map resolution and refine PCF sampling 2026-06-17 15:23:38 +08:00
662f10047a feat(renderer): add shadow mapping with PCF soft shadows
Introduce shadow mapping using a dedicated depth framebuffer and shader. The block fragment shader now performs percentage-closer filtering (PCF) with Poisson disk sampling and random rotation for soft shadows. The vertex shader outputs light-space coordinates. A new depth shader pair handles rendering from the light's perspective, discarding transparent fragments. The renderer sets up the light projection based on the camera position and sun direction, and applies the shadow factor to diffuse lighting. Day/night cycle can now be toggled off in the world server thread.
2026-06-16 22:27:08 +08:00
943c6f1f46 fix(game_time): use unsigned tick type and enforce positive tick speed 2026-06-16 18:51:47 +08:00
7ede49da72 feat(renderer): make ambient strength adjustable via dev panel 2026-06-16 18:44:59 +08:00
a4f92e3659 feat(world): add day/night cycle with server tick system 2026-06-16 16:17:47 +08:00
f43ef64691 feat(rendering): add basic diffuse and ambient lighting to block rendering 2026-06-16 13:53:47 +08:00
zhenyan121
f4114c2699 refactor: world generation (#17)
* refactor: use TBB for concurrent hash maps and parallelize chunk processing

* fix: tbb link fail

* refactor(chunk): remove biome check for caves in rivers and oceans

* refactor(random): replace std distributions with custom implementations

Avoid overhead and platform-dependent behavior of `<random>` distributions by using direct engine operations and integer arithmetic. This ensures deterministic, cross-platform results and improves performance.

* refactor(generation): use chunk seed for cave and river paths

- Use per-chunk seed instead of global path_id for cave and river generation.
- Remove unused m_sum variables and m_path_id members.
- Clamp river yaw within 10 degrees of initial direction.
- Fix river radius interpolation (use t instead of 1-t).
- Lower sea level from 64 to 63.
2026-06-14 11:36:37 +08:00
zhenyan121
932463663f feat: ocean (#16)
* feat(gameplay): add Ocean biome with water generation and heightmap adjustments

- Introduce Ocean biome enum, builder, and detection logic.
- Add ocean water building to all existing biomes and modify heightmap thresholds for low mountainous areas.
- Skip cave and river generation in Ocean (and River) biomes; avoid carving water blocks.
- Comment out border blending call and update block fill logic.

* fix(gameplay): re-enable border blending and protect water in cave gen

* refactor(generation): move ocean water build to later phase

* feat(block): add is_transitional property and refine border blending

* fix(block): set stone block as transitional

* fix(world): generate temporary chunks for surface blend neighbor data

* fix(gameplay): simplify block fill logic in blend_surface_blocks_borders

* refactor(tree): remove debug logging and unused include
2026-06-12 19:42:59 +08:00
zhenyan121
bac3df801b refactor: chunk render (#15)
* refactor(renderer): centralize VAO setup and rename init_underwater

* refactor(gameplay): replace VBO with VAO for vertex data

* fix(renderer): move depth test enable to world rendering

The `glEnable(GL_DEPTH_TEST)` call was incorrectly placed in the general `render()` function, affecting UI and text rendering. Moved it to the start of the world rendering loop to ensure depth testing is only active during 3D world pass.
2026-06-11 14:58:39 +08:00
zhenyan121
d0bc8d627f refactor: transparent render (#14)
* fix(renderer): defer uniform location retrieval and add view matrix in outline rendering

* refactor(gameplay): encapsulate per-type vertex data into VertexData struct

* feat(rendering): separate transparent blocks into discard and blend modes

* feat(renderer): implement order-independent transparency

* fix(shaders): reduce alpha discard threshold to 0.8
2026-06-11 12:21:19 +08:00
zhenyan121
2906106597 feat: water rendering (#13)
* refactor: update water texture

* feat(gameplay): implement transparent block rendering with depth sorting

* fix(world): use camera pos for distance calculations, make water passable

* refactor(player): use ivec3 for block pass check

* feat(camera): add underwater detection

* feat(renderer): add underwater effect with framebuffer post-processing

* feat(block): add gas property and refactor solid block check

* fix(assets): set leaf block transparency to false

* fix(block): set leaf as transparent
2026-05-30 15:11:40 +08:00
zhenyan121
a0139dd315 fix: msvc build fail (#12) 2026-05-28 21:55:44 +08:00
zhenyan121
5901ab7cd9 feat: grass (#11)
* feat: add grass texture and update grass_block texture

* feat: add block data

* feat: add blocks_tool

* feat: add sync info and change function in blocks_tools

* feat: add check and new function

* refactor: make block texture loading data-driven

* feat: add rendering for grass

* feat: passable grass

* feat: random grass place

* fix: memory leak in TextureManager::load_cross_plane_texture
2026-05-28 21:34:36 +08:00
zhenyan121
bbf8b4e969 refactor: river (#10)
* fix: correct snowy grass block texture

* refactor: river generation

* fix: water placement error due to interpolation

* perf: improve river naturalness

* feat: add river tab item

* fix: path truncation
2026-05-23 14:29:41 +08:00
zhenyan121
a54e87dbc6 refactor: terrain generation (#9)
* feat: add BlockType

* refactor: use fBM for heightmap generation

* feat: improve mountain realism

* refactor: adjust mountain spawn probability

* feat: add biome boundary blending

* refactor: remove resolve_biome_adjacency_conflict function

* feat: add snowy plain

* perf: speed up world generation

* refactor: lower overall terrain height
2026-05-23 10:33:52 +08:00
zhenyan121
1a26474a05 feat: add cave (#8)
* feat: add cave generate

* fix: incorrect blocks on cave surface

* fix: non-deterministic cave generator

* refactor: move all chunk generation to dedicated generation thread

* refactor: remove inital cave

* feat: add cave parameter adjustment

* refactor: adjust cave probability
2026-05-09 20:13:55 +08:00
zhenyan121
d986e03f9c fix: windows build fail (#7) 2026-05-03 19:45:14 +08:00
zhenyan121
9d200f31be refactor: chunk interpolate (#6)
* refactor: rewrite blend_heightmap_boundaries

* refactor: init_world

* fix: unnatural biome boundary transition
2026-05-03 16:02:01 +08:00
zhenyan121
a02bfad639 refactor: biome build (#5)
* refactor: rename Biome to BiomeType

* feat: add biome builder
2026-05-02 13:40:46 +08:00
zhenyan121
a63dfa7f47 feat: add river biome (#4)
* feat: add river biome

* fix: duplicate mountain terrain generation

* fix: safe_int_to_biome not include river
2026-05-01 19:18:46 +08:00
zhenyan121
d4d761b2aa Potential fix for code scanning alert no. 1: Workflow does not contain permissions (#3)
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-04-30 12:08:12 +08:00
zhenyan121
315c60e4a6 feat: block switching (#2)
* feat: add item tab item in dev panel

* feat: add block switching via mouse wheel
2026-04-30 11:53:35 +08:00
zhenyan121
9a8e76d25f refactor: set forest base y to 62 (#1) 2026-04-28 21:58:35 +08:00
14c942333c ci: upgrade clang image tag to latest 2026-04-28 12:46:01 +08:00
b88bc30756 ci: add find in include directory 2026-04-28 12:13:10 +08:00
a526d37f97 ci: use Docker instead of directly installing clang-format 2026-04-28 12:06:55 +08:00
fb86836e19 ci: upgrade clang-format version in CI 2026-04-28 09:38:22 +08:00
f2f00ce658 ci: add automated code style checking 2026-04-28 09:33:07 +08:00
611a795481 chore: add clang-format and pre-commit configuration 2026-04-28 09:22:55 +08:00
dc3be5a4bc refactor: adjust mountain frequency 2026-04-27 15:26:49 +08:00
932c11a646 fix: chunk conflict resolution not taking effort 2026-04-27 09:30:45 +08:00
148 changed files with 7344 additions and 2715 deletions

321
.clang-format Normal file
View File

@@ -0,0 +1,321 @@
---
Language: Cpp
AlignAfterOpenBracket: true
AccessModifierOffset: -4
AlignArrayOfStructures: None
AlignConsecutiveAssignments:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
AlignFunctionDeclarations: false
AlignFunctionPointers: false
PadOperators: true
AlignConsecutiveBitFields:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
AlignFunctionDeclarations: false
AlignFunctionPointers: false
PadOperators: false
AlignConsecutiveDeclarations:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
AlignFunctionDeclarations: true
AlignFunctionPointers: false
PadOperators: false
AlignConsecutiveMacros:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
AlignFunctionDeclarations: false
AlignFunctionPointers: false
PadOperators: false
AlignConsecutiveShortCaseStatements:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCaseArrows: false
AlignCaseColons: false
AlignConsecutiveTableGenBreakingDAGArgColons:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
AlignFunctionDeclarations: false
AlignFunctionPointers: false
PadOperators: false
AlignConsecutiveTableGenCondOperatorColons:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
AlignFunctionDeclarations: false
AlignFunctionPointers: false
PadOperators: false
AlignConsecutiveTableGenDefinitionColons:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
AlignFunctionDeclarations: false
AlignFunctionPointers: false
PadOperators: false
AlignEscapedNewlines: Right
AlignOperands: Align
AlignTrailingComments:
AlignPPAndNotPP: true
Kind: Always
OverEmptyLines: 0
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowBreakBeforeNoexceptSpecifier: Never
AllowBreakBeforeQtProperty: false
AllowShortBlocksOnASingleLine: Never
AllowShortCaseExpressionOnASingleLine: true
AllowShortCaseLabelsOnASingleLine: false
AllowShortCompoundRequirementOnASingleLine: true
AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: false
AllowShortNamespacesOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AttributeMacros:
- __capability
BinPackArguments: true
BinPackLongBracedList: true
BinPackParameters: BinPack
BitFieldColonSpacing: Both
BracedInitializerIndentWidth: -1
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterExternBlock: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakAdjacentStringLiterals: true
BreakAfterAttributes: Leave
BreakAfterJavaFieldAnnotations: false
BreakAfterOpenBracketBracedList: false
BreakAfterOpenBracketFunction: false
BreakAfterOpenBracketIf: false
BreakAfterOpenBracketLoop: false
BreakAfterOpenBracketSwitch: false
BreakAfterReturnType: None
BreakArrays: true
BreakBeforeBinaryOperators: None
BreakBeforeCloseBracketBracedList: false
BreakBeforeCloseBracketFunction: false
BreakBeforeCloseBracketIf: false
BreakBeforeCloseBracketLoop: false
BreakBeforeCloseBracketSwitch: false
BreakBeforeConceptDeclarations: Always
BreakBeforeBraces: Attach
BreakBeforeInlineASMColon: OnlyMultiline
BreakBeforeTemplateCloser: false
BreakBeforeTernaryOperators: true
BreakBinaryOperations: Never
BreakConstructorInitializers: BeforeColon
BreakFunctionDefinitionParameters: false
BreakInheritanceList: BeforeColon
BreakStringLiterals: true
BreakTemplateDeclarations: MultiLine
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: AlignFirstComment
DerivePointerAlignment: false
DisableFormat: false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
EnumTrailingComma: Leave
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IfMacros:
- KJ_IF_MAYBE
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
SortPriority: 0
CaseSensitive: false
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
SortPriority: 0
CaseSensitive: false
- Regex: '.*'
Priority: 1
SortPriority: 0
CaseSensitive: false
IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentAccessModifiers: false
IndentCaseBlocks: false
IndentCaseLabels: false
IndentExportBlock: true
IndentExternBlock: AfterExternBlock
IndentGotoLabels: true
IndentPPDirectives: None
IndentRequiresClause: true
IndentWidth: 4
IndentWrappedFunctionNames: false
InsertBraces: false
InsertNewlineAtEOF: false
InsertTrailingCommas: None
IntegerLiteralSeparator:
Binary: 0
BinaryMinDigitsInsert: 0
BinaryMaxDigitsRemove: 0
Decimal: 0
DecimalMinDigitsInsert: 0
DecimalMaxDigitsRemove: 0
Hex: 0
HexMinDigitsInsert: 0
HexMaxDigitsRemove: 0
BinaryMinDigits: 0
DecimalMinDigits: 0
HexMinDigits: 0
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLines:
AtEndOfFile: false
AtStartOfBlock: true
AtStartOfFile: true
KeepFormFeed: false
LambdaBodyIndentation: Signature
LineEnding: DeriveLF
MacroBlockBegin: ''
MacroBlockEnd: ''
MainIncludeChar: Quote
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
NumericLiteralCase:
ExponentLetter: Leave
HexDigit: Leave
Prefix: Leave
Suffix: Leave
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
OneLineFormatOffRegex: ''
PackConstructorInitializers: BinPack
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakBeforeMemberAccess: 150
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakOpenParenthesis: 0
PenaltyBreakScopeResolution: 500
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyIndentedWhitespace: 0
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Left
PPIndentWidth: -1
QualifierAlignment: Leave
ReferenceAlignment: Pointer
ReflowComments: Always
RemoveBracesLLVM: false
RemoveEmptyLinesInUnwrappedLines: false
RemoveParentheses: Leave
RemoveSemicolon: false
RequiresClausePosition: OwnLine
RequiresExpressionIndentation: OuterScope
SeparateDefinitionBlocks: Leave
ShortNamespaceLines: 1
SkipMacroDefinitionBody: false
SortIncludes:
Enabled: true
IgnoreCase: false
IgnoreExtension: false
SortJavaStaticImport: Before
SortUsingDeclarations: LexicographicNumeric
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterOperatorKeyword: false
SpaceAfterTemplateKeyword: true
SpaceAroundPointerQualifiers: Default
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeJsonColon: false
SpaceBeforeParens: ControlStatements
SpaceBeforeParensOptions:
AfterControlStatements: true
AfterForeachMacros: true
AfterFunctionDefinitionName: false
AfterFunctionDeclarationName: false
AfterIfMacros: true
AfterNot: false
AfterOverloadedOperator: false
AfterPlacementOperator: true
AfterRequiresInClause: false
AfterRequiresInExpression: false
BeforeNonEmptyParentheses: false
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBraces: Never
SpacesBeforeTrailingComments: 1
SpacesInAngles: Never
SpacesInContainerLiterals: true
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: -1
SpacesInParens: Never
SpacesInParensOptions:
ExceptDoubleParentheses: false
InCStyleCasts: false
InConditionalStatements: false
InEmptyParentheses: false
Other: false
SpacesInSquareBrackets: false
Standard: Latest
StatementAttributeLikeMacros:
- Q_EMIT
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TableGenBreakInsideDAGArg: DontBreak
TabWidth: 8
UseTab: Never
VerilogBreakBetweenInstancePorts: true
WhitespaceSensitiveMacros:
- BOOST_PP_STRINGIZE
- CF_SWIFT_NAME
- NS_SWIFT_NAME
- PP_STRINGIZE
- STRINGIZE
WrapNamespaceBodyWithEmptyLines: Leave
...

3
.clang-format-ignore Normal file
View File

@@ -0,0 +1,3 @@
third_party/
build/
vendor/

17
.github/workflows/format-check.yml vendored Normal file
View File

@@ -0,0 +1,17 @@
# .github/workflows/format-check.yml
name: Code Format Check
on: [push, pull_request]
permissions:
contents: read
jobs:
formatting:
runs-on: ubuntu-latest
container: silkeh/clang:latest
steps:
- uses: actions/checkout@v4
- name: Run clang-format
run: |
find src include -name '*.cpp' -o -name '*.h' -print0 | xargs -0 clang-format --dry-run --Werror

1
.gitignore vendored
View File

@@ -41,3 +41,4 @@ CMakeError.log
*~ *~
.DS_Store .DS_Store
assets/config.toml assets/config.toml
.venv/

8
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,8 @@
repos:
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: "v22.1.4"
hooks:
- id: clang-format
args: ["--style=file"]
types_or: ["c++", "c"]
exclude: '^third_party/.*$'

1
.python-version Normal file
View File

@@ -0,0 +1 @@
3.14

View File

@@ -58,6 +58,21 @@ if (WIN32)
if(TARGET freetype) if(TARGET freetype)
add_library(Freetype::Freetype ALIAS freetype) add_library(Freetype::Freetype ALIAS freetype)
endif() endif()
set(_BUILD_SHARED_LIBS_SAVED ${BUILD_SHARED_LIBS})
set(BUILD_SHARED_LIBS ON)
FetchContent_Declare(
onetbb
GIT_REPOSITORY https://github.com/uxlfoundation/oneTBB.git
GIT_TAG v2023.0.0
)
set(BUILD_TESTING OFF CACHE BOOL "Build tests" FORCE)
set(TBB_TEST OFF CACHE BOOL "Build TBB tests" FORCE)
FetchContent_MakeAvailable(onetbb)
set(BUILD_SHARED_LIBS ${_BUILD_SHARED_LIBS_SAVED})
unset(_BUILD_SHARED_LIBS_SAVED)
endif() endif()
FetchContent_Declare( FetchContent_Declare(
@@ -83,7 +98,6 @@ FetchContent_MakeAvailable(tomlplusplus)
add_subdirectory(third_party/imgui) add_subdirectory(third_party/imgui)
set(INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include) set(INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include)
add_executable(${PROJECT_NAME} add_executable(${PROJECT_NAME}
@@ -111,20 +125,34 @@ add_executable(${PROJECT_NAME}
src/tools/perlin_noise.cpp src/tools/perlin_noise.cpp
src/ui/text.cpp src/ui/text.cpp
src/window.cpp src/window.cpp
src/gameplay/builders/biome_builder.cpp
src/gameplay/builders/plain_builder.cpp
src/gameplay/builders/mountain_builder.cpp
src/gameplay/builders/river_builder.cpp
src/gameplay/builders/desert_builder.cpp
src/gameplay/builders/forest_builder.cpp
src/gameplay/cave_carver.cpp
src/gameplay/cave_path.cpp
src/gameplay/builders/snowy_plain_builder.cpp
src/gameplay/river_worm.cpp
src/gameplay/river_path.cpp
src/block.cpp
src/gameplay/vertex_data.cpp
src/gameplay/builders/ocean_builder.cpp
) )
if(CMAKE_BUILD_TYPE STREQUAL "Debug") if(CMAKE_BUILD_TYPE STREQUAL "Debug")
message(STATUS "Building with AddressSanitizer enabled for target: ${PROJECT_NAME}") message(STATUS "Building with AddressSanitizer enabled for target: ${PROJECT_NAME}")
target_compile_options(${PROJECT_NAME} PRIVATE target_compile_options(${PROJECT_NAME} PRIVATE
-fsanitize=address #-fsanitize=address
#-fsanitize=thread #-fsanitize=thread
-fno-omit-frame-pointer -fno-omit-frame-pointer
-g -g
) )
target_link_options(${PROJECT_NAME} PRIVATE target_link_options(${PROJECT_NAME} PRIVATE
-fsanitize=address #-fsanitize=address
#-fsanitize=thread #-fsanitize=thread
) )
@@ -150,10 +178,11 @@ target_link_libraries(${PROJECT_NAME}
Freetype::Freetype Freetype::Freetype
tomlplusplus::tomlplusplus tomlplusplus::tomlplusplus
imgui imgui
tbb
) )
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
target_link_libraries(${PROJECT_NAME} PRIVATE tbb) # target_link_libraries(${PROJECT_NAME} PRIVATE tbb)
endif() endif()
if (UNIX AND NOT APPLE) if (UNIX AND NOT APPLE)
@@ -173,3 +202,19 @@ if (UNIX AND NOT APPLE)
target_compile_options(${PROJECT_NAME} PRIVATE ${EGL_CFLAGS_OTHER} ${Wayland_CFLAGS_OTHER}) target_compile_options(${PROJECT_NAME} PRIVATE ${EGL_CFLAGS_OTHER} ${Wayland_CFLAGS_OTHER})
endif() endif()
if (WIN32)
foreach(TBB_LIB IN ITEMS tbb tbbmalloc tbbmalloc_proxy)
if(TARGET ${TBB_LIB})
add_custom_command(
TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:${TBB_LIB}>
$<TARGET_FILE_DIR:${PROJECT_NAME}>
COMMENT "Copying ${TBB_LIB}.dll"
)
else()
message(STATUS "Target ${TBB_LIB} not found, skipping copy")
endif()
endforeach()
endif()

View File

@@ -0,0 +1,10 @@
id = 0
is_blend = false
is_cross_plane = false
is_discard = true
is_gas = true
is_liquid = false
is_passable = true
is_transitional = false
is_transparent = true
name = 'air'

View File

@@ -0,0 +1,10 @@
id = 2
is_blend = false
is_cross_plane = false
is_discard = false
is_gas = false
is_liquid = false
is_passable = false
is_transitional = true
is_transparent = false
name = 'dirt'

View File

@@ -0,0 +1,10 @@
id = 9
is_blend = false
is_cross_plane = true
is_discard = true
is_gas = false
is_liquid = false
is_passable = true
is_transitional = false
is_transparent = true
name = 'grass'

View File

@@ -0,0 +1,10 @@
id = 1
is_blend = false
is_cross_plane = false
is_discard = false
is_gas = false
is_liquid = false
is_passable = false
is_transitional = true
is_transparent = false
name = 'grass_block'

View File

@@ -0,0 +1,10 @@
id = 6
is_blend = false
is_cross_plane = false
is_discard = true
is_gas = false
is_liquid = false
is_passable = false
is_transitional = false
is_transparent = true
name = 'leaf'

View File

@@ -0,0 +1,10 @@
id = 5
is_blend = false
is_cross_plane = false
is_discard = false
is_gas = false
is_liquid = false
is_passable = false
is_transitional = false
is_transparent = false
name = 'log'

View File

@@ -0,0 +1,10 @@
id = 4
is_blend = false
is_cross_plane = false
is_discard = false
is_gas = false
is_liquid = false
is_passable = false
is_transitional = true
is_transparent = false
name = 'sand'

View File

@@ -0,0 +1,10 @@
id = 8
is_blend = false
is_cross_plane = false
is_discard = false
is_gas = false
is_liquid = false
is_passable = false
is_transitional = true
is_transparent = false
name = 'snowy_grass_block'

View File

@@ -0,0 +1,10 @@
id = 3
is_blend = false
is_cross_plane = false
is_discard = false
is_gas = false
is_liquid = false
is_passable = false
is_transitional = true
is_transparent = false
name = 'stone'

View File

@@ -0,0 +1,10 @@
name = "template"
id = 0
is_liquid = false
is_gas = false
is_passable = false
is_cross_plane = false
is_transparent = false
is_discard = false
is_blend = false
is_transitional = false

View File

@@ -0,0 +1,10 @@
id = 7
is_blend = true
is_cross_plane = false
is_discard = false
is_gas = false
is_liquid = true
is_passable = true
is_transitional = false
is_transparent = true
name = 'water'

View File

@@ -0,0 +1,28 @@
#version 460
layout (location = 0) out vec4 accum;
layout (location = 1) out float reveal;
in vec2 tc;
flat in int tex_layer;
in float v_depth;
layout (binding = 0) uniform sampler2DArray samp;
float weight(float z, float a) {
float intermediate = 0.03 / (1e-5 + pow(z / 200.0, 4.0));
return a * clamp(intermediate, 1e-2, 3e2);
}
void main() {
vec4 color = texture(samp, vec3(tc, tex_layer));
float alpha = color.a;
if (alpha < 1e-4) discard;
float w = weight(v_depth, alpha);
accum = vec4(color.rgb * alpha * w, alpha * w);
reveal = alpha;
}

View File

@@ -0,0 +1,21 @@
#version 460
layout (location = 0) in vec3 pos;
layout (location = 1) in vec2 texCoord;
layout (location = 2) in float layer;
out vec2 tc;
flat out int tex_layer;
out float v_depth;
uniform mat4 mv_matrix;
uniform mat4 proj_matrix;
void main(void) {
vec4 view_pos = mv_matrix * vec4(pos, 1.0);
gl_Position = proj_matrix * view_pos;
tc = texCoord;
tex_layer = int(layer);
v_depth = -view_pos.z;
}

View File

@@ -0,0 +1,19 @@
#version 460
uniform sampler2D u_accumTex;
uniform sampler2D u_revealTex;
in vec2 TexCoord;
out vec4 FragColor;
void main() {
vec4 a = texture(u_accumTex, TexCoord);
float r = texture(u_revealTex, TexCoord).r;
if (a.a < 1e-4) discard;
vec3 color = a.rgb / max(a.a, 1e-5);
float transmittance = r;
float opacity = 1.0 - transmittance;
FragColor = vec4(color * opacity, opacity);
}

View File

@@ -0,0 +1,11 @@
#version 460
layout (location = 0) in vec2 pos;
layout (location = 1) in vec2 texCoord;
out vec2 TexCoord;
void main() {
gl_Position = vec4(pos.x, pos.y, 0.0, 1.0);
TexCoord = texCoord;
}

View File

@@ -1,15 +1,125 @@
#version 460 #version 460
in vec2 tc; in vec2 tc;
in vec3 normal;
in vec3 vert_pos;
in vec4 FragPosLightSpace;
flat in int tex_layer; flat in int tex_layer;
out vec4 color; out vec4 color;
layout (binding = 0) uniform sampler2D shadowMap;
layout (binding = 1) uniform sampler2DArray samp;
uniform float ambientStrength;
uniform vec3 sunlightColor;
uniform vec3 sunlightDir;
uniform bool shader_on;
uniform int shadowMode;
const vec2 poissonDisk[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)
);
float random(vec3 seed) {
return fract(sin(dot(seed, vec3(12.9898,78.233,45.5432))) * 43758.5453);
}
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 =
max(
0.0003,
0.001 * (1.0 - dot(norm, lightDir))
);
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;
const int samples = 8;
for (int i = 0; i < samples; ++i) {
vec2 offset = rot * poissonDisk[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 {
float pcfDepth =
texture(shadowMap, projCoords.xy).r;
shadow =
currentDepth - bias > pcfDepth
? 1.0
: 0.0;
}
return shadow;
}
layout (binding = 0) uniform sampler2DArray samp;
void main(void) { void main(void) {
color = texture(samp, vec3(tc, tex_layer)); vec4 objectColor = texture(samp, vec3(tc, tex_layer));
if (color.a < 0.5) {
if (objectColor.a < 0.8) {
discard; discard;
} }
if (!shader_on) {
color = objectColor;
return;
}
vec3 lightDir = normalize(-sunlightDir);
vec3 ambient = ambientStrength * sunlightColor;
vec3 norm = normalize(normal);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * sunlightColor;
float shadow = ShadowCalculation(FragPosLightSpace, norm, lightDir);
color = vec4((ambient + (1.0 - shadow) * (diffuse)) * objectColor.rgb, objectColor.a);
//color = varyingColor; //color = varyingColor;
} }

View File

@@ -3,8 +3,12 @@
layout (location = 0) in vec3 pos; layout (location = 0) in vec3 pos;
layout (location = 1) in vec2 texCoord; layout (location = 1) in vec2 texCoord;
layout (location = 2) in float layer; layout (location = 2) in float layer;
layout (location = 3) in vec3 aNormal;
out vec2 tc; out vec2 tc;
out vec3 normal;
out vec3 vert_pos;
flat out int tex_layer; flat out int tex_layer;
out vec4 FragPosLightSpace;
mat4 buildRotateX(float rad); mat4 buildRotateX(float rad);
mat4 buildRotateY(float rad); mat4 buildRotateY(float rad);
@@ -13,13 +17,21 @@ mat4 buildTranslate(float x, float y, float z);
uniform mat4 mv_matrix; uniform mat4 mv_matrix;
uniform mat4 proj_matrix; uniform mat4 proj_matrix;
uniform mat4 norm_matrix;
uniform mat4 lightSpaceMatrix;
void main(void) { void main(void) {
gl_Position = proj_matrix * mv_matrix * vec4(pos, 1.0); vec4 viewPos = mv_matrix * vec4(pos, 1.0);
vert_pos = pos;
tc = texCoord; tc = texCoord;
tex_layer = int(layer); tex_layer = int(layer);
normal = mat3(norm_matrix) * aNormal;
FragPosLightSpace = lightSpaceMatrix * vec4(pos, 1.0);
gl_Position = proj_matrix * viewPos;
} }
mat4 buildTranslate(float x, float y, float z) { mat4 buildTranslate(float x, float y, float z) {

View File

@@ -0,0 +1,16 @@
#version 460
in vec2 tc;
flat in int tex_layer;
layout (binding = 1) uniform sampler2DArray samp;
uniform bool is_discard_tranparent;
void main() {
if (is_discard_tranparent) {
vec4 texColor = texture(samp, vec3(tc, tex_layer));
if (texColor.a < 0.8)
discard;
}
//gl_FragDepth = gl_FragCoord.z;
}

View File

@@ -0,0 +1,12 @@
#version 460
layout (location = 0) in vec3 pos;
layout (location = 1) in vec2 texCoord;
layout (location = 2) in float layer;
uniform mat4 lightSpaceMatrix;
out vec2 tc;
flat out int tex_layer;
void main() {
tc = texCoord;
tex_layer = int(layer);
gl_Position = lightSpaceMatrix * vec4(pos, 1.0);
}

View File

@@ -2,8 +2,10 @@
out vec4 frag_color; out vec4 frag_color;
uniform vec3 color;
void main(void) { void main(void) {
frag_color = vec4(0.529, 0.808, 0.922, 1.0); frag_color = vec4(color, 1.0);
} }

View File

@@ -0,0 +1,35 @@
#version 460
in vec2 TexCoord;
out vec4 FragColor;
uniform sampler2D u_sceneTexture;
uniform float u_time;
uniform bool u_underwater;
uniform vec3 u_waterColor;
uniform float u_fogDensity;
void main() {
vec4 original = texture(u_sceneTexture, TexCoord);
if (!u_underwater) {
FragColor = original;
return;
}
vec2 distoredUV = TexCoord;
float strength = 0.003;
distoredUV.x += sin(TexCoord.y * 15.0 + u_time * 5.0) * strength;
distoredUV.y += cos(TexCoord.x * 15.0 + u_time * 4.3) * strength;
distoredUV = clamp(distoredUV, 0.001, 0.999);
vec4 distorted = texture(u_sceneTexture, distoredUV);
float caustic = 0.9 + 0.1 * sin(TexCoord.x * 20.0 + u_time) * cos(TexCoord.y * 20.0 + u_time * 1.2);
vec3 causticLight = vec3(caustic, caustic * 0.95, caustic * 0.9);
//vec3 causticLight = vec3(1.0);
float fogFactor = clamp(1.0 - (TexCoord.y * u_fogDensity * 10.0), 0.0, 1.0);
vec3 mixed = mix(u_waterColor, distorted.rgb * causticLight, fogFactor);
FragColor = vec4(mixed, 1.0);
}

View File

@@ -0,0 +1,11 @@
#version 460
layout (location = 0) in vec2 pos;
layout (location = 1) in vec2 texCoord;
out vec2 TexCoord;
void main() {
gl_Position = vec4(pos.x, pos.y, 0.0, 1.0);
TexCoord = texCoord;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 563 B

After

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 563 B

After

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 563 B

After

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 563 B

After

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 399 B

After

Width:  |  Height:  |  Size: 381 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 568 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 568 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 568 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 568 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 882 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 499 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 890 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 874 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 877 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 914 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 915 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 874 B

View File

@@ -3,17 +3,12 @@
namespace Cubed { namespace Cubed {
struct AABB { struct AABB {
glm::vec3 min{0.0f, 0.0f, 0.0f}; glm::vec3 min{0.0f, 0.0f, 0.0f};
glm::vec3 max{0.0f, 0.0f, 0.0f}; glm::vec3 max{0.0f, 0.0f, 0.0f};
AABB(glm::vec3 min_point, glm::vec3 max_point): AABB(glm::vec3 min_point, glm::vec3 max_point)
min(min_point), : min(min_point), max(max_point) {}
max(max_point)
{
}
bool intersects(const AABB& other) const { bool intersects(const AABB& other) const {
return (min.x <= other.max.x && max.x >= other.min.x) && return (min.x <= other.max.x && max.x >= other.min.x) &&
@@ -22,4 +17,4 @@ struct AABB {
} }
}; };
} } // namespace Cubed

View File

@@ -1,24 +1,28 @@
#pragma once #pragma once
#define GLFW_INCLUDE_NONE
#include <Cubed/camera.hpp> #include "Cubed/camera.hpp"
#include <Cubed/dev_panel.hpp> #include "Cubed/dev_panel.hpp"
#include <Cubed/gameplay/world.hpp> #include "Cubed/gameplay/world.hpp"
#include <Cubed/input.hpp> #include "Cubed/renderer.hpp"
#include <Cubed/renderer.hpp> #include "Cubed/texture_manager.hpp"
#include <Cubed/texture_manager.hpp> #include "Cubed/window.hpp"
#include <Cubed/window.hpp>
namespace Cubed { namespace Cubed {
class App { class App {
public: public:
App(); App();
~App(); ~App();
static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos); static void cursor_position_callback(GLFWwindow* window, double xpos,
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods); double ypos);
static void mouse_button_callback(GLFWwindow* window, int button, int action, int mods); static void key_callback(GLFWwindow* window, int key, int scancode,
int action, int mods);
static void mouse_button_callback(GLFWwindow* window, int button,
int action, int mods);
static void window_focus_callback(GLFWwindow* window, int focused); static void window_focus_callback(GLFWwindow* window, int focused);
static void window_reshape_callback(GLFWwindow* window, int new_width, int new_height); static void window_reshape_callback(GLFWwindow* window, int new_width,
static void mouse_scroll_callback(GLFWwindow* window, double xoffset, double yoffset); int new_height);
static void mouse_scroll_callback(GLFWwindow* window, double xoffset,
double yoffset);
static void cursor_enter_callback(GLFWwindow* window, int entered); static void cursor_enter_callback(GLFWwindow* window, int entered);
static void char_callback(GLFWwindow* window, unsigned int ch); static void char_callback(GLFWwindow* window, unsigned int ch);
static int start_cubed_application(int argc, char** argv); static int start_cubed_application(int argc, char** argv);
@@ -34,7 +38,6 @@ public:
Window& window(); Window& window();
World& world(); World& world();
private: private:
Camera m_camera; Camera m_camera;
TextureManager m_texture_manager; TextureManager m_texture_manager;
@@ -62,4 +65,4 @@ private:
void update(); void update();
}; };
} } // namespace Cubed

View File

@@ -1,27 +1,24 @@
#pragma once #pragma once
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
namespace Cubed { namespace Cubed {
class Player; class Player;
class Camera { class Camera {
private: private:
bool m_firse_mouse = true; bool m_firse_mouse = true;
Player* m_player; Player* m_player;
float m_last_mouse_x, m_last_mouse_y; float m_last_mouse_x, m_last_mouse_y;
glm::vec3 m_camera_pos; glm::vec3 m_camera_pos;
bool m_under_water = false;
public: public:
Camera(); Camera();
void update_move_camera(); void update_move_camera();
@@ -33,8 +30,9 @@ public:
const glm::mat4 get_camera_lookat() const; const glm::mat4 get_camera_lookat() const;
const glm::vec3& get_camera_pos() const; const glm::vec3& get_camera_pos() const;
bool is_under_water() const;
glm::vec3 get_camera_front() const;
}; };
} } // namespace Cubed

View File

@@ -1,22 +1,16 @@
#pragma once #pragma once
#include <toml++/toml.hpp> #include "Cubed/tools/cubed_assert.hpp"
#include <Cubed/tools/cubed_assert.hpp> #include <toml++/toml.hpp>
namespace Cubed { namespace Cubed {
template <typename T> template <typename T>
concept TomlValueType = concept TomlValueType =
std::same_as<T, int> || std::same_as<T, int> || std::same_as<T, bool> || std::same_as<T, double> ||
std::same_as<T, bool> || std::same_as<T, const char*> || std::same_as<T, toml::date> ||
std::same_as<T, double> || std::same_as<T, toml::time> || std::same_as<T, toml::date_time> ||
std::same_as<T, const char*> || std::same_as<T, std::string>;
std::same_as<T, toml::date> ||
std::same_as<T, toml::time> ||
std::same_as<T, toml::date_time> ||
std::same_as<T, std::string>
;
class Config { class Config {
public: public:
@@ -30,8 +24,7 @@ public:
void load_or_create_config(); void load_or_create_config();
void save_to_file(); void save_to_file();
template <TomlValueType T> template <TomlValueType T> T get(std::string_view key) const {
T get(std::string_view key) const{
size_t cur = 0; size_t cur = 0;
auto pos = key.find('.'); auto pos = key.find('.');
const toml::table* table = &m_tbl; const toml::table* table = &m_tbl;
@@ -67,8 +60,7 @@ public:
std::abort(); std::abort();
} }
} }
template <typename T> template <typename T> void set(std::string_view key, T&& val) {
void set(std::string_view key, T&& val) {
if constexpr (!TomlValueType<std::decay_t<T>>) { if constexpr (!TomlValueType<std::decay_t<T>>) {
static_assert(false, "Type Not Support"); static_assert(false, "Type Not Support");
} }
@@ -90,7 +82,6 @@ public:
auto [it, inserted] = table->insert_or_assign(s, toml::table{}); auto [it, inserted] = table->insert_or_assign(s, toml::table{});
table = it->second.as_table(); table = it->second.as_table();
} }
} }
std::string_view n_key = key.substr(cur); std::string_view n_key = key.substr(cur);
if (n_key.empty()) { if (n_key.empty()) {
@@ -99,21 +90,18 @@ public:
std::abort(); std::abort();
} }
table->insert_or_assign(n_key, std::forward<T>(val)); table->insert_or_assign(n_key, std::forward<T>(val));
} }
template <typename T> template <typename T> void set_and_save(std::string_view key, T&& val) {
void set_and_save(std::string_view key, T&& val) {
set(key, std::forward(val)); set(key, std::forward(val));
save_to_file(); save_to_file();
} }
toml::node_view<toml::node> val_view(std::string_view key); toml::node_view<toml::node> val_view(std::string_view key);
private: private:
toml::table m_tbl; toml::table m_tbl;
constexpr static inline std::string_view CONGIF_PATH = ASSETS_PATH"config.toml"; constexpr static inline std::string_view CONGIF_PATH =
ASSETS_PATH "config.toml";
void create_config(); void create_config();
}; };
} } // namespace Cubed

View File

@@ -1,11 +1,13 @@
#pragma once #pragma once
#include "Cubed/gameplay/chunk_pos.hpp"
#include <array> #include <array>
namespace Cubed { namespace Cubed {
constexpr int WORLD_SIZE_Y = 256; constexpr int WORLD_SIZE_Y = 256;
constexpr int CHUCK_SIZE = 16; constexpr int CHUNK_SIZE = 16;
constexpr int SEA_LEVEL = 63;
constexpr int MAX_BLOCK_NUM = 7;
constexpr int MAX_UI_NUM = 1; constexpr int MAX_UI_NUM = 1;
constexpr int MAX_BLOCK_STATUS = 1; constexpr int MAX_BLOCK_STATUS = 1;
constexpr int MAX_BIOME_SUM = 4; constexpr int MAX_BIOME_SUM = 4;
@@ -14,14 +16,20 @@ constexpr int MAX_CHARACTER = 128;
constexpr int PRE_LOAD_DISTANCE = 24; constexpr int PRE_LOAD_DISTANCE = 24;
constexpr int MAX_DISTANCE = 128; constexpr int MAX_DISTANCE = 128;
constexpr int CROSS_PLANE_DISTANCE = 8;
constexpr float DEFAULT_FOV = 70.0f; constexpr float DEFAULT_FOV = 70.0f;
constexpr float DEFAULT_MAX_WALK_SPEED = 4.5f; constexpr float DEFAULT_MAX_WALK_SPEED = 4.5f;
constexpr float DEFAULT_MAX_RUN_SPEED = 7.0f; constexpr float DEFAULT_MAX_RUN_SPEED = 7.0f;
constexpr float DEFAULT_ACCELERATION = 10.0f; constexpr float DEFAULT_ACCELERATION = 10.0f;
constexpr float DEFAULT_DECELERATION = 15.0f; constexpr float DEFAULT_DECELERATION = 15.0f;
constexpr float DEFAULT_G = 22.5f; constexpr float DEFAULT_G = 22.5f;
constexpr int SIZE_X = CHUNK_SIZE;
constexpr int SIZE_Y = WORLD_SIZE_Y;
constexpr int SIZE_Z = CHUNK_SIZE;
using HeightMapArray = std::array<std::array<float, CHUCK_SIZE>, CHUCK_SIZE>; constexpr ChunkPos CHUNK_DIR[]{{1, 0}, {-1, 0}, {0, 1}, {0, -1},
{1, 1}, {-1, 1}, {1, -1}, {-1, -1}};
} using HeightMapArray = std::array<std::array<int, CHUNK_SIZE>, CHUNK_SIZE>;
} // namespace Cubed

View File

@@ -1,13 +1,11 @@
#pragma once #pragma once
#include <Cubed/primitive_data.hpp> #include "Cubed/ui/text.hpp"
#include <Cubed/ui/text.hpp>
#include <unordered_map> #include <unordered_map>
namespace Cubed { namespace Cubed {
class DebugCollector { class DebugCollector {
public: public:
static DebugCollector& get(); static DebugCollector& get();
@@ -23,4 +21,4 @@ private:
std::unordered_map<std::size_t, Text> m_texts; std::unordered_map<std::size_t, Text> m_texts;
}; };
} } // namespace Cubed

View File

@@ -29,6 +29,7 @@ class DevPanel {
struct TextEditing { struct TextEditing {
bool perlin_seed = false; bool perlin_seed = false;
}; };
public: public:
DevPanel(App& app); DevPanel(App& app);
void init(); void init();
@@ -41,17 +42,24 @@ private:
PlayerProfile m_player_profile; PlayerProfile m_player_profile;
TextEditing m_text_editing; TextEditing m_text_editing;
bool m_need_save_config = false; bool m_need_save_config = false;
bool m_gen_thread_running = true;
int m_theme = 0; int m_theme = 0;
int m_pre_set_day_tick = 0;
int m_pre_set_tick_speed = 1;
bool m_tick_frezze = false;
void show_about_table_bar(); void show_about_table_bar();
void show_biome_table_bar(); void show_biome_table_bar();
void show_time_table_bar();
void show_cave_table_bar();
void show_river_table_bar();
void show_settings_tab_item(); void show_settings_tab_item();
void show_world_tab_item(); void show_world_tab_item();
void show_player_tab_item(); void show_player_tab_item();
void show_items_tab_item();
void show_shader_tab_item();
void update_config_view(); void update_config_view();
void update_player_profile(); void update_player_profile();
}; };
} // namespace Cubed
}

View File

@@ -5,21 +5,25 @@
namespace Cubed { namespace Cubed {
constexpr float BIOME_NOISE_FREQUENCY = 0.03f; constexpr float BIOME_NOISE_FREQUENCY = 0.06f;
constexpr float HEIGHTMAP_NOISE_FREQUENCY = 0.001f;
constexpr float PLAIN_FREQ = 0.4f; constexpr float MOUNTAINOUS_NOISE_FREQUENCY = 0.003f;
constexpr float FOREST_FREQ = 1.2f; enum class BiomeType {
constexpr float DESERT_FREQ = 1.2f;
constexpr float MOUNTAIN_FREQ = 2.0f;
enum class Biome {
PLAIN = 0, PLAIN = 0,
FOREST, FOREST,
DESERT, DESERT,
MOUNTAIN, MOUNTAIN,
RIVER,
SNOWY_PLAIN,
OCEAN,
NONE NONE
}; };
struct BiomeConditions {
float temp = 0.0f;
float humid = 0.0f;
float mountainous = 0.0f;
};
struct BiomeHeightRange { struct BiomeHeightRange {
int base_y; int base_y;
@@ -27,52 +31,50 @@ struct BiomeHeightRange {
}; };
struct BiomeNonAdjacent { struct BiomeNonAdjacent {
Biome first; BiomeType first;
std::vector<Biome> second; std::vector<BiomeType> second;
Biome replace; BiomeType replace;
}; };
static inline const std::vector<BiomeNonAdjacent> NON_ADJACENT {{ static inline const std::vector<BiomeNonAdjacent> NON_ADJACENT{
{Biome::PLAIN, {Biome::NONE}, Biome::PLAIN}, {{BiomeType::PLAIN, {BiomeType::DESERT}, BiomeType::RIVER},
{Biome::FOREST, {Biome::DESERT}, Biome::PLAIN}, {BiomeType::FOREST, {BiomeType::DESERT}, BiomeType::RIVER},
{Biome::DESERT, {Biome::MOUNTAIN, Biome::FOREST}, Biome::PLAIN}, {BiomeType::DESERT, {BiomeType::FOREST}, BiomeType::RIVER},
{Biome::MOUNTAIN, {Biome::DESERT}, Biome::PLAIN} {BiomeType::MOUNTAIN, {BiomeType::NONE}, BiomeType::RIVER}}};
}};
struct BaseBiomeParams { struct BaseBiomeParams {
Biome biome; BiomeType biome;
std::pair<float, float> temp; std::pair<float, float> temp;
std::pair<float, float> humid; std::pair<float, float> humid;
std::array<float, 3> frequencies; std::array<float, 3> frequencies;
BiomeHeightRange height_range; BiomeHeightRange height_range;
}; };
struct PlainParams : public BaseBiomeParams { struct PlainParams : public BaseBiomeParams {};
};
struct ForestParams : public BaseBiomeParams { struct ForestParams : public BaseBiomeParams {
float tree_frequency; float tree_frequency;
}; };
struct DesertParams : public BaseBiomeParams { struct DesertParams : public BaseBiomeParams {};
}; struct MountainParams : public BaseBiomeParams {};
struct MountainParams : public BaseBiomeParams { struct RiverParams : public BaseBiomeParams {};
}; std::string get_biome_str(BiomeType biome);
// std::array<float, 3> get_noise_frequencies_for_biome(BiomeType biome);
// BiomeHeightRange get_biome_height_range(BiomeType biome);
BiomeType safe_int_to_biome(int x);
int get_interpolated_height(float world_x, float world_z, float temp,
float humid);
std::string get_biome_str(Biome biome); BiomeType determine_biome(const BiomeConditions& conditions);
Biome get_biome_from_noise(float temp, float humid);
std::array<float, 3> get_noise_frequencies_for_biome(Biome biome);
BiomeHeightRange get_biome_height_range(Biome biome);
Biome safe_int_to_biome(int x);
int get_interpolated_height(float world_x, float world_z, float temp, float humid);
PlainParams& plain_params(); PlainParams& plain_params();
ForestParams& forest_params(); ForestParams& forest_params();
DesertParams& desert_params(); DesertParams& desert_params();
MountainParams& mountain_params(); MountainParams& mountain_params();
RiverParams& river_params();
} } // namespace Cubed

View File

@@ -1,16 +1,13 @@
#pragma once #pragma once
#include <glad/glad.h> #include <glad/glad.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <array>
#include <string> #include <string>
#include <vector> #include <vector>
#include <Cubed/config.hpp>
#include <Cubed/constants.hpp>
#include <Cubed/tools/cubed_assert.hpp>
namespace Cubed { namespace Cubed {
using BlockType = uint8_t;
struct BlockTexture { struct BlockTexture {
std::string name; std::string name;
@@ -18,9 +15,7 @@ struct BlockTexture {
std::vector<GLuint> texture; std::vector<GLuint> texture;
}; };
struct Block : public BlockTexture{ struct Block : public BlockTexture {};
};
struct BlockRenderData { struct BlockRenderData {
std::vector<bool> draw_face; std::vector<bool> draw_face;
@@ -28,12 +23,8 @@ struct BlockRenderData {
BlockRenderData() = default; BlockRenderData() = default;
BlockRenderData(const BlockRenderData&) = default; BlockRenderData(const BlockRenderData&) = default;
BlockRenderData& operator=(const BlockRenderData&) = default; BlockRenderData& operator=(const BlockRenderData&) = default;
BlockRenderData(BlockRenderData&& data) : BlockRenderData(BlockRenderData&& data)
draw_face(std::move(data.draw_face)), : draw_face(std::move(data.draw_face)), block_id(data.block_id) {}
block_id(data.block_id)
{
}
BlockRenderData& operator=(BlockRenderData&& data) { BlockRenderData& operator=(BlockRenderData&& data) {
draw_face = std::move(data.draw_face); draw_face = std::move(data.draw_face);
block_id = data.block_id; block_id = data.block_id;
@@ -46,30 +37,55 @@ struct LookBlock {
glm::ivec3 normal; glm::ivec3 normal;
}; };
constexpr std::array<std::string_view, MAX_BLOCK_NUM> BLOCK_REISTER{ struct BlockData {
"air", std::string name;
"grass_block", BlockType id = 0;
"dirt",
"stone", bool is_liquid = false;
"sand", bool is_gas = false;
"log",
"leaf" bool is_passable = false;
bool is_cross_plane = false;
bool is_transparent = false;
bool is_discard = false;
bool is_blend = false;
bool is_transitional = false;
BlockData(BlockType b_id, std::string_view b_name, bool liquid,
bool passable, bool cross_plane, bool transparent, bool gas,
bool discard, bool blend, bool transitional)
: name(b_name), id(b_id), is_liquid(liquid), is_gas(gas),
is_passable(passable), is_cross_plane(cross_plane),
is_transparent(transparent), is_discard(discard), is_blend(blend),
is_transitional(transitional) {}
}; };
const std::array<bool, MAX_BLOCK_NUM> TRANSPARENT_MAP { class BlockManager {
true,
false, public:
false, static const std::vector<BlockData>& datas();
false, static void init();
false, static unsigned sums();
false, static unsigned cross_plane_sum();
true static const std::string& name_form_id(BlockType id);
static bool is_gas(BlockType id);
static bool is_liquid(BlockType id);
static bool is_cross_plane(BlockType id);
static bool is_transparent(BlockType id);
static bool is_passable(BlockType id);
static bool is_discard(BlockType id);
static bool is_blend(BlockType id);
static bool is_transitional(BlockType id);
static BlockType cross_plane_index(BlockType id);
private:
static void set_up_cross_plane_map();
static inline std::vector<BlockData> m_datas;
static inline bool is_init = false;
static inline std::unordered_map<BlockType, BlockType> m_cross_plane_map;
}; };
inline bool is_in_transparent_map(unsigned id) { } // namespace Cubed
ASSERT_MSG(id < MAX_BLOCK_NUM, "ID is invaild");
return TRANSPARENT_MAP[id];
};
}

View File

@@ -0,0 +1,18 @@
#pragma once
namespace Cubed {
class ChunkGenerator;
class BiomeBuilder {
public:
BiomeBuilder() = default;
virtual ~BiomeBuilder() = default;
virtual ChunkGenerator& get_chunk_generator() = 0;
virtual void build_biome() = 0;
virtual void build_vegetation() = 0;
void ocean_water_build();
protected:
void build_bottom();
void place_grass();
};
} // namespace Cubed

View File

@@ -0,0 +1,21 @@
#pragma once
#include "Cubed/gameplay/builders/biome_builder.hpp"
namespace Cubed {
class ChunkGenerator;
class DesertBuilder : public BiomeBuilder {
public:
DesertBuilder(ChunkGenerator& chunk_generator);
void build_biome() override;
ChunkGenerator& get_chunk_generator() override;
void build_vegetation() override;
private:
ChunkGenerator& m_chunk_generator;
void build_blocks();
};
} // namespace Cubed

View File

@@ -0,0 +1,21 @@
#pragma once
#include "Cubed/gameplay/builders/biome_builder.hpp"
namespace Cubed {
class ChunkGenerator;
class ForestBuilder : public BiomeBuilder {
public:
ForestBuilder(ChunkGenerator& chunk_generator);
void build_biome() override;
ChunkGenerator& get_chunk_generator() override;
void build_vegetation() override;
private:
ChunkGenerator& m_chunk_generator;
void build_blocks();
};
} // namespace Cubed

View File

@@ -0,0 +1,21 @@
#pragma once
#include "Cubed/gameplay/builders/biome_builder.hpp"
namespace Cubed {
class ChunkGenerator;
class MountainBuilder : public BiomeBuilder {
public:
MountainBuilder(ChunkGenerator& chunk_generator);
void build_biome() override;
ChunkGenerator& get_chunk_generator() override;
void build_vegetation() override;
private:
ChunkGenerator& m_chunk_generator;
void build_blocks();
};
} // namespace Cubed

View File

@@ -0,0 +1,23 @@
#pragma once
#pragma once
#include "Cubed/gameplay/builders/biome_builder.hpp"
namespace Cubed {
class ChunkGenerator;
class OceanBuilder : public BiomeBuilder {
public:
OceanBuilder(ChunkGenerator& chunk_generator);
void build_biome() override;
ChunkGenerator& get_chunk_generator() override;
void build_vegetation() override;
private:
ChunkGenerator& m_chunk_generator;
void build_blocks();
};
} // namespace Cubed

View File

@@ -0,0 +1,21 @@
#pragma once
#include "Cubed/gameplay/builders/biome_builder.hpp"
namespace Cubed {
class ChunkGenerator;
class PlainBuilder : public BiomeBuilder {
public:
PlainBuilder(ChunkGenerator& chunk_generator);
void build_biome() override;
ChunkGenerator& get_chunk_generator() override;
void build_vegetation() override;
private:
ChunkGenerator& m_chunk_generator;
void build_blocks();
};
} // namespace Cubed

View File

@@ -0,0 +1,21 @@
#pragma once
#include "Cubed/gameplay/builders/biome_builder.hpp"
namespace Cubed {
class ChunkGenerator;
class RiverBuilder : public BiomeBuilder {
public:
RiverBuilder(ChunkGenerator& chunk_generator);
void build_biome() override;
ChunkGenerator& get_chunk_generator() override;
void build_vegetation() override;
private:
ChunkGenerator& m_chunk_generator;
void build_blocks();
};
} // namespace Cubed

View File

@@ -0,0 +1,21 @@
#pragma once
#include "Cubed/gameplay/builders/biome_builder.hpp"
namespace Cubed {
class ChunkGenerator;
class SnowyPlainBuilder : public BiomeBuilder {
public:
SnowyPlainBuilder(ChunkGenerator& chunk_generator);
void build_biome() override;
ChunkGenerator& get_chunk_generator() override;
void build_vegetation() override;
private:
ChunkGenerator& m_chunk_generator;
void build_blocks();
};
} // namespace Cubed

View File

@@ -0,0 +1,27 @@
#pragma once
#include "Cubed/gameplay/cave_path.hpp"
#include <tbb/concurrent_hash_map.h>
namespace Cubed {
class CaveCarver {
using CaveHashMap = tbb::concurrent_hash_map<unsigned, CavePath>;
public:
CaveCarver();
CaveHashMap& paths();
void init(unsigned world_seed);
void reload(unsigned world_seed);
void add_path(const glm::vec3& pos, unsigned chunk_seed);
void try_to_add_path(const ChunkPos& pos, unsigned chunk_seed);
void cleanup_finished_caves();
int cave_sum() const;
float& cave_probability();
private:
CaveHashMap m_paths;
unsigned m_seed = 0;
Random m_random;
float m_cave_probability = 0.035f;
};
} // namespace Cubed

View File

@@ -0,0 +1,54 @@
#pragma once
#include "Cubed/gameplay/chunk_pos.hpp"
#include "Cubed/gameplay/path_point.hpp"
#include "Cubed/tools/cubed_random.hpp"
#include <glm/glm.hpp>
#include <tbb/concurrent_hash_map.h>
namespace Cubed {
class CavePath {
using ChunkPosSet =
tbb::concurrent_hash_map<ChunkPos, bool, ChunkPos::TBBHash>;
public:
CavePath(unsigned int chunk_seed, unsigned world_seed,
const glm::vec3& start_pos);
const std::vector<PathPoint>& points() const;
void clear_chunk(const ChunkPos& pos);
bool is_finished() const;
static float& radius_xz_min();
static float& radius_xz_max();
static float& radius_y_min();
static float& radius_y_max();
static float& delta_angle_min();
static float& delta_angle_max();
static int& step_min();
static int& step_max();
private:
static inline float m_radius_xz_min = 5.0f;
static inline float m_radius_xz_max = 15.0f;
static inline float m_radius_y_min = 4.0f;
static inline float m_radius_y_max = 10.0f;
static inline float m_delta_angle_min = -5.0f;
static inline float m_delta_angle_max = 5.0f;
static inline int m_step_min = 10;
static inline int m_step_max = 400;
unsigned int m_seed = 0;
float m_yaw = 0.0f;
float m_pitch = 0.0f;
int m_step = 0;
float m_step_len = 1.0f;
PathPoint m_start_path_point{{0.0f, 0.0f, 0.0f}, 0.0f, 0.0f};
Random m_random;
std::vector<PathPoint> m_points;
ChunkPosSet m_pending_chunks;
void collect_path_points();
void precompute_chunk_coverage();
};
} // namespace Cubed

View File

@@ -1,32 +1,29 @@
#pragma once #pragma once
#include "Cubed/gameplay/biome.hpp"
#include "Cubed/gameplay/block.hpp"
#include "Cubed/gameplay/chunk_generator.hpp"
#include "Cubed/gameplay/chunk_pos.hpp"
#include "Cubed/gameplay/vertex_data.hpp"
#include <atomic> #include <atomic>
#include <cstdint> #include <mutex>
#include <Cubed/config.hpp>
#include <Cubed/primitive_data.hpp>
#include <Cubed/gameplay/biome.hpp>
#include <Cubed/gameplay/chunk_generator.hpp>
#include <Cubed/gameplay/chunk_pos.hpp>
#include <Cubed/gameplay/block.hpp>
namespace Cubed { namespace Cubed {
class World; class World;
// if want to use, do init_chunk(), gen_vertex_data() and // if want to use, do init_chunk(), gen_vertex_data() and
class Chunk { class Chunk {
private: private:
static constexpr int SIZE_X = CHUCK_SIZE; using OptionalBlockVectorArray =
std::array<std::optional<std::vector<BlockType>>, 4>;
static constexpr int SIZE_X = CHUNK_SIZE;
static constexpr int SIZE_Y = WORLD_SIZE_Y; static constexpr int SIZE_Y = WORLD_SIZE_Y;
static constexpr int SIZE_Z = CHUCK_SIZE; static constexpr int SIZE_Z = CHUNK_SIZE;
static constexpr int VERTEX_DATA_SUM = 4;
using HeightMapArray = std::array<std::array<float, SIZE_Z>, SIZE_X>;
std::atomic<bool> m_dirty{false}; std::atomic<bool> m_dirty{false};
std::atomic<bool> m_need_upload{true}; std::atomic<bool> m_need_upload{true};
std::atomic<bool> m_is_on_gen_vertex_data{false}; std::atomic<bool> m_is_on_gen_vertex_data{false};
std::atomic<size_t> m_vertex_sum = 0; std::atomic<BiomeType> m_biome = BiomeType::PLAIN;
std::atomic<Biome> m_biome = Biome::PLAIN;
std::mutex m_vertexs_data_mutex; std::mutex m_vertexs_data_mutex;
std::unique_ptr<ChunkGenerator> m_generator; std::unique_ptr<ChunkGenerator> m_generator;
@@ -35,14 +32,25 @@ private:
World& m_world; World& m_world;
HeightMapArray m_heightmap; HeightMapArray m_heightmap;
// the index is a array of block id // the index is a array of block id
std::vector<uint8_t> m_blocks; std::vector<BlockType> m_blocks;
GLuint m_vbo = 0;
std::vector<Vertex> m_vertexs_data;
/*
0 - normal
1 - cross_plane
2 - normal_discard
3 - transparent and blend
*/
std::vector<VertexData> m_vertex_data;
float frequency = 0.01f; float frequency = 0.01f;
float height = 80; float height = 80;
unsigned m_seed = 0;
BiomeConditions m_conditions;
void clear_dirty(); void clear_dirty();
void gen_vertices(const OptionalBlockVectorArray& neighbor_block);
void gen_cross_plane_vertices(int world_x, int world_y, int world_z,
BlockType id);
public: public:
Chunk(World& world, ChunkPos chunk_pos); Chunk(World& world, ChunkPos chunk_pos);
@@ -52,25 +60,37 @@ public:
Chunk(Chunk&&) noexcept; Chunk(Chunk&&) noexcept;
Chunk& operator=(Chunk&&) noexcept; Chunk& operator=(Chunk&&) noexcept;
Biome get_biome() const; static std::tuple<int, int, int> world_to_block(int world_x, int world_y,
int world_z, int chunk_x,
int chunk_z);
static std::tuple<int, int, int> world_to_block(const glm::ivec3& block_pos,
ChunkPos chunk_pos);
static std::tuple<int, int, int> block_to_world(int x, int y, int z,
int chunk_x, int chunk_z);
static std::tuple<int, int, int> block_to_world(const glm::ivec3& block_pos,
ChunkPos chunk_pos);
BiomeType get_biome() const;
ChunkPos get_chunk_pos() const; ChunkPos get_chunk_pos() const;
const std::vector<uint8_t>& get_chunk_blocks() const; const std::vector<BlockType>& get_chunk_blocks() const;
HeightMapArray get_heightmap() const; HeightMapArray get_heightmap() const;
static int get_index(int x, int y, int z); static int index(int x, int y, int z);
static int get_index(const glm::vec3& pos); static int index(const glm::vec3& pos);
// Init Chunk // Init Chunk
// Determine biome from temperature and humidity noise // Determine biome from temperature and humidity noise
void gen_phase_one(); void gen_phase_one();
// Resolve biome adjacency conflicts with neighbor chunks // Resolve biome adjacency conflicts with neighbor chunks
void gen_phase_two(const std::array<const Chunk*, 4>& adj_chunks); void gen_phase_two(const std::array<const Chunk*, 8>& adj_chunks);
// Generate heightmap using biome-specific noise // Generate heightmap using biome-specific noise
void gen_phase_three(); void gen_phase_three();
// Blend heightmap with neighbors for smooth transitions // Blend heightmap with neighbors for smooth transitions
void gen_phase_four(const std::array<std::optional<HeightMapArray>, 4>& neighbor_heightmap); void gen_phase_four(
const std::array<std::optional<HeightMapArray>, 8>& neighbor_heightmap,
const std::array<BiomeType, 8>& neighbor_biome);
// Generate terrain blocks from heightmap and biome // Generate terrain blocks from heightmap and biome
void gen_phase_five(); void gen_phase_five();
// Blend surface blocks at chunk borders with neighbors // Blend surface blocks at chunk borders with neighbors
void gen_phase_six(const std::array<std::optional<std::vector<uint8_t>>, 4>& neighbor_block); void gen_phase_six(const std::array<std::optional<std::vector<BlockType>>,
4>& neighbor_block);
// Generate biome-specific vegetation/structures // Generate biome-specific vegetation/structures
void gen_phase_seven(); void gen_phase_seven();
// void gen_vertex_data(); // void gen_vertex_data();
@@ -78,11 +98,20 @@ public:
// 1 : (-1, 0) // 1 : (-1, 0)
// 2 : (0, 1) // 2 : (0, 1)
// 3 : (0, -1) // 3 : (0, -1)
void gen_vertex_data(const std::array<const std::vector<uint8_t>*, 4>& neighbor_block); void gen_vertex_data(const OptionalBlockVectorArray& neighbor_block);
void upload_to_gpu(); void upload_to_gpu();
GLuint get_vbo() const; GLuint get_normal_vao() const;
size_t get_vertex_sum() const; size_t get_normal_vertices_sum() const;
GLuint get_cross_vao() const;
size_t get_cross_vertices_sum() const;
GLuint get_normal_discard_vao() const;
size_t get_normal_discard_vertices_sum() const;
GLuint get_normal_blend_vao() const;
size_t get_normal_blend_vertices_sum() const;
bool is_dirty() const; bool is_dirty() const;
void mark_dirty(); void mark_dirty();
@@ -93,11 +122,13 @@ public:
void set_chunk_block(int index, unsigned id); void set_chunk_block(int index, unsigned id);
ChunkPos chunk_pos() const; ChunkPos chunk_pos() const;
Biome biome() const; BiomeType biome() const;
void biome(Biome b); void biome(BiomeType b);
HeightMapArray& heightmap(); HeightMapArray& heightmap();
std::vector<uint8_t>& blocks(); std::vector<BlockType>& blocks();
World& world();
unsigned seed() const;
BiomeConditions& conditions();
}; };
} // namespace Cubed
}

View File

@@ -1,20 +1,20 @@
#pragma once #pragma once
#include <Cubed/constants.hpp> #include "Cubed/constants.hpp"
#include <Cubed/tools/cubed_random.hpp> #include "Cubed/gameplay/biome.hpp"
#include "Cubed/gameplay/block.hpp"
#include "Cubed/gameplay/builders/biome_builder.hpp"
#include "Cubed/gameplay/path_point.hpp"
#include "Cubed/tools/cubed_random.hpp"
#include <atomic> #include <atomic>
#include <memory>
#include <optional> #include <optional>
namespace Cubed { namespace Cubed {
class Chunk; class Chunk;
class ChunkGenerator { class ChunkGenerator {
static constexpr int SIZE_X = CHUCK_SIZE;
static constexpr int SIZE_Y = WORLD_SIZE_Y;
static constexpr int SIZE_Z = CHUCK_SIZE;
using HeightMapArray = std::array<std::array<float, CHUCK_SIZE>, CHUCK_SIZE>;
public: public:
ChunkGenerator(Chunk& chunk); ChunkGenerator(Chunk& chunk);
@@ -22,21 +22,33 @@ public:
static void reload(); static void reload();
static const unsigned& seed(); static const unsigned& seed();
static void seed(unsigned s); static void seed(unsigned s);
unsigned chunk_seed() const;
// Generate Biome // Generate Biome
void assign_chunk_biome(); void assign_chunk_biome();
// Adjust Biome // Adjust Biome
void resolve_biome_adjacency_conflict(const std::array<const Chunk*, 4>& adj_chunks); void resolve_biome_adjacency_conflict(
const std::array<const Chunk*, 8>& adj_chunks);
// Generate Heightmap // Generate Heightmap
void generate_heightmap(); void generate_heightmap();
// Adjust Height // Adjust Height
void blend_heightmap_boundaries(const std::array<std::optional<HeightMapArray>, 4>& neighbor_heightmap); void blend_heightmap_boundaries(
const std::array<std::optional<HeightMapArray>, 8>& neighbor_heightmap,
const std::array<BiomeType, 8>& neighbor_biome);
// Generate Block // Generate Block
void generate_terrain_blocks(); void generate_terrain_blocks();
// Adjust Block; // Adjust Block;
void blend_surface_blocks_borders(const std::array<std::optional<std::vector<uint8_t>>, 4>& neighbor_block); void blend_surface_blocks_borders(
const std::array<std::optional<std::vector<BlockType>>, 4>&
neighbor_block);
// Generate Structure // Generate Structure
void generate_vegetation(); void generate_vegetation();
BiomeType get_biome_at(float world_x, float world_z);
Chunk& chunk();
Random& random();
const std::array<BiomeType, 8>& neighbor_biome() const;
void ocean_build();
void generate_cave();
void generate_river();
private: private:
static inline std::atomic<bool> is_init{false}; static inline std::atomic<bool> is_init{false};
@@ -44,7 +56,15 @@ private:
static inline std::atomic<bool> is_seed_change{false}; static inline std::atomic<bool> is_seed_change{false};
Chunk& m_chunk; Chunk& m_chunk;
Random m_random; Random m_random;
std::unique_ptr<BiomeBuilder> m_biome_builder{nullptr};
bool is_cur_chunk_ins = false;
std::array<BiomeType, 8> m_neighbor_biome;
unsigned m_chunk_seed = 0;
void make_biome_builder();
void
carve_worm(const std::vector<PathPoint>& points, const ChunkPos& chunk_pos,
std::function<void(int /*x*/, int /*y*/, int /*z*/)> on_hit);
}; };
} // namespace Cubed
}

View File

@@ -1,13 +1,9 @@
#pragma once #pragma once
#include <functional> #include <functional>
#include <Cubed/tools/log.hpp>
#include <Cubed/tools/cubed_assert.hpp>
namespace Cubed { namespace Cubed {
struct ChunkPos { struct ChunkPos {
int x; int x;
int z; int z;
@@ -20,7 +16,14 @@ struct ChunkPos {
return h1 ^ (h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2)); return h1 ^ (h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2));
} }
}; };
struct TBBHash {
std::size_t hash(const ChunkPos& p) const {
return ChunkPos::Hash{}(p);
}
bool equal(const ChunkPos& a, const ChunkPos& b) const {
return a == b;
}
};
ChunkPos operator+(const ChunkPos& pos) const { ChunkPos operator+(const ChunkPos& pos) const {
return ChunkPos{x + pos.x, z + pos.z}; return ChunkPos{x + pos.x, z + pos.z};
} }
@@ -32,5 +35,4 @@ struct ChunkPos {
}; };
}; };
} // namespace Cubed
}

View File

@@ -5,11 +5,7 @@
namespace Cubed { namespace Cubed {
enum class GameMode { CREATIVE = 0, SPECTATOR };
enum class GameMode {
CREATIVE = 0,
SPECTATOR
};
inline std::string to_str(GameMode mode) { inline std::string to_str(GameMode mode) {
using enum GameMode; using enum GameMode;
@@ -22,5 +18,4 @@ inline std::string to_str(GameMode mode) {
throw std::invalid_argument{"GameMode is invaild"}; throw std::invalid_argument{"GameMode is invaild"};
} }
} // namespace Cubed
}

View File

@@ -0,0 +1,10 @@
#pragma once
// Prevent unsigned underflow issues in subtraction
using TickType = long long;
constexpr int DEFAULT_PER_TICK_TIME = 50;
constexpr TickType DAY_TIME = 24000;
constexpr TickType PER_HOUR = 1000;

View File

@@ -0,0 +1,36 @@
#pragma once
#include <glm/glm.hpp>
struct PathPoint {
glm::vec3 pos;
glm::vec3 tangent{0.0f, 0.0f, 1.0f};
float rad_xz;
float rad_y;
PathPoint(const glm::vec3& p, float rx, float ry)
: pos(p), rad_xz(rx), rad_y(ry) {}
bool contains(const glm::vec3& other_pos) const {
glm::vec3 to_point = other_pos - pos;
glm::vec3 world_up(0.0f, 1.0f, 0.0f);
glm::vec3 right = glm::normalize(glm::cross(tangent, world_up));
if (glm::length(right) < 0.001f) {
glm::vec3 alt_up(1.0f, 0.0f, 0.0f);
right = glm::normalize(glm::cross(tangent, alt_up));
}
glm::vec3 up = glm::normalize(glm::cross(right, tangent));
float horizontal_dist = glm::dot(to_point, right);
float vertical_dist = glm::dot(to_point, up);
float a = rad_xz;
float b = rad_y;
if (a <= 0.0f || b <= 0.0f)
return false;
float check = (horizontal_dist * horizontal_dist) / (a * a) +
(vertical_dist * vertical_dist) / (b * b);
return check <= 1.0f;
}
};

View File

@@ -1,23 +1,18 @@
#pragma once #pragma once
#include "Cubed/AABB.hpp"
#include "Cubed/constants.hpp"
#include "Cubed/gameplay/block.hpp"
#include "Cubed/gameplay/chunk_pos.hpp"
#include "Cubed/gameplay/game_mode.hpp"
#include "Cubed/input.hpp"
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <Cubed/AABB.hpp>
#include <Cubed/config.hpp>
#include <Cubed/constants.hpp>
#include <Cubed/gameplay/block.hpp>
#include <Cubed/gameplay/chunk_pos.hpp>
#include <Cubed/gameplay/game_mode.hpp>
#include <Cubed/input.hpp>
#include <optional> #include <optional>
#include <string> #include <string>
namespace Cubed { namespace Cubed {
enum class Gait{ enum class Gait { WALK = 0, RUN };
WALK = 0,
RUN
};
class World; class World;
@@ -47,6 +42,8 @@ private:
float m_xz_speed = 0.0f; float m_xz_speed = 0.0f;
unsigned m_place_block = 1;
glm::vec3 direction = glm::vec3(0.0f, 0.0f, 0.0f); glm::vec3 direction = glm::vec3(0.0f, 0.0f, 0.0f);
glm::vec3 move_distance{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 // player is tow block tall, the pos is the lower pos
@@ -65,7 +62,9 @@ private:
std::string m_name{}; std::string m_name{};
World& m_world; World& m_world;
bool ray_cast(const glm::vec3& start, const glm::vec3& dir, glm::ivec3& block_pos, glm::vec3& normal, float distance = 4.0f); bool ray_cast(const glm::vec3& start, const glm::vec3& dir,
glm::ivec3& block_pos, glm::vec3& normal,
float distance = 4.0f);
void check_player_chunk_transition(); void check_player_chunk_transition();
void update_direction(); void update_direction();
@@ -88,6 +87,7 @@ public:
void change_mode(GameMode mode); void change_mode(GameMode mode);
void hot_reload(); void hot_reload();
void set_player_pos(const glm::vec3& pos); void set_player_pos(const glm::vec3& pos);
void set_place_block(unsigned id);
void update(float delta_time); void update(float delta_time);
void update_front_vec(float offset_x, float offset_y); void update_front_vec(float offset_x, float offset_y);
void update_player_move_state(int key, int action); void update_player_move_state(int key, int action);
@@ -100,10 +100,11 @@ public:
float& deceleration(); float& deceleration();
float& g(); float& g();
unsigned place_block() const;
Gait& gait(); Gait& gait();
GameMode& game_mode(); GameMode& game_mode();
const World& get_world() const;
}; };
} // namespace Cubed
}

View File

@@ -0,0 +1,55 @@
#pragma once
#include "Cubed/gameplay/chunk_pos.hpp"
#include "Cubed/gameplay/path_point.hpp"
#include "Cubed/tools/cubed_random.hpp"
#include <glm/glm.hpp>
#include <tbb/concurrent_hash_map.h>
namespace Cubed {
class RiverPath {
using ChunkPosSet =
tbb::concurrent_hash_map<ChunkPos, bool, ChunkPos::TBBHash>;
public:
RiverPath(unsigned int chunk_seed, unsigned world_seed,
const glm::vec3& start_pos);
const std::vector<PathPoint>& points() const;
void clear_chunk(const ChunkPos& pos);
bool is_finished() const;
static float& radius_xz_min();
static float& radius_xz_max();
static float& radius_y_min();
static float& radius_y_max();
static float& delta_angle_min();
static float& delta_angle_max();
static int& step_min();
static int& step_max();
private:
static inline float m_radius_xz_min = 5.0f;
static inline float m_radius_xz_max = 10.0f;
static inline float m_radius_y_min = 4.0f;
static inline float m_radius_y_max = 8.0f;
static inline float m_delta_angle_min = -3.0f;
static inline float m_delta_angle_max = 3.0f;
static inline int m_step_min = 200;
static inline int m_step_max = 400;
unsigned int m_seed = 0;
float m_yaw = 0.0f;
float m_initial_yaw = 0.0f;
float m_pitch = 0.0f;
int m_step = 0;
float m_step_len = 1.0f;
PathPoint m_start_path_point{{0.0f, 0.0f, 0.0f}, 0.0f, 0.0f};
Random m_random;
std::vector<PathPoint> m_points;
ChunkPosSet m_pending_chunks;
void collect_path_points();
void precompute_chunk_coverage();
};
} // namespace Cubed

View File

@@ -0,0 +1,32 @@
#pragma once
#include "Cubed/gameplay/chunk_pos.hpp"
#include "Cubed/gameplay/river.path.hpp"
#include "Cubed/tools/cubed_random.hpp"
#include <glm/glm.hpp>
#include <tbb/concurrent_hash_map.h>
namespace Cubed {
class RiverWorm {
using RiverHashMap = tbb::concurrent_hash_map<unsigned, RiverPath>;
public:
RiverWorm();
RiverHashMap& paths();
void init(unsigned world_seed);
void reload(unsigned world_seed);
void add_path(const glm::vec3& pos, unsigned chunk_seed);
void try_to_add_path(const ChunkPos& pos, unsigned chunk_seed);
void cleanup_finished_rivers();
int river_sum() const;
float& river_probability();
private:
RiverHashMap m_paths;
unsigned m_seed = 0;
Random m_random;
float m_probability = 0.01f;
};
}; // namespace Cubed

View File

@@ -13,4 +13,4 @@ struct TreeStructNode {
bool build_tree(Chunk& chunk, const glm::ivec3& pos); bool build_tree(Chunk& chunk, const glm::ivec3& pos);
} } // namespace Cubed

View File

@@ -0,0 +1,25 @@
#pragma once
#include "Cubed/primitive_data.hpp"
#include <atomic>
#include <glad/glad.h>
#include <vector>
namespace Cubed {
class World;
struct VertexData {
std::vector<Vertex3D> m_vertices;
GLuint m_vbo = 0;
GLuint m_vao = 0;
std::atomic<std::size_t> m_sum{0};
World& m_world;
VertexData(World& world);
~VertexData();
VertexData(const VertexData&) = delete;
VertexData(VertexData&&) noexcept;
VertexData& operator=(const VertexData&) = delete;
VertexData& operator=(VertexData&&) noexcept;
void upload();
void update_sum();
};
} // namespace Cubed

View File

@@ -1,97 +1,130 @@
#pragma once #pragma once
#include "Cubed/AABB.hpp"
#include "Cubed/gameplay/cave_carver.hpp"
#include "Cubed/gameplay/chunk.hpp"
#include "Cubed/gameplay/game_time.hpp"
#include "Cubed/gameplay/river_worm.hpp"
#include <atomic> #include <atomic>
#include <condition_variable> #include <condition_variable>
#include <mutex> #include <mutex>
#include <thread>
#include <optional> #include <optional>
#include <thread>
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
#include <Cubed/AABB.hpp>
#include <Cubed/primitive_data.hpp>
#include <Cubed/gameplay/chunk.hpp>
namespace Cubed { namespace Cubed {
struct ChunkRenderSnapshot { struct ChunkRenderSnapshot {
GLuint vbo; GLuint normal_vao;
size_t vertex_count; size_t normal_vertices_count;
GLuint cross_vao;
size_t cross_vertices_count;
GLuint normal_discard_vao;
size_t normal_discard_vertices_count;
GLuint normal_blend_vao;
size_t normal_blend_vertices_count;
glm::vec3 center; glm::vec3 center;
glm::vec3 half_extents; glm::vec3 half_extents;
}; };
class Player; class Player;
class TextureManager;
class World { class World {
private: private:
using OptionalBlockVectorArray =
std::array<std::optional<std::vector<BlockType>>, 4>;
using ChunkPtrUpdateList = std::vector<std::pair<ChunkPos, Chunk*>>; using ChunkPtrUpdateList = std::vector<std::pair<ChunkPos, Chunk*>>;
using ChunkUpdateList = std::vector<std::pair<ChunkPos, Chunk>>; using ChunkPairVector = std::vector<std::pair<ChunkPos, Chunk>>;
using ConstChunkMap = std::unordered_map<ChunkPos, const Chunk*, ChunkPos::Hash>; using ConstChunkMap =
std::unordered_map<ChunkPos, const Chunk*, ChunkPos::Hash>;
using ChunkPosSet = std::unordered_set<ChunkPos, ChunkPos::Hash>; using ChunkPosSet = std::unordered_set<ChunkPos, ChunkPos::Hash>;
using ChunkHashMap = std::unordered_map<ChunkPos, Chunk, ChunkPos::Hash>;
glm::vec3 m_gen_player_pos{0.0f, 0.0f, 0.0f}; glm::vec3 m_gen_player_pos{0.0f, 0.0f, 0.0f};
std::unordered_map<ChunkPos , Chunk, ChunkPos::Hash> m_chunks; ChunkHashMap m_chunks;
std::unordered_map<std::size_t, Player> m_players; std::unordered_map<std::size_t, Player> m_players;
std::vector<glm::vec4> m_planes; std::vector<glm::vec4> m_planes;
std::thread m_gen_thread; std::thread m_gen_thread;
std::thread m_server_thread;
std::stop_source m_server_stop_source;
std::atomic<int> m_per_tick_time = DEFAULT_PER_TICK_TIME; // ms
std::atomic<TickType> m_day_tick = 6000;
mutable std::mutex m_chunks_mutex; mutable std::mutex m_chunks_mutex;
std::mutex m_gen_signal_mutex; std::mutex m_gen_signal_mutex;
std::mutex m_new_chunk_queue_mutex; std::mutex m_new_chunk_queue_mutex;
std::mutex m_delete_vbo_mutex; std::mutex m_delete_vbo_mutex;
std::mutex m_delete_vao_mutex;
std::mutex m_gen_player_pos_mutex; std::mutex m_gen_player_pos_mutex;
std::vector<GLuint> m_pending_delete_vbo; std::vector<GLuint> m_pending_delete_vbo;
std::vector<GLuint> m_pending_delete_vao;
std::condition_variable m_gen_cv; std::condition_variable m_gen_cv;
std::atomic<bool> m_gen_running{false}; std::atomic<bool> m_gen_running{false};
std::atomic<bool> m_need_gen_chunk{false}; std::atomic<bool> m_need_gen_chunk{false};
std::atomic<bool> m_is_rebuilding{false}; std::atomic<bool> m_is_rebuilding{false};
std::atomic<bool> m_chunk_gen_finished{false};
std::atomic<bool> m_could_gen{true}; std::atomic<bool> m_could_gen{true};
std::atomic<bool> m_tick_running{true};
std::atomic<int> m_rendering_distance{24}; std::atomic<int> m_rendering_distance{24};
std::atomic<float> m_chunk_gen_fraction{0.0f}; std::atomic<float> m_chunk_gen_fraction{0.0f};
std::atomic<TickType> m_game_ticks{0};
std::vector<ChunkPos> m_dirty_queue; std::vector<ChunkPos> m_dirty_queue;
std::vector<ChunkRenderSnapshot> m_render_snapshots; std::vector<ChunkRenderSnapshot> m_render_snapshots;
std::vector<std::pair<ChunkPos, Chunk>> m_new_chunk; std::vector<std::pair<ChunkPos, Chunk>> m_new_chunk;
std::vector<std::pair<ChunkPos, Chunk>> m_new_chunk_queue; std::vector<std::pair<ChunkPos, Chunk>> m_new_chunk_queue;
CaveCarver m_cave_carcer;
RiverWorm m_river_worm;
void init_chunks(); void init_chunks();
void gen_chunks_internal(); void gen_chunks_internal();
void sync_player_pos(glm::vec3& player_pos); void sync_player_pos(glm::vec3& player_pos);
void compute_required_chunks(ChunkPosSet& required_chunks); void
void sync_and_collect_missing_chunks(std::vector<ChunkPos>& , const ChunkPosSet&); compute_required_chunks(ChunkPosSet& required_chunks,
void build_neighbor_context_for_new_chunks(ConstChunkMap& new_chunks_neighbor, ChunkPtrUpdateList& affected_neighbor, const ChunkUpdateList& new_chunks); ChunkPairVector& temp_neighbor,
void build_neighbor_context_for_affected_neighbors(ChunkPtrUpdateList&, ConstChunkMap&); std::vector<ChunkPos>& need_gen_temp_chunks_pos);
void start_gen_thread(); void sync_and_collect_missing_chunks(std::vector<ChunkPos>&,
void stop_gen_thread(); const ChunkPosSet&);
void
build_neighbor_context_for_new_chunks(ConstChunkMap& new_chunks_neighbor,
ChunkPtrUpdateList& affected_neighbor,
const ChunkPairVector& new_chunks);
void build_neighbor_context_for_affected_neighbors(ChunkPtrUpdateList&,
ConstChunkMap&);
public: public:
World(); World();
~World(); ~World();
bool can_move(const AABB& player_box) const; bool can_move(const AABB& player_box) const;
// const BlockRenderData& get_block_render_data(int x, int y ,int z); // const BlockRenderData& get_block_render_data(int x, int y ,int z);
const std::optional<LookBlock>& get_look_block_pos(const std::string& name) const; const std::optional<LookBlock>&
get_look_block_pos(const std::string& name) const;
const Chunk* get_chunk(const ChunkPos& pos) const; const Chunk* get_chunk(const ChunkPos& pos) const;
Player& get_player(const std::string& name); Player& get_player(const std::string& name);
void init_world(); void init_world();
bool is_aabb_in_frustum(const glm::vec3& center, const glm::vec3& half_extents);
int get_block(const glm::ivec3& block_pos) const; int get_block(const glm::ivec3& block_pos) const;
bool is_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;
BlockType get_block_tpye(const glm::ivec3& block_pos) const;
static ChunkPos chunk_pos(int world_x, int world_z); static ChunkPos chunk_pos(int world_x, int world_z);
void need_gen(); void need_gen();
void render(const glm::mat4& mvp_matrix);
void set_block(const glm::ivec3& pos, unsigned id); void set_block(const glm::ivec3& pos, unsigned id);
void update(float delta_time); void update(float delta_time);
void push_delete_vbo(GLuint vbo); void push_delete_vbo(GLuint vbo);
void push_delete_vao(GLuint vao);
void hot_reload(); void hot_reload();
void rebuild_world(); void rebuild_world();
@@ -99,6 +132,26 @@ public:
float chunk_gen_fraction() const; float chunk_gen_fraction() const;
int rendering_distance() const; int rendering_distance() const;
void rendering_distance(int rendering_distance); void rendering_distance(int rendering_distance);
void start_gen_thread();
void start_server_thread();
void stop_gen_thread();
void stop_server_thread();
void serever_run(std::stop_token stoken);
CaveCarver& cave_carcer();
RiverWorm& river_worm();
std::vector<glm::vec4>& planes();
std::vector<ChunkRenderSnapshot>& render_snapshots();
glm::vec3 sunlight_dir() const;
TickType game_tick() const;
TickType day_tick() const;
void day_tick(TickType tick);
int per_tick_time() const;
void per_tick_time(int ms);
bool is_tick_running() const;
void tick_running(bool run);
}; };
} } // namespace Cubed

View File

@@ -4,7 +4,6 @@
namespace Cubed { namespace Cubed {
struct MoveState { struct MoveState {
bool forward = false; bool forward = false;
bool back = false; bool back = false;
@@ -32,8 +31,6 @@ struct InputState {
namespace Input { namespace Input {
InputState& get_input_state(); InputState& get_input_state();
} }
} // namespace Cubed
}

View File

@@ -1,19 +1,26 @@
#pragma once #pragma once
#include <string> // #include <string>
#include <unordered_map> // #include <unordered_map>
// #include <vector>
namespace Cubed { namespace Cubed {
class MapTable { class MapTable {
private: private:
static std::unordered_map<unsigned, std::string> id_to_name_map; /*
static std::unordered_map<size_t, unsigned> name_to_id_map; 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: public:
// please using reference // please using reference
static const std::string& get_name_from_id(unsigned id); /*
static std::string_view get_name_from_id(unsigned id);
static unsigned get_id_from_name(const std::string& name); static unsigned get_id_from_name(const std::string& name);
static void init_map();
static std::string_view item_name(unsigned id);
static const std::vector<std::string>& item_map();
*/
static void init_map();
}; };
} } // namespace Cubed

View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
namespace Cubed { namespace Cubed {
#pragma region NORMAL_BLOCK
constexpr float VERTICES_POS[6][6][3] = { constexpr float VERTICES_POS[6][6][3] = {
// ===== front (z = +1) ===== // ===== front (z = +1) =====
{{0.0f, 0.0f, 1.0f}, // bottom left {{0.0f, 0.0f, 1.0f}, // bottom left
@@ -92,23 +92,57 @@ constexpr float TEX_COORDS[6][6][2] = {
{0.0f, 0.0f}} // front left {0.0f, 0.0f}} // front left
}; };
constexpr float CUBE_VER[24] = { constexpr float NORMALS[6][6][3] = {
0.0, 0.0, 0.0, // ===== front (z = +1) =====
1.0, 0.0, 0.0, {{0.0f, 0.0f, 1.0f},
1.0, 1.0, 0.0, {0.0f, 0.0f, 1.0f},
0.0, 1.0, 0.0, {0.0f, 0.0f, 1.0f},
0.0, 0.0, 1.0, {0.0f, 0.0f, 1.0f},
1.0, 0.0, 1.0, {0.0f, 0.0f, 1.0f},
1.0, 1.0, 1.0, {0.0f, 0.0f, 1.0f}},
0.0, 1.0, 1.0 // ===== right (x = +1) =====
}; {{1.0f, 0.0f, 0.0f},
{1.0f, 0.0f, 0.0f},
{1.0f, 0.0f, 0.0f},
{1.0f, 0.0f, 0.0f},
{1.0f, 0.0f, 0.0f},
{1.0f, 0.0f, 0.0f}},
// ===== back (z = -1) =====
{{0.0f, 0.0f, -1.0f},
{0.0f, 0.0f, -1.0f},
{0.0f, 0.0f, -1.0f},
{0.0f, 0.0f, -1.0f},
{0.0f, 0.0f, -1.0f},
{0.0f, 0.0f, -1.0f}},
// ===== left (x = -1) =====
{{-1.0f, 0.0f, 0.0f},
{-1.0f, 0.0f, 0.0f},
{-1.0f, 0.0f, 0.0f},
{-1.0f, 0.0f, 0.0f},
{-1.0f, 0.0f, 0.0f},
{-1.0f, 0.0f, 0.0f}},
// ===== top (y = +1) =====
{{0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, 0.0f}},
// ===== bottom (y = -1) =====
{{0.0f, -1.0f, 0.0f},
{0.0f, -1.0f, 0.0f},
{0.0f, -1.0f, 0.0f},
{0.0f, -1.0f, 0.0f},
{0.0f, -1.0f, 0.0f},
{0.0f, -1.0f, 0.0f}}};
#pragma endregion
constexpr float CUBE_VER[24] = {0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0,
0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0,
0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0};
constexpr int OUTLINE_CUBE_INDICES[24] = { constexpr int OUTLINE_CUBE_INDICES[24] = {0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6,
0,1, 1,2, 2,3, 3,0, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7};
4,5, 5,6, 6,7, 7,4,
0,4, 1,5, 2,6, 3,7
};
constexpr float SQUARE_VERTICES[6][2] = { constexpr float SQUARE_VERTICES[6][2] = {
{-0.5f, -0.5f}, // bottom left {-0.5f, -0.5f}, // bottom left
@@ -120,18 +154,76 @@ constexpr float SQUARE_VERTICES[6][2] = {
}; };
constexpr float SQUARE_TEXTURE_POS[6][2] = { constexpr float SQUARE_TEXTURE_POS[6][2] = {
{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f},
{0.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 0.0f},
{1.0f, 1.0f}, };
{1.0f, 1.0f}, #pragma region CROSS_PLANE
{1.0f, 0.0f}, constexpr float CROSS_VERTICES_POS[2][6][3] = {
{0.0f, 0.0f}, // ===== Plane 1: bottom-front-left to top-back-right =====
{{0.0f, 0.0f, 0.0f}, // bottom front left
{0.0f, 1.0f, 0.0f}, // top front left
{1.0f, 1.0f, 1.0f}, // top back right
{1.0f, 1.0f, 1.0f}, // top back right
{1.0f, 0.0f, 1.0f}, // bottom back right
{0.0f, 0.0f, 0.0f}}, // bottom front left
// ===== Plane 2: bottom-front-right to top-back-left =====
{{1.0f, 0.0f, 0.0f}, // bottom front right
{1.0f, 1.0f, 0.0f}, // top front right
{0.0f, 1.0f, 1.0f}, // top back left
{0.0f, 1.0f, 1.0f}, // top back left
{0.0f, 0.0f, 1.0f}, // bottom back left
{1.0f, 0.0f, 0.0f}}, // bottom front right
}; };
struct Vertex { constexpr float CROSS_TEX_COORDS[2][6][2] = {
// ===== Plane 1: bottom-front-left to top-back-right =====
{{0.0f, 1.0f}, // bottom left
{0.0f, 0.0f}, // top left
{1.0f, 0.0f}, // top right
{1.0f, 0.0f}, // top right
{1.0f, 1.0f}, // bottom right
{0.0f, 1.0f}}, // bottom left
// ===== Plane 2: bottom-front-right to top-back-left =====
{{0.0f, 1.0f}, // bottom left
{0.0f, 0.0f}, // top left
{1.0f, 0.0f}, // top right
{1.0f, 0.0f}, // top right
{1.0f, 1.0f}, // bottom right
{0.0f, 1.0f}}, // bottom left
};
constexpr float CROSS_NORMALS[2][6][3] = {
// ===== Plane 1: upward =====
{{0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, 0.0f}},
// ===== Plane 2: upward =====
{{0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, 0.0f}}};
#pragma endregion
constexpr float QUAD_VERTICES[] = {
// postion // texcoorlds
-1.0f, 1.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f};
struct Vertex3D {
float x = 0.0f, y = 0.0f, z = 0.0f; float x = 0.0f, y = 0.0f, z = 0.0f;
float s = 0.0f, t = 0.0f; float s = 0.0f, t = 0.0f;
float layer = 0.0f; float layer = 0.0f;
float nx = 0.0f, ny = 0.0f, nz = 0.0f;
}; };
struct Vertex2D { struct Vertex2D {
@@ -140,4 +232,4 @@ struct Vertex2D {
float layer = 0.0f; float layer = 0.0f;
}; };
} } // namespace Cubed

View File

@@ -1,12 +1,10 @@
#pragma once #pragma once
#include <Cubed/config.hpp> #include "Cubed/constants.hpp"
#include <Cubed/constants.hpp> #include "Cubed/primitive_data.hpp"
#include <Cubed/primitive_data.hpp> #include "Cubed/shader.hpp"
#include <Cubed/shader.hpp> #include "Cubed/ui/text.hpp"
#include <Cubed/ui/text.hpp>
#include <glad/glad.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <vector> #include <vector>
namespace Cubed { namespace Cubed {
@@ -17,42 +15,103 @@ class World;
class DevPanel; class DevPanel;
class Renderer { class Renderer {
public: public:
constexpr static int NUM_VAO = 5; constexpr static int NUM_VAO = 7;
Renderer(const Camera& camera, World& world, const TextureManager& texture_manager, DevPanel& dev_panel); Renderer(const Camera& camera, World& world,
const TextureManager& texture_manager, DevPanel& dev_panel);
~Renderer(); ~Renderer();
void hot_reload(); void hot_reload();
void init(); void init();
const Shader& get_shader(const std::string& name) const; const Shader& get_shader(const std::string& name) const;
void render(); void render();
void update(float delta_time);
void update_fov(float fov); void update_fov(float fov);
void update_proj_matrix(float aspect, float width, float height); void update_proj_matrix(float aspect, float width, float height);
void updata_framebuffer(int width, int height);
float& ambient_strength();
bool& discard_transparent();
bool& shader_on();
int& shadow_mode();
int& light_cull_face();
private: private:
static constexpr glm::vec3 SUNLIGHT_COLOR{1.0f, 1.0f, 1.0f};
static constexpr glm::vec3 SUN_COLOR{1.00f, 0.95f, 0.80f};
static constexpr glm::vec3 MOON_COLOR{0.75f, 0.80f, 1.00f};
static constexpr glm::vec3 SKY_COLOR{0.529, 0.808, 0.922};
static constexpr float FAR_PLANE = 1000.0f;
static constexpr float NEAR_PLANE = 0.1f;
static constexpr float SUN_SIZE = 50.0f;
static constexpr float MOON_SIZE = 50.0f;
static constexpr float DEPTH_MAP_SIZE = 4096.0f;
static constexpr float ANGLE_STEP_DEG = 0.5f;
float m_ambient_strength = 0.1f;
const Camera& m_camera; const Camera& m_camera;
DevPanel& m_dev_panel; DevPanel& m_dev_panel;
const TextureManager& m_texture_manager; const TextureManager& m_texture_manager;
World& m_world; World& m_world;
bool m_discard_tranparent = true;
bool m_shader_on = true;
int m_shadow_mode = 0;
int m_light_cull_face = 0;
float m_aspect = 0.0f; float m_aspect = 0.0f;
float m_fov = DEFAULT_FOV; float m_fov = DEFAULT_FOV;
glm::mat4 m_p_mat, m_v_mat, m_m_mat, m_mv_mat, m_mvp_mat;
GLuint m_mv_loc; float m_delta_time = 0.0f;
GLuint m_proj_loc;
GLuint m_sky_vbo; float m_width = 0.0f;
GLuint m_text_vbo; float m_height = 0.0f;
GLuint m_outline_indices_vbo;
GLuint m_outline_vbo; glm::mat4 m_p_mat, m_v_mat, m_m_mat, m_mv_mat, m_mvp_mat, m_norm_mat;
GLuint m_ui_vbo;
GLuint m_mv_loc = 0;
GLuint m_proj_loc = 0;
GLuint m_sky_vbo = 0;
GLuint m_text_vbo = 0;
GLuint m_outline_indices_vbo = 0;
GLuint m_outline_vbo = 0;
GLuint m_ui_vbo = 0;
GLuint m_fbo = 0;
GLuint m_screen_texture = 0;
GLuint m_depth_render_buffer = 0;
GLuint m_oit_fbo = 0;
GLuint m_accum_texture = 0;
GLuint m_reveal_texture = 0;
GLuint m_oit_depth_render_buffer = 0;
GLuint m_depth_map_fbo = 0;
GLuint m_depth_map_texture = 0;
GLuint m_quad_vbo = 0;
glm::mat4 m_ui_proj; glm::mat4 m_ui_proj;
glm::mat4 m_ui_m_matrix; glm::mat4 m_ui_m_matrix;
std::unordered_map<std::size_t, Shader> m_shaders; std::unordered_map<std::size_t, Shader> m_shaders;
glm::vec3 m_blend_from_sundir;
glm::vec3 m_blend_to_sundir;
float m_blend_t = 1.0f;
bool m_blend_initialized = false;
static constexpr float BLEND_DURATION = 0.15f;
/*
0 - quad vao
1 - sky vao
2 - outline vao
3 - ui vao
4 - text vao
*/
std::vector<GLuint> m_vao; std::vector<GLuint> m_vao;
std::vector<Vertex2D> m_ui; std::vector<Vertex2D> m_ui;
void init_quad();
void init_text(); void init_text();
void render_outline(); void render_outline();
@@ -60,7 +119,13 @@ private:
void render_text(); void render_text();
void render_ui(); void render_ui();
void render_world(); void render_world();
void render_underwater();
void render_dev_panel(); void render_dev_panel();
glm::vec3 quantize_sun_direction(const glm::vec3& sundir,
float angle_step_deg) const;
glm::vec3 get_smoothed_shadow_sundir(const glm::vec3& raw_shadow_sundir,
float dt);
}; };
} } // namespace Cubed

View File

@@ -1,22 +1,22 @@
#pragma once #pragma once
#include <glad/glad.h> #include <glad/glad.h>
#include <string> #include <string>
#include <unordered_map>
namespace Cubed { namespace Cubed {
class Shader { class Shader {
public: public:
Shader(); Shader();
Shader(const std::string& name, const std::string& v_shader_path, const std::string& f_shader_path); Shader(const std::string& name, const std::string& v_shader_path,
const std::string& f_shader_path);
~Shader(); ~Shader();
Shader(const Shader&) = delete; Shader(const Shader&) = delete;
Shader& operator=(const Shader&) = delete; Shader& operator=(const Shader&) = delete;
Shader(Shader&& shader) noexcept; Shader(Shader&& shader) noexcept;
Shader& operator=(Shader&& shader) noexcept; Shader& operator=(Shader&& shader) noexcept;
void create(const std::string& name, const std::string& v_shader_path, const std::string& f_shader_path); void create(const std::string& name, const std::string& v_shader_path,
const std::string& f_shader_path);
std::size_t hash() const; std::size_t hash() const;
GLuint loc(const std::string& loc) const; GLuint loc(const std::string& loc) const;
const std::string& name() const; const std::string& name() const;
@@ -26,7 +26,7 @@ private:
GLuint m_program = 0; GLuint m_program = 0;
std::size_t m_hash = 0; std::size_t m_hash = 0;
std::string m_name = "-1"; std::string m_name = "-1";
mutable std::unordered_map<std::string, GLint> m_uniform_cache;
}; };
} } // namespace Cubed

View File

@@ -1,22 +1,31 @@
#pragma once #pragma once
#include "Cubed/gameplay/block.hpp"
#include <glad/glad.h> #include <glad/glad.h>
#include <Cubed/gameplay/block.hpp>
#include <Cubed/tools/shader_tools.hpp>
namespace Cubed { namespace Cubed {
class TextureManager { class TextureManager {
private: private:
bool m_need_reload = false; bool m_need_reload = false;
GLuint m_block_status_array; GLuint m_block_status_array = 0;
GLuint m_texture_array; GLuint m_texture_array = 0;
GLuint m_ui_array; GLuint m_cross_plane_array = 0;
GLuint m_ui_array = 0;
GLfloat m_max_aniso = 0.0f; GLfloat m_max_aniso = 0.0f;
int m_aniso = 1; int m_aniso = 1;
std::vector<GLuint> m_item_textures;
void load_block_status(unsigned status_id); void load_block_status(unsigned status_id);
void load_block_texture(unsigned block_id); void load_block_texture(unsigned block_id);
void load_block_item_texture(unsigned id);
void load_cross_plane_texture(unsigned id);
void load_ui_texture(unsigned id); void load_ui_texture(unsigned id);
void init_item();
void init_block();
void init_ui();
void init_block_status();
public: public:
TextureManager(); TextureManager();
@@ -25,7 +34,9 @@ public:
void delet_texture(); void delet_texture();
GLuint get_block_status_array() const; GLuint get_block_status_array() const;
GLuint get_texture_array() const; GLuint get_texture_array() const;
GLuint get_cross_plane_array() const;
GLuint get_ui_array() const; GLuint get_ui_array() const;
const std::vector<GLuint>& item_textures() const;
// Must call after MapTable::init_map() and glfwMakeContextCurrent(window); // Must call after MapTable::init_map() and glfwMakeContextCurrent(window);
void init_texture(); void init_texture();
void hot_reload(); void hot_reload();
@@ -34,5 +45,4 @@ public:
int max_aniso() const; int max_aniso() const;
}; };
} // namespace Cubed
}

View File

@@ -1,24 +1,20 @@
#pragma once #pragma once
#include <Cubed/tools/log.hpp> #include "Cubed/tools/log.hpp"
namespace Cubed { namespace Cubed {
namespace Assert { namespace Assert {
inline void msg(const char* condition, const char* file, inline void msg(const char* condition, const char* file, int line,
int line, const char* func, const char* func, std::string_view message = "") {
std::string_view message = ""
) {
Logger::error("Assertion failed: {} at {}: {} in function {}", Logger::error("Assertion failed: {} at {}: {} in function {}", condition,
condition, file, line, func); file, line, func);
if (message.size()) { if (message.size()) {
Logger::error("Message: {}", message); Logger::error("Message: {}", message);
} }
std::abort(); std::abort();
}
} }
} // namespace Assert
#ifdef DEBUG_MODE #ifdef DEBUG_MODE
#define ASSERT(cond) \ #define ASSERT(cond) \
@@ -30,7 +26,8 @@ namespace Assert {
#define ASSERT_MSG(cond, message) \ #define ASSERT_MSG(cond, message) \
do { \ do { \
if (!(cond)) { \ if (!(cond)) { \
::Cubed::Assert::msg(#cond, __FILE__, __LINE__, __func__, message); \ ::Cubed::Assert::msg(#cond, __FILE__, __LINE__, __func__, \
message); \
} \ } \
} while (0) } while (0)
@@ -39,4 +36,4 @@ namespace Assert {
#define ASSERT_MSG(cond, message) ((void)0) #define ASSERT_MSG(cond, message) ((void)0)
#endif #endif
} } // namespace Cubed

View File

@@ -1,14 +1,23 @@
#pragma once #pragma once
#include <string_view>
#include <cstdint> #include <cstdint>
#include <string_view>
namespace Cubed { namespace Cubed {
namespace HASH { namespace HASH {
inline std::size_t str(std::string_view value) { inline std::size_t str(std::string_view value) {
return std::hash<std::string_view>{}(value); return std::hash<std::string_view>{}(value);
} }
inline uint32_t mix_hash(int32_t a, int32_t b, uint32_t fixed_seed) { inline uint32_t combine_32(uint32_t seed, uint32_t v) {
seed ^= v + 0x9e3779b9 + (seed << 6) + (seed >> 2);
return seed;
}
inline uint32_t chunk_seed_hash(int32_t a, int32_t b, uint32_t fixed_seed) {
uint32_t seed =
combine_32(combine_32(fixed_seed, (uint32_t)a), (uint32_t)b);
return seed;
}
/*
inline uint32_t chunk_seed_hash(int32_t a, int32_t b, uint32_t fixed_seed) {
uint32_t h = fixed_seed; uint32_t h = fixed_seed;
h ^= (uint32_t)a * 0xcc9e2d51u; h ^= (uint32_t)a * 0xcc9e2d51u;
@@ -28,6 +37,8 @@ namespace HASH {
return h; return h;
} }
} */
} } // namespace HASH
} // namespace Cubed

View File

@@ -5,17 +5,18 @@ namespace Cubed {
class Random { class Random {
public: public:
Random(); Random();
Random(unsigned seed);
bool random_bool(double probability); bool random_bool(double probability);
std::mt19937& engine(); std::mt19937& engine();
unsigned seed(); unsigned seed();
void init(unsigned seed); void init(unsigned seed);
int random_int(int min, int max);
float random_float(float min, float max);
private: private:
unsigned int m_seed = 0; unsigned int m_seed = 0;
std::mt19937 m_engine; std::mt19937 m_engine;
}; };
} // namespace Cubed
}

View File

@@ -2,17 +2,15 @@
#include <ft2build.h> #include <ft2build.h>
#include FT_FREETYPE_H #include FT_FREETYPE_H
#include "Cubed/primitive_data.hpp"
#include <glad/glad.h> #include <glad/glad.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <Cubed/primitive_data.hpp>
namespace Cubed { namespace Cubed {
struct Character { struct Character {
glm::vec2 uv_min; glm::vec2 uv_min;
glm::vec2 uv_max; glm::vec2 uv_max;
@@ -28,9 +26,12 @@ public:
Font(); Font();
~Font(); ~Font();
static std::vector<Vertex2D> vertices(const std::string& text, float x = 0.0f, float y = 0.0f, float scale = 1.0f); static std::vector<Vertex2D> vertices(const std::string& text,
float x = 0.0f, float y = 0.0f,
float scale = 1.0f);
static GLuint text_texture(); static GLuint text_texture();
static const std::string& font_path(); static const std::string& font_path();
private: private:
FT_Library m_ft; FT_Library m_ft;
FT_Face m_face; FT_Face m_face;
@@ -39,13 +40,12 @@ private:
float m_texture_height = 64; float m_texture_height = 64;
static inline GLuint m_text_texture; static inline GLuint m_text_texture;
static inline std::string m_font_path{ASSETS_PATH "fonts/IBMPlexSans-Regular.ttf"}; static inline std::string m_font_path{ASSETS_PATH
"fonts/IBMPlexSans-Regular.ttf"};
std::unordered_map<char8_t, Character> m_characters; std::unordered_map<char8_t, Character> m_characters;
void load_character(char8_t c); void load_character(char8_t c);
void setup_font_character(); void setup_font_character();
}; };
} } // namespace Cubed

View File

@@ -1,83 +1,70 @@
#pragma once #pragma once
#include <syncstream>
#include <iostream>
#include <chrono> #include <chrono>
#include <format> #include <format>
#include <iostream>
#include <source_location> #include <source_location>
#include <string> #include <string>
#include <syncstream>
namespace Cubed { namespace Cubed {
namespace Logger { namespace Logger {
enum class Level { enum class Level { TRACE, DEBUG, INFO, ERROR, WARN };
TRACE,
DEBUG,
INFO,
ERROR,
WARN
};
template <typename... Args> template <typename... Args>
inline void info(std::format_string<Args...> fmt, Args&&... args) { inline void info(std::format_string<Args...> fmt, Args&&... args) {
auto now_time = std::chrono:: auto now_time = std::chrono::time_point_cast<std::chrono::seconds>(
time_point_cast<std::chrono::seconds> std::chrono::system_clock::now());
(std::chrono::system_clock::now());
std::string msg = std::vformat(fmt.get(), std::make_format_args(args...)); std::string msg = std::vformat(fmt.get(), std::make_format_args(args...));
std::osyncstream(std::cout) << "\033[1;32m" std::osyncstream(std::cout)
<< std::format("[INFO][{:%Y-%m-%d %H:%M:%S}]", now_time) << "\033[1;32m" << std::format("[INFO][{:%Y-%m-%d %H:%M:%S}]", now_time)
<< msg << msg << "\033[0m"
<< "\033[0m"
<< "\n"; << "\n";
} }
template <typename... Args> template <typename... Args>
inline void error(std::format_string<Args...> fmt, Args&&... args) { inline void error(std::format_string<Args...> fmt, Args&&... args) {
auto now_time = std::chrono:: auto now_time = std::chrono::time_point_cast<std::chrono::seconds>(
time_point_cast<std::chrono::seconds> std::chrono::system_clock::now());
(std::chrono::system_clock::now());
std::string msg = std::vformat(fmt.get(), std::make_format_args(args...)); std::string msg = std::vformat(fmt.get(), std::make_format_args(args...));
std::osyncstream(std::cerr) << "\033[1;31m" std::osyncstream(std::cerr)
<< std::format("[ERROR][{:%Y-%m-%d %H:%M:%S}]", now_time) << "\033[1;31m"
<< msg << std::format("[ERROR][{:%Y-%m-%d %H:%M:%S}]", now_time) << msg
<< "\033[0m" << "\033[0m"
<< "\n"; << "\n";
} }
template <typename... Args> template <typename... Args>
inline void warn(std::format_string<Args...> fmt, Args&&... args) { inline void warn(std::format_string<Args...> fmt, Args&&... args) {
auto now_time = std::chrono:: auto now_time = std::chrono::time_point_cast<std::chrono::seconds>(
time_point_cast<std::chrono::seconds> std::chrono::system_clock::now());
(std::chrono::system_clock::now());
std::string msg = std::vformat(fmt.get(), std::make_format_args(args...)); std::string msg = std::vformat(fmt.get(), std::make_format_args(args...));
std::osyncstream(std::cout) << "\033[1;33m" std::osyncstream(std::cout)
<< std::format("[WARN][{:%Y-%m-%d %H:%M:%S}]", now_time) << "\033[1;33m" << std::format("[WARN][{:%Y-%m-%d %H:%M:%S}]", now_time)
<< msg << msg << "\033[0m"
<< "\033[0m"
<< "\n"; << "\n";
} }
template <typename... Args> template <typename... Args>
inline void log(Level level, std::source_location loc, std::format_string<Args...> fmt, Args&&... args) { inline void log(Level level, std::source_location loc,
auto now_time = std::chrono:: std::format_string<Args...> fmt, Args&&... args) {
time_point_cast<std::chrono::seconds> auto now_time = std::chrono::time_point_cast<std::chrono::seconds>(
(std::chrono::system_clock::now()); std::chrono::system_clock::now());
std::string msg = std::vformat(fmt.get(), std::make_format_args(args...)); std::string msg = std::vformat(fmt.get(), std::make_format_args(args...));
switch (level) { switch (level) {
case Logger::Level::TRACE: case Logger::Level::TRACE:
std::osyncstream(std::cout) << "\033[1;34m" std::osyncstream(std::cout)
<< std::format("[TRACE][{:%Y-%m-%d %H:%M:%S}]", now_time) << "\033[1;34m"
<< "[" << loc.file_name() << ":" << loc.line() << "]" << std::format("[TRACE][{:%Y-%m-%d %H:%M:%S}]", now_time) << "["
<< "[" << loc.function_name() << "]" << loc.file_name() << ":" << loc.line() << "]"
<< msg << "[" << loc.function_name() << "]" << msg << "\033[0m"
<< "\033[0m"
<< "\n"; << "\n";
break; break;
case Logger::Level::DEBUG: case Logger::Level::DEBUG:
std::osyncstream(std::cout) << "\033[1;34m" std::osyncstream(std::cout)
<< std::format("[DEBUG][{:%Y-%m-%d %H:%M:%S}]", now_time) << "\033[1;34m"
<< msg << std::format("[DEBUG][{:%Y-%m-%d %H:%M:%S}]", now_time) << msg
<< "\033[0m" << "\033[0m"
<< "\n"; << "\n";
break; break;
@@ -90,13 +77,9 @@ namespace Logger {
case Logger::Level::ERROR: case Logger::Level::ERROR:
error(fmt, std::forward<Args>(args)...); error(fmt, std::forward<Args>(args)...);
break; break;
}
} }
} } // namespace Logger
}
}
} // namespace Cubed

View File

@@ -3,9 +3,17 @@
namespace Cubed { namespace Cubed {
namespace Math { namespace Math {
void extract_frustum_planes(const glm::mat4& mvp_matrix, std::vector<glm::vec4>& planes);
}
} void extract_frustum_planes(const glm::mat4& mvp_matrix,
std::vector<glm::vec4>& planes);
float smootherstep(float edge0, float edge1, float x);
bool is_aabb_in_frustum(const glm::vec3& center, const glm::vec3& half_extents,
const std::vector<glm::vec4>& planes);
float deterministic_random(int x, int z, uint64_t seed);
glm::vec3 slerp(const glm::vec3& from, const glm::vec3& to, float t);
} // namespace Math
} // namespace Cubed

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