Commit for 2022.06.25 23-41-15.7z

This commit is contained in:
mrq 2022-06-25 23:41:00 -05:00
parent ddb43b26ea
commit 813907f0a3
41 changed files with 961 additions and 467 deletions

View File

@ -1,15 +1,15 @@
{
"engine": {
"scenes": {
"start": "SS2",
"start": "McDonalds",
"meshes": { "interleaved": false },
"matrix": { "reverseInfinite": true },
"lights": { "enabled": true,
"useLightmaps": false,
"max": 32
"max": 24
},
"shadows": {
"enabled": true,
"enabled": false,
"update": 2,
"max": 16,
"samples": 1
@ -48,7 +48,7 @@
"ext": {
"vulkan": {
"validation": {
"enabled": false,
"enabled": true,
"filters": [
"MessageID = 0x4dae5635", // UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout (false positive for cubemaps)
"MessageID = 0x609a13b", // UNASSIGNED-CoreValidation-Shader-OutputNotConsumed (from depth-only calls)
@ -243,6 +243,10 @@
"delete children on destroy": true,
"delete components on destroy": true
},
"userdata": {
"auto destruct": true,
"auto validate": false
},
"loader": {
"assert": true
}

View File

@ -2,10 +2,10 @@
"type": "Object",
"name": "Player: Model",
"ignore": true,
"import": "/model.json",
"assets": [
"/player/bear.glb"
// { "filename": "/player/bear/graph.json", "delay": 0, "single threaded": false, "category": "models" }
// { "filename": "/player/bear/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" }
// { "filename": "/player/bear/graph.json" }
],
"behaviors": [
"PlayerModelBehavior"
@ -29,30 +29,22 @@
"track": true,
"hide": true,
"model": {
"debug": {
"no cleanup": false,
"print tree": false,
"print stats": false
"lightmap": false,
"exporter": {
"enabled": false,
"unwrap": false,
"optimize": false
},
"export": {
"should": true,
"pretty": false,
"compress": true,
"quantize": false,
"precision": 4,
"combined": false,
"encode buffers": true,
"unwrap": false
"baking": {
"enabled": false
},
"animation": "wank",
"print animations": true,
// "filter": "NEAREST",
"cull mode": "none",
"flags": {
"ATLAS": false,
"INVERT": true,
"TRANSFORM": false,
"SKINNED": true,
"SKINNED": false,
"RENDER": true,
"SEPARATE": false,

View File

@ -0,0 +1,36 @@
{
"import": "/model.json",
"assets": [
// { "filename": "./models/cornell.glb" }
// { "filename": "./models/cornell/graph.json" }
// { "filename": "./models/sponza.glb" }
// { "filename": "./models/sponza/graph.json" }
// { "filename": "./models/sponza-cornell.glb" }
{ "filename": "./models/sponza-cornell/graph.json" }
],
"metadata": {
"model": {
"baking": {
"enabled": false,
"resolution": 1024
},
"filter": "LINEAR",
"lightmap": false,
"tags": {
"/^Mesh_/": {
"physics": { "type": "mesh", "static": true },
// "grid": { "size": [3,1,3], "epsilon": 0.0001, "cleanup": true, "print": true },
// "optimize mesh": { "simplify": 0 },
"unwrap mesh": true
},
"Camera": {
"action": "attach",
"filename": "./player.json",
"preserve orientation": true
}
}
}
}
}

View File

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

View File

@ -0,0 +1,55 @@
{
"import": "/scene.json",
"assets": [
"./loading.json"
],
"system": {
"hot reload": {
"enabled": true
},
"renderer": {
"clear values": [
[ 0, 0, 0, 0 ]
],
"shader": {
"mode": 1,
"scalar": 16,
"parameters": [ 0, 0, 0, "time" ]
}
}
},
"metadata": {
"menus": {
"pause": "/gui/pause/menu.json"
},
"bloom": {
"scale": 1.0,
"strength": 0.125,
"sigma": 0.8,
"samples": 5
},
"light": {
"exposure": 1.0,
"gamma": 1.0,
"brightnessThreshold": 1.2,
// "ambient": [ 0.0, 0.0, 0.0 ],
"ambient": [ 0.5, 0.5, 0.5 ],
"fog": {
"color": [ 0.025, 0.025, 0.1 ],
"step scale": 0.0,
"range": [ 1, 1 ],
"absorbtion": 0.85,
"density": {
"threshold": 0.5,
"multiplier": 5.0,
"scale": 50.0,
"offset": "time"
}
},
"should": true,
"shadows": true
}
}
}

View File

@ -22,8 +22,8 @@
"tags": {
"/^worldspawn/": {
"physics": { "type": "mesh", "static": true },
"grid": { "size": [4,1,4], "epsilon": 1.0, "cleanup": true, "print": true },
"optimize mesh": { "simplify": 0 },
// "grid": { "size": [4,1,4], "epsilon": 1.0, "cleanup": true, "print": true },
// "optimize mesh": { "simplify": 0 },
"unwrap mesh": true
},
"info_player_spawn": { "action": "attach", "filename": "./player.json", "preserve orientation": true },

View File

@ -35,7 +35,8 @@
"gamma": 1.0,
"brightnessThreshold": 1.2,
// "ambient": [ 0, 0, 0 ],
"ambient": [ 0.025, 0.025, 0.025 ],
// "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

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

View File

@ -54,6 +54,8 @@
#if ADDRESS_ENABLED
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable
// #extension GL_EXT_shader_explicit_arithmetic_types_int16 : enable
// #extension GL_EXT_shader_explicit_arithmetic_types_int8 : enable
#endif
const float PI = 3.14159265359;

View File

@ -13,7 +13,7 @@ float gaSchlickGGX(float cosLi, float cosLo, float roughness) {
return gaSchlickG1(cosLi, k) * gaSchlickG1(cosLo, k);
}
vec3 fresnelSchlick(vec3 F0, float cosTheta) { return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); }
#if !BAKING && !COMPUTE
#if (!BAKING && !COMPUTE) || RAYTRACE
void pbr() {
if ( bool(ubo.useLightmaps) && validTextureIndex( surface.instance.lightmapID ) ) return;

View File

@ -140,6 +140,10 @@ struct Instance {
struct InstanceAddresses {
uint64_t vertex;
uint64_t index;
uint64_t indirect;
uint drawID;
uint padding0;
uint64_t position;
uint64_t uv;
@ -154,7 +158,7 @@ struct InstanceAddresses {
uint64_t weights;
uint64_t id;
uint64_t padding;
uint64_t padding1;
};
#endif
@ -221,4 +225,30 @@ struct VoxelInfo {
float mipmapLevels;
float radianceSize;
float radianceSizeRecip;
} voxelInfo;
} voxelInfo;
// Raytrace stuff
struct Vertex {
vec3 position;
vec2 uv;
uint color;
vec2 st;
vec3 normal;
vec3 tangent;
uvec2 joints;
vec4 weights;
uint id;
};
struct Triangle {
uvec3 indices;
Vertex points[3];
Vertex point;
};
struct RayTracePayload {
bool hit;
uint instanceID;
Triangle triangle;
};

View File

@ -62,7 +62,7 @@ layout (binding = 5) uniform UBO {
uint msaa;
uint shadowSamples;
uint indexSkybox;
int indexSkybox;
uint useLightmaps;
uint padding2;
uint padding3;
@ -194,7 +194,9 @@ void populateSurface() {
const uint drawID = ID.x - 1;
const uint instanceID = ID.y - 1;
if ( ID.x == 0 || ID.y == 0 ) {
surface.fragment.rgb = texture( samplerCubemaps[ubo.indexSkybox], surface.ray.direction ).rgb;
if ( 0 <= ubo.indexSkybox && ubo.indexSkybox < CUBEMAPS ) {
surface.fragment.rgb = texture( samplerCubemaps[ubo.indexSkybox], surface.ray.direction ).rgb;
}
surface.fragment.a = 0.0;
postProcess();
return;

View File

@ -56,13 +56,13 @@ void main() {
const uint instanceID = uint(inId.y);
const uint materialID = uint(inId.z);
vec4 A = vec4(1, 1, 1, 1);
surface.normal.world = normalize( inNormal );
surface.uv.xy = wrap(inUv.xy);
surface.uv.z = mipLevel(dFdx(inUv), dFdy(inUv));
surface.position.world = inPosition;
const Material material = materials[materialID];
vec4 A = material.colorBase;
surface.material.metallic = material.factorMetallic;
surface.material.roughness = material.factorRoughness;
surface.material.occlusion = 1.0f - material.factorOcclusion;

View File

@ -59,12 +59,13 @@ void main() {
const Instance instance = instances[instanceID];
const Material material = materials[materialID];
A = material.colorBase;
float M = material.factorMetallic;
float R = material.factorRoughness;
float AO = material.factorOcclusion;
// sample albedo
if ( !validTextureIndex( material.indexAlbedo ) ) discard; {
if ( validTextureIndex( material.indexAlbedo ) ) {
A = sampleTexture( material.indexAlbedo );
// alpha mode OPAQUE
if ( material.modeAlpha == 0 ) {

View File

@ -36,13 +36,15 @@ void main() {
const uint instanceID = uint(inId.y);
const uint materialID = uint(inId.z);
const vec2 uv = wrap(inUv.xy);
vec4 A = vec4(0, 0, 0, 0);
const Material material = materials[materialID];
vec4 A = material.colorBase;
surface.uv.xy = uv;
surface.uv.z = mipLevel(dFdx(inUv), dFdy(inUv));
const Material material = materials[materialID];
// sample albedo
if ( !validTextureIndex( material.indexAlbedo ) ) discard; {
// if ( !validTextureIndex( material.indexAlbedo ) ) discard; {
if ( validTextureIndex( material.indexAlbedo ) ) {
// const Texture t = textures[material.indexAlbedo];
// A = textureLod( samplerTextures[nonuniformEXT(t.index)], mix( t.lerp.xy, t.lerp.zw, uv ), mip );
A = sampleTexture( material.indexAlbedo );

View File

@ -69,18 +69,18 @@ void main() {
surface.st.z = mipLevel(dFdx(inSt), dFdy(inSt));
vec3 N = inNormal;
vec4 A = vec4(0, 0, 0, 0);
const Instance instance = instances[instanceID];
const Material material = materials[materialID];
surface.instance = instance;
vec4 A = material.colorBase;
float M = material.factorMetallic;
float R = material.factorRoughness;
float AO = material.factorOcclusion;
// sample albedo
if ( !validTextureIndex( material.indexAlbedo ) ) discard; {
if ( validTextureIndex( material.indexAlbedo ) ) {
A = sampleTexture( material.indexAlbedo );
// alpha mode OPAQUE
if ( material.modeAlpha == 0 ) {

View File

@ -1,47 +0,0 @@
#version 460
#extension GL_EXT_ray_tracing : enable
#pragma shader_stage(raygen)
layout (constant_id = 0) const uint PASSES = 2;
#include "../common/macros.h"
#include "../common/structs.h"
layout (binding = 0) uniform UBO {
EyeMatrices eyes[2];
} ubo;
layout (binding = 1) uniform accelerationStructureEXT inTlas;
layout (binding = 2, rgba8) uniform volatile coherent image2D outImage;
layout (location = 0) rayPayloadEXT vec4 hitValue;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
void main() {
{
surface.pass = PushConstant.pass;
const vec2 inUv = (vec2(gl_LaunchIDEXT.xy) + vec2(0.5)) / vec2(gl_LaunchSizeEXT.xy);
const mat4 iProjectionView = inverse( ubo.eyes[surface.pass].projection * mat4(mat3(ubo.eyes[surface.pass].view)) );
const vec4 near4 = iProjectionView * (vec4(2.0 * inUv - 1.0, -1.0, 1.0));
const vec4 far4 = iProjectionView * (vec4(2.0 * inUv - 1.0, 1.0, 1.0));
const vec3 near3 = near4.xyz / near4.w;
const vec3 far3 = far4.xyz / far4.w;
surface.ray.direction = normalize( far3 - near3 );
surface.ray.origin = ubo.eyes[surface.pass].eyePos.xyz;
}
uint rayFlags = gl_RayFlagsOpaqueEXT;
uint cullMask = 0xFF;
float tMin = 0.001;
float tMax = 10000.0;
hitValue = vec4(0);
traceRayEXT(inTlas, rayFlags, cullMask, 0, 0, 0, surface.ray.origin.xyz, tMin, surface.ray.direction.xyz, tMax, 0);
imageStore(outImage, ivec2(gl_LaunchIDEXT.xy), vec4(hitValue));
}

View File

@ -1,12 +0,0 @@
#version 460
#extension GL_EXT_ray_tracing : enable
#extension GL_EXT_nonuniform_qualifier : enable
#pragma shader_stage(closest)
layout(location = 0) rayPayloadInEXT vec4 hitValue;
hitAttributeEXT vec2 attribs;
void main() {
const vec3 barycentricCoords = vec3(1.0f - attribs.x - attribs.y, attribs.x, attribs.y);
hitValue = vec4(barycentricCoords, 1.0);
}

View File

@ -1,9 +0,0 @@
#version 460
#extension GL_EXT_ray_tracing : enable
#pragma shader_stage(miss)
layout(location = 0) rayPayloadInEXT vec4 hitValue;
void main() {
hitValue = vec4(0.2, 0.2, 0.2, 0.0);
}

View File

@ -0,0 +1,280 @@
#version 460
#extension GL_EXT_ray_tracing : enable
#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;
#define ADDRESS_ENABLED 1
#define COMPUTE 1
#define PBR 1
#define VXGI 0
#define RAYTRACE 1
#define FOG 0
#define WHITENOISE 0
#define MAX_TEXTURES TEXTURES
#include "../common/macros.h"
#include "../common/structs.h"
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
layout (binding = 0) uniform accelerationStructureEXT tlas;
layout (binding = 1, rgba8) uniform volatile coherent image2D outImage;
layout (binding = 2) uniform UBO {
EyeMatrices eyes[2];
Mode mode;
Fog fog;
Vxgi vxgi;
uint lights;
uint materials;
uint textures;
uint drawCommands;
vec3 ambient;
float gamma;
float exposure;
float brightnessThreshold;
uint msaa;
uint shadowSamples;
int indexSkybox;
uint useLightmaps;
uint padding2;
uint padding3;
} ubo;
layout (std140, binding = 3) readonly buffer Instances {
Instance instances[];
};
layout (std140, binding = 4) readonly buffer Materials {
Material materials[];
};
layout (std140, binding = 5) readonly buffer Textures {
Texture textures[];
};
layout (std140, binding = 6) readonly buffer Lights {
Light lights[];
};
layout (binding = 7) uniform sampler2D samplerTextures[TEXTURES];
layout (binding = 8) uniform samplerCube samplerCubemaps[CUBEMAPS];
#if VXGI
layout (binding = 14) uniform usampler3D voxelId[CASCADES];
layout (binding = 15) uniform sampler3D voxelNormal[CASCADES];
layout (binding = 16) uniform sampler3D voxelRadiance[CASCADES];
#endif
layout (location = 0) rayPayloadEXT RayTracePayload payload;
#include "../common/functions.h"
#include "../common/light.h"
#if VXGI
#include "../common/vxgi.h"
#endif
float shadowFactor( const Light light, float def ) {
Ray ray;
ray.origin = surface.position.world;
ray.direction = light.position - ray.origin;
uint rayFlags = gl_RayFlagsOpaqueEXT | gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsSkipClosestHitShaderEXT;
uint cullMask = 0xFF;
float tMin = 0.125;
float tMax = length(ray.direction) - 1;
ray.direction = normalize(ray.direction);
payload.hit = true;
traceRayEXT(tlas, rayFlags, cullMask, 0, 0, 0, ray.origin.xyz, tMin, ray.direction.xyz, tMax, 0);
return payload.hit ? 0.0 : 1.0;
}
void processHit( uint instanceID, Triangle triangle ) {
const Instance instance = instances[instanceID];
surface.instance = instance;
surface.pass = 0;
surface.fragment = vec4(0);
surface.light = vec4(0);
// bind position
{
surface.position.world = vec3( instance.model * vec4(triangle.point.position, 1.0 ) );
surface.position.eye = vec3( ubo.eyes[surface.pass].view * vec4(surface.position.world, 1.0) );
}
// bind normals
{
surface.normal.world = vec3( instance.model * vec4(triangle.point.normal, 0.0 ) );
surface.normal.eye = vec3( ubo.eyes[surface.pass].view * vec4(surface.normal.world, 0.0) );
}
// bind UVs
{
surface.uv.xy = triangle.point.uv;
surface.st.xy = triangle.point.st;
}
const Material material = materials[surface.instance.materialID];
surface.material.albedo = material.colorBase;
surface.material.metallic = material.factorMetallic;
surface.material.roughness = material.factorRoughness;
surface.material.occlusion = material.factorOcclusion;
surface.fragment = material.colorEmissive;
if ( validTextureIndex( material.indexAlbedo ) ) {
surface.material.albedo = sampleTexture( material.indexAlbedo );
}
// OPAQUE
if ( material.modeAlpha == 0 ) {
surface.material.albedo.a = 1;
// BLEND
} else if ( material.modeAlpha == 1 ) {
// MASK
} else if ( material.modeAlpha == 2 ) {
}
// Lightmap
if ( bool(ubo.useLightmaps) && validTextureIndex( surface.instance.lightmapID ) ) {
surface.light += surface.material.albedo * sampleTexture( surface.instance.lightmapID, surface.st );
}
// Emissive textures
if ( validTextureIndex( material.indexEmissive ) ) {
surface.light += sampleTexture( material.indexEmissive );
}
// Occlusion map
if ( validTextureIndex( material.indexOcclusion ) ) {
surface.material.occlusion = sampleTexture( material.indexOcclusion ).r;
}
// Metallic/Roughness map
if ( validTextureIndex( material.indexMetallicRoughness ) ) {
vec4 samp = sampleTexture( material.indexMetallicRoughness );
surface.material.metallic = samp.r;
surface.material.roughness = samp.g;
}
#if VXGI
{
indirectLighting();
}
#endif
{
surface.light.rgb += surface.material.albedo.rgb * ubo.ambient.rgb * surface.material.occlusion; // add ambient lighting
surface.light.rgb += surface.material.indirect.rgb; // add indirect lighting
#if PBR
pbr();
#endif
surface.fragment.rgb += surface.light.rgb;
surface.fragment.a = surface.material.albedo.a;
}
}
void trace( float tMin, float tMax ) {
uint rayFlags = gl_RayFlagsOpaqueEXT;
uint cullMask = 0xFF;
payload.hit = false;
traceRayEXT(tlas, rayFlags, cullMask, 0, 0, 0, surface.ray.origin.xyz, tMin, surface.ray.direction.xyz, tMax, 0);
}
void main() {
{
surface.fragment = vec4(0);
surface.pass = PushConstant.pass;
const vec2 inUv = (vec2(gl_LaunchIDEXT.xy) + vec2(0.5)) / vec2(gl_LaunchSizeEXT.xy);
const mat4 iProjectionView = inverse( ubo.eyes[surface.pass].projection * mat4(mat3(ubo.eyes[surface.pass].view)) );
const vec4 near4 = iProjectionView * (vec4(2.0 * inUv - 1.0, -1.0, 1.0));
const vec4 far4 = iProjectionView * (vec4(2.0 * inUv - 1.0, 1.0, 1.0));
const vec3 near3 = near4.xyz / near4.w;
const vec3 far3 = far4.xyz / far4.w;
surface.ray.direction = normalize( far3 - near3 );
surface.ray.origin = ubo.eyes[surface.pass].eyePos.xyz;
}
trace( 0.001, 4096.0 );
if ( payload.hit ) {
processHit( payload.instanceID, payload.triangle );
#if 1
uint tries = 8;
while ( 0 < surface.material.metallic && --tries > 0 ) {
vec4 back = surface.fragment;
surface.fragment = vec4(0);
surface.ray.direction = reflect( normalize(surface.position.world - surface.ray.origin), surface.normal.world );
surface.ray.origin = surface.position.world;
trace( 0.01, 4096.0 );
if ( payload.hit ) {
processHit( payload.instanceID, payload.triangle );
vec4 front = surface.fragment;
surface.fragment = mix( front, back, surface.material.metallic );
// surface.fragment.rgb = front.rgb * front.a + back.rgb * back.a;
} else {
surface.fragment = back;
}
}
#endif
#if 0
if ( surface.fragment.a < 1.0 ) {
vec4 back = surface.fragment;
surface.fragment = vec4(0);
surface.ray.origin = surface.position.world;
trace( 0.01, 4096.0 );
if ( payload.hit ) {
processHit( payload.instanceID, payload.triangle );
vec4 front = surface.fragment;
// surface.fragment = mix( front, back, back.a );
surface.fragment.rgb = front.rgb * front.a + back.rgb * back.a;
} else {
surface.fragment = back;
}
}
#endif
} else if ( 0 <= ubo.indexSkybox && ubo.indexSkybox < CUBEMAPS ) {
surface.fragment.rgb = texture( samplerCubemaps[ubo.indexSkybox], surface.ray.direction ).rgb;
}
{
surface.fragment.a = 1;
// float brightness = dot(surface.fragment.rgb, vec3(0.2126, 0.7152, 0.0722));
// outFragBright = brightness > ubo.brightnessThreshold ? vec4(surface.fragment.rgb, 1.0) : vec4(0, 0, 0, 1);
#if FOG
fog( surface.ray, surface.fragment.rgb, surface.fragment.a );
#endif
#if TONE_MAP
surface.fragment.rgb = vec3(1.0) - exp(-surface.fragment.rgb * ubo.exposure);
#endif
#if GAMMA_CORRECT
surface.fragment.rgb = pow(surface.fragment.rgb, vec3(1.0 / ubo.gamma));
#endif
#if WHITENOISE
if ( enabled(ubo.mode.type, 1) ) whitenoise(surface.fragment.rgb, ubo.mode.parameters);
#endif
imageStore(outImage, ivec2(gl_LaunchIDEXT.xy), surface.fragment);
}
}

View File

@ -0,0 +1,91 @@
#version 460
#extension GL_EXT_ray_tracing : enable
#extension GL_EXT_nonuniform_qualifier : enable
#extension GL_EXT_buffer_reference : enable
#extension GL_EXT_buffer_reference2 : enable
#extension GL_EXT_scalar_block_layout : enable
#pragma shader_stage(anyhit)
layout (constant_id = 0) const uint PASSES = 2;
layout (constant_id = 1) const uint TEXTURES = 512;
layout (constant_id = 2) const uint CUBEMAPS = 128;
#define ADDRESS_ENABLED 1
#define COMPUTE 1
#define PBR 1
#define RAYTRACE 1
#define MAX_TEXTURES TEXTURES
#include "../common/macros.h"
#include "../common/structs.h"
layout (std140, binding = 10) readonly buffer InstanceAddresseses {
InstanceAddresses instanceAddresses[];
};
layout(buffer_reference, scalar) buffer Vertices { Vertex v[]; };
layout(buffer_reference, scalar) buffer Indices { uvec3 i[]; };
layout(buffer_reference, scalar) buffer Indirects { DrawCommand dc[]; };
layout(buffer_reference, scalar) buffer VPos { vec3 v[]; };
layout(buffer_reference, scalar) buffer VUv { vec2 v[]; };
layout(buffer_reference, scalar) buffer VColor { uint v[]; };
layout(buffer_reference, scalar) buffer VSt { vec2 v[]; };
layout(buffer_reference, scalar) buffer VNormal { vec3 v[]; };
layout(buffer_reference, scalar) buffer VTangent { vec3 v[]; };
layout(buffer_reference, scalar) buffer VID { uint v[]; };
layout(location = 0) rayPayloadInEXT RayTracePayload payload;
hitAttributeEXT vec2 attribs;
void main() {
const vec3 bary = vec3(
1.0 - attribs.x - attribs.y,
attribs.x,
attribs.y
);
const uint instanceID = gl_InstanceCustomIndexEXT;
const InstanceAddresses instanceAddresses = instanceAddresses[instanceID];
if ( !(0 < instanceAddresses.index) ) return;
const DrawCommand drawCommand = Indirects(nonuniformEXT(instanceAddresses.indirect)).dc[instanceAddresses.drawID];
const uint triangleID = gl_PrimitiveID + (drawCommand.indexID / 3);
Triangle triangle;
triangle.indices = Indices(nonuniformEXT(instanceAddresses.index)).i[triangleID];
for ( uint _ = 0; _ < 3; ++_ ) triangle.indices[_] += drawCommand.vertexID;
if ( 0 < instanceAddresses.vertex ) {
Vertices vertices = Vertices(nonuniformEXT(instanceAddresses.vertex));
for ( uint _ = 0; _ < 3; ++_ ) triangle.points[_] = vertices.v[triangle.indices[_]];
} else {
if ( 0 < instanceAddresses.position ) {
VPos buf = VPos(nonuniformEXT(instanceAddresses.position));
for ( uint _ = 0; _ < 3; ++_ ) triangle.points[_].position = buf.v[triangle.indices[_]];
}
if ( 0 < instanceAddresses.uv ) {
VUv buf = VUv(nonuniformEXT(instanceAddresses.uv));
for ( uint _ = 0; _ < 3; ++_ ) triangle.points[_].uv = buf.v[triangle.indices[_]];
}
if ( 0 < instanceAddresses.st ) {
VSt buf = VSt(nonuniformEXT(instanceAddresses.st));
for ( uint _ = 0; _ < 3; ++_ ) triangle.points[_].st = buf.v[triangle.indices[_]];
}
if ( 0 < instanceAddresses.normal ) {
VNormal buf = VNormal(nonuniformEXT(instanceAddresses.normal));
for ( uint _ = 0; _ < 3; ++_ ) triangle.points[_].normal = buf.v[triangle.indices[_]];
}
}
triangle.point.position = triangle.points[0].position * bary[0] + triangle.points[1].position * bary[1] + triangle.points[2].position * bary[2];
triangle.point.uv = triangle.points[0].uv * bary[0] + triangle.points[1].uv * bary[1] + triangle.points[2].uv * bary[2];
triangle.point.st = triangle.points[0].st * bary[0] + triangle.points[1].st * bary[1] + triangle.points[2].st * bary[2];
triangle.point.normal = triangle.points[0].normal * bary[0] + triangle.points[1].normal * bary[1] + triangle.points[2].normal * bary[2];
payload.hit = true;
payload.instanceID = instanceID;
payload.triangle = triangle;
}

View File

@ -0,0 +1,91 @@
#version 460
#extension GL_EXT_ray_tracing : enable
#extension GL_EXT_nonuniform_qualifier : enable
#extension GL_EXT_buffer_reference : enable
#extension GL_EXT_buffer_reference2 : enable
#extension GL_EXT_scalar_block_layout : enable
#pragma shader_stage(closest)
layout (constant_id = 0) const uint PASSES = 2;
layout (constant_id = 1) const uint TEXTURES = 512;
layout (constant_id = 2) const uint CUBEMAPS = 128;
#define ADDRESS_ENABLED 1
#define COMPUTE 1
#define PBR 1
#define RAYTRACE 1
#define MAX_TEXTURES TEXTURES
#include "../common/macros.h"
#include "../common/structs.h"
layout (std140, binding = 9) readonly buffer InstanceAddresseses {
InstanceAddresses instanceAddresses[];
};
layout(buffer_reference, scalar) buffer Vertices { Vertex v[]; };
layout(buffer_reference, scalar) buffer Indices { uvec3 i[]; };
layout(buffer_reference, scalar) buffer Indirects { DrawCommand dc[]; };
layout(buffer_reference, scalar) buffer VPos { vec3 v[]; };
layout(buffer_reference, scalar) buffer VUv { vec2 v[]; };
layout(buffer_reference, scalar) buffer VColor { uint v[]; };
layout(buffer_reference, scalar) buffer VSt { vec2 v[]; };
layout(buffer_reference, scalar) buffer VNormal { vec3 v[]; };
layout(buffer_reference, scalar) buffer VTangent { vec3 v[]; };
layout(buffer_reference, scalar) buffer VID { uint v[]; };
layout(location = 0) rayPayloadInEXT RayTracePayload payload;
hitAttributeEXT vec2 attribs;
void main() {
const vec3 bary = vec3(
1.0 - attribs.x - attribs.y,
attribs.x,
attribs.y
);
const uint instanceID = gl_InstanceCustomIndexEXT;
const InstanceAddresses instanceAddresses = instanceAddresses[instanceID];
if ( !(0 < instanceAddresses.index) ) return;
const DrawCommand drawCommand = Indirects(nonuniformEXT(instanceAddresses.indirect)).dc[instanceAddresses.drawID];
const uint triangleID = gl_PrimitiveID + (drawCommand.indexID / 3);
Triangle triangle;
triangle.indices = Indices(nonuniformEXT(instanceAddresses.index)).i[triangleID];
for ( uint _ = 0; _ < 3; ++_ ) triangle.indices[_] += drawCommand.vertexID;
if ( 0 < instanceAddresses.vertex ) {
Vertices vertices = Vertices(nonuniformEXT(instanceAddresses.vertex));
for ( uint _ = 0; _ < 3; ++_ ) triangle.points[_] = vertices.v[triangle.indices[_]];
} else {
if ( 0 < instanceAddresses.position ) {
VPos buf = VPos(nonuniformEXT(instanceAddresses.position));
for ( uint _ = 0; _ < 3; ++_ ) triangle.points[_].position = buf.v[triangle.indices[_]];
}
if ( 0 < instanceAddresses.uv ) {
VUv buf = VUv(nonuniformEXT(instanceAddresses.uv));
for ( uint _ = 0; _ < 3; ++_ ) triangle.points[_].uv = buf.v[triangle.indices[_]];
}
if ( 0 < instanceAddresses.st ) {
VSt buf = VSt(nonuniformEXT(instanceAddresses.st));
for ( uint _ = 0; _ < 3; ++_ ) triangle.points[_].st = buf.v[triangle.indices[_]];
}
if ( 0 < instanceAddresses.normal ) {
VNormal buf = VNormal(nonuniformEXT(instanceAddresses.normal));
for ( uint _ = 0; _ < 3; ++_ ) triangle.points[_].normal = buf.v[triangle.indices[_]];
}
}
triangle.point.position = triangle.points[0].position * bary[0] + triangle.points[1].position * bary[1] + triangle.points[2].position * bary[2];
triangle.point.uv = triangle.points[0].uv * bary[0] + triangle.points[1].uv * bary[1] + triangle.points[2].uv * bary[2];
triangle.point.st = triangle.points[0].st * bary[0] + triangle.points[1].st * bary[1] + triangle.points[2].st * bary[2];
triangle.point.normal = triangle.points[0].normal * bary[0] + triangle.points[1].normal * bary[1] + triangle.points[2].normal * bary[2];
payload.hit = true;
payload.instanceID = instanceID;
payload.triangle = triangle;
}

View File

@ -0,0 +1,18 @@
#version 460
#extension GL_EXT_ray_tracing : enable
#pragma shader_stage(miss)
#define ADDRESS_ENABLED 1
#define COMPUTE 1
#define PBR 1
#define RAYTRACE 1
#define MAX_TEXTURES TEXTURES
#include "../common/macros.h"
#include "../common/structs.h"
layout(location = 0) rayPayloadInEXT RayTracePayload payload;
void main() {
payload.hit = false;
}

View File

@ -7,7 +7,7 @@
#include <uf/utils/memory/unordered_map.h>
#include <typeinfo>
#define UF_COMPONENT_POINTERED_USERDATA 0
#define UF_COMPONENT_POINTERED_USERDATA 1 //
namespace pod {
struct UF_API Component {

View File

@ -86,6 +86,10 @@ namespace pod {
alignas(8) uint64_t vertex{};
alignas(8) uint64_t index{};
alignas(8) uint64_t indirect{};
alignas(4) uint32_t drawID{};
alignas(4) uint32_t padding0{};
alignas(8) uint64_t position{};
alignas(8) uint64_t uv{};
@ -99,7 +103,7 @@ namespace pod {
alignas(8) uint64_t weights{};
alignas(8) uint64_t id{};
alignas(8) uint64_t padding{};
alignas(8) uint64_t padding1{};
};
struct Primitive {

View File

@ -264,7 +264,7 @@ 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 ).dump(1,'\t'));
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 );

View File

@ -464,7 +464,7 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
uf::stl::string uf::graph::print( const pod::Graph& graph ) {
uf::stl::stringstream ss;
#if 0
#if 1
ss << "Graph Data:"
"\n\tImages: " << graph.images.size() << ""
"\n\tTextures: " << graph.textures.size() << ""
@ -487,8 +487,8 @@ uf::stl::string uf::graph::print( const pod::Graph& graph ) {
uf::Serializer uf::graph::stats( const pod::Graph& graph ) {
ext::json::Value json;
#if 0
size_t memoryTextures = sizeof(pod::Texture::Storage) * graph.textures.size();
size_t memoryMaterials = sizeof(pod::Material::Storage) * graph.materials.size();
size_t memoryTextures = sizeof(pod::Texture) * graph.textures.size();
size_t memoryMaterials = sizeof(pod::Material) * graph.materials.size();
size_t memoryLights = sizeof(pod::Light) * graph.lights.size();
size_t memoryImages = 0;
size_t memoryMeshes = 0;

View File

@ -359,25 +359,31 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::M
// grab addresses
{
pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer( mesh.indirect ).data();
for ( size_t i = 0; i < mesh.indirect.count; ++i ) {
auto instanceID = drawCommands[i].instanceID;
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();
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();
else if ( attribute.descriptor.name == "uv" ) instanceAddresses.uv = graphic.buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "color" ) instanceAddresses.color = graphic.buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "st" ) instanceAddresses.st = graphic.buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "normal" ) instanceAddresses.normal = graphic.buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "tangent" ) instanceAddresses.tangent = graphic.buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "joints" ) instanceAddresses.joints = graphic.buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "weights" ) instanceAddresses.weights = graphic.buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "id" ) instanceAddresses.id = graphic.buffers.at(attribute.buffer).getAddress();
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)*/;
}
}
}
@ -385,6 +391,13 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::M
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
@ -717,6 +730,8 @@ void uf::graph::process( pod::Graph& graph ) {
*/
}
uf::graph::storage.instanceAddresses.keys = uf::graph::storage.instances.keys;
}
void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) {
auto& node = graph.nodes[index];
@ -919,9 +934,6 @@ 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;
// corner.x = abs(corner.x);
// corner.y = abs(corner.y);
// corner.z = abs(corner.z);
metadataJson["system"]["physics"]["center"] = uf::vector::encode( center );
metadataJson["system"]["physics"]["corner"] = uf::vector::encode( corner );

View File

@ -482,7 +482,7 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
#endif
#if UF_USE_MESHOPT
// cleanup if blender's exporter is poopy
if ( graph.metadata["exporter"]["optimize"].as<bool>(true) || graph.metadata["exporter"]["optimize"].as<uf::stl::string>("") == "tagged" ) {
if ( graph.metadata["exporter"]["optimize"].as<bool>(false) || graph.metadata["exporter"]["optimize"].as<uf::stl::string>("") == "tagged" ) {
UF_MSG_DEBUG( "Optimizing meshes..." );
for ( auto& keyName : graph.meshes ) {
size_t level = SIZE_MAX;

View File

@ -291,6 +291,10 @@ void ext::reactphysics::attach( pod::PhysicsState& state ) {
state.body->setType(rp3d::BodyType::STATIC);
}
if ( state.stats.gravity == pod::Vector3f{0,0,0} ) {
state.body->enableGravity(false);
}
auto& material = collider->getMaterial();
material.setBounciness(0);
@ -406,7 +410,13 @@ void ext::reactphysics::syncFrom( float interp ) {
auto* body = ::world->getRigidBody(i); if ( !body ) continue;
uf::Object* object = (uf::Object*) body->getUserData(); if ( !object ) continue;
auto& state = object->getComponent<pod::PhysicsState>();;
auto& state = object->getComponent<pod::PhysicsState>();
if ( !state.object ) {
state.object = object;
//continue;
}
auto& transform = state.object->getComponent<pod::Transform<>>();
auto& physics = state.object->getComponent<pod::Physics>();

View File

@ -123,8 +123,8 @@ void ext::vulkan::Buffer::initialize( const void* data, VkDeviceSize length, VkB
if ( data && length ) update( data, length, stage );
}
bool ext::vulkan::Buffer::update( const void* data, VkDeviceSize length, bool stage ) const {
if ( !data || !length ) return false;
// if ( !data || !length ) return false;
if ( !length ) return false;
if ( length > allocationInfo.size ) {
UF_MSG_DEBUG("LENGTH OF " << length << " EXCEEDS BUFFER SIZE " << allocationInfo.size );
Buffer& b = *const_cast<Buffer*>(this);
@ -132,6 +132,7 @@ bool ext::vulkan::Buffer::update( const void* data, VkDeviceSize length, bool st
b.initialize( data, length, usage, memoryProperties, stage );
return true;
}
if ( !data ) return false;
if ( !stage ) {
void* map = this->map();
memcpy(map, data, length);

View File

@ -425,7 +425,6 @@ void ext::vulkan::Pipeline::record( const Graphic& graphic, const GraphicDescrip
vkCmdBindPipeline(commandBuffer, bindPoint, pipeline);
if ( bindPoint == VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR ) {
UF_MSG_DEBUG("vkCmdTraceRaysKHR");
uf::renderer::vkCmdTraceRaysKHR(
commandBuffer,
&sbtEntries[0],
@ -512,8 +511,7 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
}
}
auto& textures = !shader->textures.empty() ? shader->textures : graphic.material.textures;
for ( auto& texture : textures ) {
for ( auto& texture : shader->textures ) {
infos.image.emplace_back(texture.descriptor);
switch ( texture.viewType ) {
case VK_IMAGE_VIEW_TYPE_2D: infos.image2D.emplace_back(texture.descriptor); break;
@ -523,6 +521,17 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
default: infos.imageUnknown.emplace_back(texture.descriptor); break;
}
}
for ( auto& texture : graphic.material.textures ) {
infos.image.emplace_back(texture.descriptor);
switch ( texture.viewType ) {
case VK_IMAGE_VIEW_TYPE_2D: infos.image2D.emplace_back(texture.descriptor); break;
case VK_IMAGE_VIEW_TYPE_2D_ARRAY: infos.image2DA.emplace_back(texture.descriptor); break;
case VK_IMAGE_VIEW_TYPE_CUBE: infos.imageCube.emplace_back(texture.descriptor); break;
case VK_IMAGE_VIEW_TYPE_3D: infos.image3D.emplace_back(texture.descriptor); break;
default: infos.imageUnknown.emplace_back(texture.descriptor); break;
}
}
for ( auto& sampler : graphic.material.samplers ) {
infos.sampler.emplace_back(sampler.descriptor.info);
}
@ -1169,12 +1178,13 @@ void ext::vulkan::Graphic::generateBottomAccelerationStructures() {
indexInput.count = drawCommand.indices;
auto& blasData = blasDatas.emplace_back();
// blasData.as.drawID = i;
blasData.as.instanceID = drawCommand.instanceID;
VkAccelerationStructureGeometryKHR& asGeom = blasData.asGeom.emplace_back();
asGeom.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
asGeom.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
asGeom.flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
asGeom.flags = VK_GEOMETRY_OPAQUE_BIT_KHR | VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR;
VkAccelerationStructureGeometryTrianglesDataKHR& triangles = asGeom.geometry.triangles;
triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR;
@ -1287,7 +1297,6 @@ void ext::vulkan::Graphic::generateBottomAccelerationStructures() {
blasBufferOffset += blasData.sizeInfo.accelerationStructureSize;
// UF_MSG_DEBUG("vkCreateAccelerationStructureKHR");
VK_CHECK_RESULT(uf::renderer::vkCreateAccelerationStructureKHR(device, &createInfo, nullptr, &blasData.as.handle));
VkAccelerationStructureDeviceAddressInfoKHR accelerationDeviceAddressInfo{};
@ -1301,7 +1310,6 @@ void ext::vulkan::Graphic::generateBottomAccelerationStructures() {
blasData.buildInfo.scratchData.deviceAddress = scratchBuffer.getAddress();
VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, uf::renderer::Device::QueueEnum::COMPUTE);
// UF_MSG_DEBUG("vkCmdBuildAccelerationStructuresKHR");
uf::renderer::vkCmdBuildAccelerationStructuresKHR(
commandBuffer,
1,
@ -1318,7 +1326,9 @@ void ext::vulkan::Graphic::generateBottomAccelerationStructures() {
}
void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vector<uf::renderer::Graphic*>& graphics, const uf::stl::vector<pod::Instance>& instances ) {
auto& device = *this->device;
// graphic.process = false;
bool rebuild = false;
bool update = this->accelerationStructures.top.handle != VK_NULL_HANDLE;
VkPhysicalDeviceAccelerationStructurePropertiesKHR acclerationStructureProperties{};
VkPhysicalDeviceRayTracingPipelinePropertiesKHR rayTracingPipelineProperties{};
@ -1334,84 +1344,45 @@ void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vect
vkGetPhysicalDeviceProperties2(device.physicalDevice, &deviceProperties2);
}
uf::renderer::Buffer instanceBuffer;
uf::renderer::Buffer scratchBuffer;
uf::renderer::Buffer tlasBuffer;
uf::stl::vector<VkAccelerationStructureInstanceKHR> instancesVK; instancesVK.reserve( instances.size() );
uf::stl::vector<pod::InstanceAddresses> instanceAddresseses( instances.size() );
for ( auto& graphic : graphics ) {
for ( auto& blas : graphic->accelerationStructures.bottoms ) {
size_t instanceID = blas.instanceID;
auto instanceKeyName = std::to_string(instanceID);
auto& instanceAddresses = instanceAddresseses[instanceID];
if ( graphic->descriptor.inputs.vertex.count ) {
if ( 0 <= graphic->descriptor.inputs.vertex.interleaved ) {
instanceAddresses.vertex = graphic->buffers.at(graphic->descriptor.inputs.vertex.interleaved).getAddress();
} 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();
else if ( attribute.descriptor.name == "uv" ) instanceAddresses.uv = graphic->buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "color" ) instanceAddresses.color = graphic->buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "st" ) instanceAddresses.st = graphic->buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "normal" ) instanceAddresses.normal = graphic->buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "tangent" ) instanceAddresses.tangent = graphic->buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "joints" ) instanceAddresses.joints = graphic->buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "weights" ) instanceAddresses.weights = graphic->buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "id" ) instanceAddresses.id = graphic->buffers.at(attribute.buffer).getAddress();
}
}
}
if ( graphic->descriptor.inputs.index.count ) {
if ( 0 <= graphic->descriptor.inputs.index.interleaved ) {
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();
}
}
auto& instanceVK = instancesVK.emplace_back();
instanceVK.transform = {
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f
};
auto mat = instances[instanceID].model;
mat = uf::matrix::transpose(mat);
auto& instanceVK = instancesVK.emplace_back();
memcpy(&instanceVK.transform, &mat, sizeof(instanceVK.transform));
instanceVK.instanceCustomIndex = blas.instanceID;
instanceVK.accelerationStructureReference = blas.deviceAddress;
instanceVK.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
instanceVK.flags = 0; // VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
instanceVK.mask = 0xFF;
instanceVK.instanceShaderBindingTableRecordOffset = 0;
}
}
// do not stage, because apparently vkQueueWaitIdle doesn't actually wait for the transfer to complete
size_t instanceIndex = this->initializeBuffer(
(const void*) instancesVK.data(), instancesVK.size() * sizeof(VkAccelerationStructureInstanceKHR),
uf::renderer::enums::Buffer::ADDRESS | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, false
);
size_t instanceBufferAddress = this->buffers[instanceIndex].getAddress();
// build SBT
if ( !this->material.hasShader("ray:gen", uf::renderer::settings::pipelines::names::rt) ) {
uf::stl::string rayGenShaderFilename = uf::io::root+"/shaders/raytrace/shader.gen.spv";
uf::stl::string rayMissShaderFilename = uf::io::root+"/shaders/raytrace/shader.miss.spv";
uf::stl::string rayHitShaderFilename = uf::io::root+"/shaders/raytrace/shader.hit.spv";
this->material.attachShader(rayGenShaderFilename, VK_SHADER_STAGE_RAYGEN_BIT_KHR, uf::renderer::settings::pipelines::names::rt);
this->material.attachShader(rayMissShaderFilename, VK_SHADER_STAGE_MISS_BIT_KHR, uf::renderer::settings::pipelines::names::rt);
this->material.attachShader(rayHitShaderFilename, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, uf::renderer::settings::pipelines::names::rt);
size_t instanceIndex{};
size_t tlasBufferIndex{};
if ( !update ) {
instanceIndex = this->initializeBuffer(
(const void*) instancesVK.data(), instancesVK.size() * sizeof(VkAccelerationStructureInstanceKHR),
uf::renderer::enums::Buffer::ADDRESS | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, false
);
} else {
for ( size_t i = 0; i < buffers.size(); ++i ) {
if ( !(this->buffers[i].usage & (uf::renderer::enums::Buffer::ADDRESS | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR)) ) continue;
instanceIndex = i;
break;
}
rebuild = rebuild || this->updateBuffer( (const void*) instancesVK.data(), instancesVK.size() * sizeof(VkAccelerationStructureInstanceKHR), instanceIndex, false );
}
size_t instanceBufferAddress = this->buffers[instanceIndex].getAddress();
{
VkBuildAccelerationStructureFlagsKHR flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
bool update = false;
VkBuildAccelerationStructureFlagsKHR flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR | VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR;
uint32_t countInstance = instancesVK.size();
auto& tlas = this->accelerationStructures.top;
@ -1431,7 +1402,6 @@ void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vect
buildInfo.srcAccelerationStructure = VK_NULL_HANDLE;
VkAccelerationStructureBuildSizesInfoKHR sizeInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR};
UF_MSG_DEBUG("vkGetAccelerationStructureBuildSizesKHR");
uf::renderer::vkGetAccelerationStructureBuildSizesKHR(
device,
VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
@ -1441,31 +1411,38 @@ void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vect
);
// create BLAS buffer and handle
size_t tlasBufferIndex = this->initializeBuffer( NULL, sizeInfo.accelerationStructureSize, uf::renderer::enums::Buffer::ACCELERATION_STRUCTURE | uf::renderer::enums::Buffer::ADDRESS );
auto& tlasBuffer = this->buffers[tlasBufferIndex]; {
auto& shader = this->material.getShader("ray:gen", uf::renderer::settings::pipelines::names::rt);
shader.buffers.emplace_back( this->buffers[tlasBufferIndex].alias() );
auto tlasBufferUsageFlags = uf::renderer::enums::Buffer::ACCELERATION_STRUCTURE | uf::renderer::enums::Buffer::ADDRESS;
if ( !update ) {
tlasBufferIndex = this->initializeBuffer( NULL, sizeInfo.accelerationStructureSize, tlasBufferUsageFlags);
} else {
for ( int i = buffers.size() - 1; i >= 0; --i ) {
if ( !(this->buffers[i].usage & tlasBufferUsageFlags) ) continue;
tlasBufferIndex = i;
break;
}
rebuild = rebuild || this->updateBuffer( NULL, sizeInfo.accelerationStructureSize, tlasBufferIndex );
}
VkAccelerationStructureCreateInfoKHR createInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR};
createInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
createInfo.size = sizeInfo.accelerationStructureSize;
createInfo.buffer = tlasBuffer.buffer;
if ( !update ) {
VkAccelerationStructureCreateInfoKHR createInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR};
createInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
createInfo.size = sizeInfo.accelerationStructureSize;
createInfo.buffer = this->buffers[tlasBufferIndex].buffer;
UF_MSG_DEBUG("vkCreateAccelerationStructureKHR");
VK_CHECK_RESULT(uf::renderer::vkCreateAccelerationStructureKHR(device, &createInfo, nullptr, &tlas.handle));
VK_CHECK_RESULT(uf::renderer::vkCreateAccelerationStructureKHR(device, &createInfo, nullptr, &tlas.handle));
VkAccelerationStructureDeviceAddressInfoKHR accelerationDeviceAddressInfo{};
accelerationDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR;
accelerationDeviceAddressInfo.accelerationStructure = tlas.handle;
tlas.deviceAddress = uf::renderer::vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo);
VkAccelerationStructureDeviceAddressInfoKHR accelerationDeviceAddressInfo{};
accelerationDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR;
accelerationDeviceAddressInfo.accelerationStructure = tlas.handle;
tlas.deviceAddress = uf::renderer::vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo);
}
// write to BLAS
uf::renderer::Buffer scratchBuffer;
scratchBuffer.alignment = acclerationStructureProperties.minAccelerationStructureScratchOffsetAlignment;
scratchBuffer.initialize( NULL, sizeInfo.buildScratchSize, uf::renderer::enums::Buffer::STORAGE | uf::renderer::enums::Buffer::ADDRESS );
UF_MSG_DEBUG("Scratch buffer size: " << sizeInfo.buildScratchSize);
buildInfo.srcAccelerationStructure = VK_NULL_HANDLE;
buildInfo.srcAccelerationStructure = update ? tlas.handle : VK_NULL_HANDLE;
buildInfo.dstAccelerationStructure = tlas.handle;
buildInfo.scratchData.deviceAddress = scratchBuffer.getAddress();
@ -1473,7 +1450,6 @@ void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vect
const VkAccelerationStructureBuildRangeInfoKHR* rangeInfo = &buildOffsetInfo;
VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, uf::renderer::Device::QueueEnum::COMPUTE);
UF_MSG_DEBUG("vkCmdBuildAccelerationStructuresKHR");
uf::renderer::vkCmdBuildAccelerationStructuresKHR(
commandBuffer,
1,
@ -1485,98 +1461,41 @@ void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vect
scratchBuffer.destroy();
}
// should be placed outside, in the responsible scene/rendermode
#if 1
{
auto& shader = this->material.getShader("ray:gen", uf::renderer::settings::pipelines::names::rt);
auto& image = shader.textures.emplace_back();
image.fromBuffers( NULL, 0, uf::renderer::enums::Format::R8G8B8A8_UNORM, uf::renderer::settings::width, uf::renderer::settings::height, 1, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
this->descriptor.pipeline = uf::renderer::settings::pipelines::names::rt;
this->descriptor.inputs.width = image.width;
this->descriptor.inputs.height = image.height;
//
struct UniformDescriptor {
struct Matrices {
alignas(16) pod::Matrix4f view;
alignas(16) pod::Matrix4f projection;
alignas(16) pod::Matrix4f iView;
alignas(16) pod::Matrix4f iProjection;
alignas(16) pod::Matrix4f iProjectionView;
alignas(16) pod::Vector4f eyePos;
} matrices[2];
} uniforms;
auto& scene = uf::scene::getCurrentScene();
auto& controller = scene.getController();
auto& camera = controller.getComponent<uf::Camera>();
for ( auto i = 0; i < 2; ++i ) {
uniforms.matrices[i] = UniformDescriptor::Matrices{
.view = camera.getView(i),
.projection = camera.getProjection(i),
.iView = uf::matrix::inverse( camera.getView(i) ),
.iProjection = uf::matrix::inverse( camera.getProjection(i) ),
.iProjectionView = uf::matrix::inverse( camera.getProjection(i) * camera.getView(i) ),
.eyePos = camera.getEye( i ),
};
}
bool found = false;
for ( auto& buffer : shader.buffers ) {
if ( !(buffer.usage & uf::renderer::enums::Buffer::UNIFORM) ) continue;
if ( buffer.allocationInfo.size != sizeof(UniformDescriptor) ) continue;
found = true;
break;
}
if ( !found ) shader.initializeBuffer( (const void*) &uniforms, sizeof(UniformDescriptor), uf::renderer::enums::Buffer::UNIFORM );
//
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
size_t maxLights = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["lights"]["max"].as<size_t>(512);
size_t maxTextures2D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["2D"].as<size_t>(512);
size_t maxTexturesCube = 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>(1);
size_t maxCascades = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["vxgi"]["cascades"].as<size_t>(16);
// shader.buffers.emplace_back( uf::graph::storage.buffers.camera.alias() );
// shader.buffers.emplace_back( uf::graph::storage.buffers.joint.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.instance.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() );
shader.buffers.emplace_back( uf::graph::storage.buffers.instanceAddresses.alias() );
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] = maxTextures2D);
else if ( sc.name == "CUBEMAPS" ) sc.value.ui = (specializationConstants[sc.index] = maxTexturesCube);
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 = maxTextures2D;
else if ( tx.name == "samplerCubemaps" ) layout.descriptorCount = maxTexturesCube;
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;
}
}
if ( rebuild ) {
auto& renderMode = ext::vulkan::getRenderMode( descriptor.renderMode, true );
renderMode.rebuild = true;
}
// UF_MSG_DEBUG("Building pipeline...");
this->initializePipeline();
this->initialized = true;
this->process = true;
// build SBT
if ( !this->material.hasShader("ray:gen", uf::renderer::settings::pipelines::names::rt) ) {
{
uf::stl::string rayGenShaderFilename = uf::io::root+"/shaders/raytrace/shader.ray-gen.spv";
uf::stl::string rayMissShaderFilename = uf::io::root+"/shaders/raytrace/shader.ray-miss.spv";
uf::stl::string rayHitClosestShaderFilename = uf::io::root+"/shaders/raytrace/shader.ray-hit-closest.spv";
uf::stl::string rayHitAnyShaderFilename = uf::io::root+"/shaders/raytrace/shader.ray-hit-any.spv";
#endif
this->material.attachShader(rayGenShaderFilename, VK_SHADER_STAGE_RAYGEN_BIT_KHR, uf::renderer::settings::pipelines::names::rt);
this->material.attachShader(rayMissShaderFilename, VK_SHADER_STAGE_MISS_BIT_KHR, uf::renderer::settings::pipelines::names::rt);
this->material.attachShader(rayHitClosestShaderFilename, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, uf::renderer::settings::pipelines::names::rt);
// this->material.attachShader(rayHitAnyShaderFilename, VK_SHADER_STAGE_ANY_HIT_BIT_KHR, uf::renderer::settings::pipelines::names::rt);
}
{
auto& shader = this->material.getShader("ray:gen", uf::renderer::settings::pipelines::names::rt);
UF_MSG_DEBUG("Generated acceleration structures for " << this << " (" << this->descriptor.renderMode << ")");
auto& image = shader.textures.emplace_back();
image.fromBuffers( NULL, 0, uf::renderer::enums::Format::R8G8B8A8_UNORM, uf::renderer::settings::width, uf::renderer::settings::height, 1, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
this->descriptor.pipeline = uf::renderer::settings::pipelines::names::rt;
this->descriptor.inputs.width = image.width;
this->descriptor.inputs.height = image.height;
//
shader.buffers.emplace_back( this->buffers[tlasBufferIndex].alias() );
}
}
if ( !update ) UF_MSG_DEBUG("Generated acceleration structures for " << this << " (" << this->descriptor.renderMode << ")");
}
bool ext::vulkan::Graphic::hasPipeline( const GraphicDescriptor& descriptor ) const {
return pipelines.count( descriptor ) > 0;

View File

@ -555,7 +555,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
for ( size_t eye = 0; eye < metadata.eyes; ++eye ) {
size_t currentPass = 0;
size_t currentDraw = 0;
for ( auto graphic : graphics ) {
if ( !settings::pipelines::rt ) for ( auto graphic : graphics ) {
// only draw graphics that are assigned to this type of render mode
if ( graphic->descriptor.renderMode != this->getName() ) continue;
ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentSubpass);
@ -573,7 +573,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
}
vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE); ++currentPass; ++currentSubpass;
// deferred post-processing lighting pass
{
if ( !settings::pipelines::rt ) {
ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(blitter.descriptor, currentSubpass);
blitter.record(commands[i], descriptor, eye, currentDraw++);
}

View File

@ -258,6 +258,8 @@ void ext::PlayerBehavior::tick( uf::Object& self ) {
}
}
if ( collider.stats.gravity == pod::Vector3f{0,0,0} ) stats.noclipped = true;
struct {
float move = 4;
float walk = 1;
@ -274,8 +276,8 @@ void ext::PlayerBehavior::tick( uf::Object& self ) {
speed.air = metadata.movement.air;
if ( stats.noclipped ) {
speed.move *= 4.0;
speed.run *= 2.0;
speed.move *= 1.5;
speed.run *= 1.5;
}
if ( !stats.floored || stats.noclipped ) speed.friction = 1;
if ( stats.noclipped ) physics.linear.velocity = {};
@ -318,7 +320,8 @@ void ext::PlayerBehavior::tick( uf::Object& self ) {
} else
#endif
// un-flatted if noclipped
if ( stats.noclipped ){
if ( stats.noclipped || collider.stats.gravity == pod::Vector3f{0,0,0} ){
translator.forward.y += cameraTransform.forward.y;
translator.forward = uf::vector::normalize( translator.forward );
}
@ -328,6 +331,7 @@ void ext::PlayerBehavior::tick( uf::Object& self ) {
TIMER(0.25, keys.vee && ) {
bool state = !stats.noclipped;
metadata.system.noclipped = state;
if ( collider.body ) collider.body->enableGravity(!state);
UF_MSG_DEBUG( (state ? "En" : "Dis") << "abled noclip: " << uf::vector::toString(transform.position));
#if 0

View File

@ -16,92 +16,10 @@
#include "../light/behavior.h"
#include "../scene/behavior.h"
#define TEST 0
UF_BEHAVIOR_REGISTER_CPP(ext::RayTraceSceneBehavior)
UF_BEHAVIOR_TRAITS_CPP(ext::RayTraceSceneBehavior, ticks = true, renders = false, multithread = false)
#define this (&self)
void ext::RayTraceSceneBehavior::initialize( uf::Object& self ) {
#if TEST
auto& metadata = this->getComponent<ext::RayTraceSceneBehavior::Metadata>();
auto& graphic = this->getComponent<uf::renderer::Graphic>(); //metadata.renderer.graphic;
auto& mesh = this->getComponent<uf::Mesh>();
mesh.bind<pod::Vertex_3F>();
mesh.insertVertices<pod::Vertex_3F>({
{-1.0f,-1.0f,-1.0f,},
{-1.0f,-1.0f, 1.0f,},
{-1.0f, 1.0f, 1.0f,},
{1.0f, 1.0f,-1.0f,},
{-1.0f,-1.0f,-1.0f,},
{-1.0f, 1.0f,-1.0f,},
{1.0f,-1.0f, 1.0f,},
{-1.0f,-1.0f,-1.0f,},
{1.0f,-1.0f,-1.0f,},
{1.0f, 1.0f,-1.0f,},
{1.0f,-1.0f,-1.0f,},
{-1.0f,-1.0f,-1.0f,},
{-1.0f,-1.0f,-1.0f,},
{-1.0f, 1.0f, 1.0f,},
{-1.0f, 1.0f,-1.0f,},
{1.0f,-1.0f, 1.0f,},
{-1.0f,-1.0f, 1.0f,},
{-1.0f,-1.0f,-1.0f,},
{-1.0f, 1.0f, 1.0f,},
{-1.0f,-1.0f, 1.0f,},
{1.0f,-1.0f, 1.0f,},
{1.0f, 1.0f, 1.0f,},
{1.0f,-1.0f,-1.0f,},
{1.0f, 1.0f,-1.0f,},
{1.0f,-1.0f,-1.0f,},
{1.0f, 1.0f, 1.0f,},
{1.0f,-1.0f, 1.0f,},
{1.0f, 1.0f, 1.0f,},
{1.0f, 1.0f,-1.0f,},
{-1.0f, 1.0f,-1.0f,},
{1.0f, 1.0f, 1.0f,},
{-1.0f, 1.0f,-1.0f,},
{-1.0f, 1.0f, 1.0f,},
{1.0f, 1.0f, 1.0f,},
{-1.0f, 1.0f, 1.0f,},
{1.0f,-1.0f, 1.0f,},
});
mesh.updateDescriptor();
graphic.initialize("Compute");
graphic.initializeMesh( mesh );
uf::stl::vector<pod::Instance> instances;
auto& instance = instances.emplace_back();
instance.model = uf::matrix::identity();
graphic.generateBottomAccelerationStructures();
graphic.generateTopAccelerationStructure( { &graphic }, instances );
auto& shader = graphic.material.getShader("ray:gen", uf::renderer::settings::pipelines::names::rt);
auto& image = shader.textures.front();
if ( !uf::renderer::hasRenderMode("Compute", true) ) {
auto* renderMode = new uf::renderer::RenderTargetRenderMode;
renderMode->setTarget("Compute");
renderMode->metadata.json["shaders"]["vertex"] = "/shaders/display/renderTargetSimple.vert.spv";
renderMode->metadata.json["shaders"]["fragment"] = "/shaders/display/renderTargetSimple.frag.spv";
renderMode->blitter.descriptor.subpass = 1;
renderMode->metadata.type = uf::renderer::settings::pipelines::names::rt;
renderMode->metadata.pipelines.emplace_back(uf::renderer::settings::pipelines::names::rt);
renderMode->execute = false;
uf::renderer::addRenderMode( renderMode, "Compute" );
} else {
auto& renderMode = uf::renderer::getRenderMode("Compute", true);
auto& blitter = *renderMode.getBlitter();
if ( blitter.material.hasShader("fragment") ) {
auto& shader = blitter.material.getShader("fragment");
shader.textures.emplace_back().aliasTexture( image );
}
}
#else
if ( !uf::renderer::hasRenderMode("Compute", true) ) {
auto* renderMode = new uf::renderer::RenderTargetRenderMode;
renderMode->setTarget("Compute");
@ -113,72 +31,82 @@ void ext::RayTraceSceneBehavior::initialize( uf::Object& self ) {
renderMode->execute = false;
uf::renderer::addRenderMode( renderMode, "Compute" );
}
#endif
}
void ext::RayTraceSceneBehavior::tick( uf::Object& self ) {
auto& metadata = this->getComponent<ext::RayTraceSceneBehavior::Metadata>();
#if !TEST
if ( !metadata.renderer.bound ) {
auto instances = uf::graph::storage.instances.flatten();
if ( instances.empty() ) return;
auto instances = uf::graph::storage.instances.flatten();
if ( instances.empty() ) return;
uf::stl::vector<uf::Graphic*> graphics;
this->process([&]( uf::Entity* entity ) {
if ( !entity->hasComponent<uf::Graphic>() ) return;
graphics.emplace_back(entity->getComponentPointer<uf::Graphic>());
});
if ( graphics.empty() ) return;
uf::stl::vector<uf::Graphic*> graphics;
this->process([&]( uf::Entity* entity ) {
if ( !entity->hasComponent<uf::Graphic>() ) return;
graphics.emplace_back(entity->getComponentPointer<uf::Graphic>());
});
auto& graphic = this->getComponent<uf::renderer::Graphic>();
graphic.initialize("Compute");
graphic.generateTopAccelerationStructure( graphics, instances );
if ( graphics.empty() ) return;
auto& graphic = this->getComponent<uf::renderer::Graphic>();
if ( !metadata.renderer.bound ) graphic.initialize("Compute");
graphic.generateTopAccelerationStructure( graphics, instances );
UF_MSG_DEBUG( graphics.size() << " " << instances.size() );
if ( !metadata.renderer.bound ) {
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);
auto& scene = uf::scene::getCurrentScene();
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
size_t maxLights = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["lights"]["max"].as<size_t>(512);
size_t maxTextures2D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["2D"].as<size_t>(512);
size_t maxTexturesCube = 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>(1);
size_t maxCascades = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["vxgi"]["cascades"].as<size_t>(16);
metadata.renderer.bound = true;
return;
shader.buffers.emplace_back( uf::graph::storage.buffers.instance.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() );
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] = maxTextures2D);
else if ( sc.name == "CUBEMAPS" ) sc.value.ui = (specializationConstants[sc.index] = maxTexturesCube);
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 = maxTextures2D;
else if ( tx.name == "samplerCubemaps" ) layout.descriptorCount = maxTexturesCube;
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;
}
}
metadata.renderer.bound = true;
}
if ( graphic.material.hasShader("ray:hit:closest", uf::renderer::settings::pipelines::names::rt) ) {
auto& shader = graphic.material.getShader("ray:hit:closest", uf::renderer::settings::pipelines::names::rt);
shader.buffers.emplace_back( uf::graph::storage.buffers.instanceAddresses.alias() );
}
if ( graphic.material.hasShader("ray:hit:any", uf::renderer::settings::pipelines::names::rt) ) {
auto& shader = graphic.material.getShader("ray:hit:any", uf::renderer::settings::pipelines::names::rt);
shader.buffers.emplace_back( uf::graph::storage.buffers.instanceAddresses.alias() );
}
graphic.process = false;
}
/* Update lights */ {
ext::ExtSceneBehavior::bindBuffers( *this, graphic, "ray:gen", uf::renderer::settings::pipelines::names::rt );
}
if ( !metadata.renderer.bound ) return;
#endif
auto& graphic = this->getComponent<uf::renderer::Graphic>();
auto& shader = graphic.material.getShader("ray:gen", uf::renderer::settings::pipelines::names::rt);
auto& image = shader.textures.front();
struct UniformDescriptor {
struct Matrices {
alignas(16) pod::Matrix4f view;
alignas(16) pod::Matrix4f projection;
alignas(16) pod::Matrix4f iView;
alignas(16) pod::Matrix4f iProjection;
alignas(16) pod::Matrix4f iProjectionView;
alignas(16) pod::Vector4f eyePos;
} matrices[2];
} uniforms;
auto& scene = uf::scene::getCurrentScene();
auto& controller = scene.getController();
auto& camera = controller.getComponent<uf::Camera>();
for ( auto i = 0; i < 2; ++i ) {
uniforms.matrices[i] = UniformDescriptor::Matrices{
.view = camera.getView(i),
.projection = camera.getProjection(i),
.iView = uf::matrix::inverse( camera.getView(i) ),
.iProjection = uf::matrix::inverse( camera.getProjection(i) ),
.iProjectionView = uf::matrix::inverse( camera.getProjection(i) * camera.getView(i) ),
.eyePos = camera.getEye( i ),
};
}
for ( auto& buffer : shader.buffers ) {
if ( !(buffer.usage & uf::renderer::enums::Buffer::UNIFORM) ) continue;
if ( buffer.allocationInfo.size != sizeof(UniformDescriptor) ) continue;
buffer.update( (const void*) &uniforms, sizeof(UniformDescriptor) );
break;
}
auto& renderMode = uf::renderer::getRenderMode("Compute", true);
auto& blitter = *renderMode.getBlitter();
if ( blitter.material.hasShader("fragment") ) {
@ -186,6 +114,7 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) {
if ( shader.textures.empty() ) {
shader.textures.emplace_back().aliasTexture( image );
renderMode.execute = true;
graphic.process = true;
}
}
@ -212,7 +141,7 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) {
void ext::RayTraceSceneBehavior::render( uf::Object& self ){}
void ext::RayTraceSceneBehavior::destroy( uf::Object& self ){
auto& metadata = this->getComponent<ext::RayTraceSceneBehavior::Metadata>();
auto& graphic = this->getComponent<uf::renderer::Graphic>(); // metadata.renderer.graphic;
auto& graphic = this->getComponent<uf::renderer::Graphic>();
graphic.destroy();
}

View File

@ -687,7 +687,7 @@ void ext::ExtSceneBehavior::Metadata::deserialize( uf::Object& self, uf::Seriali
}
}
void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string& renderModeName, bool isCompute ) {
void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string& renderModeName, const uf::stl::string& shaderType, const uf::stl::string& shaderPipeline ) {
auto& graph = this->getGraph();
auto& controller = this->getController();
auto& camera = controller.getComponent<uf::Camera>();
@ -700,6 +700,20 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string
auto& renderMode = uf::renderer::getRenderMode(renderModeName, true);
auto blitters = renderMode.getBlitters();
bindBuffers( self, *blitters.front(), shaderType, shaderPipeline );
}
void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, uf::renderer::Graphic& graphic, const uf::stl::string& shaderType, const uf::stl::string& shaderPipeline ) {
auto& graph = this->getGraph();
auto& controller = this->getController();
auto& camera = controller.getComponent<uf::Camera>();
auto& controllerMetadata = controller.getComponent<uf::Serializer>();
auto& controllerTransform = controller.getComponent<pod::Transform<>>();
auto& metadata = this->getComponent<ext::ExtSceneBehavior::Metadata>();
auto& metadataVxgi = this->getComponent<ext::VoxelizerSceneBehavior::Metadata>();
auto& metadataJson = this->getComponent<uf::Serializer>();
if ( !graphic.initialized ) return;
#if UF_USE_VULKAN
struct UniformDescriptor {
struct Matrices {
@ -871,29 +885,25 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string
uniforms.useLightmaps = metadata.light.useLightmaps;
}
for ( auto* blitter : blitters ) {
auto& graphic = *blitter;
if ( !graphic.initialized ) continue;
uf::stl::vector<VkImage> previousTextures;
for ( auto& texture : graphic.material.textures ) previousTextures.emplace_back(texture.image);
graphic.material.textures.clear();
uf::stl::vector<VkImage> previousTextures;
for ( auto& texture : graphic.material.textures ) previousTextures.emplace_back(texture.image);
graphic.material.textures.clear();
// attach our textures to the graphic
for ( auto& t : textures2D ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : texturesCube ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : textures3D ) graphic.material.textures.emplace_back().aliasTexture(t);
// attach our textures to the graphic
for ( auto& t : textures2D ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : texturesCube ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : textures3D ) graphic.material.textures.emplace_back().aliasTexture(t);
// trigger an update when we have differing bound texture sizes
bool shouldUpdate = metadata.shader.invalidated || graphic.material.textures.size() != previousTextures.size();
for ( uint32_t i = 0; !shouldUpdate && i < previousTextures.size() && i < graphic.material.textures.size(); ++i ) {
if ( previousTextures[i] != graphic.material.textures[i].image ) shouldUpdate = true;
}
if ( shouldUpdate ) graphic.updatePipelines();
auto& shader = graphic.material.getShader(isCompute ? "compute" : "fragment");
shader.updateBuffer( (const void*) &uniforms, sizeof(uniforms), shader.getUniformBuffer("UBO") );
// trigger an update when we have differing bound texture sizes
bool shouldUpdate = metadata.shader.invalidated || graphic.material.textures.size() != previousTextures.size();
for ( uint32_t i = 0; !shouldUpdate && i < previousTextures.size() && i < graphic.material.textures.size(); ++i ) {
if ( previousTextures[i] != graphic.material.textures[i].image ) shouldUpdate = true;
}
if ( shouldUpdate ) graphic.updatePipelines();
auto& shader = graphic.material.getShader(shaderType, shaderPipeline);
shader.updateBuffer( (const void*) &uniforms, sizeof(uniforms), shader.getUniformBuffer("UBO") );
#endif
}
#undef this

View File

@ -5,6 +5,7 @@
#include <uf/engine/entity/entity.h>
#include <uf/engine/scene/scene.h>
#include <uf/utils/math/vector.h>
#include <uf/utils/graphic/graphic.h>
namespace ext {
namespace ExtSceneBehavior {
@ -67,6 +68,7 @@ namespace ext {
} sky;
);
void bindBuffers( uf::Object&, const uf::stl::string& = "", bool = false );
void bindBuffers( uf::Object&, const uf::stl::string& = "", const uf::stl::string& = "fragment", const uf::stl::string& = "" );
void bindBuffers( uf::Object&, uf::renderer::Graphic&, const uf::stl::string& = "fragment", const uf::stl::string& = "" );
}
}

View File

@ -174,7 +174,6 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
if ( renderMode.blitter.initialized ) {
auto& pipeline = renderMode.blitter.getPipeline();
pipeline.record(renderMode.blitter, commandBuffer);
// vkCmdDispatch(commandBuffer, metadata.voxelSize.x / metadata.dispatchSize.x, metadata.voxelSize.y / metadata.dispatchSize.y, metadata.voxelSize.z / metadata.dispatchSize.z);
}
// generate mipmaps
@ -437,7 +436,7 @@ void ext::VoxelizerSceneBehavior::tick( uf::Object& self ) {
}
#endif
}
ext::ExtSceneBehavior::bindBuffers( scene, metadata.renderModeName, true );
ext::ExtSceneBehavior::bindBuffers( scene, metadata.renderModeName, "compute" );
ext::ExtSceneBehavior::bindBuffers( scene );
#endif
}

View File

@ -230,6 +230,9 @@ void EXT_API ext::initialize() {
uf::Object::assertionLoad = ::json["engine"]["debug"]["loader"]["assert"].as( uf::Object::assertionLoad );
uf::Asset::assertionLoad = ::json["engine"]["debug"]["loader"]["assert"].as( uf::Asset::assertionLoad );
uf::userdata::autoDestruct = ::json["engine"]["debug"]["userdata"]["auto destruct"].as( uf::userdata::autoDestruct );
uf::userdata::autoValidate = ::json["engine"]["debug"]["userdata"]["auto validate"].as( uf::userdata::autoValidate );
}
{
@ -417,6 +420,11 @@ 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::rt ) {
// uf::renderer::settings::pipelines::vxgi = false;
uf::renderer::settings::pipelines::culling = false;
}
#define JSON_TO_VKFORMAT( key ) if ( configRenderJson["formats"][#key].is<uf::stl::string>() ) {\
uf::stl::string format = configRenderJson["formats"][#key].as<uf::stl::string>();\

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