Commit for 2022.07.09 19-45-23.7z

This commit is contained in:
mrq 2022-07-09 19:45:00 -05:00
parent 967f6b768f
commit 26a933307b
71 changed files with 1237 additions and 932 deletions

View File

@ -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 .

View File

@ -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 ],

View File

@ -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
}

View File

@ -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 ],

View File

@ -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 ]
}
}
}

View File

@ -1,6 +1,6 @@
{
"assets": ["./scripts/door.lua"],
"system": {
"metadata": {
"physics": {
"type": "bounding box",
"recenter": true

View File

@ -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] } }
}
}
}

View File

@ -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]
}
}
}

View File

@ -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 ],

View File

@ -1,6 +1,6 @@
{
"assets": ["./scripts/door.lua"],
"system": {
"metadata": {
"physics": {
"mass": 0,
"inertia": [0, 0, 0],

View File

@ -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]
}
}
}

View File

@ -1,6 +1,6 @@
{
"assets": [],
"system": {
"metadata": {
"physics": {
"mass": 0,
"inertia": [0, 0, 0],

View File

@ -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] } }
}
}
}

View File

@ -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": "コマンド"
}
}
}

View File

@ -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
}
}
}

View File

@ -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
}
}
}

View File

@ -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" } }
}
}
}
}

View File

@ -1,6 +1,6 @@
{
"assets": [ "./scripts/lift.lua" ],
"system": {
"metadata": {
"physics": {
"type": "bounding box",
"recenter": true,

View File

@ -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 },

View File

@ -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
}
}
}
}

View File

@ -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);

View File

@ -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

View File

