vxgi optimizations (to-do: fix the stuttering again from the UBO lagging or something)

This commit is contained in:
ecker 2026-05-06 20:47:54 -05:00
parent ec2122ab12
commit 682dd2c794
28 changed files with 822 additions and 925 deletions

View File

@ -109,7 +109,7 @@
"invariant": {
"default stage buffers": true,
"default defer buffer destroy": true,
"default command buffer immediate": true,
"default command buffer immediate": false,
"multithreaded recording": true
},
"pipelines": {
@ -117,10 +117,10 @@
"gui": true,
"vsync": true, // vsync on vulkan side rather than engine-side
"hdr": true,
"vxgi": false,
"vxgi": true,
"culling": false,
"bloom": true,
"dof": true,
"bloom": false,
"dof": false,
"rt": false,
"fsr": false,
"postProcess": false // "postProcess.chromab" // false
@ -299,7 +299,7 @@
"enabled": true
},
"imgui": {
"enabled": true
"enabled": false
},
"fsr": {
"enabled": true,

View File

@ -2,6 +2,10 @@
float random(vec3 seed, int i){ return fract(sin(dot(vec4(seed,i), vec4(12.9898,78.233,45.164,94.673))) * 43758.5453); }
float rand2(vec2 co){ return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 143758.5453); }
float rand3(vec3 co){ return fract(sin(dot(co.xyz ,vec3(12.9898,78.233, 37.719))) * 143758.5453); }
float interleavedGradientNoise(vec2 co) {
vec3 seed = vec3(0.06711056, 0.00583715, 52.9829189);
return fract(seed.z * fract(dot(co, seed.xy)));
}
//
float mipLevel( in vec2 dx_vtc, in vec2 dy_vtc ) {
const float delta_max_sqr = max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc));
@ -44,7 +48,8 @@ void gammaCorrect( inout vec3 color, float gamma ) {
}
void toneMap( inout vec4 color, float exposure ) { toneMap(color.rgb, exposure); }
void gammaCorrect( inout vec4 color, float gamma ) { gammaCorrect(color.rgb, gamma); }
float luma( vec3 color ) { return dot(color, vec3(0.2126, 0.7152, 0.0722)); }
float luma( vec3 color ) { return dot(color, vec3(0.2126, 0.7152, 0.0722)); } // REF 709
float luminance( vec3 color ) { return dot(color, vec3(0.299, 0.587, 0.114)); } // REF 601
//
uint tea(uint val0, uint val1) {
uint v0 = val0;

View File

@ -94,19 +94,10 @@ layout (binding = 18) uniform sampler2D samplerTextures[TEXTURES];
layout (binding = 19) uniform samplerCube samplerCubemaps[CUBEMAPS];
layout (binding = 20) uniform sampler3D samplerNoise;
#if VXGI
layout (binding = 21) uniform usampler3D voxelDrawId[CASCADES];
layout (binding = 22) uniform usampler3D voxelInstanceId[CASCADES];
layout (binding = 23) uniform sampler3D voxelNormalX[CASCADES];
layout (binding = 24) uniform sampler3D voxelNormalY[CASCADES];
layout (binding = 25) uniform sampler3D voxelRadianceR[CASCADES];
layout (binding = 26) uniform sampler3D voxelRadianceG[CASCADES];
layout (binding = 27) uniform sampler3D voxelRadianceB[CASCADES];
layout (binding = 28) uniform sampler3D voxelRadianceA[CASCADES];
layout (binding = 29) uniform sampler3D voxelCount[CASCADES];
layout (binding = 30) uniform sampler3D voxelOutput[CASCADES];
layout (binding = 21) uniform sampler3D voxelOutput[CASCADES];
#endif
#if RT
layout (binding = 31) uniform accelerationStructureEXT tlas;
layout (binding = 22) uniform accelerationStructureEXT tlas;
#endif
#if BUFFER_REFERENCE
@ -296,7 +287,7 @@ void directLighting() {
surface.material.albedo.rgb = radiance.rgb;
surface.material.indirect.rgb = vec3(0);
surface.fragment.rgb = radiance.rgb;
surface.fragment.a = radiance.a;
surface.fragment.a = 1; // radiance.a;
//return;
}
#endif

View File

@ -50,18 +50,11 @@ layout (std140, binding = 7) readonly buffer Lights {
layout (binding = 8) uniform sampler2D samplerTextures[TEXTURES];
layout (binding = 9) uniform samplerCube samplerCubemaps[CUBEMAPS];
layout (binding = 10) uniform sampler3D samplerNoise;
layout (binding = 11, r32ui) uniform readonly uimage3D voxelDrawId[CASCADES];
layout (binding = 12, r32ui) uniform readonly uimage3D voxelInstanceId[CASCADES];
layout (binding = 13, r32ui) uniform readonly uimage3D voxelNormalX[CASCADES];
layout (binding = 14, r32ui) uniform readonly uimage3D voxelNormalY[CASCADES];
layout (binding = 15, r32ui) uniform readonly uimage3D voxelRadianceR[CASCADES];
layout (binding = 16, r32ui) uniform readonly uimage3D voxelRadianceG[CASCADES];
layout (binding = 17, r32ui) uniform readonly uimage3D voxelRadianceB[CASCADES];
layout (binding = 18, r32ui) uniform readonly uimage3D voxelRadianceA[CASCADES];
layout (binding = 19, r32ui) uniform readonly uimage3D voxelCount[CASCADES];
layout (binding = 20, rgba8) uniform writeonly image3D voxelOutput[CASCADES];
layout (binding = 10, r32ui) uniform readonly uimage3D voxelId[CASCADES];
layout (binding = 11, r32ui) uniform readonly uimage3D voxelNormal[CASCADES];
layout (binding = 12, r32ui) uniform readonly uimage3D voxelRadiance[CASCADES];
layout (binding = 13, rgba8) uniform writeonly image3D voxelOutput[CASCADES];
#include "../../common/functions.h"
#include "../../common/light.h"
@ -71,55 +64,27 @@ layout (binding = 20, rgba8) uniform writeonly image3D voxelOutput[CASCADES];
void main() {
const vec3 tUvw = gl_GlobalInvocationID.xzy;
for ( uint CASCADE = 0; CASCADE < CASCADES; ++CASCADE ) {
vec2 N_E = vec2(
uintBitsToFloat(imageLoad(voxelNormalX[CASCADE], ivec3(tUvw) ).x),
uintBitsToFloat(imageLoad(voxelNormalY[CASCADE], ivec3(tUvw) ).x)
);
surface.normal.world = decodeNormals( N_E );
surface.normal.eye = vec3( ubo.settings.vxgi.matrix * vec4( surface.normal.world, 0.0f ) );
surface.position.eye = (vec3(gl_GlobalInvocationID.xyz) / vec3(imageSize(voxelOutput[CASCADE])) * 2.0f - 1.0f) * cascadePower(CASCADE);
surface.position.world = vec3( inverse(ubo.settings.vxgi.matrix) * vec4( surface.position.eye, 1.0f ) );
#if 0
vec4 A = unpackUnorm4x8(imageLoad(voxelRadiance[CASCADE], ivec3(tUvw)).r);
A.a = length(luma(A.rgb)) > 0.001 ? 1 : 0;
imageStore(voxelOutput[CASCADE], ivec3(tUvw), A);
#else
surface.pass = 0; // PushConstant.pass;
surface.fragment = vec4(0);
surface.light = vec4(0);
surface.motion = vec2(0);
surface.material.indirect = vec4(0);
#if 0
#if 0
vec4 A = imageLoad(voxelOutput[CASCADE], ivec3(tUvw) );
#else
vec4 A = vec4(0);
A.r = imageLoad(voxelRadianceR[CASCADE], ivec3(tUvw) ).r;
A.g = imageLoad(voxelRadianceG[CASCADE], ivec3(tUvw) ).r;
A.b = imageLoad(voxelRadianceB[CASCADE], ivec3(tUvw) ).r;
A.a = imageLoad(voxelRadianceA[CASCADE], ivec3(tUvw) ).r;
A /= 256.0;
uint count = imageLoad(voxelCount[CASCADE], ivec3(tUvw) ).r;
if ( count > 0 ) A /= count;
/*
vec4 A = vec4(surface.normal.world, 1.0);
*/
#endif
surface.material.albedo = A;
surface.fragment.rgb = surface.material.albedo.rgb;
const bool DISCARD_DUE_TO_DIVERGENCE = surface.material.albedo.a == 0;
#else
const uint packedID = imageLoad(voxelId[CASCADE], ivec3(tUvw) ).x;
const uvec2 ID = uvec2(
imageLoad(voxelDrawId[CASCADE], ivec3(tUvw) ).x,
imageLoad(voxelInstanceId[CASCADE], ivec3(tUvw) ).x
(packedID & 0xFFFF),
(packedID >> 16)
);
const bool DISCARD_DUE_TO_DIVERGENCE = ID.x == 0 || ID.y == 0;
const uint drawID = ID.x == 0 ? 0 : ID.x - 1;
const uint instanceID = ID.y == 0 ? 0 : ID.y - 1;
// if ( ID.x == 0 || ID.y == 0 ) {
#if 1
if ( DISCARD_DUE_TO_DIVERGENCE ) {
@ -138,15 +103,8 @@ void main() {
#if 0
vec4 A = imageLoad(voxelOutput[CASCADE], ivec3(tUvw) );
#else
vec4 A = vec4(0);
A.r = imageLoad(voxelRadianceR[CASCADE], ivec3(tUvw) ).r;
A.g = imageLoad(voxelRadianceG[CASCADE], ivec3(tUvw) ).r;
A.b = imageLoad(voxelRadianceB[CASCADE], ivec3(tUvw) ).r;
A.a = imageLoad(voxelRadianceA[CASCADE], ivec3(tUvw) ).r;
A /= 256.0;
uint count = imageLoad(voxelCount[CASCADE], ivec3(tUvw) ).r;
if ( count > 0 ) A /= count;
vec4 A = unpackUnorm4x8(imageLoad(voxelRadiance[CASCADE], ivec3(tUvw)).r);
A.a = 1.0;
#endif
surface.material.albedo = A;
@ -205,7 +163,6 @@ void main() {
#endif
}
surface.fragment.rgb += surface.light.rgb;
#endif
#if TONE_MAP
toneMap(surface.fragment.rgb, ubo.settings.bloom.exposure);
@ -214,14 +171,11 @@ void main() {
gammaCorrect(surface.fragment.rgb, 1.0 / ubo.settings.bloom.gamma);
#endif
#if 0
imageStore(voxelOutput[CASCADE], ivec3(tUvw), vec4(surface.fragment.rgb, surface.material.albedo.a));
#else
if ( DISCARD_DUE_TO_DIVERGENCE ) {
imageStore(voxelOutput[CASCADE], ivec3(tUvw), vec4(0));
} else {
imageStore(voxelOutput[CASCADE], ivec3(tUvw), vec4(surface.fragment.rgb, surface.material.albedo.a));
}
#endif
#endif
}
}

View File

@ -37,16 +37,10 @@ layout (std140, binding = 12) readonly buffer Lights {
Light lights[];
};
layout (binding = 13, r32ui) uniform volatile uimage3D voxelDrawId[CASCADES];
layout (binding = 14, r32ui) uniform volatile uimage3D voxelInstanceId[CASCADES];
layout (binding = 15, r32ui) uniform volatile uimage3D voxelNormalX[CASCADES];
layout (binding = 16, r32ui) uniform volatile uimage3D voxelNormalY[CASCADES];
layout (binding = 17, r32ui) uniform volatile uimage3D voxelRadianceR[CASCADES];
layout (binding = 18, r32ui) uniform volatile uimage3D voxelRadianceG[CASCADES];
layout (binding = 19, r32ui) uniform volatile uimage3D voxelRadianceB[CASCADES];
layout (binding = 20, r32ui) uniform volatile uimage3D voxelRadianceA[CASCADES];
layout (binding = 21, r32ui) uniform volatile uimage3D voxelCount[CASCADES];
layout (binding = 22, rgba8) uniform writeonly image3D voxelOutput[CASCADES];
layout (binding = 13, r32ui) uniform volatile uimage3D voxelId[CASCADES];
layout (binding = 14, r32ui) uniform volatile uimage3D voxelNormal[CASCADES];
layout (binding = 15, r32ui) uniform volatile uimage3D voxelRadiance[CASCADES];
layout (binding = 16, rgba8) uniform writeonly image3D voxelOutput[CASCADES];
layout (location = 0) flat in uvec4 inId;
layout (location = 1) flat in vec4 inPOS0;
@ -94,7 +88,8 @@ void main() {
A.a = 1;
// alpha mode BLEND
} else if ( material.modeAlpha == 1 ) {
float dither = interleavedGradientNoise(gl_FragCoord.xy);
// if ( A.a < dither ) discard;
// alpha mode MASK
} else if ( material.modeAlpha == 2 ) {
if ( A.a < abs(material.factorAlphaCutoff) ) discard;
@ -121,16 +116,13 @@ void main() {
const ivec3 uvw = ivec3(P * imageSize(voxelOutput[CASCADE]));
imageAtomicMax(voxelDrawId[CASCADE], ivec3(uvw), uint( drawID + 1 ) );
imageAtomicMax(voxelInstanceId[CASCADE], ivec3(uvw), uint( instanceID + 1 ) );
uint packedId = ( instanceID + 1 ) << 16 | ( drawID + 1 );
imageAtomicMax(voxelId[CASCADE], ivec3(uvw), packedId);
vec2 N_E = encodeNormals( normalize( N ) );
imageAtomicMin(voxelNormalX[CASCADE], ivec3(uvw), uint( floatBitsToUint( N_E.x ) ) );
imageAtomicMin(voxelNormalY[CASCADE], ivec3(uvw), uint( floatBitsToUint( N_E.y ) ) );
imageAtomicAdd(voxelRadianceR[CASCADE], ivec3(uvw), uint( A.r * 256 ) );
imageAtomicAdd(voxelRadianceG[CASCADE], ivec3(uvw), uint( A.g * 256 ) );
imageAtomicAdd(voxelRadianceB[CASCADE], ivec3(uvw), uint( A.b * 256 ) );
imageAtomicAdd(voxelRadianceA[CASCADE], ivec3(uvw), uint( A.a * 256 ) );
imageAtomicAdd(voxelCount[CASCADE], ivec3(uvw), uint( 1 ) );
uint packedNormal = packHalf2x16(N_E);
imageAtomicMin(voxelNormal[CASCADE], uvw, packedNormal);
uint packedRadiance = packUnorm4x8(vec4(A.rgb, luminance(A.rgb)));
imageAtomicMax(voxelRadiance[CASCADE], uvw, packedRadiance);
}

View File

@ -5,15 +5,9 @@ namespace pod {
uf::renderer::Texture3D noise;
uf::renderer::TextureCube skybox;
struct {
uf::stl::vector<uf::renderer::Texture3D> drawId;
uf::stl::vector<uf::renderer::Texture3D> instanceId;
uf::stl::vector<uf::renderer::Texture3D> normalX;
uf::stl::vector<uf::renderer::Texture3D> normalY;
uf::stl::vector<uf::renderer::Texture3D> radianceR;
uf::stl::vector<uf::renderer::Texture3D> radianceG;
uf::stl::vector<uf::renderer::Texture3D> radianceB;
uf::stl::vector<uf::renderer::Texture3D> radianceA;
uf::stl::vector<uf::renderer::Texture3D> count;
uf::stl::vector<uf::renderer::Texture3D> id;
uf::stl::vector<uf::renderer::Texture3D> normal;
uf::stl::vector<uf::renderer::Texture3D> radiance;
uf::stl::vector<uf::renderer::Texture3D> output;
} voxels;
};

View File

@ -59,6 +59,7 @@ namespace ext {
VkImageViewType viewType = enums::Image::VIEW_TYPE_2D;
VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED;
VkImageUsageFlags usage = {};
VkImageCreateFlags flags = {};
VkDeviceMemory deviceMemory = VK_NULL_HANDLE;
VkDescriptorImageInfo descriptor = {};
VkFormat format = enums::Format::R8G8B8A8_UNORM;
@ -102,29 +103,45 @@ namespace ext {
const uf::stl::string& filename,
VkFormat format = DefaultFormat,
VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT,
VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VkImageCreateFlags flags = {}
);
void loadFromFile(
const uf::stl::string& filename,
Device& device,
VkFormat format = DefaultFormat,
VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT,
VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VkImageCreateFlags flags = {}
);
void loadFromImage(
const uf::Image& image,
Device& device,
VkFormat format = DefaultFormat,
VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT,
VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VkImageCreateFlags flags = {}
);
void loadFromImage(
const uf::Image& image,
VkFormat format = DefaultFormat,
VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT,
VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VkImageCreateFlags flags = {}
);
void fromBuffers(
void* buffer,
VkDeviceSize bufferSize,
VkFormat format,
uint32_t texWidth,
uint32_t texHeight,
uint32_t texDepth,
uint32_t layers,
Device& device,
VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT,
VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VkImageCreateFlags flags = {}
);
void fromBuffers( void* buffer, VkDeviceSize bufferSize, VkFormat format, uint32_t texWidth, uint32_t texHeight, uint32_t texDepth, uint32_t layers, Device& device, VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL );
void asRenderTarget( Device& device, uint32_t texWidth, uint32_t texHeight, VkFormat format = DefaultFormat );
Texture alias() const;
@ -136,14 +153,14 @@ namespace ext {
void update( uf::Image& image, VkImageLayout, uint32_t layer = 1 );
void update( void*, VkDeviceSize, VkImageLayout, uint32_t layer = 1 );
inline void fromBuffers( void* buffer, VkDeviceSize bufferSize, VkFormat format, uint32_t texWidth, uint32_t texHeight, Device& device, VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ) { return this->fromBuffers(buffer, bufferSize, format, texWidth, texHeight, 1, 1, device, usage, layout); }
inline void fromBuffers( void* buffer, VkDeviceSize bufferSize, VkFormat format, uint32_t texWidth, uint32_t texHeight, Device& device, VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VkImageCreateFlags flags = {} ) { return this->fromBuffers(buffer, bufferSize, format, texWidth, texHeight, 1, 1, device, usage, layout, flags); }
inline void update( uf::Image& image, uint32_t layer = 1 ) { return this->update(image, this->layout, layer); }
inline void update( void* data, VkDeviceSize size, uint32_t layer = 1 ) { return this->update(data, size, this->layout, layer); }
void generateMipmaps(VkCommandBuffer commandBuffer, uint32_t layer = 0);
void fromBuffers( void* buffer, VkDeviceSize bufferSize, VkFormat format, uint32_t texWidth, uint32_t texHeight, uint32_t texDepth, uint32_t layers, VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL );
inline void fromBuffers( void* buffer, VkDeviceSize bufferSize, VkFormat format, uint32_t texWidth, uint32_t texHeight, VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ) { return this->fromBuffers(buffer, bufferSize, format, texWidth, texHeight, 1, 1, usage, layout); }
void fromBuffers( void* buffer, VkDeviceSize bufferSize, VkFormat format, uint32_t texWidth, uint32_t texHeight, uint32_t texDepth, uint32_t layers, VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VkImageCreateFlags flags = {} );
inline void fromBuffers( void* buffer, VkDeviceSize bufferSize, VkFormat format, uint32_t texWidth, uint32_t texHeight, VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VkImageCreateFlags flags = {} ) { return this->fromBuffers(buffer, bufferSize, format, texWidth, texHeight, 1, 1, usage, layout, flags); }
};
class UF_API Texture2D : public Texture {
public:

View File

@ -384,7 +384,9 @@ void ext::GuiGlyphBehavior::initialize( uf::Object& self ) {
bool forced = payload["force"].as(false);
// override
// metadata.sdf = false;
#if UF_USE_OPENGL
metadata.sdf = false;
#endif
metadataGui.scaling = "none";
auto& scene = uf::scene::getCurrentScene();

View File

@ -225,39 +225,11 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) {
shader.setDescriptorCounts({
{ "samplerTextures", maxTextures2D },
{ "samplerCubemaps", maxTexturesCube },
{ "voxelDrawId", maxCascades },
{ "voxelInstanceId", maxCascades },
{ "voxelNormalX", maxCascades },
{ "voxelNormalY", maxCascades },
{ "voxelRadianceR", maxCascades },
{ "voxelRadianceG", maxCascades },
{ "voxelRadianceB", maxCascades },
{ "voxelRadianceA", maxCascades },
{ "voxelCount", maxCascades },
{ "voxelId", maxCascades },
{ "voxelNormal", maxCascades },
{ "voxelRadiance", maxCascades },
{ "voxelOutput", maxCascades },
});
/*
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;
}
}
*/
}
}
}

View File

@ -740,26 +740,14 @@ void ext::ExtSceneBehavior::destroy( uf::Object& self ) {
}
if ( this->hasComponent<pod::SceneTextures>() ) {
auto& sceneTextures = this->getComponent<pod::SceneTextures>();
for ( auto& t : sceneTextures.voxels.drawId ) t.destroy();
for ( auto& t : sceneTextures.voxels.instanceId ) t.destroy();
for ( auto& t : sceneTextures.voxels.normalX ) t.destroy();
for ( auto& t : sceneTextures.voxels.normalY ) t.destroy();
for ( auto& t : sceneTextures.voxels.radianceR ) t.destroy();
for ( auto& t : sceneTextures.voxels.radianceG ) t.destroy();
for ( auto& t : sceneTextures.voxels.radianceB ) t.destroy();
for ( auto& t : sceneTextures.voxels.radianceA ) t.destroy();
for ( auto& t : sceneTextures.voxels.count ) t.destroy();
for ( auto& t : sceneTextures.voxels.id ) t.destroy();
for ( auto& t : sceneTextures.voxels.normal ) t.destroy();
for ( auto& t : sceneTextures.voxels.radiance ) t.destroy();
for ( auto& t : sceneTextures.voxels.output ) t.destroy();
sceneTextures.voxels.drawId.clear();
sceneTextures.voxels.instanceId.clear();
sceneTextures.voxels.normalX.clear();
sceneTextures.voxels.normalY.clear();
sceneTextures.voxels.radianceR.clear();
sceneTextures.voxels.radianceG.clear();
sceneTextures.voxels.radianceB.clear();
sceneTextures.voxels.radianceA.clear();
sceneTextures.voxels.count.clear();
sceneTextures.voxels.id.clear();
sceneTextures.voxels.normal.clear();
sceneTextures.voxels.radiance.clear();
sceneTextures.voxels.output.clear();
sceneTextures.noise.destroy();
@ -1136,17 +1124,14 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, uf::renderer::Graphic
// attach VXGI voxels
if ( uf::renderer::settings::pipelines::vxgi ) {
for ( auto& t : sceneTextures.voxels.drawId ) textures3D.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.instanceId ) textures3D.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.normalX ) textures3D.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.normalY ) textures3D.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radianceR ) textures3D.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radianceG ) textures3D.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radianceB ) textures3D.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radianceA ) textures3D.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.count ) textures3D.emplace_back().aliasTexture(t);
/*
for ( auto& t : sceneTextures.voxels.id ) textures3D.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.normal ) textures3D.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radiance ) textures3D.emplace_back().aliasTexture(t);
*/
for ( auto& t : sceneTextures.voxels.output ) textures3D.emplace_back().aliasTexture(t);
}
// bind textures
while ( textures2D.size() < metadata.max.textures2D ) textures2D.emplace_back().aliasTexture(uf::renderer::Texture2D::empty);
while ( texturesCube.size() < metadata.max.texturesCube ) texturesCube.emplace_back().aliasTexture(uf::renderer::TextureCube::empty);

