Commit for 2022.07.18 00-44-24.7z

This commit is contained in:
mrq 2022-07-18 00:44:00 -05:00
parent 60e64ccb0d
commit 0c76838ea1
66 changed files with 511 additions and 778 deletions

View File

@ -1,7 +1,7 @@
{
"engine": {
"scenes": {
"start": "SH2_McDonalds",
"start": "SS2",
"matrix": { "reverseInfinite": true },
"meshes": { "interleaved": false },
"lights": { "enabled": true,
@ -33,15 +33,15 @@
"traceStartOffsetFactor": 2,
"shadows": 0,
"extents": {
"min": [ -8, -1, -8 ],
"min": [ -8, -4, -8 ],
"max": [ 8, 4, 8 ]
}
},
"rt": {
// "size": [ 1280, 720 ],
"filter": "nearest",
"defaultRayBounds": [ 0.0001, 256.0 ],
"alphaTestOffset": 0.001,
"defaultRayBounds": [ 0.5, 256.0 ],
"alphaTestOffset": 0.01,
"samples": 1,
"paths": 2,
"frameAccumulationMinimum": 0
@ -109,7 +109,7 @@
"vxgi": true,
"culling": true,
"bloom": false,
"rt": false
"rt": true
},
"formats": {
"depth": "D32_SFLOAT",
@ -250,7 +250,7 @@
"count": 4
},
"volumes": {
"sfx": 0.25,
"sfx": 0.35,
"bgm": 0.15,
"voice": 1.0
},

View File

@ -51,6 +51,7 @@
},
"renderer": {
"flip textures": false,
"invert": false,
"skinned": true
},
"animations": {

View File

@ -22,10 +22,14 @@ if metadata["normal"] ~= nil then
end
local starting = Quaternion(transform.orientation)
local ending = transform.orientation:multiply(Quaternion.axisAngle( Vector3f(0,1,0), metadata["angle"] ))
-- local soundEmitter = ent:loadChild("/sound.json",true)
local soundEmitter = ent
local playSound = function( key, loop )
if not loop then loop = false end
local url = "/door/" .. key .. ".ogg"
ent:queueHook("sound:Emit.%UID%", {
soundEmitter:queueHook("sound:Emit.%UID%", {
filename = string.resolveURI(url, metadata["system"]["root"]),
spatial = true,
streamed = true,
@ -35,13 +39,13 @@ local playSound = function( key, loop )
end
local stopSound = function( key )
local url = "/door/" .. key .. ".ogg"
ent:queueHook("sound:Stop.%UID%", {
soundEmitter:queueHook("sound:Stop.%UID%", {
filename = string.resolveURI(url, metadata["system"]["root"])
}, 0)
end
local playSoundscape = function( key )
local url = "/soundscape/" .. key .. ".ogg"
ent:queueHook("sound:Emit.%UID%", {
soundEmitter:queueHook("sound:Emit.%UID%", {
filename = string.resolveURI(url, metadata["system"]["root"]),
spatial = false,
volume = "sfx",
@ -51,7 +55,7 @@ local playSoundscape = function( key )
end
local stopSoundscape = function( key )
local url = "/soundscape/" .. key .. ".ogg"
ent:queueHook("sound:Stop.%UID%", {
soundEmitter:queueHook("sound:Stop.%UID%", {
filename = string.resolveURI(url, metadata["system"]["root"])
}, 0)
end
@ -89,7 +93,7 @@ ent:addHook( "entity:Use.%UID%", function( payload )
-- if timer:elapsed() <= 0.125 then return end
-- timer:reset()
print("Processing use: " .. payload["uid"] .. " | " .. payload["depth"] )
print("Processing use: " .. ent:name() .. " | " .. payload["depth"] )
if state == 0 or state == 3 then
state = 1

View File

@ -74,15 +74,30 @@ ent:bind( "tick", function(self)
flattenedTransform.forward = ( transform.forward + Vector3f( 0, cameraTransform.forward.y, 0 ) ):normalize();
-- toggle flashlight
light.transform.position = flattenedTransform.position + flattenedTransform.forward * 2
if light.enabled then
local center = flattenedTransform.position
local direction = flattenedTransform.forward * 4
local offset = 0.05
local _, depth = physicsState:rayCast( center, direction )
if depth >= 0.5 then
depth = 0.5
elseif depth < 0 then
depth = 0.5
end
light.transform.position = center + direction * (depth - offset)
end
if timers.flashlight:elapsed() > 0.5 and inputs.key("F") then
timers.flashlight:reset()
local metadata = { light = { power = light.power } }
if light.entity:getComponent("Metadata")["light"]["power"] ~= light.power then
metadata["light"]["power"] = light.power
light.enabled = true
else
metadata["light"]["power"] = 0
light.enabled = false
end
light.entity:setComponent("Metadata", metadata)
@ -190,8 +205,8 @@ ent:addHook( "entity:Use.%UID%", function( payload )
if payload.user ~= ent:uid() then return end
local validUse = false
if heldObject.uid == 0 then
if heldObject.uid == 0 and payload.depth > 0 then
local prop = entities.get( payload.uid )
local propMetadata = prop:getComponent("Metadata")
if propMetadata["holdable"] then
@ -202,6 +217,8 @@ ent:addHook( "entity:Use.%UID%", function( payload )
heldObject.distance = offset:norm()
prop:getComponent("PhysicsState"):enableGravity(false)
else
validUse = not string.matched( prop:name(), "/^worldspawn/" )
end
elseif heldObject.uid ~= 0 then
validUse = true
@ -213,9 +230,6 @@ ent:addHook( "entity:Use.%UID%", function( payload )
heldObject.uid = 0
heldObject.distance = 0
heldObject.momentum = Vector3f(0,0,0)
elseif payload.uid ~= 0 then
local hit = entities.get( heldObject.uid )
validUse = not string.matched( hit:name(), "/^worldspawn/" )
end
if validUse then

View File

@ -0,0 +1,20 @@
{
"type": "Object",
"name": "Sound Emitter",
"ignore": false,
"assets": [],
"behaviors": [ "SoundEmitterBehavior" ],
"transform": { "reference": true },
"system": {
"hot reload": { "enabled": true }
},
"metadata": {
"audio": {
"spatial": true,
"loop": false,
"volume": 1,
"rolloffFactor": 0.5,
"epsilon": 0.5
}
}
}

View File

@ -1,34 +0,0 @@
{
"type": "Object",
"name": "Sound Emitter",
"ignore": false,
"assets": [
],
"behaviors": [
"SoundEmitterBehavior"
],
"transform": {
"reference": true
},
"system": {
"hot reload": {
"enabled": true
},
"defaults": {
"render": true,
"asset load": true
},
"load": {
"ignore": true
}
},
"metadata": {
"audio": {
"spatial": true,
"loop": false,
"volume": 1,
"rolloffFactor": 0.5,
"epsilon": 0.5
}
}
}

View File

@ -1,16 +0,0 @@
{
"name": "Craeture",
"behaviors": [ "CraetureBehavior" ],
"assets": [
"./textures/craeture.jpg"
],
"transform": {
"position": [19.9875, 1.54269, -2.97276],
"scale": [1.5, 2, 1.5]
},
"metadata": {
"model": {
"cull mode": "none"
}
}
}

View File

@ -1,32 +0,0 @@
{
"name": "Gui: Loading",
"type": "Object",
"behaviors": [
// "GuiBehavior"
],
"assets": [
{ "filename": "./sh2_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

@ -1,24 +0,0 @@
{
"name": "Marker",
"type": "Gui",
"ignore": false,
"transform": {
"position": [ 0, 0, 0 ],
"rotation": {
"axis": [ 1, 0, 0 ],
"angle": 0
},
"scale": [ 1, 1, 1 ]
},
"metadata": {
"uv": [ 0, 0, 1, 1 ],
"color": [ 1, 1, 1, 0.8 ],
"location": "",
"scaling": [ 1, 1 ],
"world": true,
"gui layer": false
},
"assets": [
"https://cdn..xyz//unity/Android/sprite/sprite_magiccircle_in2.png"
]
}

View File

@ -1,6 +0,0 @@
{
"import": "/player.json",
"assets": [],
"metadata": {
}
}

View File

@ -1,32 +0,0 @@
{
"import": "/light.json",
"ignore": false,
"assets": [
],
"transform": {
"track": "parent",
"position": [ 0, 1.7, 0 ]
},
"system": {
"hot reload": {
"enabled": true
}
},
"metadata": {
"light": {
"type": "point",
"color": [1, 1, 1],
"power": 15,
"fov": 90,
"bias": {
"constant": 1.25,
"slope": 1.75,
"shader": 0.000005 //0.000000005
},
"radius": [0.001, 0],
"resolution": 1024,
"shadows": false,
"static": false
}
}
}

View File

@ -1,89 +0,0 @@
{
"import": "/scene.json",
"assets": [
"./audio/soundscape/ambience.ogg",
"./sh2_mcdonalds.json"
// "./loading.json"
// "./static.json"
],
"system": {
"hot reload": {
"enabled": true
},
"renderer": {
"shader": {
"mode": 1,
"scalar": 16,
"parameters": [ 0, 0, 0, "time" ]
},
"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 ],
"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.5, 1024.0 ],
"alphaTestOffset": 1.125,
"samples": 1,
"paths": 1,
"frameAccumulationMinimum": 0
}
}
}

View File

@ -1,22 +0,0 @@
local scene = entities.currentScene()
local controller = entities.controller()
local timer = Timer.new()
if not timer:running() then
timer:start();
end
local transform = ent:getComponent("Transform")
-- on tick
ent:bind( "tick", function(self)
local offset = Vector3f(0,0,0)
if window.keyPressed("J") then offset.x = offset.x - time.delta() end
if window.keyPressed("L") then offset.x = offset.x + time.delta() end
if window.keyPressed("N") then offset.y = offset.y - time.delta() end
if window.keyPressed("M") then offset.y = offset.y + time.delta() end
if window.keyPressed("I") then offset.z = offset.z - time.delta() end
if window.keyPressed("K") then offset.z = offset.z + time.delta() end
if offset:magnitude() > 0.0001 then
transform.position = transform.position + offset
end
end )

View File

@ -1,90 +0,0 @@
local scene = entities.currentScene()
local controller = entities.controller()
local timer = Timer.new()
if not timer:running() then
timer:start();
end
-- release control
--[[
hooks.call("window:Mouse.CursorVisibility", { state = true })
hooks.call("window:Mouse.Lock", {});
]]
-- on tick
ent:bind( "tick", function(self)
-- update static effect
local metadatas = {
ent = ent:getComponent("Metadata"),
scene = scene:getComponent("Metadata")
}
local transforms = {
ent = ent:getComponent("Transform"),
controller = controller:getComponent("Transform")
}
local distanceSquared = transforms.controller.position:distance( transforms.ent.position )
distanceSquared = distanceSquared * distanceSquared
if type(metadatas.ent["static"]["scale"]) == "number" then
distanceSquared = distanceSquared * metadatas.ent["static"]["scale"]
end
local lo = type(metadatas.ent["static"]["range"][1]) == "number" and metadatas.ent["static"]["range"][1] or 0.1
local hi = type(metadatas.ent["static"]["range"][2]) == "number" and metadatas.ent["static"]["range"][2] or 0.5
local staticBlend = distanceSquared > 1 and 1.0 / distanceSquared or 1.0
staticBlend = math.clamp( staticBlend, lo, hi )
local flicker = type(metadatas.ent["static"]["flicker"]) == "number" and metadatas.ent["static"]["flicker"] or 0.001
local pieces = type(metadatas.ent["static"]["pieces"]) == "number" and metadatas.ent["static"]["pieces"] or 1000
local payload = {
mode = 2,
parameters = {
[1] = flicker,
[2] = pieces,
[3] = staticBlend,
[4] = "time"
}
}
scene:callHook("shader:Update.%UID%", payload)
end )
--[[
local hud = ent:loadChild("/hud.json", true)
hud:bind( "tick", function(self)
-- update distance HUD element
if timer:elapsed() <= 0.0125 then return end
timer:reset()
local metadata = self:getComponent("Metadata")
local transforms = {
controller = controller:getComponent("Transform"),
source = ent:getComponent("Transform")
}
local distance = transforms.controller.position:distance( transforms.source.position )
--distance = string.si( distance, "m" )
local maximum = 40
local value = math.floor(distance/maximum * 100)
if value >= 100 then value = 100 end
distance = "Sanity: " .. value .. "%"
--distance = math.floor((15-distance)/15 * 100) .. "%"
if metadata["text settings"]["string"] ~= distance then
self:callHook( "gui:UpdateString.%UID%", {
string = distance
} )
end
end )
]]
--[[
local marker = ent:loadChild("./marker.json", true)
marker:bind( "tick", function(self)
local transform = marker:getComponent("Transform")
local parentTransform = ent:getComponent("Transform")
local controllerTransform = controller:getComponent("Transform")
local controllerCamera = controller:getComponent("Camera")
local controllerCameraTransform = controllerCamera:getTransform()
transform.position = parentTransform.position + Vector3f(0,3,0)
transform.orientation = Quaternion.lookAt( transform.position - controllerTransform.position, Vector3f(0,1,0) )
-- transform.orientation = transform.orientation:normalize()
-- transform.model = controllerCamera:getProjection() * controllerCamera:getView() * Matrix4f.translate( transform.position ) * transform.orientation:matrix()
end )
]]

View File

@ -1,11 +0,0 @@
local scene = entities.currentScene()
local controller = entities.controller()
local transform = ent:getComponent("Transform")
local controllerTransform = controller:getComponent("Transform")
local offset = Vector3f(0,1,0) -- transform.position
io.print("TRACKING PLAYER")
-- on tick
ent:bind( "tick", function(self)
transform.position = offset + controllerTransform.position
end )

View File

@ -1,70 +0,0 @@
{
"import": "/model.json",
"assets": [
// { "filename": "./static.json", "delay": 8 },
// { "filename": "./models/sh_mcd.glb" }
// { "filename": "./models/sh_mcd/graph.json" }
// { "filename": "./models/mcdonalds.glb" }
{ "filename": "./models/mcdonalds/graph.json" }
// { "filename": "./models/mini_mcd.glb" }
// { "filename": "./models/mini_mcd/graph.json" }
// { "filename": "/cornell/cornell.glb" }
// { "filename": "/cornell/cornell/graph.json" }
// { "filename": "/burger.json" }
],
"metadata": {
"model": {
"baking": {
"enabled": true,
"resolution": 2048,
"settings": {
"useInputMeshUvs": false
}
},
"renderer": {
"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 }
},
"info_player_spawn": { "action": "attach", "filename": "./player.json", "preserve orientation": true },
"func_door_rotating_5409": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
"func_door_rotating_5487": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle": 1.570795, "normal": [ 1,0,0] } } },
"func_door_rotating_5495": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle": 1.570795, "normal": [ 1,0,0] } } },
"func_door_rotating_5656": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle": 1.570795, "normal": [ 1,0,0] } } },
"func_door_rotating_5664": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
"func_door_rotating_5689": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
"func_door_rotating_5698": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
"func_door_rotating_5712": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
"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/": { "action": "load", "payload": { "import": "/prop.json" } },
"/^prop_physics/": { "action": "load", "payload": { "import": "/prop.json" } },
"/^func_door_/": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
"func_door_rotating_5568": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
"func_door_rotating_5576": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
"func_door_rotating_5584": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
"tools/toolsnodraw": { "material": { "base": [0, 0, 0, 0] } },
"materials/models/props_wasteland/prison_lamp001a": { "material": { "emissive": [0, 0, 0, 0] } },
"/alpha_mtl/": { "material": { "modeAlpha": "blend" } }
}
}
}
}

View File

@ -1,34 +0,0 @@
{
"type": "Object",
"name": "Sound Emitter",
"ignore": false,
"assets": [
],
"behaviors": [
"SoundEmitterBehavior"
],
"transform": {
"reference": true
},
"system": {
"hot reload": {
"enabled": true
},
"defaults": {
"render": true,
"asset load": true
},
"load": {
"ignore": true
}
},
"metadata": {
"audio": {
"spatial": true,
"loop": false,
"volume": 1,
"rolloffFactor": 0.5,
"epsilon": 0.5
}
}
}

View File

@ -1,48 +0,0 @@
{
"type": "Object",
"name": "Static Emitter",
"ignore": false,
"assets": [
"/overworld/static.ogg",
"./scripts/static.lua"
],
"behaviors": [
"SoundEmitterBehavior"
],
"transform": {
"position": [ -13.4342, 2.43658, 298.797 ],
"rotation": {
"axis": [ 0, 1, 0 ],
"angle": 0
},
"scale": [ 1, 1, 1 ]
},
"system": {
"hot reload": {
"enabled": true
},
"defaults": {
"render": true,
"asset load": true
},
"load": {
"ignore": true
}
},
"metadata": {
"audio": {
"spatial": true,
"loop": true,
"streamed": false,
"volume": 1.6,
"rolloffFactor": 2
},
"static": {
"range": [ 0.0025, 1 ],
"flicker": 0.5,
"pieces": 16,
"scale": 0.4
},
"distance": false
}
}

View File

@ -1,28 +1,17 @@
{
"import": "/model.json",
"assets": [
// { "filename": "./models/gm_construct.glb" }
{ "filename": "./models/gm_construct/graph.json" }
// { "filename": "./models/rp_downtown_v2.glb" }
// { "filename": "./models/rp_downtown_v2/graph.json" }
],
"metadata": {
"model": {
"baking": {
"enabled": false
},
"renderer": {
"separate": true
},
// "renderer": { "separate": true },
"baking": { "enabled": false },
"tags": {
"/^worldspawn$/": {
// exact matches
"worldspawn": {
"physics": { "type": "mesh", "static": true },
// "grid": { "size": [2,1,2], "epsilon": 1.0, "cleanup": true, "print": true },
// "unwrap mesh": true,
"grid": { "size": [3,1,3], "epsilon": 1.0, "cleanup": true, "print": true },
"unwrap mesh": true,
"optimize mesh": { "simplify": 0 }
},
"/^worldspawn_skybox$/": { "ignore": true },
"info_player_spawn": { "action": "attach", "filename": "./player.json", "transform": { "orientation": [ 0, 1, 0, 0 ] } },
"light_environment": { "transform": { "orientation": [0,0,0,1] }, "light": {
"power": 100000,
@ -35,24 +24,17 @@
"radius": [0.95, 0],
"resolution": 1536
} },
// "/^light_[^e]/": { "ignore": true },
// "/^func/": { "ignore": true },
// "/^prop/": { "ignore": true },
// regexp matches
"/^worldspawn/": { "physics": { "type": "mesh", "static": true } },
"/^func_door_/": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
"/^prop_door_/": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
"/^prop_static/": { /*"action": "load", "payload": { "import": "/prop.json", "metadata": { "physics": { "gravity": [ 0, 0, 0 ] } } }*/ },
"/^prop_dynamic/": { /*"action": "load", "payload": { "import": "/prop.json", "metadata": { "physics": { "gravity": [ 0, 0, 0 ] } } }*/ },
"/^func_physbox/": { "action": "load", "payload": { "import": "/prop.json" } },
"/^prop_physics/": { "action": "load", "payload": { "import": "/prop.json" } },
"/^gm_construct\\/water/": { "material": {
"base": [ 0.027, 0.227, 0.259, 0.5 ],
"fRoughness": 0.3
} }
"/^tools\\/toolsnodraw/": { "material": { "base": [ 1.0, 1.0, 1.0, 0.0 ] } }
}
}
}

View File

@ -0,0 +1,21 @@
{
"import": "./base_sourceengine.json",
"assets": [
// { "filename": "./models/gm_construct.glb" }
{ "filename": "./models/gm_construct/graph.json" }
],
"metadata": {
"model": {
"tags": {
// exact matches
"worldspawn_skybox": { "ignore": true },
// regex matches
"/^gm_construct\\/water/": { "material": {
"base": [ 0.027, 0.227, 0.259, 0.5 ],
"fRoughness": 0.3
} }
}
}
}
}

View File

@ -5,7 +5,7 @@
"GuiBehavior"
],
"assets": [
{ "filename": "./gm_construct.json", "delay": 0 }
{ "filename": "./sourceengine.json", "delay": 0 }
],
"ignore": false,
"transform": {

View File

@ -0,0 +1,33 @@
{
"import": "./base_sourceengine.json",
"assets": [
// { "filename": "./models/mds_mcdonalds.glb" }
{ "filename": "./models/mds_mcdonalds/graph.json" }
],
"metadata": {
"model": {
"tags": {
// exact matches
"func_door_rotating_5473": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [1,0,0] } } },
"func_door_rotating_5509": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [1,0,0] } } },
"func_door_rotating_5568": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [1,0,0] } } },
"func_door_rotating_5584": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [1,0,0] } } },
// regex matches
// "/^prop_physics_override/": { "action": "load", "payload": { "import": "/prop.json", "metadata": { "physics": { "gravity": [ 0, 0, 0 ] } } } },
// "/^prop_physics_[^o]/": { "action": "load", "payload": { "import": "/prop.json" } },
"/^tools\\/toolsnodraw/": { "material": {
"base": [ 1.0, 1.0, 1.0, 1.0 ],
"emissive": [ 0.0, 0.0, 0.0, 0.0 ],
"fMetallic": 0.0,
"fRoughness": 0.10000000149011612,
"fOcclusion": 1.0,
"fAlphaCutoff": 0.5,
"iAlbedo": 27,
"modeAlpha": 1
} }
}
}
}
}

View File

@ -0,0 +1,23 @@
{
"import": "./base_sourceengine.json",
"assets": [
"./audio/soundscape/ambience.ogg",
// { "filename": "./models/rp_downtown_v2.glb" }
{ "filename": "./models/rp_downtown_v2/graph.json" }
],
"metadata": {
"model": {
"renderer": { "separate": true },
"tags": {
// exact matches
"worldspawn_skybox": { "ignore": true },
// regex matches
"/^light_/": { "ignore": true },
"/^func/": { "ignore": true },
"/^prop/": { "ignore": true }
}
}
}
}

View File

@ -1,8 +1,8 @@
{
"import": "/scene.json",
"assets": [
"./audio/soundscape/ambience.ogg",
"./gm_construct.json"
"./audio/soundscape/sh2_ambience.ogg",
"./sourceengine.json"
// "./loading.json"
],
"system": {
@ -28,15 +28,17 @@
"exposure": 1.0,
"gamma": 1.0,
// "ambient": [ 0, 0, 0 ],
"ambient": [ 0.05, 0.05, 0.05 ],
// "ambient": [ 0.15, 0.15, 0.15 ],
"ambient": [ 0.5, 0.5, 0.5 ],
// "ambient": [ 0.5, 0.5, 0.5 ],
// "ambient": [ 0.8, 0.8, 0.8 ],
"fog-disabled": {
"fog": {
"color": [ 0.5, 0.5, 0.5 ],
"range": [ 64, 256 ],
"step scale": 2,
"absorbtion": 0.07,
"absorbtion": 0.0125,
"density": {
"threshold": 0.35,
"multiplier": 5.0,
@ -50,6 +52,13 @@
},
"noise": {
"size": [ 32, 32, 32 ]
},
"rt": {
"defaultRayBounds": [ 0.5, 1024.0 ],
"alphaTestOffset": 0.01,
"samples": 1,
"paths": 1,
"frameAccumulationMinimum": 0
}
}
}

View File

@ -0,0 +1,60 @@
{
"import": "./base_sourceengine.json",
"assets": [
// { "filename": "./models/sh2_mcdonalds.glb" }
{ "filename": "./models/sh2_mcdonalds/graph.json" }
],
"metadata": {
"model": {
"tags": {
// exact matches
"worldspawn_sh2": {
"physics": { "type": "mesh", "static": true },
"grid": { "size": [5,1,5], "epsilon": 1.0, "cleanup": true, "print": true },
"unwrap mesh": true,
"optimize mesh": { "simplify": 0 }
},
"worldspawn_barrier": { "ignore": true },
"worldspawn_skybox": { "ignore": true },
"func_door_rotating_5473": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [1,0,0] } } },
"func_door_rotating_5509": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [1,0,0] } } },
"func_door_rotating_5568": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [1,0,0] } } },
"func_door_rotating_5584": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [1,0,0] } } },
"func_door_rotating_9120": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [0,0,1] } } },
"light_environment": { "transform": { "orientation": [0,0,0,1] }, "light": {
"color": [0.05, 0.05, 0.05],
"power": 100000,
"global": true,
"bias": {
"constant": 1.25,
"slope": 1.75,
"shader": 0.0000025
},
"radius": [0.95, 0],
"resolution": 1536
} },
// regex matches
// "/^prop_physics_[^o]/": { "action": "load", "payload": { "import": "/prop.json" } },
"/^prop_physics_override/": { "action": "load", "payload": {} },
"/^prop_physics_/": { "action": "load", "payload": {} },
"/^func_physbox/": { "action": "load", "payload": {} },
"materials/models/props_wasteland/prison_lamp001a": { "material": { "emissive": [0, 0, 0, 0] } },
"/^tools\\/toolsnodraw/": { "material": {
"base": [ 1.0, 1.0, 1.0, 1.0 ],
"emissive": [ 0.0, 0.0, 0.0, 0.0 ],
"fMetallic": 0.0,
"fRoughness": 0.10000000149011612,
"fOcclusion": 1.0,
"fAlphaCutoff": 0.5,
"iAlbedo": 27,
"modeAlpha": 1
} },
"/alpha_mtl/": { "material": { "modeAlpha": "blend" } }
}
}
}
}

