diff --git a/Makefile b/Makefile index 4d94815d..9a53c79e 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,7 @@ BIN_DIR += ./bin ENGINE_SRC_DIR += ./engine/src ENGINE_INC_DIR += ./engine/inc ENGINE_LIB_DIR += ./engine/lib +DEP_SRC_DIR += ./dep/src EXT_SRC_DIR += ./ext CLIENT_SRC_DIR += ./client @@ -49,25 +50,29 @@ SPV_OPTIMIZER += $(VULKAN_SDK_PATH)/Bin/spirv-opt INC_DIR += $(ENGINE_INC_DIR) LIB_DIR += $(ENGINE_LIB_DIR) -INCS += -I$(ENGINE_INC_DIR) -I$(INC_DIR) -I./dep/ #-I/mingw64/include -LIBS += -L$(ENGINE_LIB_DIR) -L$(LIB_DIR) -L$(LIB_DIR)/$(ARCH) -L$(LIB_DIR)/$(PREFIX_PATH) +INCS += -I$(ENGINE_INC_DIR) -I./dep/include/ #-I/mingw64/include/ +LIBS += -L$(ENGINE_LIB_DIR) -L$(LIB_DIR)/$(PREFIX_PATH) -L$(LIB_DIR)/$(ARCH)/$(CC) -L$(LIB_DIR)/$(ARCH) #-L/mingw64/lib/ LINKS += $(UF_LIBS) $(EXT_LIBS) $(DEPS) DEPS += ifneq (,$(findstring win64,$(ARCH))) - REQ_DEPS += $(RENDERER) json:nlohmann png zlib openal ogg freetype curl luajit reactphysics meshoptimizer xatlas simd ctti gltf imgui fmt # ncurses openvr draco discord bullet ultralight-ux + ifneq (,$(findstring zig,$(CC))) + REQ_DEPS += $(RENDERER) json:nlohmann png zlib luajit reactphysics meshoptimizer xatlas simd ctti gltf imgui fmt curl freetype openal ogg # ncurses openvr draco discord bullet ultralight-ux + else + REQ_DEPS += $(RENDERER) json:nlohmann png zlib luajit reactphysics meshoptimizer xatlas simd ctti gltf imgui fmt curl freetype openal ogg # ncurses openvr draco discord bullet ultralight-ux + endif FLAGS += -DUF_ENV_WINDOWS -DUF_ENV_WIN64 -DWIN32_LEAN_AND_MEAN DEPS += -lgdi32 -ldwmapi LINKS += #-Wl,-subsystem,windows else ifneq (,$(findstring dreamcast,$(ARCH))) FLAGS += -DUF_ENV_DREAMCAST - REQ_DEPS += simd opengl gldc json:nlohmann reactphysics png zlib ctti lua fmt # lua ogg openal aldc gltf freetype bullet meshoptimizer draco luajit ultralight-ux ncurses curl openvr discord + REQ_DEPS += simd opengl gldc json:nlohmann reactphysics png zlib ctti lua fmt # ogg openal aldc gltf freetype bullet meshoptimizer draco luajit ultralight-ux ncurses curl openvr discord endif ifneq (,$(findstring vulkan,$(REQ_DEPS))) FLAGS += -DVK_USE_PLATFORM_WIN32_KHR -DUF_USE_VULKAN - DEPS += -lvulkan -lspirv-cross #-lVulkanMemoryAllocator - INCS += -I$(VULKAN_SDK_PATH)/include + DEPS += -lvulkan -lspirv-cross-core -lspirv-cross-cpp #-lVulkanMemoryAllocator + INCS += -I$(VULKAN_SDK_PATH)/include -I./dep/include/spirv_cross/ LIBS += -L$(VULKAN_SDK_PATH)/Lib endif ifneq (,$(findstring opengl,$(REQ_DEPS))) @@ -100,8 +105,8 @@ ifneq (,$(findstring fmt,$(REQ_DEPS))) endif ifneq (,$(findstring imgui,$(REQ_DEPS))) FLAGS += -DUF_USE_IMGUI - INCS += -I./dep/imgui/ - INCS += -I./dep/imgui/backends + INCS += -I./dep/include/imgui/ + INCS += -I./dep/include/imgui/backends endif ifneq (,$(findstring json,$(REQ_DEPS))) FLAGS += -DUF_USE_JSON @@ -222,7 +227,11 @@ endif # SRCS_DLL += $(wildcard $(ENGINE_SRC_DIR)/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*/*/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*/*/*/*.cpp) #SRCS_DLL += $(wildcard $(ENGINE_SRC_DIR)/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*/*/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*/*/*/*.cpp) $(wildcard $(EXT_SRC_DIR)/*.cpp) $(wildcard $(EXT_SRC_DIR)/*/*.cpp) $(wildcard $(EXT_SRC_DIR)/*/*/*.cpp) $(wildcard $(EXT_SRC_DIR)/*/*/*/*.cpp) $(wildcard $(EXT_SRC_DIR)/*/*/*/*/*.cpp) -SRCS_DLL := $(shell find $(ENGINE_SRC_DIR) -name "*.cpp") $(shell find $(EXT_SRC_DIR) -name "*.cpp") +ifneq (,$(findstring zig,$(CC))) + SRCS_DLL := $(shell find $(ENGINE_SRC_DIR) -name "*.cpp") $(shell find $(EXT_SRC_DIR) -name "*.cpp") $(shell find $(DEP_SRC_DIR) -name "*.cpp") $(shell find ./dep/zig/src/ -name "*.cpp") +else + SRCS_DLL := $(shell find $(ENGINE_SRC_DIR) -name "*.cpp") $(shell find $(EXT_SRC_DIR) -name "*.cpp") $(shell find $(DEP_SRC_DIR) -name "*.cpp") +endif OBJS_DLL += $(patsubst %.cpp,%.$(PREFIX).o,$(SRCS_DLL)) BASE_DLL += lib$(LIB_NAME) IM_DLL += $(ENGINE_LIB_DIR)/$(PREFIX_PATH)/$(BASE_DLL).$(TARGET_LIB_EXTENSION).a @@ -234,8 +243,8 @@ EXT_DEPS += -l$(LIB_NAME) $(DEPS) EXT_LINKS += $(UF_LIBS) $(EXT_LIBS) $(EXT_DEPS) EXT_LIB_DIR += $(ENGINE_LIB_DIR)/$(ARCH) -EXT_INCS += -I$(ENGINE_INC_DIR) -I$(EXT_INC_DIR) -I/mingw64/include -EXT_LIBS += -L$(ENGINE_LIB_DIR) -L$(EXT_LIB_DIR) -L$(EXT_LIB_DIR)/$(ARCH) -L$(EXT_LIB_DIR)/$(PREFIX_PATH) -L/mingw64/lib +EXT_INCS += $(INCS) +EXT_LIBS += $(LIBS) #SRCS_EXT_DLL += $(wildcard $(EXT_SRC_DIR)/*.cpp) $(wildcard $(EXT_SRC_DIR)/*/*.cpp) $(wildcard $(EXT_SRC_DIR)/*/*/*.cpp) $(wildcard $(EXT_SRC_DIR)/*/*/*/*.cpp) $(wildcard $(EXT_SRC_DIR)/*/*/*/*/*.cpp) SRCS_EXT_DLL := $(shell find $(EXT_SRC_DIR) -name "*.cpp") @@ -377,4 +386,6 @@ backup: make CC=gcc RENDERER=vulkan clean make CC=clang RENDERER=opengl clean make CC=clang RENDERER=vulkan clean + make CC=zig RENDERER=opengl clean + make CC=zig RENDERER=vulkan clean $(7Z) a -r ../misc/backups/$(shell date +"%Y.%m.%d\ %H-%M-%S").7z . \ No newline at end of file diff --git a/bin/data/config.json b/bin/data/config.json index c1d56d89..13529a97 100644 --- a/bin/data/config.json +++ b/bin/data/config.json @@ -1,7 +1,7 @@ { "engine": { "scenes": { - "start": "SH2_McDonalds", + "start": "McDonalds", "meshes": { "interleaved": false }, "matrix": { "reverseInfinite": true }, "lights": { "enabled": true, @@ -16,9 +16,9 @@ }, "textures": { "max": { - "2D": 512, - "cube": 128, - "3D": 64 + "2D": 1024, + "cube": 1024, + "3D": 128 } }, "vxgi": { @@ -38,6 +38,8 @@ } }, "rt": { + "size": [ 960, 540 ], + "filter": "NEAREST", "defaultRayBounds": [ 0.001, 1024.0 ], "alphaTestOffset": 0.001, "samples": 1, @@ -90,6 +92,7 @@ }, "invariant": { // "multithreaded recording": true + "deferred alias output to swapchain": false, "defaultStageBuffers": true }, "pipelines": { @@ -98,7 +101,7 @@ "vxgi": true, "culling": true, "bloom": false, - "rt": false + "rt": true }, "formats": { "depth": "D32_SFLOAT", @@ -288,13 +291,13 @@ "cursor" : { "visible" : true, "center" : false, - "sensitivity": [ 1.25, 1.25 ], - "smoothing": [ 10, 10 ] + "sensitivity": [ 0.75, 0.75 ], + "smoothing": [ 4, 4 ] }, - "mode" : "borderless", // fullscreen, borderless, windowed + "mode" : "windowed", // fullscreen, borderless, windowed "icon" : "./data/textures/icon.png", - "size" : [ 1920, 1080 ], - // "size" : [ 1280, 720 ], + // "size" : [ 1920, 1080 ], + "size" : [ 1280, 720 ], // "size" : [ 960, 540 ], // "size" : [ 640, 480 ], // "size" : [ 256, 224 ], diff --git a/bin/data/entities/model.json b/bin/data/entities/model.json index b33e2187..655c61d4 100644 --- a/bin/data/entities/model.json +++ b/bin/data/entities/model.json @@ -12,8 +12,16 @@ "model": { "debug": { "no cleanup": false, - "print tree": false, - "print stats": false + "print": { + "tree": false, + "stats": false, + "meshes": false, + "materials": false, + "textures": false + } + }, + "sanitizer": { + "winding order": true }, "exporter": { "enabled": true, @@ -24,14 +32,9 @@ "precision": 4, "combined": false, "encode buffers": true, - "unwrap": true, + "unwrap": true, // "tagged", // "unwrap": "tagged", - "optimize": "tagged", - // "optimize": true, - "quit": true, - "mesh": { - // "print": true - } + "quit": true }, "baking": { "enabled": true, @@ -55,8 +58,11 @@ "rotateCharts": true } }, - // "filter": "NEAREST", - "lightmap": "auto", + "renderer": { + "front face": "ccw", + "cull mode": "back", + "filter": "linear" + }, "flags": { "ATLAS": false, "INVERT": false, @@ -68,6 +74,7 @@ "NORMALS": false }, "lights": { + "lightmap": "auto", // "disable if lightmapped": false, "shadows": true } diff --git a/bin/data/entities/player.json b/bin/data/entities/player.json index c508710d..0cc23dc8 100644 --- a/bin/data/entities/player.json +++ b/bin/data/entities/player.json @@ -14,36 +14,10 @@ "scale": [ 1, 1, 1 ] }, "assets": [ - { "filename": "./playerModel.json", "delay": 1.0, "single threaded": true }, + "./playerModel.json", "./hands.json" ], "system": { - "physics": { - "movement": { - "walk": 1, - "move": 8, - "run": 16, - "rotate": 1.5, - "air": 0.1, - - "crouch": 1, - "jump": [ 0, 4, 0 ], - "look": 0.75 - }, - - "gravity": [ 0, -9.81, 0 ], - "inertia": [ 0, 0, 0 ], - - "type": "capsule", - "radius": 1, - "height": 2, - - "mass": 100, - "friction": 0.8, - "restitution": 0.0, - - "shared": false - }, "hot reload": { "enabled": true } @@ -74,6 +48,36 @@ ] } }, + "movement": { + "walk": 1, + "move": 4, + "run": 16, + "rotate": 1.5, + "air": 0.1, + + "crouch": 1, + "jump": [ 0, 4, 0 ], + "look": 1, + "floored": { + "feet": [ 0, -1.5, 0 ], + "floor": [ 0, -0.5, 0 ], + "print": false + } + }, + "physics": { + "gravity": [ 0, -9.81, 0 ], + "inertia": [ 0, 0, 0 ], + + "type": "capsule", + "radius": 1, + "height": 2, + + "mass": 100, + "friction": 0.95, + "restitution": 0.0, + + "shared": false + }, "camera": { "offset": [ 0, 0, 0 ], "position" : [ 0, 1.8, 0 ], diff --git a/bin/data/scenes/cornell/player.json b/bin/data/scenes/cornell/player.json index 72aafad1..ddfc0fa3 100644 --- a/bin/data/scenes/cornell/player.json +++ b/bin/data/scenes/cornell/player.json @@ -3,25 +3,10 @@ "assets": [ // { "filename": "/gui/hud/hud.json", "delay": 0 } ], - "system": { - "physics": { - "gravity": [ 0, 0, 0 ] - }, - "hot reload": { - "enabled": true - } - }, "metadata": { - "overlay": { - "floating": true - }, - "collider": false, - "light": { - "should": false, - "color": [1, 1, 1], - "position": [ 0, 2.5, 0 ], - "power": 1, - "radius": [0.001, 32] + "physics": { + "collider": false, + "gravity": [ 0, 0, 0 ] } } } \ No newline at end of file diff --git a/bin/data/scenes/mcdonalds/door.json b/bin/data/scenes/mcdonalds/door.json index 41caf066..4da4924a 100644 --- a/bin/data/scenes/mcdonalds/door.json +++ b/bin/data/scenes/mcdonalds/door.json @@ -1,6 +1,6 @@ { "assets": ["./scripts/door.lua"], - "system": { + "metadata": { "physics": { "type": "bounding box", "recenter": true diff --git a/bin/data/scenes/mcdonalds/mcdonalds.json b/bin/data/scenes/mcdonalds/mcdonalds.json index 7b9c9e15..c30e80dd 100644 --- a/bin/data/scenes/mcdonalds/mcdonalds.json +++ b/bin/data/scenes/mcdonalds/mcdonalds.json @@ -15,13 +15,17 @@ "metadata": { "model": { "baking": { - "enabled": false, + "enabled": true, "resolution": 2048, "settings": { "useInputMeshUvs": false } }, - // "cull mode": "none", + "renderer": { + "front face": "cw", + "cull mode": "back", + "filter": "linear" + }, "tags": { "/^worldspawn/": { "physics": { "type": "mesh", "static": true }, @@ -49,7 +53,9 @@ "func_physbox_5212": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } }, "func_physbox_5548": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } }, - "func_physbox_5931": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } } + "func_physbox_5931": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } }, + + "tools/toolsnodraw": { "material": { "base": [0, 0, 0, 0] } } } } } diff --git a/bin/data/scenes/mcdonalds/player.json b/bin/data/scenes/mcdonalds/player.json index dec26007..e2c6058c 100644 --- a/bin/data/scenes/mcdonalds/player.json +++ b/bin/data/scenes/mcdonalds/player.json @@ -3,17 +3,8 @@ "assets": [ // { "filename": "/gui/hud/hud.json", "delay": 0 } ], + "system": { + }, "metadata": { - "overlay": { - "floating": true - }, - "collider": true, - "light": { - "should": false, - "color": [1, 1, 1], - "position": [ 0, 2.5, 0 ], - "power": 1, - "radius": [0.001, 32] - } } } \ No newline at end of file diff --git a/bin/data/scenes/mcdonalds/scene.json b/bin/data/scenes/mcdonalds/scene.json index 314507fe..c949a3cd 100644 --- a/bin/data/scenes/mcdonalds/scene.json +++ b/bin/data/scenes/mcdonalds/scene.json @@ -36,8 +36,8 @@ "exposure": 1.0, "gamma": 1.0, "brightnessThreshold": 1.2, - "ambient": [ 0, 0, 0 ], - // "ambient": [ 0.025, 0.025, 0.025 ], + // "ambient": [ 0, 0, 0 ], + "ambient": [ 0.025, 0.025, 0.025 ], // "ambient": [ 0.075, 0.075, 0.075 ], // "ambient": [ 0.1, 0.1, 0.1 ], // "ambient": [ 0.4, 0.4, 0.4 ], diff --git a/bin/data/scenes/sh2_mcdonalds/door.json b/bin/data/scenes/sh2_mcdonalds/door.json index 1f268ed9..8ba9c58c 100644 --- a/bin/data/scenes/sh2_mcdonalds/door.json +++ b/bin/data/scenes/sh2_mcdonalds/door.json @@ -1,6 +1,6 @@ { "assets": ["./scripts/door.lua"], - "system": { + "metadata": { "physics": { "mass": 0, "inertia": [0, 0, 0], diff --git a/bin/data/scenes/sh2_mcdonalds/player.json b/bin/data/scenes/sh2_mcdonalds/player.json index 18145681..f41a4d75 100644 --- a/bin/data/scenes/sh2_mcdonalds/player.json +++ b/bin/data/scenes/sh2_mcdonalds/player.json @@ -5,16 +5,5 @@ "./playerLight.json" ], "metadata": { - "overlay": { - "floating": true - }, - "collider": true, - "light": { - "should": false, - "color": [1, 1, 1], - "position": [ 0, 2.5, 0 ], - "power": 1, - "radius": [0.001, 32] - } } } \ No newline at end of file diff --git a/bin/data/scenes/sh2_mcdonalds/prop.json b/bin/data/scenes/sh2_mcdonalds/prop.json index 2d33ce82..47b31635 100644 --- a/bin/data/scenes/sh2_mcdonalds/prop.json +++ b/bin/data/scenes/sh2_mcdonalds/prop.json @@ -1,6 +1,6 @@ { "assets": [], - "system": { + "metadata": { "physics": { "mass": 0, "inertia": [0, 0, 0], diff --git a/bin/data/scenes/sh2_mcdonalds/sh2_mcdonalds.json b/bin/data/scenes/sh2_mcdonalds/sh2_mcdonalds.json index 3143edd2..c7802fbe 100644 --- a/bin/data/scenes/sh2_mcdonalds/sh2_mcdonalds.json +++ b/bin/data/scenes/sh2_mcdonalds/sh2_mcdonalds.json @@ -8,8 +8,6 @@ ], "metadata": { "model": { - "cull mode": "none", - "alpha mode": "BLEND", "baking": { "enabled": true, "resolution": 1024, @@ -17,12 +15,18 @@ "useInputMeshUvs": false } }, + "renderer": { + "front face": "cw", + "cull mode": "back", + "filter": "linear" + }, "tags": { "/^worldspawn/": { "physics": { "type": "mesh", "static": true }, "grid": { "size": [3,1,3], "epsilon": 1.0, "cleanup": true, "print": true } }, "/^cb$/": { + "physics": { "type": "mesh", "static": true }, "grid": { "size": [6,1,6], "epsilon": 1.0, "cleanup": true, "print": true } }, // "worldspawn_sh2": { "physics": { "type": "mesh", "static": true } }, @@ -101,7 +105,9 @@ "prop_physics_override_5810": { "action": "load", "payload": { "import": "./prop.json" } }, "prop_physics_override_5814": { "action": "load", "payload": { "import": "./prop.json" } }, "prop_physics_override_5822": { "action": "load", "payload": { "import": "./prop.json" } }, - "prop_physics_override_5824": { "action": "load", "payload": { "import": "./prop.json" } } + "prop_physics_override_5824": { "action": "load", "payload": { "import": "./prop.json" } }, + + "tools/toolsnodraw": { "material": { "base": [0, 0, 0, 0] } } } } } diff --git a/bin/data/scenes/sm64/loading.json b/bin/data/scenes/sm64/loading.json new file mode 100644 index 00000000..0ec6c59c --- /dev/null +++ b/bin/data/scenes/sm64/loading.json @@ -0,0 +1,32 @@ +{ + "name": "Gui: Loading", + "type": "Object", + "behaviors": [ + // "GuiBehavior" + ], + "assets": [ + { "filename": "./mcdonalds.json", "delay": 0 } + ], + "ignore": false, + "transform": { + "position": [ -0.830591, -0.699509, 0 ], + "rotation": { + "axis": [ 1, 0, 0 ], + "angle": 0 + }, + "scale": [ 0.258737, 0.115371, 1 ] + }, + "metadata": { + "uv": [ 0, 0, 1, 1 ], + "color": [ 1, 1, 1, 0.1 ], + "location": "", + "scaling": "relative", + "text settings": { + "stroke": [ 1, 0.749, 0.368, 1 ], + "color": [ 1, 0.749, 0.368, 1 ], + + "string": "Loading...", + "string1": "コマンド" + } + } +} \ No newline at end of file diff --git a/bin/data/scenes/sm64/player.json b/bin/data/scenes/sm64/player.json new file mode 100644 index 00000000..f56e6fd8 --- /dev/null +++ b/bin/data/scenes/sm64/player.json @@ -0,0 +1,19 @@ +{ + "import": "/player.json", + "assets": [ + // { "filename": "/gui/hud/hud.json", "delay": 0 } + ], + "metadata": { + "movement": { + "jump": [0, 1, 0], + "floored": { + "feet": [ 0, 0, 0 ], + "floor": [ 0, -0.8, 0 ] + } + }, + "physics": { + "radius": 0.25, + "height": 0.25 + } + } +} \ No newline at end of file diff --git a/bin/data/scenes/sm64/scene.json b/bin/data/scenes/sm64/scene.json new file mode 100644 index 00000000..dc7f523a --- /dev/null +++ b/bin/data/scenes/sm64/scene.json @@ -0,0 +1,89 @@ +{ + "import": "/scene.json", + "assets": [ + // "./loading.json", + "./sm64.json" + ], + "system": { + "hot reload": { + "enabled": true + }, + "renderer": { + "shader": { + "mode": 1, + "scalar": 16, + "parameters": [ 0, 0, 0, "time" ], + "frame accumulate limit": 0 + }, + "clear values": [ + [ 1, 1, 1, 0 ] + ] + } + }, + "metadata": { + "menus": { + "pause": "/gui/pause/menu.json" + }, + "bloom": { + "scale": 6.0, + "strength": 0.125, + "sigma": 0.125, + "samples": 8 + }, + "light": { + "exposure": 1.0, + "gamma": 1.0, + "brightnessThreshold": 1.2, + // "ambient": [ 0, 0, 0 ], + // "ambient": [ 0.025, 0.025, 0.025 ], + // "ambient": [ 0.075, 0.075, 0.075 ], + // "ambient": [ 0.1, 0.1, 0.1 ], + "ambient": [ 0.4, 0.4, 0.4 ], + // "ambient": [ 0.8, 0.8, 0.8 ], + + "fog-": { + "color": [ 0.5, 0.5, 0.5 ], + "range": [ 16, 32 ], + "step scale": 2, + "absorbtion": 0.01, + "density": { + "threshold": 0.35, + "multiplier": 5.0, + "scale": 25.0, + "offset": [0, -1, 1], + "timescale": 8 + } + }, + "should": true, + "shadows": true + }, + "noise": { + "size": [ 32, 32, 32 ] + }, + "vxgi": { + /* + "limiter": 1, + "size": 96, + "dispatch": 8, + "cascades": 2, + "cascadePower": 4, + "voxelizeScale": 1, + "shadows": 0, + */ + "occlusionFalloff": 2, + "traceStartOffsetFactor": 1, + "granularity": 2, + "extents": { + "min": [ -1.5, -1.5, -1.5 ], + "max": [ 1.5, 1.5, 1.5 ] + } + }, + "rt": { + "defaultRayBounds": [ 0.001, 1024.0 ], + "alphaTestOffset": 1.125, + "samples": 1, + "paths": 1, + "frameAccumulationMinimum": 0 + } + } +} \ No newline at end of file diff --git a/bin/data/scenes/sm64/sm64.json b/bin/data/scenes/sm64/sm64.json new file mode 100644 index 00000000..8109fd6c --- /dev/null +++ b/bin/data/scenes/sm64/sm64.json @@ -0,0 +1,35 @@ +{ + "import": "/model.json", + "assets": [ + // { "filename": "./models/sm64_bbb.glb" } + { "filename": "./models/sm64_bbb/graph.json" } + ], + "metadata": { + "model": { + "baking": { + "enabled": true, + "resolution": 2048, + "settings": { + "useInputMeshUvs": false + } + }, + "renderer": { + "front face": "cw", + "cull mode": "none", + "filter": "nearest" + }, + "tags": { + "/^worldspawn/": { + "physics": { "type": "mesh", "static": true }, + "grid": { "size": [3,1,3], "epsilon": 1.0, "cleanup": true, "print": true }, + // "optimize mesh": { "simplify": 0 }, + "unwrap mesh": true + }, + "info_player_spawn": { "action": "attach", "filename": "./player.json" }, + + "Material.071_574B138E_c.bmp": { "material": { "modeAlpha": "BLEND" } }, + "Material.070_41A41EE3_c.bmp": { "material": { "modeAlpha": "BLEND" } } + } + } + } +} \ No newline at end of file diff --git a/bin/data/scenes/ss2/lift.json b/bin/data/scenes/ss2/lift.json index 4fa0e75d..d94f0d54 100644 --- a/bin/data/scenes/ss2/lift.json +++ b/bin/data/scenes/ss2/lift.json @@ -1,6 +1,6 @@ { "assets": [ "./scripts/lift.lua" ], - "system": { + "metadata": { "physics": { "type": "bounding box", "recenter": true, diff --git a/bin/data/scenes/ss2/medsci.json b/bin/data/scenes/ss2/medsci.json index 2c02a9ba..c940d22c 100644 --- a/bin/data/scenes/ss2/medsci.json +++ b/bin/data/scenes/ss2/medsci.json @@ -5,7 +5,7 @@ // { "filename": "./test.json", "delay": 1 }, // { "filename": "./models/tiny_msci.glb" } - { "filename": "./models/tiny_msci/graph.json" } + // { "filename": "./models/tiny_msci/graph.json" } // { "filename": "./models/micro_sci.glb" } // { "filename": "./models/micro_sci/graph.json" } @@ -14,7 +14,7 @@ // { "filename": "./models/msci/graph.json" } // { "filename": "./models/medsci.glb" } - // { "filename": "./models/medsci/graph.json" } + { "filename": "./models/medsci/graph.json" } ], "metadata": { "model": { @@ -22,7 +22,11 @@ "enabled": true, "resolution": 1024 }, - "filter": "LINEAR", + "renderer": { + "front face": "cw", + "cull mode": "back", + "filter": "linear" + }, "tags": { "/^worldspawn/": { "physics": { "type": "mesh", "static": true }, diff --git a/bin/data/scenes/ss2/player.json b/bin/data/scenes/ss2/player.json index 49c574ca..1c608815 100644 --- a/bin/data/scenes/ss2/player.json +++ b/bin/data/scenes/ss2/player.json @@ -12,16 +12,12 @@ "scale": [ 1, 1, 1 ] }, "metadata": { - "overlay": { - "floating": true - }, - "collider": true, - "light": { - "should": false, - "color": [1, 1, 1], - "position": [ 0, 2.5, 0 ], - "power": 1, - "radius": [0.001, 32] + "movement": { + "floored": { + "feet": [ 0, -1.5, 0 ], + "floor": [ 0, -0.5, 0 ], + "print": false + } } } } \ No newline at end of file diff --git a/bin/data/shaders/common/vxgi.h b/bin/data/shaders/common/vxgi.h index 3dae4fc3..2b3b6605 100644 --- a/bin/data/shaders/common/vxgi.h +++ b/bin/data/shaders/common/vxgi.h @@ -135,7 +135,7 @@ void indirectLighting() { const float DIFFUSE_INDIRECT_FACTOR = 1.0f / float(CONES_COUNT); const float SPECULAR_CONE_APERTURE = clamp(tan(PI * 0.5f * surface.material.roughness), 0.0174533f, PI); // tan( R * PI * 0.5f * 0.1f ); - const float SPECULAR_INDIRECT_FACTOR = (1.0 - surface.material.metallic) * 0.5; // 1.0f; + const float SPECULAR_INDIRECT_FACTOR = (1.0 - surface.material.metallic) * 0.25; // 1.0f; vec4 indirectDiffuse = vec4(0); vec4 indirectSpecular = vec4(0); diff --git a/bin/data/shaders/raytrace/shader.ray-gen.glsl b/bin/data/shaders/raytrace/shader.ray-gen.glsl index 2efb2241..7bc973d8 100644 --- a/bin/data/shaders/raytrace/shader.ray-gen.glsl +++ b/bin/data/shaders/raytrace/shader.ray-gen.glsl @@ -6,8 +6,8 @@ #pragma shader_stage(raygen) layout (constant_id = 0) const uint PASSES = 2; layout (constant_id = 1) const uint TEXTURES = 512; -layout (constant_id = 2) const uint CUBEMAPS = 128; -layout (constant_id = 3) const uint CASCADES = 4; +layout (constant_id = 2) const uint CUBEMAPS = 8; +layout (constant_id = 3) const uint CASCADES = 1; #define COMPUTE 1 #define PBR 1 @@ -70,17 +70,18 @@ layout (std140, binding = 6) readonly buffer Lights { layout (binding = 7) uniform sampler2D samplerTextures[TEXTURES]; layout (binding = 8) uniform samplerCube samplerCubemaps[CUBEMAPS]; - +layout (binding = 9) uniform sampler3D samplerNoise; #if VXGI - layout (binding = 14) uniform usampler3D voxelId[CASCADES]; - layout (binding = 15) uniform sampler3D voxelNormal[CASCADES]; - layout (binding = 16) uniform sampler3D voxelRadiance[CASCADES]; + layout (binding = 10) uniform usampler3D voxelId[CASCADES]; + layout (binding = 11) uniform sampler3D voxelNormal[CASCADES]; + layout (binding = 12) uniform sampler3D voxelRadiance[CASCADES]; #endif layout (location = 0) rayPayloadEXT RayTracePayload payload; #include "../common/functions.h" #include "../common/light.h" +#include "../common/fog.h" #if VXGI #include "../common/vxgi.h" #endif diff --git a/bin/dreamcast/config.json b/bin/dreamcast/config.json index c674c0b2..df8ede35 100644 --- a/bin/dreamcast/config.json +++ b/bin/dreamcast/config.json @@ -1,7 +1,7 @@ { "engine": { "scenes": { - "start": "SS2", + "start": "SM64", "meshes": { "interleaved": false }, "matrix": { "reverseInfinite": false }, "lights": { "enabled": false, diff --git a/client/client/ext.cpp b/client/client/ext.cpp index c45ae933..c865b3d7 100644 --- a/client/client/ext.cpp +++ b/client/client/ext.cpp @@ -17,7 +17,6 @@ uf::Window client::window; uf::Serializer client::config; void client::initialize() { - uf::IoStream::ncurses = true; uf::renderer::device.window = &client::window; ext::load(); @@ -111,6 +110,9 @@ void client::initialize() { #if UF_ENV_DREAMCAST client::window.pollEvents(); #endif + + { + } } void client::tick() { diff --git a/client/main.cpp b/client/main.cpp index 310e3d2d..d20ab961 100644 --- a/client/main.cpp +++ b/client/main.cpp @@ -67,6 +67,7 @@ int main(int argc, char** argv){ if ( timer.elapsed().asDouble() >= next ) { // UF_MSG_INFO("Waiting for " << ( client::ready ? "client" : "extension / engine" ) << " to initialize... Retrying in " << next << " seconds."); + UF_MSG_INFO("Waiting for {} to initialize; retrying in {} seconds", ( client::ready ? "client" : "extension / engine" ), next); next *= 2; } } diff --git a/engine/inc/uf/engine/graph/graph.h b/engine/inc/uf/engine/graph/graph.h index 4e15e9f3..87e89f4c 100644 --- a/engine/inc/uf/engine/graph/graph.h +++ b/engine/inc/uf/engine/graph/graph.h @@ -61,8 +61,6 @@ namespace pod { // Local storage, used for save/load struct Storage { - - uf::stl::KeyMap instances; uf::stl::KeyMap instanceAddresses; uf::stl::KeyMap> primitives; diff --git a/engine/inc/uf/ext/opengl/opengl.h b/engine/inc/uf/ext/opengl/opengl.h index 84895359..4a75e63d 100644 --- a/engine/inc/uf/ext/opengl/opengl.h +++ b/engine/inc/uf/ext/opengl/opengl.h @@ -38,7 +38,6 @@ namespace ext { extern UF_API bool multithreadedRecording; extern UF_API uf::stl::string deferredMode; - extern UF_API bool deferredReconstructPosition; extern UF_API bool deferredAliasOutputToSwapchain; extern UF_API bool deferredSampling; extern UF_API bool multiview; diff --git a/engine/inc/uf/ext/reactphysics/reactphysics.h b/engine/inc/uf/ext/reactphysics/reactphysics.h index 71beb221..f0361cea 100644 --- a/engine/inc/uf/ext/reactphysics/reactphysics.h +++ b/engine/inc/uf/ext/reactphysics/reactphysics.h @@ -104,8 +104,7 @@ namespace ext { // ray casting float UF_API rayCast( const pod::Vector3f&, const pod::Vector3f& ); - float UF_API rayCast( const pod::Vector3f&, const pod::Vector3f&, size_t& ); - float UF_API rayCast( const pod::Vector3f&, const pod::Vector3f&, uf::Object*& ); + float UF_API rayCast( const pod::Vector3f&, const pod::Vector3f&, uf::Object*, uf::Object*& ); // allows noclip void UF_API activateCollision( pod::PhysicsState&, bool = true ); diff --git a/engine/inc/uf/ext/vulkan/vulkan.h b/engine/inc/uf/ext/vulkan/vulkan.h index 1979e85b..12a3358a 100644 --- a/engine/inc/uf/ext/vulkan/vulkan.h +++ b/engine/inc/uf/ext/vulkan/vulkan.h @@ -75,7 +75,6 @@ namespace ext { extern UF_API bool multithreadedRecording; extern UF_API uf::stl::string deferredMode; - extern UF_API bool deferredReconstructPosition; extern UF_API bool deferredAliasOutputToSwapchain; extern UF_API bool deferredSampling; extern UF_API bool multiview; diff --git a/engine/inc/uf/macros.h b/engine/inc/uf/macros.h index d45eeaa9..da0b998b 100644 --- a/engine/inc/uf/macros.h +++ b/engine/inc/uf/macros.h @@ -27,7 +27,7 @@ #if UF_USE_FMT #define UF_MSG(CATEGORY, ...) uf::io::log(CATEGORY, __FILE__, __FUNCTION__, __LINE__, ::fmt::format(__VA_ARGS__)); #else - #define UF_MSG(CATEGORY, ...) uf::io::log(CATEGORY, __FILE__, __FUNCTION__, __LINE__, #__VA_ARGS__); // std::cout << "[" << CATEGORY << "] [" << __FILE__ << ":" << __FUNCTION__ << "@" << __LINE__ << "]" << std::endl;; + #define UF_MSG(CATEGORY, ...) uf::io::log(CATEGORY, __FILE__, __FUNCTION__, __LINE__, #__VA_ARGS__); #endif #define UF_MSG_DEBUG(...) if (UF_DEBUG) UF_MSG("DEBUG", __VA_ARGS__); @@ -45,7 +45,8 @@ #define UF_NO_EXCEPTIONS 0 #define UF_EXCEPTIONS 1 #define UF_EXCEPTION(...) {\ - throw std::runtime_error(UF_MSG_ERROR(__VA_ARGS__));\ + auto msg = UF_MSG_ERROR(__VA_ARGS__);\ + throw std::runtime_error(msg);\ } #endif @@ -81,7 +82,7 @@ TIMER_TRACE_PREV = TIMER_TRACE_CUR;\ } -#define UF_TIMER_MULTITRACE_END(X) UF_MSG_DEBUG(X); +#define UF_TIMER_MULTITRACE_END(...) UF_MSG_DEBUG(__VA_ARGS__); #include #define TYPE_SANITIZE(T) std::remove_cv_t> @@ -108,7 +109,7 @@ #define ALIGNED_SIZE(V, A) ((V + A - 1) & ~(A - 1)) -#define UF_MSG_PEEK(X) #X << ": " << X +#define UF_MSG_PEEK(X) #X"="+std::to_string(X) #if UF_ENV_DREAMCAST #define DC_STATS() {\ diff --git a/engine/inc/uf/utils/io/fmt.h b/engine/inc/uf/utils/io/fmt.h index b7217426..df1f59a8 100644 --- a/engine/inc/uf/utils/io/fmt.h +++ b/engine/inc/uf/utils/io/fmt.h @@ -3,12 +3,7 @@ #if UF_USE_FMT #if UF_ENV_DREAMCAST #define FMT_HEADER_ONLY - // #include - - // #include - // #include #include - // #include #else // #include #endif diff --git a/engine/inc/uf/utils/math/vector/simd.inl b/engine/inc/uf/utils/math/vector/simd.inl index d7a5e6c3..2c00d536 100644 --- a/engine/inc/uf/utils/math/vector/simd.inl +++ b/engine/inc/uf/utils/math/vector/simd.inl @@ -139,8 +139,11 @@ inline uf::simd::value /*UF_API*/ uf::simd::sqrt( uf::simd::value } inline float /*UF_API*/ uf::simd::dot( uf::simd::value x, uf::simd::value y ) { #if SSE_INSTR_SET >= 5 + float res; __m128 result = _mm_dp_ps(x, y, 0xFF); - return uf::simd::vector( result )[0]; + _mm_store_ss(&res, result); + return res; +// return uf::simd::vector( result )[0]; #elif SSE_INSTR_SET >= 3 __m128 mulRes = _mm_mul_ps(x, y); __m128 shufReg = _mm_movehdup_ps(mulRes); @@ -155,13 +158,13 @@ inline float /*UF_API*/ uf::simd::dot( uf::simd::value x, uf::simd::value inline uf::simd::value /*UF_API*/ uf::simd::load( const int32_t* f ) { #if SSE_INSTR_SET >= 3 #if UF_VECTOR_ALIGNED - return _mm_load_si128(f); + return _mm_load_si128((__m128i*) f); #else - if ( uf::aligned(f, 16) ) return _mm_load_si128(f); + if ( uf::aligned(f, 16) ) return _mm_load_si128((__m128i*) f); alignas(16) int32_t s[4]; memcpy( &s[0], f, sizeof(int32_t) * 4 ); - return _mm_load_si128(s); + return _mm_load_si128((__m128i*) s); #endif #else return uf::simd::value( f[0], f[1], f[2], f[3] ); @@ -170,12 +173,12 @@ inline uf::simd::value /*UF_API*/ uf::simd::load( const int32_t* f ) { inline void /*UF_API*/ uf::simd::store( uf::simd::value v, int32_t* f ) { #if SSE_INSTR_SET >= 3 #if UF_VECTOR_ALIGNED - return _mm_store_si128(f, v); + return _mm_store_si128((__m128i*) f, v); #else - if ( uf::aligned(f, 16) ) return _mm_store_si128(f, v); + if ( uf::aligned(f, 16) ) return _mm_store_si128((__m128i*) f, v); alignas(16) int32_t s[4]; - _mm_store_si128(&s[0], v); + _mm_store_si128((__m128i*) &s[0], v); memcpy( f, &s[0], sizeof(int32_t) * 4 ); #endif #else @@ -246,13 +249,13 @@ inline int32_t /*UF_API*/ uf::simd::dot( uf::simd::value x, uf::simd::v inline uf::simd::value /*UF_API*/ uf::simd::load( const uint32_t* f ) { #if SSE_INSTR_SET >= 3 #if UF_VECTOR_ALIGNED - return _mm_load_si128(f); + return _mm_load_si128((__m128i*) f); #else - if ( uf::aligned(f, 16) ) return _mm_load_si128(f); + if ( uf::aligned(f, 16) ) return _mm_load_si128((__m128i*) f); alignas(16) uint32_t s[4]; memcpy( &s[0], f, sizeof(uint32_t) * 4 ); - return _mm_load_si128(s); + return _mm_load_si128((__m128i*) &s[0]); #endif #else return uf::simd::value( f[0], f[1], f[2], f[3] ); @@ -261,12 +264,12 @@ inline uf::simd::value /*UF_API*/ uf::simd::load( const uint32_t* f ) inline void /*UF_API*/ uf::simd::store( uf::simd::value v, uint32_t* f ) { #if SSE_INSTR_SET >= 3 #if UF_VECTOR_ALIGNED - return _mm_store_si128(f, v); + return _mm_store_si128((__m128i*) f, v); #else - if ( uf::aligned(f, 16) ) return _mm_store_si128(f, v); + if ( uf::aligned(f, 16) ) return _mm_store_si128((__m128i*) f, v); alignas(16) uint32_t s[4]; - _mm_store_si128(&s[0], v); + _mm_store_si128((__m128i*) &s[0], v); memcpy( f, &s[0], sizeof(uint32_t) * 4 ); #endif #else diff --git a/engine/inc/uf/utils/memory/key_map.h b/engine/inc/uf/utils/memory/key_map.h index 27f1c2d9..cfefa373 100644 --- a/engine/inc/uf/utils/memory/key_map.h +++ b/engine/inc/uf/utils/memory/key_map.h @@ -15,8 +15,10 @@ namespace uf { uf::stl::unordered_map indices; T& operator[]( const Key& key ); + void reserve( size_t i ); uf::stl::vector flatten() const; + void clear(); }; } } @@ -38,6 +40,13 @@ void uf::stl::KeyMap::reserve( size_t i ) { map.reserve(i); } +template +void uf::stl::KeyMap::clear() { + keys.clear(); + indices.clear(); + map.clear(); +} + template uf::stl::vector uf::stl::KeyMap::flatten() const { uf::stl::vector res; res.reserve(keys.size()); diff --git a/engine/inc/uf/utils/thread/thread.h b/engine/inc/uf/utils/thread/thread.h index 86fe582c..6a1e9eca 100644 --- a/engine/inc/uf/utils/thread/thread.h +++ b/engine/inc/uf/utils/thread/thread.h @@ -91,7 +91,7 @@ namespace uf { pod::Thread& UF_API get( const uf::stl::string& ); bool UF_API isMain(); - pod::Thread& currentThread(); + pod::Thread& UF_API currentThread(); /* Acts on thread */ void UF_API start( pod::Thread& ); diff --git a/engine/lib/win64/discord_game_sdk.bundle b/engine/lib/win64/other/discord_game_sdk.bundle similarity index 100% rename from engine/lib/win64/discord_game_sdk.bundle rename to engine/lib/win64/other/discord_game_sdk.bundle diff --git a/engine/lib/win64/openvr_api.dll.sig b/engine/lib/win64/other/openvr_api.dll.sig similarity index 100% rename from engine/lib/win64/openvr_api.dll.sig rename to engine/lib/win64/other/openvr_api.dll.sig diff --git a/engine/lib/win64/openvr_api.pdb b/engine/lib/win64/other/openvr_api.pdb similarity index 100% rename from engine/lib/win64/openvr_api.pdb rename to engine/lib/win64/other/openvr_api.pdb diff --git a/engine/lib/win64/zig/libalut.pdb b/engine/lib/win64/zig/libalut.pdb new file mode 100644 index 00000000..1ba425e9 Binary files /dev/null and b/engine/lib/win64/zig/libalut.pdb differ diff --git a/engine/src/engine/asset/asset.cpp b/engine/src/engine/asset/asset.cpp index c876433d..bc8e1f8a 100644 --- a/engine/src/engine/asset/asset.cpp +++ b/engine/src/engine/asset/asset.cpp @@ -264,8 +264,8 @@ uf::stl::string uf::Asset::load(const uf::Asset::Payload& payload ) { asset = uf::graph::load( filename, metadata[payload.filename] ); uf::graph::process( asset ); #if !UF_ENV_DREAMCAST - if ( asset.metadata["debug"]["print stats"].as() ) UF_MSG_INFO("{}", uf::graph::stats( asset )); - if ( asset.metadata["debug"]["print tree"].as() ) UF_MSG_INFO("{}", uf::graph::print( asset )); + if ( asset.metadata["debug"]["print"]["stats"].as() ) UF_MSG_INFO("{}", uf::graph::stats( asset )); + if ( asset.metadata["debug"]["print"]["tree"].as() ) UF_MSG_INFO("{}", uf::graph::print( asset )); #endif if ( !asset.metadata["debug"]["no cleanup"].as() ) uf::graph::cleanup( asset ); } break; diff --git a/engine/src/engine/graph/decode.cpp b/engine/src/engine/graph/decode.cpp index aad34557..58352ed7 100644 --- a/engine/src/engine/graph/decode.cpp +++ b/engine/src/engine/graph/decode.cpp @@ -259,6 +259,44 @@ namespace { mesh.updateDescriptor(); + #if 0 + // swap winding order + if ( graph.metadata["decode"]["invert winding order"].as() ) { + if ( mesh.index.count ) { + uf::Mesh::Attribute indexAttribute = mesh.index.attributes.front(); + size_t tri[3]; + for ( size_t i = 0; i < mesh.index.count / 3; ++i ) { + switch ( mesh.index.size ) { + case sizeof(uint8_t): { + uint8_t* pointer = (uint8_t*) (indexAttribute.pointer); + tri[0] = pointer[i * 3 + 0]; + tri[2] = pointer[i * 3 + 2]; + + pointer[i * 3 + 0] = tri[2]; + pointer[i * 3 + 2] = tri[0]; + } break; + case sizeof(uint16_t): { + uint16_t* pointer = (uint16_t*) (indexAttribute.pointer); + tri[0] = pointer[i * 3 + 0]; + tri[2] = pointer[i * 3 + 2]; + + pointer[i * 3 + 0] = tri[2]; + pointer[i * 3 + 2] = tri[0]; + } break; + case sizeof(uint32_t): { + uint32_t* pointer = (uint32_t*) (indexAttribute.pointer); + tri[0] = pointer[i * 3 + 0]; + tri[2] = pointer[i * 3 + 2]; + + pointer[i * 3 + 0] = tri[2]; + pointer[i * 3 + 2] = tri[0]; + } break; + } + } + } + } + #endif + return mesh; } @@ -302,7 +340,18 @@ pod::Graph uf::graph::load( const uf::stl::string& filename, const uf::Serialize serializer.readFromFile( filename ); // load metadata graph.name = filename; //serializer["name"].as(); - graph.metadata = metadata; // serializer["metadata"]; +// graph.metadata = metadata; // serializer["metadata"]; + +// UF_MSG_DEBUG("A: {}", serializer["metadata"].dump(1, '\t')); +// UF_MSG_DEBUG("B: {}", metadata.dump(1, '\t')); +#if 0 + graph.metadata = serializer["metadata"]; + graph.metadata.merge( metadata, false ); +#else + graph.metadata = metadata; + graph.metadata.merge( serializer["metadata"], true ); +#endif +// UF_MSG_DEBUG("C: {}", graph.metadata.dump(1, '\t')); #if UF_GRAPH_LOAD_MULTITHREAD auto tasks = uf::thread::schedule(true); diff --git a/engine/src/engine/graph/encode.cpp b/engine/src/engine/graph/encode.cpp index 873ae481..c851b83e 100644 --- a/engine/src/engine/graph/encode.cpp +++ b/engine/src/engine/graph/encode.cpp @@ -250,15 +250,7 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string& if ( settings.compression == "auto" ) settings.compression = ext::json::PREFERRED_COMPRESSION; if ( !settings.combined ) uf::io::mkdir(directory); -#if UF_USE_XATLAS -/* - if ( settings.unwrap ) { - pod::Graph& g = const_cast(graph); - auto size = ext::xatlas::unwrap( g ); - serializer["wrapped"] = uf::vector::encode( size ); - } -*/ -#endif + serializer["metadata"] = graph.metadata; #if UF_GRAPH_LOAD_MULTITHREAD auto tasks = uf::thread::schedule(true); diff --git a/engine/src/engine/graph/graph.cpp b/engine/src/engine/graph/graph.cpp index b309ca4e..e484185d 100644 --- a/engine/src/engine/graph/graph.cpp +++ b/engine/src/engine/graph/graph.cpp @@ -12,6 +12,20 @@ namespace { bool newGraphAdded = true; + + ext::json::Value findTag( const uf::stl::string& tagName, const ext::json::Value& tags ) { + ext::json::Value tag = ext::json::null(); + ext::json::forEach( tags, [&]( const uf::stl::string& key, const ext::json::Value& value ) { + if ( uf::string::isRegex( key ) ) { + if ( !uf::string::matched( tagName, key ) ) return; + } else if ( tagName != key ) return; + tag = value; + }); + return tag; + } + ext::json::Value findTag( const uf::stl::string& tagName, pod::Graph& graph ) { + return findTag( tagName, graph.metadata["tags"] ); + } } pod::Graph::Storage uf::graph::storage; @@ -64,113 +78,181 @@ pod::Node* uf::graph::find( pod::Graph& graph, const uf::stl::string& name ) { } void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::Mesh& mesh ) { - auto& scene = uf::scene::getCurrentScene(); - auto& sceneTextures = scene.getComponent(); - auto& sceneMetadataJson = scene.getComponent(); - - auto& graphic = entity.getComponent(); - graphic.initialize(); - graphic.initializeMesh( mesh ); + auto& scene = uf::scene::getCurrentScene(); + auto& sceneTextures = scene.getComponent(); + auto& sceneMetadataJson = scene.getComponent(); + + auto& graphic = entity.getComponent(); + graphic.initialize(); + graphic.initializeMesh( mesh ); - graphic.device = &uf::renderer::device; - graphic.material.device = &uf::renderer::device; - graphic.descriptor.frontFace = uf::renderer::enums::Face::CCW; - graphic.descriptor.cullMode = !(graph.metadata["flags"]["INVERT"].as()) ? uf::renderer::enums::CullMode::BACK : uf::renderer::enums::CullMode::FRONT; - if ( graph.metadata["cull mode"].is() ) { - const auto mode = graph.metadata["cull mode"].as(); - if ( mode == "back" ) graphic.descriptor.cullMode = uf::renderer::enums::CullMode::BACK; - else if ( mode == "front" ) graphic.descriptor.cullMode = uf::renderer::enums::CullMode::FRONT; - else if ( mode == "none" ) graphic.descriptor.cullMode = uf::renderer::enums::CullMode::NONE; - else if ( mode == "both" ) graphic.descriptor.cullMode = uf::renderer::enums::CullMode::BOTH; + graphic.device = &uf::renderer::device; + graphic.material.device = &uf::renderer::device; + graphic.descriptor.frontFace = uf::renderer::enums::Face::CCW; + graphic.descriptor.cullMode = !(graph.metadata["flags"]["INVERT"].as()) ? uf::renderer::enums::CullMode::BACK : uf::renderer::enums::CullMode::FRONT; + + auto tag = ::findTag( entity.getName(), graph ); + if ( !ext::json::isObject( tag ) ) { + tag["renderer"] = graph.metadata["renderer"]; + } + + if ( tag["renderer"]["front face"].is() ) { + const auto mode = uf::string::lowercase( tag["renderer"]["front face"].as() ); + if ( mode == "cw" ) graphic.descriptor.frontFace = uf::renderer::enums::Face::CW; + else if ( mode == "ccw" ) graphic.descriptor.frontFace = uf::renderer::enums::Face::CCW; + else UF_MSG_WARNING("Invalid Face enum string specified: {}", mode); + } + if ( tag["renderer"]["cull mode"].is() ) { + const auto mode = uf::string::lowercase( tag["renderer"]["cull mode"].as() ); + if ( mode == "back" ) graphic.descriptor.cullMode = uf::renderer::enums::CullMode::BACK; + else if ( mode == "front" ) graphic.descriptor.cullMode = uf::renderer::enums::CullMode::FRONT; + else if ( mode == "none" ) graphic.descriptor.cullMode = uf::renderer::enums::CullMode::NONE; + else if ( mode == "both" ) graphic.descriptor.cullMode = uf::renderer::enums::CullMode::BOTH; + else UF_MSG_WARNING("Invalid CullMode enum string specified: {}", mode); + } + + { + // for ( auto& s : graph.samplers ) graphic.material.samplers.emplace_back( uf::graph::storage.samplers.map[s] ); + // for ( auto pair : uf::graph::storage.samplers.map ) graphic.material.samplers.emplace_back( pair.second ); + // for ( auto& key : uf::graph::storage.samplers.keys ) graphic.material.samplers.emplace_back( uf::graph::storage.samplers.map[key] ); + + // for ( auto& i : graph.images ) graphic.material.textures.emplace_back().aliasTexture( uf::graph::storage.texture2Ds.map[i] ); + // for ( auto pair : uf::graph::storage.texture2Ds.map ) graphic.material.textures.emplace_back().aliasTexture( pair.second ); + for ( auto& key : uf::graph::storage.texture2Ds.keys ) graphic.material.textures.emplace_back().aliasTexture( uf::graph::storage.texture2Ds.map[key] ); + + // bind scene's voxel texture + if ( uf::renderer::settings::pipelines::vxgi ) { + auto& scene = uf::scene::getCurrentScene(); + auto& sceneTextures = scene.getComponent(); + for ( auto& t : sceneTextures.voxels.id ) graphic.material.textures.emplace_back().aliasTexture(t); + for ( auto& t : sceneTextures.voxels.normal ) graphic.material.textures.emplace_back().aliasTexture(t); + for ( auto& t : sceneTextures.voxels.uv ) graphic.material.textures.emplace_back().aliasTexture(t); + for ( auto& t : sceneTextures.voxels.radiance ) graphic.material.textures.emplace_back().aliasTexture(t); + for ( auto& t : sceneTextures.voxels.depth ) graphic.material.textures.emplace_back().aliasTexture(t); } - { - // for ( auto& s : graph.samplers ) graphic.material.samplers.emplace_back( uf::graph::storage.samplers.map[s] ); - // for ( auto pair : uf::graph::storage.samplers.map ) graphic.material.samplers.emplace_back( pair.second ); - // for ( auto& key : uf::graph::storage.samplers.keys ) graphic.material.samplers.emplace_back( uf::graph::storage.samplers.map[key] ); + } + + uf::stl::string root = uf::io::directory( graph.name ); + size_t texture2Ds = 0; + size_t texture3Ds = 0; + for ( auto& texture : graphic.material.textures ) { + if ( texture.width > 1 && texture.height > 1 && texture.depth == 1 && texture.layers == 1 ) ++texture2Ds; + else if ( texture.width > 1 && texture.height > 1 && texture.depth > 1 && texture.layers == 1 ) ++texture3Ds; + } - // for ( auto& i : graph.images ) graphic.material.textures.emplace_back().aliasTexture( uf::graph::storage.texture2Ds.map[i] ); - // for ( auto pair : uf::graph::storage.texture2Ds.map ) graphic.material.textures.emplace_back().aliasTexture( pair.second ); - for ( auto& key : uf::graph::storage.texture2Ds.keys ) graphic.material.textures.emplace_back().aliasTexture( uf::graph::storage.texture2Ds.map[key] ); + // standard pipeline + uf::stl::string vertexShaderFilename = graph.metadata["shaders"]["vertex"].as("/graph/base.vert.spv"); { + std::pair settings[] = { + { graph.metadata["flags"]["SKINNED"].as(), "skinned.vert" }, + { !graph.metadata["flags"]["SEPARATE"].as(), "instanced.vert" }, + }; + FOR_ARRAY(settings) if ( settings[i].first ) vertexShaderFilename = uf::string::replace( vertexShaderFilename, "vert", settings[i].second ); + vertexShaderFilename = entity.resolveURI( vertexShaderFilename, root ); + } + uf::stl::string geometryShaderFilename = graph.metadata["shaders"]["geometry"].as(""); + uf::stl::string fragmentShaderFilename = graph.metadata["shaders"]["fragment"].as("/graph/base.frag.spv"); { + std::pair settings[] = { + { uf::renderer::settings::invariant::deferredSampling, "deferredSampling.frag" }, + }; + FOR_ARRAY(settings) if ( settings[i].first ) fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", settings[i].second ); + fragmentShaderFilename = entity.resolveURI( fragmentShaderFilename, root ); + } + { + graphic.material.metadata.autoInitializeUniformBuffers = false; + graphic.material.attachShader(vertexShaderFilename, uf::renderer::enums::Shader::VERTEX); + graphic.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT); + graphic.material.metadata.autoInitializeUniformBuffers = true; + } - // bind scene's voxel texture - if ( uf::renderer::settings::pipelines::vxgi ) { - auto& scene = uf::scene::getCurrentScene(); - auto& sceneTextures = scene.getComponent(); - for ( auto& t : sceneTextures.voxels.id ) graphic.material.textures.emplace_back().aliasTexture(t); - for ( auto& t : sceneTextures.voxels.normal ) graphic.material.textures.emplace_back().aliasTexture(t); - for ( auto& t : sceneTextures.voxels.uv ) graphic.material.textures.emplace_back().aliasTexture(t); - for ( auto& t : sceneTextures.voxels.radiance ) graphic.material.textures.emplace_back().aliasTexture(t); - for ( auto& t : sceneTextures.voxels.depth ) graphic.material.textures.emplace_back().aliasTexture(t); + uf::renderer::Buffer* indirect = NULL; + for ( auto& buffer : graphic.buffers ) if ( !indirect && buffer.usage & uf::renderer::enums::Buffer::INDIRECT ) indirect = &buffer; + + { + auto& shader = graphic.material.getShader("vertex"); + + shader.buffers.emplace_back( uf::graph::storage.buffers.camera.alias() ); +// // shader.buffers.emplace_back( uf::graph::storage.buffers.drawCommands.alias() ); + #if UF_USE_VULKAN + shader.buffers.emplace_back( indirect->alias() ); + #endif + shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() ); + shader.buffers.emplace_back( uf::graph::storage.buffers.joint.alias() ); + #if UF_USE_VULKAN + uint32_t maxPasses = 6; + uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants; + for ( auto pair : shader.metadata.definitions.specializationConstants ) { + auto& sc = pair.second; + if ( sc.name == "PASSES" ) sc.value.ui = (specializationConstants[sc.index] = maxPasses); + } + #endif + } + { + auto& shader = graphic.material.getShader("fragment"); + + shader.buffers.emplace_back( uf::graph::storage.buffers.drawCommands.alias() ); + shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() ); + shader.buffers.emplace_back( uf::graph::storage.buffers.instanceAddresses.alias() ); + shader.buffers.emplace_back( uf::graph::storage.buffers.material.alias() ); + shader.buffers.emplace_back( uf::graph::storage.buffers.texture.alias() ); + shader.buffers.emplace_back( uf::graph::storage.buffers.light.alias() ); + + #if UF_USE_VULKAN + uint32_t maxTextures = graph.textures.size(); // texture2Ds; + + uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants; + for ( auto pair : shader.metadata.definitions.specializationConstants ) { + auto& sc = pair.second; + if ( sc.name == "TEXTURES" ) sc.value.ui = (specializationConstants[sc.index] = maxTextures); + } + for ( auto pair : shader.metadata.definitions.textures ) { + auto& tx = pair.second; + for ( auto& layout : shader.descriptorSetLayoutBindings ) { + if ( layout.binding != tx.binding ) continue; + if ( tx.name == "samplerTextures" ) layout.descriptorCount = maxTextures; } } - - uf::stl::string root = uf::io::directory( graph.name ); - size_t texture2Ds = 0; - size_t texture3Ds = 0; - for ( auto& texture : graphic.material.textures ) { - if ( texture.width > 1 && texture.height > 1 && texture.depth == 1 && texture.layers == 1 ) ++texture2Ds; - else if ( texture.width > 1 && texture.height > 1 && texture.depth > 1 && texture.layers == 1 ) ++texture3Ds; - } - - // standard pipeline - uf::stl::string vertexShaderFilename = graph.metadata["shaders"]["vertex"].as("/graph/base.vert.spv"); { - std::pair settings[] = { - { graph.metadata["flags"]["SKINNED"].as(), "skinned.vert" }, - { !graph.metadata["flags"]["SEPARATE"].as(), "instanced.vert" }, - }; - FOR_ARRAY(settings) if ( settings[i].first ) vertexShaderFilename = uf::string::replace( vertexShaderFilename, "vert", settings[i].second ); - vertexShaderFilename = entity.resolveURI( vertexShaderFilename, root ); - } - uf::stl::string geometryShaderFilename = graph.metadata["shaders"]["geometry"].as(""); - uf::stl::string fragmentShaderFilename = graph.metadata["shaders"]["fragment"].as("/graph/base.frag.spv"); { - std::pair settings[] = { - { uf::renderer::settings::invariant::deferredSampling, "deferredSampling.frag" }, - }; - FOR_ARRAY(settings) if ( settings[i].first ) fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", settings[i].second ); - fragmentShaderFilename = entity.resolveURI( fragmentShaderFilename, root ); - } - { - graphic.material.metadata.autoInitializeUniformBuffers = false; - graphic.material.attachShader(vertexShaderFilename, uf::renderer::enums::Shader::VERTEX); - graphic.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT); - graphic.material.metadata.autoInitializeUniformBuffers = true; - } - + #endif + } +#if UF_USE_VULKAN + // culling pipeline + if ( uf::renderer::settings::pipelines::culling ) { uf::renderer::Buffer* indirect = NULL; for ( auto& buffer : graphic.buffers ) if ( !indirect && buffer.usage & uf::renderer::enums::Buffer::INDIRECT ) indirect = &buffer; + UF_ASSERT( indirect ); + if ( indirect ) { + uf::stl::string compShaderFilename = graph.metadata["shaders"]["vertex"].as("/graph/cull.comp.spv"); + { + graphic.material.metadata.autoInitializeUniformBuffers = false; + compShaderFilename = entity.resolveURI( compShaderFilename, root ); + graphic.material.attachShader(compShaderFilename, uf::renderer::enums::Shader::COMPUTE, uf::renderer::settings::pipelines::names::culling); + graphic.material.metadata.autoInitializeUniformBuffers = true; + } + graphic.descriptor.inputs.dispatch = { graphic.descriptor.inputs.indirect.count, 1, 1 }; - { - auto& shader = graphic.material.getShader("vertex"); + auto& shader = graphic.material.getShader("compute", uf::renderer::settings::pipelines::names::culling); shader.buffers.emplace_back( uf::graph::storage.buffers.camera.alias() ); - // // shader.buffers.emplace_back( uf::graph::storage.buffers.drawCommands.alias() ); #if UF_USE_VULKAN shader.buffers.emplace_back( indirect->alias() ); #endif shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() ); - shader.buffers.emplace_back( uf::graph::storage.buffers.joint.alias() ); - #if UF_USE_VULKAN - uint32_t maxPasses = 6; - uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants; - for ( auto pair : shader.metadata.definitions.specializationConstants ) { - auto& sc = pair.second; - if ( sc.name == "PASSES" ) sc.value.ui = (specializationConstants[sc.index] = maxPasses); - } - #endif } + } + if ( geometryShaderFilename != "" && uf::renderer::device.enabledFeatures.geometryShader ) { + geometryShaderFilename = entity.resolveURI( geometryShaderFilename, root ); + graphic.material.attachShader(geometryShaderFilename, uf::renderer::enums::Shader::GEOMETRY); + } + // depth only pipeline + { + graphic.material.metadata.autoInitializeUniformBuffers = false; + uf::stl::string fragmentShaderFilename = graph.metadata["shaders"]["vertex"].as("/graph/depth.frag.spv"); + fragmentShaderFilename = entity.resolveURI( fragmentShaderFilename, root ); + graphic.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT, "depth"); + graphic.material.metadata.autoInitializeUniformBuffers = true; { - auto& shader = graphic.material.getShader("fragment"); - - shader.buffers.emplace_back( uf::graph::storage.buffers.drawCommands.alias() ); - shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() ); - shader.buffers.emplace_back( uf::graph::storage.buffers.instanceAddresses.alias() ); - shader.buffers.emplace_back( uf::graph::storage.buffers.material.alias() ); - shader.buffers.emplace_back( uf::graph::storage.buffers.texture.alias() ); - shader.buffers.emplace_back( uf::graph::storage.buffers.light.alias() ); - - #if UF_USE_VULKAN uint32_t maxTextures = graph.textures.size(); // texture2Ds; + auto& shader = graphic.material.getShader("fragment", "depth"); uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants; for ( auto pair : shader.metadata.definitions.specializationConstants ) { auto& sc = pair.second; @@ -183,239 +265,185 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::M if ( tx.name == "samplerTextures" ) layout.descriptorCount = maxTextures; } } - #endif + + shader.buffers.emplace_back( uf::graph::storage.buffers.drawCommands.alias() ); + shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() ); + shader.buffers.emplace_back( uf::graph::storage.buffers.instanceAddresses.alias() ); + shader.buffers.emplace_back( uf::graph::storage.buffers.material.alias() ); + shader.buffers.emplace_back( uf::graph::storage.buffers.texture.alias() ); + shader.buffers.emplace_back( uf::graph::storage.buffers.light.alias() ); } - #if UF_USE_VULKAN - // culling pipeline - if ( uf::renderer::settings::pipelines::culling ) { - uf::renderer::Buffer* indirect = NULL; - for ( auto& buffer : graphic.buffers ) if ( !indirect && buffer.usage & uf::renderer::enums::Buffer::INDIRECT ) indirect = &buffer; - UF_ASSERT( indirect ); - if ( indirect ) { - uf::stl::string compShaderFilename = graph.metadata["shaders"]["vertex"].as("/graph/cull.comp.spv"); - { - graphic.material.metadata.autoInitializeUniformBuffers = false; - compShaderFilename = entity.resolveURI( compShaderFilename, root ); - graphic.material.attachShader(compShaderFilename, uf::renderer::enums::Shader::COMPUTE, uf::renderer::settings::pipelines::names::culling); - graphic.material.metadata.autoInitializeUniformBuffers = true; - } - graphic.descriptor.inputs.dispatch = { graphic.descriptor.inputs.indirect.count, 1, 1 }; + } + // vxgi pipeline + if ( uf::renderer::settings::pipelines::vxgi ) { + uf::stl::string vertexShaderFilename = graph.metadata["shaders"]["vertex"].as("/graph/base.vert.spv"); + uf::stl::string geometryShaderFilename = graph.metadata["shaders"]["geometry"].as("/graph/voxelize.geom.spv"); + uf::stl::string fragmentShaderFilename = graph.metadata["shaders"]["fragment"].as("/graph/voxelize.frag.spv"); - auto& shader = graphic.material.getShader("compute", uf::renderer::settings::pipelines::names::culling); - - shader.buffers.emplace_back( uf::graph::storage.buffers.camera.alias() ); - #if UF_USE_VULKAN - shader.buffers.emplace_back( indirect->alias() ); - #endif - shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() ); - } + { + fragmentShaderFilename = entity.resolveURI( fragmentShaderFilename, root ); + graphic.material.metadata.autoInitializeUniformBuffers = false; + graphic.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT, uf::renderer::settings::pipelines::names::vxgi); + graphic.material.metadata.autoInitializeUniformBuffers = true; } if ( geometryShaderFilename != "" && uf::renderer::device.enabledFeatures.geometryShader ) { geometryShaderFilename = entity.resolveURI( geometryShaderFilename, root ); - graphic.material.attachShader(geometryShaderFilename, uf::renderer::enums::Shader::GEOMETRY); + graphic.material.attachShader(geometryShaderFilename, uf::renderer::enums::Shader::GEOMETRY, uf::renderer::settings::pipelines::names::vxgi); } - // depth only pipeline + { + uint32_t voxelTypes = 0; + if ( !sceneTextures.voxels.id.empty() ) ++voxelTypes; + if ( !sceneTextures.voxels.normal.empty() ) ++voxelTypes; + if ( !sceneTextures.voxels.uv.empty() ) ++voxelTypes; + if ( !sceneTextures.voxels.radiance.empty() ) ++voxelTypes; + if ( !sceneTextures.voxels.depth.empty() ) ++voxelTypes; + + uint32_t maxTextures = texture2Ds; + uint32_t maxCascades = texture3Ds / voxelTypes; + + auto& shader = graphic.material.getShader("fragment", uf::renderer::settings::pipelines::names::vxgi); + uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants; + for ( auto pair : shader.metadata.definitions.specializationConstants ) { + auto& sc = pair.second; + if ( sc.name == "TEXTURES" ) sc.value.ui = (specializationConstants[sc.index] = maxTextures); + else if ( sc.name == "CASCADES" ) sc.value.ui = (specializationConstants[sc.index] = maxCascades); + } + for ( auto pair : shader.metadata.definitions.textures ) { + auto& tx = pair.second; + for ( auto& layout : shader.descriptorSetLayoutBindings ) { + if ( layout.binding != tx.binding ) continue; + if ( tx.name == "samplerTextures" ) layout.descriptorCount = maxTextures; + else if ( tx.name == "voxelId" ) layout.descriptorCount = maxCascades; + else if ( tx.name == "voxelUv" ) layout.descriptorCount = maxCascades; + else if ( tx.name == "voxelNormal" ) layout.descriptorCount = maxCascades; + else if ( tx.name == "voxelRadiance" ) layout.descriptorCount = maxCascades; + } + } + + shader.buffers.emplace_back( uf::graph::storage.buffers.drawCommands.alias() ); + shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() ); + shader.buffers.emplace_back( uf::graph::storage.buffers.instanceAddresses.alias() ); + shader.buffers.emplace_back( uf::graph::storage.buffers.material.alias() ); + shader.buffers.emplace_back( uf::graph::storage.buffers.texture.alias() ); + shader.buffers.emplace_back( uf::graph::storage.buffers.light.alias() ); + } + } + // baking pipeline + if ( graph.metadata["baking"]["enabled"].as() ) { { graphic.material.metadata.autoInitializeUniformBuffers = false; - uf::stl::string fragmentShaderFilename = graph.metadata["shaders"]["vertex"].as("/graph/depth.frag.spv"); - fragmentShaderFilename = entity.resolveURI( fragmentShaderFilename, root ); - graphic.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT, "depth"); + uf::stl::string vertexShaderFilename = uf::io::resolveURI("/graph/baking/bake.vert.spv"); + uf::stl::string geometryShaderFilename = uf::io::resolveURI("/graph/baking/bake.geom.spv"); + uf::stl::string fragmentShaderFilename = uf::io::resolveURI("/graph/baking/bake.frag.spv"); + graphic.material.attachShader(vertexShaderFilename, uf::renderer::enums::Shader::VERTEX, "baking"); + graphic.material.attachShader(geometryShaderFilename, uf::renderer::enums::Shader::GEOMETRY, "baking"); + graphic.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT, "baking"); graphic.material.metadata.autoInitializeUniformBuffers = true; - { - uint32_t maxTextures = graph.textures.size(); // texture2Ds; - - auto& shader = graphic.material.getShader("fragment", "depth"); - uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants; - for ( auto pair : shader.metadata.definitions.specializationConstants ) { - auto& sc = pair.second; - if ( sc.name == "TEXTURES" ) sc.value.ui = (specializationConstants[sc.index] = maxTextures); - } - for ( auto pair : shader.metadata.definitions.textures ) { - auto& tx = pair.second; - for ( auto& layout : shader.descriptorSetLayoutBindings ) { - if ( layout.binding != tx.binding ) continue; - if ( tx.name == "samplerTextures" ) layout.descriptorCount = maxTextures; - } - } - - shader.buffers.emplace_back( uf::graph::storage.buffers.drawCommands.alias() ); - shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() ); - shader.buffers.emplace_back( uf::graph::storage.buffers.instanceAddresses.alias() ); - shader.buffers.emplace_back( uf::graph::storage.buffers.material.alias() ); - shader.buffers.emplace_back( uf::graph::storage.buffers.texture.alias() ); - shader.buffers.emplace_back( uf::graph::storage.buffers.light.alias() ); - } } - // vxgi pipeline - if ( uf::renderer::settings::pipelines::vxgi ) { - uf::stl::string vertexShaderFilename = graph.metadata["shaders"]["vertex"].as("/graph/base.vert.spv"); - uf::stl::string geometryShaderFilename = graph.metadata["shaders"]["geometry"].as("/graph/voxelize.geom.spv"); - uf::stl::string fragmentShaderFilename = graph.metadata["shaders"]["fragment"].as("/graph/voxelize.frag.spv"); - - { - fragmentShaderFilename = entity.resolveURI( fragmentShaderFilename, root ); - graphic.material.metadata.autoInitializeUniformBuffers = false; - graphic.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT, uf::renderer::settings::pipelines::names::vxgi); - graphic.material.metadata.autoInitializeUniformBuffers = true; - } - if ( geometryShaderFilename != "" && uf::renderer::device.enabledFeatures.geometryShader ) { - geometryShaderFilename = entity.resolveURI( geometryShaderFilename, root ); - graphic.material.attachShader(geometryShaderFilename, uf::renderer::enums::Shader::GEOMETRY, uf::renderer::settings::pipelines::names::vxgi); - } - { - uint32_t voxelTypes = 0; - if ( !sceneTextures.voxels.id.empty() ) ++voxelTypes; - if ( !sceneTextures.voxels.normal.empty() ) ++voxelTypes; - if ( !sceneTextures.voxels.uv.empty() ) ++voxelTypes; - if ( !sceneTextures.voxels.radiance.empty() ) ++voxelTypes; - if ( !sceneTextures.voxels.depth.empty() ) ++voxelTypes; - - uint32_t maxTextures = texture2Ds; - uint32_t maxCascades = texture3Ds / voxelTypes; - - auto& shader = graphic.material.getShader("fragment", uf::renderer::settings::pipelines::names::vxgi); - uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants; - for ( auto pair : shader.metadata.definitions.specializationConstants ) { - auto& sc = pair.second; - if ( sc.name == "TEXTURES" ) sc.value.ui = (specializationConstants[sc.index] = maxTextures); - else if ( sc.name == "CASCADES" ) sc.value.ui = (specializationConstants[sc.index] = maxCascades); - } - for ( auto pair : shader.metadata.definitions.textures ) { - auto& tx = pair.second; - for ( auto& layout : shader.descriptorSetLayoutBindings ) { - if ( layout.binding != tx.binding ) continue; - if ( tx.name == "samplerTextures" ) layout.descriptorCount = maxTextures; - else if ( tx.name == "voxelId" ) layout.descriptorCount = maxCascades; - else if ( tx.name == "voxelUv" ) layout.descriptorCount = maxCascades; - else if ( tx.name == "voxelNormal" ) layout.descriptorCount = maxCascades; - else if ( tx.name == "voxelRadiance" ) layout.descriptorCount = maxCascades; - } - } - - shader.buffers.emplace_back( uf::graph::storage.buffers.drawCommands.alias() ); - shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() ); - shader.buffers.emplace_back( uf::graph::storage.buffers.instanceAddresses.alias() ); - shader.buffers.emplace_back( uf::graph::storage.buffers.material.alias() ); - shader.buffers.emplace_back( uf::graph::storage.buffers.texture.alias() ); - shader.buffers.emplace_back( uf::graph::storage.buffers.light.alias() ); - } - } - // baking pipeline - if ( graph.metadata["baking"]["enabled"].as() ) { - { - graphic.material.metadata.autoInitializeUniformBuffers = false; - uf::stl::string vertexShaderFilename = uf::io::resolveURI("/graph/baking/bake.vert.spv"); - uf::stl::string geometryShaderFilename = uf::io::resolveURI("/graph/baking/bake.geom.spv"); - uf::stl::string fragmentShaderFilename = uf::io::resolveURI("/graph/baking/bake.frag.spv"); - graphic.material.attachShader(vertexShaderFilename, uf::renderer::enums::Shader::VERTEX, "baking"); - graphic.material.attachShader(geometryShaderFilename, uf::renderer::enums::Shader::GEOMETRY, "baking"); - graphic.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT, "baking"); - graphic.material.metadata.autoInitializeUniformBuffers = true; - } - { - uint32_t maxPasses = 6; - - auto& shader = graphic.material.getShader("vertex", "baking"); - uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants; - for ( auto pair : shader.metadata.definitions.specializationConstants ) { - auto& sc = pair.second; - if ( sc.name == "PASSES" ) sc.value.ui = (specializationConstants[sc.index] = maxPasses); - } - - // shader.buffers.emplace_back( uf::graph::storage.buffers.camera.alias() ); - // shader.buffers.emplace_back( uf::graph::storage.buffers.drawCommands.alias() ); - #if UF_USE_VULKAN - shader.buffers.emplace_back( indirect->alias() ); - #endif - shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() ); - shader.buffers.emplace_back( uf::graph::storage.buffers.joint.alias() ); - } - - { - size_t maxTextures = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["2D"].as(512); - size_t maxCubemaps = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["cube"].as(128); - size_t maxTextures3D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["3D"].as(128); - - auto& shader = graphic.material.getShader("fragment", "baking"); - uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants; - for ( auto pair : shader.metadata.definitions.specializationConstants ) { - auto& sc = pair.second; - if ( sc.name == "TEXTURES" ) sc.value.ui = (specializationConstants[sc.index] = maxTextures); - else if ( sc.name == "CUBEMAPS" ) sc.value.ui = (specializationConstants[sc.index] = maxCubemaps); - } - for ( auto pair : shader.metadata.definitions.textures ) { - auto& tx = pair.second; - for ( auto& layout : shader.descriptorSetLayoutBindings ) { - if ( layout.binding != tx.binding ) continue; - if ( tx.name == "samplerTextures" ) layout.descriptorCount = maxTextures; - else if ( tx.name == "samplerCubemaps" ) layout.descriptorCount = maxCubemaps; - } - } - - shader.buffers.emplace_back( uf::graph::storage.buffers.drawCommands.alias() ); - shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() ); - shader.buffers.emplace_back( uf::graph::storage.buffers.instanceAddresses.alias() ); - shader.buffers.emplace_back( uf::graph::storage.buffers.material.alias() ); - shader.buffers.emplace_back( uf::graph::storage.buffers.texture.alias() ); - shader.buffers.emplace_back( uf::graph::storage.buffers.light.alias() ); - } - } - // rt pipeline - if ( uf::renderer::settings::pipelines::rt ) { - graphic.generateBottomAccelerationStructures(); - } - - // grab addresses { - pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer( mesh.indirect ).data(); - for ( size_t drawID = 0; drawID < mesh.indirect.count; ++drawID ) { - auto& drawCommand = drawCommands[drawID]; - auto instanceID = drawCommand.instanceID; - auto instanceKeyName = std::to_string(instanceID); + uint32_t maxPasses = 6; - if ( uf::graph::storage.instanceAddresses.map.count(instanceKeyName) > 0 ) { - UF_MSG_DEBUG("DUPLICATE INSTANCE ID"); - } + auto& shader = graphic.material.getShader("vertex", "baking"); + uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants; + for ( auto pair : shader.metadata.definitions.specializationConstants ) { + auto& sc = pair.second; + if ( sc.name == "PASSES" ) sc.value.ui = (specializationConstants[sc.index] = maxPasses); + } - auto& instanceAddresses = uf::graph::storage.instanceAddresses.map[instanceKeyName]; - if ( mesh.vertex.count ) { - if ( mesh.isInterleaved( mesh.vertex ) ) { - instanceAddresses.vertex = graphic.buffers.at(graphic.descriptor.inputs.vertex.interleaved).getAddress()/* + (drawCommand.vertexID * mesh.vertex.size)*/; - } else { - for ( auto& attribute : graphic.descriptor.inputs.vertex.attributes ) { - if ( attribute.buffer < 0 ) continue; - if ( attribute.descriptor.name == "position" ) instanceAddresses.position = graphic.buffers.at(attribute.buffer).getAddress()/* + (drawCommand.vertexID * attribute.stride)*/; - else if ( attribute.descriptor.name == "uv" ) instanceAddresses.uv = graphic.buffers.at(attribute.buffer).getAddress()/* + (drawCommand.vertexID * attribute.stride)*/; - else if ( attribute.descriptor.name == "color" ) instanceAddresses.color = graphic.buffers.at(attribute.buffer).getAddress()/* + (drawCommand.vertexID * attribute.stride)*/; - else if ( attribute.descriptor.name == "st" ) instanceAddresses.st = graphic.buffers.at(attribute.buffer).getAddress()/* + (drawCommand.vertexID * attribute.stride)*/; - else if ( attribute.descriptor.name == "normal" ) instanceAddresses.normal = graphic.buffers.at(attribute.buffer).getAddress()/* + (drawCommand.vertexID * attribute.stride)*/; - else if ( attribute.descriptor.name == "tangent" ) instanceAddresses.tangent = graphic.buffers.at(attribute.buffer).getAddress()/* + (drawCommand.vertexID * attribute.stride)*/; - else if ( attribute.descriptor.name == "joints" ) instanceAddresses.joints = graphic.buffers.at(attribute.buffer).getAddress()/* + (drawCommand.vertexID * attribute.stride)*/; - else if ( attribute.descriptor.name == "weights" ) instanceAddresses.weights = graphic.buffers.at(attribute.buffer).getAddress()/* + (drawCommand.vertexID * attribute.stride)*/; - else if ( attribute.descriptor.name == "id" ) instanceAddresses.id = graphic.buffers.at(attribute.buffer).getAddress()/* + (drawCommand.vertexID * attribute.stride)*/; - } - } - } - if ( mesh.index.count ) { - if ( mesh.isInterleaved( mesh.index ) ) instanceAddresses.index = graphic.buffers.at(graphic.descriptor.inputs.index.interleaved).getAddress(); - else instanceAddresses.index = graphic.buffers.at(graphic.descriptor.inputs.index.attributes.front().buffer).getAddress(); - } + // shader.buffers.emplace_back( uf::graph::storage.buffers.camera.alias() ); + // shader.buffers.emplace_back( uf::graph::storage.buffers.drawCommands.alias() ); + #if UF_USE_VULKAN + shader.buffers.emplace_back( indirect->alias() ); + #endif + shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() ); + shader.buffers.emplace_back( uf::graph::storage.buffers.joint.alias() ); + } - if ( mesh.indirect.count ) { - if ( mesh.isInterleaved( mesh.indirect ) ) instanceAddresses.indirect = graphic.buffers.at(graphic.descriptor.inputs.indirect.interleaved).getAddress(); - else instanceAddresses.indirect = graphic.buffers.at(graphic.descriptor.inputs.indirect.attributes.front().buffer).getAddress(); + { + size_t maxTextures = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["2D"].as(512); + size_t maxCubemaps = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["cube"].as(128); + size_t maxTextures3D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["3D"].as(128); - instanceAddresses.drawID = drawID; + auto& shader = graphic.material.getShader("fragment", "baking"); + uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants; + for ( auto pair : shader.metadata.definitions.specializationConstants ) { + auto& sc = pair.second; + if ( sc.name == "TEXTURES" ) sc.value.ui = (specializationConstants[sc.index] = maxTextures); + else if ( sc.name == "CUBEMAPS" ) sc.value.ui = (specializationConstants[sc.index] = maxCubemaps); + } + for ( auto pair : shader.metadata.definitions.textures ) { + auto& tx = pair.second; + for ( auto& layout : shader.descriptorSetLayoutBindings ) { + if ( layout.binding != tx.binding ) continue; + if ( tx.name == "samplerTextures" ) layout.descriptorCount = maxTextures; + else if ( tx.name == "samplerCubemaps" ) layout.descriptorCount = maxCubemaps; } } + + shader.buffers.emplace_back( uf::graph::storage.buffers.drawCommands.alias() ); + shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() ); + shader.buffers.emplace_back( uf::graph::storage.buffers.instanceAddresses.alias() ); + shader.buffers.emplace_back( uf::graph::storage.buffers.material.alias() ); + shader.buffers.emplace_back( uf::graph::storage.buffers.texture.alias() ); + shader.buffers.emplace_back( uf::graph::storage.buffers.light.alias() ); } - #endif - - // uf::instantiator::bind( "GraphBehavior", entity ); - // uf::instantiator::unbind( "RenderBehavior", entity ); - - graphic.process = true; } + // rt pipeline + if ( uf::renderer::settings::pipelines::rt ) { + graphic.generateBottomAccelerationStructures(); + } + + // grab addresses + { + pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer( mesh.indirect ).data(); + for ( size_t drawID = 0; drawID < mesh.indirect.count; ++drawID ) { + auto& drawCommand = drawCommands[drawID]; + auto instanceID = drawCommand.instanceID; + auto instanceKeyName = std::to_string(instanceID); + + if ( uf::graph::storage.instanceAddresses.map.count(instanceKeyName) > 0 ) { + UF_MSG_DEBUG("DUPLICATE INSTANCE ID"); + } + + auto& instanceAddresses = uf::graph::storage.instanceAddresses.map[instanceKeyName]; + if ( mesh.vertex.count ) { + if ( mesh.isInterleaved( mesh.vertex ) ) { + instanceAddresses.vertex = graphic.buffers.at(graphic.descriptor.inputs.vertex.interleaved).getAddress()/* + (drawCommand.vertexID * mesh.vertex.size)*/; + } else { + for ( auto& attribute : graphic.descriptor.inputs.vertex.attributes ) { + if ( attribute.buffer < 0 ) continue; + if ( attribute.descriptor.name == "position" ) instanceAddresses.position = graphic.buffers.at(attribute.buffer).getAddress()/* + (drawCommand.vertexID * attribute.stride)*/; + else if ( attribute.descriptor.name == "uv" ) instanceAddresses.uv = graphic.buffers.at(attribute.buffer).getAddress()/* + (drawCommand.vertexID * attribute.stride)*/; + else if ( attribute.descriptor.name == "color" ) instanceAddresses.color = graphic.buffers.at(attribute.buffer).getAddress()/* + (drawCommand.vertexID * attribute.stride)*/; + else if ( attribute.descriptor.name == "st" ) instanceAddresses.st = graphic.buffers.at(attribute.buffer).getAddress()/* + (drawCommand.vertexID * attribute.stride)*/; + else if ( attribute.descriptor.name == "normal" ) instanceAddresses.normal = graphic.buffers.at(attribute.buffer).getAddress()/* + (drawCommand.vertexID * attribute.stride)*/; + else if ( attribute.descriptor.name == "tangent" ) instanceAddresses.tangent = graphic.buffers.at(attribute.buffer).getAddress()/* + (drawCommand.vertexID * attribute.stride)*/; + else if ( attribute.descriptor.name == "joints" ) instanceAddresses.joints = graphic.buffers.at(attribute.buffer).getAddress()/* + (drawCommand.vertexID * attribute.stride)*/; + else if ( attribute.descriptor.name == "weights" ) instanceAddresses.weights = graphic.buffers.at(attribute.buffer).getAddress()/* + (drawCommand.vertexID * attribute.stride)*/; + else if ( attribute.descriptor.name == "id" ) instanceAddresses.id = graphic.buffers.at(attribute.buffer).getAddress()/* + (drawCommand.vertexID * attribute.stride)*/; + } + } + } + if ( mesh.index.count ) { + if ( mesh.isInterleaved( mesh.index ) ) instanceAddresses.index = graphic.buffers.at(graphic.descriptor.inputs.index.interleaved).getAddress(); + else instanceAddresses.index = graphic.buffers.at(graphic.descriptor.inputs.index.attributes.front().buffer).getAddress(); + } + + if ( mesh.indirect.count ) { + if ( mesh.isInterleaved( mesh.indirect ) ) instanceAddresses.indirect = graphic.buffers.at(graphic.descriptor.inputs.indirect.interleaved).getAddress(); + else instanceAddresses.indirect = graphic.buffers.at(graphic.descriptor.inputs.indirect.attributes.front().buffer).getAddress(); + + instanceAddresses.drawID = drawID; + } + } + } +#endif + +// uf::instantiator::bind( "GraphBehavior", entity ); +// uf::instantiator::unbind( "RenderBehavior", entity ); + + graphic.process = true; +} void uf::graph::process( pod::Graph& graph ) { // copy our local storage to global storage @@ -451,11 +479,11 @@ void uf::graph::process( pod::Graph& graph ) { auto& scene = uf::scene::getCurrentScene(); auto& sceneMetadataJson = scene.getComponent(); if ( !sceneMetadataJson["system"]["config"]["engine"]["scenes"]["lights"]["useLightmaps"].as(true) ) { - graph.metadata["lightmap"] = false; + graph.metadata["lights"]["lightmap"] = false; graph.metadata["baking"]["enabled"] = false; } - if ( graph.metadata["lightmap"].is() && graph.metadata["lightmap"].as() == "auto" ) { + if ( graph.metadata["lights"]["lightmap"].is() && graph.metadata["lights"]["lightmap"].as() == "auto" ) { uint32_t mtime = uf::io::mtime( graph.name ); // lightmaps are considered stale if they're older than the graph's source bool stale = false; @@ -469,13 +497,13 @@ void uf::graph::process( pod::Graph& graph ) { break; } } - graph.metadata["lightmap"] = !stale; + graph.metadata["lights"]["lightmap"] = !stale; } graph.metadata["baking"]["layers"] = lightmapCount; - if ( graph.metadata["lightmap"].as() ) for ( auto& pair : filenames ) { + if ( graph.metadata["lights"]["lightmap"].as() ) for ( auto& pair : filenames ) { auto i = pair.first; auto f = uf::io::sanitize( pair.second, uf::io::directory( graph.name ) ); @@ -496,7 +524,7 @@ void uf::graph::process( pod::Graph& graph ) { lightmapIDs[i] = textureID; - graph.metadata["lightmaps"][i] = f; + graph.metadata["lights"]["lightmaps"][i] = f; graph.metadata["baking"]["enabled"] = false; isSrgb[f] = false; @@ -542,11 +570,18 @@ void uf::graph::process( pod::Graph& graph ) { auto& image = uf::graph::storage.images[key]; auto& texture = uf::graph::storage.texture2Ds[key]; if ( !texture.generated() ) { - // bool isLightmap = graph.metadata["lightmapped"].as() == key; - // auto filter = graph.metadata["filter"].as() == "NEAREST" && !isLightmap ? uf::renderer::enums::Filter::NEAREST : uf::renderer::enums::Filter::LINEAR; - // auto filter = uf::renderer::enums::Filter::LINEAR; + auto filter = uf::renderer::enums::Filter::LINEAR; + auto tag = ::findTag( key, graph ); + if ( !ext::json::isObject( tag ) ) { + tag["renderer"] = graph.metadata["renderer"]; + } + if ( tag["renderer"]["filter"].is() ) { + const auto mode = uf::string::lowercase( tag["renderer"]["filter"].as("linear") ); + if ( mode == "linear" ) filter = uf::renderer::enums::Filter::LINEAR; + else if ( mode == "nearest" ) filter = uf::renderer::enums::Filter::NEAREST; + else UF_MSG_WARNING("Invalid Filter enum string specified: {}", mode); + } - auto filter = graph.metadata["filter"].as() == "NEAREST" ? uf::renderer::enums::Filter::NEAREST : uf::renderer::enums::Filter::LINEAR; texture.sampler.descriptor.filter.min = filter; texture.sampler.descriptor.filter.mag = filter; texture.srgb = isSrgb.count(key) == 0 ? false : isSrgb[key]; @@ -681,6 +716,39 @@ void uf::graph::process( pod::Graph& graph ) { } } + // patch materials/textures + for ( auto& name : graph.materials ) { + auto& material = uf::graph::storage.materials[name]; + auto tag = ::findTag( name, graph ); + if ( ext::json::isObject( tag ) ) { + material.colorBase = uf::vector::decode( tag["material"]["base"], material.colorBase); + material.colorEmissive = uf::vector::decode( tag["material"]["emissive"], material.colorEmissive); + material.factorMetallic = tag["material"]["fMetallic"].as(material.factorMetallic); + material.factorRoughness = tag["material"]["fRoughness"].as(material.factorRoughness); + material.factorOcclusion = tag["material"]["fOcclusion"].as(material.factorOcclusion); + material.factorAlphaCutoff = tag["material"]["fAlphaCutoff"].as(material.factorAlphaCutoff); + material.indexAlbedo = tag["material"]["iAlbedo"].as(material.indexAlbedo); + material.indexNormal = tag["material"]["iNormal"].as(material.indexNormal); + material.indexEmissive = tag["material"]["iEmissive"].as(material.indexEmissive); + material.indexOcclusion = tag["material"]["iOcclusion"].as(material.indexOcclusion); + material.indexMetallicRoughness = tag["material"]["iMetallicRoughness"].as(material.indexMetallicRoughness); + + if ( tag["material"]["modeAlpha"].is() ) { + const auto mode = uf::string::lowercase( tag["material"]["modeAlpha"].as() ); + if ( mode == "opaque" ) material.modeAlpha = 0; + else if ( mode == "blend" ) material.modeAlpha = 1; + else if ( mode == "mask" ) material.modeAlpha = 2; + else UF_MSG_WARNING("Invalid AlphaMode enum string specified: {}", mode); + } else { + material.modeAlpha = tag["material"]["modeAlpha"].as(material.modeAlpha); + } + } + } + + if ( graph.metadata["debug"]["print"]["meshes"].as() ) for ( auto& name : graph.meshes ) UF_MSG_DEBUG("Mesh: {}", name); + if ( graph.metadata["debug"]["print"]["materials"].as() ) for ( auto& name : graph.materials ) UF_MSG_DEBUG("Material: {}", name); + if ( graph.metadata["debug"]["print"]["textures"].as() ) for ( auto& name : graph.textures ) UF_MSG_DEBUG("Texture: {}", name); + uf::graph::reload(); // setup combined mesh if requested @@ -756,7 +824,7 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) // ignore pesky light_Orientation nodes if ( uf::string::split( node.name, "_" ).back() == "Orientation" ) return; // for dreamcast, ignore lights if we're baked - if ( graph.metadata["lightmapped"].as() && graph.metadata["lights"]["disable if lightmapped"].as(true) ) if ( graph.lights.count(node.name) > 0 ) return; + if ( graph.metadata["lights"]["lightmapped"].as() && graph.metadata["lights"]["disable if lightmapped"].as(true) ) if ( graph.lights.count(node.name) > 0 ) return; // create child if requested @@ -775,18 +843,7 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) // on systems where frametime is very, very important, we can set all static nodes to not tick // tie to tag - ext::json::Value tag = ext::json::null(); -/* - if ( ext::json::isObject( graph.metadata["tags"][node.name] ) ) { - tag = graph.metadata["tags"][node.name]; - } -*/ - ext::json::forEach( graph.metadata["tags"], [&]( const uf::stl::string& key, ext::json::Value& value ) { - if ( uf::string::isRegex( key ) ) { - if ( !uf::string::matched( node.name, key ) ) return; - } else if ( node.name != key ) return; - tag = value; - }); + ext::json::Value tag = ::findTag( node.name, graph ); if ( ext::json::isObject( tag ) ) { if ( tag["ignore"].as() ) return; if ( graph.metadata["baking"]["enabled"].as(false) && !tag["bake"].as(true) ) return; @@ -843,8 +900,13 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) metadataLight[key] = value; }); #if !UF_USE_OPENGL - if ( !(graph.metadata["lightmapped"].as() && !(metadataLight["shadows"].as() || metadataLight["dynamic"].as())) ) { - // { + bool should = false; + if ( !graph.metadata["lights"]["lightmapped"].as() ) { + should = true; + } else if ( metadataLight["shadows"].as() || metadataLight["dynamic"].as() ) { + should = true; + } + if ( should ) { auto& metadataJson = entity.getComponent(); entity.load("/light.json"); // copy @@ -931,8 +993,8 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) { auto phyziks = tag["physics"]; - if ( !ext::json::isObject( phyziks ) ) phyziks = metadataJson["system"]["physics"]; - else metadataJson["system"]["physics"] = phyziks; + if ( !ext::json::isObject( phyziks ) ) phyziks = metadataJson["physics"]; + else metadataJson["physics"] = phyziks; if ( ext::json::isObject( phyziks ) ) { uf::stl::string type = phyziks["type"].as(); @@ -953,8 +1015,8 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) pod::Vector3f center = (max + min) * 0.5f; pod::Vector3f corner = uf::vector::abs(max - min) * 0.5f; - metadataJson["system"]["physics"]["center"] = uf::vector::encode( center ); - metadataJson["system"]["physics"]["corner"] = uf::vector::encode( corner ); + metadataJson["physics"]["center"] = uf::vector::encode( center ); + metadataJson["physics"]["corner"] = uf::vector::encode( corner ); } } } @@ -1130,20 +1192,12 @@ void uf::graph::update( pod::Graph& graph, pod::Node& node ) { } } } + void uf::graph::destroy( pod::Graph& graph ) { #if 0 for ( auto& t : graph.textures ) t.texture.destroy(); for ( auto& m : graph.meshes ) m.destroy(); #endif - - uf::graph::storage.buffers.camera.destroy(); - uf::graph::storage.buffers.drawCommands.destroy(); - uf::graph::storage.buffers.instance.destroy(); - uf::graph::storage.buffers.instanceAddresses.destroy(); - uf::graph::storage.buffers.joint.destroy(); - uf::graph::storage.buffers.material.destroy(); - uf::graph::storage.buffers.texture.destroy(); - uf::graph::storage.buffers.light.destroy(); } void uf::graph::initialize() { @@ -1237,6 +1291,7 @@ void uf::graph::render() { uf::graph::storage.buffers.camera.update( (const void*) &camera.data().viewport, sizeof(pod::Camera::Viewports) ); } void uf::graph::destroy() { + // cleanup graphic handles for ( auto pair : uf::graph::storage.texture2Ds.map ) pair.second.destroy(); for ( auto& t : uf::graph::storage.shadow2Ds ) t.destroy(); for ( auto& t : uf::graph::storage.shadowCubes ) t.destroy(); @@ -1244,6 +1299,34 @@ void uf::graph::destroy() { for ( auto pair : uf::graph::storage.atlases.map ) pair.second.clear(); for ( auto pair : uf::graph::storage.images.map ) pair.second.clear(); for ( auto pair : uf::graph::storage.meshes.map ) pair.second.destroy(); + // cleanup storage buffers + uf::graph::storage.buffers.camera.destroy(); + uf::graph::storage.buffers.drawCommands.destroy(); + uf::graph::storage.buffers.instance.destroy(); + uf::graph::storage.buffers.instanceAddresses.destroy(); + uf::graph::storage.buffers.joint.destroy(); + uf::graph::storage.buffers.material.destroy(); + uf::graph::storage.buffers.texture.destroy(); + uf::graph::storage.buffers.light.destroy(); + + // cleanup storage cache + uf::graph::storage.instances.clear(); + uf::graph::storage.instanceAddresses.clear(); + uf::graph::storage.primitives.clear(); + uf::graph::storage.drawCommands.clear(); + uf::graph::storage.meshes.clear(); + uf::graph::storage.images.clear(); + uf::graph::storage.materials.clear(); + uf::graph::storage.textures.clear(); + uf::graph::storage.samplers.clear(); + uf::graph::storage.skins.clear(); + uf::graph::storage.animations.clear(); + uf::graph::storage.atlases.clear(); + uf::graph::storage.joints.clear(); + uf::graph::storage.texture2Ds.clear(); + uf::graph::storage.entities.clear(); + uf::graph::storage.shadow2Ds.clear(); + uf::graph::storage.shadowCubes.clear(); } void uf::graph::reload() { ::newGraphAdded = true; diff --git a/engine/src/engine/object/behavior.cpp b/engine/src/engine/object/behavior.cpp index fbc74dee..3d2e0bbe 100644 --- a/engine/src/engine/object/behavior.cpp +++ b/engine/src/engine/object/behavior.cpp @@ -101,25 +101,25 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) { this->addHook( "object:Deserialize.%UID%", [&](ext::json::Value& json){ metadata.deserialize(self, metadataJson); }); metadata.deserialize(self, metadataJson); - if ( ext::json::isObject(metadataJson["system"]["physics"]) ) { + if ( ext::json::isObject(metadataJson["physics"]) ) { auto& collider = this->getComponent(); - collider.stats.flags = metadataJson["system"]["physics"]["flags"].as(collider.stats.flags); - collider.stats.mass = metadataJson["system"]["physics"]["mass"].as(collider.stats.mass); - collider.stats.restitution = metadataJson["system"]["physics"]["restitution"].as(collider.stats.restitution); - collider.stats.friction = metadataJson["system"]["physics"]["friction"].as(collider.stats.friction); - collider.stats.inertia = uf::vector::decode( metadataJson["system"]["physics"]["inertia"], collider.stats.inertia ); - collider.stats.gravity = uf::vector::decode( metadataJson["system"]["physics"]["gravity"], collider.stats.gravity ); + collider.stats.flags = metadataJson["physics"]["flags"].as(collider.stats.flags); + collider.stats.mass = metadataJson["physics"]["mass"].as(collider.stats.mass); + collider.stats.restitution = metadataJson["physics"]["restitution"].as(collider.stats.restitution); + collider.stats.friction = metadataJson["physics"]["friction"].as(collider.stats.friction); + collider.stats.inertia = uf::vector::decode( metadataJson["physics"]["inertia"], collider.stats.inertia ); + collider.stats.gravity = uf::vector::decode( metadataJson["physics"]["gravity"], collider.stats.gravity ); - if ( metadataJson["system"]["physics"]["type"].as() == "bounding box" ) { - pod::Vector3f center = uf::vector::decode( metadataJson["system"]["physics"]["center"], pod::Vector3f{} ); - pod::Vector3f corner = uf::vector::decode( metadataJson["system"]["physics"]["corner"], pod::Vector3f{0.5, 0.5, 0.5} ); + if ( metadataJson["physics"]["type"].as() == "bounding box" ) { + pod::Vector3f center = uf::vector::decode( metadataJson["physics"]["center"], pod::Vector3f{} ); + pod::Vector3f corner = uf::vector::decode( metadataJson["physics"]["corner"], pod::Vector3f{0.5, 0.5, 0.5} ); - if ( metadataJson["system"]["physics"]["recenter"].as(true) ) collider.transform.position = (center - transform.position); + if ( metadataJson["physics"]["recenter"].as(true) ) collider.transform.position = (center - transform.position); uf::physics::impl::create( *this, corner ); - } else if ( metadataJson["system"]["physics"]["type"].as() == "capsule" ) { - float radius = metadataJson["system"]["physics"]["radius"].as(); - float height = metadataJson["system"]["physics"]["height"].as(); + } else if ( metadataJson["physics"]["type"].as() == "capsule" ) { + float radius = metadataJson["physics"]["radius"].as(); + float height = metadataJson["physics"]["height"].as(); uf::physics::impl::create( *this, radius, height ); } @@ -128,7 +128,9 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) { void uf::ObjectBehavior::destroy( uf::Object& self ) { auto& metadata = this->getComponent(); for ( auto pair : metadata.hooks.bound ) { - for ( auto id : pair.second ) uf::hooks.removeHook(pair.first, id); + for ( auto id : pair.second ) { + uf::hooks.removeHook(pair.first, id); + } } if ( this->hasComponent() ) { diff --git a/engine/src/engine/object/object.cpp b/engine/src/engine/object/object.cpp index 1d846932..b162a758 100644 --- a/engine/src/engine/object/object.cpp +++ b/engine/src/engine/object/object.cpp @@ -224,22 +224,6 @@ bool uf::Object::load( const uf::Serializer& _json ) { physics.linear.acceleration = uf::vector::decode( json["physics"]["linear"]["acceleration"], physics.linear.acceleration ); physics.rotational.velocity = uf::vector::decode( json["physics"]["rotational"]["velocity"], physics.rotational.velocity ); physics.rotational.acceleration = uf::vector::decode( json["physics"]["rotational"]["acceleration"], physics.rotational.acceleration ); - - /* - if ( ext::json::isArray( json["physics"]["linear"]["velocity"] ) ) - for ( size_t j = 0; j < 3; ++j ) - physics.linear.velocity[j] = json["physics"]["linear"]["velocity"][j].as(); - if ( ext::json::isArray( json["physics"]["linear"]["acceleration"] ) ) - for ( size_t j = 0; j < 3; ++j ) - physics.linear.acceleration[j] = json["physics"]["linear"]["acceleration"][j].as(); - - if ( ext::json::isArray( json["physics"]["rotational"]["velocity"] ) ) - for ( size_t j = 0; j < 4; ++j ) - physics.rotational.velocity[j] = json["physics"]["rotational"]["velocity"][j].as(); - if ( ext::json::isArray( json["physics"]["rotational"]["acceleration"] ) ) - for ( size_t j = 0; j < 4; ++j ) - physics.rotational.acceleration[j] = json["physics"]["rotational"]["acceleration"][j].as(); - */ } } diff --git a/engine/src/ext/gltf/gltf.cpp b/engine/src/ext/gltf/gltf.cpp index ed1e3462..a3733991 100644 --- a/engine/src/ext/gltf/gltf.cpp +++ b/engine/src/ext/gltf/gltf.cpp @@ -155,7 +155,7 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize auto imageID = graph.images.size(); auto keyName = graph.images.emplace_back(/*filename + "/" +*/ i.name); auto& image = /*graph.storage*/uf::graph::storage.images[keyName]; - if ( graph.metadata["exporter"]["image"]["print"].as() ) { + if ( graph.metadata["debug"]["print"]["image"].as() ) { UF_MSG_DEBUG("Image: {}", i.name ); } @@ -169,7 +169,7 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize auto samplerID = graph.samplers.size(); auto keyName = graph.samplers.emplace_back(/*filename + "/" +*/ s.name); auto& sampler = /*graph.storage*/uf::graph::storage.samplers[keyName]; - if ( graph.metadata["exporter"]["sampler"]["print"].as() ) { + if ( graph.metadata["debug"]["print"]["sampler"].as() ) { UF_MSG_DEBUG("Sampler: {}", s.name ); } @@ -189,7 +189,7 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize auto textureID = graph.textures.size(); auto keyName = graph.textures.emplace_back((t.name == "" ? graph.images[t.source] : (/*filename + "/" +*/ t.name))); auto& texture = /*graph.storage*/uf::graph::storage.textures[keyName]; - if ( graph.metadata["exporter"]["texture"]["print"].as() ) { + if ( graph.metadata["debug"]["print"]["texture"].as() ) { UF_MSG_DEBUG("Texture: {}", t.name ); } @@ -206,7 +206,7 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize auto materialID = graph.materials.size(); auto keyName = graph.materials.emplace_back(/*filename + "/" +*/ m.name); auto& material = /*graph.storage*/uf::graph::storage.materials[keyName]; - if ( graph.metadata["exporter"]["material"]["print"].as() ) { + if ( graph.metadata["debug"]["print"]["material"].as() ) { UF_MSG_DEBUG("Material: {}", m.name ); } @@ -233,14 +233,14 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize material.factorOcclusion = m.occlusionTexture.strength; material.factorAlphaCutoff = m.alphaCutoff; - const uf::stl::string mode = graph.metadata["alpha mode"].as(m.alphaMode); - if ( mode == "OPAQUE" ) material.modeAlpha = 0; - else if ( mode == "BLEND" ) material.modeAlpha = 1; - else if ( mode == "MASK" ) material.modeAlpha = 2; - else UF_MSG_WARNING("Unhandled alpha mode: {}", mode); + const auto mode = uf::string::lowercase( graph.metadata["renderer"]["alpha mode"].as(m.alphaMode) ); + if ( mode == "opaque" ) material.modeAlpha = 0; + else if ( mode == "blend" ) material.modeAlpha = 1; + else if ( mode == "mask" ) material.modeAlpha = 2; + else UF_MSG_WARNING("Invalid AlphaMode enum string specified: {}", mode); - if ( m.doubleSided && graph.metadata["cull mode"].as() == "auto" ) { - graph.metadata["cull mode"] = "none"; + if ( m.doubleSided && graph.metadata["renderer"]["cull mode"].as() == "auto" ) { + graph.metadata["renderer"]["cull mode"] = "none"; } } } @@ -253,7 +253,7 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize for ( auto& m : model.meshes ) { auto meshID = graph.meshes.size(); auto keyName = graph.meshes.emplace_back(/*filename + "/" +*/ m.name); - if ( graph.metadata["exporter"]["mesh"]["print"].as() ) { + if ( graph.metadata["debug"]["print"]["mesh"].as() ) { UF_MSG_DEBUG("Mesh: {}", m.name ); } @@ -299,13 +299,13 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize #define UF_GRAPH_MESH_FORMAT uf::graph::mesh::Skinned, uint32_t #define UF_GRAPH_PROCESS_PRIMITIVES_FULL 1 #define UF_GRAPH_GRID 1 - #include "processPrimitives2.inl" + #include "processPrimitives.inl" #undef UF_GRAPH_PROCESS_PRIMITIVES_FULL #undef UF_GRAPH_MESH_FORMAT } else { #define UF_GRAPH_MESH_FORMAT uf::graph::mesh::Base, uint32_t #define UF_GRAPH_PROCESS_PRIMITIVES_FULL 0 - #include "processPrimitives2.inl" + #include "processPrimitives.inl" #undef UF_GRAPH_PROCESS_PRIMITIVES_FULL #undef UF_GRAPH_MESH_FORMAT } @@ -320,7 +320,7 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize auto skinID = graph.skins.size(); auto keyName = graph.skins.emplace_back(/*filename + "/" +*/ s.name); auto& skin = /*graph.storage*/uf::graph::storage.skins[keyName]; - if ( graph.metadata["exporter"]["skin"]["print"].as() ) { + if ( graph.metadata["debug"]["print"]["skin"].as() ) { UF_MSG_DEBUG("Skin: {}", s.name ); } @@ -357,7 +357,7 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize auto animationID = graph.animations.size(); auto keyName = graph.animations.emplace_back(/*filename + "/" +*/ a.name); auto& animation = /*graph.storage*/uf::graph::storage.animations[keyName]; - if ( graph.metadata["exporter"]["animation"]["print"].as() ) { + if ( graph.metadata["debug"]["print"]["animation"].as() ) { UF_MSG_DEBUG("Animation: {}", a.name ); } @@ -417,7 +417,7 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize { for ( auto& l : model.lights ) { auto& light = graph.lights[l.name]; - if ( graph.metadata["exporter"]["light"]["print"].as() ) { + if ( graph.metadata["debug"]["print"]["light"].as() ) { UF_MSG_DEBUG("Light: {}", l.name ); } @@ -524,7 +524,7 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize // graph.metadata["baking"]["enabled"] = false; // disable lightmap loading, 99.999% of the time a previously baked lightmap will not work due to changing STs - graph.metadata["lightmap"] = false; + graph.metadata["lights"]["lightmapped"] = false; } return graph; } diff --git a/engine/src/ext/gltf/processPrimitives.inl b/engine/src/ext/gltf/processPrimitives.inl index e7dd3dd9..6e93b49e 100644 --- a/engine/src/ext/gltf/processPrimitives.inl +++ b/engine/src/ext/gltf/processPrimitives.inl @@ -1,7 +1,20 @@ +struct { + struct { + bool should = true; + size_t corrected{}; + size_t total{}; + } windingOrder; +} sanitizer; + +if ( graph.metadata["sanitizer"]["winding order"].as(true) ) { + sanitizer.windingOrder.should = true; +} + +uf::stl::vector> meshlets; + for ( auto& p : m.primitives ) { - vertices.clear(); - indices.clear(); - auto& primitive = primitives.emplace_back(); + size_t primitiveID = meshlets.size(); + auto& meshlet = meshlets.emplace_back(); struct Attribute { uf::stl::string name = ""; @@ -38,13 +51,13 @@ for ( auto& p : m.primitives ) { auto& view = model.bufferViews[accessor.bufferView]; if ( attribute.name == "POSITION" ) { - vertices.resize(accessor.count); - primitive.instance.bounds.min = pod::Vector3f{ accessor.minValues[0], accessor.minValues[1], accessor.minValues[2] }; - primitive.instance.bounds.max = pod::Vector3f{ accessor.maxValues[0], accessor.maxValues[1], accessor.maxValues[2] }; + meshlet.vertices.resize(accessor.count); + meshlet.primitive.instance.bounds.min = pod::Vector3f{ accessor.minValues[0], accessor.minValues[1], accessor.minValues[2] }; + meshlet.primitive.instance.bounds.max = pod::Vector3f{ accessor.maxValues[0], accessor.maxValues[1], accessor.maxValues[2] }; if ( !(graph.metadata["flags"]["INVERT"].as()) ){ - primitive.instance.bounds.min.x = -primitive.instance.bounds.min.x; - primitive.instance.bounds.max.x = -primitive.instance.bounds.max.x; + meshlet.primitive.instance.bounds.min.x = -meshlet.primitive.instance.bounds.min.x; + meshlet.primitive.instance.bounds.max.x = -meshlet.primitive.instance.bounds.max.x; } } @@ -80,7 +93,7 @@ for ( auto& p : m.primitives ) { } } - for ( size_t i = 0; i < vertices.size(); ++i ) { + for ( size_t i = 0; i < meshlet.vertices.size(); ++i ) { #if 0 #define ITERATE_ATTRIBUTE( name, member )\ memcpy( &vertex.member[0], &attributes[name].buffer[i * attributes[name].components], attributes[name].stride ); @@ -101,7 +114,7 @@ for ( auto& p : m.primitives ) { } #endif - auto& vertex = vertices[i]; + auto& vertex = meshlet.vertices[i]; ITERATE_ATTRIBUTE("POSITION", position, 1); ITERATE_ATTRIBUTE("TEXCOORD_0", uv, 1); ITERATE_ATTRIBUTE("COLOR_0", color, 255.0f); @@ -123,6 +136,9 @@ for ( auto& p : m.primitives ) { vertex.tangent.x = -vertex.tangent.x; #endif } + + vertex.id.x = primitiveID; + vertex.id.y = meshID; } if ( p.indices > -1 ) { @@ -130,9 +146,9 @@ for ( auto& p : m.primitives ) { auto& view = model.bufferViews[accessor.bufferView]; auto& buffer = model.buffers[view.buffer]; - indices.reserve( static_cast(accessor.count) ); + meshlet.indices.reserve( static_cast(accessor.count) ); - #define COPY_INDICES() for (size_t index = 0; index < accessor.count; index++) indices.emplace_back(buf[index]); + #define COPY_INDICES() for (size_t index = 0; index < accessor.count; index++) meshlet.indices.emplace_back(buf[index]); const void* pointer = &(buffer.data[accessor.byteOffset + view.byteOffset]); switch (accessor.componentType) { @@ -155,29 +171,113 @@ for ( auto& p : m.primitives ) { #undef COPY_INDICES } - primitive.instance.materialID = p.material; - primitive.instance.primitiveID = primitives.size() - 1; - primitive.instance.meshID = meshID; - primitive.instance.objectID = 0; + meshlet.primitive.instance.materialID = p.material; + meshlet.primitive.instance.primitiveID = primitiveID; + meshlet.primitive.instance.meshID = meshID; + meshlet.primitive.instance.objectID = 0; - primitive.drawCommand.indices = indices.size(); - primitive.drawCommand.instances = 1; - primitive.drawCommand.indexID = 0; - primitive.drawCommand.vertexID = 0; - primitive.drawCommand.instanceID = 0; - primitive.drawCommand.vertices = vertices.size(); + meshlet.primitive.drawCommand.indices = meshlet.indices.size(); + meshlet.primitive.drawCommand.instances = 1; + meshlet.primitive.drawCommand.indexID = 0; + meshlet.primitive.drawCommand.vertexID = 0; + meshlet.primitive.drawCommand.instanceID = 0; + meshlet.primitive.drawCommand.vertices = meshlet.vertices.size(); - auto& drawCommand = drawCommands.emplace_back(pod::DrawCommand{ - .indices = indices.size(), - .instances = 1, - .indexID = mesh.index.count, - .vertexID = mesh.vertex.count, - .instanceID = 0, + /* detect winding order */ if ( sanitizer.windingOrder.should ) { + if ( !meshlet.indices.empty() ) { + for ( size_t i = 0; i < meshlet.indices.size() / 3; ++i ) { + size_t indices[3] = { + meshlet.indices[i * 3 + 0], + meshlet.indices[i * 3 + 1], + meshlet.indices[i * 3 + 2], + }; + pod::Vector3f triPosition[3] = { + meshlet.vertices[indices[0]].position, + meshlet.vertices[indices[1]].position, + meshlet.vertices[indices[2]].position, + }; + pod::Vector3f normal = meshlet.vertices[indices[0]].normal; + pod::Vector3f geomNormal = uf::vector::normalize( uf::vector::cross((triPosition[0] - triPosition[1]), (triPosition[1] - triPosition[2]))); + + // negative dot = mismatched winding order + if ( uf::vector::dot( normal, geomNormal ) < 0.0f ) { + meshlet.indices[i * 3 + 0] = indices[2]; + meshlet.indices[i * 3 + 2] = indices[0]; + ++sanitizer.windingOrder.corrected; + } + ++sanitizer.windingOrder.total; + } + } else { + for ( size_t i = 0; i < meshlet.vertices.size() / 3; ++i ) { + size_t indices[3] = { + i * 3 + 0, + i * 3 + 1, + i * 3 + 2, + }; + pod::Vector3f triPosition[3] = { + meshlet.vertices[indices[0]].position, + meshlet.vertices[indices[1]].position, + meshlet.vertices[indices[2]].position, + }; + pod::Vector3f normal = meshlet.vertices[indices[0]].normal; + pod::Vector3f geomNormal = uf::vector::normalize( uf::vector::cross((triPosition[0] - triPosition[1]), (triPosition[1] - triPosition[2]))); + + // negative dot = mismatched winding order + if ( uf::vector::dot( normal, geomNormal ) < 0.0f ) { + meshlet.indices[i * 3 + 0] = indices[2]; + meshlet.indices[i * 3 + 2] = indices[0]; + ++sanitizer.windingOrder.corrected; + } + ++sanitizer.windingOrder.total; + } + } + } +} + +if ( sanitizer.windingOrder.should ) { + UF_MSG_DEBUG("Winding order correction: {:.3f}%", ( (float) sanitizer.windingOrder.corrected / (float) sanitizer.windingOrder.total ) * 100.0f ); + if ( sanitizer.windingOrder.corrected * 2 > sanitizer.windingOrder.total ) { + UF_MSG_DEBUG("Consider inverting the front face settings for mesh: {}", m.name); + } +} - .vertices = vertices.size(), - }); +if ( meshgrid.grid.divisions.x > 1 || meshgrid.grid.divisions.y > 1 || meshgrid.grid.divisions.z > 1 ) { + auto partitioned = uf::meshgrid::partition( meshgrid.grid, meshlets, meshgrid.eps ); + if ( meshgrid.print ) UF_MSG_DEBUG( "Draw commands: {}: {} -> {} | Partitions: {} -> {}", m.name, meshlets.size(), partitioned.size(), + (meshgrid.grid.divisions.x * meshgrid.grid.divisions.y * meshgrid.grid.divisions.z), meshgrid.grid.nodes.size() + ); + meshlets = std::move( partitioned ); +} + +{ + size_t indexID = 0; + size_t vertexID = 0; + + mesh.bindIndirect(); + mesh.bind(false); // default to de-interleaved regardless of requirement (makes things easier) - mesh.insertVertices(vertices); - mesh.insertIndices(indices); + for ( auto& meshlet : meshlets ) { + auto& drawCommand = drawCommands.emplace_back(pod::DrawCommand{ + .indices = meshlet.indices.size(), + .instances = 1, + .indexID = indexID, + .vertexID = vertexID, + .instanceID = 0, + .auxID = meshlet.primitive.drawCommand.auxID, + .materialID = meshlet.primitive.drawCommand.materialID, + .vertices = meshlet.vertices.size(), + }); + + primitives.emplace_back( meshlet.primitive ); + + indexID += meshlet.indices.size(); + vertexID += meshlet.vertices.size(); + + mesh.insertVertices(meshlet.vertices); + mesh.insertIndices(meshlet.indices); + } + + mesh.insertIndirects(drawCommands); + mesh.updateDescriptor(); } \ No newline at end of file diff --git a/engine/src/ext/gltf/processPrimitives2.inl b/engine/src/ext/gltf/processPrimitives2.inl deleted file mode 100644 index 4bf11db7..00000000 --- a/engine/src/ext/gltf/processPrimitives2.inl +++ /dev/null @@ -1,214 +0,0 @@ -uf::stl::vector> meshlets; - -for ( auto& p : m.primitives ) { - size_t primitiveID = meshlets.size(); - auto& meshlet = meshlets.emplace_back(); - - struct Attribute { - uf::stl::string name = ""; - size_t components = 0; - size_t length = 0; - size_t stride = 0; - uint8_t* buffer = NULL; - - uf::stl::vector floats; - uf::stl::vector int8s; - uf::stl::vector int16s; - uf::stl::vector int32s; - }; - - uf::stl::unordered_map attributes = { - {"POSITION", {}}, - {"TEXCOORD_0", {}}, - {"COLOR_0", {}}, - {"NORMAL", {}}, -#if UF_GRAPH_PROCESS_PRIMITIVES_FULL - {"TANGENT", {}}, - {"JOINTS_0", {}}, - {"WEIGHTS_0", {}}, -#endif - }; - - for ( auto& kv : attributes ) { - auto& attribute = kv.second; - attribute.name = kv.first; - auto it = p.attributes.find(attribute.name); - if ( it == p.attributes.end() ) continue; - - auto& accessor = model.accessors[it->second]; - auto& view = model.bufferViews[accessor.bufferView]; - - if ( attribute.name == "POSITION" ) { - meshlet.vertices.resize(accessor.count); - meshlet.primitive.instance.bounds.min = pod::Vector3f{ accessor.minValues[0], accessor.minValues[1], accessor.minValues[2] }; - meshlet.primitive.instance.bounds.max = pod::Vector3f{ accessor.maxValues[0], accessor.maxValues[1], accessor.maxValues[2] }; - - if ( !(graph.metadata["flags"]["INVERT"].as()) ){ - meshlet.primitive.instance.bounds.min.x = -meshlet.primitive.instance.bounds.min.x; - meshlet.primitive.instance.bounds.max.x = -meshlet.primitive.instance.bounds.max.x; - } - } - - switch ( accessor.componentType ) { - case TINYGLTF_COMPONENT_TYPE_BYTE: - case TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE: { - auto* buffer = reinterpret_cast(&(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); - attribute.components = accessor.ByteStride(view) / sizeof(uint8_t); - attribute.length = accessor.count * attribute.components; - attribute.int8s.assign( &buffer[0], &buffer[attribute.length] ); - } break; - case TINYGLTF_COMPONENT_TYPE_SHORT: - case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT: { - auto* buffer = reinterpret_cast(&(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); - attribute.components = accessor.ByteStride(view) / sizeof(uint16_t); - attribute.length = accessor.count * attribute.components; - attribute.int16s.assign( &buffer[0], &buffer[attribute.length] ); - } break; - case TINYGLTF_COMPONENT_TYPE_INT: - case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT: { - auto* buffer = reinterpret_cast(&(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); - attribute.components = accessor.ByteStride(view) / sizeof(uint32_t); - attribute.length = accessor.count * attribute.components; - attribute.int32s.assign( &buffer[0], &buffer[attribute.length] ); - } break; - case TINYGLTF_COMPONENT_TYPE_FLOAT: { - auto* buffer = reinterpret_cast(&(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); - attribute.components = accessor.ByteStride(view) / sizeof(float); - attribute.length = accessor.count * attribute.components; - attribute.floats.assign( &buffer[0], &buffer[attribute.length] ); - } break; - default: UF_MSG_ERROR("Unsupported component type"); - } - } - - for ( size_t i = 0; i < meshlet.vertices.size(); ++i ) { - #if 0 - #define ITERATE_ATTRIBUTE( name, member )\ - memcpy( &vertex.member[0], &attributes[name].buffer[i * attributes[name].components], attributes[name].stride ); - #else - #define ITERATE_ATTRIBUTE( name, member, floatScale )\ - if ( !attributes[name].int8s.empty() ) { \ - for ( size_t j = 0; j < attributes[name].components; ++j )\ - vertex.member[j] = attributes[name].int8s[i * attributes[name].components + j];\ - } else if ( !attributes[name].int16s.empty() ) { \ - for ( size_t j = 0; j < attributes[name].components; ++j )\ - vertex.member[j] = attributes[name].int16s[i * attributes[name].components + j];\ - } else if ( !attributes[name].int32s.empty() ) { \ - for ( size_t j = 0; j < attributes[name].components; ++j )\ - vertex.member[j] = attributes[name].int32s[i * attributes[name].components + j];\ - } else if ( !attributes[name].floats.empty() ) { \ - for ( size_t j = 0; j < attributes[name].components; ++j )\ - vertex.member[j] = attributes[name].floats[i * attributes[name].components + j] * floatScale;\ - } - #endif - - auto& vertex = meshlet.vertices[i]; - ITERATE_ATTRIBUTE("POSITION", position, 1); - ITERATE_ATTRIBUTE("TEXCOORD_0", uv, 1); - ITERATE_ATTRIBUTE("COLOR_0", color, 255.0f); - ITERATE_ATTRIBUTE("NORMAL", normal, 1); - #if UF_GRAPH_PROCESS_PRIMITIVES_FULL - ITERATE_ATTRIBUTE("TANGENT", tangent, 1); - ITERATE_ATTRIBUTE("JOINTS_0", joints, 1); - ITERATE_ATTRIBUTE("WEIGHTS_0", weights, 1); - #endif - - #undef ITERATE_ATTRIBUTE - - // required due to reverse-Z projection matrix flipping the X axis as well - // default is to proceed with this - if ( !(graph.metadata["flags"]["INVERT"].as()) ){ - vertex.position.x = -vertex.position.x; - vertex.normal.x = -vertex.normal.x; - #if UF_GRAPH_PROCESS_PRIMITIVES_FULL - vertex.tangent.x = -vertex.tangent.x; - #endif - } - - vertex.id.x = primitiveID; - vertex.id.y = meshID; - } - - if ( p.indices > -1 ) { - auto& accessor = model.accessors[p.indices]; - auto& view = model.bufferViews[accessor.bufferView]; - auto& buffer = model.buffers[view.buffer]; - - meshlet.indices.reserve( static_cast(accessor.count) ); - - #define COPY_INDICES() for (size_t index = 0; index < accessor.count; index++) meshlet.indices.emplace_back(buf[index]); - - const void* pointer = &(buffer.data[accessor.byteOffset + view.byteOffset]); - switch (accessor.componentType) { - case TINYGLTF_PARAMETER_TYPE_UNSIGNED_INT: { - auto* buf = static_cast( pointer ); - COPY_INDICES() - break; - } - case TINYGLTF_PARAMETER_TYPE_UNSIGNED_SHORT: { - auto* buf = static_cast( pointer ); - COPY_INDICES() - break; - } - case TINYGLTF_PARAMETER_TYPE_UNSIGNED_BYTE: { - auto* buf = static_cast( pointer ); - COPY_INDICES() - break; - } - } - #undef COPY_INDICES - } - - meshlet.primitive.instance.materialID = p.material; - meshlet.primitive.instance.primitiveID = primitiveID; - meshlet.primitive.instance.meshID = meshID; - meshlet.primitive.instance.objectID = 0; - - meshlet.primitive.drawCommand.indices = meshlet.indices.size(); - meshlet.primitive.drawCommand.instances = 1; - meshlet.primitive.drawCommand.indexID = 0; - meshlet.primitive.drawCommand.vertexID = 0; - meshlet.primitive.drawCommand.instanceID = 0; - meshlet.primitive.drawCommand.vertices = meshlet.vertices.size(); -} - - -if ( meshgrid.grid.divisions.x > 1 || meshgrid.grid.divisions.y > 1 || meshgrid.grid.divisions.z > 1 ) { - auto partitioned = uf::meshgrid::partition( meshgrid.grid, meshlets, meshgrid.eps ); - if ( meshgrid.print ) UF_MSG_DEBUG( "Draw commands: {}: {} -> {} | Partitions: {} -> {}", m.name, meshlets.size(), partitioned.size(), - (meshgrid.grid.divisions.x * meshgrid.grid.divisions.y * meshgrid.grid.divisions.z), meshgrid.grid.nodes.size() - ); - meshlets = std::move( partitioned ); -} - -{ - size_t indexID = 0; - size_t vertexID = 0; - - mesh.bindIndirect(); - mesh.bind(false); // default to de-interleaved regardless of requirement (makes things easier) - - for ( auto& meshlet : meshlets ) { - auto& drawCommand = drawCommands.emplace_back(pod::DrawCommand{ - .indices = meshlet.indices.size(), - .instances = 1, - .indexID = indexID, - .vertexID = vertexID, - .instanceID = 0, - .auxID = meshlet.primitive.drawCommand.auxID, - .materialID = meshlet.primitive.drawCommand.materialID, - .vertices = meshlet.vertices.size(), - }); - - primitives.emplace_back( meshlet.primitive ); - - indexID += meshlet.indices.size(); - vertexID += meshlet.vertices.size(); - - mesh.insertVertices(meshlet.vertices); - mesh.insertIndices(meshlet.indices); - } - - mesh.insertIndirects(drawCommands); - mesh.updateDescriptor(); -} \ No newline at end of file diff --git a/engine/src/ext/imgui/imgui.cpp b/engine/src/ext/imgui/imgui.cpp index 6c647345..0a8ba0fc 100644 --- a/engine/src/ext/imgui/imgui.cpp +++ b/engine/src/ext/imgui/imgui.cpp @@ -91,7 +91,7 @@ namespace { Items.clear(); } - void AddLog(const uf::stl::string &str) { AddLog(str.c_str()); } + void AddLog(const uf::stl::string &str) { AddLog("%s", str.c_str()); } void AddLog(const char *fmt, ...) IM_FMTARGS(2) { // FIXME-OPT char buf[1024]; diff --git a/engine/src/ext/lua/lua.cpp b/engine/src/ext/lua/lua.cpp index 72378539..e16dc1db 100644 --- a/engine/src/ext/lua/lua.cpp +++ b/engine/src/ext/lua/lua.cpp @@ -59,7 +59,7 @@ void ext::lua::onInitialization( const std::function& function ) { namespace binds { namespace hook { - void add( const uf::stl::string& name, const sol::function& function ) { + void add( const uf::stl::string& name, sol::function function ) { uf::hooks.addHook( name, [function](ext::json::Value& json){ sol::table table = ext::lua::state["json"]["decode"]( json.dump() ); auto result = function( table ); diff --git a/engine/src/ext/lua/usertypes/object.cpp b/engine/src/ext/lua/usertypes/object.cpp index fd38eb01..5fdb7444 100644 --- a/engine/src/ext/lua/usertypes/object.cpp +++ b/engine/src/ext/lua/usertypes/object.cpp @@ -87,7 +87,7 @@ namespace binds { self.generateGraph(); return true; } - uf::Object& findByUid( uf::Object& self, const size_t& index ) { + uf::Object& findByUid( uf::Object& self, size_t index ) { auto* pointer = self.findByUid( index ); if ( pointer ) return pointer->as(); static uf::Object null; @@ -123,7 +123,7 @@ namespace binds { uf::Object& getParent( uf::Object& self ){ return self.getParent().as(); } - void addHook( uf::Object& self, const uf::stl::string& name, const sol::function& function ) { + void addHook( uf::Object& self, const uf::stl::string& name, sol::function function ) { self.addHook( name, [function](ext::json::Value& json){ uf::stl::string payload = json.dump(); auto decoded = ext::lua::decode( payload ); diff --git a/engine/src/ext/lua/usertypes/quaternion.cpp b/engine/src/ext/lua/usertypes/quaternion.cpp index 43236454..83d690d5 100644 --- a/engine/src/ext/lua/usertypes/quaternion.cpp +++ b/engine/src/ext/lua/usertypes/quaternion.cpp @@ -3,7 +3,7 @@ #include namespace binds { - float index( const pod::Quaternion<>& self, const size_t& index ) { + float index( const pod::Quaternion<>& self, size_t index ) { return self[index]; } pod::Quaternion<> lookAt( const pod::Vector3f& at, const pod::Vector3f& up ) { diff --git a/engine/src/ext/lua/usertypes/vector.cpp b/engine/src/ext/lua/usertypes/vector.cpp index 587bb756..0036ed8a 100644 --- a/engine/src/ext/lua/usertypes/vector.cpp +++ b/engine/src/ext/lua/usertypes/vector.cpp @@ -4,7 +4,7 @@ namespace binds { namespace v3f { - float index( const pod::Vector3f& self, const size_t& index ) { + float index( const pod::Vector3f& self, size_t index ) { return self[index]; } float distance( pod::Vector3f& self, const pod::Vector3f& other ) { @@ -45,7 +45,7 @@ namespace binds { } } namespace v4f { - float index( const pod::Vector4f& self, const size_t& index ) { + float index( const pod::Vector4f& self, size_t index ) { return self[index]; } float distance( pod::Vector4f& self, const pod::Vector4f& other ) { diff --git a/engine/src/ext/opengl/commands.cpp b/engine/src/ext/opengl/commands.cpp index 7dd57185..f7c6fc6e 100644 --- a/engine/src/ext/opengl/commands.cpp +++ b/engine/src/ext/opengl/commands.cpp @@ -300,7 +300,7 @@ void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer:: GL_ERROR_CHECK(glEnable(drawInfo.textures.primary.viewType)); GL_ERROR_CHECK(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); GL_ERROR_CHECK(glBindTexture(drawInfo.textures.primary.viewType, drawInfo.textures.primary.image)); - GL_ERROR_CHECK(glTexCoordPointer(2, GL_FLOAT, drawInfo.attributes.uv.stride, (drawInfo.attributes.uv.pointer + drawInfo.attributes.uv.stride * drawInfo.descriptor.inputs.vertex.first))); + GL_ERROR_CHECK(glTexCoordPointer(2, GL_FLOAT, drawInfo.attributes.uv.stride, (static_cast(drawInfo.attributes.uv.pointer) + drawInfo.attributes.uv.stride * drawInfo.descriptor.inputs.vertex.first))); if ( !(drawInfo.textures.secondary.image && drawInfo.attributes.st.pointer) ) { GL_ERROR_CHECK(glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)); @@ -314,23 +314,23 @@ void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer:: GL_ERROR_CHECK(glBindTexture(drawInfo.textures.secondary.viewType, drawInfo.textures.secondary.image)); GL_ERROR_CHECK(glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)); - GL_ERROR_CHECK(glTexCoordPointer(2, GL_FLOAT, drawInfo.attributes.st.stride, (drawInfo.attributes.st.pointer + drawInfo.attributes.st.stride * drawInfo.descriptor.inputs.vertex.first))); + GL_ERROR_CHECK(glTexCoordPointer(2, GL_FLOAT, drawInfo.attributes.st.stride, (static_cast(drawInfo.attributes.st.pointer) + drawInfo.attributes.st.stride * drawInfo.descriptor.inputs.vertex.first))); } } - if ( drawInfo.attributes.normal.pointer ) GL_ERROR_CHECK(glNormalPointer(GL_FLOAT, drawInfo.attributes.normal.stride, (drawInfo.attributes.normal.pointer + drawInfo.attributes.normal.stride * drawInfo.descriptor.inputs.vertex.first))); + if ( drawInfo.attributes.normal.pointer ) GL_ERROR_CHECK(glNormalPointer(GL_FLOAT, drawInfo.attributes.normal.stride, (static_cast(drawInfo.attributes.normal.pointer) + drawInfo.attributes.normal.stride * drawInfo.descriptor.inputs.vertex.first))); if ( drawInfo.attributes.color.pointer ) { GLenum format = GL_UNSIGNED_BYTE; switch ( drawInfo.attributes.color.descriptor.size / drawInfo.attributes.color.descriptor.components ) { case sizeof(uint8_t): format = GL_UNSIGNED_BYTE; break; case sizeof(float): format = GL_FLOAT; break; } - GL_ERROR_CHECK(glColorPointer(drawInfo.attributes.color.descriptor.components, format, drawInfo.attributes.color.stride, (drawInfo.attributes.color.pointer + drawInfo.attributes.color.stride * drawInfo.descriptor.inputs.vertex.first))); + GL_ERROR_CHECK(glColorPointer(drawInfo.attributes.color.descriptor.components, format, drawInfo.attributes.color.stride, (static_cast(drawInfo.attributes.color.pointer) + drawInfo.attributes.color.stride * drawInfo.descriptor.inputs.vertex.first))); } - GL_ERROR_CHECK(glVertexPointer(3, GL_FLOAT, drawInfo.attributes.position.stride, (drawInfo.attributes.position.pointer + drawInfo.attributes.position.stride * drawInfo.descriptor.inputs.vertex.first))); + GL_ERROR_CHECK(glVertexPointer(3, GL_FLOAT, drawInfo.attributes.position.stride, (static_cast(drawInfo.attributes.position.pointer) + drawInfo.attributes.position.stride * drawInfo.descriptor.inputs.vertex.first))); if ( drawInfo.descriptor.inputs.index.count ) { - GL_ERROR_CHECK(glDrawElements(GL_TRIANGLES, drawInfo.descriptor.inputs.index.count, indicesType, (drawInfo.attributes.index.pointer + drawInfo.attributes.index.stride * drawInfo.descriptor.inputs.index.first))); + GL_ERROR_CHECK(glDrawElements(GL_TRIANGLES, drawInfo.descriptor.inputs.index.count, indicesType, (static_cast(drawInfo.attributes.index.pointer) + drawInfo.attributes.index.stride * drawInfo.descriptor.inputs.index.first))); } else { GL_ERROR_CHECK(glDrawArrays(GL_TRIANGLES, drawInfo.descriptor.inputs.vertex.first, drawInfo.descriptor.inputs.vertex.count)); } diff --git a/engine/src/ext/opengl/opengl.cpp b/engine/src/ext/opengl/opengl.cpp index 5cb1ab49..dc5cf3df 100644 --- a/engine/src/ext/opengl/opengl.cpp +++ b/engine/src/ext/opengl/opengl.cpp @@ -47,7 +47,6 @@ bool ext::opengl::settings::invariant::individualPipelines = true; bool ext::opengl::settings::invariant::multithreadedRecording = true; uf::stl::string ext::opengl::settings::invariant::deferredMode = ""; -bool ext::opengl::settings::invariant::deferredReconstructPosition = false; bool ext::opengl::settings::invariant::deferredAliasOutputToSwapchain = false; bool ext::opengl::settings::invariant::deferredSampling = false; diff --git a/engine/src/ext/reactphysics/reactphysics.cpp b/engine/src/ext/reactphysics/reactphysics.cpp index f5ed4555..4fd95a4a 100644 --- a/engine/src/ext/reactphysics/reactphysics.cpp +++ b/engine/src/ext/reactphysics/reactphysics.cpp @@ -20,16 +20,21 @@ namespace { class RaycastCallback : public rp3d::RaycastCallback { public: bool isHit = false; + uf::Object* source = NULL; rp3d::RaycastInfo raycastInfo; virtual rp3d::decimal notifyRaycastHit(const rp3d::RaycastInfo& info) override { if ( !isHit || raycastInfo.hitFraction > info.hitFraction ) { - raycastInfo.body = info.body; - raycastInfo.hitFraction = info.hitFraction; - raycastInfo.collider = info.collider; - raycastInfo.worldNormal = info.worldNormal; - raycastInfo.worldPoint = info.worldPoint; - isHit = true; + if ( info.body->getUserData() == source ) { + + } else { + raycastInfo.body = info.body; + raycastInfo.hitFraction = info.hitFraction; + raycastInfo.collider = info.collider; + raycastInfo.worldNormal = info.worldNormal; + raycastInfo.worldPoint = info.worldPoint; + isHit = true; + } } // return rp3d::decimal(1.0); return raycastInfo.hitFraction; @@ -295,6 +300,9 @@ void ext::reactphysics::attach( pod::PhysicsState& state ) { state.body->enableGravity(false); } + // affects air speed, bad +// state.body->setLinearDamping(state.stats.friction); + auto& material = collider->getMaterial(); material.setBounciness(0); @@ -316,13 +324,18 @@ pod::PhysicsState& ext::reactphysics::create( uf::Object& object, const uf::Mesh uf::Mesh::Input indexInput = mesh.index; uf::Mesh::Attribute vertexAttribute = mesh.vertex.attributes.front(); + uf::Mesh::Attribute normalAttribute = mesh.vertex.attributes.front(); uf::Mesh::Attribute indexAttribute = mesh.index.attributes.front(); - for ( auto& attribute : mesh.vertex.attributes ) if ( attribute.descriptor.name == "position" ) { vertexAttribute = attribute; break; } + for ( auto& attribute : mesh.vertex.attributes ) { + if ( attribute.descriptor.name == "position" ) vertexAttribute = attribute; + if ( attribute.descriptor.name == "normal" ) normalAttribute = attribute; + } UF_ASSERT( vertexAttribute.descriptor.name == "position" ); rp3d::TriangleVertexArray::IndexDataType indexType = rp3d::TriangleVertexArray::IndexDataType::INDEX_INTEGER_TYPE; rp3d::TriangleVertexArray::VertexDataType vertexType = rp3d::TriangleVertexArray::VertexDataType::VERTEX_FLOAT_TYPE; + rp3d::TriangleVertexArray::NormalDataType normalType = rp3d::TriangleVertexArray::NormalDataType::NORMAL_FLOAT_TYPE; switch ( mesh.index.size ) { case sizeof(uint16_t): indexType = rp3d::TriangleVertexArray::IndexDataType::INDEX_SHORT_TYPE; break; case sizeof(uint32_t): indexType = rp3d::TriangleVertexArray::IndexDataType::INDEX_INTEGER_TYPE; break; @@ -334,6 +347,57 @@ pod::PhysicsState& ext::reactphysics::create( uf::Object& object, const uf::Mesh vertexInput = mesh.remapVertexInput( i ); indexInput = mesh.remapIndexInput( i ); + if ( normalAttribute.descriptor.name == "normal" ) { + rMesh->addSubpart(new rp3d::TriangleVertexArray( + vertexInput.count, + (const uint8_t*) (vertexAttribute.pointer) + vertexAttribute.stride * vertexInput.first, + vertexAttribute.stride, + + (const uint8_t*) (normalAttribute.pointer) + normalAttribute.stride * vertexInput.first, + normalAttribute.stride, + + indexInput.count / 3, + (const uint8_t*) (indexAttribute.pointer) + indexAttribute.stride * indexInput.first, + indexAttribute.stride * 3, + + vertexType, + normalType, + indexType + )); + } else { + rMesh->addSubpart(new rp3d::TriangleVertexArray( + vertexInput.count, + (const uint8_t*) (vertexAttribute.pointer) + vertexAttribute.stride * vertexInput.first, + vertexAttribute.stride, + + indexInput.count / 3, + (const uint8_t*) (indexAttribute.pointer) + indexAttribute.stride * indexInput.first, + indexAttribute.stride * 3, + + vertexType, + indexType + )); + } + } + } else { + if ( normalAttribute.descriptor.name == "normal" ) { + rMesh->addSubpart(new rp3d::TriangleVertexArray( + vertexInput.count, + (const uint8_t*) (vertexAttribute.pointer) + vertexAttribute.stride * vertexInput.first, + vertexAttribute.stride, + + (const uint8_t*) (normalAttribute.pointer) + normalAttribute.stride * vertexInput.first, + normalAttribute.stride, + + indexInput.count / 3, + (const uint8_t*) (indexAttribute.pointer) + indexAttribute.stride * indexInput.first, + indexAttribute.stride * 3, + + vertexType, + normalType, + indexType + )); + } else { rMesh->addSubpart(new rp3d::TriangleVertexArray( vertexInput.count, (const uint8_t*) (vertexAttribute.pointer) + vertexAttribute.stride * vertexInput.first, @@ -347,19 +411,6 @@ pod::PhysicsState& ext::reactphysics::create( uf::Object& object, const uf::Mesh indexType )); } - } else { - rMesh->addSubpart(new rp3d::TriangleVertexArray( - vertexInput.count, - (const uint8_t*) (vertexAttribute.pointer) + vertexAttribute.stride * vertexInput.first, - vertexAttribute.stride, - - indexInput.count / 3, - (const uint8_t*) (indexAttribute.pointer) + indexAttribute.stride * indexInput.first, - indexAttribute.stride * 3, - - vertexType, - indexType - )); } auto& state = ext::reactphysics::create( object ); @@ -512,30 +563,17 @@ float ext::reactphysics::rayCast( const pod::Vector3f& center, const pod::Vector return -1; ::RaycastCallback callback; - ::world->raycast( rp3d::Ray( ::convert( center ), ::convert( direction ) ), &callback ); + ::world->raycast( rp3d::Ray( ::convert( center ), ::convert( center + direction ) ), &callback ); if ( !callback.isHit ) return -1; return callback.raycastInfo.hitFraction; } -float ext::reactphysics::rayCast( const pod::Vector3f& center, const pod::Vector3f& direction, size_t& uid ) { +float ext::reactphysics::rayCast( const pod::Vector3f& center, const pod::Vector3f& direction, uf::Object* source, uf::Object*& object ) { if ( !::world ) return -1; ::RaycastCallback callback; - ::world->raycast( rp3d::Ray( ::convert( center ), ::convert( direction ) ), &callback ); - uid = 0; - if ( !callback.isHit ) { - return -1; - } - auto* object = (uf::Object*) callback.raycastInfo.body->getUserData(); - uid = object->getUid(); - return callback.raycastInfo.hitFraction; -} -float ext::reactphysics::rayCast( const pod::Vector3f& center, const pod::Vector3f& direction, uf::Object*& object ) { - if ( !::world ) - return -1; - - ::RaycastCallback callback; - ::world->raycast( rp3d::Ray( ::convert( center ), ::convert( direction ) ), &callback ); + callback.source = source; + ::world->raycast( rp3d::Ray( ::convert( center ), ::convert( center + direction ) ), &callback ); object = NULL; if ( !callback.isHit ) { return -1; diff --git a/engine/src/ext/vulkan/graphic.cpp b/engine/src/ext/vulkan/graphic.cpp index 8b5f4c36..4d9b022d 100644 --- a/engine/src/ext/vulkan/graphic.cpp +++ b/engine/src/ext/vulkan/graphic.cpp @@ -1042,8 +1042,7 @@ void ext::vulkan::Graphic::initializeMesh( uf::Mesh& mesh, bool buffer ) { } } bool ext::vulkan::Graphic::updateMesh( uf::Mesh& mesh ) { - UF_MSG_ERROR("need to fix"); - return false; +// UF_MSG_ERROR("need to fix"); return false; // generate indices if not found // if ( mesh.index.count == 0 ) mesh.generateIndices(); diff --git a/engine/src/ext/vulkan/vulkan.cpp b/engine/src/ext/vulkan/vulkan.cpp index 0db80cf2..a94778a2 100644 --- a/engine/src/ext/vulkan/vulkan.cpp +++ b/engine/src/ext/vulkan/vulkan.cpp @@ -46,8 +46,7 @@ bool ext::vulkan::settings::invariant::individualPipelines = true; bool ext::vulkan::settings::invariant::multithreadedRecording = true; uf::stl::string ext::vulkan::settings::invariant::deferredMode = ""; -bool ext::vulkan::settings::invariant::deferredReconstructPosition = false; -bool ext::vulkan::settings::invariant::deferredAliasOutputToSwapchain = true; +bool ext::vulkan::settings::invariant::deferredAliasOutputToSwapchain = false; bool ext::vulkan::settings::invariant::deferredSampling = true; bool ext::vulkan::settings::invariant::multiview = true; diff --git a/engine/src/utils/hook/hook.cpp b/engine/src/utils/hook/hook.cpp index ca54d584..4b5d6c2b 100644 --- a/engine/src/utils/hook/hook.cpp +++ b/engine/src/utils/hook/hook.cpp @@ -16,7 +16,7 @@ void uf::Hooks::removeHook( const uf::Hooks::name_t& name, size_t uid ) { auto& container = this->m_container[name]; for ( auto it = container.begin(); it != container.end(); ++it ) { if ( it->uid == uid ) { - this->m_container[name].erase(it); + it = container.erase(it); break; } } diff --git a/engine/src/utils/http/http.cpp b/engine/src/utils/http/http.cpp index 3f99734d..3846c89b 100644 --- a/engine/src/utils/http/http.cpp +++ b/engine/src/utils/http/http.cpp @@ -11,7 +11,7 @@ namespace { } } -uf::Http UF_API uf::http::get( const uf::stl::string& url ) { +uf::Http uf::http::get( const uf::stl::string& url ) { uf::Http http; #if UF_USE_CURL diff --git a/engine/src/utils/serialize/serializer.cpp b/engine/src/utils/serialize/serializer.cpp index b8b39a59..0e99559d 100644 --- a/engine/src/utils/serialize/serializer.cpp +++ b/engine/src/utils/serialize/serializer.cpp @@ -160,18 +160,9 @@ void uf::Serializer::merge( const uf::Serializer& other, bool priority ) { update(*this, other); } -void uf::Serializer::import( const uf::Serializer& other ) { -/* - uf::Serializer diff = nlohmann::json::diff(*this, other); - uf::Serializer filtered; - for ( size_t i = 0; i < diff.size(); ++i ) { - if ( diff[i]["op"].as() != "remove" ) - filtered.emplace_back(diff[i]); - } - patch( filtered ); - std::cout << this->dump(1, '\t') << std::endl; -*/ +// only updates if this[key] == null +void uf::Serializer::import( const uf::Serializer& other ) { if ( !ext::json::isObject( *this ) || !ext::json::isObject( other ) ) return; std::function update = [&]( ext::json::Value& a, const ext::json::Value& b ) { // doesn't exist, just copy it diff --git a/ext/behaviors/player/behavior.cpp b/ext/behaviors/player/behavior.cpp index dce82de8..9743e711 100644 --- a/ext/behaviors/player/behavior.cpp +++ b/ext/behaviors/player/behavior.cpp @@ -203,17 +203,26 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { stats.noclipped = metadata.system.noclipped; stats.floored = stats.noclipped; auto& collider = this->getComponent(); - if ( !stats.floored && collider.body && uf::physics::impl::rayCast( transform.position, transform.position - pod::Vector3f{0,1,0} ) >= 0.0f ) stats.floored = true; - else stats.floored |= fabs(physics.linear.velocity.y) < 0.01f; +// if ( !stats.floored && collider.body && uf::physics::impl::rayCast( transform.position, transform.position - pod::Vector3f{0,1,0} ) >= 0.0f ) stats.floored = true; + { + uf::Object* hit = NULL; + pod::Vector3f center = transform.position + metadata.movement.floored.feet; + pod::Vector3f direction = metadata.movement.floored.floor; + float t = 0.0f; + if ( !stats.floored && collider.body && (t = uf::physics::impl::rayCast( center, direction, this, hit )) >= 0.0f ) { + if ( metadata.movement.floored.print ) UF_MSG_DEBUG("Floored: {} | {}", hit->getName(), t); + stats.floored = true; + } + } - TIMER(0.125, keys.use && ) { + TIMER(0.25, keys.use && ) { size_t uid = 0; uf::Object* pointer = NULL; float length = 4.0f; - pod::Vector3f pos = transform.position + cameraTransform.position; - pod::Vector3f dir = uf::vector::normalize( transform.forward + pod::Vector3f{ 0, cameraTransform.forward.y, 0 } ) * length; + pod::Vector3f center = transform.position + cameraTransform.position; + pod::Vector3f direction = uf::vector::normalize( transform.forward + pod::Vector3f{ 0, cameraTransform.forward.y, 0 } ) * length; - float depth = uf::physics::impl::rayCast( pos, pos + dir, pointer ); + float depth = uf::physics::impl::rayCast( center, direction, this, pointer ); if ( pointer ) { ext::json::Value payload; payload["uid"] = this->getUid(); @@ -363,7 +372,8 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { if ( stats.noclipped ) { physics.linear.velocity += target * speed.move; } else { - float delta = collider.body ? uf::physics::impl::timescale : uf::physics::time::delta; + // float delta = collider.body ? uf::physics::impl::timescale : uf::physics::time::delta; + float delta = uf::physics::time::delta; physics.linear.velocity += target * std::clamp( speed.move * factor - uf::vector::dot( physics.linear.velocity, target ), 0.0f, speed.move * 10 * delta ); } @@ -511,8 +521,8 @@ void ext::PlayerBehavior::render( uf::Object& self ){} void ext::PlayerBehavior::destroy( uf::Object& self ){} void ext::PlayerBehavior::Metadata::serialize( uf::Object& self, uf::Serializer& serializer ){ auto& serializerSystem = serializer["system"]; - auto& serializerSystemPhysics = serializerSystem["physics"]; - auto& serializerSystemPhysicsMovement = serializerSystemPhysics["movement"]; + auto& serializerPhysics = serializer["physics"]; + auto& serializerMovement = serializer["movement"]; auto& serializerAudioFootstep = serializer["audio"]["footstep"]; auto& serializerCamera = serializer["camera"]; auto& serializerCameraLimit = serializerCamera["limit"]; @@ -521,15 +531,18 @@ void ext::PlayerBehavior::Metadata::serialize( uf::Object& self, uf::Serializer& serializerSystem["control"] = /*this->*/system.control; serializerSystem["crouching"] = /*this->*/system.crouching; serializerSystem["noclipped"] = /*this->*/system.noclipped; - serializerSystemPhysics["friction"] = /*this->*/movement.friction; - serializerSystemPhysicsMovement["rotate"] = /*this->*/movement.rotate; - serializerSystemPhysicsMovement["move"] = /*this->*/movement.move; - serializerSystemPhysicsMovement["run"] = /*this->*/movement.run; - serializerSystemPhysicsMovement["walk"] = /*this->*/movement.walk; - serializerSystemPhysicsMovement["air"] = /*this->*/movement.air; - serializerSystemPhysicsMovement["jump"] = uf::vector::encode(/*this->*/movement.jump); - serializerSystemPhysicsMovement["crouch"] = /*this->*/movement.crouch; -// serializerSystemPhysicsMovement["look"] = /*this->*/movement.look; + serializerPhysics["friction"] = /*this->*/movement.friction; + serializerMovement["rotate"] = /*this->*/movement.rotate; + serializerMovement["move"] = /*this->*/movement.move; + serializerMovement["run"] = /*this->*/movement.run; + serializerMovement["walk"] = /*this->*/movement.walk; + serializerMovement["air"] = /*this->*/movement.air; + serializerMovement["jump"] = uf::vector::encode(/*this->*/movement.jump); + serializerMovement["floored"]["feet"] = uf::vector::encode(/*this->*/movement.floored.feet); + serializerMovement["floored"]["floor"] = uf::vector::encode(/*this->*/movement.floored.floor); + serializerMovement["floored"]["print"] = /*this->*/movement.floored.print; + serializerMovement["crouch"] = /*this->*/movement.crouch; +// serializerMovement["look"] = /*this->*/movement.look; serializerAudioFootstep["list"] = /*this->*/audio.footstep.list; serializerAudioFootstep["volume"] = /*this->*/audio.footstep.volume; serializerCamera["invert"] = uf::vector::encode(/*this->*/camera.invert); @@ -540,32 +553,35 @@ void ext::PlayerBehavior::Metadata::serialize( uf::Object& self, uf::Serializer& void ext::PlayerBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer& serializer ){ auto& serializerSystem = serializer["system"]; auto& serializerAudioFootstep = serializer["audio"]["footstep"]; - auto& serializerSystemPhysics = serializerSystem["physics"]; - auto& serializerSystemPhysicsMovement = serializerSystemPhysics["movement"]; + auto& serializerPhysics = serializer["physics"]; + auto& serializerMovement = serializer["movement"]; auto& serializerCamera = serializer["camera"]; auto& serializerCameraLimit = serializerCamera["limit"]; - /*this->*/system.menu = serializerSystem["menu"].as(); - /*this->*/system.control = serializerSystem["control"].as(true); - /*this->*/system.crouching = serializerSystem["crouching"].as(); - /*this->*/system.noclipped = serializerSystem["noclipped"].as(); - /*this->*/movement.friction = serializerSystemPhysics["friction"].as(); - /*this->*/movement.rotate = serializerSystemPhysicsMovement["rotate"].as(); - /*this->*/movement.move = serializerSystemPhysicsMovement["move"].as(); - /*this->*/movement.run = serializerSystemPhysicsMovement["run"].as(); - /*this->*/movement.walk = serializerSystemPhysicsMovement["walk"].as(); - /*this->*/movement.air = serializerSystemPhysicsMovement["air"].as(); - /*this->*/movement.jump = uf::vector::decode(serializerSystemPhysicsMovement["jump"], pod::Vector3f{}); - /*this->*/movement.crouch = serializerSystemPhysicsMovement["crouch"].as(); -// /*this->*/movement.look = serializerSystemPhysicsMovement["look"].as(1.0f); + /*this->*/system.menu = serializerSystem["menu"].as(/*this->*/system.menu); + /*this->*/system.control = serializerSystem["control"].as(/*this->*/system.control); + /*this->*/system.crouching = serializerSystem["crouching"].as(/*this->*/system.crouching); + /*this->*/system.noclipped = serializerSystem["noclipped"].as(/*this->*/system.noclipped); + /*this->*/movement.friction = serializerPhysics["friction"].as(/*this->*/movement.friction); + /*this->*/movement.rotate = serializerMovement["rotate"].as(/*this->*/movement.rotate); + /*this->*/movement.move = serializerMovement["move"].as(/*this->*/movement.move); + /*this->*/movement.run = serializerMovement["run"].as(/*this->*/movement.run); + /*this->*/movement.walk = serializerMovement["walk"].as(/*this->*/movement.walk); + /*this->*/movement.air = serializerMovement["air"].as(/*this->*/movement.air); + /*this->*/movement.jump = uf::vector::decode(serializerMovement["jump"], /*this->*/movement.jump); + /*this->*/movement.floored.feet = uf::vector::decode(serializerMovement["floored"]["feet"], /*this->*/movement.floored.feet); + /*this->*/movement.floored.floor = uf::vector::decode(serializerMovement["floored"]["floor"], /*this->*/movement.floored.floor); + /*this->*/movement.floored.print = serializerMovement["floored"]["print"].as(/*this->*/movement.floored.print); + /*this->*/movement.crouch = serializerMovement["crouch"].as(/*this->*/movement.crouch); +// /*this->*/movement.look = serializerMovement["look"].as(1.0f); ext::json::forEach( serializerAudioFootstep["list"], [&]( const ext::json::Value& value ){ /*this->*/audio.footstep.list.emplace_back(value); }); /*this->*/audio.footstep.volume = serializerAudioFootstep["volume"].as(); - /*this->*/camera.invert = uf::vector::decode( serializerCamera["invert"], pod::Vector3t{false, false, false} ); - /*this->*/camera.limit.current = uf::vector::decode( serializerCameraLimit["current"], pod::Vector3f{NAN, NAN, NAN} ); - /*this->*/camera.limit.min = uf::vector::decode( serializerCameraLimit["minima"], pod::Vector3f{NAN, NAN, NAN} ); - /*this->*/camera.limit.max = uf::vector::decode( serializerCameraLimit["maxima"], pod::Vector3f{NAN, NAN, NAN} ); + /*this->*/camera.invert = uf::vector::decode( serializerCamera["invert"], /*this->*/camera.invert ); + /*this->*/camera.limit.current = uf::vector::decode( serializerCameraLimit["current"], /*this->*/camera.limit.current ); + /*this->*/camera.limit.min = uf::vector::decode( serializerCameraLimit["minima"], /*this->*/camera.limit.min ); + /*this->*/camera.limit.max = uf::vector::decode( serializerCameraLimit["maxima"], /*this->*/camera.limit.max ); } #undef this \ No newline at end of file diff --git a/ext/behaviors/player/behavior.h b/ext/behaviors/player/behavior.h index f1c6083e..22002f3a 100644 --- a/ext/behaviors/player/behavior.h +++ b/ext/behaviors/player/behavior.h @@ -27,6 +27,11 @@ namespace ext { float friction = 0.8f; float air = 1.0f; pod::Vector3f jump = {0,8,0}; + struct { + pod::Vector3f feet = {0,-1.5,0}; + pod::Vector3f floor = {0,-1,0}; + bool print = false; + } floored; } movement; struct { struct { diff --git a/ext/behaviors/raytrace/behavior.cpp b/ext/behaviors/raytrace/behavior.cpp index 8af77eaa..3c8521e3 100644 --- a/ext/behaviors/raytrace/behavior.cpp +++ b/ext/behaviors/raytrace/behavior.cpp @@ -87,11 +87,17 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) { if ( graphic.material.hasShader("ray:gen", uf::renderer::settings::pipelines::names::rt) ) { auto& shader = graphic.material.getShader("ray:gen", uf::renderer::settings::pipelines::names::rt); // + pod::Vector2ui size = metadata.renderer.size; + UF_MSG_DEBUG("Size: {}", uf::vector::toString( size )); + if ( size.x == 0 ) size.x = uf::renderer::settings::width * metadata.renderer.scale; + if ( size.y == 0 ) size.y = uf::renderer::settings::height * metadata.renderer.scale; + UF_MSG_DEBUG("Size: {}", uf::vector::toString( size )); + auto& image = shader.textures.emplace_back(); image.fromBuffers( NULL, 0, uf::renderer::enums::Format::R8G8B8A8_UNORM, - uf::renderer::settings::width * metadata.renderer.scale, uf::renderer::settings::height * metadata.renderer.scale, 1, 1, + size.x, size.y, 1, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL ); @@ -161,8 +167,9 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) { if ( shader.textures.empty() ) { auto& tex = shader.textures.emplace_back(); tex.aliasTexture( image ); - tex.sampler.descriptor.filter.min = VK_FILTER_NEAREST; - tex.sampler.descriptor.filter.mag = VK_FILTER_NEAREST; + + tex.sampler.descriptor.filter.min = metadata.renderer.filter; + tex.sampler.descriptor.filter.mag = metadata.renderer.filter; renderMode.execute = true; renderMode.metadata.limiter.execute = true; @@ -172,11 +179,14 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) { } if ( uf::renderer::states::resized ) { + pod::Vector2ui size = metadata.renderer.size; + if ( size.x == 0 ) size.x = uf::renderer::settings::width * metadata.renderer.scale; + if ( size.y == 0 ) size.y = uf::renderer::settings::height * metadata.renderer.scale; image.destroy(); image.fromBuffers( NULL, 0, uf::renderer::enums::Format::R8G8B8A8_UNORM, - uf::renderer::settings::width * metadata.renderer.scale, uf::renderer::settings::height * metadata.renderer.scale, 1, 1, + size.x, size.y, 1, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL ); @@ -207,7 +217,6 @@ void ext::RayTraceSceneBehavior::Metadata::serialize( uf::Object& self, uf::Seri } void ext::RayTraceSceneBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer& serializer ) { - UF_MSG_DEBUG("Update"); // merge vxgi settings with global settings { const auto& globalSettings = ext::config["engine"]["scenes"]["rt"]; @@ -217,8 +226,17 @@ void ext::RayTraceSceneBehavior::Metadata::deserialize( uf::Object& self, uf::Se } ); } - if ( serializer["size"].is() ) { - /*this->*/renderer.scale = serializer["size"].as(/*this->*/renderer.scale); + if ( serializer["rt"]["filter"].is() ) { + const auto mode = uf::string::lowercase( serializer["rt"]["filter"].as() ); + if ( mode == "nearest" ) /*this->*/renderer.filter = uf::renderer::enums::Filter::NEAREST; + else if ( mode == "linear" ) /*this->*/renderer.filter = uf::renderer::enums::Filter::LINEAR; + else UF_MSG_WARNING("Invalid Filter enum string specified: {}", mode); + } + + if ( serializer["rt"]["size"].is() ) { + /*this->*/renderer.scale = serializer["rt"]["size"].as(/*this->*/renderer.scale); + } else if ( ext::json::isArray( serializer["rt"]["size"] ) ) { + /*this->*/renderer.size = uf::vector::decode( serializer["rt"]["size"], /*this->*/renderer.size ); } else if ( ext::config["engine"]["ext"]["vulkan"]["framebuffer"]["size"].is() ) { /*this->*/renderer.scale = ext::config["engine"]["ext"]["vulkan"]["framebuffer"]["size"].as(/*this->*/renderer.scale); } diff --git a/ext/behaviors/raytrace/behavior.h b/ext/behaviors/raytrace/behavior.h index 296e7904..b3d98fb7 100644 --- a/ext/behaviors/raytrace/behavior.h +++ b/ext/behaviors/raytrace/behavior.h @@ -17,6 +17,8 @@ namespace ext { struct { bool bound = false; float scale = 1; + pod::Vector2ui size{}; + uf::renderer::enums::Filter::type_t filter = uf::renderer::enums::Filter::NEAREST; } renderer; struct { diff --git a/ext/gui/behavior.cpp b/ext/gui/behavior.cpp index 68d1291f..58576436 100644 --- a/ext/gui/behavior.cpp +++ b/ext/gui/behavior.cpp @@ -413,6 +413,16 @@ void ext::Gui::load( const uf::Image& image ) { } } else if ( ext::json::isArray(metadataJson["scaling"]) ) { raidou = uf::vector::decode( metadataJson["scaling"], raidou ); + #if 1 + float factor = 1; + if ( raidou.x == 0 && raidou.y != 0 ) { + factor = raidou.y; + } else if ( raidou.y == 0 && raidou.x != 0 ) { + factor = raidou.x; + } + raidou.x /= factor; + raidou.y /= factor; + #endif modified = true; } if ( modified ) { @@ -531,7 +541,11 @@ void ext::GuiBehavior::initialize( uf::Object& self ) { metadata.clicked = clicked; - if ( clicked ) this->callHook("gui:Clicked.%UID%", payload); + + if ( clicked ) { + UF_MSG_DEBUG("{} clicked", this->getName()); + this->callHook("gui:Clicked.%UID%", payload); + } this->callHook("gui:Mouse.Clicked.%UID%", payload); } ); diff --git a/ext/gui/manager/behavior.cpp b/ext/gui/manager/behavior.cpp index 58af983c..dbe7f19d 100644 --- a/ext/gui/manager/behavior.cpp +++ b/ext/gui/manager/behavior.cpp @@ -38,7 +38,7 @@ ext::gui::Size ext::gui::size = { 0, }, #if UF_ENV_DREAMCAST - .reference = { 960, 720 }, + .reference = { 640, 480 }, #else .reference = { 1920, 1080 }, #endif @@ -67,7 +67,7 @@ void ext::GuiManagerBehavior::initialize( uf::Object& self ) { ext::gui::size.current = uf::vector::decode( ext::config["window"]["size"], pod::Vector2f{} ); this->addHook( "window:Resized", [&](pod::payloads::windowResized& payload){ ext::gui::size.current = payload.window.size; - // ext::gui::size.reference = payload.window.size; + ext::gui::size.reference = payload.window.size; } ); this->addHook( "window:Mouse.Moved", [&](pod::payloads::windowMouseMoved& payload){ bool clicked = false; diff --git a/ext/main.cpp b/ext/main.cpp index 47acde89..186be593 100644 --- a/ext/main.cpp +++ b/ext/main.cpp @@ -416,7 +416,6 @@ void EXT_API ext::initialize() { uf::renderer::settings::invariant::waitOnRenderEnd = configRenderInvariantJson["wait on render end"].as( uf::renderer::settings::invariant::waitOnRenderEnd ); uf::renderer::settings::invariant::individualPipelines = configRenderInvariantJson["individual pipelines"].as( uf::renderer::settings::invariant::individualPipelines ); uf::renderer::settings::invariant::deferredMode = configRenderInvariantJson["deferred mode"].as( uf::renderer::settings::invariant::deferredMode ); - uf::renderer::settings::invariant::deferredReconstructPosition = configRenderInvariantJson["deferred reconstruct position"].as( uf::renderer::settings::invariant::deferredReconstructPosition ); uf::renderer::settings::invariant::deferredAliasOutputToSwapchain = configRenderInvariantJson["deferred alias output to swapchain"].as( uf::renderer::settings::invariant::deferredAliasOutputToSwapchain ); uf::renderer::settings::invariant::deferredSampling = configRenderInvariantJson["deferred sampling"].as( uf::renderer::settings::invariant::deferredSampling ); @@ -606,11 +605,45 @@ void EXT_API ext::initialize() { }); uf::hooks.addHook( "game:Scene.Cleanup", [&](){ - UF_MSG_DEBUG("Cleanup"); - uf::scene::unloadScene(); - uf::physics::terminate(); - uf::physics::initialize(); + + // reset physics world + { + uf::physics::terminate(); + uf::physics::initialize(); + } + // reset graph state + { + // cleanup graphic handles + for ( auto pair : uf::graph::storage.texture2Ds.map ) pair.second.destroy(); + for ( auto& t : uf::graph::storage.shadow2Ds ) t.destroy(); + for ( auto& t : uf::graph::storage.shadowCubes ) t.destroy(); + + for ( auto pair : uf::graph::storage.atlases.map ) pair.second.clear(); + for ( auto pair : uf::graph::storage.images.map ) pair.second.clear(); + for ( auto pair : uf::graph::storage.meshes.map ) pair.second.destroy(); + + // cleanup storage cache + uf::graph::storage.instances.clear(); + uf::graph::storage.instanceAddresses.clear(); + uf::graph::storage.primitives.clear(); + uf::graph::storage.drawCommands.clear(); + uf::graph::storage.meshes.clear(); + uf::graph::storage.images.clear(); + uf::graph::storage.materials.clear(); + uf::graph::storage.textures.clear(); + uf::graph::storage.samplers.clear(); + uf::graph::storage.skins.clear(); + uf::graph::storage.animations.clear(); + uf::graph::storage.atlases.clear(); + uf::graph::storage.joints.clear(); + uf::graph::storage.texture2Ds.clear(); + uf::graph::storage.entities.clear(); + uf::graph::storage.shadow2Ds.clear(); + uf::graph::storage.shadowCubes.clear(); + } + + uf::renderer::states::rebuild = true; }); uf::hooks.addHook( "system:Quit", [&](ext::json::Value& json){ if ( json["message"].is() ) { diff --git a/makefiles/win64.clang.make b/makefiles/win64.clang.make index 1bd4a23b..16f4c3f4 100644 --- a/makefiles/win64.clang.make +++ b/makefiles/win64.clang.make @@ -2,6 +2,7 @@ ARCH = win64 CDIR = CC = clang CXX = clang++ -OPTIMIZATIONS = -O3 -fstrict-aliasing # -flto +OPTIMIZATIONS = -O3 -fstrict-aliasing -flto WARNINGS = -g -Wall -Wno-pointer-arith -Wno-unused-function -Wno-unused-variable -Wno-switch -Wno-reorder-ctor -Wno-ignored-attributes -Wno-c++11-narrowing -Wno-unknown-pragmas -Wno-nullability-completeness -Wno-defaulted-function-deleted -Wno-mismatched-tags -FLAGS += -std=c++17 $(OPTIMIZATIONS) $(WARNINGS) -fcolor-diagnostics -fansi-escape-codes \ No newline at end of file +SANITIZE = -fuse-ld=lld # -fsanitize=address -fno-omit-frame-pointer +FLAGS += -std=c++17 $(OPTIMIZATIONS) $(WARNINGS) $(SANITIZE) -fcolor-diagnostics -fansi-escape-codes \ No newline at end of file diff --git a/makefiles/win64.gcc.make b/makefiles/win64.gcc.make index 88166693..b081d1d4 100644 --- a/makefiles/win64.gcc.make +++ b/makefiles/win64.gcc.make @@ -2,6 +2,6 @@ ARCH = win64 CDIR = CC = gcc CXX = g++ -OPTIMIZATIONS = -O3 -g -fstrict-aliasing -DUF_NO_EXCEPTIONS # -flto +OPTIMIZATIONS = -O3 -g -fstrict-aliasing -DUF_NO_EXCEPTIONS -march=native # -flto WARNINGS = -Wall -Wno-unknown-pragmas -Wno-unused-function -Wno-unused-variable -Wno-switch -Wno-reorder -Wno-sign-compare -Wno-unused-but-set-variable -Wno-ignored-attributes -Wno-narrowing -Wno-misleading-indentation FLAGS += -std=c++20 $(OPTIMIZATIONS) $(WARNINGS) -fdiagnostics-color=always \ No newline at end of file diff --git a/makefiles/win64.zig.make b/makefiles/win64.zig.make new file mode 100644 index 00000000..08641e92 --- /dev/null +++ b/makefiles/win64.zig.make @@ -0,0 +1,8 @@ +ARCH = win64 +CDIR = +CC = /opt/zig/zig cc +CXX = /opt/zig/zig c++ +OPTIMIZATIONS = -O3 -fstrict-aliasing #-flto +WARNINGS = -g -Wall -Wno-pointer-arith -Wno-unused-function -Wno-unused-variable -Wno-switch -Wno-reorder-ctor -Wno-ignored-attributes -Wno-c++11-narrowing -Wno-unknown-pragmas -Wno-nullability-completeness -Wno-defaulted-function-deleted -Wno-mismatched-tags +SANITIZE = #-fuse-ld=lld -fsanitize=address -fno-omit-frame-pointer +FLAGS += -std=c++17 $(OPTIMIZATIONS) $(WARNINGS) $(SANITIZE) -I./dep/zig/include/ -target x86_64-windows-gnu \ No newline at end of file diff --git a/program.sh b/program.sh index a71b47b3..741760be 100644 --- a/program.sh +++ b/program.sh @@ -6,7 +6,9 @@ ARCH=$(cat ./exe/default/arch) CC=$(cat ./exe/default/cc) RENDERER=$(cat ./exe/default/renderer) -export PATH="$(pwd)/exe/lib/${ARCH}/:$(pwd)/exe/lib/${ARCH}/${CC}/${RENDERER}/:${PATH}" +export PATH="$(pwd)/exe/lib/${ARCH}/:$(pwd)/exe/lib/${ARCH}/${CC}/:$(pwd)/exe/lib/${ARCH}/${CC}/${RENDERER}/:${PATH}" +echo PATH: ${PATH} +echo Executing ./exe/program.${ARCH}.${CC}.${RENDERER}.exe $@ ./exe/program.${ARCH}.${CC}.${RENDERER}.exe $@ tskill program