View File

@ -18,6 +18,7 @@
#include "../scene/behavior.h"
#include <uf/engine/ext.h>
#define ALIAS_OUTPUT_TO_RADIANCE 1
UF_BEHAVIOR_REGISTER_CPP(ext::VoxelizerSceneBehavior)
UF_BEHAVIOR_TRAITS_CPP(ext::VoxelizerSceneBehavior, ticks = true, renders = false, thread = "")
@ -35,44 +36,46 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
for ( size_t i = 0; i < metadata.cascades; ++i ) {
const bool HDR = false;
auto& drawId = sceneTextures.voxels.drawId.emplace_back();
drawId.sampler.descriptor.filter.min = uf::renderer::enums::Filter::NEAREST;
drawId.sampler.descriptor.filter.mag = uf::renderer::enums::Filter::NEAREST;
drawId.fromBuffers( NULL, 0, uf::renderer::enums::Format::R32_UINT, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
auto& instanceId = sceneTextures.voxels.instanceId.emplace_back();
instanceId.sampler.descriptor.filter.min = uf::renderer::enums::Filter::NEAREST;
instanceId.sampler.descriptor.filter.mag = uf::renderer::enums::Filter::NEAREST;
instanceId.fromBuffers( NULL, 0, uf::renderer::enums::Format::R32_UINT, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
auto& id = sceneTextures.voxels.id.emplace_back();
id.sampler.descriptor.filter.min = uf::renderer::enums::Filter::NEAREST;
id.sampler.descriptor.filter.mag = uf::renderer::enums::Filter::NEAREST;
id.fromBuffers( NULL, 0, uf::renderer::enums::Format::R32_UINT, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
auto& normalX = sceneTextures.voxels.normalX.emplace_back();
normalX.fromBuffers( NULL, 0, uf::renderer::enums::Format::R32_UINT, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
auto& normalY = sceneTextures.voxels.normalY.emplace_back();
normalY.fromBuffers( NULL, 0, uf::renderer::enums::Format::R32_UINT, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
auto& normal = sceneTextures.voxels.normal.emplace_back();
normal.fromBuffers( NULL, 0, uf::renderer::enums::Format::R32_UINT, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
auto& radianceR = sceneTextures.voxels.radianceR.emplace_back();
radianceR.fromBuffers( NULL, 0, uf::renderer::enums::Format::R32_UINT, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
auto& radiance = sceneTextures.voxels.radiance.emplace_back();
radiance.fromBuffers( NULL, 0, uf::renderer::enums::Format::R32_UINT, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
auto& radianceG = sceneTextures.voxels.radianceG.emplace_back();
radianceG.fromBuffers( NULL, 0, uf::renderer::enums::Format::R32_UINT, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
auto& radianceB = sceneTextures.voxels.radianceB.emplace_back();
radianceB.fromBuffers( NULL, 0, uf::renderer::enums::Format::R32_UINT, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
auto& radianceA = sceneTextures.voxels.radianceA.emplace_back();
radianceA.fromBuffers( NULL, 0, uf::renderer::enums::Format::R32_UINT, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
auto& count = sceneTextures.voxels.count.emplace_back();
count.fromBuffers( NULL, 0, uf::renderer::enums::Format::R32_UINT, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
auto& output = sceneTextures.voxels.output.emplace_back();
/*
if ( metadata.filtering == "NEAREST" ) {
output.sampler.descriptor.filter.min = uf::renderer::enums::Filter::NEAREST;
output.sampler.descriptor.filter.mag = uf::renderer::enums::Filter::NEAREST;
}
*/
// output.fromBuffers( NULL, 0, uf::renderer::settings::pipelines::hdr ? uf::renderer::enums::Format::HDR : uf::renderer::enums::Format::SDR, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
#if ALIAS_OUTPUT_TO_RADIANCE
output.aliasTexture( radiance );
{
VkImageViewCreateInfo viewCreateInfo = {};
viewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewCreateInfo.image = radiance.image;
viewCreateInfo.viewType = radiance.viewType;
viewCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
viewCreateInfo.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
viewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
viewCreateInfo.subresourceRange.baseMipLevel = 0;
viewCreateInfo.subresourceRange.levelCount = radiance.mips;
viewCreateInfo.subresourceRange.baseArrayLayer = 0;
viewCreateInfo.subresourceRange.layerCount = 1;
VK_CHECK_RESULT(vkCreateImageView(uf::renderer::device.logicalDevice, &viewCreateInfo, nullptr, &output.view));
VK_REGISTER_HANDLE( output.view );
}
#else
output.fromBuffers( NULL, 0, uf::renderer::enums::Format::R8G8B8A8_UNORM, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
#endif
}
// initialize render mode
{
@ -120,15 +123,9 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
for ( size_t i = 0; i < maxTexturesCube; ++i ) renderMode.blitter.material.textures.emplace_back().aliasTexture(uf::renderer::TextureCube::empty);
for ( size_t i = 0; i < maxTextures3D; ++i ) renderMode.blitter.material.textures.emplace_back().aliasTexture(uf::renderer::Texture3D::empty);
for ( auto& t : sceneTextures.voxels.drawId ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.instanceId ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.normalX ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.normalY ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radianceR ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radianceG ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radianceB ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radianceA ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.count ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.id ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.normal ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radiance ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.output ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
renderMode.bindCallback( renderMode.CALLBACK_BEGIN, [&]( VkCommandBuffer commandBuffer, size_t _ ){
@ -141,15 +138,9 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
subresourceRange.layerCount = 1;
VkClearColorValue clearColor = { 0.0, 0.0, 0.0, 0.0 };
for ( auto& t : sceneTextures.voxels.drawId ) vkCmdClearColorImage( commandBuffer, t.image, t.layout, &clearColor, 1, &subresourceRange );
for ( auto& t : sceneTextures.voxels.instanceId ) vkCmdClearColorImage( commandBuffer, t.image, t.layout, &clearColor, 1, &subresourceRange );
for ( auto& t : sceneTextures.voxels.normalX ) vkCmdClearColorImage( commandBuffer, t.image, t.layout, &clearColor, 1, &subresourceRange );
for ( auto& t : sceneTextures.voxels.normalY ) vkCmdClearColorImage( commandBuffer, t.image, t.layout, &clearColor, 1, &subresourceRange );
for ( auto& t : sceneTextures.voxels.radianceR ) vkCmdClearColorImage( commandBuffer, t.image, t.layout, &clearColor, 1, &subresourceRange );
for ( auto& t : sceneTextures.voxels.radianceG ) vkCmdClearColorImage( commandBuffer, t.image, t.layout, &clearColor, 1, &subresourceRange );
for ( auto& t : sceneTextures.voxels.radianceB ) vkCmdClearColorImage( commandBuffer, t.image, t.layout, &clearColor, 1, &subresourceRange );
for ( auto& t : sceneTextures.voxels.radianceA ) vkCmdClearColorImage( commandBuffer, t.image, t.layout, &clearColor, 1, &subresourceRange );
for ( auto& t : sceneTextures.voxels.count ) vkCmdClearColorImage( commandBuffer, t.image, t.layout, &clearColor, 1, &subresourceRange );
for ( auto& t : sceneTextures.voxels.id ) vkCmdClearColorImage( commandBuffer, t.image, t.layout, &clearColor, 1, &subresourceRange );
for ( auto& t : sceneTextures.voxels.normal ) vkCmdClearColorImage( commandBuffer, t.image, t.layout, &clearColor, 1, &subresourceRange );
for ( auto& t : sceneTextures.voxels.radiance ) vkCmdClearColorImage( commandBuffer, t.image, t.layout, &clearColor, 1, &subresourceRange );
for ( auto& t : sceneTextures.voxels.output ) vkCmdClearColorImage( commandBuffer, t.image, t.layout, &clearColor, 1, &subresourceRange );
});
@ -287,15 +278,16 @@ void ext::VoxelizerSceneBehavior::tick( uf::Object& self ) {
}
void ext::VoxelizerSceneBehavior::render( uf::Object& self ){}
void ext::VoxelizerSceneBehavior::destroy( uf::Object& self ){
#if UF_USE_VULKAN
/*
if ( this->hasComponent<uf::renderer::RenderTargetRenderMode>() ) {
auto& renderMode = this->getComponent<uf::renderer::RenderTargetRenderMode>();
uf::renderer::removeRenderMode( &renderMode, false );
// this->deleteComponent<uf::renderer::RenderTargetRenderMode>();
#if ALIAS_OUTPUT_TO_RADIANCE
auto& sceneTextures = this->getComponent<pod::SceneTextures>();
for ( auto& t : sceneTextures.voxels.output ) {
ext::vulkan::mutex.lock();
auto& texture = uf::renderer::device.transient.textures.emplace_back();
ext::vulkan::mutex.unlock();
texture.device = &uf::renderer::device;
texture.view = t.view;
}
*/
#endif
}
void ext::VoxelizerSceneBehavior::Metadata::serialize( uf::Object& self, uf::Serializer& serializer ) {

View File

@ -80,20 +80,23 @@ namespace {
for ( auto& key : storage.texture2Ds.keys ) graphic.material.textures.emplace_back().aliasTexture( storage.texture2Ds.map[key] );
// bind scene's voxel texture
#if UF_USE_VULKAN
#if 0 && UF_USE_VULKAN
if ( uf::renderer::settings::pipelines::vxgi ) {
auto& scene = uf::scene::getCurrentScene();
auto& sceneTextures = scene.getComponent<pod::SceneTextures>();
for ( auto& t : sceneTextures.voxels.drawId ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.instanceId ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.normalX ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.normalY ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radianceR ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radianceG ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radianceB ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radianceA ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.count ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.id ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.normal ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radiance ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.output ) graphic.material.textures.emplace_back().aliasTexture(t);
/*
auto& shader = graphic.material.getShader("fragment", uf::renderer::settings::pipelines::names::vxgi);
shader.textures.clear();
for ( auto& t : sceneTextures.voxels.id ) shader.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.normal ) shader.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radiance ) shader.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.output ) shader.textures.emplace_back().aliasTexture(t);
*/
}
#endif
}
@ -219,21 +222,9 @@ namespace {
graphic.material.attachShader(geometryShaderFilename, uf::renderer::enums::Shader::GEOMETRY, uf::renderer::settings::pipelines::names::vxgi);
}
uint32_t voxelTypes = 0;
if ( !sceneTextures.voxels.drawId.empty() ) ++voxelTypes;
if ( !sceneTextures.voxels.instanceId.empty() ) ++voxelTypes;
if ( !sceneTextures.voxels.normalX.empty() ) ++voxelTypes;
if ( !sceneTextures.voxels.normalY.empty() ) ++voxelTypes;
if ( !sceneTextures.voxels.radianceR.empty() ) ++voxelTypes;
if ( !sceneTextures.voxels.radianceG.empty() ) ++voxelTypes;
if ( !sceneTextures.voxels.radianceB.empty() ) ++voxelTypes;
if ( !sceneTextures.voxels.radianceA.empty() ) ++voxelTypes;
if ( !sceneTextures.voxels.count.empty() ) ++voxelTypes;
if ( !sceneTextures.voxels.output.empty() ) ++voxelTypes;
uint32_t maxTextures = texture2Ds;
uint32_t maxCascades = texture3Ds / voxelTypes;
uint32_t maxCascades = sceneTextures.voxels.id.size();
// fragment shader
{
auto& shader = graphic.material.getShader("fragment", uf::renderer::settings::pipelines::names::vxgi);
@ -243,17 +234,16 @@ namespace {
});
shader.setDescriptorCounts({
{ "samplerTextures", maxTextures },
{ "voxelDrawId", maxCascades },
{ "voxelInstanceId", maxCascades },
{ "voxelNormalX", maxCascades },
{ "voxelNormalY", maxCascades },
{ "voxelRadianceR", maxCascades },
{ "voxelRadianceG", maxCascades },
{ "voxelRadianceB", maxCascades },
{ "voxelRadianceA", maxCascades },
{ "voxelCount", maxCascades },
{ "voxelId", maxCascades },
{ "voxelNormal", maxCascades },
{ "voxelRadiance", maxCascades },
{ "voxelOutput", maxCascades },
});
for ( auto& t : sceneTextures.voxels.id ) shader.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.normal ) shader.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radiance ) shader.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.output ) shader.textures.emplace_back().aliasTexture(t);
}
}
// baking pipeline

View File

@ -273,17 +273,17 @@ for ( auto& p : m.primitives ) {
};
float r = 1.0f / (deltaTriUV[0].x * deltaTriUV[1].y - deltaTriUV[0].y * deltaTriUV[1].x);
auto tangent_tri = (deltaTriPosition[0] * deltaTriUV[1].y - deltaTriPosition[1] * deltaTriUV[0].y) * r;
auto bitangent_tri = (deltaTriPosition[1] * deltaTriUV[0].x - deltaTriPosition[0] * deltaTriUV[1].x) * r;
auto tangent_tri = (deltaTriPosition[0] * deltaTriUV[1].y - deltaTriPosition[1] * deltaTriUV[0].y) * r;
auto bitangent_tri = (deltaTriPosition[1] * deltaTriUV[0].x - deltaTriPosition[0] * deltaTriUV[1].x) * r;
for ( auto i = 0; i < 3; ++i ) {
auto& normal = meshlet.vertices[indices[0]].normal;
auto& tangent = meshlet.vertices[indices[0]].tangent;
for ( auto i = 0; i < 3; ++i ) {
auto& normal = meshlet.vertices[indices[0]].normal;
auto& tangent = meshlet.vertices[indices[0]].tangent;
tangent = uf::vector::normalize(tangent_tri - normal * uf::vector::dot(normal, tangent_tri));
if (uf::vector::dot(uf::vector::cross(normal, tangent), bitangent_tri) < 0.0f)
tangent = tangent * -1.0f;
}
}
}
} else {
for ( size_t i = 0; i < meshlet.vertices.size() / 3; ++i ) {
@ -313,17 +313,17 @@ for ( auto& p : m.primitives ) {
};
float r = 1.0f / (deltaTriUV[0].x * deltaTriUV[1].y - deltaTriUV[0].y * deltaTriUV[1].x);
auto tangent_tri = (deltaTriPosition[0] * deltaTriUV[1].y - deltaTriPosition[1] * deltaTriUV[0].y) * r;
auto bitangent_tri = (deltaTriPosition[1] * deltaTriUV[0].x - deltaTriPosition[0] * deltaTriUV[1].x) * r;
auto tangent_tri = (deltaTriPosition[0] * deltaTriUV[1].y - deltaTriPosition[1] * deltaTriUV[0].y) * r;
auto bitangent_tri = (deltaTriPosition[1] * deltaTriUV[0].x - deltaTriPosition[0] * deltaTriUV[1].x) * r;
for ( auto i = 0; i < 3; ++i ) {
auto& normal = meshlet.vertices[indices[0]].normal;
auto& tangent = meshlet.vertices[indices[0]].tangent;
for ( auto i = 0; i < 3; ++i ) {
auto& normal = meshlet.vertices[indices[0]].normal;
auto& tangent = meshlet.vertices[indices[0]].tangent;
tangent = uf::vector::normalize(tangent_tri - normal * uf::vector::dot(normal, tangent_tri));
if (uf::vector::dot(uf::vector::cross(normal, tangent), bitangent_tri) < 0.0f)
tangent = tangent * -1.0f;
}
}
}
}
}

View File

@ -173,10 +173,12 @@ void ext::imgui::tick() {
auto& renderMode = uf::renderer::getRenderMode("Gui", true);
// check if rendermode changed
#if UF_USE_VULKAN
if ( ::boundRenderMode != &renderMode ) {
::shutdownRenderer();
::initRenderer();
}
#endif
ImGuiIO& io = ImGui::GetIO();
io.DeltaTime = uf::physics::time::delta;

View File

@ -19,6 +19,7 @@ namespace {
struct Pair {
bool aliased = false;
size_t index = 0;
size_t size = 0;
};
uf::stl::vector<void*> local;
uf::stl::vector<void*> aliases;
@ -105,7 +106,7 @@ void ext::opengl::Device::initialize() {
#endif
#if UF_USE_OPENGL_FIXED_FUNCTION
{
::buffers::type.emplace_back(::buffers::Pair{.aliased = false, .index = 0});
::buffers::type.emplace_back(::buffers::Pair{.aliased = false, .index = 0, .size = 0});
::buffers::local.emplace_back((void*) NULL);
}
#endif
@ -172,7 +173,7 @@ GLuint ext::opengl::Device::createBuffer( enums::Buffer::type_t usage, GLsizeipt
#else
// CPU-based buffer
index = ::buffers::type.size();
::buffers::type.emplace_back( ::buffers::Pair{.aliased = aliased, .index = index} );
::buffers::type.emplace_back( ::buffers::Pair{.aliased = aliased, .index = index, .size = size} );
if ( aliased ) {
::buffers::aliases.emplace_back( data );
@ -215,11 +216,11 @@ void ext::opengl::Device::destroyBuffer( GLuint& index ) {
auto& buffer = ::buffers::local[type.index];
if ( buffer ) {
#if UF_MEMORYPOOL_INVALID_FREE
uf::memoryPool::global.free( buffer );
uf::memoryPool::global.free( buffer, type.size );
#else
uf::MemoryPool* memoryPool = uf::memoryPool::global.size() > 0 ? &uf::memoryPool::global : NULL;
if ( memoryPool ) memoryPool->free( buffer );
else free( buffer );
if ( memoryPool ) memoryPool->free( buffer, type.size );
else free( buffer, type.size );
#endif
}
#endif

View File

@ -1226,13 +1226,13 @@ void ext::vulkan::Graphic::generateBottomAccelerationStructures() {
uf::stl::vector<VkAccelerationStructureBuildRangeInfoKHR> asBuildOffsetInfo;
VkBuildAccelerationStructureFlagsKHR flags{};
VkAccelerationStructureBuildGeometryInfoKHR buildInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR};
VkAccelerationStructureBuildSizesInfoKHR sizeInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR};
VkAccelerationStructureBuildGeometryInfoKHR buildInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR};
VkAccelerationStructureBuildSizesInfoKHR sizeInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR};
const VkAccelerationStructureBuildRangeInfoKHR* rangeInfo;
uf::renderer::AccelerationStructure as;
uf::renderer::AccelerationStructure previous;
const VkAccelerationStructureBuildRangeInfoKHR* rangeInfo;
uf::renderer::AccelerationStructure as;
uf::renderer::AccelerationStructure previous;
};
uf::stl::vector<BlasData> blasDatas;
@ -1297,7 +1297,7 @@ void ext::vulkan::Graphic::generateBottomAccelerationStructures() {
triangles.indexData.deviceAddress = indexBufferAddress;
VkAccelerationStructureBuildRangeInfoKHR& offset = blasData.asBuildOffsetInfo.emplace_back();
offset.firstVertex = vertexInput.first;
offset.firstVertex = vertexInput.first;
offset.primitiveCount = vertexInput.count / 3;
offset.primitiveOffset = indexInput.first * indexInput.size;
offset.transformOffset = 0;
@ -1334,7 +1334,7 @@ void ext::vulkan::Graphic::generateBottomAccelerationStructures() {
triangles.indexData.deviceAddress = indexBufferAddress;
VkAccelerationStructureBuildRangeInfoKHR& offset = blasData.asBuildOffsetInfo.emplace_back();
offset.firstVertex = vertexInput.first;
offset.firstVertex = vertexInput.first;
offset.primitiveCount = vertexInput.count / 3;
offset.primitiveOffset = indexInput.first * indexInput.size;
offset.transformOffset = 0;
@ -1715,7 +1715,7 @@ void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vect
buildInfo.dstAccelerationStructure = tlas.handle;
buildInfo.scratchData.deviceAddress = scratchBuffer.getAddress();
VkAccelerationStructureBuildRangeInfoKHR buildOffsetInfo{countInstance, 0, 0, 0};
VkAccelerationStructureBuildRangeInfoKHR buildOffsetInfo{countInstance, 0, 0, 0};
const VkAccelerationStructureBuildRangeInfoKHR* rangeInfo = &buildOffsetInfo;
auto commandBuffer = device.fetchCommandBuffer(uf::renderer::QueueEnum::COMPUTE);

View File

@ -329,15 +329,9 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
shader.setDescriptorCounts({
{ "samplerTextures", maxTextures2D },
{ "samplerCubemaps", maxTexturesCube },
{ "voxelDrawId", maxCascades },
{ "voxelInstanceId", maxCascades },
{ "voxelNormalX", maxCascades },
{ "voxelNormalY", maxCascades },
{ "voxelRadianceR", maxCascades },
{ "voxelRadianceG", maxCascades },
{ "voxelRadianceB", maxCascades },
{ "voxelRadianceA", maxCascades },
{ "voxelCount", maxCascades },
{ "voxelId", maxCascades },
{ "voxelNormal", maxCascades },
{ "voxelRadiance", maxCascades },
{ "voxelOutput", maxCascades },
});

View File

@ -316,6 +316,7 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
{uf::io::resolveURI(fragmentShaderFilename), VK_SHADER_STAGE_FRAGMENT_BIT}
});
}
if ( metadata.type == uf::renderer::settings::pipelines::names::vxgi ) {
auto& shader = blitter.material.getShader("compute");
@ -333,17 +334,21 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
shader.setDescriptorCounts({
{ "samplerTextures", maxTextures2D },
{ "samplerCubemaps", maxTexturesCube },
{ "voxelDrawId", maxCascades },
{ "voxelInstanceId", maxCascades },
{ "voxelNormalX", maxCascades },
{ "voxelNormalY", maxCascades },
{ "voxelRadianceR", maxCascades },
{ "voxelRadianceG", maxCascades },
{ "voxelRadianceB", maxCascades },
{ "voxelRadianceA", maxCascades },
{ "voxelCount", maxCascades },
{ "voxelId", maxCascades },
{ "voxelNormal", maxCascades },
{ "voxelRadiance", maxCascades },
{ "voxelOutput", maxCascades },
});
auto& scene = uf::scene::getCurrentScene();
auto& sceneTextures = scene.getComponent<pod::SceneTextures>();
shader.textures.clear();
for ( auto& t : sceneTextures.voxels.id ) shader.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.normal ) shader.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radiance ) shader.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.output ) shader.textures.emplace_back().aliasTexture(t);
} else if ( metadata.type == uf::renderer::settings::pipelines::names::rt ) {
#if 0
auto& shader = blitter.material.getShader("fragment");

View File

@ -36,14 +36,14 @@ namespace {
}
if ( image == VK_NULL_HANDLE ) continue;
subresourceRange.baseMipLevel = 0;
subresourceRange.levelCount = 1;
subresourceRange.levelCount = 1;
subresourceRange.aspectMask = descriptor.name == "depth" ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
uf::renderer::Texture::setImageLayout( commandBuffer, image, layout, descriptor.layout, subresourceRange );
if ( mips > 1 ) {
subresourceRange.baseMipLevel = 1;
subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
uf::renderer::Texture::setImageLayout( commandBuffer, image, initialLayout, descriptor.layout, subresourceRange );
}
subresourceRange.baseMipLevel = 1;
subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
uf::renderer::Texture::setImageLayout( commandBuffer, image, initialLayout, descriptor.layout, subresourceRange );
}
}
}
void transitionAttachmentsFrom(
@ -83,14 +83,14 @@ namespace {
}
if ( image == VK_NULL_HANDLE ) continue;
subresourceRange.baseMipLevel = 0;
subresourceRange.levelCount = 1;
subresourceRange.levelCount = 1;
subresourceRange.aspectMask = descriptor.name == "depth" ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
uf::renderer::Texture::setImageLayout( commandBuffer, image, descriptor.layout, layout, subresourceRange );
if ( mips > 1 ) {
subresourceRange.baseMipLevel = 1;
subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
uf::renderer::Texture::setImageLayout( commandBuffer, image, descriptor.layout, initialLayout, subresourceRange );
}
subresourceRange.baseMipLevel = 1;
subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
uf::renderer::Texture::setImageLayout( commandBuffer, image, descriptor.layout, initialLayout, subresourceRange );
}
}
}
}

View File

@ -371,35 +371,39 @@ void ext::vulkan::Texture::loadFromFile(
const uf::stl::string& filename,
VkFormat format,
VkImageUsageFlags usage,
VkImageLayout layout
VkImageLayout layout,
VkImageCreateFlags flags
) {
return loadFromFile( filename, ext::vulkan::device, format, usage, layout );
return loadFromFile( filename, ext::vulkan::device, format, usage, layout, flags );
}
void ext::vulkan::Texture::loadFromFile(
const uf::stl::string& filename,
Device& device,
VkFormat format,
VkImageUsageFlags usage,
VkImageLayout layout
VkImageLayout layout,
VkImageCreateFlags flags
) {
uf::Image image;
image.open( filename );
return loadFromImage( image, device, format, usage, layout );
return loadFromImage( image, device, format, usage, layout, flags );
}
void ext::vulkan::Texture::loadFromImage(
const uf::Image& image,
VkFormat format,
VkImageUsageFlags usage,
VkImageLayout layout
VkImageLayout layout,
VkImageCreateFlags flags
) {
return loadFromImage( image, ext::vulkan::device, format, usage, layout );
return loadFromImage( image, ext::vulkan::device, format, usage, layout, flags );
}
void ext::vulkan::Texture::loadFromImage(
const uf::Image& image,
Device& device,
VkFormat format,
VkImageUsageFlags usage,
VkImageLayout layout
VkImageLayout layout,
VkImageCreateFlags flags
) {
/*
switch ( format ) {
@ -474,7 +478,8 @@ void ext::vulkan::Texture::loadFromImage(
1,
device,
usage,
layout
layout,
flags
);
}
@ -487,9 +492,10 @@ void ext::vulkan::Texture::fromBuffers(
uint32_t texDepth,
uint32_t layers,
VkImageUsageFlags usage,
VkImageLayout layout
VkImageLayout layout,
VkImageCreateFlags flags
) {
return this->fromBuffers( buffer, bufferSize, format, texWidth, texHeight, texDepth, layers, ext::vulkan::device, usage, layout );
return this->fromBuffers( buffer, bufferSize, format, texWidth, texHeight, texDepth, layers, ext::vulkan::device, usage, layout, flags );
}
@ -503,11 +509,13 @@ void ext::vulkan::Texture::fromBuffers(
uint32_t layers,
Device& device,
VkImageUsageFlags usage,
VkImageLayout layout
VkImageLayout layout,
VkImageCreateFlags flags
) {
this->initialize(device, texWidth, texHeight, texDepth, layers);
this->layout = VK_IMAGE_LAYOUT_UNDEFINED;
this->initialize( device, texWidth, texHeight, texDepth, layers );
this->usage = usage;
this->layout = VK_IMAGE_LAYOUT_UNDEFINED;
this->flags = flags;
if ( this->mips == 0 ) {
this->mips = 1;
@ -545,6 +553,7 @@ void ext::vulkan::Texture::fromBuffers(
imageCreateInfo.initialLayout = this->layout;
imageCreateInfo.extent = { width, height, depth };
imageCreateInfo.usage = this->usage;
imageCreateInfo.flags = this->flags;
// Ensure that the TRANSFER_SRC bit is set for mip creation
if ( this->mips > 1 && !(imageCreateInfo.usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT)) {
imageCreateInfo.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
@ -555,7 +564,7 @@ void ext::vulkan::Texture::fromBuffers(
}
// Ensure cube maps get the compat flag bit
if ( this->viewType == ext::vulkan::enums::Image::VIEW_TYPE_CUBE || this->viewType == ext::vulkan::enums::Image::VIEW_TYPE_CUBE_ARRAY ) {
imageCreateInfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
imageCreateInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
}
VmaAllocationCreateInfo allocInfo = {};
@ -955,8 +964,8 @@ void ext::vulkan::Texture::generateMipmaps( VkCommandBuffer commandBuffer, uint3
);
if (mipWidth > 1) mipWidth /= 2;
if (mipHeight > 1) mipHeight /= 2;
if (mipDepth > 1) mipDepth /= 2;
if (mipHeight > 1) mipHeight /= 2;
if (mipDepth > 1) mipDepth /= 2;
}
}

View File

@ -2,7 +2,7 @@
#if UF_USE_XATLAS
#include <xatlas/xatlas.h>
#define UF_XATLAS_UNWRAP_MULTITHREAD 1 // prone to crashing
#define UF_XATLAS_UNWRAP_MULTITHREAD 1
size_t ext::xatlas::unwrap( pod::Graph& graph ) {
struct Entry {
@ -56,50 +56,49 @@ size_t ext::xatlas::unwrap( pod::Graph& graph ) {
if ( !should ) continue;
source = mesh;
source.updateDescriptor();
source.updateDescriptor();
for ( size_t viewIdx = 0; viewIdx < source.buffer_views.size(); ++viewIdx ) {
const auto& view = source.buffer_views[viewIdx];
for ( size_t viewIdx = 0; viewIdx < source.buffer_views.size(); ++viewIdx ) {
const auto& view = source.buffer_views[viewIdx];
size_t atlasID = 0;
if ( view.indirectIndex != -1 ) {
pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data();
atlasID = drawCommands[view.indirectIndex].auxID;
}
size_t atlasID = 0;
if ( view.indirectIndex != -1 ) {
pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data();
atlasID = drawCommands[view.indirectIndex].auxID;
}
auto& atlas = atlases[atlasID];
auto& entry = atlas.entries.emplace_back();
entry.index = index;
entry.commandID = viewIdx;
auto& atlas = atlases[atlasID];
auto& entry = atlas.entries.emplace_back();
entry.index = index;
entry.commandID = viewIdx;
auto& decl = entry.decl;
auto posView = view["position"];
auto uvView = view["uv"];
auto idxView = view["index"];
auto& decl = entry.decl;
auto posView = view["position"];
auto uvView = view["uv"];
auto idxView = view["index"];
UF_ASSERT( posView.valid() && uvView.valid() );
UF_ASSERT( posView.valid() && uvView.valid() );
decl.vertexCount = view.vertex.count;
decl.vertexPositionData = posView.data(view.vertex.first);
decl.vertexPositionStride = posView.stride();
decl.vertexUvData = uvView.data(view.vertex.first);
decl.vertexUvStride = uvView.stride();
decl.vertexCount = view.vertex.count;
decl.vertexPositionData = posView.data(view.vertex.first);
decl.vertexPositionStride = posView.stride();
decl.vertexUvData = uvView.data(view.vertex.first);
decl.vertexUvStride = uvView.stride();
if ( idxView.valid() ) {
decl.indexCount = view.index.count;
// Pass view.index.first to offset the index pointer!
decl.indexData = idxView.data(view.index.first);
if ( idxView.valid() ) {
decl.indexCount = view.index.count;
decl.indexData = idxView.data(view.index.first);
switch ( idxView.attribute.descriptor.size ) {
case 1: UF_EXCEPTION("xatlas does not support 8-bit indices"); break;
case 2: decl.indexFormat = ::xatlas::IndexFormat::UInt16; break;
case 4: decl.indexFormat = ::xatlas::IndexFormat::UInt32; break;
default: UF_EXCEPTION("unsupported index type"); break;
}
} else {
decl.indexCount = 0;
}
}
switch ( idxView.attribute.descriptor.size ) {
case 1: UF_EXCEPTION("xatlas does not support 8-bit indices"); break;
case 2: decl.indexFormat = ::xatlas::IndexFormat::UInt16; break;
case 4: decl.indexFormat = ::xatlas::IndexFormat::UInt32; break;
default: UF_EXCEPTION("unsupported index type"); break;
}
} else {
decl.indexCount = 0;
}
}
}
::xatlas::ChartOptions chartOptions{};
@ -236,70 +235,63 @@ size_t ext::xatlas::unwrap( pod::Graph& graph ) {
// update vertices
for ( auto& pair : atlases ) {
auto& atlas = pair.second;
auto& atlas = pair.second;
for ( auto i = 0; i < atlas.pointer->meshCount; i++ ) {
auto& xmesh = atlas.pointer->meshes[i];
auto& entry = atlas.entries[i];
for ( auto i = 0; i < atlas.pointer->meshCount; i++ ) {
auto& xmesh = atlas.pointer->meshes[i];
auto& entry = atlas.entries[i];
auto& name = graph.meshes[entry.index];
auto& mesh = storage.meshes[name];
auto& source = sources[entry.index];
auto& name = graph.meshes[entry.index];
auto& mesh = storage.meshes[name];
auto& source = sources[entry.index];
if ( source.vertex.count == 0 ) continue;
if ( source.vertex.count == 0 ) continue;
// Grab the read-only view from our unmodified source mesh
const auto& srcView = source.buffer_views[entry.commandID];
const auto& srcView = source.buffer_views[entry.commandID];
// We dynamically calculate the destination offsets using the updated draw commands
// Or if it's direct, it's just 0.
size_t dstVertexFirst = 0;
size_t dstIndexFirst = 0;
if ( mesh.indirect.count > 0 ) {
pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data();
dstVertexFirst = drawCommands[entry.commandID].vertexID;
dstIndexFirst = drawCommands[entry.commandID].indexID;
}
size_t dstVertexFirst = 0;
size_t dstIndexFirst = 0;
if ( mesh.indirect.count > 0 ) {
pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data();
dstVertexFirst = drawCommands[entry.commandID].vertexID;
dstIndexFirst = drawCommands[entry.commandID].indexID;
}
// 1. Copy over the vertices based on the xref mapping
for ( auto j = 0; j < xmesh.vertexCount; ++j ) {
auto& vertex = xmesh.vertexArray[j];
uint32_t ref = vertex.xref; // original vertex index relative to the sub-mesh
for ( auto j = 0; j < xmesh.vertexCount; ++j ) {
auto& vertex = xmesh.vertexArray[j];
uint32_t ref = vertex.xref; // original vertex index relative to the sub-mesh
for ( auto attrIdx = 0; attrIdx < mesh.vertex.attributes.size(); ++attrIdx ) {
auto srcAttribute = srcView.vertex.attributes[attrIdx];
auto dstAttribute = mesh.vertex.attributes[attrIdx];
for ( auto attrIdx = 0; attrIdx < mesh.vertex.attributes.size(); ++attrIdx ) {
auto srcAttribute = srcView.vertex.attributes[attrIdx];
auto dstAttribute = mesh.vertex.attributes[attrIdx];
uint8_t* dstPtr = static_cast<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * (dstVertexFirst + j);
uint8_t* dstPtr = static_cast<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * (dstVertexFirst + j);
if ( dstAttribute.descriptor.name == "st" ) {
// Write new lightmap STs!
pod::Vector2f& st = *(pod::Vector2f*)dstPtr;
st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };
} else {
// Copy original vertex data
const uint8_t* srcPtr = static_cast<const uint8_t*>(srcAttribute.pointer) + srcAttribute.stride * (srcView.vertex.first + ref);
memcpy(dstPtr, srcPtr, srcAttribute.descriptor.size);
}
}
}
if ( dstAttribute.descriptor.name == "st" ) {
pod::Vector2f& st = *(pod::Vector2f*)dstPtr;
st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };
} else {
const uint8_t* srcPtr = static_cast<const uint8_t*>(srcAttribute.pointer) + srcAttribute.stride * (srcView.vertex.first + ref);
memcpy(dstPtr, srcPtr, srcAttribute.descriptor.size);
}
}
}
// 2. Write new indices
if ( mesh.index.count ) {
uf::Mesh::Attribute indexAttribute = mesh.index.attributes.front();
uint8_t* dstIndexPtr = static_cast<uint8_t*>(indexAttribute.pointer) + indexAttribute.stride * dstIndexFirst;
if ( mesh.index.count ) {
uf::Mesh::Attribute indexAttribute = mesh.index.attributes.front();
uint8_t* dstIndexPtr = static_cast<uint8_t*>(indexAttribute.pointer) + indexAttribute.stride * dstIndexFirst;
for ( auto idx = 0; idx < xmesh.indexCount; ++idx ) {
switch ( mesh.index.size ) {
case 1: (( uint8_t*) dstIndexPtr)[idx] = (uint8_t) xmesh.indexArray[idx]; break;
case 2: ((uint16_t*) dstIndexPtr)[idx] = (uint16_t) xmesh.indexArray[idx]; break;
case 4: ((uint32_t*) dstIndexPtr)[idx] = (uint32_t) xmesh.indexArray[idx]; break;
}
}
}
mesh.updateDescriptor();
}
}
for ( auto idx = 0; idx < xmesh.indexCount; ++idx ) {
switch ( mesh.index.size ) {
case 1: (( uint8_t*) dstIndexPtr)[idx] = (uint8_t) xmesh.indexArray[idx]; break;
case 2: ((uint16_t*) dstIndexPtr)[idx] = (uint16_t) xmesh.indexArray[idx]; break;
case 4: ((uint32_t*) dstIndexPtr)[idx] = (uint32_t) xmesh.indexArray[idx]; break;
}
}
}
mesh.updateDescriptor();
}
}
// cleanup
size_t atlasCount = 0;

File diff suppressed because it is too large Load Diff

View File

@ -57,10 +57,10 @@ namespace {
}
}
LRESULT CALLBACK globalOnEvent(spec::win32::Window::handle_t handle, UINT message, WPARAM wParam, LPARAM lParam) {
#if UF_USE_IMGUI
#if UF_USE_IMGUI
if (ImGui_ImplWin32_WndProcHandler(handle, message, wParam, lParam))
return true;
#endif
return true;
#endif
if (message == WM_CREATE) {
LONG_PTR window = (LONG_PTR)reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams;
SetWindowLongPtrW(handle, GWLP_USERDATA, window);

View File

@ -6,8 +6,8 @@
namespace {
size_t writeFunction(void *ptr, size_t size, size_t nmemb, uf::stl::string* data) {
data->append((char*) ptr, size * nmemb);
return size * nmemb;
data->append((char*) ptr, size * nmemb);
return size * nmemb;
}
}
@ -39,5 +39,5 @@ uf::Http uf::http::get( const uf::stl::string& url ) {
curl_easy_cleanup(curl);
curl = NULL;
#endif
return http;
return http;
}

View File

@ -190,11 +190,11 @@ uf::stl::vector<uint8_t>& uf::io::readAsBuffer( uf::stl::vector<uint8_t>& buffer
// Read each range
size_t currentOffset = 0;
for (const auto& r : ranges) {
is.seekg(r.start, std::ios::beg);
is.read(reinterpret_cast<char*>(buffer.data() + currentOffset), r.len);
currentOffset += static_cast<size_t>(is.gcount());
}
for (const auto& r : ranges) {
is.seekg(r.start, std::ios::beg);
is.read(reinterpret_cast<char*>(buffer.data() + currentOffset), r.len);
currentOffset += static_cast<size_t>(is.gcount());
}
}
uf::stl::string expected;

View File

@ -3,18 +3,18 @@
// credit: https://github.com/zeux/meshoptimizer/blob/master/src/quantization.cpp
uint16_t UF_API uf::quant::quantize_f32u16( float v ) {
union { float f; uint32_t ui; } u = {v};
uint32_t ui = u.ui;
uint32_t ui = u.ui;
int s = (ui >> 16) & 0x8000;
int em = ui & 0x7fffffff;
int s = (ui >> 16) & 0x8000;
int em = ui & 0x7fffffff;
int h = (em - (112 << 23) + (1 << 12)) >> 13;
h = (em < (113 << 23)) ? 0 : h;
h = (em >= (143 << 23)) ? 0x7c00 : h;
h = (em > (255 << 23)) ? 0x7e00 : h;
int h = (em - (112 << 23) + (1 << 12)) >> 13;
h = (em < (113 << 23)) ? 0 : h;
h = (em >= (143 << 23)) ? 0x7c00 : h;
h = (em > (255 << 23)) ? 0x7e00 : h;
uint16_t res = (s | h);
return res;
uint16_t res = (s | h);
return res;
}
float UF_API uf::quant::dequantize_u16f32( uint16_t h ) {
uint32_t s = unsigned(h & 0x8000) << 16;

View File

@ -10,78 +10,78 @@ static const int B64index[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 };
static const uint8_t base64_table[65] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
uf::stl::string uf::base64::encode( const uint8_t* src, size_t len ) {
uint8_t *out, *pos;
const uint8_t *end, *in;
uint8_t *out, *pos;
const uint8_t *end, *in;
size_t olen;
size_t olen;
olen = 4*((len + 2) / 3);
olen = 4*((len + 2) / 3);
if (olen < len)
return uf::stl::string();
if (olen < len)
return uf::stl::string();
uf::stl::string outStr;
outStr.resize(olen);
out = (uint8_t*)&outStr[0];
uf::stl::string outStr;
outStr.resize(olen);
out = (uint8_t*)&outStr[0];
end = src + len;
in = src;
pos = out;
while (end - in >= 3) {
*pos++ = base64_table[in[0] >> 2];
*pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
*pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)];
*pos++ = base64_table[in[2] & 0x3f];
in += 3;
}
end = src + len;
in = src;
pos = out;
while (end - in >= 3) {
*pos++ = base64_table[in[0] >> 2];
*pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
*pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)];
*pos++ = base64_table[in[2] & 0x3f];
in += 3;
}
if (end - in) {
*pos++ = base64_table[in[0] >> 2];
if (end - in == 1) {
*pos++ = base64_table[(in[0] & 0x03) << 4];
*pos++ = '=';
}
else {
*pos++ = base64_table[((in[0] & 0x03) << 4) |
(in[1] >> 4)];
*pos++ = base64_table[(in[1] & 0x0f) << 2];
}
*pos++ = '=';
}
if (end - in) {
*pos++ = base64_table[in[0] >> 2];
if (end - in == 1) {
*pos++ = base64_table[(in[0] & 0x03) << 4];
*pos++ = '=';
}
else {
*pos++ = base64_table[((in[0] & 0x03) << 4) |
(in[1] >> 4)];
*pos++ = base64_table[(in[1] & 0x0f) << 2];
}
*pos++ = '=';
}
return outStr;
return outStr;
}
// uf::stl::vector<uint8_t> uf::base64::decode( const uint8_t* data, size_t len ) {
uf::stl::vector<uint8_t> uf::base64::decode( const uf::stl::string& data ) {
size_t len = data.size();
uint8_t* p = (uint8_t*) &data[0];
int pad = len > 0 && (len % 4 || p[len - 1] == '=');
const size_t L = ((len + 3) / 4 - pad) * 4;
uf::stl::vector<uint8_t> str(L / 4 * 3 + pad, '\0');
uint8_t* p = (uint8_t*) &data[0];
int pad = len > 0 && (len % 4 || p[len - 1] == '=');
const size_t L = ((len + 3) / 4 - pad) * 4;
uf::stl::vector<uint8_t> str(L / 4 * 3 + pad, '\0');
for (size_t i = 0, j = 0; i < L; i += 4)
{
int n = B64index[p[i]] << 18 | B64index[p[i + 1]] << 12 | B64index[p[i + 2]] << 6 | B64index[p[i + 3]];
str[j++] = n >> 16;
str[j++] = n >> 8 & 0xFF;
str[j++] = n & 0xFF;
}
if (pad)
{
int n = B64index[p[L]] << 18 | B64index[p[L + 1]] << 12;
str[str.size() - 1] = n >> 16;
for (size_t i = 0, j = 0; i < L; i += 4)
{
int n = B64index[p[i]] << 18 | B64index[p[i + 1]] << 12 | B64index[p[i + 2]] << 6 | B64index[p[i + 3]];
str[j++] = n >> 16;
str[j++] = n >> 8 & 0xFF;
str[j++] = n & 0xFF;
}
if (pad)
{
int n = B64index[p[L]] << 18 | B64index[p[L + 1]] << 12;
str[str.size() - 1] = n >> 16;
if (len > L + 2 && p[L + 2] != '=')
{
n |= B64index[p[L + 2]] << 6;
str.push_back(n >> 8 & 0xFF);
}
}
return str;
if (len > L + 2 && p[L + 2] != '=')
{
n |= B64index[p[L + 2]] << 6;
str.push_back(n >> 8 & 0xFF);
}
}
return str;
}
uf::stl::string uf::string::base64::encode( const uf::stl::string& input ) {
@ -95,9 +95,9 @@ uf::stl::string uf::string::base64::decode( const uf::stl::string& input ) {
/*
static const uf::stl::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
static inline bool is_base64(uint8_t c) {
@ -112,34 +112,34 @@ uf::stl::string uf::base64::encode(const uint8_t* buf, std::size_t bufLen) {
uint8_t char_array_4[4];
while (bufLen--) {
char_array_3[i++] = *(buf++);
if (i == 3) {
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
char_array_3[i++] = *(buf++);
if (i == 3) {
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for(i = 0; (i <4) ; i++)
ret += base64_chars[char_array_4[i]];
i = 0;
}
for(i = 0; (i <4) ; i++)
ret += base64_chars[char_array_4[i]];
i = 0;
}
}
if (i)
{
for(j = i; j < 3; j++)
char_array_3[j] = '\0';
for(j = i; j < 3; j++)
char_array_3[j] = '\0';
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (j = 0; (j < i + 1); j++)
ret += base64_chars[char_array_4[j]];
for (j = 0; (j < i + 1); j++)
ret += base64_chars[char_array_4[j]];
while((i++ < 3))
ret += '=';
while((i++ < 3))
ret += '=';
}
return ret;
@ -154,33 +154,33 @@ uf::stl::vector<uint8_t> uf::base64::decode(const uf::stl::string& encoded_strin
uf::stl::vector<uint8_t> ret;
while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
char_array_4[i++] = encoded_string[in_]; in_++;
if (i ==4) {
for (i = 0; i <4; i++)
char_array_4[i] = base64_chars.find(char_array_4[i]);
char_array_4[i++] = encoded_string[in_]; in_++;
if (i ==4) {
for (i = 0; i <4; i++)
char_array_4[i] = base64_chars.find(char_array_4[i]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (i = 0; (i < 3); i++)
ret.push_back(char_array_3[i]);
i = 0;
}
for (i = 0; (i < 3); i++)
ret.push_back(char_array_3[i]);
i = 0;
}
}
if (i) {
for (j = i; j <4; j++)
char_array_4[j] = 0;
for (j = i; j <4; j++)
char_array_4[j] = 0;
for (j = 0; j <4; j++)
char_array_4[j] = base64_chars.find(char_array_4[j]);
for (j = 0; j <4; j++)
char_array_4[j] = base64_chars.find(char_array_4[j]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (j = 0; (j < i - 1); j++) ret.push_back(char_array_3[j]);
for (j = 0; (j < i - 1); j++) ret.push_back(char_array_3[j]);
}
return ret;

View File

@ -9,10 +9,10 @@ namespace {
int status = -4;
std::unique_ptr<char, void(*)(void*)> demangled{
abi::__cxa_demangle(mangled.c_str(), NULL, NULL, &status),
std::free
};
return ( status == 0 ) ? demangled.get() : mangled;
abi::__cxa_demangle(mangled.c_str(), NULL, NULL, &status),
std::free
};
return ( status == 0 ) ? demangled.get() : mangled;
/*
int status;
char* pointer = abi::__cxa_demangle(mangled.c_str(), 0, 0, &status);