@ -1,7 +1,7 @@
{
"engine": {
"scenes": {
"start": "SS2",
"start": "SM64",
"meshes": { "interleaved": false },
"matrix": { "reverseInfinite": false },
"lights": { "enabled": false,

View File

@ -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() {

View File

@ -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;
}
}

View File

@ -61,8 +61,6 @@ namespace pod {
// Local storage, used for save/load
struct Storage {
uf::stl::KeyMap<pod::Instance> instances;
uf::stl::KeyMap<pod::Instance::Addresses> instanceAddresses;
uf::stl::KeyMap<uf::stl::vector<pod::Primitive>> primitives;

View File

@ -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;

View File

@ -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 );

View File

@ -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;

View File

@ -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 <type_traits>
#define TYPE_SANITIZE(T) std::remove_cv_t<std::remove_reference_t<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() {\

View File

@ -3,12 +3,7 @@
#if UF_USE_FMT
#if UF_ENV_DREAMCAST
#define FMT_HEADER_ONLY
// #include <fmt-1/format.h>
// #include <fmt-3/format.h>
// #include <fmt-8/format.h>
#include <fmt-7/format.h>
// #include <fmt-7/core.h>
#else
// #include <fmt/core.h>
#endif

View File

@ -139,8 +139,11 @@ inline uf::simd::value<float> /*UF_API*/ uf::simd::sqrt( uf::simd::value<float>
}
inline float /*UF_API*/ uf::simd::dot( uf::simd::value<float> x, uf::simd::value<float> y ) {
#if SSE_INSTR_SET >= 5
float res;
__m128 result = _mm_dp_ps(x, y, 0xFF);
return uf::simd::vector<float,4>( result )[0];
_mm_store_ss(&res, result);
return res;
// return uf::simd::vector<float,4>( 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<float> x, uf::simd::value
inline uf::simd::value<int32_t> /*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<int32_t>( f[0], f[1], f[2], f[3] );
@ -170,12 +173,12 @@ inline uf::simd::value<int32_t> /*UF_API*/ uf::simd::load( const int32_t* f ) {
inline void /*UF_API*/ uf::simd::store( uf::simd::value<int32_t> 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<int32_t> x, uf::simd::v
inline uf::simd::value<uint32_t> /*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<uint32_t>( f[0], f[1], f[2], f[3] );
@ -261,12 +264,12 @@ inline uf::simd::value<uint32_t> /*UF_API*/ uf::simd::load( const uint32_t* f )
inline void /*UF_API*/ uf::simd::store( uf::simd::value<uint32_t> 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

View File

@ -15,8 +15,10 @@ namespace uf {
uf::stl::unordered_map<Key, size_t> indices;
T& operator[]( const Key& key );
void reserve( size_t i );
uf::stl::vector<T> flatten() const;
void clear();
};
}
}
@ -38,6 +40,13 @@ void uf::stl::KeyMap<T,Key>::reserve( size_t i ) {
map.reserve(i);
}
template<typename T, typename Key>
void uf::stl::KeyMap<T,Key>::clear() {
keys.clear();
indices.clear();
map.clear();
}
template<typename T, typename Key>
uf::stl::vector<T> uf::stl::KeyMap<T,Key>::flatten() const {
uf::stl::vector<T> res; res.reserve(keys.size());

View File

@ -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& );

Binary file not shown.

View File

@ -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<bool>() ) UF_MSG_INFO("{}", uf::graph::stats( asset ));
if ( asset.metadata["debug"]["print tree"].as<bool>() ) UF_MSG_INFO("{}", uf::graph::print( asset ));
if ( asset.metadata["debug"]["print"]["stats"].as<bool>() ) UF_MSG_INFO("{}", uf::graph::stats( asset ));
if ( asset.metadata["debug"]["print"]["tree"].as<bool>() ) UF_MSG_INFO("{}", uf::graph::print( asset ));
#endif
if ( !asset.metadata["debug"]["no cleanup"].as<bool>() ) uf::graph::cleanup( asset );
} break;

View File

@ -259,6 +259,44 @@ namespace {
mesh.updateDescriptor();
#if 0
// swap winding order
if ( graph.metadata["decode"]["invert winding order"].as<bool>() ) {
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<uf::stl::string>();
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);

View File

@ -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<pod::Graph&>(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);

View File

@ -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<pod::SceneTextures>();
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
auto& graphic = entity.getComponent<uf::renderer::Graphic>();
graphic.initialize();
graphic.initializeMesh( mesh );
auto& scene = uf::scene::getCurrentScene();
auto& sceneTextures = scene.getComponent<pod::SceneTextures>();
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
auto& graphic = entity.getComponent<uf::renderer::Graphic>();
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<bool>()) ? uf::renderer::enums::CullMode::BACK : uf::renderer::enums::CullMode::FRONT;
if ( graph.metadata["cull mode"].is<uf::stl::string>() ) {
const auto mode = graph.metadata["cull mode"].as<uf::stl::string>();
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<bool>()) ? 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<uf::stl::string>() ) {
const auto mode = uf::string::lowercase( tag["renderer"]["front face"].as<uf::stl::string>() );
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<uf::stl::string>() ) {
const auto mode = uf::string::lowercase( tag["renderer"]["cull mode"].as<uf::stl::string>() );
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<pod::SceneTextures>();
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<uf::stl::string>("/graph/base.vert.spv"); {
std::pair<bool, uf::stl::string> settings[] = {
{ graph.metadata["flags"]["SKINNED"].as<bool>(), "skinned.vert" },
{ !graph.metadata["flags"]["SEPARATE"].as<bool>(), "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>("");
uf::stl::string fragmentShaderFilename = graph.metadata["shaders"]["fragment"].as<uf::stl::string>("/graph/base.frag.spv"); {
std::pair<bool, uf::stl::string> 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<pod::SceneTextures>();
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<uf::stl::string>("/graph/base.vert.spv"); {
std::pair<bool, uf::stl::string> settings[] = {
{ graph.metadata["flags"]["SKINNED"].as<bool>(), "skinned.vert" },
{ !graph.metadata["flags"]["SEPARATE"].as<bool>(), "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>("");
uf::stl::string fragmentShaderFilename = graph.metadata["shaders"]["fragment"].as<uf::stl::string>("/graph/base.frag.spv"); {
std::pair<bool, uf::stl::string> 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<uf::stl::string>("/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<uf::stl::string>("/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<uf::stl::string>("/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<uf::stl::string>("/graph/base.vert.spv");
uf::stl::string geometryShaderFilename = graph.metadata["shaders"]["geometry"].as<uf::stl::string>("/graph/voxelize.geom.spv");
uf::stl::string fragmentShaderFilename = graph.metadata["shaders"]["fragment"].as<uf::stl::string>("/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<bool>() ) {
{
graphic.material.metadata.autoInitializeUniformBuffers = false;
uf::stl::string fragmentShaderFilename = graph.metadata["shaders"]["vertex"].as<uf::stl::string>("/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<uf::stl::string>("/graph/base.vert.spv");
uf::stl::string geometryShaderFilename = graph.metadata["shaders"]["geometry"].as<uf::stl::string>("/graph/voxelize.geom.spv");
uf::stl::string fragmentShaderFilename = graph.metadata["shaders"]["fragment"].as<uf::stl::string>("/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<bool>() ) {
{
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<size_t>(512);
size_t maxCubemaps = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["cube"].as<size_t>(128);
size_t maxTextures3D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["3D"].as<size_t>(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<size_t>(512);
size_t maxCubemaps = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["cube"].as<size_t>(128);
size_t maxTextures3D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["3D"].as<size_t>(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<uf::Serializer>();
if ( !sceneMetadataJson["system"]["config"]["engine"]["scenes"]["lights"]["useLightmaps"].as<bool>(true) ) {
graph.metadata["lightmap"] = false;
graph.metadata["lights"]["lightmap"] = false;
graph.metadata["baking"]["enabled"] = false;
}
if ( graph.metadata["lightmap"].is<uf::stl::string>() && graph.metadata["lightmap"].as<uf::stl::string>() == "auto" ) {
if ( graph.metadata["lights"]["lightmap"].is<uf::stl::string>() && graph.metadata["lights"]["lightmap"].as<uf::stl::string>() == "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<bool>() ) for ( auto& pair : filenames ) {
if ( graph.metadata["lights"]["lightmap"].as<bool>() ) 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<uf::stl::string>() == key;
// auto filter = graph.metadata["filter"].as<uf::stl::string>() == "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<uf::stl::string>() ) {
const auto mode = uf::string::lowercase( tag["renderer"]["filter"].as<uf::stl::string>("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<uf::stl::string>() == "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<uf::stl::string>() ) {
const auto mode = uf::string::lowercase( tag["material"]["modeAlpha"].as<uf::stl::string>() );
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<bool>() ) for ( auto& name : graph.meshes ) UF_MSG_DEBUG("Mesh: {}", name);
if ( graph.metadata["debug"]["print"]["materials"].as<bool>() ) for ( auto& name : graph.materials ) UF_MSG_DEBUG("Material: {}", name);
if ( graph.metadata["debug"]["print"]["textures"].as<bool>() ) 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<bool>() && graph.metadata["lights"]["disable if lightmapped"].as<bool>(true) ) if ( graph.lights.count(node.name) > 0 ) return;
if ( graph.metadata["lights"]["lightmapped"].as<bool>() && graph.metadata["lights"]["disable if lightmapped"].as<bool>(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<bool>() ) return;
if ( graph.metadata["baking"]["enabled"].as<bool>(false) && !tag["bake"].as<bool>(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<bool>() && !(metadataLight["shadows"].as<bool>() || metadataLight["dynamic"].as<bool>())) ) {
// {
bool should = false;
if ( !graph.metadata["lights"]["lightmapped"].as<bool>() ) {
should = true;
} else if ( metadataLight["shadows"].as<bool>() || metadataLight["dynamic"].as<bool>() ) {
should = true;
}
if ( should ) {
auto& metadataJson = entity.getComponent<uf::Serializer>();
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<uf::stl::string>();
@ -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;

View File

@ -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<pod::PhysicsState>();
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<uf::stl::string>() == "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<uf::stl::string>() == "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<bool>(true) ) collider.transform.position = (center - transform.position);
if ( metadataJson["physics"]["recenter"].as<bool>(true) ) collider.transform.position = (center - transform.position);
uf::physics::impl::create( *this, corner );
} else if ( metadataJson["system"]["physics"]["type"].as<uf::stl::string>() == "capsule" ) {
float radius = metadataJson["system"]["physics"]["radius"].as<float>();
float height = metadataJson["system"]["physics"]["height"].as<float>();
} else if ( metadataJson["physics"]["type"].as<uf::stl::string>() == "capsule" ) {
float radius = metadataJson["physics"]["radius"].as<float>();
float height = metadataJson["physics"]["height"].as<float>();
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<uf::ObjectBehavior::Metadata>();
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<uf::Audio>() ) {

View File

@ -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<float>();
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<float>();
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<float>();
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<float>();
*/
}
}

View File

@ -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<bool>() ) {
if ( graph.metadata["debug"]["print"]["image"].as<bool>() ) {
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<bool>() ) {
if ( graph.metadata["debug"]["print"]["sampler"].as<bool>() ) {
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<bool>() ) {
if ( graph.metadata["debug"]["print"]["texture"].as<bool>() ) {
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<bool>() ) {
if ( graph.metadata["debug"]["print"]["material"].as<bool>() ) {
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<uf::stl::string>(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<uf::stl::string>(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<uf::stl::string>() == "auto" ) {
graph.metadata["cull mode"] = "none";
if ( m.doubleSided && graph.metadata["renderer"]["cull mode"].as<uf::stl::string>() == "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<bool>() ) {
if ( graph.metadata["debug"]["print"]["mesh"].as<bool>() ) {
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<bool>() ) {
if ( graph.metadata["debug"]["print"]["skin"].as<bool>() ) {
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<bool>() ) {
if ( graph.metadata["debug"]["print"]["animation"].as<bool>() ) {
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<bool>() ) {
if ( graph.metadata["debug"]["print"]["light"].as<bool>() ) {
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;
}

View File

@ -1,7 +1,20 @@
struct {
struct {
bool should = true;
size_t corrected{};
size_t total{};
} windingOrder;
} sanitizer;
if ( graph.metadata["sanitizer"]["winding order"].as<bool>(true) ) {
sanitizer.windingOrder.should = true;
}
uf::stl::vector<uf::Meshlet_T<UF_GRAPH_MESH_FORMAT>> 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<bool>()) ){
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<uint32_t>(accessor.count) );
meshlet.indices.reserve( static_cast<uint32_t>(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<pod::DrawCommand>();
mesh.bind<UF_GRAPH_MESH_FORMAT>(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();
}

View File

@ -1,214 +0,0 @@
uf::stl::vector<uf::Meshlet_T<UF_GRAPH_MESH_FORMAT>> 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<float> floats;
uf::stl::vector<uint8_t> int8s;
uf::stl::vector<uint16_t> int16s;
uf::stl::vector<uint32_t> int32s;
};
uf::stl::unordered_map<uf::stl::string, Attribute> 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<bool>()) ){
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<const uint8_t*>(&(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<const uint16_t*>(&(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<const uint32_t*>(&(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<const float*>(&(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<bool>()) ){
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<uint32_t>(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<const uint32_t*>( pointer );
COPY_INDICES()
break;
}
case TINYGLTF_PARAMETER_TYPE_UNSIGNED_SHORT: {
auto* buf = static_cast<const uint16_t*>( pointer );
COPY_INDICES()
break;
}
case TINYGLTF_PARAMETER_TYPE_UNSIGNED_BYTE: {
auto* buf = static_cast<const uint8_t*>( 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<pod::DrawCommand>();
mesh.bind<UF_GRAPH_MESH_FORMAT>(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();
}

View File

@ -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];

View File

@ -59,7 +59,7 @@ void ext::lua::onInitialization( const std::function<void()>& 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 );

View File

@ -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<uf::Object>();
static uf::Object null;
@ -123,7 +123,7 @@ namespace binds {
uf::Object& getParent( uf::Object& self ){
return self.getParent().as<uf::Object>();
}
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 );

View File

@ -3,7 +3,7 @@
#include <uf/utils/math/quaternion.h>
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 ) {

View File

@ -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 ) {

View File

@ -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<uint8_t*>(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<uint8_t*>(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<uint8_t*>(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<uint8_t*>(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<uint8_t*>(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<uint8_t*>(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));
}

View File

@ -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;

View File

@ -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;

View File

@ -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();

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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

View File

@ -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<uf::stl::string>() != "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<void(ext::json::Value&, const ext::json::Value&)> update = [&]( ext::json::Value& a, const ext::json::Value& b ) {
// doesn't exist, just copy it

View File

@ -203,17 +203,26 @@ void ext::PlayerBehavior::tick( uf::Object& self ) {
stats.noclipped = metadata.system.noclipped;
stats.floored = stats.noclipped;
auto& collider = this->getComponent<pod::PhysicsState>();
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<uf::stl::string>();
/*this->*/system.control = serializerSystem["control"].as<bool>(true);
/*this->*/system.crouching = serializerSystem["crouching"].as<bool>();
/*this->*/system.noclipped = serializerSystem["noclipped"].as<bool>();
/*this->*/movement.friction = serializerSystemPhysics["friction"].as<float>();
/*this->*/movement.rotate = serializerSystemPhysicsMovement["rotate"].as<float>();
/*this->*/movement.move = serializerSystemPhysicsMovement["move"].as<float>();
/*this->*/movement.run = serializerSystemPhysicsMovement["run"].as<float>();
/*this->*/movement.walk = serializerSystemPhysicsMovement["walk"].as<float>();
/*this->*/movement.air = serializerSystemPhysicsMovement["air"].as<float>();
/*this->*/movement.jump = uf::vector::decode(serializerSystemPhysicsMovement["jump"], pod::Vector3f{});
/*this->*/movement.crouch = serializerSystemPhysicsMovement["crouch"].as<float>();
// /*this->*/movement.look = serializerSystemPhysicsMovement["look"].as<float>(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<float>(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<float>();
/*this->*/camera.invert = uf::vector::decode( serializerCamera["invert"], pod::Vector3t<bool>{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

View File

@ -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 {

View File

@ -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<float>() ) {
/*this->*/renderer.scale = serializer["size"].as(/*this->*/renderer.scale);
if ( serializer["rt"]["filter"].is<uf::stl::string>() ) {
const auto mode = uf::string::lowercase( serializer["rt"]["filter"].as<uf::stl::string>() );
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<float>() ) {
/*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<float>() ) {
/*this->*/renderer.scale = ext::config["engine"]["ext"]["vulkan"]["framebuffer"]["size"].as(/*this->*/renderer.scale);
}

View File

@ -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 {

View File

@ -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);
} );

View File

@ -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;

View File

@ -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<uf::stl::string>() ) {

View File

@ -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
SANITIZE = -fuse-ld=lld # -fsanitize=address -fno-omit-frame-pointer
FLAGS += -std=c++17 $(OPTIMIZATIONS) $(WARNINGS) $(SANITIZE) -fcolor-diagnostics -fansi-escape-codes

View File

@ -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

8
makefiles/win64.zig.make Normal file
View File

@ -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

View File

@ -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