View File

@ -0,0 +1,4 @@
{
"import": "./sh2_mcdonalds.json"
// "import": "./gm_construct.json"
}

View File

@ -6,7 +6,7 @@ if not timer:running() then
timer:start();
end
local metadata = ent:getComponent("Metadata")
local soundEmitter = ent:loadChild("./sound.json",true)
local soundEmitter = ent:loadChild("/sound.json",true)
local playSound = function( key )
if not loop then loop = false end
local url = "./audio/sfx/" .. key .. ".ogg"

View File

@ -20,7 +20,7 @@ local direction = 1.0 / math.abs(starting:distance(ending))
local alpha = 0
local startingSound = true
local soundEmitter = ent:loadChild("./sound.json",true)
local soundEmitter = ent:loadChild("/sound.json",true)
local playSound = function( key, loop )
if not loop then loop = false end
local url = "./audio/sfx/" .. key .. ".ogg"

View File

@ -1,34 +0,0 @@
{
"type": "Object",
"name": "Sound Emitter",
"ignore": false,
"assets": [
],
"behaviors": [
"SoundEmitterBehavior"
],
"transform": {
"reference": true
},
"system": {
"hot reload": {
"enabled": true
},
"defaults": {
"render": true,
"asset load": true
},
"load": {
"ignore": true
}
},
"metadata": {
"audio": {
"spatial": true,
"loop": false,
"volume": 1,
"rolloffFactor": 0.5,
"epsilon": 0.5
}
}
}

View File

@ -14,7 +14,7 @@ layout (constant_id = 3) const uint CASCADES = 1;
#define VXGI 0
#define RAYTRACE 1
#define BUFFER_REFERENCE 1
#define FOG 0
#define FOG 1
#define BLOOM 0
#define WHITENOISE 0
#define MAX_TEXTURES TEXTURES
@ -149,6 +149,7 @@ void trace( Ray ray, float tMin, float tMax ) {
uint cullMask = 0xFF;
payload.hit = false;
surface.position.eye.z = tMax;
traceRayEXT(tlas, rayFlags, cullMask, 0, 0, 0, ray.origin, tMin, ray.direction, tMax, 0);
}
void trace( Ray ray, float tMin ) {
@ -158,6 +159,7 @@ void trace( Ray ray, float tMin ) {
float tMax = ubo.settings.rt.defaultRayBounds.y;
payload.hit = false;
surface.position.eye.z = tMax;
traceRayEXT(tlas, rayFlags, cullMask, 0, 0, 0, ray.origin, tMin, ray.direction, tMax, 0);
}
@ -290,6 +292,8 @@ void directLighting() {
}
vec4 traceStep( Ray ray ) {
Ray fogRay = ray;
float eyeDepth = 0;
vec4 outFrag = vec4(0);
// initial condition
@ -299,38 +303,58 @@ vec4 traceStep( Ray ray ) {
if ( payload.hit ) {
setupSurface( payload );
directLighting();
outFrag = surface.fragment;
} else if ( 0 <= ubo.settings.lighting.indexSkybox && ubo.settings.lighting.indexSkybox < CUBEMAPS ) {
outFrag = texture( samplerCubemaps[ubo.settings.lighting.indexSkybox], ray.direction );
surface.fragment = texture( samplerCubemaps[ubo.settings.lighting.indexSkybox], ray.direction );
surface.fragment.a = 4096;
surface.position.eye.z /= 8;
} else {
outFrag = vec4(ubo.settings.lighting.ambient.rgb, 0);
surface.fragment = vec4(ubo.settings.lighting.ambient.rgb, 0.5);
}
#if FOG
fog( ray, surface.fragment.rgb, surface.fragment.a );
#endif
outFrag = surface.fragment;
eyeDepth = surface.position.eye.z;
}
// "transparency"
if ( payload.hit && surface.material.albedo.a < 0.999 ) {
const vec4 TRANSPARENCY_COLOR = vec4(1.0 - surface.material.albedo.a);
if ( surface.material.albedo.a < 0.001 ) outFrag = vec4(0);
RayTracePayload surfacePayload = payload;
Ray transparency;
transparency.direction = ray.direction;
transparency.origin = surface.position.world;
fogRay = transparency;
vec4 transparencyColor = vec4(1.0 - surface.material.albedo.a);
trace( transparency, ubo.settings.rt.alphaTestOffset );
if ( payload.hit ) {
setupSurface( payload );
directLighting();
transparencyColor *= surface.fragment;
} else if ( 0 <= ubo.settings.lighting.indexSkybox && ubo.settings.lighting.indexSkybox < CUBEMAPS ) {
transparencyColor *= texture( samplerCubemaps[ubo.settings.lighting.indexSkybox], ray.direction );
surface.fragment = texture( samplerCubemaps[ubo.settings.lighting.indexSkybox], ray.direction );
surface.fragment.a = 4096;
surface.position.eye.z /= 8;
}
outFrag += transparencyColor;
#if FOG
fog( transparency, surface.fragment.rgb, surface.fragment.a );
#endif
outFrag += TRANSPARENCY_COLOR * surface.fragment;
eyeDepth = surface.position.eye.z;
payload = surfacePayload;
setupSurface( payload );
}
#if FOG
{
// surface.position.eye.z = eyeDepth;
// fog( fogRay, outFrag.rgb, outFrag.a );
// fog( ray, surface.fragment.rgb, surface.fragment.a );
}
#endif
// reflection
if ( payload.hit ) {
@ -346,17 +370,17 @@ vec4 traceStep( Ray ray ) {
trace( reflection );
vec4 reflectionColor = REFLECTED_ALBEDO;
if ( payload.hit ) {
setupSurface( payload );
directLighting();
reflectionColor *= surface.fragment;
} else if ( 0 <= ubo.settings.lighting.indexSkybox && ubo.settings.lighting.indexSkybox < CUBEMAPS ) {
reflectionColor *= texture( samplerCubemaps[ubo.settings.lighting.indexSkybox], reflection.direction );
surface.fragment = texture( samplerCubemaps[ubo.settings.lighting.indexSkybox], reflection.direction );
surface.fragment.a = 4096;
}
outFrag += reflectionColor;
#if FOG
fog( reflection, surface.fragment.rgb, surface.fragment.a );
#endif
outFrag += REFLECTED_ALBEDO * surface.fragment;
payload = surfacePayload;
setupSurface( payload );

View File

@ -56,10 +56,12 @@ namespace uf {
typedef pod::Behavior::function_t value_t;
// typedef uint_fast8_t value_t;
uf::stl::vector<value_t> initialize;
uf::stl::vector<value_t> tick;
uf::stl::vector<pod::Thread::function_t> tickMT;
uf::stl::vector<value_t> render;
uf::stl::vector<value_t> destroy;
struct {
uf::stl::vector<value_t> serial;
uf::stl::vector<value_t> parallel;
} tick;
} m_graph;
public:
void initialize();

View File

@ -18,7 +18,10 @@ namespace uf {
uf::stl::unordered_map<uf::stl::string, uf::Entity*> cache;
#endif
pod::Thread::Tasks tasks;
struct {
pod::Thread::Tasks serial;
pod::Thread::Tasks parallel;
} tasks;
);
}
}

View File

@ -31,6 +31,9 @@ namespace ext {
uf::stl::string encoding = "";
};
//
ext::json::Value find( const uf::stl::string& needle, const ext::json::Value& haystack );
// cares not about breaking
void UF_API forEach( ext::json::Value& json, const std::function<void(ext::json::Value&)>& function );
void UF_API forEach( ext::json::Value& json, const std::function<void(size_t, ext::json::Value&)>& function );

View File

@ -13,7 +13,7 @@
#include <nlohmann/json.hpp>
#include <nlohmann/fifo_map.hpp>
#define UF_JSON_NLOHMANN_ORDERED 1
#define UF_JSON_NLOHMANN_ORDERED 0
#define UF_JSON_NLOHMANN_FIFO_MAP 0
namespace uf {

View File

@ -17,6 +17,10 @@ namespace ext {
extern UF_API bool validation;
extern UF_API bool defaultStageBuffers;
extern UF_API size_t viewCount;
extern UF_API size_t scratchBufferAlignment;
extern UF_API size_t scratchBufferInitialSize;
extern UF_API size_t defaultTimeout;
constexpr size_t maxViews = 6;
extern UF_API uf::stl::vector<uf::stl::string> validationFilters;
@ -44,6 +48,7 @@ namespace ext {
}
namespace pipelines {
extern UF_API bool deferred;
extern UF_API bool vsync;
extern UF_API bool hdr;
extern UF_API bool vxgi;
@ -52,6 +57,7 @@ namespace ext {
extern UF_API bool rt;
namespace names {
extern UF_API uf::stl::string deferred;
extern UF_API uf::stl::string vsync;
extern UF_API uf::stl::string hdr;
extern UF_API uf::stl::string vxgi;

View File

@ -14,7 +14,7 @@
#define VK_CHECK_RESULT(f) { VkResult res = (f); if ( res != VK_SUCCESS ) UF_EXCEPTION("{}", ext::vulkan::errorString( res )); }
#define VK_FLAGS_NONE 0
#define VK_DEFAULT_FENCE_TIMEOUT 100000000000
#define VK_DEFAULT_FENCE_TIMEOUT ext::vulkan::settings::defaultTimeout
#define VK_DEFAULT_STAGE_BUFFERS ext::vulkan::settings::defaultStageBuffers
namespace ext {

View File

@ -59,6 +59,7 @@ namespace ext {
extern UF_API size_t gpuID;
extern UF_API size_t scratchBufferAlignment;
extern UF_API size_t scratchBufferInitialSize;
extern UF_API size_t defaultTimeout;
extern UF_API uf::stl::vector<uf::stl::string> validationFilters;
extern UF_API uf::stl::vector<uf::stl::string> requestedDeviceFeatures;

View File

@ -73,7 +73,9 @@ namespace uf {
pod::Thread& UF_API fetchWorker( const uf::stl::string& name = uf::thread::workerThreadName );
pod::Thread::Tasks UF_API schedule( bool multithread, bool waits = true );
pod::Thread::Tasks UF_API schedule( const uf::stl::string& name = uf::thread::workerThreadName, bool waits = true );
void UF_API execute( pod::Thread::Tasks& tasks );
uf::stl::vector<pod::Thread*> UF_API execute( pod::Thread::Tasks& tasks );
void UF_API wait( uf::stl::vector<pod::Thread*>& );
void UF_API wait( const uf::stl::vector<pod::Thread*>& );
/* Acts on global threads */
typedef uf::stl::vector<pod::Thread*> container_t;

View File

@ -1,5 +1,6 @@
#include <uf/engine/behavior/behavior.h>
#include <uf/engine/object/object.h>
#include <uf/engine/scene/scene.h>
#include <uf/utils/serialize/serializer.h>
#include <uf/utils/thread/thread.h>
@ -30,18 +31,21 @@ void uf::Behaviors::removeBehavior( const pod::Behavior& behavior ) {
m_behaviors.erase(it);
generateGraph();
}
uf::Behaviors::Graph& uf::Behaviors::getGraph() { return m_graph; }
uf::Behaviors::Graph& uf::Behaviors::getGraph() {
// if ( m_graph.initialize.size() != m_behaviors.size() ) generateGraph(); // should never actually happen, so no need to actually check
return m_graph;
}
const uf::Behaviors::Graph& uf::Behaviors::getGraph() const { return m_graph; }
void uf::Behaviors::generateGraph() {
m_graph.initialize.clear();
m_graph.tick.clear();
m_graph.tickMT.clear();
m_graph.tick.serial.clear();
m_graph.tick.parallel.clear();
m_graph.render.clear();
m_graph.destroy.clear();
m_graph.initialize.reserve( m_behaviors.size() );
m_graph.tick.reserve( m_behaviors.size() );
m_graph.tickMT.reserve( m_behaviors.size() );
m_graph.tick.serial.reserve( m_behaviors.size() );
m_graph.tick.parallel.reserve( m_behaviors.size() );
m_graph.render.reserve( m_behaviors.size() );
m_graph.destroy.reserve( m_behaviors.size() );
@ -49,11 +53,15 @@ void uf::Behaviors::generateGraph() {
uf::Object* self = (uf::Object*) this;
for ( auto& behavior : m_behaviors ) {
m_graph.initialize.emplace_back(behavior.initialize);
#if 1
if ( behavior.traits.ticks ) {
auto& f = behavior.tick;
if ( behavior.traits.multithread ) m_graph.tickMT.emplace_back([f, self](){f(*self);});
else m_graph.tick.emplace_back(f);
if ( behavior.traits.multithread ) m_graph.tick.parallel.emplace_back(f); //m_graph.tickMT.emplace_back([f, self](){f(*self);});
else m_graph.tick.serial.emplace_back(f);
}
#else
if ( behavior.traits.ticks ) m_graph.tick.emplace_back(behavior.tick);
#endif
if ( behavior.traits.renders ) m_graph.render.emplace_back(behavior.render);
m_graph.destroy.emplace_back(behavior.destroy);
}
@ -61,11 +69,13 @@ void uf::Behaviors::generateGraph() {
// reverse order ticking (LIFO order iteration)
if ( !forwardIteration ) {
std::reverse( m_graph.initialize.begin(), m_graph.initialize.end() );
std::reverse( m_graph.tick.begin(), m_graph.tick.end() );
std::reverse( m_graph.tickMT.begin(), m_graph.tickMT.end() );
std::reverse( m_graph.tick.serial.begin(), m_graph.tick.serial.end() );
std::reverse( m_graph.tick.parallel.begin(), m_graph.tick.parallel.end() );
std::reverse( m_graph.render.begin(), m_graph.render.end() );
std::reverse( m_graph.destroy.begin(), m_graph.destroy.end() );
}
// uf::scene::invalidateGraphs();
}
#define UF_BEHAVIOR_POLYFILL UF_BEHAVIOR_POLYFILL_GRAPH
@ -86,17 +96,22 @@ void uf::Behaviors::tick() {
uf::Object& self = *((uf::Object*) this);
if ( !self.isValid() ) return;
// if ( !m_graph.tickMT.empty() ) uf::thread::queue(m_graph.tickMT);
if ( m_graph.tick.empty() ) return;
if ( m_graph.tick.serial.empty() && m_graph.tick.parallel.empty() ) return;
#if UF_GRAPH_PRINT_TRACE
UF_TIMER_MULTITRACE_START("Starting tick " << self.getName() << ": " << self.getUid());
// for ( auto& behavior : m_behaviors ) if ( behavior.traits.ticks ) UF_MSG_DEBUG( behavior.type.name() );
for ( auto& fun : m_graph.tick ) {
for ( auto& fun : m_graph.tick.serial ) {
fun(self);
UF_TIMER_MULTITRACE("");
}
for ( auto& fun : m_graph.tick.parallel ) {
fun(self);
UF_TIMER_MULTITRACE("");
}
UF_TIMER_MULTITRACE_END("Finished tick " << self.getName() << ": " << self.getUid())
#else
UF_BEHAVIOR_POLYFILL(tick)
UF_BEHAVIOR_POLYFILL(tick.serial)
UF_BEHAVIOR_POLYFILL(tick.parallel)
#endif
}
void uf::Behaviors::render() {
@ -120,8 +135,8 @@ void uf::Behaviors::destroy() {
UF_BEHAVIOR_POLYFILL(destroy)
m_behaviors.clear();
m_graph.initialize.clear();
m_graph.tick.clear();
m_graph.tickMT.clear();
m_graph.tick.serial.clear();
m_graph.tick.parallel.clear();
m_graph.render.clear();
m_graph.destroy.clear();
}

View File

@ -22,21 +22,6 @@
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, bool& breaks ) {
if ( uf::string::isRegex( key ) ) {
if ( !uf::string::matched( tagName, key ) ) return;
} else if ( tagName != key ) return;
tag = value;
breaks = true;
});
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;
@ -102,7 +87,7 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::M
graphic.descriptor.frontFace = graph.metadata["renderer"]["invert"].as<bool>(true) ? uf::renderer::enums::Face::CW : uf::renderer::enums::Face::CCW;
graphic.descriptor.cullMode = uf::renderer::enums::CullMode::BACK;
auto tag = ::findTag( entity.getName(), graph );
auto tag = ext::json::find( entity.getName(), graph.metadata["tags"] );
if ( !ext::json::isObject( tag ) ) {
tag["renderer"] = graph.metadata["renderer"];
}
@ -601,7 +586,7 @@ void uf::graph::process( pod::Graph& graph ) {
auto& texture = uf::graph::storage.texture2Ds[key];
if ( !texture.generated() ) {
auto filter = uf::renderer::enums::Filter::LINEAR;
auto tag = ::findTag( key, graph );
auto tag = ext::json::find( key, graph.metadata["tags"] );
if ( !ext::json::isObject( tag ) ) {
tag["renderer"] = graph.metadata["renderer"];
}
@ -633,6 +618,76 @@ void uf::graph::process( pod::Graph& graph ) {
if ( node.entity ) UF_DEBUG_TIMER_MULTITRACE("Processed node: {}", node.name);
}
// patch materials/textures
UF_DEBUG_TIMER_MULTITRACE("Remapping patching/textures");
for ( auto& name : graph.materials ) {
auto& material = uf::graph::storage.materials[name];
auto tag = ext::json::find( name, graph.metadata["tags"] );
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);
if ( tag["material"]["iAlbedo"].is<uf::stl::string>() ) {
auto keyName = tag["material"]["iAlbedo"].as<uf::stl::string>();
if ( uf::graph::storage.textures.map.count(keyName) > 0 ) {
auto& texture = uf::graph::storage.textures[keyName];
material.indexAlbedo = tag["material"]["iAlbedo"].as(texture.index);
}
} else {
material.indexAlbedo = tag["material"]["iAlbedo"].as(material.indexAlbedo);
}
if ( tag["material"]["iNormal"].is<uf::stl::string>() ) {
auto keyName = tag["material"]["iNormal"].as<uf::stl::string>();
if ( uf::graph::storage.textures.map.count(keyName) > 0 ) {
auto& texture = uf::graph::storage.textures[keyName];
material.indexNormal = tag["material"]["iNormal"].as(texture.index);
}
} else {
material.indexNormal = tag["material"]["iNormal"].as(material.indexNormal);
}
if ( tag["material"]["iEmissive"].is<uf::stl::string>() ) {
auto keyName = tag["material"]["iEmissive"].as<uf::stl::string>();
if ( uf::graph::storage.textures.map.count(keyName) > 0 ) {
auto& texture = uf::graph::storage.textures[keyName];
material.indexEmissive = tag["material"]["iEmissive"].as(texture.index);
}
} else {
material.indexEmissive = tag["material"]["iEmissive"].as(material.indexEmissive);
}
if ( tag["material"]["iOcclusion"].is<uf::stl::string>() ) {
auto keyName = tag["material"]["iOcclusion"].as<uf::stl::string>();
if ( uf::graph::storage.textures.map.count(keyName) > 0 ) {
auto& texture = uf::graph::storage.textures[keyName];
material.indexOcclusion = tag["material"]["iOcclusion"].as(texture.index);
}
} else {
material.indexOcclusion = tag["material"]["iOcclusion"].as(material.indexOcclusion);
}
if ( tag["material"]["iMetallicRoughness"].is<uf::stl::string>() ) {
auto keyName = tag["material"]["iMetallicRoughness"].as<uf::stl::string>();
if ( uf::graph::storage.textures.map.count(keyName) > 0 ) {
auto& texture = uf::graph::storage.textures[keyName];
material.indexMetallicRoughness = tag["material"]["iMetallicRoughness"].as(texture.index);
}
} else {
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);
}
}
}
// remap textures->images IDs
UF_DEBUG_TIMER_MULTITRACE("Remapping textures");
for ( auto& name : graph.textures ) {
@ -756,36 +811,6 @@ void uf::graph::process( pod::Graph& graph ) {
}
}
// patch materials/textures
UF_DEBUG_TIMER_MULTITRACE("Remapping patching/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"]["lights"].as<bool>() ) for ( auto& pair : graph.lights ) UF_MSG_DEBUG("Light: {}", pair.first);
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);
@ -809,6 +834,10 @@ void uf::graph::process( pod::Graph& graph ) {
size_t counts = 0;
for ( auto& name : graph.meshes ) {
if ( name == keyName ) continue;
auto tag = ext::json::find( name, graph.metadata["tags"] );
if ( ext::json::isObject( tag ) ) {
if ( tag["ignore"].as<bool>() ) continue;
}
auto& m = uf::graph::storage.meshes.map[name];
m.updateDescriptor();
@ -875,7 +904,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
ext::json::Value tag = ::findTag( node.name, graph );
ext::json::Value tag = ext::json::find( node.name, graph.metadata["tags"] );
if ( ext::json::isObject( tag ) ) {
if ( graph.metadata["baking"]["enabled"].as<bool>(false) && !tag["bake"].as<bool>(true) ) ignore = true;
if ( tag["ignore"].as<bool>() ) ignore = true;

View File

@ -13,7 +13,7 @@
#include <uf/ext/gltf/gltf.h>
UF_BEHAVIOR_ENTITY_CPP_BEGIN(uf::Object)
UF_BEHAVIOR_TRAITS_CPP(uf::ObjectBehavior, ticks = true, renders = false, multithread = false)
UF_BEHAVIOR_TRAITS_CPP(uf::ObjectBehavior, ticks = true, renders = false, multithread = false) // segfaults @ engine/src/ext/lua/lua.cpp:298 `auto result = state.safe_script_file( s.file, s.env, sol::script_pass_on_error );`
#define this (&self)
void uf::ObjectBehavior::initialize( uf::Object& self ) {
auto& scene = uf::scene::getCurrentScene();

View File

@ -13,7 +13,7 @@
#include <uf/ext/gltf/gltf.h>
UF_BEHAVIOR_REGISTER_CPP(uf::LoadingBehavior)
UF_BEHAVIOR_TRAITS_CPP(uf::LoadingBehavior, ticks = true, renders = false, multithread = false)
UF_BEHAVIOR_TRAITS_CPP(uf::LoadingBehavior, ticks = true, renders = false, multithread = true)
#define this (&self)
void uf::LoadingBehavior::initialize( uf::Object& self ) {
this->addHook( "system:Load.Finished.%UID%", [&](){

View File

@ -13,6 +13,8 @@ UF_OBJECT_REGISTER_END()
uf::Scene::Scene() UF_BEHAVIOR_ENTITY_CPP_ATTACH(uf::Scene)
#define UF_SCENE_GLOBAL_GRAPH 1
#define UF_TICK_MULTITHREAD_OVERRIDE 0
#define UF_TICK_FROM_TASKS 1
#if UF_SCENE_GLOBAL_GRAPH
namespace {
@ -59,13 +61,9 @@ void uf::Scene::invalidateGraph() {
auto& metadata = this->getComponent<uf::SceneBehavior::Metadata>();
#endif
metadata.invalidationQueued = true;
#if 1
metadata.cache.clear();
metadata.tasks.clear();
#else
metadata.cached.renderMode = NULL;
metadata.cached.controller = NULL;
#endif
metadata.tasks.serial.clear();
metadata.tasks.parallel.clear();
}
const uf::stl::vector<uf::Entity*>& uf::Scene::getGraph() {
#if !UF_SCENE_GLOBAL_GRAPH
@ -74,19 +72,54 @@ const uf::stl::vector<uf::Entity*>& uf::Scene::getGraph() {
if ( metadata.invalidationQueued ) {
metadata.invalidationQueued = false;
metadata.graph.clear();
metadata.tasks.clear();
metadata.tasks.serial.clear();
metadata.tasks.parallel.clear();
}
if ( !metadata.graph.empty() ) return metadata.graph;
metadata.tasks.serial = uf::thread::schedule(false);
metadata.tasks.parallel = uf::thread::schedule(true, false);
this->process([&]( uf::Entity* entity ) {
if ( !entity->hasComponent<uf::ObjectBehavior::Metadata>() ) return;
auto& eMetadata = entity->getComponent<uf::ObjectBehavior::Metadata>();
if ( !eMetadata.system.ignoreGraph ) {
metadata.graph.emplace_back(entity);
if ( eMetadata.system.ignoreGraph ) return;
auto& behaviorGraph = entity->getGraph();
for ( auto& fun : behaviorGraph.tickMT ) metadata.tasks.queue(fun);
metadata.graph.emplace_back(entity);
#if UF_TICK_FROM_TASKS
auto* self = (uf::Object*) entity;
auto& behaviorGraph = entity->getGraph();
#if 1
#if UF_TICK_MULTITHREAD_OVERRIDE
for ( auto fun : behaviorGraph.tick.serial ) metadata.tasks.parallel.queue([=]{ fun(*self); });
#else
for ( auto fun : behaviorGraph.tick.serial ) metadata.tasks.serial.queue([=]{ fun(*self); });
#endif
for ( auto fun : behaviorGraph.tick.parallel ) metadata.tasks.parallel.queue([=]{ fun(*self); });
#else
for ( auto& behavior : self->getBehaviors() ) {
if ( !behavior.traits.ticks ) continue;
auto name = behavior.type.name().str();
#if UF_TICK_MULTITHREAD_OVERRIDE
if ( true )
#else
if ( behavior.traits.multithread )
#endif
metadata.tasks.parallel.queue([=]{
behavior.tick(*self);
UF_MSG_DEBUG("Parallel {} task exectued: {}: {}", name, self->getName(), self->getUid());
}); else metadata.tasks.serial.queue([=]{
behavior.tick(*self);
UF_MSG_DEBUG("Serial {} task exectued: {}: {}", name, self->getName(), self->getUid());
});
}
#endif
#endif
});
uf::renderer::states::rebuild = true;
return metadata.graph;
}
@ -148,15 +181,15 @@ void uf::scene::tick() {
auto& metadata = scene.getComponent<uf::SceneBehavior::Metadata>();
#endif
auto graph = scene.getGraph(true);
#if 1
for ( auto entity : graph ) entity->tick();
#if UF_TICK_FROM_TASKS
// copy because executing from the tasks erases them all
auto tasks = metadata.tasks;
auto workers = uf::thread::execute( tasks.parallel );
uf::thread::execute( tasks.serial );
uf::thread::wait( workers );
#else
auto& tasks = metadata.tasks;
pod::Thread::Tasks tasks = metadata.tasks;
tasks.queue([&]{
for ( auto entity : graph ) entity->tick();
});
uf::thread::execute( tasks );
for ( auto entity : graph ) entity->tick();
#endif
}
void uf::scene::render() {

View File

@ -33,6 +33,21 @@ ext::json::Value& ext::json::Value::reserve( size_t n ) {
return *this;
}
ext::json::Value ext::json::find( const uf::stl::string& needle, const ext::json::Value& haystack ) {
ext::json::Value exact = ext::json::null();
ext::json::Value regexed = ext::json::null();
ext::json::forEach( haystack, [&]( const uf::stl::string& key, const ext::json::Value& value, bool& breaks ) {
if ( needle == key ) {
exact = value;
breaks = true;
} else if ( uf::string::isRegex( key ) && uf::string::matched( needle, key ) ) {
regexed = value;
}
});
return !ext::json::isNull(exact) ? exact : regexed;
}
void ext::json::forEach( ext::json::Value& json, const std::function<void(ext::json::Value&)>& function ) {
// UF_ASSERT_SAFE( ext::json::isArray(json) || ext::json::isObject(json) );
// for ( auto it = json.begin(); it != json.end(); ++it ) { auto& v = *it;

View File

@ -76,7 +76,7 @@ namespace binds {
pod::Behavior::function_t* functionPointer = NULL;
if ( type == "initialize" ) functionPointer = &behavior.initialize;
else if ( type == "tick" ) { functionPointer = &behavior.tick; behavior.traits.ticks = true; }
else if ( type == "tick" ) { functionPointer = &behavior.tick; behavior.traits.ticks = true; behavior.traits.multithread = false; }
else if ( type == "render" ) { functionPointer = &behavior.render; behavior.traits.renders = true; }
else if ( type == "destroy" ) functionPointer = &behavior.destroy;

View File

@ -25,6 +25,10 @@ bool ext::opengl::settings::defaultStageBuffers = false;
// constexpr size_t ext::opengl::settings::maxViews = 6;
size_t ext::opengl::settings::viewCount = 1;
size_t ext::opengl::settings::scratchBufferAlignment = 0;
size_t ext::opengl::settings::scratchBufferInitialSize = 256;
size_t ext::opengl::settings::defaultTimeout = 100000000000;
uf::stl::vector<uf::stl::string> ext::opengl::settings::validationFilters;
uf::stl::vector<uf::stl::string> ext::opengl::settings::requestedDeviceFeatures;
uf::stl::vector<uf::stl::string> ext::opengl::settings::requestedDeviceExtensions;
@ -52,6 +56,7 @@ bool ext::opengl::settings::invariant::deferredSampling = false;
bool ext::opengl::settings::invariant::multiview = false;
// pipelines
bool ext::opengl::settings::pipelines::deferred = false;
bool ext::opengl::settings::pipelines::vsync = true;
bool ext::opengl::settings::pipelines::hdr = false;
bool ext::opengl::settings::pipelines::vxgi = false;
@ -59,6 +64,7 @@ bool ext::opengl::settings::pipelines::culling = false;
bool ext::opengl::settings::pipelines::bloom = false;
bool ext::opengl::settings::pipelines::rt = false;
uf::stl::string ext::opengl::settings::pipelines::names::deferred = "deferred";
uf::stl::string ext::opengl::settings::pipelines::names::vsync = "vsync";
uf::stl::string ext::opengl::settings::pipelines::names::hdr = "hdr";
uf::stl::string ext::opengl::settings::pipelines::names::vxgi = "vxgi";

View File

@ -223,7 +223,7 @@ void ext::vulkan::BaseRenderMode::render() {
VK_CHECK_RESULT(swapchain.acquireNextImage(&states::currentBuffer, swapchain.presentCompleteSemaphore));
// Use a fence to wait until the command buffer has finished execution before using it again
VK_CHECK_RESULT(vkWaitForFences(*device, 1, &fences[states::currentBuffer], VK_TRUE, UINT64_MAX));
VK_CHECK_RESULT(vkWaitForFences(*device, 1, &fences[states::currentBuffer], VK_TRUE, VK_DEFAULT_FENCE_TIMEOUT));
VK_CHECK_RESULT(vkResetFences(*device, 1, &fences[states::currentBuffer]));
// Pipeline stage at which the queue submission will wait (via pWaitSemaphores)

View File

@ -197,7 +197,7 @@ void ext::vulkan::ComputeRenderMode::render() {
// Submit commands
// Use a fence to ensure that command buffer has finished executing before using it again
VK_CHECK_RESULT(vkWaitForFences( *device, 1, &fences[states::currentBuffer], VK_TRUE, UINT64_MAX ));
VK_CHECK_RESULT(vkWaitForFences( *device, 1, &fences[states::currentBuffer], VK_TRUE, VK_DEFAULT_FENCE_TIMEOUT ));
VK_CHECK_RESULT(vkResetFences( *device, 1, &fences[states::currentBuffer] ));
VkSubmitInfo submitInfo = {};

View File

@ -124,9 +124,6 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
/*.blend =*/ blend,
/*.samples =*/ 1,
});
UF_MSG_DEBUG("{} = {}", "color", attachments.color);
UF_MSG_DEBUG("{} = {}", "bright", attachments.bright);
UF_MSG_DEBUG("{} = {}", "scratch", attachments.scratch);
// Attach swapchain's image as output
if ( settings::invariant::deferredAliasOutputToSwapchain ) {
@ -264,9 +261,10 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
}
{
size_t index = uf::renderer::settings::pipelines::deferred ? metadata.outputs[0] : metadata.outputs[0] - 2; // deferred ? attachments.color : attachments.albedo;
auto& shader = blitter.material.getShader("fragment");
shader.textures.clear();
shader.textures.emplace_back().aliasAttachment( renderTarget.attachments[metadata.outputs[0]], (size_t) 0 ); // attachments.color
shader.textures.emplace_back().aliasAttachment( renderTarget.attachments[index], (size_t) 0 ); // attachments.color
/*
for ( auto& texture : shader.textures ) {
texture.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
@ -435,9 +433,10 @@ void ext::vulkan::DeferredRenderMode::tick() {
// update blitter descriptor set
if ( rebuild && blitter.initialized ) {
{
size_t index = uf::renderer::settings::pipelines::deferred ? metadata.outputs[0] : metadata.outputs[0] - 2; // deferred ? attachments.color : attachments.albedo;
auto& shader = blitter.material.getShader("fragment");
shader.textures.clear();
shader.textures.emplace_back().aliasAttachment( renderTarget.attachments[metadata.outputs[0]], (size_t) 0 ); // attachments.color
shader.textures.emplace_back().aliasAttachment( renderTarget.attachments[index], (size_t) 0 ); // attachments.color
/*
for ( auto& texture : shader.textures ) {
texture.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
@ -510,7 +509,7 @@ void ext::vulkan::DeferredRenderMode::render() {
auto& commands = getCommands( this->mostRecentCommandPoolId );
// Submit commands
// Use a fence to ensure that command buffer has finished executing before using it again
VK_CHECK_RESULT(vkWaitForFences( *device, 1, &fences[states::currentBuffer], VK_TRUE, UINT64_MAX ));
VK_CHECK_RESULT(vkWaitForFences( *device, 1, &fences[states::currentBuffer], VK_TRUE, VK_DEFAULT_FENCE_TIMEOUT ));
VK_CHECK_RESULT(vkResetFences( *device, 1, &fences[states::currentBuffer] ));
VkSubmitInfo submitInfo = {};
@ -528,41 +527,6 @@ void ext::vulkan::DeferredRenderMode::render() {
if ( commandBufferCallbacks.count(EXECUTE_END) > 0 ) commandBufferCallbacks[EXECUTE_END]( VkCommandBuffer{} );
this->executed = true;
#if 0
//lockMutex( this->mostRecentCommandPoolId );
auto& commands = getCommands( this->mostRecentCommandPoolId );
// Get next image in the swap chain (back/front buffer)
VK_CHECK_RESULT(swapchain.acquireNextImage(&states::currentBuffer, swapchain.presentCompleteSemaphore));
// Use a fence to wait until the command buffer has finished execution before using it again
VK_CHECK_RESULT(vkWaitForFences(*device, 1, &fences[states::currentBuffer], VK_TRUE, UINT64_MAX));
VK_CHECK_RESULT(vkResetFences(*device, 1, &fences[states::currentBuffer]));
// Pipeline stage at which the queue submission will wait (via pWaitSemaphores)
VkPipelineStageFlags waitStageMask[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
// The submit info structure specifices a command buffer queue submission batch
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.pWaitDstStageMask = waitStageMask; // Pointer to the list of pipeline stages that the semaphore waits will occur at
submitInfo.pWaitSemaphores = &swapchain.presentCompleteSemaphore; // Semaphore(s) to wait upon before the submitted command buffer starts executing
submitInfo.waitSemaphoreCount = 1; // One wait semaphore
submitInfo.pSignalSemaphores = &renderCompleteSemaphore; // Semaphore(s) to be signaled when command buffers have completed
submitInfo.signalSemaphoreCount = 1; // One signal semaphore
submitInfo.pCommandBuffers = &commands[states::currentBuffer]; // Command buffers(s) to execute in this batch (submission)
submitInfo.commandBufferCount = 1;
// Submit to the graphics queue passing a wait fence
VK_CHECK_RESULT(vkQueueSubmit( device->getQueue( Device::QueueEnum::GRAPHICS ), 1, &submitInfo, fences[states::currentBuffer]));
//vkQueueSubmit(device->queues.graphics, 1, &submitInfo, fences[states::currentBuffer]);
// Present the current buffer to the swap chain
// Pass the semaphore signaled by the command buffer submission from the submit info as the wait semaphore for swap chain presentation
// This ensures that the image is not presented to the windowing system until all commands have been submitted
VK_CHECK_RESULT(swapchain.queuePresent(device->getQueue( Device::QueueEnum::PRESENT ), states::currentBuffer, renderCompleteSemaphore));
VK_CHECK_RESULT(vkQueueWaitIdle(device->getQueue( Device::QueueEnum::PRESENT )));
this->executed = true;
#endif
//unlockMutex( this->mostRecentCommandPoolId );
}
void ext::vulkan::DeferredRenderMode::destroy() {

View File

@ -445,7 +445,7 @@ void ext::vulkan::RenderTargetRenderMode::render() {
auto& commands = getCommands( this->mostRecentCommandPoolId );
// Submit commands
// Use a fence to ensure that command buffer has finished executing before using it again
VK_CHECK_RESULT(vkWaitForFences( *device, 1, &fences[states::currentBuffer], VK_TRUE, UINT64_MAX ));
VK_CHECK_RESULT(vkWaitForFences( *device, 1, &fences[states::currentBuffer], VK_TRUE, VK_DEFAULT_FENCE_TIMEOUT ));
VK_CHECK_RESULT(vkResetFences( *device, 1, &fences[states::currentBuffer] ));
VkSubmitInfo submitInfo = {};

View File

@ -8,7 +8,7 @@
VkResult ext::vulkan::Swapchain::acquireNextImage( uint32_t* imageIndex, VkSemaphore presentCompleteSemaphore ) {
// By setting timeout to UINT64_MAX we will always wait until the next image has been acquired or an actual error is thrown
// With that we don't have to handle VK_NOT_READY
return vkAcquireNextImageKHR( *device, swapChain, UINT64_MAX, presentCompleteSemaphore, (VkFence) nullptr, imageIndex );
return vkAcquireNextImageKHR( *device, swapChain, VK_DEFAULT_FENCE_TIMEOUT, presentCompleteSemaphore, (VkFence) nullptr, imageIndex );
}
VkResult ext::vulkan::Swapchain::queuePresent( VkQueue queue, uint32_t imageIndex, VkSemaphore waitSemaphore ) {

View File

@ -28,6 +28,7 @@ size_t ext::vulkan::settings::viewCount = 2;
size_t ext::vulkan::settings::gpuID = -1;
size_t ext::vulkan::settings::scratchBufferAlignment = 256;
size_t ext::vulkan::settings::scratchBufferInitialSize = 1024 * 1024;
size_t ext::vulkan::settings::defaultTimeout = 100000000000;
uf::stl::vector<uf::stl::string> ext::vulkan::settings::validationFilters;
uf::stl::vector<uf::stl::string> ext::vulkan::settings::requestedDeviceFeatures;
@ -473,12 +474,12 @@ void ext::vulkan::render() {
}
if ( !submitsCompute.empty() ) {
VK_CHECK_RESULT(vkWaitForFences(device, 1, &::auxFencesCompute[states::currentBuffer], VK_TRUE, UINT64_MAX));
VK_CHECK_RESULT(vkWaitForFences(device, 1, &::auxFencesCompute[states::currentBuffer], VK_TRUE, VK_DEFAULT_FENCE_TIMEOUT));
VK_CHECK_RESULT(vkResetFences(device, 1, &::auxFencesCompute[states::currentBuffer]));
VK_CHECK_RESULT(vkQueueSubmit(device.getQueue( Device::QueueEnum::COMPUTE ), submitsCompute.size(), submitsCompute.data(), ::auxFencesCompute[states::currentBuffer]));
}
if ( !submitsGraphics.empty() ) {
VK_CHECK_RESULT(vkWaitForFences(device, 1, &::auxFencesGraphics[states::currentBuffer], VK_TRUE, UINT64_MAX));
VK_CHECK_RESULT(vkWaitForFences(device, 1, &::auxFencesGraphics[states::currentBuffer], VK_TRUE, VK_DEFAULT_FENCE_TIMEOUT));
VK_CHECK_RESULT(vkResetFences(device, 1, &::auxFencesGraphics[states::currentBuffer]));
VK_CHECK_RESULT(vkQueueSubmit(device.getQueue( Device::QueueEnum::GRAPHICS ), submitsGraphics.size(), submitsGraphics.data(), ::auxFencesGraphics[states::currentBuffer]));
}

View File

@ -78,28 +78,17 @@ pod::Thread::Tasks UF_API uf::thread::schedule( const uf::stl::string& name, boo
return tasks;
}
void UF_API uf::thread::execute( pod::Thread::Tasks& tasks ) {
if ( tasks.container.empty() ) return;
uf::stl::vector<pod::Thread*> UF_API uf::thread::execute( pod::Thread::Tasks& tasks ) {
uf::stl::vector<pod::Thread*> workers;
if ( tasks.container.empty() ) return workers;
if ( tasks.name == uf::thread::mainThreadName ) {
while ( !tasks.container.empty() ) {
auto& task = tasks.container.front();
task();
tasks.container.pop();
}
#if 0
} else /*if ( tasks.name == "Async" )*/ {
uf::stl::vector<std::future<void>> futures;
futures.reserve(tasks.container.size());
// for ( auto& task : tasks.container ) {
while ( !tasks.container.empty() ) {
auto task = tasks.container.front();
futures.emplace_back(std::async( std::launch::async, task ));
tasks.container.pop();
}
if ( tasks.waits ) for ( auto& future : futures ) future.wait();
#else
} else {
uf::stl::vector<pod::Thread*> workers;
while ( !tasks.container.empty() ) {
auto task = tasks.container.front();
auto& worker = uf::thread::fetchWorker( tasks.name );
@ -107,9 +96,16 @@ void UF_API uf::thread::execute( pod::Thread::Tasks& tasks ) {
workers.emplace_back(&worker);
tasks.container.pop();
}
if ( tasks.waits ) for ( auto& worker : workers ) uf::thread::wait( *worker );
if ( tasks.waits ) uf::thread::wait( workers );
}
#endif
return workers;
}
void UF_API uf::thread::wait( uf::stl::vector<pod::Thread*>& workers ) {
for ( auto& worker : workers ) uf::thread::wait( *worker );
workers.clear();
}
void UF_API uf::thread::wait( const uf::stl::vector<pod::Thread*>& workers ) {
for ( auto& worker : workers ) uf::thread::wait( *worker );
}
/*
void UF_API uf::thread::batchWorker( const pod::Thread::function_t& function, const uf::stl::string& name ) {

View File

@ -18,7 +18,7 @@
#define UF_BAKER_SAVE_MULTITHREAD 0
UF_BEHAVIOR_REGISTER_CPP(ext::BakingBehavior)
UF_BEHAVIOR_TRAITS_CPP(ext::BakingBehavior, ticks = true, renders = false, multithread = false)
UF_BEHAVIOR_TRAITS_CPP(ext::BakingBehavior, ticks = true, renders = false, multithread = true)
#define this (&self)
void ext::BakingBehavior::initialize( uf::Object& self ) {
#if UF_USE_VULKAN

View File

@ -23,7 +23,7 @@ namespace {
}
UF_BEHAVIOR_REGISTER_CPP(ext::LightBehavior)
UF_BEHAVIOR_TRAITS_CPP(ext::LightBehavior, ticks = true, renders = false, multithread = false)
UF_BEHAVIOR_TRAITS_CPP(ext::LightBehavior, ticks = true, renders = false, multithread = true)
#define this (&self)
void ext::LightBehavior::initialize( uf::Object& self ) {
auto& metadata = this->getComponent<ext::LightBehavior::Metadata>();

View File

@ -20,7 +20,7 @@
#include "../../gui/manager/behavior.h"
UF_BEHAVIOR_REGISTER_CPP(ext::PlayerBehavior)
UF_BEHAVIOR_TRAITS_CPP(ext::PlayerBehavior, ticks = true, renders = false, multithread = false)
UF_BEHAVIOR_TRAITS_CPP(ext::PlayerBehavior, ticks = true, renders = false, multithread = true)
#define this (&self)
void ext::PlayerBehavior::initialize( uf::Object& self ) {
auto& transform = this->getComponent<pod::Transform<>>();

View File

@ -15,7 +15,7 @@
#include <uf/utils/renderer/renderer.h>
UF_BEHAVIOR_REGISTER_CPP(ext::PlayerModelBehavior)
UF_BEHAVIOR_TRAITS_CPP(ext::PlayerModelBehavior, ticks = true, renders = false, multithread = false)
UF_BEHAVIOR_TRAITS_CPP(ext::PlayerModelBehavior, ticks = true, renders = false, multithread = true)
#define this ((uf::Scene*) &self)
void ext::PlayerModelBehavior::initialize( uf::Object& self ) {
auto& scene = uf::scene::getCurrentScene();

View File

@ -17,7 +17,7 @@
#include "../scene/behavior.h"
UF_BEHAVIOR_REGISTER_CPP(ext::RayTraceSceneBehavior)
UF_BEHAVIOR_TRAITS_CPP(ext::RayTraceSceneBehavior, ticks = true, renders = false, multithread = false)
UF_BEHAVIOR_TRAITS_CPP(ext::RayTraceSceneBehavior, ticks = true, renders = false, multithread = true)
#define this (&self)
void ext::RayTraceSceneBehavior::initialize( uf::Object& self ) {
auto& metadata = this->getComponent<ext::RayTraceSceneBehavior::Metadata>();

View File

@ -33,7 +33,7 @@
#include "../../gui/gui.h"
UF_BEHAVIOR_REGISTER_CPP(ext::ExtSceneBehavior)
UF_BEHAVIOR_TRAITS_CPP(ext::ExtSceneBehavior, ticks = true, renders = false, multithread = false)
UF_BEHAVIOR_TRAITS_CPP(ext::ExtSceneBehavior, ticks = true, renders = false, multithread = false) // hangs on initialization
#define this ((uf::Scene*) &self)
void ext::ExtSceneBehavior::initialize( uf::Object& self ) {
auto& assetLoader = this->getComponent<uf::Asset>();
@ -239,14 +239,14 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
}
}
}
#endif
#if 0
/* Mark as ready for multithreading */ {
TIMER(1, uf::inputs::kbm::states::M ) {
uf::renderer::settings::experimental::dedicatedThread = !uf::renderer::settings::experimental::dedicatedThread;
UF_MSG_DEBUG("Toggling multithreaded rendering...");
}
}
#endif
#if 0
/* Print World Tree */ {
TIMER(1, uf::inputs::kbm::states::U ) {
std::function<void(uf::Entity*, int)> filter = []( uf::Entity* entity, int indent ) {
@ -565,7 +565,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
uf::graph::storage.buffers.light.update( (const void*) uf::graph::storage.lights.data(), uf::graph::storage.lights.size() * sizeof(pod::Light) );
}
#endif
/* Update lights */ if ( !uf::renderer::settings::pipelines::vxgi ) {
/* Update lights */ if ( uf::renderer::settings::pipelines::deferred && !uf::renderer::settings::pipelines::vxgi ) {
ext::ExtSceneBehavior::bindBuffers( *this );
}
}

View File

@ -9,7 +9,7 @@
#include <mutex>
UF_BEHAVIOR_REGISTER_CPP(ext::SoundEmitterBehavior)
UF_BEHAVIOR_TRAITS_CPP(ext::SoundEmitterBehavior, ticks = true, renders = false, multithread = false)
UF_BEHAVIOR_TRAITS_CPP(ext::SoundEmitterBehavior, ticks = true, renders = false, multithread = true)
#define this ((uf::Object*) &self)
void ext::SoundEmitterBehavior::initialize( uf::Object& self ) {
auto& metadata = this->getComponent<uf::Serializer>();

View File

@ -435,7 +435,7 @@ void ext::VoxelizerSceneBehavior::tick( uf::Object& self ) {
#endif
}
ext::ExtSceneBehavior::bindBuffers( scene, metadata.renderModeName, "compute", "" );
ext::ExtSceneBehavior::bindBuffers( scene );
ext::ExtSceneBehavior::bindBuffers( scene, "", "fragment", "deferred" );
#endif
}
void ext::VoxelizerSceneBehavior::render( uf::Object& self ){}

View File

@ -481,7 +481,7 @@ UF_OBJECT_REGISTER_BEGIN(ext::Gui)
UF_OBJECT_REGISTER_BEHAVIOR(uf::ObjectBehavior)
UF_OBJECT_REGISTER_BEHAVIOR(ext::GuiBehavior)
UF_OBJECT_REGISTER_END()
UF_BEHAVIOR_TRAITS_CPP(ext::GuiBehavior, ticks = true, renders = false, multithread = false)
UF_BEHAVIOR_TRAITS_CPP(ext::GuiBehavior, ticks = true, renders = false, multithread = false) // segfaults when destroying, keep off to make smooth transitions
#define this (&self)
void ext::GuiBehavior::initialize( uf::Object& self ) {
auto& metadata = this->getComponent<ext::GuiBehavior::Metadata>();

View File

@ -34,7 +34,7 @@
#include <uf/ext/ultralight/ultralight.h>
UF_BEHAVIOR_REGISTER_CPP(ext::GuiHtmlBehavior)
UF_BEHAVIOR_TRAITS_CPP(ext::GuiHtmlBehavior, ticks = true, renders = false, multithread = false)
UF_BEHAVIOR_TRAITS_CPP(ext::GuiHtmlBehavior, ticks = true, renders = false, multithread = true)
#define this ((uf::Object*) &self)
void ext::GuiHtmlBehavior::initialize( uf::Object& self ) {
#if UF_USE_ULTRALIGHT

View File

@ -46,7 +46,7 @@ ext::gui::Size ext::gui::size = {
UF_BEHAVIOR_REGISTER_CPP(ext::GuiManagerBehavior)
UF_BEHAVIOR_TRAITS_CPP(ext::GuiManagerBehavior, ticks = true, renders = false, multithread = false)
UF_BEHAVIOR_TRAITS_CPP(ext::GuiManagerBehavior, ticks = true, renders = false, multithread = true)
UF_BEHAVIOR_REGISTER_AS_OBJECT(ext::GuiManagerBehavior, ext::GuiManager)
#define this (&self)
void ext::GuiManagerBehavior::initialize( uf::Object& self ) {

View File

@ -428,6 +428,10 @@ void EXT_API ext::initialize() {
uf::renderer::settings::pipelines::culling = configRenderPipelinesJson["culling"].as( uf::renderer::settings::pipelines::culling );
uf::renderer::settings::pipelines::bloom = configRenderPipelinesJson["bloom"].as( uf::renderer::settings::pipelines::bloom );
uf::renderer::settings::pipelines::rt = configRenderPipelinesJson["rt"].as( uf::renderer::settings::pipelines::rt );
if ( !uf::renderer::settings::pipelines::deferred /*&& !uf::renderer::settings::pipelines::rt*/ ) {
uf::renderer::settings::invariant::deferredSampling = false;
}
if ( uf::renderer::settings::pipelines::rt ) {
uf::renderer::settings::pipelines::vxgi = false;
@ -497,7 +501,7 @@ void EXT_API ext::initialize() {
renderMode->metadata.type = "single";
uf::renderer::addRenderMode( renderMode, "Gui" );
}
if ( uf::renderer::settings::pipelines::deferred ) {
if ( ::json["engine"]["render modes"]["deferred"].as<bool>(true) ) {
auto* renderMode = new uf::renderer::DeferredRenderMode;
renderMode->blitter.descriptor.renderMode = "Swapchain";