Commit for 2021.07.16 23-54-06.7z
This commit is contained in:
parent
5d9de97436
commit
6d8fbc6ee5
2
Makefile
2
Makefile
@ -1,5 +1,5 @@
|
||||
ARCH = win64
|
||||
CC = $(shell cat "./bin/exe/default.config")
|
||||
CC = $(shell cat "./bin/exe/default.config")
|
||||
TARGET_NAME = program
|
||||
TARGET_EXTENSION = exe
|
||||
TARGET_LIB_EXTENSION = dll
|
||||
|
||||
@ -1,46 +1,52 @@
|
||||
{
|
||||
"engine": {
|
||||
"scenes": {
|
||||
"start": "SS2",
|
||||
"start": "McDonalds",
|
||||
"lights": {
|
||||
"max": 512,
|
||||
"max": 64,
|
||||
"enabled": true
|
||||
},
|
||||
"shadows": {
|
||||
"enabled": true,
|
||||
"update": 4,
|
||||
"update": 2,
|
||||
"max": 8,
|
||||
"samples": 2,
|
||||
"experimental mode": 1
|
||||
},
|
||||
"textures": {
|
||||
"max": {
|
||||
"2D": 512,
|
||||
"2D": 1024,
|
||||
"cube": 128,
|
||||
"3D": 1
|
||||
}
|
||||
},
|
||||
"meshes": {
|
||||
"interleave": false
|
||||
},
|
||||
"matrix": {
|
||||
"reverseInfinite": true
|
||||
},
|
||||
"vxgi": {
|
||||
"limiter": 0.125,
|
||||
"size": 64,
|
||||
"size": 96,
|
||||
"dispatch": 8,
|
||||
"cascades": 4,
|
||||
"cascades": 6,
|
||||
"cascadePower": 4,
|
||||
"shadows": 0,
|
||||
"granularity": 4,
|
||||
"extents": {
|
||||
"min": [ -2.5, -2.5, -2.5 ],
|
||||
"max": [ 2.5, 2.5, 2.5 ]
|
||||
"min": [ -1.5, -1.5, -1.5 ],
|
||||
"max": [ 1.5, 1.5, 1.5 ]
|
||||
}
|
||||
}
|
||||
},
|
||||
"ext": {
|
||||
"vulkan": {
|
||||
"validation": {
|
||||
"enabled": true,
|
||||
"enabled": false,
|
||||
"filters": [
|
||||
"MessageID = 0x4dae5635", // UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout (false positive for cubemaps)
|
||||
"MessageID = 0x71500fba", // VUID-vkDestroyDevice-device-00378 (don't care about a clean cleanup)
|
||||
// "MessageID = 0x71500fba", // VUID-vkDestroyDevice-device-00378 (don't care about a clean cleanup)
|
||||
"MessageID = 0x609a13b", // UNASSIGNED-CoreValidation-Shader-OutputNotConsumed (from depth-only calls)
|
||||
"MessageID = 0x23e43bb7" // UNASSIGNED-CoreValidation-Shader-InputNotProduced (from depth-only calls)
|
||||
// "MessageID = 0xe91b58a0" // VUID-vkCmdDrawIndexed-None-02686 (?)
|
||||
@ -66,8 +72,9 @@
|
||||
"deferred alias output to swapchain": true,
|
||||
"vsync": true,
|
||||
"hdr": false,
|
||||
"vxgi": false,
|
||||
"deferred sampling": false
|
||||
"vxgi": true,
|
||||
"deferred sampling": true,
|
||||
"culling": false
|
||||
},
|
||||
"formats": {
|
||||
"depth": "D32_SFLOAT",
|
||||
@ -76,6 +83,10 @@
|
||||
"position": "R16G16B16A16_SFLOAT"
|
||||
},
|
||||
"features": [
|
||||
"shaderDrawParameters",
|
||||
"multiDrawIndirect",
|
||||
"fillModeNonSolid",
|
||||
"wideLines",
|
||||
"independentBlend",
|
||||
"deviceCoherentMemory",
|
||||
"robustBufferAccess",
|
||||
@ -117,7 +128,8 @@
|
||||
// "deferred mode": "deferredSampling",
|
||||
"deferred reconstruct position": true,
|
||||
"deferred alias output to swapchain": true,
|
||||
"hdr": false
|
||||
"hdr": false,
|
||||
"culling": true
|
||||
},
|
||||
"formats": {
|
||||
"depth": "D32_SFLOAT",
|
||||
@ -159,7 +171,7 @@
|
||||
},
|
||||
"debug draw": {
|
||||
"enabled": false,
|
||||
"rate": 1.0
|
||||
"rate": 0.0125
|
||||
}
|
||||
},
|
||||
"discord": {
|
||||
@ -175,7 +187,7 @@
|
||||
"streams by default": true
|
||||
},
|
||||
"memory pool": {
|
||||
"enabled": false,
|
||||
"enabled": true,
|
||||
"subPools": true,
|
||||
"alignment": 64,
|
||||
"override": false,
|
||||
@ -212,8 +224,8 @@
|
||||
"announce": true
|
||||
},
|
||||
"entity": {
|
||||
"delete children on destroy": false,
|
||||
"delete components on destroy": false
|
||||
"delete children on destroy": true,
|
||||
"delete components on destroy": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@ -35,7 +35,7 @@
|
||||
"slope": 1.75,
|
||||
"shader": 0.000005 //0.000000005
|
||||
},
|
||||
"radius": [0.001, 0],
|
||||
"radius": [0.001, 256.0],
|
||||
"resolution": 1024,
|
||||
"shadows": true,
|
||||
"static": false
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
"name": "Gui: Loading",
|
||||
"type": "Object",
|
||||
"behaviors": [
|
||||
"GuiBehavior"
|
||||
// "GuiBehavior"
|
||||
],
|
||||
"assets": [
|
||||
{ "filename": "./mcdonalds.json", "delay": 0 }
|
||||
|
||||
@ -5,9 +5,9 @@
|
||||
"assets": [
|
||||
// { "filename": "./static.json", "delay": 8 },
|
||||
|
||||
// { "filename": "./models/mcdonalds.glb", "delay": 0, "single threaded": false }
|
||||
{ "filename": "./models/mcdonalds.glb", "delay": 0, "single threaded": false }
|
||||
// { "filename": "./models/mcdonalds/graph.json", "delay": 0, "single threaded": false, "category": "models" }
|
||||
{ "filename": "./models/mcdonalds/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" }
|
||||
// { "filename": "./models/mcdonalds/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" }
|
||||
],
|
||||
"behaviors": [
|
||||
"LoadingBehavior"
|
||||
@ -44,7 +44,7 @@
|
||||
|
||||
// "filter": "NEAREST",
|
||||
"flags": {
|
||||
"ATLAS": true,
|
||||
"ATLAS": false,
|
||||
"INVERT": false,
|
||||
"TRANSFORM": false,
|
||||
"SKINNED": false,
|
||||
|
||||
@ -5,9 +5,9 @@
|
||||
"assets": [
|
||||
// { "filename": "./static.json", "delay": 8 },
|
||||
|
||||
// { "filename": "./models/sh_mcd.glb", "delay": 0, "single threaded": false }
|
||||
{ "filename": "./models/sh_mcd.glb", "delay": 0, "single threaded": false }
|
||||
// { "filename": "./models/sh_mcd/graph.json", "delay": 0, "single threaded": false, "category": "models" }
|
||||
{ "filename": "./models/sh_mcd/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" }
|
||||
// { "filename": "./models/sh_mcd/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" }
|
||||
],
|
||||
"behaviors": [
|
||||
"LoadingBehavior"
|
||||
|
||||
@ -50,12 +50,13 @@
|
||||
// "lightmap": "./lightmap.png",
|
||||
"filter": "NEAREST",
|
||||
"flags": {
|
||||
"ATLAS": true,
|
||||
"ATLAS": false,
|
||||
"INVERT": false,
|
||||
"TRANSFORM": false,
|
||||
"SKINNED": false,
|
||||
|
||||
"RENDER": true,
|
||||
// "SEPARATE": false,
|
||||
"SEPARATE": false,
|
||||
"NORMALS": false
|
||||
},
|
||||
|
||||
13
bin/data/shaders/bullet/base.frag.glsl
Normal file
13
bin/data/shaders/bullet/base.frag.glsl
Normal file
@ -0,0 +1,13 @@
|
||||
#version 450
|
||||
#pragma shader_stage(fragment)
|
||||
|
||||
layout (location = 0) in vec3 inPosition;
|
||||
layout (location = 1) in vec3 inColor;
|
||||
|
||||
layout (location = 0) out uvec2 outId;
|
||||
layout (location = 1) out vec2 outNormals;
|
||||
layout (location = 2) out vec4 outAlbedo;
|
||||
|
||||
void main() {
|
||||
outAlbedo = vec4(inColor, 1);
|
||||
}
|
||||
28
bin/data/shaders/bullet/base.vert.glsl
Normal file
28
bin/data/shaders/bullet/base.vert.glsl
Normal file
@ -0,0 +1,28 @@
|
||||
#version 450
|
||||
#pragma shader_stage(vertex)
|
||||
|
||||
#include "../common/structs.h"
|
||||
|
||||
layout (constant_id = 0) const uint PASSES = 6;
|
||||
|
||||
layout (location = 0) in vec3 inPos;
|
||||
layout (location = 1) in vec3 inColor;
|
||||
|
||||
layout( push_constant ) uniform PushBlock {
|
||||
uint pass;
|
||||
uint draw;
|
||||
} PushConstant;
|
||||
|
||||
layout (binding = 0) uniform Camera {
|
||||
Viewport viewport[PASSES];
|
||||
} camera;
|
||||
|
||||
layout (location = 0) out vec3 outPosition;
|
||||
layout (location = 1) out vec3 outColor;
|
||||
|
||||
void main() {
|
||||
outPosition = vec3(camera.viewport[PushConstant.pass].view * vec4(inPos.xyz, 1.0));
|
||||
outColor = inColor;
|
||||
|
||||
gl_Position = camera.viewport[PushConstant.pass].projection * camera.viewport[PushConstant.pass].view * vec4(inPos.xyz, 1.0);
|
||||
}
|
||||
@ -24,6 +24,7 @@ void pbr() {
|
||||
if ( light.power <= LIGHT_POWER_CUTOFF ) continue;
|
||||
const vec3 Liu = vec3(ubo.eyes[surface.pass].view * vec4(light.position, 1)) - surface.position.eye;
|
||||
const vec3 Li = normalize(Liu);
|
||||
const bool reverseZ = light.projection[2][2] < 0.00001;
|
||||
const float Ls = shadowFactor( light, 0.0 );
|
||||
const float La = 1.0 / (PI * pow(length(Liu), 2.0));
|
||||
if ( light.power * La * Ls <= LIGHT_POWER_CUTOFF ) continue;
|
||||
|
||||
@ -86,9 +86,9 @@ struct Material {
|
||||
int indexOcclusion;
|
||||
|
||||
int indexMetallicRoughness;
|
||||
int indexAtlas;
|
||||
int indexLightmap;
|
||||
int modeAlpha;
|
||||
int padding;
|
||||
};
|
||||
|
||||
struct Texture {
|
||||
@ -107,9 +107,28 @@ struct DrawCommand {
|
||||
int vertexID; // starting vertex position
|
||||
|
||||
uint instanceID; // starting instance position
|
||||
uint materialID; // material used for draw
|
||||
uint objectID; //
|
||||
uint vertices; //
|
||||
uint padding; //
|
||||
uint materialID; // material to use for this draw call
|
||||
uint vertices; // number of vertices used
|
||||
};
|
||||
|
||||
struct Bounds {
|
||||
vec3 min;
|
||||
float padding1;
|
||||
vec3 max;
|
||||
float padding2;
|
||||
};
|
||||
|
||||
struct Instance {
|
||||
mat4 model;
|
||||
vec4 color;
|
||||
|
||||
uint materialID;
|
||||
uint primitiveID;
|
||||
uint meshID;
|
||||
uint objectID;
|
||||
|
||||
Bounds bounds;
|
||||
};
|
||||
|
||||
struct SurfaceMaterial {
|
||||
@ -122,7 +141,6 @@ struct SurfaceMaterial {
|
||||
float roughness;
|
||||
float occlusion;
|
||||
int indexLightmap;
|
||||
|
||||
};
|
||||
|
||||
struct Surface {
|
||||
|
||||
@ -1,18 +1,13 @@
|
||||
#version 450
|
||||
#pragma shader_stage(vertex)
|
||||
|
||||
#if 0
|
||||
layout (location = 0) in vec2 inPos;
|
||||
layout (location = 1) in vec2 inUv;
|
||||
|
||||
#endif
|
||||
layout (location = 0) out vec2 outUv;
|
||||
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
};
|
||||
|
||||
|
||||
void main() {
|
||||
outUv = inUv;
|
||||
|
||||
gl_Position = vec4(inPos.xy, 0.0, 1.0);
|
||||
outUv = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
|
||||
gl_Position = vec4(outUv * 2.0f + -1.0f, 0.0f, 1.0f);
|
||||
}
|
||||
@ -19,10 +19,6 @@ layout( push_constant ) uniform PushBlock {
|
||||
uint draw;
|
||||
} PushConstant;
|
||||
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
};
|
||||
|
||||
struct Matrices {
|
||||
mat4 model[2];
|
||||
};
|
||||
@ -34,9 +30,8 @@ layout (binding = 0) uniform UBO {
|
||||
} ubo;
|
||||
|
||||
void main() {
|
||||
outUv = inUv;
|
||||
outUv = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
|
||||
outCursor = ubo.cursor;
|
||||
outAlpha = 1;
|
||||
|
||||
gl_Position = ubo.matrices.model[PushConstant.pass] * vec4(inPos.xy, 0.0, 1.0);
|
||||
gl_Position = ubo.matrices.model[PushConstant.pass] * vec4(outUv * 2.0f + -1.0f, 0.0f, 1.0f);
|
||||
}
|
||||
@ -53,9 +53,13 @@ layout (binding = 4) uniform UBO {
|
||||
uint shadowSamples;
|
||||
uint indexSkybox;
|
||||
} ubo;
|
||||
|
||||
layout (std140, binding = 5) readonly buffer Lights {
|
||||
Light lights[];
|
||||
/*
|
||||
layout (std140, binding = 5) readonly buffer DrawCommands {
|
||||
DrawCommand drawCommands[];
|
||||
};
|
||||
*/
|
||||
layout (std140, binding = 5) readonly buffer Instances {
|
||||
Instance instances[];
|
||||
};
|
||||
layout (std140, binding = 6) readonly buffer Materials {
|
||||
Material materials[];
|
||||
@ -63,8 +67,8 @@ layout (std140, binding = 6) readonly buffer Materials {
|
||||
layout (std140, binding = 7) readonly buffer Textures {
|
||||
Texture textures[];
|
||||
};
|
||||
layout (std140, binding = 8) readonly buffer DrawCommands {
|
||||
DrawCommand drawCommands[];
|
||||
layout (std140, binding = 8) readonly buffer Lights {
|
||||
Light lights[];
|
||||
};
|
||||
|
||||
layout (binding = 9) uniform sampler2D samplerTextures[TEXTURES];
|
||||
@ -161,15 +165,17 @@ void populateSurface() {
|
||||
#endif
|
||||
surface.normal.eye = vec3( ubo.eyes[surface.pass].view * vec4(surface.normal.world, 0.0) );
|
||||
|
||||
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;
|
||||
surface.fragment.a = 0.0;
|
||||
postProcess();
|
||||
return;
|
||||
}
|
||||
const uint drawId = ID.x - 1;
|
||||
const DrawCommand drawCommand = drawCommands[drawId];
|
||||
surface.material.id = ID.y + drawCommand.materialID - 1;
|
||||
// const DrawCommand drawCommand = drawCommands[drawID];
|
||||
const Instance instance = instances[instanceID];
|
||||
surface.material.id = instance.materialID;
|
||||
const Material material = materials[surface.material.id];
|
||||
surface.material.albedo = material.colorBase;
|
||||
surface.fragment = material.colorEmissive;
|
||||
@ -180,8 +186,6 @@ void populateSurface() {
|
||||
surface.uv = resolve(samplerUv, ubo.msaa).xy;
|
||||
#endif
|
||||
const float mip = mipLevel(inUv.xy);
|
||||
// if ( validTextureIndex( drawCommand.textureIndex, material.indexAlbedo ) ) {
|
||||
// surface.material.albedo = sampleTexture( drawCommand.textureIndex, drawCommand.textureSlot, material.indexAlbedo, material.indexAtlas, mip );
|
||||
if ( validTextureIndex( material.indexAlbedo ) ) {
|
||||
surface.material.albedo = sampleTexture( material.indexAlbedo, mip );
|
||||
}
|
||||
@ -196,8 +200,6 @@ void populateSurface() {
|
||||
|
||||
}
|
||||
// Emissive textures
|
||||
// if ( validTextureIndex( drawCommand.textureIndex, material.indexEmissive ) ) {
|
||||
// surface.fragment += sampleTexture( drawCommand.textureIndex, drawCommand.textureSlot, material.indexEmissive, material.indexAtlas, mip );
|
||||
if ( validTextureIndex( material.indexEmissive ) ) {
|
||||
surface.fragment += sampleTexture( material.indexEmissive, mip );
|
||||
}
|
||||
@ -217,7 +219,7 @@ void populateSurface() {
|
||||
void directLighting() {
|
||||
const vec3 ambient = ubo.ambient.rgb * surface.material.occlusion + surface.material.indirect.rgb;
|
||||
surface.fragment.rgb += (0 <= surface.material.indexLightmap) ? (surface.material.albedo.rgb + ambient) : (surface.material.albedo.rgb * ambient);
|
||||
|
||||
if ( ubo.lights == 0 ) { surface.fragment.rgb = surface.material.albedo.rgb; return; }
|
||||
#if PBR
|
||||
pbr();
|
||||
#elif LAMBERT
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
#version 450
|
||||
#pragma shader_stage(vertex)
|
||||
|
||||
#if 0
|
||||
layout (location = 0) in vec2 inPos;
|
||||
layout (location = 1) in vec2 inUv;
|
||||
|
||||
#endif
|
||||
layout (location = 0) out vec2 outUv;
|
||||
layout (location = 1) out flat uint outPushConstantPass;
|
||||
|
||||
@ -18,8 +19,11 @@ out gl_PerVertex {
|
||||
|
||||
|
||||
void main() {
|
||||
outUv = inUv;
|
||||
outPushConstantPass = PushConstant.pass;
|
||||
|
||||
outUv = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
|
||||
gl_Position = vec4(outUv * 2.0f + -1.0f, 0.0f, 1.0f);
|
||||
#if 0
|
||||
outUv = inUv;
|
||||
gl_Position = vec4(inPos.xy, 0.0, 1.0);
|
||||
#endif
|
||||
}
|
||||
@ -36,9 +36,13 @@ layout (binding = 4) uniform UBO {
|
||||
uint shadowSamples;
|
||||
uint indexSkybox;
|
||||
} ubo;
|
||||
|
||||
layout (std140, binding = 5) readonly buffer Lights {
|
||||
Light lights[];
|
||||
/*
|
||||
layout (std140, binding = 5) readonly buffer DrawCommands {
|
||||
DrawCommand drawCommands[];
|
||||
};
|
||||
*/
|
||||
layout (std140, binding = 5) readonly buffer Instances {
|
||||
Instance instances[];
|
||||
};
|
||||
layout (std140, binding = 6) readonly buffer Materials {
|
||||
Material materials[];
|
||||
@ -46,8 +50,8 @@ layout (std140, binding = 6) readonly buffer Materials {
|
||||
layout (std140, binding = 7) readonly buffer Textures {
|
||||
Texture textures[];
|
||||
};
|
||||
layout (std140, binding = 8) readonly buffer DrawCommands {
|
||||
DrawCommand drawCommands[];
|
||||
layout (std140, binding = 8) readonly buffer Lights {
|
||||
Light lights[];
|
||||
};
|
||||
|
||||
layout (binding = 9) uniform sampler2D samplerTextures[TEXTURES];
|
||||
@ -76,21 +80,21 @@ void main() {
|
||||
surface.position.world = vec3( inverse(ubo.vxgi.matrix) * vec4( surface.position.eye, 1.0f ) );
|
||||
|
||||
const uvec2 ID = uvec2(imageLoad(voxelId[CASCADE], ivec3(tUvw) ).xy);
|
||||
const uint drawID = ID.x - 1;
|
||||
const uint instanceID = ID.y - 1;
|
||||
if ( ID.x == 0 || ID.y == 0 ) {
|
||||
imageStore(voxelRadiance[CASCADE], ivec3(tUvw), vec4(0));
|
||||
continue;
|
||||
}
|
||||
const uint drawId = ID.x - 1;
|
||||
const DrawCommand drawCommand = drawCommands[drawId];
|
||||
surface.material.id = ID.y + drawCommand.materialID - 1;
|
||||
// const DrawCommand drawCommand = drawCommands[drawID];
|
||||
const Instance instance = instances[instanceID];
|
||||
surface.material.id = instance.materialID;
|
||||
const Material material = materials[surface.material.id];
|
||||
surface.material.albedo = material.colorBase;
|
||||
surface.fragment = material.colorEmissive;
|
||||
|
||||
#if DEFERRED_SAMPLING
|
||||
surface.uv = imageLoad(voxelUv[CASCADE], ivec3(tUvw) ).xy;
|
||||
// if ( validTextureIndex( drawCommand.textureIndex, material.indexAlbedo ) ) {
|
||||
// surface.material.albedo = sampleTexture( drawCommand.textureIndex, drawCommand.textureSlot, material.indexAlbedo, material.indexAtlas );
|
||||
if ( validTextureIndex( material.indexAlbedo ) ) {
|
||||
surface.material.albedo = sampleTexture( material.indexAlbedo );
|
||||
}
|
||||
@ -106,8 +110,6 @@ void main() {
|
||||
|
||||
}
|
||||
// Emissive textures
|
||||
// if ( validTextureIndex( drawCommand.textureIndex, material.indexEmissive ) ) {
|
||||
// surface.fragment += sampleTexture( drawCommand.textureIndex, drawCommand.textureSlot, material.indexEmissive, material.indexAtlas );
|
||||
if ( validTextureIndex( material.indexEmissive ) ) {
|
||||
surface.fragment += sampleTexture( material.indexEmissive );
|
||||
}
|
||||
|
||||
@ -1,50 +0,0 @@
|
||||
#version 450
|
||||
#pragma shader_stage(vertex)
|
||||
|
||||
layout (constant_id = 0) const uint PASSES = 6;
|
||||
layout (location = 0) in vec3 inPos;
|
||||
layout (location = 1) in vec2 inUv;
|
||||
layout (location = 2) in vec2 inSt;
|
||||
layout (location = 3) in vec3 inNormal;
|
||||
layout (location = 4) in vec4 inTangent;
|
||||
layout (location = 5) in uvec2 inId;
|
||||
|
||||
layout( push_constant ) uniform PushBlock {
|
||||
uint pass;
|
||||
uint draw;
|
||||
} PushConstant;
|
||||
|
||||
layout (std140, binding = 0) readonly buffer Models {
|
||||
mat4 models[];
|
||||
};
|
||||
|
||||
layout (location = 0) out vec2 outUv;
|
||||
layout (location = 1) out vec4 outColor;
|
||||
layout (location = 2) out vec3 outNormal;
|
||||
layout (location = 3) out mat3 outTBN;
|
||||
layout (location = 6) out vec3 outPosition;
|
||||
layout (location = 7) out ivec4 outId;
|
||||
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
};
|
||||
|
||||
void main() {
|
||||
outUv = inUv;
|
||||
outColor = vec4(1.0);
|
||||
outId = ivec4(inId, PushConstant.pass, PushConstant.draw);
|
||||
|
||||
mat4 model = models.length() <= 0 ? mat4(1.0) : models[int(inId.x)];
|
||||
outPosition = vec3(model * vec4(inPos.xyz, 1.0));
|
||||
outNormal = vec3(model * vec4(inNormal.xyz, 0.0));
|
||||
outNormal = normalize(outNormal);
|
||||
|
||||
{
|
||||
vec3 T = vec3(model * vec4(inTangent.xyz, 0.0));
|
||||
vec3 N = outNormal;
|
||||
vec3 B = cross(N, T) * inTangent.w;
|
||||
outTBN = mat3( T, B, N );
|
||||
}
|
||||
|
||||
gl_Position = vec4(inSt * 2.0 - 1.0, 0.0, 1.0);
|
||||
}
|
||||
@ -45,5 +45,5 @@ void main() {
|
||||
A = textureLod( samplerTextures[0], inSt, mip );
|
||||
#endif
|
||||
outNormals = encodeNormals( N );
|
||||
outId = ivec2(inId.w+1, inId.y+1);
|
||||
outId = ivec2(inId.x+1, inId.y+1);
|
||||
}
|
||||
6
bin/data/shaders/graph/baking/bake.vert.glsl
Normal file
6
bin/data/shaders/graph/baking/bake.vert.glsl
Normal file
@ -0,0 +1,6 @@
|
||||
#version 450
|
||||
#pragma shader_stage(vertex)
|
||||
|
||||
#define INSTANCED 1
|
||||
#define SKINNED 0
|
||||
#include "../base.vert.h"
|
||||
@ -1,6 +1,7 @@
|
||||
#extension GL_EXT_nonuniform_qualifier : enable
|
||||
|
||||
#define CUBEMAPS 1
|
||||
// #define MAX_TEXTURES TEXTURES
|
||||
#define MAX_TEXTURES textures.length()
|
||||
layout (constant_id = 0) const uint TEXTURES = 1;
|
||||
|
||||
@ -8,7 +9,6 @@ layout (constant_id = 0) const uint TEXTURES = 1;
|
||||
#include "../common/structs.h"
|
||||
|
||||
layout (binding = 0) uniform sampler2D samplerTextures[TEXTURES];
|
||||
|
||||
layout (std140, binding = 1) readonly buffer Materials {
|
||||
Material materials[];
|
||||
};
|
||||
@ -35,28 +35,28 @@ layout (location = 1) out vec2 outNormals;
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
const uint drawID = uint(inId.x);
|
||||
const uint instanceID = uint(inId.y);
|
||||
const uint materialID = uint(inId.z);
|
||||
const float mip = mipLevel(inUv.xy);
|
||||
const vec2 uv = wrap(inUv.xy);
|
||||
const vec3 P = inPosition;
|
||||
vec3 N = inNormal;
|
||||
vec4 A = vec4(0, 0, 0, 0);
|
||||
|
||||
#if DEFERRED_SAMPLING
|
||||
vec4 outAlbedo = vec4(0,0,0,0);
|
||||
#endif
|
||||
#if !DEFERRED_SAMPLING || CAN_DISCARD
|
||||
const int materialId = int(inId.y);
|
||||
Material material = materials[materialId];
|
||||
Material material = materials[materialID];
|
||||
|
||||
float M = material.factorMetallic;
|
||||
float R = material.factorRoughness;
|
||||
float AO = material.factorOcclusion;
|
||||
|
||||
// sample albedo
|
||||
const bool useAtlas = validTextureIndex( material.indexAtlas );
|
||||
Texture textureAtlas;
|
||||
if ( useAtlas ) textureAtlas = textures[material.indexAtlas];
|
||||
if ( !validTextureIndex( material.indexAlbedo ) ) discard; {
|
||||
Texture t = textures[material.indexAlbedo];
|
||||
const Texture t = textures[material.indexAlbedo];
|
||||
A = textureLod( samplerTextures[nonuniformEXT(t.index)], mix( t.lerp.xy, t.lerp.zw, uv ), mip );
|
||||
// alpha mode OPAQUE
|
||||
if ( material.modeAlpha == 0 ) {
|
||||
@ -110,5 +110,5 @@ void main() {
|
||||
outUvs = wrap(inUv.xy);
|
||||
#endif
|
||||
outNormals = encodeNormals( N );
|
||||
outId = ivec2(inId.w+1, inId.y+1);
|
||||
outId = uvec2(drawID + 1, instanceID + 1);
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
layout (constant_id = 0) const uint PASSES = 6;
|
||||
|
||||
#extension GL_ARB_shader_draw_parameters : enable
|
||||
#include "../common/structs.h"
|
||||
|
||||
layout (location = 0) in vec3 inPos;
|
||||
@ -7,10 +7,9 @@ layout (location = 1) in vec2 inUv;
|
||||
layout (location = 2) in vec2 inSt;
|
||||
layout (location = 3) in vec3 inNormal;
|
||||
layout (location = 4) in vec4 inTangent;
|
||||
layout (location = 5) in uvec2 inId;
|
||||
#if SKINNED
|
||||
layout (location = 6) in uvec4 inJoints;
|
||||
layout (location = 7) in vec4 inWeights;
|
||||
layout (location = 5) in uvec4 inJoints;
|
||||
layout (location = 6) in vec4 inWeights;
|
||||
#endif
|
||||
|
||||
layout( push_constant ) uniform PushBlock {
|
||||
@ -18,31 +17,23 @@ layout( push_constant ) uniform PushBlock {
|
||||
uint draw;
|
||||
} PushConstant;
|
||||
|
||||
|
||||
layout (binding = 3) uniform Camera {
|
||||
Viewport viewport[PASSES];
|
||||
} camera;
|
||||
|
||||
#if SKINNED && INSTANCED
|
||||
layout (std140, binding = 4) readonly buffer Models {
|
||||
mat4 models[];
|
||||
};
|
||||
/*
|
||||
layout (std140, binding = 4) readonly buffer DrawCommands {
|
||||
DrawCommand drawCommands[];
|
||||
};
|
||||
*/
|
||||
layout (std140, binding = 4) readonly buffer Instances {
|
||||
Instance instances[];
|
||||
};
|
||||
|
||||
#if SKINNED
|
||||
layout (std140, binding = 5) readonly buffer Joints {
|
||||
mat4 joints[];
|
||||
};
|
||||
#else
|
||||
layout (binding = 4) uniform UBO {
|
||||
mat4 model;
|
||||
} ubo;
|
||||
#if SKINNED
|
||||
layout (std140, binding = 5) readonly buffer Joints {
|
||||
mat4 joints[];
|
||||
};
|
||||
#elif INSTANCED
|
||||
layout (std140, binding = 5) readonly buffer Models {
|
||||
mat4 models[];
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
layout (location = 0) out vec2 outUv;
|
||||
@ -64,21 +55,23 @@ vec4 snap(vec4 vertex, vec2 resolution) {
|
||||
void main() {
|
||||
outUv = inUv;
|
||||
outSt = inSt;
|
||||
outColor = vec4(1); // ubo.color;
|
||||
outId = ivec4(inId, PushConstant.pass, PushConstant.draw);
|
||||
|
||||
|
||||
const mat4 view = camera.viewport[PushConstant.pass].view;
|
||||
const mat4 projection = camera.viewport[PushConstant.pass].projection;
|
||||
#if SKINNED
|
||||
mat4 skinned = joints.length() <= 0 ? mat4(1.0) : inWeights.x * joints[int(inJoints.x)] + inWeights.y * joints[int(inJoints.y)] + inWeights.z * joints[int(inJoints.z)] + inWeights.w * joints[int(inJoints.w)];
|
||||
const mat4 skinned = joints.length() <= 0 ? mat4(1.0) : inWeights.x * joints[int(inJoints.x)] + inWeights.y * joints[int(inJoints.y)] + inWeights.z * joints[int(inJoints.z)] + inWeights.w * joints[int(inJoints.w)];
|
||||
#else
|
||||
mat4 skinned = mat4(1.0);
|
||||
#endif
|
||||
#if INSTANCED
|
||||
mat4 model = models.length() <= 0 ? skinned : (models[int(inId.x)] * skinned);
|
||||
#else
|
||||
mat4 model = ubo.model * skinned;
|
||||
const mat4 skinned = mat4(1.0);
|
||||
#endif
|
||||
const uint drawID = gl_DrawIDARB;
|
||||
// const DrawCommand drawCommand = drawCommands[drawID];
|
||||
const uint instanceID = gl_InstanceIndex;
|
||||
const Instance instance = instances[instanceID];
|
||||
const uint materialID = instance.materialID;
|
||||
const mat4 model = instances.length() <= 0 ? skinned : (instance.model * skinned);
|
||||
|
||||
outId = ivec4(drawID, instanceID, materialID, PushConstant.pass);
|
||||
outColor = instance.color;
|
||||
outPosition = vec3(model * vec4(inPos.xyz, 1.0));
|
||||
outNormal = vec3(model * vec4(inNormal.xyz, 0.0));
|
||||
outNormal = normalize(outNormal);
|
||||
267
bin/data/shaders/graph/cull.comp.glsl
Normal file
267
bin/data/shaders/graph/cull.comp.glsl
Normal file
@ -0,0 +1,267 @@
|
||||
#version 450
|
||||
#pragma shader_stage(compute)
|
||||
|
||||
#extension GL_EXT_nonuniform_qualifier : enable
|
||||
|
||||
layout (constant_id = 0) const uint PASSES = 6;
|
||||
layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||
|
||||
#define COMPUTE 1
|
||||
|
||||
#include "../common/macros.h"
|
||||
#include "../common/structs.h"
|
||||
|
||||
layout( push_constant ) uniform PushBlock {
|
||||
uint pass;
|
||||
uint passes;
|
||||
} PushConstant;
|
||||
|
||||
layout (binding = 0) uniform Camera {
|
||||
Viewport viewport[PASSES];
|
||||
} camera;
|
||||
|
||||
layout (std140, binding = 1) buffer DrawCommands {
|
||||
DrawCommand drawCommands[];
|
||||
};
|
||||
|
||||
layout (std140, binding = 2) buffer Instances {
|
||||
Instance instances[];
|
||||
};
|
||||
|
||||
struct Frustum {
|
||||
vec4 planes[6];
|
||||
};
|
||||
|
||||
float inside( vec3 v, vec3 min, vec3 max ) {
|
||||
vec3 s = step(min, v) - step(max, v);
|
||||
return s.x * s.y * s.z;
|
||||
}
|
||||
/*
|
||||
T f = 1 / tan( fov / 2 );
|
||||
return pod::Matrix4t<T>({
|
||||
f / raidou, 0, 0, 0,
|
||||
0, -f, 0, 0,
|
||||
0, 0, 0, 1,
|
||||
0, 0, znear, 0
|
||||
});
|
||||
*/
|
||||
|
||||
vec4 normalizePlane( vec4 p ) {
|
||||
return p / length(p.xyz);
|
||||
}
|
||||
|
||||
bool frustumCull( uint id ) {
|
||||
if ( PushConstant.passes == 0 ) return true;
|
||||
|
||||
const DrawCommand drawCommand = drawCommands[id];
|
||||
const Instance instance = instances[drawCommand.instanceID];
|
||||
|
||||
bool visible = false;
|
||||
for ( uint pass = 0; pass < PushConstant.passes; ++pass ) {
|
||||
// return if our camera position is inside the AABB
|
||||
vec3 camPos = vec3( inverse(camera.viewport[pass].view)[3] );
|
||||
if ( instance.bounds.min.x <= camPos.x && camPos.x <= instance.bounds.max.x && instance.bounds.min.y <= camPos.y && camPos.y <= instance.bounds.max.y && instance.bounds.min.z <= camPos.z && camPos.z <= instance.bounds.max.z ) return true;
|
||||
// sphere based one, source of this block uses reverse infinite Z, but would be nice if it used AABB
|
||||
#if 0
|
||||
vec3 min = vec3(camera.viewport[pass].view * instance.model * vec4(instance.bounds.min, 1));
|
||||
vec3 max = vec3(camera.viewport[pass].view * instance.model * vec4(instance.bounds.max, 1));
|
||||
|
||||
vec3 center = (max + min) * 0.5;
|
||||
vec3 extent = (max - min) * 0.5;
|
||||
float radius = length(extent);
|
||||
|
||||
mat4 projectionT = transpose(camera.viewport[pass].projection);
|
||||
vec4 frustumX = normalizePlane(projectionT[3] + projectionT[0]); // x + w < 0
|
||||
vec4 frustumY = normalizePlane(projectionT[3] + projectionT[1]); // y + w < 0
|
||||
vec4 frustum = vec4( frustumX.x, frustumX.z, frustumY.y, frustumY.z );
|
||||
|
||||
visible = visible && center.z * frustum[1] - abs(center.x) * frustum[0] > -radius;
|
||||
visible = visible && center.z * frustum[3] - abs(center.y) * frustum[2] > -radius;
|
||||
// optimized version of the below blocks
|
||||
#elif 1
|
||||
mat4 mat = camera.viewport[pass].projection * camera.viewport[pass].view * instance.model;
|
||||
vec3 min = vec3(mat * vec4(instance.bounds.min, 1));
|
||||
vec3 max = vec3(mat * vec4(instance.bounds.max, 1));
|
||||
|
||||
vec3 center = (max + min) * 0.5;
|
||||
vec3 extent = (max - min) * 0.5;
|
||||
vec4 planes[6]; {
|
||||
for (int i = 0; i < 3; ++i)
|
||||
for (int j = 0; j < 2; ++j) {
|
||||
planes[i*2+j].x = mat[0][3] + (j == 0 ? mat[0][i] : -mat[0][i]);
|
||||
planes[i*2+j].y = mat[1][3] + (j == 0 ? mat[1][i] : -mat[1][i]);
|
||||
planes[i*2+j].z = mat[2][3] + (j == 0 ? mat[2][i] : -mat[2][i]);
|
||||
planes[i*2+j].w = mat[3][3] + (j == 0 ? mat[3][i] : -mat[3][i]);
|
||||
planes[i*2+j] = normalizePlane( planes[i*2+j] );
|
||||
}
|
||||
}
|
||||
for ( uint p = 0; p < 6; ++p ) {
|
||||
if ( dot(center + extent * sign(planes[p].xyz), planes[p].xyz ) > -planes[p].w ) return true;
|
||||
}
|
||||
// transforms each corner into clip space
|
||||
// an AABB is not visible if a plane has all 8 corners outside of it
|
||||
#elif 0
|
||||
mat4 mat = camera.viewport[pass].projection * camera.viewport[pass].view * instance.model;
|
||||
vec4 corners[9] = {
|
||||
vec4( instance.bounds.min.x, instance.bounds.min.y, instance.bounds.min.z, 1.0 ),
|
||||
vec4( instance.bounds.max.x, instance.bounds.min.y, instance.bounds.min.z, 1.0 ),
|
||||
vec4( instance.bounds.max.x, instance.bounds.max.y, instance.bounds.min.z, 1.0 ),
|
||||
vec4( instance.bounds.min.x, instance.bounds.max.y, instance.bounds.min.z, 1.0 ),
|
||||
|
||||
vec4( instance.bounds.min.x, instance.bounds.min.y, instance.bounds.max.z, 1.0 ),
|
||||
vec4( instance.bounds.max.x, instance.bounds.min.y, instance.bounds.max.z, 1.0 ),
|
||||
vec4( instance.bounds.max.x, instance.bounds.max.y, instance.bounds.max.z, 1.0 ),
|
||||
vec4( instance.bounds.min.x, instance.bounds.max.y, instance.bounds.max.z, 1.0 ),
|
||||
|
||||
vec4( (instance.bounds.max + instance.bounds.min) * 0.5, 1.0 ),
|
||||
};
|
||||
for ( uint p = 0; p < 9; ++p ) {
|
||||
vec4 t = mat * corners[p];
|
||||
if ( -t.w <= t.x && t.x <= t.w && -t.w <= t.y && t.y <= t.w ) return true;
|
||||
}
|
||||
// "optimized" version of the next block, compares bounds to each plane
|
||||
// an AABB is not visible if a plane has all 8 corners outside of it
|
||||
#elif 0
|
||||
mat4 mat = camera.viewport[pass].projection * camera.viewport[pass].view * instance.model;
|
||||
vec4 planes[6]; {
|
||||
for (int i = 0; i < 3; ++i)
|
||||
for (int j = 0; j < 2; ++j) {
|
||||
planes[i*2+j].x = mat[0][3] + (j == 0 ? mat[0][i] : -mat[0][i]);
|
||||
planes[i*2+j].y = mat[1][3] + (j == 0 ? mat[1][i] : -mat[1][i]);
|
||||
planes[i*2+j].z = mat[2][3] + (j == 0 ? mat[2][i] : -mat[2][i]);
|
||||
planes[i*2+j].w = mat[3][3] + (j == 0 ? mat[3][i] : -mat[3][i]);
|
||||
planes[i*2+j] = normalizePlane( planes[i*2+j] );
|
||||
}
|
||||
}
|
||||
for ( uint p = 0; p < 6; ++p ) {
|
||||
float d = max(instance.bounds.min.x * planes[p].x, instance.bounds.max.x * planes[p].x)
|
||||
+ max(instance.bounds.min.y * planes[p].y, instance.bounds.max.y * planes[p].y)
|
||||
+ max(instance.bounds.min.z * planes[p].z, instance.bounds.max.z * planes[p].z);
|
||||
if ( d > -planes[p].w ) return true;
|
||||
}
|
||||
#else
|
||||
mat4 mat = camera.viewport[pass].projection * camera.viewport[pass].view * instance.model;
|
||||
vec4 corners[9] = {
|
||||
vec4( instance.bounds.min.x, instance.bounds.min.y, instance.bounds.min.z, 1.0 ),
|
||||
vec4( instance.bounds.max.x, instance.bounds.min.y, instance.bounds.min.z, 1.0 ),
|
||||
vec4( instance.bounds.max.x, instance.bounds.max.y, instance.bounds.min.z, 1.0 ),
|
||||
vec4( instance.bounds.min.x, instance.bounds.max.y, instance.bounds.min.z, 1.0 ),
|
||||
|
||||
vec4( instance.bounds.min.x, instance.bounds.min.y, instance.bounds.max.z, 1.0 ),
|
||||
vec4( instance.bounds.max.x, instance.bounds.min.y, instance.bounds.max.z, 1.0 ),
|
||||
vec4( instance.bounds.max.x, instance.bounds.max.y, instance.bounds.max.z, 1.0 ),
|
||||
vec4( instance.bounds.min.x, instance.bounds.max.y, instance.bounds.max.z, 1.0 ),
|
||||
|
||||
vec4( (instance.bounds.max + instance.bounds.min) * 0.5, 1.0 ),
|
||||
};
|
||||
vec4 planes[6]; {
|
||||
for (int i = 0; i < 3; ++i)
|
||||
for (int j = 0; j < 2; ++j) {
|
||||
planes[i*2+j].x = mat[0][3] + (j == 0 ? mat[0][i] : -mat[0][i]);
|
||||
planes[i*2+j].y = mat[1][3] + (j == 0 ? mat[1][i] : -mat[1][i]);
|
||||
planes[i*2+j].z = mat[2][3] + (j == 0 ? mat[2][i] : -mat[2][i]);
|
||||
planes[i*2+j].w = mat[3][3] + (j == 0 ? mat[3][i] : -mat[3][i]);
|
||||
planes[i*2+j] = normalizePlane( planes[i*2+j] );
|
||||
}
|
||||
}
|
||||
for ( uint p = 0; p < 9; ++p ) corners[p] = mat * corners[p];
|
||||
for ( uint p = 0; p < 6; ++p ) {
|
||||
for ( uint q = 0; q < 9; ++q ) {
|
||||
if ( dot( corners[q], planes[p] ) > 0 ) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return visible;
|
||||
}
|
||||
|
||||
void main() {
|
||||
const uint gID = gl_GlobalInvocationID.x;
|
||||
if ( !(0 <= gID && gID < drawCommands.length()) ) return;
|
||||
drawCommands[gID].instances = frustumCull( gID ) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Frustum frustum;
|
||||
for (int i = 0; i < 3; ++i)
|
||||
for (int j = 0; j < 2; ++j) {
|
||||
frustum.planes[i*2+j].x = mat[0][3] + (j == 0 ? mat[0][i] : -mat[0][i]);
|
||||
frustum.planes[i*2+j].y = mat[1][3] + (j == 0 ? mat[1][i] : -mat[1][i]);
|
||||
frustum.planes[i*2+j].z = mat[2][3] + (j == 0 ? mat[2][i] : -mat[2][i]);
|
||||
frustum.planes[i*2+j].w = mat[3][3] + (j == 0 ? mat[3][i] : -mat[3][i]);
|
||||
frustum.planes[i*2+j]*= length(frustum.planes[i*2+j].xyz);
|
||||
}
|
||||
for ( uint i = 0; i < 6; ++i ) {
|
||||
vec4 plane = frustum.planes[i];
|
||||
float d = dot(instance.bounds.center, plane.xyz);
|
||||
float r = dot(instance.bounds.extent, abs(plane.xyz));
|
||||
bool inside = d + r > -plane.w;
|
||||
if ( !inside ) return 0;
|
||||
}
|
||||
return true;
|
||||
*/
|
||||
/*
|
||||
vec4 plane;
|
||||
vec4 center = vec4( (max + min) * 0.5, 1 );
|
||||
vec4 extent = vec4( (max - min) * 0.5, 1 );
|
||||
center = mat * center;
|
||||
extent = mat * extent;
|
||||
center.xyz /= center.w;
|
||||
extent.xyz /= extent.w;
|
||||
for (int i = 0; i < 4; ++i ) plane[i] = mat[i][3] + mat[i][0]; // left
|
||||
visible = dot(center.xyz + extent.xyz * sign(plane.xyz), plane.xyz ) > -plane.w;
|
||||
if ( visible ) return true;
|
||||
|
||||
for (int i = 0; i < 4; ++i ) plane[i] = mat[i][3] - mat[i][0]; // right
|
||||
visible = dot(center.xyz + extent.xyz * sign(plane.xyz), plane.xyz ) > -plane.w;
|
||||
if ( visible ) return true;
|
||||
|
||||
for (int i = 0; i < 4; ++i ) plane[i] = mat[i][3] + mat[i][1]; // bottom
|
||||
visible = dot(center.xyz + extent.xyz * sign(plane.xyz), plane.xyz ) > -plane.w;
|
||||
if ( visible ) return true;
|
||||
|
||||
for (int i = 0; i < 4; ++i ) plane[i] = mat[i][3] - mat[i][1]; // top
|
||||
visible = dot(center.xyz + extent.xyz * sign(plane.xyz), plane.xyz ) > -plane.w;
|
||||
if ( visible ) return true;
|
||||
|
||||
for (int i = 0; i < 4; ++i ) plane[i] = mat[i][3] + mat[i][2]; // near
|
||||
visible = dot(center.xyz + extent.xyz * sign(plane.xyz), plane.xyz ) > -plane.w;
|
||||
if ( visible ) return true;
|
||||
|
||||
for (int i = 0; i < 4; ++i ) plane[i] = mat[i][3] - mat[i][2]; // far
|
||||
visible = dot(center.xyz + extent.xyz * sign(plane.xyz), plane.xyz ) > -plane.w;
|
||||
if ( visible ) return true;
|
||||
|
||||
*/
|
||||
/*
|
||||
for ( uint p = 0; p < 8; ++p ) {
|
||||
vec4 t = corners[p];
|
||||
float w = abs(t.w);
|
||||
visible = -w <= t.x && t.x <= w && -w <= t.y && t.y <= w && 0 <= t.z && t.z <= w; // && -w <= t.z && t.z <= w;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
mat4 convert( mat4 proj ) {
|
||||
float f = -proj[1][1];
|
||||
float raidou = f / proj[0][0];
|
||||
float zNear = proj[3][2];
|
||||
float zFar = 32;
|
||||
|
||||
float range = zNear - zFar;
|
||||
|
||||
float Sx = f * raidou;
|
||||
float Sy = f;
|
||||
float Sz = (-zNear - zFar) / range;
|
||||
float Pz = 2 * zFar * zNear / range;
|
||||
|
||||
mat4 new = mat4(1.0);
|
||||
new[0][0] = Sx;
|
||||
new[1][1] = -Sy;
|
||||
new[2][2] = Sz;
|
||||
new[3][2] = Pz;
|
||||
new[2][3] = 1;
|
||||
return new;
|
||||
}
|
||||
*/
|
||||
58
bin/data/shaders/graph/depth.frag.glsl
Normal file
58
bin/data/shaders/graph/depth.frag.glsl
Normal file
@ -0,0 +1,58 @@
|
||||
#version 450
|
||||
#pragma shader_stage(fragment)
|
||||
|
||||
#extension GL_EXT_nonuniform_qualifier : enable
|
||||
|
||||
#define CUBEMAPS 1
|
||||
// #define MAX_TEXTURES TEXTURES
|
||||
#define MAX_TEXTURES textures.length()
|
||||
layout (constant_id = 0) const uint TEXTURES = 1;
|
||||
|
||||
#include "../common/macros.h"
|
||||
#include "../common/structs.h"
|
||||
|
||||
layout (binding = 0) uniform sampler2D samplerTextures[TEXTURES];
|
||||
layout (std140, binding = 1) readonly buffer Materials {
|
||||
Material materials[];
|
||||
};
|
||||
layout (std140, binding = 2) readonly buffer Textures {
|
||||
Texture textures[];
|
||||
};
|
||||
|
||||
#include "../common/functions.h"
|
||||
|
||||
layout (location = 0) in vec2 inUv;
|
||||
layout (location = 1) in vec2 inSt;
|
||||
layout (location = 2) in vec4 inColor;
|
||||
layout (location = 3) in vec3 inNormal;
|
||||
layout (location = 4) in mat3 inTBN;
|
||||
layout (location = 7) in vec3 inPosition;
|
||||
layout (location = 8) flat in ivec4 inId;
|
||||
|
||||
void main() {
|
||||
const uint drawID = uint(inId.x);
|
||||
const uint instanceID = uint(inId.y);
|
||||
const uint materialID = uint(inId.z);
|
||||
const float mip = mipLevel(inUv.xy);
|
||||
const vec2 uv = wrap(inUv.xy);
|
||||
vec4 A = vec4(0, 0, 0, 0);
|
||||
|
||||
const Material material = materials[materialID];
|
||||
// sample albedo
|
||||
if ( !validTextureIndex( material.indexAlbedo ) ) discard; {
|
||||
const Texture t = textures[material.indexAlbedo];
|
||||
A = textureLod( samplerTextures[nonuniformEXT(t.index)], mix( t.lerp.xy, t.lerp.zw, uv ), mip );
|
||||
// alpha mode OPAQUE
|
||||
if ( material.modeAlpha == 0 ) {
|
||||
A.a = 1;
|
||||
// alpha mode BLEND
|
||||
} else if ( material.modeAlpha == 1 ) {
|
||||
|
||||
// alpha mode MASK
|
||||
} else if ( material.modeAlpha == 2 ) {
|
||||
if ( A.a < abs(material.factorAlphaCutoff) ) discard;
|
||||
A.a = 1;
|
||||
}
|
||||
// if ( A.a < 1 - 0.00001 ) discard;
|
||||
}
|
||||
}
|
||||
@ -49,7 +49,7 @@ layout (location = 1) out vec2 outNormals;
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
const uint CASCADE = inId.z;
|
||||
const uint CASCADE = inId.w;
|
||||
if ( CASCADES <= CASCADE ) discard;
|
||||
const vec3 P = inPosition.xzy * 0.5 + 0.5;
|
||||
if ( abs(P.x) > 1 || abs(P.y) > 1 || abs(P.z) > 1 ) discard;
|
||||
@ -58,20 +58,19 @@ void main() {
|
||||
const vec3 N = inNormal;
|
||||
const vec2 uv = wrap(inUv.xy);
|
||||
const float mip = 0; // mipLevel(inUv.xy);
|
||||
const int materialId = int(inId.y);
|
||||
const Material material = materials[materialId];
|
||||
const uint drawID = int(inId.x);
|
||||
const uint instanceID = int(inId.y);
|
||||
const uint materialID = int(inId.z);
|
||||
Material material = materials[materialID];
|
||||
|
||||
const float M = material.factorMetallic;
|
||||
const float R = material.factorRoughness;
|
||||
const float AO = material.factorOcclusion;
|
||||
|
||||
// sample albedo
|
||||
const bool useAtlas = validTextureIndex( material.indexAtlas );
|
||||
Texture textureAtlas;
|
||||
if ( useAtlas ) textureAtlas = textures[material.indexAtlas];
|
||||
if ( !validTextureIndex( material.indexAlbedo ) ) discard; {
|
||||
Texture t = textures[material.indexAlbedo];
|
||||
A = textureLod( samplerTextures[nonuniformEXT((useAtlas) ? textureAtlas.index : t.index)], (useAtlas) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv, mip );
|
||||
const Texture t = textures[material.indexAlbedo];
|
||||
A = textureLod( samplerTextures[nonuniformEXT(t.index)], mix( t.lerp.xy, t.lerp.zw, uv ), mip );
|
||||
// alpha mode OPAQUE
|
||||
if ( material.modeAlpha == 0 ) {
|
||||
A.a = 1;
|
||||
@ -107,7 +106,7 @@ void main() {
|
||||
imageStore(voxelDepth[CASCADE], uvw, vec4(inDepth, 0, 0, 0));
|
||||
#endif
|
||||
|
||||
imageStore(voxelId[CASCADE], uvw, uvec4(uvec2(inId.w+1, inId.y+1), 0, 0));
|
||||
imageStore(voxelId[CASCADE], uvw, uvec4(uvec2(drawID + 1, instanceID + 1), 0, 0));
|
||||
imageStore(voxelNormal[CASCADE], uvw, vec4(encodeNormals( normalize( N ) ), 0, 0));
|
||||
#if BLEND
|
||||
// GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
|
||||
@ -47,7 +47,7 @@ void main(){
|
||||
A = N.z > N[A] ? 2 : A;
|
||||
#endif
|
||||
|
||||
const uint CASCADE = inId[0].z;
|
||||
const uint CASCADE = inId[0].w;
|
||||
vec3 P[3] = {
|
||||
vec3( ubo.voxel * vec4( inPosition[0], 1 ) ) / cascadePower(CASCADE),
|
||||
vec3( ubo.voxel * vec4( inPosition[1], 1 ) ) / cascadePower(CASCADE),
|
||||
@ -90,6 +90,11 @@ void client::initialize() {
|
||||
client::window.setMousePosition(client::window.getSize()/2);
|
||||
}
|
||||
});
|
||||
uf::hooks.addHook( "window:Mouse.Lock", [&](){
|
||||
if ( client::window.hasFocus() ) {
|
||||
client::window.setMousePosition(client::window.getSize()/2);
|
||||
}
|
||||
});
|
||||
uf::hooks.addHook( "window:Closed", [&]( ext::json::Value& json ){
|
||||
client::ready = false;
|
||||
} );
|
||||
|
||||
@ -58,46 +58,6 @@ int main(int argc, char** argv){
|
||||
signal(SIGABRT, ::handlers::abrt);
|
||||
signal(SIGSEGV, ::handlers::segv);
|
||||
|
||||
{
|
||||
uf::Mesh mesh;
|
||||
mesh.bind<pod::Vertex_2F2F, uint16_t>();
|
||||
mesh.insertVertices<pod::Vertex_2F2F>({
|
||||
{ {-1.0f, 1.0f}, {0.0f, 1.0f}, },
|
||||
{ {-1.0f, -1.0f}, {0.0f, 0.0f}, },
|
||||
{ {1.0f, -1.0f}, {1.0f, 0.0f}, },
|
||||
{ {1.0f, 1.0f}, {1.0f, 1.0f}, }
|
||||
});
|
||||
mesh.insertIndices<uint16_t>({
|
||||
0, 1, 2, 2, 3, 0
|
||||
});
|
||||
/*
|
||||
mesh.bind<pod::Vertex_3F2F3F>();
|
||||
mesh.insertVertices<pod::Vertex_3F2F3F>({
|
||||
{{0.0f, 1.0f, 2.0f}, {3.0f, 4.0f}, {5.0f, 6.0f, 7.0f}},
|
||||
{{8.0f, 9.0f, 10.0f}, {11.0f, 12.0f}, {13.0f, 14.0f, 15.0f}},
|
||||
{{16.0f, 17.0f, 18.0f}, {19.0f, 20.0f}, {21.0f, 22.0f, 23.0f}},
|
||||
});
|
||||
mesh.insertIndices<uint32_t>({
|
||||
0, 1, 2
|
||||
});
|
||||
*/
|
||||
|
||||
mesh.print();
|
||||
/*
|
||||
auto& buffer = mesh.buffers[0 <= mesh.vertex.interleaved && mesh.vertex.interleaved < mesh.buffers.size() ? mesh.vertex.interleaved :];
|
||||
uint8_t* pointer = (uint8_t*) buffer.data();
|
||||
while ( pointer < (uint8_t*) buffer.data() + buffer.size() ) {
|
||||
for ( auto& attribute : mesh.vertex.attributes ) {
|
||||
float* vector = pointer + attrribute.descriptor.offset;
|
||||
for ( auto i = 0; i < attribute.descriptor.components; ++i ) {
|
||||
UF_MSG_DEBUG( attribute.descriptor.name << ": " << vector[i] );
|
||||
}
|
||||
pointer += attribute.descriptor.size;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
client::initialize();
|
||||
ext::initialize();
|
||||
|
||||
|
||||
@ -20,8 +20,12 @@
|
||||
#if defined(__CYGWIN__)
|
||||
#define to_string(var) string(var)
|
||||
#endif
|
||||
#define _WIN32_WINNT 0x0600
|
||||
#define WINVER 0x0600
|
||||
#ifndef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0600
|
||||
#endif
|
||||
#ifndef WINVER
|
||||
#define WINVER 0x0600
|
||||
#endif
|
||||
|
||||
#define UF_IO_ROOT "./data/"
|
||||
#elif defined(linux) || defined(__linux)
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#include <uf/utils/math/transform.h>
|
||||
#include <uf/utils/mesh/mesh.h>
|
||||
#include <uf/utils/renderer/renderer.h>
|
||||
#include <uf/utils/memory/fifo_map.h>
|
||||
#include <uf/utils/memory/unordered_map.h>
|
||||
|
||||
#include <queue>
|
||||
|
||||
@ -23,28 +23,27 @@ namespace pod {
|
||||
uf::Serializer metadata;
|
||||
|
||||
pod::Node root;
|
||||
uf::stl::vector<pod::Node> nodes; // node's position corresponds to its drawCommand and instance
|
||||
uf::stl::vector<pod::Node> nodes; //
|
||||
|
||||
// Render information
|
||||
uf::stl::vector<uf::stl::vector<pod::DrawCommand>> drawCommands; // draws to dispatch, one per primitive, gets copied per rendermode
|
||||
uf::stl::vector<uf::stl::string> instances; //
|
||||
uf::stl::vector<uf::stl::string> primitives; //
|
||||
uf::stl::vector<uf::stl::string> drawCommands; //
|
||||
uf::stl::vector<uf::stl::string> meshes; //
|
||||
|
||||
uf::stl::vector<pod::Instance> instances; // instance data to use, gets copied per rendermode
|
||||
uf::stl::vector<uf::stl::string> images; //
|
||||
uf::stl::vector<uf::stl::string> materials; //
|
||||
uf::stl::vector<uf::stl::string> textures; //
|
||||
|
||||
uf::stl::vector<uf::stl::string> meshes; // collection of primitives (stored as meshes, by material)
|
||||
|
||||
uf::stl::vector<uf::stl::string> images; // references global pool of images
|
||||
uf::stl::vector<uf::stl::string> materials; // references global pool of materials
|
||||
uf::stl::vector<uf::stl::string> textures; // references global pool of textures
|
||||
|
||||
uf::stl::vector<uf::stl::string> texture2Ds; // references global pool of texture2Ds
|
||||
uf::stl::vector<uf::stl::string> samplers; // references global pool of samplers
|
||||
uf::stl::vector<uf::stl::string> texture2Ds; //
|
||||
uf::stl::vector<uf::stl::string> samplers; //
|
||||
|
||||
// Lighting information
|
||||
uf::stl::unordered_map<uf::stl::string, pod::Light> lights;
|
||||
|
||||
// Animations
|
||||
uf::stl::vector<Skin> skins;
|
||||
uf::stl::unordered_map<uf::stl::string, Animation> animations;
|
||||
uf::stl::vector<uf::stl::string> skins;
|
||||
uf::stl::vector<uf::stl::string> animations;
|
||||
// Animation queue
|
||||
std::queue<uf::stl::string> sequence;
|
||||
struct {
|
||||
@ -61,15 +60,55 @@ namespace pod {
|
||||
|
||||
// Local storage, used for save/load
|
||||
struct Storage {
|
||||
uf::stl::fifo_map<uf::stl::string, uf::Atlas> atlases;
|
||||
uf::stl::fifo_map<uf::stl::string, uf::Image> images;
|
||||
uf::stl::fifo_map<uf::stl::string, pod::Mesh> meshes;
|
||||
uf::stl::fifo_map<uf::stl::string, pod::Material> materials;
|
||||
uf::stl::fifo_map<uf::stl::string, pod::Texture> textures;
|
||||
template<typename T, typename Key = uf::stl::string>
|
||||
struct KeyMap {
|
||||
public:
|
||||
uf::stl::vector<Key> keys;
|
||||
uf::stl::unordered_map<Key, T> map;
|
||||
|
||||
uf::stl::fifo_map<uf::stl::string, uf::renderer::Texture2D> texture2Ds;
|
||||
uf::stl::fifo_map<uf::stl::string, uf::renderer::Sampler> samplers;
|
||||
};
|
||||
T& operator[]( const Key& key ) {
|
||||
if ( map.count( key ) == 0 ) keys.emplace_back( key );
|
||||
return map[key];
|
||||
}
|
||||
|
||||
void reserve( size_t i ) {
|
||||
keys.reserve(i);
|
||||
map.reserve(i);
|
||||
}
|
||||
};
|
||||
|
||||
KeyMap<pod::Instance> instances;
|
||||
KeyMap<uf::stl::vector<pod::Primitive>> primitives;
|
||||
KeyMap<uf::stl::vector<pod::DrawCommand>> drawCommands;
|
||||
KeyMap<uf::Mesh> meshes;
|
||||
|
||||
KeyMap<uf::Image> images;
|
||||
KeyMap<pod::Material> materials;
|
||||
KeyMap<pod::Texture> textures;
|
||||
KeyMap<uf::renderer::Sampler> samplers;
|
||||
uf::stl::vector<pod::Light> lights;
|
||||
KeyMap<pod::Skin> skins;
|
||||
KeyMap<pod::Animation> animations;
|
||||
|
||||
// maps without direct analogues
|
||||
KeyMap<uf::Atlas> atlases;
|
||||
KeyMap<pod::Matrix4f> joints;
|
||||
KeyMap<uf::renderer::Texture2D> texture2Ds;
|
||||
KeyMap<uf::Entity*> entities;
|
||||
|
||||
uf::stl::vector<uf::renderer::Texture2D> shadow2Ds;
|
||||
uf::stl::vector<uf::renderer::TextureCube> shadowCubes;
|
||||
|
||||
struct Buffer {
|
||||
uf::renderer::Buffer camera;
|
||||
uf::renderer::Buffer drawCommands;
|
||||
uf::renderer::Buffer instance;
|
||||
uf::renderer::Buffer joint;
|
||||
uf::renderer::Buffer material;
|
||||
uf::renderer::Buffer texture;
|
||||
uf::renderer::Buffer light;
|
||||
} buffers;
|
||||
} storage;
|
||||
};
|
||||
}
|
||||
|
||||
@ -100,6 +139,11 @@ namespace uf {
|
||||
void UF_API update( pod::Graph&, pod::Node& );
|
||||
|
||||
void UF_API destroy( pod::Graph& );
|
||||
|
||||
void UF_API initialize();
|
||||
void UF_API tick();
|
||||
void UF_API render();
|
||||
void UF_API destroy();
|
||||
|
||||
pod::Graph UF_API load( const uf::stl::string&, const uf::Serializer& = ext::json::null() );
|
||||
void UF_API save( const pod::Graph&, const uf::stl::string& );
|
||||
|
||||
@ -4,30 +4,36 @@ namespace pod {
|
||||
uint32_t instances = 0; // instance count
|
||||
uint32_t indexID = 0; // starting triangle position
|
||||
int32_t vertexID = 0; // starting vertex position
|
||||
|
||||
uint32_t instanceID = 0; // starting instance position
|
||||
uint32_t materialID = 0;
|
||||
uint32_t objectID = 0;
|
||||
uint32_t vertices = 0;
|
||||
// extra data
|
||||
uint32_t padding1 = 0; //
|
||||
uint32_t padding2 = 0; //
|
||||
uint32_t vertices = 0; //
|
||||
};
|
||||
|
||||
|
||||
struct UF_API Instance {
|
||||
pod::Matrix4f model;
|
||||
pod::Vector4f color = {1,1,1,1};
|
||||
|
||||
alignas(4) uint32_t materialID = 0;
|
||||
alignas(4) uint32_t padding1 = 0;
|
||||
alignas(4) uint32_t padding2 = 0;
|
||||
alignas(4) uint32_t padding3 = 0;
|
||||
alignas(4) uint32_t primitiveID = 0;
|
||||
alignas(4) uint32_t meshID = 0;
|
||||
alignas(4) uint32_t objectID = 0;
|
||||
|
||||
struct {
|
||||
pod::Vector3f min = {};
|
||||
struct Bounds {
|
||||
pod::Vector3f min = { std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max() };
|
||||
alignas(4) float padding1 = 0;
|
||||
pod::Vector3f max = {};
|
||||
pod::Vector3f max = { -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max() };
|
||||
alignas(4) float padding2 = 0;
|
||||
} bounds;
|
||||
};
|
||||
|
||||
struct Primitive {
|
||||
pod::DrawCommand drawCommand;
|
||||
pod::Instance instance;
|
||||
};
|
||||
|
||||
struct UF_API Material {
|
||||
pod::Vector4f colorBase = { 0, 0, 0, 0 };
|
||||
pod::Vector4f colorEmissive = { 0, 0, 0, 0 };
|
||||
@ -72,11 +78,6 @@ namespace pod {
|
||||
float depthBias = 0;
|
||||
};
|
||||
//
|
||||
struct UF_API Mesh {
|
||||
uf::stl::vector<pod::DrawCommand> drawCommands;
|
||||
uf::Mesh mesh;
|
||||
};
|
||||
//
|
||||
struct UF_API Skin {
|
||||
uf::stl::string name = "";
|
||||
|
||||
|
||||
@ -58,6 +58,12 @@ namespace ext {
|
||||
|
||||
// collider for mesh (static or dynamic)
|
||||
pod::Bullet& create( uf::Object&, const uf::Mesh&, bool );
|
||||
pod::Bullet& create( uf::Object&, const void* verticesPointer, size_t verticesCount, size_t verticesStride, const void* indicesPointer, size_t indicesCount, size_t indicesStride, bool );
|
||||
|
||||
template<typename T, typename U>
|
||||
pod::Bullet& create( uf::Object& o, const uf::Mesh_T<T,U>& m, bool b ) {
|
||||
return create( o, m.vertices.data() + offsetof(T, position), m.vertices.size(), sizeof(T), m.indices.data(), m.indices.size(), sizeof(U), b );
|
||||
}
|
||||
// collider for boundingbox
|
||||
pod::Bullet& UF_API create( uf::Object&, const pod::Vector3f&, float );
|
||||
// collider for capsule
|
||||
|
||||
@ -37,9 +37,9 @@ namespace ext {
|
||||
extern UF_API bool multiview;
|
||||
extern UF_API bool vsync;
|
||||
extern UF_API bool hdr;
|
||||
extern UF_API bool frustrumCull;
|
||||
extern UF_API bool vxgi;
|
||||
extern UF_API bool deferredSampling;
|
||||
extern UF_API bool culling;
|
||||
}
|
||||
|
||||
namespace formats {
|
||||
|
||||
@ -19,11 +19,11 @@ namespace ext {
|
||||
VkDeviceSize alignment = 0;
|
||||
void* mapped = nullptr;
|
||||
|
||||
VkBufferUsageFlags usage;
|
||||
VkMemoryPropertyFlags memoryProperties;
|
||||
VkBufferUsageFlags usage = 0;
|
||||
VkMemoryPropertyFlags memoryProperties = 0;
|
||||
|
||||
VmaAllocation allocation;
|
||||
VmaAllocationInfo allocationInfo;
|
||||
VmaAllocation allocation = {};
|
||||
VmaAllocationInfo allocationInfo = {};
|
||||
|
||||
void* map( VkDeviceSize size = VK_WHOLE_SIZE, VkDeviceSize offset = 0 );
|
||||
void unmap();
|
||||
@ -49,7 +49,7 @@ namespace ext {
|
||||
};
|
||||
struct UF_API Buffers {
|
||||
uf::stl::vector<Buffer> buffers;
|
||||
Device* device;
|
||||
Device* device = NULL;
|
||||
|
||||
// ~Buffers();
|
||||
//
|
||||
|
||||
@ -16,18 +16,19 @@ namespace ext {
|
||||
|
||||
Device* device = NULL;
|
||||
|
||||
VkPipeline pipeline;
|
||||
VkPipelineLayout pipelineLayout;
|
||||
VkDescriptorSetLayout descriptorSetLayout;
|
||||
VkDescriptorPool descriptorPool;
|
||||
VkDescriptorSet descriptorSet;
|
||||
GraphicDescriptor descriptor;
|
||||
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||
VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
|
||||
VkDescriptorSetLayout descriptorSetLayout = VK_NULL_HANDLE;
|
||||
VkDescriptorPool descriptorPool = VK_NULL_HANDLE;
|
||||
VkDescriptorSet descriptorSet = VK_NULL_HANDLE;
|
||||
GraphicDescriptor descriptor = {};
|
||||
|
||||
struct {
|
||||
uf::Serializer json;
|
||||
|
||||
uf::stl::string type = "";
|
||||
bool process = true;
|
||||
bool rebuild = false;
|
||||
} metadata;
|
||||
|
||||
void initialize( const Graphic& graphic );
|
||||
@ -43,7 +44,7 @@ namespace ext {
|
||||
|
||||
struct UF_API Material {
|
||||
bool aliased = false;
|
||||
Device* device;
|
||||
Device* device = NULL;
|
||||
|
||||
uf::stl::vector<Sampler> samplers;
|
||||
uf::stl::vector<Texture2D> textures;
|
||||
@ -51,6 +52,7 @@ namespace ext {
|
||||
|
||||
struct Metadata {
|
||||
uf::Serializer json;
|
||||
bool autoInitializeUniforms = true;
|
||||
uf::stl::unordered_map<uf::stl::string, size_t> shaders;
|
||||
} metadata;
|
||||
|
||||
@ -68,30 +70,17 @@ namespace ext {
|
||||
};
|
||||
|
||||
struct UF_API Graphic : public Buffers {
|
||||
GraphicDescriptor descriptor;
|
||||
GraphicDescriptor descriptor = {};
|
||||
|
||||
bool initialized = false;
|
||||
bool process = true;
|
||||
Material material;
|
||||
Material material = {};
|
||||
uf::stl::unordered_map<GraphicDescriptor::hash_t, Pipeline> pipelines;
|
||||
|
||||
struct {
|
||||
uf::stl::unordered_map<uf::stl::string, size_t> buffers;
|
||||
} metadata;
|
||||
|
||||
struct Layout {
|
||||
uf::stl::vector<VkDescriptorBufferInfo> uniform;
|
||||
uf::stl::vector<VkDescriptorBufferInfo> storage;
|
||||
|
||||
uf::stl::vector<VkDescriptorImageInfo> image;
|
||||
uf::stl::vector<VkDescriptorImageInfo> image2D;
|
||||
uf::stl::vector<VkDescriptorImageInfo> imageCube;
|
||||
uf::stl::vector<VkDescriptorImageInfo> image3D;
|
||||
|
||||
uf::stl::vector<VkDescriptorImageInfo> sampler;
|
||||
uf::stl::vector<VkDescriptorImageInfo> input;
|
||||
} layout;
|
||||
|
||||
~Graphic();
|
||||
void initialize( const uf::stl::string& = "" );
|
||||
void destroy();
|
||||
@ -101,6 +90,7 @@ namespace ext {
|
||||
// void initializeAttributes( const uf::Mesh::Attributes& mesh );
|
||||
|
||||
void initializeMesh( uf::Mesh& mesh, bool buffer = true );
|
||||
void updateMesh( uf::Mesh& mesh );
|
||||
|
||||
bool hasPipeline( const GraphicDescriptor& descriptor ) const;
|
||||
void initializePipeline();
|
||||
|
||||
@ -12,24 +12,23 @@ namespace ext {
|
||||
bool execute = false;
|
||||
bool executed = false;
|
||||
bool rebuild = false;
|
||||
|
||||
uint32_t width = 0;
|
||||
uint32_t height = 0;
|
||||
|
||||
struct {
|
||||
uf::Serializer json;
|
||||
|
||||
uf::stl::string name = "";
|
||||
uf::stl::string type = "";
|
||||
uf::stl::string target = "";
|
||||
uf::stl::string pipeline = "";
|
||||
uf::stl::vector<uf::stl::string> pipelines;
|
||||
uf::stl::vector<uint8_t> outputs;
|
||||
|
||||
uint8_t subpasses = 1;
|
||||
uint8_t samples = 1;
|
||||
uint8_t eyes = 1;
|
||||
|
||||
size_t lightBufferIndex = 0;
|
||||
size_t materialBufferIndex = 0;
|
||||
size_t textureBufferIndex = 0;
|
||||
size_t drawCallBufferIndex = 0;
|
||||
} metadata;
|
||||
|
||||
Device* device = VK_NULL_HANDLE;
|
||||
|
||||
@ -7,7 +7,6 @@ namespace ext {
|
||||
namespace vulkan {
|
||||
struct UF_API ComputeRenderMode : public ext::vulkan::RenderMode {
|
||||
ext::vulkan::Graphic blitter, compute;
|
||||
pod::Vector2ui dispatchSize = { 32, 32 };
|
||||
|
||||
// RAII
|
||||
virtual const uf::stl::string getType() const;
|
||||
|
||||
@ -26,14 +26,15 @@ namespace ext {
|
||||
uf::stl::string filename = "";
|
||||
|
||||
VkShaderModule module = VK_NULL_HANDLE;
|
||||
VkPipelineShaderStageCreateInfo descriptor;
|
||||
VkPipelineShaderStageCreateInfo descriptor = {};
|
||||
uf::stl::vector<VkDescriptorSetLayoutBinding> descriptorSetLayoutBindings;
|
||||
uf::stl::vector<VkSpecializationMapEntry> specializationMapEntries;
|
||||
VkSpecializationInfo specializationInfo;
|
||||
VkSpecializationInfo specializationInfo = {};
|
||||
|
||||
struct Metadata {
|
||||
uf::Serializer json;
|
||||
|
||||
bool autoInitializeUniforms = true;
|
||||
uf::stl::string pipeline = "";
|
||||
uf::stl::string type = "";
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@ namespace ext {
|
||||
VkSwapchainKHR swapChain = VK_NULL_HANDLE;
|
||||
|
||||
bool initialized = false;
|
||||
uint32_t buffers;
|
||||
uint32_t buffers = {};
|
||||
|
||||
VkSemaphore presentCompleteSemaphore;
|
||||
VkSemaphore renderCompleteSemaphore;
|
||||
|
||||
@ -10,7 +10,7 @@ namespace ext {
|
||||
struct UF_API Sampler {
|
||||
Device* device = NULL;
|
||||
|
||||
VkSampler sampler;
|
||||
VkSampler sampler = VK_NULL_HANDLE;
|
||||
struct Descriptor {
|
||||
struct {
|
||||
VkFilter min = VK_FILTER_LINEAR;
|
||||
@ -34,7 +34,7 @@ namespace ext {
|
||||
float max = 16.0f;
|
||||
} anisotropy;
|
||||
VkDescriptorImageInfo info;
|
||||
} descriptor;
|
||||
} descriptor = {};
|
||||
|
||||
void initialize( Device& device );
|
||||
void destroy();
|
||||
@ -46,21 +46,24 @@ namespace ext {
|
||||
struct UF_API Texture {
|
||||
Device* device = nullptr;
|
||||
|
||||
VkImage image;
|
||||
VkImageView view;
|
||||
VkImage image = VK_NULL_HANDLE;
|
||||
VkImageView view = VK_NULL_HANDLE;
|
||||
VkImageType type = enums::Image::TYPE_2D;
|
||||
VkImageViewType viewType = enums::Image::VIEW_TYPE_2D;
|
||||
VkImageLayout imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
VkDeviceMemory deviceMemory;
|
||||
VkDescriptorImageInfo descriptor;
|
||||
VkFormat format = enums::Format::R8G8B8A8_UNORM;;
|
||||
VkDeviceMemory deviceMemory = VK_NULL_HANDLE;
|
||||
VkDescriptorImageInfo descriptor = {};
|
||||
VkFormat format = enums::Format::R8G8B8A8_UNORM;
|
||||
|
||||
Sampler sampler;
|
||||
Sampler sampler = {};
|
||||
|
||||
VmaAllocation allocation;
|
||||
VmaAllocationInfo allocationInfo;
|
||||
VmaAllocation allocation = {};
|
||||
VmaAllocationInfo allocationInfo = {};
|
||||
|
||||
uint32_t width, height, depth, layers;
|
||||
uint32_t width = 0;
|
||||
uint32_t height = 0;
|
||||
uint32_t depth = 0;
|
||||
uint32_t layers = 0;
|
||||
uint32_t mips = 1;
|
||||
// RAII
|
||||
void initialize( Device& device, size_t width, size_t height, size_t depth = 1, size_t layers = 1 );
|
||||
|
||||
@ -64,9 +64,9 @@ namespace ext {
|
||||
extern UF_API bool multiview;
|
||||
extern UF_API bool vsync;
|
||||
extern UF_API bool hdr;
|
||||
extern UF_API bool frustrumCull;
|
||||
extern UF_API bool vxgi;
|
||||
extern UF_API bool deferredSampling;
|
||||
extern UF_API bool culling;
|
||||
}
|
||||
|
||||
namespace formats {
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
#define UF_MSG_ERROR(X) UF_MSG(X, " ERROR ");
|
||||
|
||||
#if UF_NO_EXCEPTIONS
|
||||
#define UF_EXCEPTION(X) { UF_MSG_ERROR(X); }
|
||||
#define UF_EXCEPTION(X) { UF_MSG_ERROR(X); std::abort(); }
|
||||
#else
|
||||
#define UF_EXCEPTION(X) {\
|
||||
uf::stl::stringstream str;\
|
||||
|
||||
@ -21,13 +21,14 @@ namespace uf {
|
||||
std::size_t m_format;
|
||||
public:
|
||||
// C-tor
|
||||
/*
|
||||
Image(); // Default
|
||||
Image( const Image::vec2_t& size ); // Just Size
|
||||
Image( Image&& move ); // Move pixels
|
||||
Image( const Image& copy ); // Copy pixels
|
||||
Image( Image::container_t&& move, const Image::vec2_t& size ); // Move from vector of pixels
|
||||
Image( const Image::container_t& copy, const Image::vec2_t& size ); // Copy from vector of pixels
|
||||
|
||||
*/
|
||||
bool open( const uf::stl::string& filename, bool = true ); // from file
|
||||
void open( const std::istream& stream ); // from stream
|
||||
void move( Image::container_t&& move, const Image::vec2_t& size ); // move from vector of pixels
|
||||
|
||||
@ -570,15 +570,15 @@ pod::Matrix4t<T> /*UF_API*/ uf::matrix::perspective( T fov, T raidou, T znear, T
|
||||
});
|
||||
#elif UF_USE_VULKAN
|
||||
return pod::Matrix4t<T>({
|
||||
f / raidou, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, -f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f,
|
||||
0.0f, 0.0f, znear, 0.0f
|
||||
f / raidou, 0, 0, 0,
|
||||
0, -f, 0, 0,
|
||||
0, 0, 0, 1,
|
||||
0, 0, znear, 0
|
||||
});
|
||||
#endif
|
||||
} else {
|
||||
T range = znear - zfar;
|
||||
T f = tanf( static_cast<T>(0.5) * fov );
|
||||
T f = tan( static_cast<T>(0.5) * fov );
|
||||
|
||||
T Sx = static_cast<T>(1) / (f * raidou);
|
||||
T Sy = static_cast<T>(1) / f;
|
||||
|
||||
@ -131,6 +131,11 @@ namespace uf {
|
||||
template<typename T> T& /*UF_API*/ divide( T& left, const typename T::type_t& scalar ); // Divides this vector by a scalar
|
||||
template<typename T> T& /*UF_API*/ negate( T& vector ); // Flip sign of all components
|
||||
template<typename T> T& /*UF_API*/ normalize( T& vector ); // Normalizes a vector
|
||||
template<typename T> T /*UF_API*/ min( const T& left, const T& right ); //
|
||||
template<typename T> T /*UF_API*/ max( const T& left, const T& right ); //
|
||||
template<typename T> T /*UF_API*/ ceil( const T& vector ); //
|
||||
template<typename T> T /*UF_API*/ floor( const T& vector ); //
|
||||
template<typename T> T /*UF_API*/ round( const T& vector ); //
|
||||
// Complex arithmetic
|
||||
template<typename T> typename T::type_t /*UF_API*/ dot( const T& left, const T& right ); // Compute the dot product between two vectors
|
||||
template<typename T> pod::Angle /*UF_API*/ angle( const T& a, const T& b ); // Compute the angle between two vectors
|
||||
|
||||
@ -266,6 +266,36 @@ T& /*UF_API*/ uf::vector::normalize( T& vector ) {
|
||||
if ( norm == 0 ) return vector;
|
||||
return uf::vector::divide(vector, norm);
|
||||
}
|
||||
template<typename T> //
|
||||
T /*UF_API*/ uf::vector::min( const T& left, const T& right ) {
|
||||
T res = left;
|
||||
for ( uint_fast8_t i = 0; i < T::size; ++i ) res[i] = std::min( left[i], right[i] );
|
||||
return res;
|
||||
}
|
||||
template<typename T> //
|
||||
T /*UF_API*/ uf::vector::max( const T& left, const T& right ) {
|
||||
T res;
|
||||
for ( uint_fast8_t i = 0; i < T::size; ++i ) res[i] = std::max( left[i], right[i] );
|
||||
return res;
|
||||
}
|
||||
template<typename T> //
|
||||
T /*UF_API*/ uf::vector::ceil( const T& vector ) {
|
||||
T res;
|
||||
for ( uint_fast8_t i = 0; i < T::size; ++i ) res[i] = std::ceil( vector[i] );
|
||||
return res;
|
||||
}
|
||||
template<typename T> //
|
||||
T /*UF_API*/ uf::vector::floor( const T& vector ) {
|
||||
T res;
|
||||
for ( uint_fast8_t i = 0; i < T::size; ++i ) res[i] = std::floor( vector[i] );
|
||||
return res;
|
||||
}
|
||||
template<typename T> //
|
||||
T /*UF_API*/ uf::vector::round( const T& vector ) {
|
||||
T res;
|
||||
for ( uint_fast8_t i = 0; i < T::size; ++i ) res[i] = std::round( vector[i] );
|
||||
return res;
|
||||
}
|
||||
// Complex arithmetic
|
||||
template<typename T> // Compute the dot product between two vectors
|
||||
typename T::type_t /*UF_API*/ uf::vector::dot( const T& left, const T& right ) {
|
||||
|
||||
@ -30,9 +30,6 @@ namespace ext {
|
||||
uf::stl::string name = "";
|
||||
ext::RENDERER::enums::Type::type_t type = 0;
|
||||
size_t components = 0;
|
||||
// somewhat essential
|
||||
size_t length = 0;
|
||||
void* pointer = NULL;
|
||||
|
||||
bool operator==( const AttributeDescriptor& right ) const { return
|
||||
offset == right.offset &&
|
||||
@ -56,6 +53,10 @@ namespace uf {
|
||||
ext::RENDERER::AttributeDescriptor descriptor;
|
||||
int32_t buffer = -1;
|
||||
size_t offset = 0;
|
||||
|
||||
size_t stride = 0;
|
||||
size_t length = 0;
|
||||
void* pointer = NULL;
|
||||
};
|
||||
struct Input {
|
||||
uf::stl::vector<Attribute> attributes;
|
||||
@ -64,16 +65,19 @@ namespace uf {
|
||||
size_t stride = 0; // size of one element in the input's buffer
|
||||
size_t offset = 0; // bytes to offset from within the associated buffer
|
||||
int32_t interleaved = -1; // index to interleaved buffer if in bounds
|
||||
|
||||
struct Settings {
|
||||
bool interleaved = false;
|
||||
} settings;
|
||||
} vertex, index, instance, indirect;
|
||||
/*
|
||||
struct Bounds {
|
||||
pod::Vector3f min = { std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max() };
|
||||
pod::Vector3f max = { -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max() };
|
||||
} bounds;
|
||||
*/
|
||||
uf::stl::vector<buffer_t> buffers;
|
||||
protected:
|
||||
void _destroy( uf::Mesh::Input& input );
|
||||
void _bind( bool interleaved = uf::Mesh::defaultInterleaved );
|
||||
void _updateDescriptor( uf::Mesh::Input& input );
|
||||
uf::Mesh::Attribute _remapAttribute( const uf::Mesh::Input& input, const uf::Mesh::Attribute& attribute, size_t i = 0 ) const;
|
||||
|
||||
bool _hasV( const uf::Mesh::Input& input, const uf::stl::vector<ext::RENDERER::AttributeDescriptor>& descriptors ) const;
|
||||
bool _hasV( const uf::Mesh::Input& input, const uf::Mesh::Input& src ) const;
|
||||
@ -81,10 +85,10 @@ namespace uf {
|
||||
void _resizeVs( uf::Mesh::Input& input, size_t count );
|
||||
void _reserveVs( uf::Mesh::Input& input, size_t count );
|
||||
void _insertV( uf::Mesh::Input& input, const void* data );
|
||||
void _insertV( uf::Mesh::Input& input, const uf::Mesh& mesh, const uf::Mesh::Input& srcInput );
|
||||
void _insertVs( uf::Mesh::Input& input, const void* data, size_t size );
|
||||
void _insertVs( uf::Mesh::Input& input, const uf::Mesh& mesh, const uf::Mesh::Input& srcInput );
|
||||
|
||||
template<typename T> inline bool _hasV( const uf::Mesh::Input& input ) const { return _hasV( input, T::descriptors ); }
|
||||
template<typename T> inline bool _hasV( const uf::Mesh::Input& input ) const { return _hasV( input, T::descriptor ); }
|
||||
template<typename T> inline void _bindV( uf::Mesh::Input& input ) { return _bindV( input, T::descriptor ); }
|
||||
template<typename T> inline void _insertV( uf::Mesh::Input& input, const T& vertex ) { return _insertV( input, (const void*) &vertex ); }
|
||||
template<typename T> inline void _insertVs( uf::Mesh::Input& input, const uf::stl::vector<T>& vs ) { return _insertVs( input, (const void*) vs.data(), vs.size() ); }
|
||||
@ -93,8 +97,8 @@ namespace uf {
|
||||
void _reserveIs( uf::Mesh::Input& input, size_t count, size_t i = 0 );
|
||||
void _resizeIs( uf::Mesh::Input& input, size_t count, size_t i = 0 );
|
||||
void _insertI( uf::Mesh::Input& input, const void* data, size_t i );
|
||||
void _insertI( uf::Mesh::Input& input, const uf::Mesh& mesh, const uf::Mesh::Input& srcInput );
|
||||
void _insertIs( uf::Mesh::Input& input, const void* data, size_t size, size_t i );
|
||||
void _insertIs( uf::Mesh::Input& input, const uf::Mesh& mesh, const uf::Mesh::Input& srcInput );
|
||||
|
||||
template<typename U> inline void _bindI( uf::Mesh::Input& input, size_t indices = 1 ) { return _bindI( input, sizeof(U), ext::RENDERER::typeToEnum<U>(), indices ); }
|
||||
template<typename U> inline void _insertI( uf::Mesh::Input& input, U index, size_t i = 0 ) { return _insertI( input, (const void*) &index, i ); }
|
||||
@ -105,6 +109,8 @@ namespace uf {
|
||||
|
||||
uf::Mesh interleave() const;
|
||||
void updateDescriptor();
|
||||
|
||||
void bind( const uf::Mesh& );
|
||||
void insert( const uf::Mesh& );
|
||||
|
||||
void generateIndices();
|
||||
@ -121,10 +127,11 @@ namespace uf {
|
||||
inline void reserveVertices( size_t count ) { return _reserveVs( vertex, count ); }
|
||||
inline void insertVertex( const void* data ) { return _insertV( vertex, data ); }
|
||||
inline void insertVertices( const void* data, size_t size ) { return _insertVs( vertex, data, size ); }
|
||||
inline void insertVertices( const uf::Mesh& mesh ) { return _insertV( vertex, mesh, mesh.vertex ); }
|
||||
inline void insertVertices( const uf::Mesh& mesh ) { return _insertVs( vertex, mesh, mesh.vertex ); }
|
||||
inline void updateVertexDescriptor() { return _updateDescriptor( vertex ); }
|
||||
inline uf::Mesh::Attribute remapVertexAttribute( const uf::Mesh::Attribute& attribute, size_t i = 0 ) const { return _remapAttribute( vertex, attribute, i ); }
|
||||
|
||||
template<typename T> inline bool hasVertex() const { return _hasV( vertex, T::descriptors ); }
|
||||
template<typename T> inline bool hasVertex() const { return _hasV( vertex, T::descriptor ); }
|
||||
template<typename T> inline void bindVertex() { return _bindV( vertex, T::descriptor ); }
|
||||
template<typename T> inline void insertVertex( const T& v ) { return _insertV( vertex, (const void*) &v ); }
|
||||
template<typename T> inline void insertVertices( const uf::stl::vector<T>& vertices ) { return _insertVs( vertex, (const void*) vertices.data(), vertices.size() ); }
|
||||
@ -134,8 +141,9 @@ namespace uf {
|
||||
inline void resizeIndices( size_t count, size_t i = 0 ) { return _resizeIs( index, count, i ); }
|
||||
inline void insertIndex( const void* data, size_t i = 0 ) { return _insertI( index, data, i ); }
|
||||
inline void insertIndices( const void* data, size_t size, size_t i = 0 ) { return _insertIs( index, data, size, i ); }
|
||||
inline void insertIndices( const uf::Mesh& mesh ) { return _insertI( index, mesh, mesh.index ); }
|
||||
inline void insertIndices( const uf::Mesh& mesh ) { return _insertIs( index, mesh, mesh.index ); }
|
||||
inline void updateIndexDescriptor() { return _updateDescriptor( index ); }
|
||||
inline uf::Mesh::Attribute remapIndexAttribute( const uf::Mesh::Attribute& attribute, size_t i = 0 ) const { return _remapAttribute( index, attribute, i ); }
|
||||
|
||||
template<typename U> inline void bindIndex( size_t count = 1 ) { return _bindI( index, sizeof(U), ext::RENDERER::typeToEnum<U>(), count ); }
|
||||
template<typename U> inline void insertIndex( U I, size_t i = 0 ) { return _insertI( index, (const void*) &I, i ); }
|
||||
@ -148,10 +156,10 @@ namespace uf {
|
||||
inline void reserveInstances( size_t count ) { return _reserveVs( instance, count ); }
|
||||
inline void insertInstance( const void* data ) { return _insertV( instance, data ); }
|
||||
inline void insertInstances( const void* data, size_t size ) { return _insertVs( instance, data, size ); }
|
||||
inline void insertInstances( const uf::Mesh& mesh ) { return _insertV( instance, mesh, mesh.instance ); }
|
||||
inline void insertInstances( const uf::Mesh& mesh ) { return _insertVs( instance, mesh, mesh.instance ); }
|
||||
inline void updateInstanceDescriptor() { return _updateDescriptor( instance ); }
|
||||
|
||||
template<typename T> inline bool hasInstance() const { return _hasV( instance, T::descriptors ); }
|
||||
template<typename T> inline bool hasInstance() const { return _hasV( instance, T::descriptor ); }
|
||||
template<typename T> inline void bindInstance() { return _bindV( instance, T::descriptor ); }
|
||||
template<typename T> inline void insertInstance( const T& v ) { return _insertV( instance, (const void*) &v ); }
|
||||
template<typename T> inline void insertInstances( const uf::stl::vector<T>& instances ) { return _insertVs( instance, (const void*) instances.data(), instances.size() ); }
|
||||
@ -161,7 +169,7 @@ namespace uf {
|
||||
inline void resizeIndirects( size_t count, size_t i = 0 ) { return _resizeIs( indirect, count, i ); }
|
||||
inline void insertIndirect( const void* data, size_t i = 0 ) { return _insertI( indirect, data, i ); }
|
||||
inline void insertIndirects( const void* data, size_t size, size_t i = 0 ) { return _insertIs( indirect, data, size, i ); }
|
||||
inline void insertIndirects( const uf::Mesh& mesh ) { return _insertI( indirect, mesh, mesh.indirect ); }
|
||||
inline void insertIndirects( const uf::Mesh& mesh ) { return _insertIs( indirect, mesh, mesh.indirect ); }
|
||||
inline void updateIndirectDescriptor() { return _updateDescriptor( indirect ); }
|
||||
|
||||
template<typename U> inline void bindIndirect( size_t i = 1 ) { return _bindI( indirect, sizeof(U), ext::RENDERER::typeToEnum<U>(), i ); }
|
||||
@ -175,6 +183,15 @@ namespace uf {
|
||||
_bind( interleave );
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename U = uint32_t>
|
||||
struct UF_API Mesh_T {
|
||||
typedef T vertex_t;
|
||||
typedef U index_t;
|
||||
|
||||
uf::stl::vector<vertex_t> vertices;
|
||||
uf::stl::vector<index_t> indices;
|
||||
};
|
||||
}
|
||||
|
||||
namespace ext {
|
||||
@ -195,6 +212,7 @@ namespace ext {
|
||||
struct {
|
||||
uf::Mesh::Input vertex, index, instance, indirect;
|
||||
size_t bufferOffset = 0;
|
||||
pod::Vector3ui dispatch = { 0, 0, 0 };
|
||||
} inputs;
|
||||
|
||||
ext::RENDERER::enums::PrimitiveTopology::type_t topology = ext::RENDERER::enums::PrimitiveTopology::TRIANGLE_LIST;
|
||||
|
||||
@ -176,8 +176,8 @@ uf::stl::string uf::Asset::load( const uf::stl::string& uri, const uf::stl::stri
|
||||
metadata[uri]["flags"]["ATLAS"] = false;
|
||||
metadata[uri]["flags"]["SEPARATE"] = true;
|
||||
#elif UF_GRAPH_INDIRECT_DRAW
|
||||
metadata[uri]["flags"]["ATLAS"] = false;
|
||||
metadata[uri]["flags"]["SEPARATE"] = false;
|
||||
// metadata[uri]["flags"]["ATLAS"] = false;
|
||||
// metadata[uri]["flags"]["SEPARATE"] = false;
|
||||
#endif
|
||||
asset = uf::graph::load( filename, metadata[uri] );
|
||||
uf::graph::process( asset );
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -66,6 +66,10 @@ void uf::GraphBehavior::initialize( uf::Object& self ) {
|
||||
}
|
||||
void uf::GraphBehavior::destroy( uf::Object& self ) {}
|
||||
void uf::GraphBehavior::tick( uf::Object& self ) {
|
||||
if ( this->hasComponent<pod::Graph>() ) {
|
||||
auto& graph = this->getComponent<pod::Graph>();
|
||||
uf::graph::update( graph );
|
||||
}
|
||||
#if 0
|
||||
/* Update animations */ if ( this->hasComponent<pod::Graph>() ) {
|
||||
auto& graph = this->getComponent<pod::Graph>();
|
||||
|
||||
@ -18,6 +18,7 @@ UF_BEHAVIOR_TRAITS_CPP(uf::RenderBehavior, ticks = true, renders = true, multith
|
||||
#define this (&self)
|
||||
void uf::RenderBehavior::initialize( uf::Object& self ) {}
|
||||
void uf::RenderBehavior::tick( uf::Object& self ) {
|
||||
#if 0
|
||||
if ( !this->hasComponent<uf::Graphic>() ) return;
|
||||
const auto& metadata = this->getComponent<uf::Serializer>();
|
||||
const auto& scene = uf::scene::getCurrentScene();
|
||||
@ -67,8 +68,10 @@ void uf::RenderBehavior::tick( uf::Object& self ) {
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
void uf::RenderBehavior::render( uf::Object& self ) {
|
||||
#if 0
|
||||
if ( !this->hasComponent<uf::Graphic>() ) return;
|
||||
const auto& metadata = this->getComponent<uf::Serializer>();
|
||||
const auto& scene = uf::scene::getCurrentScene();
|
||||
@ -119,7 +122,7 @@ void uf::RenderBehavior::render( uf::Object& self ) {
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
void uf::RenderBehavior::destroy( uf::Object& self ) {}
|
||||
|
||||
@ -5,8 +5,21 @@
|
||||
#include <uf/utils/renderer/renderer.h>
|
||||
#include <uf/utils/graphic/graphic.h>
|
||||
#include <uf/engine/scene/scene.h>
|
||||
#include <uf/engine/graph/graph.h>
|
||||
#include <BulletCollision/CollisionShapes/btTriangleShape.h>
|
||||
|
||||
struct VertexLine {
|
||||
pod::Vector3f position;
|
||||
pod::Vector3f color;
|
||||
|
||||
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
|
||||
};
|
||||
|
||||
UF_VERTEX_DESCRIPTOR(VertexLine,
|
||||
UF_VERTEX_DESCRIPTION(VertexLine, R32G32B32_SFLOAT, position)
|
||||
UF_VERTEX_DESCRIPTION(VertexLine, R32G32B32_SFLOAT, color)
|
||||
);
|
||||
|
||||
class BulletDebugDrawer : public btIDebugDraw {
|
||||
protected:
|
||||
int m;
|
||||
@ -16,15 +29,19 @@ public:
|
||||
drawLine( from, to, color, color );
|
||||
}
|
||||
virtual void drawLine( const btVector3& from, const btVector3& to, const btVector3& fromColor, const btVector3& toColor ) {
|
||||
pod::Vertex_3F2F3F4F vertex;
|
||||
|
||||
vertex.position = { from.getX(), from.getY(), from.getZ() };
|
||||
vertex.color = { fromColor.getX(), fromColor.getY(), fromColor.getZ(), 1.0f };
|
||||
mesh.insertVertex(vertex);
|
||||
|
||||
vertex.position = { to.getX(), to.getY(), to.getZ() };
|
||||
vertex.color = { toColor.getX(), toColor.getY(), toColor.getZ(), 1.0f };
|
||||
mesh.insertVertex(vertex);
|
||||
uf::stl::vector<VertexLine> vertices;
|
||||
{
|
||||
auto& vertex = vertices.emplace_back();
|
||||
vertex.position = { from.getX(), from.getY(), from.getZ() };
|
||||
vertex.color = { fromColor.getX(), fromColor.getY(), fromColor.getZ() };
|
||||
}
|
||||
{
|
||||
auto& vertex = vertices.emplace_back();
|
||||
vertex.position = { to.getX(), to.getY(), to.getZ() };
|
||||
vertex.color = { toColor.getX(), toColor.getY(), toColor.getZ() };
|
||||
}
|
||||
if ( !mesh.hasVertex<VertexLine>() ) mesh.bind<VertexLine>();
|
||||
mesh.insertVertices(vertices);
|
||||
}
|
||||
virtual void drawContactPoint(const btVector3&, const btVector3&, btScalar, int, const btVector3&) {
|
||||
|
||||
@ -39,7 +56,9 @@ public:
|
||||
m = p;
|
||||
}
|
||||
virtual void clearLines() {
|
||||
mesh.destroy();
|
||||
for ( auto& buffer : mesh.buffers ) buffer.clear();
|
||||
mesh.vertex.count = 0;
|
||||
mesh.index.count = 0;
|
||||
}
|
||||
virtual void flushLines() {
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
@ -113,6 +132,9 @@ void ext::bullet::initialize() {
|
||||
ext::bullet::debugDrawer.setDebugMode(btIDebugDraw::DBG_DrawWireframe);
|
||||
ext::bullet::dynamicsWorld->setDebugDrawer(&ext::bullet::debugDrawer);
|
||||
|
||||
auto& mesh = ext::bullet::debugDrawer.getMesh();
|
||||
mesh.bind<VertexLine>();
|
||||
|
||||
#if !UF_ENV_DREAMCAST
|
||||
gContactAddedCallback = contactCallback;
|
||||
#endif
|
||||
@ -276,42 +298,110 @@ void ext::bullet::detach( pod::Bullet& collider ) {
|
||||
}
|
||||
|
||||
pod::Bullet& ext::bullet::create( uf::Object& object, const uf::Mesh& mesh, bool dynamic ) {
|
||||
auto& transform = object.getComponent<pod::Transform<>>();
|
||||
btTriangleIndexVertexArray* bMesh = new btTriangleIndexVertexArray();
|
||||
|
||||
if ( mesh.index.count ) {
|
||||
uf::Mesh::Attribute vertexAttribute;
|
||||
for ( auto& attribute : mesh.vertex.attributes ) if ( attribute.descriptor.name == "position" ) { vertexAttribute = attribute; break; }
|
||||
UF_ASSERT( vertexAttribute.descriptor.name == "position" );
|
||||
|
||||
auto& indexAttribute = mesh.index.attributes.front();
|
||||
PHY_ScalarType indexType = PHY_INTEGER;
|
||||
PHY_ScalarType vertexType = PHY_FLOAT;
|
||||
switch ( mesh.index.stride ) {
|
||||
case sizeof(uint8_t): indexType = PHY_UCHAR; break;
|
||||
case sizeof(uint16_t): indexType = PHY_SHORT; break;
|
||||
case sizeof(uint32_t): indexType = PHY_INTEGER; break;
|
||||
default: UF_EXCEPTION("unsupported index type"); break;
|
||||
}
|
||||
|
||||
btIndexedMesh iMesh;
|
||||
if ( mesh.indirect.count ) {
|
||||
uf::Mesh::Attribute remappedVertexAttribute;
|
||||
uf::Mesh::Attribute remappedIndexAttribute;
|
||||
for ( auto i = 0; i < mesh.indirect.count; ++i ) {
|
||||
remappedVertexAttribute = mesh.remapVertexAttribute( vertexAttribute, i );
|
||||
remappedIndexAttribute = mesh.remapIndexAttribute( indexAttribute, i );
|
||||
|
||||
iMesh.m_numTriangles = remappedIndexAttribute.length / 3;
|
||||
iMesh.m_triangleIndexBase = (const uint8_t*) remappedIndexAttribute.pointer;
|
||||
iMesh.m_triangleIndexStride = remappedIndexAttribute.stride * 3;
|
||||
|
||||
iMesh.m_numVertices = remappedVertexAttribute.length;
|
||||
iMesh.m_vertexBase = (const uint8_t*) remappedVertexAttribute.pointer;
|
||||
iMesh.m_vertexStride = remappedVertexAttribute.stride;
|
||||
iMesh.m_indexType = indexType;
|
||||
iMesh.m_vertexType = vertexType;
|
||||
|
||||
bMesh->addIndexedMesh( iMesh, indexType );
|
||||
}
|
||||
} else {
|
||||
iMesh.m_numTriangles = indexAttribute.length / 3;
|
||||
iMesh.m_triangleIndexBase = (const uint8_t*) indexAttribute.pointer;
|
||||
iMesh.m_triangleIndexStride = indexAttribute.stride * 3;
|
||||
|
||||
iMesh.m_numVertices = vertexAttribute.length;
|
||||
iMesh.m_vertexBase = (const uint8_t*) vertexAttribute.pointer;
|
||||
iMesh.m_vertexStride = vertexAttribute.stride;
|
||||
iMesh.m_indexType = indexType;
|
||||
iMesh.m_vertexType = vertexType;
|
||||
bMesh->addIndexedMesh( iMesh, indexType );
|
||||
}
|
||||
} else UF_EXCEPTION("to-do: not require indices for meshes");
|
||||
|
||||
auto& collider = ext::bullet::create( object );
|
||||
auto model = uf::transform::model( collider.transform );
|
||||
|
||||
btTriangleMesh* bMesh = new btTriangleMesh( true, false );
|
||||
for ( auto& attribute : mesh.vertex.attributes ) {
|
||||
if ( attribute.descriptor.name != "position" ) continue;
|
||||
|
||||
const pod::Vector3f* pointer = (const pod::Vector3f*) attribute.descriptor.pointer;
|
||||
bMesh->preallocateVertices( mesh.vertex.count );
|
||||
for ( auto i = 0; i < mesh.vertex.count; ++i ) {
|
||||
bMesh->findOrAddVertex( btVector3( pointer[i].x, pointer[i].y, pointer[i].z ), false );
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ( mesh.index.count ) {
|
||||
bMesh->preallocateIndices( mesh.index.count );
|
||||
for ( auto& attribute : mesh.index.attributes ) {
|
||||
size_t count = attribute.descriptor.length / attribute.descriptor.size;
|
||||
const uint8_t* pointer = (const uint8_t*) attribute.descriptor.pointer;
|
||||
for ( auto i = 0; i < count; ++i ) {
|
||||
uint32_t index = 0;
|
||||
switch ( attribute.descriptor.size ) {
|
||||
case sizeof( uint8_t): index = (( uint8_t*) pointer)[i]; break;
|
||||
case sizeof(uint16_t): index = ((uint16_t*) pointer)[i]; break;
|
||||
case sizeof(uint32_t): index = ((uint32_t*) pointer)[i]; break;
|
||||
}
|
||||
bMesh->addIndex( index );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
collider.shape = new btBvhTriangleMeshShape(bMesh, true);
|
||||
collider.shape = new btBvhTriangleMeshShape( bMesh, true, true );
|
||||
ext::bullet::attach( collider );
|
||||
|
||||
auto& transform = object.getComponent<pod::Transform<>>();
|
||||
auto model = uf::transform::model( collider.transform );
|
||||
btTransform t = collider.body->getWorldTransform();
|
||||
t.setFromOpenGLMatrix(&model[0]);
|
||||
collider.body->setWorldTransform(t);
|
||||
collider.body->setCenterOfMassTransform(t);
|
||||
|
||||
btBvhTriangleMeshShape* triangleMeshShape = (btBvhTriangleMeshShape*) collider.shape;
|
||||
btTriangleInfoMap* triangleInfoMap = new btTriangleInfoMap();
|
||||
triangleInfoMap->m_edgeDistanceThreshold = 0.01f;
|
||||
triangleInfoMap->m_maxEdgeAngleThreshold = SIMD_HALF_PI*0.25;
|
||||
if ( !false ) btGenerateInternalEdgeInfo( triangleMeshShape, triangleInfoMap );
|
||||
collider.body->setCollisionFlags(collider.body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
|
||||
return collider;
|
||||
}
|
||||
pod::Bullet& ext::bullet::create( uf::Object& object, const void* verticesPointer, size_t verticesCount, size_t verticesStride, const void* indicesPointer, size_t indicesCount, size_t indicesStride, bool dynamic ) {
|
||||
btTriangleIndexVertexArray* bMesh = new btTriangleIndexVertexArray();
|
||||
|
||||
if ( indicesCount ) {
|
||||
PHY_ScalarType indexType = PHY_INTEGER;
|
||||
PHY_ScalarType vertexType = PHY_FLOAT;
|
||||
switch ( indicesStride ) {
|
||||
case 1: indexType = PHY_UCHAR; break;
|
||||
case 2: indexType = PHY_SHORT; break;
|
||||
case 4: indexType = PHY_INTEGER; break;
|
||||
}
|
||||
|
||||
const uint8_t* indicesBuffer = (const uint8_t*) indicesPointer;
|
||||
const uint8_t* verticesBuffer = (const uint8_t*) verticesPointer;
|
||||
|
||||
btIndexedMesh iMesh;
|
||||
iMesh.m_numTriangles = indicesCount / 3;
|
||||
iMesh.m_triangleIndexBase = indicesBuffer;
|
||||
iMesh.m_triangleIndexStride = 3 * indicesStride;
|
||||
iMesh.m_numVertices = verticesCount;
|
||||
iMesh.m_vertexBase = verticesBuffer;
|
||||
iMesh.m_vertexStride = verticesStride;
|
||||
iMesh.m_indexType = indexType;
|
||||
iMesh.m_vertexType = vertexType;
|
||||
bMesh->addIndexedMesh( iMesh, indexType );
|
||||
} else UF_EXCEPTION("to-do: not require indices for meshes");
|
||||
|
||||
|
||||
auto& collider = ext::bullet::create( object );
|
||||
collider.shape = new btBvhTriangleMeshShape( bMesh, true, true );
|
||||
ext::bullet::attach( collider );
|
||||
|
||||
auto& transform = object.getComponent<pod::Transform<>>();
|
||||
auto model = uf::transform::model( collider.transform );
|
||||
btTransform t = collider.body->getWorldTransform();
|
||||
t.setFromOpenGLMatrix(&model[0]);
|
||||
collider.body->setWorldTransform(t);
|
||||
@ -443,33 +533,32 @@ void UF_API ext::bullet::activateCollision( pod::Bullet& collider, bool enabled
|
||||
|
||||
void UF_API ext::bullet::debugDraw( uf::Object& object ) {
|
||||
auto& mesh = ext::bullet::debugDrawer.getMesh();
|
||||
mesh.bind<pod::Vertex_3F2F3F4F>();
|
||||
|
||||
if ( !mesh.vertex.count ) return;
|
||||
|
||||
bool create = !object.hasComponent<uf::Graphic>();
|
||||
auto& graphic = object.getComponent<uf::Graphic>();
|
||||
graphic.process = false;
|
||||
if ( create ) {
|
||||
graphic.process = true;
|
||||
|
||||
graphic.device = &uf::renderer::device;
|
||||
graphic.material.device = &uf::renderer::device;
|
||||
graphic.descriptor.cullMode = uf::renderer::enums::CullMode::NONE;
|
||||
|
||||
graphic.material.attachShader(uf::io::root + "/shaders/base/colored.vert.spv", uf::renderer::enums::Shader::VERTEX);
|
||||
graphic.material.attachShader(uf::io::root + "/shaders/base/base.frag.spv", uf::renderer::enums::Shader::FRAGMENT);
|
||||
graphic.material.metadata.json["shader"]["autoInitializeUniformBuffers"] = false;
|
||||
|
||||
graphic.initialize();
|
||||
graphic.material.attachShader(uf::io::root + "/shaders/bullet/base.vert.spv", uf::renderer::enums::Shader::VERTEX);
|
||||
graphic.material.attachShader(uf::io::root + "/shaders/bullet/base.frag.spv", uf::renderer::enums::Shader::FRAGMENT);
|
||||
|
||||
graphic.material.getShader("vertex").buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.camera );
|
||||
|
||||
graphic.initialize("Gui");
|
||||
graphic.initializeMesh( mesh );
|
||||
|
||||
graphic.descriptor.topology = uf::renderer::enums::PrimitiveTopology::LINE_LIST;
|
||||
graphic.descriptor.fill = uf::renderer::enums::PolygonMode::LINE;
|
||||
graphic.descriptor.lineWidth = 8.0f;
|
||||
} else {
|
||||
graphic.process = true;
|
||||
|
||||
graphic.initializeMesh( mesh );
|
||||
graphic.getPipeline().update( graphic );
|
||||
graphic.updateMesh( mesh );
|
||||
}
|
||||
graphic.process = true;
|
||||
}
|
||||
#endif
|
||||
@ -133,11 +133,26 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
|
||||
return graph;
|
||||
}
|
||||
|
||||
// load images
|
||||
{
|
||||
graph.images.reserve(model.images.size());
|
||||
graph.storage.images.reserve(model.images.size());
|
||||
|
||||
for ( auto& i : model.images ) {
|
||||
auto imageID = graph.images.size();
|
||||
auto keyName = graph.images.emplace_back(filename + "/" + i.name);
|
||||
auto& image = graph.storage.images[keyName];
|
||||
image.loadFromBuffer( &i.image[0], {i.width, i.height}, 8, i.component, true );
|
||||
}
|
||||
}
|
||||
// load samplers
|
||||
{
|
||||
uf::graph::storage.samplers.reserve(model.samplers.size());
|
||||
graph.storage.samplers.reserve(model.samplers.size());
|
||||
for ( auto& s : model.samplers ) {
|
||||
auto& sampler = uf::graph::storage.samplers[graph.samplers.emplace_back(s.name)];
|
||||
auto samplerID = graph.samplers.size();
|
||||
auto keyName = graph.samplers.emplace_back(filename + "/" + s.name);
|
||||
auto& sampler = graph.storage.samplers[keyName];
|
||||
|
||||
sampler.descriptor.filter.min = getFilterMode( s.minFilter );
|
||||
sampler.descriptor.filter.mag = getFilterMode( s.magFilter );
|
||||
sampler.descriptor.addressMode.u = getWrapMode( s.wrapS );
|
||||
@ -145,44 +160,30 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
|
||||
sampler.descriptor.addressMode.w = sampler.descriptor.addressMode.v;
|
||||
}
|
||||
}
|
||||
|
||||
// load images
|
||||
{
|
||||
uf::graph::storage.images.reserve(model.images.size());
|
||||
for ( auto& i : model.images ) {
|
||||
auto& image = uf::graph::storage.images[graph.images.emplace_back(i.name)];
|
||||
image.loadFromBuffer( &i.image[0], {i.width, i.height}, 8, i.component, true );
|
||||
}
|
||||
}
|
||||
// generate atlas
|
||||
if ( graph.metadata["flags"]["ATLAS"].as<bool>() ) {
|
||||
// uf::graph::storage.atlases[filename].generate();
|
||||
}
|
||||
// load textures
|
||||
{
|
||||
uf::graph::storage.textures.reserve(model.textures.size());
|
||||
graph.textures.reserve(model.textures.size());
|
||||
graph.storage.textures.reserve(model.textures.size());
|
||||
|
||||
for ( auto& t : model.textures ) {
|
||||
auto& texture = uf::graph::storage.textures[graph.textures.emplace_back(t.name)];
|
||||
auto textureID = graph.textures.size();
|
||||
auto keyName = graph.textures.emplace_back((t.name == "" ? graph.images[t.source] : (filename + "/" + t.name)));
|
||||
auto& texture = graph.storage.textures[keyName];
|
||||
|
||||
texture.index = t.source;
|
||||
texture.sampler = t.sampler;
|
||||
if ( 0 <= t.source && uf::graph::storage.atlases[filename].generated() ) {
|
||||
auto& image = graph.images[t.source];
|
||||
const auto& hash = uf::graph::storage.images[image].getHash();
|
||||
auto atlasMin = uf::graph::storage.atlases[filename].mapUv( {0, 0}, hash );
|
||||
auto atlasMax = uf::graph::storage.atlases[filename].mapUv( {1, 1}, hash );
|
||||
texture.lerp = { atlasMin.x, atlasMin.y, atlasMax.x, atlasMax.y, };
|
||||
}
|
||||
}
|
||||
}
|
||||
// clear source images
|
||||
if ( uf::graph::storage.atlases[filename].generated() ) {
|
||||
uf::graph::storage.atlases[filename].clear(false);
|
||||
}
|
||||
// load materials
|
||||
{
|
||||
uf::graph::storage.materials.reserve(model.materials.size());
|
||||
graph.materials.reserve(model.materials.size());
|
||||
graph.storage.materials.reserve(model.materials.size());
|
||||
|
||||
for ( auto& m : model.materials ) {
|
||||
auto& material = uf::graph::storage.materials[graph.materials.emplace_back(m.name)];
|
||||
auto materialID = graph.materials.size();
|
||||
auto keyName = graph.materials.emplace_back(filename + "/" + m.name);
|
||||
auto& material = graph.storage.materials[keyName];
|
||||
|
||||
material.indexAlbedo = m.pbrMetallicRoughness.baseColorTexture.index;
|
||||
material.indexNormal = m.normalTexture.index;
|
||||
material.indexEmissive = m.emissiveTexture.index;
|
||||
@ -219,14 +220,28 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
|
||||
// load meshes
|
||||
{
|
||||
graph.meshes.reserve(model.meshes.size());
|
||||
for ( auto& m : model.meshes ) {
|
||||
auto& pair = uf::graph::storage.meshes[graph.meshes.emplace_back(m.name)];
|
||||
auto& mesh = pair.mesh;
|
||||
mesh.bind<uf::graph::mesh::Skinned, uint32_t>();
|
||||
graph.storage.meshes.reserve(model.meshes.size());
|
||||
|
||||
for ( auto& m : model.meshes ) {
|
||||
auto meshID = graph.meshes.size();
|
||||
auto keyName = graph.meshes.emplace_back(filename + "/" + m.name);
|
||||
graph.primitives.emplace_back(keyName);
|
||||
graph.drawCommands.emplace_back(keyName);
|
||||
|
||||
auto& drawCommands = graph.storage.drawCommands[keyName];
|
||||
auto& primitives = graph.storage.primitives[keyName];
|
||||
auto& mesh = graph.storage.meshes[keyName];
|
||||
mesh.bindIndirect<pod::DrawCommand>();
|
||||
mesh.bind<uf::graph::mesh::Skinned, uint32_t>();
|
||||
/*
|
||||
size_t primitiveID = 0;
|
||||
*/
|
||||
uf::stl::vector<uf::graph::mesh::Skinned> vertices;
|
||||
uf::stl::vector<uint32_t> indices;
|
||||
for ( auto& p : m.primitives ) {
|
||||
uf::stl::vector<uf::graph::mesh::Skinned> vertices;
|
||||
uf::stl::vector<uint32_t> indices;
|
||||
vertices.clear();
|
||||
indices.clear();
|
||||
auto& primitive = primitives.emplace_back();
|
||||
|
||||
struct Attribute {
|
||||
uf::stl::string name = "";
|
||||
@ -234,6 +249,7 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
|
||||
uf::stl::vector<float> floats;
|
||||
uf::stl::vector<uint16_t> ints;
|
||||
};
|
||||
|
||||
uf::stl::unordered_map<uf::stl::string, Attribute> attributes = {
|
||||
{"POSITION", {}},
|
||||
{"TEXCOORD_0", {}},
|
||||
@ -254,11 +270,8 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
|
||||
|
||||
if ( attribute.name == "POSITION" ) {
|
||||
vertices.resize(accessor.count);
|
||||
pod::Vector3f minCorner = { accessor.minValues[0], accessor.minValues[1], accessor.minValues[2] };
|
||||
pod::Vector3f maxCorner = { accessor.maxValues[0], accessor.maxValues[1], accessor.maxValues[2] };
|
||||
|
||||
pod::Vector3f origin = (maxCorner + minCorner) * 0.5f;
|
||||
pod::Vector3f size = (maxCorner - minCorner) * 0.5f;
|
||||
primitive.instance.bounds.min = pod::Vector3f{ accessor.minValues[0], accessor.minValues[1], accessor.minValues[2] };
|
||||
primitive.instance.bounds.max = pod::Vector3f{ accessor.maxValues[0], accessor.maxValues[1], accessor.maxValues[2] };
|
||||
}
|
||||
if ( attribute.name == "JOINTS_0" ) {
|
||||
auto* buffer = reinterpret_cast<const uint16_t*>(&(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset]));
|
||||
@ -300,8 +313,6 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
|
||||
vertex.normal.x *= -1;
|
||||
vertex.tangent.x *= -1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if ( p.indices > -1 ) {
|
||||
@ -311,9 +322,7 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
|
||||
|
||||
indices.reserve( static_cast<uint32_t>(accessor.count) );
|
||||
|
||||
#define COPY_INDICES()\
|
||||
for (size_t index = 0; index < indices.size(); index++)\
|
||||
indices.emplace_back(buf[index]);
|
||||
#define COPY_INDICES() for (size_t index = 0; index < accessor.count; index++) indices.emplace_back(buf[index]);
|
||||
|
||||
const void* pointer = &(buffer.data[accessor.byteOffset + view.byteOffset]);
|
||||
switch (accessor.componentType) {
|
||||
@ -336,49 +345,46 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
|
||||
#undef COPY_INDICES
|
||||
}
|
||||
|
||||
pair.drawCommands.emplace_back(pod::DrawCommand{
|
||||
primitive.instance.materialID = p.material;
|
||||
primitive.instance.primitiveID = primitives.size() - 1;
|
||||
primitive.instance.meshID = meshID;
|
||||
primitive.instance.objectID = 0;
|
||||
|
||||
primitive.drawCommand.indices = indices.size();
|
||||
primitive.drawCommand.instances = 1;
|
||||
primitive.drawCommand.indexID = 0;
|
||||
primitive.drawCommand.vertexID = 0;
|
||||
primitive.drawCommand.instanceID = 0;
|
||||
primitive.drawCommand.vertices = vertices.size();
|
||||
|
||||
auto& drawCommand = drawCommands.emplace_back(pod::DrawCommand{
|
||||
.indices = indices.size(),
|
||||
.instances = 1,
|
||||
.indexID = mesh.index.count,
|
||||
.vertexID = mesh.vertex.count,
|
||||
|
||||
.instanceID = mesh.instance.count,
|
||||
.materialID = p.material,
|
||||
.objectID = 0,
|
||||
.instanceID = 0,
|
||||
// .meshID = meshID,
|
||||
// .objectID = materialID,
|
||||
.vertices = vertices.size(),
|
||||
});
|
||||
|
||||
|
||||
mesh.insertVertices(vertices);
|
||||
mesh.insertIndices(indices);
|
||||
}
|
||||
mesh.insertIndirects(drawCommands);
|
||||
mesh.updateDescriptor();
|
||||
}
|
||||
}
|
||||
// load node information/meshes
|
||||
{
|
||||
const auto& scene = model.scenes[model.defaultScene > -1 ? model.defaultScene : 0];
|
||||
graph.nodes.resize( model.nodes.size() );
|
||||
graph.root.index = -1;
|
||||
graph.root.children.reserve( scene.nodes.size() );
|
||||
for ( auto i : scene.nodes ) {
|
||||
size_t childIndex = loadNode( model, graph, i, -1 );
|
||||
graph.root.children.emplace_back(childIndex);
|
||||
}
|
||||
}
|
||||
// load lights
|
||||
{
|
||||
for ( auto& l : model.lights ) {
|
||||
auto& light = graph.lights[l.name];
|
||||
light.color = { l.color[0], l.color[1], l.color[2], };
|
||||
light.intensity = l.intensity;
|
||||
light.range = l.range;
|
||||
}
|
||||
}
|
||||
// load skins
|
||||
{
|
||||
graph.skins.reserve( model.skins.size() );
|
||||
graph.storage.skins.reserve( model.skins.size() );
|
||||
|
||||
for ( auto& s : model.skins ) {
|
||||
auto& skin = graph.skins.emplace_back();
|
||||
auto skinID = graph.skins.size();
|
||||
auto keyName = graph.skins.emplace_back(filename + "/" + s.name);
|
||||
auto& skin = graph.storage.skins[keyName];
|
||||
|
||||
skin.name = s.name;
|
||||
if ( s.inverseBindMatrices > -1 ) {
|
||||
const tinygltf::Accessor& accessor = model.accessors[s.inverseBindMatrices];
|
||||
@ -406,8 +412,12 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
|
||||
// load animations
|
||||
{
|
||||
graph.animations.reserve( model.animations.size() );
|
||||
graph.storage.animations.reserve( model.animations.size() );
|
||||
|
||||
for ( auto& a : model.animations ) {
|
||||
auto& animation = graph.animations[a.name];
|
||||
auto animationID = graph.animations.size();
|
||||
auto keyName = graph.animations.emplace_back(filename + "/" + a.name);
|
||||
auto& animation = graph.storage.animations[keyName];
|
||||
animation.name = a.name;
|
||||
|
||||
// load samplers
|
||||
@ -460,6 +470,62 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
|
||||
}
|
||||
}
|
||||
}
|
||||
// load lights
|
||||
{
|
||||
for ( auto& l : model.lights ) {
|
||||
auto& light = graph.lights[l.name];
|
||||
light.color = { l.color[0], l.color[1], l.color[2], };
|
||||
light.intensity = l.intensity;
|
||||
light.range = l.range;
|
||||
}
|
||||
}
|
||||
// load node information/meshes
|
||||
{
|
||||
const auto& scene = model.scenes[model.defaultScene > -1 ? model.defaultScene : 0];
|
||||
graph.nodes.resize( model.nodes.size() );
|
||||
|
||||
graph.root.name = "%ROOT%";
|
||||
graph.root.index = -1;
|
||||
graph.root.children.reserve( scene.nodes.size() );
|
||||
for ( auto i : scene.nodes ) {
|
||||
size_t childIndex = loadNode( model, graph, i, -1 );
|
||||
graph.root.children.emplace_back(childIndex);
|
||||
}
|
||||
}
|
||||
// generate atlas
|
||||
if ( graph.metadata["flags"]["ATLAS"].as<bool>() ) {
|
||||
auto atlasName = filename + "/" + "atlas";
|
||||
auto& atlas = graph.storage.atlases[atlasName];
|
||||
auto atlasImageIndex = graph.images.size();
|
||||
auto atlasTextureIndex = graph.textures.size();
|
||||
|
||||
for ( auto& keyName : graph.images ) atlas.addImage( graph.storage.images[keyName] );
|
||||
atlas.generate();
|
||||
|
||||
for ( auto& keyName : graph.images ) {
|
||||
auto& texture = graph.storage.textures[keyName];
|
||||
if ( texture.index < 0 ) continue;
|
||||
auto& image = graph.storage.images[keyName];
|
||||
|
||||
const auto& hash = image.getHash();
|
||||
auto min = atlas.mapUv( {0, 0}, hash );
|
||||
auto max = atlas.mapUv( {1, 1}, hash );
|
||||
|
||||
texture.lerp = pod::Vector4f{ min.x, min.y, max.x, max.y, };
|
||||
texture.index = atlasImageIndex;
|
||||
}
|
||||
|
||||
{
|
||||
graph.images.emplace_back(atlasName);
|
||||
auto& image = graph.storage.images[atlasName];
|
||||
image = atlas.getAtlas();
|
||||
|
||||
graph.textures.emplace_back(atlasName);
|
||||
auto& texture = graph.storage.textures[atlasName];
|
||||
texture.index = atlasImageIndex;
|
||||
}
|
||||
}
|
||||
|
||||
if ( graph.metadata["export"]["should"].as<bool>() ) uf::graph::save( graph, filename );
|
||||
return graph;
|
||||
}
|
||||
@ -163,61 +163,6 @@ void ext::opengl::CommandBuffer::record( const CommandBuffer::Info& header ) {
|
||||
info = &userdata.get<InfoDraw>();
|
||||
info->type = enums::Command::DRAW;
|
||||
} break;
|
||||
/*
|
||||
case ext::opengl::enums::Command::BIND_BUFFER: {
|
||||
InfoBuffer* info = (InfoBuffer*) &header;
|
||||
info->next = NULL;
|
||||
auto& userdata = infos.emplace_back();
|
||||
userdata.autoDestruct = false;
|
||||
userdata.create<InfoBuffer>( *info );
|
||||
info = &userdata.get<InfoBuffer>();
|
||||
info->type = enums::Command::BIND_BUFFER;
|
||||
} break;
|
||||
case ext::opengl::enums::Command::BIND_GRAPHIC_BUFFER: {
|
||||
InfoGraphicBuffer* info = (InfoGraphicBuffer*) &header;
|
||||
info->next = NULL;
|
||||
auto& userdata = infos.emplace_back();
|
||||
userdata.autoDestruct = false;
|
||||
userdata.create<InfoGraphicBuffer>( *info );
|
||||
info = &userdata.get<InfoGraphicBuffer>();
|
||||
info->type = enums::Command::BIND_GRAPHIC_BUFFER;
|
||||
} break;
|
||||
case ext::opengl::enums::Command::BIND_TEXTURE: {
|
||||
InfoTexture* info = (InfoTexture*) &header;
|
||||
info->next = NULL;
|
||||
auto& userdata = infos.emplace_back();
|
||||
userdata.autoDestruct = false;
|
||||
userdata.create<InfoTexture>( *info );
|
||||
info = &userdata.get<InfoTexture>();
|
||||
info->type = enums::Command::BIND_TEXTURE;
|
||||
} break;
|
||||
case ext::opengl::enums::Command::BIND_PIPELINE: {
|
||||
InfoPipeline* info = (InfoPipeline*) &header;
|
||||
info->next = NULL;
|
||||
auto& userdata = infos.emplace_back();
|
||||
userdata.autoDestruct = false;
|
||||
userdata.create<InfoPipeline>( *info );
|
||||
info = &userdata.get<InfoPipeline>();
|
||||
info->type = enums::Command::BIND_PIPELINE;
|
||||
} break;
|
||||
case ext::opengl::enums::Command::DRAW: {
|
||||
InfoDraw* info = (InfoDraw*) &header;
|
||||
info->next = NULL;
|
||||
auto& userdata = infos.emplace_back();
|
||||
userdata.autoDestruct = false;
|
||||
userdata.create<InfoDraw>( *info );
|
||||
info = &userdata.get<InfoDraw>();
|
||||
info->type = enums::Command::DRAW;
|
||||
} break;
|
||||
case ext::opengl::enums::Command::GENERATE_TEXTURE: {
|
||||
InfoGenerateTexture* info = (InfoGenerateTexture*) &header;
|
||||
auto& userdata = infos.emplace_back();
|
||||
userdata.autoDestruct = false;
|
||||
userdata.create( *info );
|
||||
info = &userdata.get<InfoGenerateTexture>();
|
||||
info->type = enums::Command::GENERATE_TEXTURE;
|
||||
} break;
|
||||
*/
|
||||
default: {
|
||||
} break;
|
||||
}
|
||||
@ -271,82 +216,6 @@ void ext::opengl::CommandBuffer::submit() {
|
||||
} break;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
CommandBuffer::Info* vertexBufferInfo = GL_NULL_HANDLE;
|
||||
CommandBuffer::Info* indexBufferInfo = GL_NULL_HANDLE;
|
||||
uf::stl::vector<CommandBuffer::InfoTexture*> textureInfos;
|
||||
textureInfos.reserve(maxTextures);
|
||||
if ( state == 2 && VERBOSE_SUBMIT ) std::cout << "==== ["<<this<<"] COMMAND BUFFER SUBMIT START ====\n";
|
||||
// 50us each process
|
||||
for ( auto& info : infos ) {
|
||||
CommandBuffer::Info* header = (CommandBuffer::Info*) (void*) info;
|
||||
switch ( header->type ) {
|
||||
case ext::opengl::enums::Command::CLEAR: {
|
||||
InfoClear* info = (InfoClear*) header;
|
||||
if ( state == 2 && VERBOSE_SUBMIT ) std::cout << "["<<info<<"] CLEARING SCREEN TO " << uf::vector::toString( info->color ) << " | DEPTH: " << info->depth << " | BITS: " << std::bitset<32>(info->bits) << "\n";
|
||||
GL_ERROR_CHECK(glClearColor(info->color[0], info->color[1], info->color[2], info->color[3]));
|
||||
GL_ERROR_CHECK(glClearDepth(info->depth));
|
||||
GL_ERROR_CHECK(glClear(info->bits));
|
||||
GL_ERROR_CHECK(glLightModelfv(GL_LIGHT_MODEL_AMBIENT, &info->color[0]));
|
||||
} break;
|
||||
case ext::opengl::enums::Command::VIEWPORT: {
|
||||
InfoViewport* info = (InfoViewport*) header;
|
||||
if ( state == 2 && VERBOSE_SUBMIT ) std::cout << "["<<info<<"] SETTING VIEWPORT TO " << uf::vector::toString(info->corner) << " | " << uf::vector::toString(info->size) << "\n";
|
||||
GL_ERROR_CHECK(glViewport(info->corner[0], info->corner[1], info->size[0], info->size[1]));
|
||||
} break;
|
||||
case ext::opengl::enums::Command::VARIANT: {
|
||||
InfoVariant* info = (InfoVariant*) header;
|
||||
if ( state == 2 && VERBOSE_SUBMIT ) std::cout << "["<<info<<"] CALLING LAMBDA\n";
|
||||
if ( info->lambda ) info->lambda();
|
||||
} break;
|
||||
case ext::opengl::enums::Command::BIND_BUFFER: {
|
||||
InfoBuffer* info = (InfoBuffer*) header;
|
||||
if ( state == 2 && VERBOSE_SUBMIT ) std::cout << "["<<info<<"] BINDING BUFFER: " << info->descriptor.buffer << " | FLAGS: " << /*std::bitset<16>*/(info->usage) << "\n";
|
||||
if ( info->usage & enums::Buffer::UNIFORM ) bindUniform( info->descriptor );
|
||||
if ( info->usage & enums::Buffer::VERTEX ) vertexBufferInfo = header;
|
||||
if ( info->usage & enums::Buffer::INDEX ) indexBufferInfo = header;
|
||||
} break;
|
||||
case ext::opengl::enums::Command::BIND_GRAPHIC_BUFFER: {
|
||||
InfoGraphicBuffer* info = (InfoGraphicBuffer*) header;
|
||||
if ( state == 2 && VERBOSE_SUBMIT ) std::cout << "["<<info<<"] BINDING BUFFER: ";
|
||||
auto& buffer = info->graphic->buffers[info->bufferIndex];
|
||||
if ( state == 2 && VERBOSE_SUBMIT ) std::cout << buffer.descriptor.buffer << " | FLAGS: " << /*std::bitset<16>*/(buffer.usage) << "\n";
|
||||
if ( buffer.usage & enums::Buffer::UNIFORM ) bindUniform( buffer.descriptor );
|
||||
if ( buffer.usage & enums::Buffer::VERTEX ) vertexBufferInfo = header;
|
||||
if ( buffer.usage & enums::Buffer::INDEX ) indexBufferInfo = header;
|
||||
} break;
|
||||
case ext::opengl::enums::Command::BIND_TEXTURE: {
|
||||
InfoTexture* info = (InfoTexture*) header;
|
||||
if ( state == 2 && VERBOSE_SUBMIT ) std::cout << "["<<info<<"] BINDING TEXTURE: " << info->descriptor.image << " | " << info->descriptor.viewType << "\n";
|
||||
textureInfos.emplace_back(info);
|
||||
} break;
|
||||
case ext::opengl::enums::Command::BIND_PIPELINE: {
|
||||
InfoPipeline* info = (InfoPipeline*) header;
|
||||
if ( state == 2 && VERBOSE_SUBMIT ) std::cout << "["<<info<<"] BINDING PIPELINE: " << info->descriptor.pipeline << " | " << info->descriptor.vertexArray << "\n";
|
||||
#if !UF_USE_OPENGL_FIXED_FUNCTION
|
||||
GL_ERROR_CHECK(glUseProgram(info->descriptor.pipeline));
|
||||
#endif
|
||||
} break;
|
||||
case ext::opengl::enums::Command::DRAW: {
|
||||
InfoDraw* info = (InfoDraw*) header;
|
||||
if ( state == 2 && VERBOSE_SUBMIT ) std::cout << "["<<info<<"] DRAW CALL | COUNT: " << info->length << " | VERTEX INFO: " << vertexBufferInfo << " | INDEX INFO: " << indexBufferInfo << "\n";
|
||||
if ( vertexBufferInfo ) {
|
||||
if ( indexBufferInfo ) drawIndexed( *info, *vertexBufferInfo, *indexBufferInfo, textureInfos );
|
||||
else draw( *info, *vertexBufferInfo, textureInfos );
|
||||
}
|
||||
textureInfos.clear();
|
||||
vertexBufferInfo = NULL;
|
||||
indexBufferInfo = NULL;
|
||||
} break;
|
||||
default: {
|
||||
if ( state == 2 && VERBOSE_SUBMIT ) {
|
||||
std::cout << "["<<header<<"] UNKNOWN COMMAND TYPE: " << header->type << ": " << info.data().len << std::endl;;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
if ( state == 2 && VERBOSE_SUBMIT ) std::cout << "==== ["<<this<<"] COMMAND BUFFER SUBMIT END ==== " << std::endl;
|
||||
#endif
|
||||
state = 3;
|
||||
mutex->unlock();
|
||||
}
|
||||
@ -355,10 +224,6 @@ void ext::opengl::CommandBuffer::flush() {
|
||||
for ( auto& userdata : infos ) userdata.destroy();
|
||||
infos.clear();
|
||||
state = 0;
|
||||
/*
|
||||
startInfo = NULL;
|
||||
endInfo = NULL;
|
||||
*/
|
||||
mutex->unlock();
|
||||
}
|
||||
size_t ext::opengl::CommandBuffer::size() const {
|
||||
@ -378,164 +243,6 @@ pod::Matrix4f ext::opengl::CommandBuffer::bindUniform( const ext::opengl::Buffer
|
||||
return uniform->projection * uniform->modelView;
|
||||
#endif
|
||||
}
|
||||
#if 0
|
||||
void ext::opengl::CommandBuffer::draw( const ext::opengl::CommandBuffer::InfoDraw& drawInfo, const ext::opengl::CommandBuffer::Info& vertexBufferInfo, const uf::stl::vector<InfoTexture*>& textureInfos ) {
|
||||
ext::opengl::Buffer::Descriptor vertexBuffer = {};
|
||||
|
||||
switch ( vertexBufferInfo.type ) {
|
||||
case ext::opengl::enums::Command::BIND_BUFFER: {
|
||||
ext::opengl::CommandBuffer::InfoBuffer* info = (ext::opengl::CommandBuffer::InfoBuffer*) &vertexBufferInfo;
|
||||
vertexBuffer = info->descriptor;
|
||||
} break;
|
||||
case ext::opengl::enums::Command::BIND_GRAPHIC_BUFFER: {
|
||||
ext::opengl::CommandBuffer::InfoGraphicBuffer* info = (ext::opengl::CommandBuffer::InfoGraphicBuffer*) &vertexBufferInfo;
|
||||
vertexBuffer = info->graphic->buffers[info->bufferIndex].descriptor;
|
||||
} break;
|
||||
}
|
||||
if ( !vertexBuffer.buffer ) return;
|
||||
|
||||
size_t vertexStride = drawInfo.descriptor.attributes.vertex.size;
|
||||
size_t vertices = vertexBuffer.range / vertexStride;
|
||||
|
||||
uf::renderer::AttributeDescriptor vertexAttributePosition,
|
||||
vertexAttributeNormal,
|
||||
vertexAttributeColor,
|
||||
vertexAttributeUv,
|
||||
vertexAttributeSt,
|
||||
vertexAttributeId;
|
||||
|
||||
for ( auto& attribute : drawInfo.descriptor.attributes.vertex.descriptor ) {
|
||||
if ( attribute.name == "position" ) vertexAttributePosition = attribute;
|
||||
else if ( attribute.name == "normal" ) vertexAttributeNormal = attribute;
|
||||
else if ( attribute.name == "color" ) vertexAttributeColor = attribute;
|
||||
else if ( attribute.name == "uv" ) vertexAttributeUv = attribute;
|
||||
else if ( attribute.name == "st" ) vertexAttributeSt = attribute;
|
||||
else if ( attribute.name == "id" ) vertexAttributeId = attribute;
|
||||
}
|
||||
if ( vertexAttributePosition.name == "" ) return;
|
||||
|
||||
if ( drawInfo.descriptor.cullMode == GL_NONE ) {
|
||||
GL_ERROR_CHECK(glDisable(GL_CULL_FACE));
|
||||
} else {
|
||||
GL_ERROR_CHECK(glEnable(GL_CULL_FACE));
|
||||
GL_ERROR_CHECK(glFrontFace(drawInfo.descriptor.frontFace));
|
||||
GL_ERROR_CHECK(glCullFace(drawInfo.descriptor.cullMode));
|
||||
}
|
||||
if ( drawInfo.descriptor.depth.test ) {
|
||||
GL_ERROR_CHECK(glEnable(GL_DEPTH_TEST));
|
||||
} else {
|
||||
GL_ERROR_CHECK(glDisable(GL_DEPTH_TEST));
|
||||
}
|
||||
GL_ERROR_CHECK(glDepthMask(drawInfo.descriptor.depth.write ? GL_TRUE : GL_FALSE));
|
||||
|
||||
// GPU-buffer based command dispatching
|
||||
#if !UF_USE_OPENGL_FIXED_FUNCTION
|
||||
|
||||
#else
|
||||
// CPU-buffer based command dispatching
|
||||
uint8_t* vertexPointer = (uint8_t*) ( device->getBuffer( vertexBuffer.buffer ) + vertexBuffer.offset );
|
||||
|
||||
// vertices do not need to be transformed
|
||||
//if ( vertexAttributeId.name == "" )
|
||||
#if !UF_USE_OPENGL_IMMEDIATE_MODE
|
||||
if ( vertexAttributeNormal.name != "" ) GL_ERROR_CHECK(glEnableClientState(GL_NORMAL_ARRAY));
|
||||
if ( vertexAttributeColor.name != "" )GL_ERROR_CHECK(glEnableClientState(GL_COLOR_ARRAY));
|
||||
if ( vertexAttributeUv.name != "" ) GL_ERROR_CHECK(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
|
||||
GL_ERROR_CHECK(glEnableClientState(GL_VERTEX_ARRAY));
|
||||
|
||||
|
||||
// no ID attribute found, fallback
|
||||
if ( vertexAttributeId.name == "" ) {
|
||||
if ( !textureInfos.empty() ) {
|
||||
InfoTexture* info = textureInfos.front();
|
||||
GL_ERROR_CHECK(glEnable(info->descriptor.viewType));
|
||||
GL_ERROR_CHECK(glBindTexture(info->descriptor.viewType, info->descriptor.image));
|
||||
}
|
||||
GL_BIND_POINTERS();
|
||||
GL_ERROR_CHECK(glDrawArrays(GL_TRIANGLES, 0, vertices));
|
||||
} else {
|
||||
if ( textureInfos.empty() ) {
|
||||
GL_BIND_POINTERS();
|
||||
GL_ERROR_CHECK(glDrawArrays(GL_TRIANGLES, 0, vertices));
|
||||
} else if ( textureInfos.size() == 1 ) {
|
||||
InfoTexture* info = textureInfos.front();
|
||||
GL_ERROR_CHECK(glEnable(info->descriptor.viewType));
|
||||
GL_ERROR_CHECK(glBindTexture(info->descriptor.viewType, info->descriptor.image));
|
||||
GL_BIND_POINTERS();
|
||||
GL_ERROR_CHECK(glDrawArrays(GL_TRIANGLES, 0, vertices));
|
||||
} else {
|
||||
uf::stl::vector<uf::stl::vector<uf::renderer::index_t>> sorted( textureInfos.size() );
|
||||
for ( uf::renderer::index_t index = 0; index < vertices; ++index ) {
|
||||
uint8_t* vertex = vertexPointer + (index * vertexStride);
|
||||
|
||||
const pod::Vector<uf::graph::id_t,2>& id = *((pod::Vector<uf::graph::id_t,2>*) (vertex + vertexAttributeId.offset));
|
||||
size_t textureId = id.y;
|
||||
if ( textureInfos.size() < textureId ) continue;
|
||||
sorted[textureId].emplace_back(index);
|
||||
}
|
||||
GLenum indicesType = GL_UNSIGNED_INT;
|
||||
switch ( sizeof(uf::renderer::index_t) ) {
|
||||
case sizeof(uint32_t): indicesType = GL_UNSIGNED_INT; break;
|
||||
case sizeof(uint16_t): indicesType = GL_UNSIGNED_SHORT; break;
|
||||
case sizeof(uint8_t): indicesType = GL_UNSIGNED_BYTE; break;
|
||||
}
|
||||
for ( size_t textureId = 0; textureId < sorted.size(); ++textureId ) {
|
||||
auto& indices = sorted[textureId];
|
||||
if ( indices.empty() ) continue;
|
||||
InfoTexture* info = textureInfos[textureId];
|
||||
GL_ERROR_CHECK(glEnable(info->descriptor.viewType));
|
||||
GL_ERROR_CHECK(glBindTexture(info->descriptor.viewType, info->descriptor.image));
|
||||
GL_BIND_POINTERS();
|
||||
GL_ERROR_CHECK(glDrawElements(GL_TRIANGLES, indices.size(), indicesType, &indices[0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( vertexAttributeNormal.name != "" ) GL_ERROR_CHECK(glDisableClientState(GL_NORMAL_ARRAY));
|
||||
if ( vertexAttributeColor.name != "" ) GL_ERROR_CHECK(glDisableClientState(GL_COLOR_ARRAY));
|
||||
if ( vertexAttributeUv.name != "" ) GL_ERROR_CHECK(glDisableClientState(GL_TEXTURE_COORD_ARRAY));
|
||||
GL_ERROR_CHECK(glDisableClientState(GL_VERTEX_ARRAY));
|
||||
#else
|
||||
// no ID attribute found, fallback
|
||||
if ( vertexAttributeId.name == "" ) {
|
||||
if ( !textureInfos.empty() ) {
|
||||
InfoTexture* info = textureInfos.front();
|
||||
GL_ERROR_CHECK(glEnable(info->descriptor.viewType));
|
||||
GL_ERROR_CHECK(glBindTexture(info->descriptor.viewType, info->descriptor.image));
|
||||
}
|
||||
GL_DRAW_ARRAYS( vertexPointer, vertices );
|
||||
} else {
|
||||
if ( textureInfos.empty() ) {
|
||||
GL_DRAW_ARRAYS( vertexPointer, vertices );
|
||||
} else if ( textureInfos.size() == 1 ) {
|
||||
InfoTexture* info = textureInfos.front();
|
||||
GL_ERROR_CHECK(glEnable(info->descriptor.viewType));
|
||||
GL_ERROR_CHECK(glBindTexture(info->descriptor.viewType, info->descriptor.image));
|
||||
GL_DRAW_ARRAYS( vertexPointer, vertices );
|
||||
} else {
|
||||
uf::stl::vector<uf::stl::vector<uf::renderer::index_t>> sorted( textureInfos.size() );
|
||||
for ( uf::renderer::index_t index = 0; index < vertices; ++index ) {
|
||||
uint8_t* vertex = vertexPointer + (index * vertexStride);
|
||||
|
||||
const pod::Vector<uf::graph::id_t,2>& id = *((pod::Vector<uf::graph::id_t,2>*) (vertex + vertexAttributeId.offset));
|
||||
size_t textureId = id.y;
|
||||
if ( textureInfos.size() < textureId ) continue;
|
||||
sorted[textureId].emplace_back(index);
|
||||
}
|
||||
for ( size_t textureId = 0; textureId < sorted.size(); ++textureId ) {
|
||||
auto& indices = sorted[textureId];
|
||||
if ( indices.empty() ) continue;
|
||||
InfoTexture* info = textureInfos[textureId];
|
||||
GL_ERROR_CHECK(glEnable(info->descriptor.viewType));
|
||||
GL_ERROR_CHECK(glBindTexture(info->descriptor.viewType, info->descriptor.image));
|
||||
GL_DRAW_ELEMENTS( (&indices[0]) , (indices.size()) );
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer::InfoDraw& drawInfo ) {
|
||||
auto projectionViewMatrix = bindUniform( drawInfo.uniformBuffer );
|
||||
|
||||
@ -601,7 +308,8 @@ void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer::
|
||||
GL_ERROR_CHECK(glVertexPointer(3, GL_FLOAT, vertexStride, vertexPointer + drawInfo.attributes.position));
|
||||
|
||||
// frustrum culling
|
||||
if ( ext::opengl::settings::experimental::frustrumCull ) {
|
||||
#if 0
|
||||
if ( ext::opengl::settings::experimental::culling ) {
|
||||
uf::stl::vector<uf::renderer::index_t> unculled;
|
||||
unculled.reserve(indices);
|
||||
for ( size_t currentIndex = 0; currentIndex < indices; currentIndex += 3 ) {
|
||||
@ -641,6 +349,9 @@ void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer::
|
||||
} else {
|
||||
GL_ERROR_CHECK(glDrawElements(GL_TRIANGLES, indices, indicesType, indicesPointer));
|
||||
}
|
||||
#else
|
||||
GL_ERROR_CHECK(glDrawElements(GL_TRIANGLES, indices, indicesType, indicesPointer));
|
||||
#endif
|
||||
|
||||
if ( drawInfo.auxTexture.image ) {
|
||||
#if UF_ENV_DREAMCAST
|
||||
|
||||
@ -38,9 +38,9 @@ bool ext::opengl::settings::experimental::deferredAliasOutputToSwapchain = true;
|
||||
bool ext::opengl::settings::experimental::multiview = true;
|
||||
bool ext::opengl::settings::experimental::vsync = true;
|
||||
bool ext::opengl::settings::experimental::hdr = true;
|
||||
bool ext::opengl::settings::experimental::frustrumCull = false;
|
||||
bool ext::opengl::settings::experimental::vxgi = true;
|
||||
bool ext::opengl::settings::experimental::deferredSampling = true;
|
||||
bool ext::opengl::settings::experimental::culling = false;
|
||||
|
||||
GLhandle(VkColorSpaceKHR) ext::opengl::settings::formats::colorSpace;
|
||||
ext::opengl::enums::Format::type_t ext::opengl::settings::formats::color = ext::opengl::enums::Format::R8G8B8A8_UNORM;
|
||||
@ -171,7 +171,7 @@ void UF_API ext::opengl::initialize() {
|
||||
// bind shaders
|
||||
#if !UF_ENV_DREAMCAST
|
||||
{
|
||||
ext::opengl::Shader::bind( uf::io::root + "shaders/gltf/instanced.vert.spv", [](const ext::opengl::Shader& shader, const ext::opengl::Graphic& graphic, void* userdata) {
|
||||
ext::opengl::Shader::bind( uf::io::root + "shaders/graph/instanced.vert.spv", [](const ext::opengl::Shader& shader, const ext::opengl::Graphic& graphic, void* userdata) {
|
||||
if ( !userdata ) return;
|
||||
uint8_t* verticesSrc = (uint8_t*) userdata;
|
||||
|
||||
@ -240,7 +240,7 @@ void UF_API ext::opengl::initialize() {
|
||||
}
|
||||
}
|
||||
});
|
||||
ext::opengl::Shader::bind( uf::io::root + "shaders/gltf/skinned.vert.spv", [](const ext::opengl::Shader& shader, const ext::opengl::Graphic& graphic, void* userdata) {
|
||||
ext::opengl::Shader::bind( uf::io::root + "shaders/graph/skinned.vert.spv", [](const ext::opengl::Shader& shader, const ext::opengl::Graphic& graphic, void* userdata) {
|
||||
if ( !userdata ) return;
|
||||
uint8_t* verticesSrc = (uint8_t*) userdata;
|
||||
|
||||
|
||||
@ -55,31 +55,14 @@ void ext::vulkan::Buffer::copyTo( void* data, VkDeviceSize size ) {
|
||||
}
|
||||
|
||||
VkResult ext::vulkan::Buffer::flush( VkDeviceSize size, VkDeviceSize offset ) const {
|
||||
/*
|
||||
VkMappedMemoryRange mappedRange = {};
|
||||
mappedRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
|
||||
mappedRange.memory = memory;
|
||||
mappedRange.offset = offset;
|
||||
mappedRange.size = size;
|
||||
return vkFlushMappedMemoryRanges(device, 1, &mappedRange);
|
||||
*/
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult ext::vulkan::Buffer::invalidate( VkDeviceSize size, VkDeviceSize offset ) {
|
||||
/*
|
||||
VkMappedMemoryRange mappedRange = {};
|
||||
mappedRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
|
||||
mappedRange.memory = memory;
|
||||
mappedRange.offset = offset;
|
||||
mappedRange.size = size;
|
||||
return vkInvalidateMappedMemoryRanges(device, 1, &mappedRange);
|
||||
*/
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void ext::vulkan::Buffer::allocate( VkBufferCreateInfo bufferCreateInfo ) {
|
||||
// VK_CHECK_RESULT(vkCreateBuffer( device, &bufferCreateInfo, nullptr, &buffer));
|
||||
VmaAllocationCreateInfo allocCreateInfo = {};
|
||||
|
||||
allocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
|
||||
@ -89,10 +72,6 @@ void ext::vulkan::Buffer::allocate( VkBufferCreateInfo bufferCreateInfo ) {
|
||||
}
|
||||
|
||||
vmaCreateBuffer( allocator, &bufferCreateInfo, &allocCreateInfo, &buffer, &allocation, &allocationInfo );
|
||||
// VkMemoryPropertyFlags memFlags;
|
||||
// vmaGetMemoryTypeProperties(allocator, allocationInfo.memoryType, &memFlags);
|
||||
// memory = allocationInfo.deviceMemory;
|
||||
// size = allocationInfo.size;
|
||||
}
|
||||
|
||||
// RAII
|
||||
@ -107,14 +86,13 @@ void ext::vulkan::Buffer::destroy() {
|
||||
|
||||
if ( buffer ) {
|
||||
vmaDestroyBuffer( allocator, buffer, allocation );
|
||||
// vkDestroyBuffer(device, buffer, nullptr);
|
||||
}
|
||||
// if ( memory ) vkFreeMemory(device, memory, nullptr);
|
||||
|
||||
buffer = nullptr;
|
||||
memory = nullptr;
|
||||
}
|
||||
void ext::vulkan::Buffer::initialize( const void* data, VkDeviceSize length, VkBufferUsageFlags usage, VkMemoryPropertyFlags memoryProperties, bool stage ) {
|
||||
if ( !device ) device = &ext::vulkan::device;
|
||||
if ( stage ) usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; // implicitly set properties
|
||||
VK_CHECK_RESULT(device->createBuffer(
|
||||
usage,
|
||||
@ -122,9 +100,11 @@ void ext::vulkan::Buffer::initialize( const void* data, VkDeviceSize length, VkB
|
||||
*this,
|
||||
length
|
||||
));
|
||||
if ( data ) update( data, length, stage );
|
||||
if ( data && length ) update( data, length, stage );
|
||||
}
|
||||
void ext::vulkan::Buffer::update( const void* data, VkDeviceSize length, bool stage ) const {
|
||||
if ( !data || !length ) return;
|
||||
|
||||
if ( length > allocationInfo.size ) {
|
||||
UF_MSG_DEBUG("LENGTH OF " << length << " EXCEEDS BUFFER SIZE " << allocationInfo.size );
|
||||
Buffer& b = *const_cast<Buffer*>(this);
|
||||
@ -141,6 +121,8 @@ void ext::vulkan::Buffer::update( const void* data, VkDeviceSize length, bool st
|
||||
}
|
||||
|
||||
Buffer staging;
|
||||
|
||||
ext::vulkan::Device* device = this->device ? this->device : &ext::vulkan::device;
|
||||
device->createBuffer(
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include <uf/ext/vulkan/vulkan.h>
|
||||
#include <uf/ext/openvr/openvr.h>
|
||||
#include <uf/utils/camera/camera.h>
|
||||
#include <uf/engine/graph/graph.h>
|
||||
|
||||
#include <spirv_cross/spirv_cross.hpp>
|
||||
#include <spirv_cross/spirv_glsl.hpp>
|
||||
@ -42,15 +43,16 @@ void ext::vulkan::Pipeline::initialize( const Graphic& graphic, const GraphicDes
|
||||
|
||||
uf::stl::vector<VkPipelineColorBlendAttachmentState> blendAttachmentStates;
|
||||
uf::stl::vector<VkPipelineShaderStageCreateInfo> shaderDescriptors;
|
||||
uf::stl::vector<VkSpecializationInfo> shaderSpecializationInfos;
|
||||
uf::stl::vector<VkVertexInputBindingDescription> inputBindingDescriptions;
|
||||
uf::stl::vector<VkVertexInputAttributeDescription> attributeDescriptions;
|
||||
{
|
||||
|
||||
for ( auto* shaderPointer : shaders ) {
|
||||
auto& shader = *shaderPointer;
|
||||
descriptorSetLayoutBindings.insert( descriptorSetLayoutBindings.begin(), shader.descriptorSetLayoutBindings.begin(), shader.descriptorSetLayoutBindings.end() );
|
||||
descriptorSetLayoutBindings.insert( descriptorSetLayoutBindings.end(), shader.descriptorSetLayoutBindings.begin(), shader.descriptorSetLayoutBindings.end() );
|
||||
|
||||
std::size_t offset = 0;
|
||||
size_t offset = 0;
|
||||
for ( auto& pushConstant : shader.pushConstants ) {
|
||||
size_t len = pushConstant.data().len;
|
||||
if ( len <= 0 || len > device.properties.limits.maxPushConstantsSize ) {
|
||||
@ -186,6 +188,15 @@ void ext::vulkan::Pipeline::initialize( const Graphic& graphic, const GraphicDes
|
||||
descriptor.depth.write,
|
||||
descriptor.depth.operation
|
||||
);
|
||||
if ( uf::matrix::reverseInfiniteProjection ) {
|
||||
depthStencilState.depthCompareOp = ext::vulkan::enums::Compare::GREATER_OR_EQUAL;
|
||||
depthStencilState.minDepthBounds = 1.0f;
|
||||
depthStencilState.maxDepthBounds = 0.0f;
|
||||
} else {
|
||||
depthStencilState.depthCompareOp = ext::vulkan::enums::Compare::LESS;
|
||||
depthStencilState.minDepthBounds = 0.0f;
|
||||
depthStencilState.maxDepthBounds = 1.0f;
|
||||
}
|
||||
VkPipelineViewportStateCreateInfo viewportState = ext::vulkan::initializers::pipelineViewportStateCreateInfo(
|
||||
1, 1, 0
|
||||
);
|
||||
@ -250,7 +261,38 @@ void ext::vulkan::Pipeline::initialize( const Graphic& graphic, const GraphicDes
|
||||
vertexInputState.vertexAttributeDescriptionCount = attributeDescriptions.size();
|
||||
vertexInputState.pVertexAttributeDescriptions = attributeDescriptions.data();
|
||||
|
||||
#if 0
|
||||
for ( auto* SHADER : shaders ) {
|
||||
ext::vulkan::Shader* shader = const_cast<ext::vulkan::Shader*>(SHADER);
|
||||
void* s = (void*) shader->specializationConstants;
|
||||
size_t len = shader->specializationConstants.data().len;
|
||||
bool invalidated = true;
|
||||
for ( auto pair : shader->metadata.definitions.specializationConstants ) {
|
||||
auto& name = pair.first;
|
||||
auto& payload = pair.second;
|
||||
uf::stl::string type = payload.type;
|
||||
if ( type == "int32_t" ) {
|
||||
int32_t& v = ((int32_t*) s)[payload.index];
|
||||
UF_MSG_DEBUG("SC " << payload.name << " = " << v << " = " << payload.value.i << "`" << shader->filename << "`");
|
||||
if ( payload.validate && v != payload.value.i ) v = payload.value.i;
|
||||
payload.value.i = v;
|
||||
} else if ( type == "uint32_t" ) {
|
||||
uint32_t& v = ((uint32_t*) s)[payload.index];
|
||||
UF_MSG_DEBUG("SC " << payload.name << " = " << v << " = " << payload.value.ui << "`" << shader->filename << "`");
|
||||
if ( payload.validate && v != payload.value.ui ) v = payload.value.ui;
|
||||
payload.value.ui = v;
|
||||
} else if ( type == "float" ) {
|
||||
float& v = ((float*) s)[payload.index];
|
||||
UF_MSG_DEBUG("SC " << payload.name << " = " << v << " = " << payload.value.f << "`" << shader->filename << "`");
|
||||
if ( payload.validate && v != payload.value.f ) v = payload.value.f;
|
||||
payload.value.f = v;
|
||||
}
|
||||
}
|
||||
shaderDescriptors.push_back(shader->descriptor);
|
||||
}
|
||||
#else
|
||||
for ( auto* shader : shaders ) shaderDescriptors.emplace_back(shader->descriptor);
|
||||
#endif
|
||||
|
||||
VkGraphicsPipelineCreateInfo pipelineCreateInfo = ext::vulkan::initializers::pipelineCreateInfo(
|
||||
pipelineLayout,
|
||||
@ -287,15 +329,15 @@ void ext::vulkan::Pipeline::record( const Graphic& graphic, VkCommandBuffer comm
|
||||
auto shaders = getShaders( graphic.material.shaders );
|
||||
for ( auto* shader : shaders ) {
|
||||
if ( shader->descriptor.stage == VK_SHADER_STAGE_COMPUTE_BIT ) bindPoint = VK_PIPELINE_BIND_POINT_COMPUTE;
|
||||
#if 0
|
||||
#if 1
|
||||
if ( shader->metadata.definitions.pushConstants.count("PushConstant") > 0 ) {
|
||||
if ( shader->descriptor.stage == VK_SHADER_STAGE_VERTEX_BIT ) {
|
||||
struct PushConstant {
|
||||
uint32_t pass;
|
||||
uint32_t draw;
|
||||
} pushConstant = { pass, draw };
|
||||
( commandBuffer, pipelineLayout, shader->descriptor.stage, 0, sizeof(pushConstant), &pushConstant );
|
||||
}
|
||||
if ( shader->descriptor.stage == VK_SHADER_STAGE_VERTEX_BIT || shader->descriptor.stage == VK_SHADER_STAGE_COMPUTE_BIT ) {
|
||||
struct PushConstant {
|
||||
uint32_t pass;
|
||||
uint32_t draw;
|
||||
} pushConstant = { pass, draw };
|
||||
vkCmdPushConstants( commandBuffer, pipelineLayout, shader->descriptor.stage, 0, sizeof(pushConstant), &pushConstant );
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if ( !shader->pushConstants.empty() ) {
|
||||
@ -332,6 +374,10 @@ void ext::vulkan::Pipeline::record( const Graphic& graphic, VkCommandBuffer comm
|
||||
// Bind the rendering pipeline
|
||||
// The pipeline (state object) contains all states of the rendering pipeline, binding it will set all the states specified at pipeline creation time
|
||||
vkCmdBindPipeline(commandBuffer, bindPoint, pipeline);
|
||||
|
||||
if ( bindPoint == VK_PIPELINE_BIND_POINT_COMPUTE && descriptor.inputs.dispatch.x != 0 && descriptor.inputs.dispatch.y != 0 && descriptor.inputs.dispatch.z != 0 ) {
|
||||
vkCmdDispatch(commandBuffer, descriptor.inputs.dispatch.x, descriptor.inputs.dispatch.y, descriptor.inputs.dispatch.z);
|
||||
}
|
||||
}
|
||||
void ext::vulkan::Pipeline::update( const Graphic& graphic ) {
|
||||
return this->update( graphic, descriptor );
|
||||
@ -348,7 +394,7 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
|
||||
auto shaders = getShaders( graphic.material.shaders );
|
||||
uf::stl::vector<VkWriteDescriptorSet> writeDescriptorSets;
|
||||
|
||||
struct {
|
||||
struct Infos {
|
||||
uf::stl::vector<VkDescriptorBufferInfo> uniform;
|
||||
uf::stl::vector<VkDescriptorBufferInfo> storage;
|
||||
|
||||
@ -360,35 +406,38 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
|
||||
|
||||
uf::stl::vector<VkDescriptorImageInfo> sampler;
|
||||
uf::stl::vector<VkDescriptorImageInfo> input;
|
||||
} infos;
|
||||
};
|
||||
uf::stl::vector<Infos> INFOS; INFOS.reserve( shaders.size() );
|
||||
|
||||
uf::stl::vector<ext::vulkan::enums::Image::viewType_t> types;
|
||||
|
||||
if ( descriptor.subpass < renderTarget.passes.size() ) {
|
||||
auto& subpass = renderTarget.passes[descriptor.subpass];
|
||||
for ( auto& input : subpass.inputs ) {
|
||||
infos.input.emplace_back(ext::vulkan::initializers::descriptorImageInfo(
|
||||
renderTarget.attachments[input.attachment].views[subpass.layer],
|
||||
input.layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : input.layout
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
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_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);
|
||||
}
|
||||
|
||||
size_t consumes = 0;
|
||||
for ( auto* shader : shaders ) {
|
||||
auto& infos = INFOS.emplace_back();
|
||||
|
||||
uf::stl::vector<ext::vulkan::enums::Image::viewType_t> types;
|
||||
|
||||
if ( descriptor.subpass < renderTarget.passes.size() ) {
|
||||
auto& subpass = renderTarget.passes[descriptor.subpass];
|
||||
for ( auto& input : subpass.inputs ) {
|
||||
infos.input.emplace_back(ext::vulkan::initializers::descriptorImageInfo(
|
||||
renderTarget.attachments[input.attachment].views[subpass.layer],
|
||||
input.layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : input.layout
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
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_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);
|
||||
}
|
||||
|
||||
size_t consumes = 0;
|
||||
for ( auto& buffer : shader->buffers ) {
|
||||
if ( buffer.usage & uf::renderer::enums::Buffer::UNIFORM ) infos.uniform.emplace_back(buffer.descriptor);
|
||||
if ( buffer.usage & uf::renderer::enums::Buffer::STORAGE ) infos.storage.emplace_back(buffer.descriptor);
|
||||
@ -408,45 +457,43 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t maxTextures2D = 0;
|
||||
size_t maxTextures3D = 0;
|
||||
size_t maxTexturesCube = 0;
|
||||
size_t maxTexturesUnknown = 0;
|
||||
for ( auto& type : types ) {
|
||||
if ( type == ext::vulkan::enums::Image::VIEW_TYPE_3D ) ++maxTextures3D;
|
||||
else if ( type == ext::vulkan::enums::Image::VIEW_TYPE_CUBE ) ++maxTexturesCube;
|
||||
else if ( type == ext::vulkan::enums::Image::VIEW_TYPE_2D ) ++maxTextures2D;
|
||||
else ++maxTexturesUnknown;
|
||||
}
|
||||
|
||||
size_t maxTextures2D = 0;
|
||||
size_t maxTextures3D = 0;
|
||||
size_t maxTexturesCube = 0;
|
||||
size_t maxTexturesUnknown = 0;
|
||||
for ( auto& type : types ) {
|
||||
if ( type == ext::vulkan::enums::Image::VIEW_TYPE_3D ) ++maxTextures3D;
|
||||
else if ( type == ext::vulkan::enums::Image::VIEW_TYPE_CUBE ) ++maxTexturesCube;
|
||||
else if ( type == ext::vulkan::enums::Image::VIEW_TYPE_2D ) ++maxTextures2D;
|
||||
else ++maxTexturesUnknown;
|
||||
}
|
||||
|
||||
while ( infos.image2D.size() < maxTextures2D ) infos.image2D.emplace_back(Texture2D::empty.descriptor);
|
||||
while ( infos.imageCube.size() < maxTexturesCube ) infos.imageCube.emplace_back(TextureCube::empty.descriptor);
|
||||
while ( infos.image3D.size() < maxTextures3D ) infos.image3D.emplace_back(Texture3D::empty.descriptor);
|
||||
while ( infos.imageUnknown.size() < maxTexturesUnknown ) infos.imageUnknown.emplace_back(Texture2D::empty.descriptor);
|
||||
while ( infos.image2D.size() < maxTextures2D ) infos.image2D.emplace_back(Texture2D::empty.descriptor);
|
||||
while ( infos.imageCube.size() < maxTexturesCube ) infos.imageCube.emplace_back(TextureCube::empty.descriptor);
|
||||
while ( infos.image3D.size() < maxTextures3D ) infos.image3D.emplace_back(Texture3D::empty.descriptor);
|
||||
while ( infos.imageUnknown.size() < maxTexturesUnknown ) infos.imageUnknown.emplace_back(Texture2D::empty.descriptor);
|
||||
|
||||
for ( size_t i = infos.image.size(); i < consumes; ++i ) {
|
||||
ext::vulkan::enums::Image::viewType_t type = i < types.size() ? types[i] : ext::vulkan::enums::Image::viewType_t{};
|
||||
if ( type == ext::vulkan::enums::Image::VIEW_TYPE_3D ) infos.image.emplace_back(Texture3D::empty.descriptor);
|
||||
else if ( type == ext::vulkan::enums::Image::VIEW_TYPE_CUBE ) infos.image.emplace_back(TextureCube::empty.descriptor);
|
||||
else if ( type == ext::vulkan::enums::Image::VIEW_TYPE_2D ) infos.image.emplace_back(Texture2D::empty.descriptor);
|
||||
else infos.image.emplace_back(Texture2D::empty.descriptor);
|
||||
}
|
||||
|
||||
auto uniformBufferInfo = infos.uniform.begin();
|
||||
auto storageBufferInfo = infos.storage.begin();
|
||||
|
||||
auto imageInfo = infos.image.begin();
|
||||
auto image2DInfo = infos.image2D.begin();
|
||||
auto imageCubeInfo = infos.imageCube.begin();
|
||||
auto image3DInfo = infos.image3D.begin();
|
||||
auto imageUnknownInfo = infos.imageUnknown.begin();
|
||||
for ( size_t i = infos.image.size(); i < consumes; ++i ) {
|
||||
ext::vulkan::enums::Image::viewType_t type = i < types.size() ? types[i] : ext::vulkan::enums::Image::viewType_t{};
|
||||
if ( type == ext::vulkan::enums::Image::VIEW_TYPE_3D ) infos.image.emplace_back(Texture3D::empty.descriptor);
|
||||
else if ( type == ext::vulkan::enums::Image::VIEW_TYPE_CUBE ) infos.image.emplace_back(TextureCube::empty.descriptor);
|
||||
else if ( type == ext::vulkan::enums::Image::VIEW_TYPE_2D ) infos.image.emplace_back(Texture2D::empty.descriptor);
|
||||
else infos.image.emplace_back(Texture2D::empty.descriptor);
|
||||
}
|
||||
|
||||
auto uniformBufferInfo = infos.uniform.begin();
|
||||
auto storageBufferInfo = infos.storage.begin();
|
||||
|
||||
auto imageInfo = infos.image.begin();
|
||||
auto image2DInfo = infos.image2D.begin();
|
||||
auto imageCubeInfo = infos.imageCube.begin();
|
||||
auto image3DInfo = infos.image3D.begin();
|
||||
auto imageUnknownInfo = infos.imageUnknown.begin();
|
||||
|
||||
auto samplerInfo = infos.sampler.begin();
|
||||
auto inputInfo = infos.input.begin();
|
||||
auto samplerInfo = infos.sampler.begin();
|
||||
auto inputInfo = infos.input.begin();
|
||||
|
||||
for ( auto* shader : shaders ) {
|
||||
for ( auto& layout : shader->descriptorSetLayoutBindings ) {
|
||||
switch ( layout.descriptorType ) {
|
||||
// consume an texture image info
|
||||
@ -635,8 +682,14 @@ void ext::vulkan::Pipeline::destroy() {
|
||||
uf::stl::vector<ext::vulkan::Shader*> ext::vulkan::Pipeline::getShaders( uf::stl::vector<ext::vulkan::Shader>& shaders ) {
|
||||
uf::stl::unordered_map<uf::stl::string, ext::vulkan::Shader*> map;
|
||||
uf::stl::vector<ext::vulkan::Shader*> res;
|
||||
bool isCompute = false;
|
||||
for ( auto& shader : shaders ) {
|
||||
if ( shader.metadata.pipeline != "" && shader.metadata.pipeline != metadata.type ) continue;
|
||||
if ( shader.descriptor.stage == VK_SHADER_STAGE_COMPUTE_BIT ) isCompute = true;
|
||||
}
|
||||
for ( auto& shader : shaders ) {
|
||||
if ( shader.metadata.pipeline != "" && shader.metadata.pipeline != metadata.type ) continue;
|
||||
if ( isCompute && shader.descriptor.stage != VK_SHADER_STAGE_COMPUTE_BIT ) continue;
|
||||
map[shader.metadata.type] = &shader;
|
||||
}
|
||||
for ( auto pair : map ) res.insert( res.begin(), pair.second);
|
||||
@ -645,8 +698,14 @@ uf::stl::vector<ext::vulkan::Shader*> ext::vulkan::Pipeline::getShaders( uf::stl
|
||||
uf::stl::vector<const ext::vulkan::Shader*> ext::vulkan::Pipeline::getShaders( const uf::stl::vector<ext::vulkan::Shader>& shaders ) const {
|
||||
uf::stl::unordered_map<uf::stl::string, const ext::vulkan::Shader*> map;
|
||||
uf::stl::vector<const ext::vulkan::Shader*> res;
|
||||
bool isCompute = false;
|
||||
for ( auto& shader : shaders ) {
|
||||
if ( shader.metadata.pipeline != "" && shader.metadata.pipeline != metadata.type ) continue;
|
||||
if ( shader.descriptor.stage == VK_SHADER_STAGE_COMPUTE_BIT ) isCompute = true;
|
||||
}
|
||||
for ( auto& shader : shaders ) {
|
||||
if ( shader.metadata.pipeline != "" && shader.metadata.pipeline != metadata.type ) continue;
|
||||
if ( isCompute && shader.descriptor.stage != VK_SHADER_STAGE_COMPUTE_BIT ) continue;
|
||||
map[shader.metadata.type] = &shader;
|
||||
}
|
||||
for ( auto pair : map ) res.insert( res.begin(), pair.second);
|
||||
@ -668,9 +727,12 @@ void ext::vulkan::Material::destroy() {
|
||||
}
|
||||
void ext::vulkan::Material::attachShader( const uf::stl::string& filename, VkShaderStageFlagBits stage, const uf::stl::string& pipeline ) {
|
||||
auto& shader = shaders.emplace_back();
|
||||
shader.metadata.json = metadata.json["shader"];
|
||||
shader.metadata.autoInitializeUniforms = metadata.autoInitializeUniforms;
|
||||
shader.initialize( *device, filename, stage );
|
||||
|
||||
// repoint our specialization info descriptor because our shaders will change memory locations when attaching one by one
|
||||
|
||||
for ( auto& shader : shaders ) {
|
||||
shader.specializationInfo.mapEntryCount = shader.specializationMapEntries.size();
|
||||
shader.specializationInfo.pMapEntries = shader.specializationMapEntries.data();
|
||||
@ -755,7 +817,6 @@ ext::vulkan::Pipeline& ext::vulkan::Graphic::initializePipeline( const GraphicDe
|
||||
pipeline.initialize(*this, descriptor);
|
||||
pipeline.update(*this, descriptor);
|
||||
|
||||
// process = true;
|
||||
initialized = true;
|
||||
material.validate();
|
||||
|
||||
@ -763,9 +824,9 @@ ext::vulkan::Pipeline& ext::vulkan::Graphic::initializePipeline( const GraphicDe
|
||||
}
|
||||
void ext::vulkan::Graphic::initializeMesh( uf::Mesh& mesh, bool buffer ) {
|
||||
// generate indices if not found
|
||||
if ( mesh.index.count == 0 ) mesh.generateIndices();
|
||||
// if ( mesh.index.count == 0 ) mesh.generateIndices();
|
||||
// generate indirect data if not found
|
||||
if ( mesh.indirect.count == 0 ) mesh.generateIndirect();
|
||||
// if ( mesh.indirect.count == 0 ) mesh.generateIndirect();
|
||||
// ensure our descriptors are proper
|
||||
mesh.updateDescriptor();
|
||||
|
||||
@ -776,12 +837,12 @@ void ext::vulkan::Graphic::initializeMesh( uf::Mesh& mesh, bool buffer ) {
|
||||
descriptor.inputs.indirect = mesh.indirect;
|
||||
|
||||
// create buffer if not set and requested
|
||||
if ( !initialized && buffer ) {
|
||||
if ( buffer ) {
|
||||
// ensures each buffer index reflects nicely
|
||||
struct Queue {
|
||||
void* data;
|
||||
size_t size;
|
||||
uf::renderer::enums::Buffer::type_t usage;
|
||||
VkBufferUsageFlags usage;
|
||||
};
|
||||
uf::stl::vector<Queue> queue;
|
||||
descriptor.inputs.bufferOffset = buffers.empty() ? 0 : buffers.size() - 1;
|
||||
@ -799,10 +860,11 @@ void ext::vulkan::Graphic::initializeMesh( uf::Mesh& mesh, bool buffer ) {
|
||||
PARSE_INPUT(vertex, uf::renderer::enums::Buffer::VERTEX)
|
||||
PARSE_INPUT(index, uf::renderer::enums::Buffer::INDEX)
|
||||
PARSE_INPUT(instance, uf::renderer::enums::Buffer::VERTEX)
|
||||
PARSE_INPUT(indirect, uf::renderer::enums::Buffer::INDIRECT)
|
||||
PARSE_INPUT(indirect, uf::renderer::enums::Buffer::INDIRECT | uf::renderer::enums::Buffer::STORAGE)
|
||||
|
||||
// allocate buffers
|
||||
for ( auto& q : queue ) {
|
||||
for ( auto i = 0; i < queue.size(); ++i ) {
|
||||
auto& q = queue[i];
|
||||
initializeBuffer( q.data, q.size, q.usage );
|
||||
}
|
||||
}
|
||||
@ -811,6 +873,54 @@ void ext::vulkan::Graphic::initializeMesh( uf::Mesh& mesh, bool buffer ) {
|
||||
descriptor.inputs.instance.count = 1;
|
||||
}
|
||||
}
|
||||
void ext::vulkan::Graphic::updateMesh( uf::Mesh& mesh ) {
|
||||
// generate indices if not found
|
||||
// if ( mesh.index.count == 0 ) mesh.generateIndices();
|
||||
// generate indirect data if not found
|
||||
// if ( mesh.indirect.count == 0 ) mesh.generateIndirect();
|
||||
// ensure our descriptors are proper
|
||||
mesh.updateDescriptor();
|
||||
|
||||
// copy descriptors
|
||||
descriptor.inputs.vertex = mesh.vertex;
|
||||
descriptor.inputs.index = mesh.index;
|
||||
descriptor.inputs.instance = mesh.instance;
|
||||
descriptor.inputs.indirect = mesh.indirect;
|
||||
|
||||
// create buffer if not set and requested
|
||||
// ensures each buffer index reflects nicely
|
||||
struct Queue {
|
||||
void* data;
|
||||
size_t size;
|
||||
uf::renderer::enums::Buffer::type_t usage;
|
||||
};
|
||||
uf::stl::vector<Queue> queue;
|
||||
|
||||
#define PARSE_ATTRIBUTE(i, usage) {\
|
||||
auto& buffer = mesh.buffers[i];\
|
||||
if ( queue.size() <= i ) queue.resize( i );\
|
||||
if ( !buffer.empty() ) queue.emplace_back(Queue{ (void*) buffer.data(), buffer.size(), usage });\
|
||||
}
|
||||
#define PARSE_INPUT(name, usage){\
|
||||
if ( mesh.isInterleaved( mesh.name.interleaved ) ) PARSE_ATTRIBUTE(descriptor.inputs.name.interleaved, usage)\
|
||||
else for ( auto& attribute : descriptor.inputs.name.attributes ) PARSE_ATTRIBUTE(attribute.buffer, usage)\
|
||||
}
|
||||
|
||||
PARSE_INPUT(vertex, uf::renderer::enums::Buffer::VERTEX)
|
||||
PARSE_INPUT(index, uf::renderer::enums::Buffer::INDEX)
|
||||
PARSE_INPUT(instance, uf::renderer::enums::Buffer::VERTEX)
|
||||
PARSE_INPUT(indirect, uf::renderer::enums::Buffer::INDIRECT)
|
||||
|
||||
// allocate buffers
|
||||
for ( auto i = 0; i < queue.size(); ++i ) {
|
||||
auto& q = queue[i];
|
||||
updateBuffer( q.data, q.size, descriptor.inputs.bufferOffset + i );
|
||||
}
|
||||
|
||||
if ( mesh.instance.count == 0 && mesh.instance.attributes.empty() ) {
|
||||
descriptor.inputs.instance.count = 1;
|
||||
}
|
||||
}
|
||||
bool ext::vulkan::Graphic::hasPipeline( const GraphicDescriptor& descriptor ) const {
|
||||
return pipelines.count( descriptor.hash() ) > 0;
|
||||
}
|
||||
@ -849,44 +959,8 @@ void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, const GraphicD
|
||||
if ( !pipeline.metadata.process ) return;
|
||||
pipeline.record(*this, commandBuffer, pass, draw);
|
||||
|
||||
/*
|
||||
struct VertexInstance {
|
||||
VkBuffer buffer;
|
||||
VkDeviceSize offset;
|
||||
};
|
||||
struct {
|
||||
struct {
|
||||
size_t min;
|
||||
size_t max;
|
||||
} binding;
|
||||
uf::stl::vector<VkBuffer> buffer;
|
||||
uf::stl::vector<VkDeviceSize> offset;
|
||||
} vertexInstance;
|
||||
|
||||
uf::stl::unordered_map<size_t, VertexInstance> vertexInstanceRemap;
|
||||
for ( auto& attribute : descriptor.inputs.vertex.attributes ) {
|
||||
vertexInstanceRemap[attribute.binding] = {
|
||||
.buffer = buffers.at(attribute.buffer).buffer,
|
||||
.offset = attribute.offset,
|
||||
};
|
||||
vertexInstance.binding.min = MIN(vertexInstance.binding.min, attribute.binding);
|
||||
vertexInstance.binding.max = MAX(vertexInstance.binding.max, attribute.binding);
|
||||
}
|
||||
for ( auto& attribute : descriptor.inputs.instance.attributes ) {
|
||||
vertexInstanceRemap[attribute.binding] = {
|
||||
.buffer = buffers.at(attribute.buffer).buffer,
|
||||
.offset = attribute.offset,
|
||||
};
|
||||
vertexInstance.binding.min = MIN(vertexInstance.binding.min, attribute.binding);
|
||||
vertexInstance.binding.max = MAX(vertexInstance.binding.max, attribute.binding);
|
||||
}
|
||||
vertexInstance.buffer.resize( vertexInstanceRemap.size() );
|
||||
vertexInstance.offset.resize( vertexInstanceRemap.size() );
|
||||
for ( auto i = vertexInstance.binding.min; i <= vertexInstance.binding.max; ++i ) {
|
||||
vertexInstance.buffer.emplace_back(vertexInstanceRemap[i].buffer);
|
||||
vertexInstance.offset.emplace_back(vertexInstanceRemap[i].offset);
|
||||
}
|
||||
*/
|
||||
auto shaders = pipeline.getShaders( material.shaders );
|
||||
for ( auto* shader : shaders ) if ( shader->descriptor.stage == VK_SHADER_STAGE_COMPUTE_BIT ) return;
|
||||
|
||||
struct {
|
||||
uf::stl::vector<VkBuffer> buffer;
|
||||
@ -918,6 +992,26 @@ void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, const GraphicD
|
||||
auto& attribute = descriptor.inputs.indirect.attributes.front();
|
||||
indirect.buffer = buffers.at((0 <= descriptor.inputs.indirect.interleaved ? descriptor.inputs.indirect.interleaved : attribute.buffer) + descriptor.inputs.bufferOffset).buffer;
|
||||
indirect.offset = 0 <= descriptor.inputs.indirect.interleaved ? descriptor.inputs.indirect.offset : attribute.offset;
|
||||
|
||||
/*
|
||||
.indices = indices.size(),
|
||||
.instances = 1,
|
||||
.indexID = mesh.index.count,
|
||||
.vertexID = mesh.vertex.count,
|
||||
|
||||
.instanceID = mesh.instance.count,
|
||||
.materialID = p.material,
|
||||
.objectID = 0,
|
||||
.vertices = vertices.size(),
|
||||
|
||||
if ( attribute.descriptor.pointer ) {
|
||||
pod::DrawCommand* drawCommands = (pod::DrawCommand*) attribute.descriptor.pointer;
|
||||
for ( auto i = 0; i < descriptor.inputs.indirect.count; ++i ) {
|
||||
auto& drawCommand = drawCommands[i];
|
||||
// UF_MSG_DEBUG( "DrawCommand[" << i << "]: " << drawCommand.indices << " " << drawCommand.instances << " " << drawCommand.indexID << " " << drawCommand.vertexID << " " << drawCommand.instanceID << " " << drawCommand.materialID << " " << drawCommand.objectID << " " << drawCommand.vertices );
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
for ( auto& buffer : buffers ) {
|
||||
@ -941,12 +1035,36 @@ void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, const GraphicD
|
||||
}
|
||||
vkCmdBindIndexBuffer(commandBuffer, index.buffer, index.offset, indicesType);
|
||||
}
|
||||
if ( index.buffer && indirect.buffer ) {
|
||||
vkCmdDrawIndexedIndirect(commandBuffer, indirect.buffer,
|
||||
descriptor.inputs.indirect.offset, // offset
|
||||
descriptor.inputs.indirect.count, // drawCount
|
||||
descriptor.inputs.indirect.stride // stride
|
||||
);
|
||||
const bool cpuSideIndirection = false;
|
||||
if ( index.buffer && indirect.buffer && cpuSideIndirection ) {
|
||||
auto& indirectAttribute = descriptor.inputs.indirect.attributes.front();
|
||||
const pod::DrawCommand* drawCommands = (const pod::DrawCommand*) indirectAttribute.pointer;
|
||||
for ( auto i = 0; i < descriptor.inputs.indirect.count; ++i ) {
|
||||
auto& drawCommand = drawCommands[i];
|
||||
vkCmdDrawIndexed(commandBuffer,
|
||||
drawCommand.indices, // indexCount
|
||||
drawCommand.instances, // instanceCount
|
||||
drawCommand.indexID, // firstIndex
|
||||
drawCommand.vertexID, // vertexOffset
|
||||
drawCommand.instanceID // firstInstance
|
||||
);
|
||||
}
|
||||
} else if ( index.buffer && indirect.buffer ) {
|
||||
if ( device->enabledFeatures.multiDrawIndirect || descriptor.inputs.indirect.count <= 1 ) {
|
||||
vkCmdDrawIndexedIndirect(commandBuffer, indirect.buffer,
|
||||
descriptor.inputs.indirect.offset, // offset
|
||||
descriptor.inputs.indirect.count, // drawCount
|
||||
descriptor.inputs.indirect.stride // stride
|
||||
);
|
||||
} else {
|
||||
for ( auto i = 0; i < descriptor.inputs.indirect.count; ++i ) {
|
||||
vkCmdDrawIndexedIndirect(commandBuffer, indirect.buffer,
|
||||
descriptor.inputs.indirect.offset + i * descriptor.inputs.indirect.stride, // offset
|
||||
1, // drawCount
|
||||
descriptor.inputs.indirect.stride // stride
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if ( index.buffer && !indirect.buffer ) {
|
||||
vkCmdDrawIndexed(commandBuffer,
|
||||
descriptor.inputs.index.count, // indexCount
|
||||
@ -1006,24 +1124,26 @@ ext::vulkan::GraphicDescriptor::hash_t ext::vulkan::GraphicDescriptor::hash() co
|
||||
hash += std::hash<decltype(renderMode)>{}(renderMode);
|
||||
|
||||
hash += std::hash<decltype(renderTarget)>{}(renderTarget);
|
||||
hash += std::hash<decltype(pipeline)>{}(pipeline);
|
||||
|
||||
/*
|
||||
hash += std::hash<decltype(vertex.attributes.size)>{}(vertex.attributes.size);
|
||||
hash += std::hash<decltype(vertex.attributes.length)>{}(vertex.attributes.length);
|
||||
hash += std::hash<decltype(index.attributes.size)>{}(index.attributes.size);
|
||||
hash += std::hash<decltype(index.attributes.length)>{}(index.attributes.length);
|
||||
hash += std::hash<decltype(instance.attributes.size)>{}(instance.attributes.size);
|
||||
hash += std::hash<decltype(instance.attributes.length)>{}(instance.attributes.length);
|
||||
*/
|
||||
|
||||
for ( uint8_t i = 0; i < inputs.vertex.attributes.size(); ++i ) {
|
||||
for ( auto i = 0; i < inputs.vertex.attributes.size(); ++i ) {
|
||||
hash += std::hash<decltype(inputs.vertex.attributes[i].descriptor.format)>{}(inputs.vertex.attributes[i].descriptor.format);
|
||||
hash += std::hash<decltype(inputs.vertex.attributes[i].descriptor.offset)>{}(inputs.vertex.attributes[i].descriptor.offset);
|
||||
}
|
||||
for ( uint8_t i = 0; i < inputs.index.attributes.size(); ++i ) {
|
||||
for ( auto i = 0; i < inputs.index.attributes.size(); ++i ) {
|
||||
hash += std::hash<decltype(inputs.index.attributes[i].descriptor.format)>{}(inputs.index.attributes[i].descriptor.format);
|
||||
hash += std::hash<decltype(inputs.index.attributes[i].descriptor.offset)>{}(inputs.index.attributes[i].descriptor.offset);
|
||||
}
|
||||
for ( auto i = 0; i < inputs.instance.attributes.size(); ++i ) {
|
||||
hash += std::hash<decltype(inputs.instance.attributes[i].descriptor.format)>{}(inputs.instance.attributes[i].descriptor.format);
|
||||
hash += std::hash<decltype(inputs.instance.attributes[i].descriptor.offset)>{}(inputs.instance.attributes[i].descriptor.offset);
|
||||
}
|
||||
/*
|
||||
for ( auto i = 0; i < inputs.indirect.attributes.size(); ++i ) {
|
||||
hash += std::hash<decltype(inputs.indirect.attributes[i].descriptor.format)>{}(inputs.indirect.attributes[i].descriptor.format);
|
||||
hash += std::hash<decltype(inputs.indirect.attributes[i].descriptor.offset)>{}(inputs.indirect.attributes[i].descriptor.offset);
|
||||
}
|
||||
*/
|
||||
|
||||
hash += std::hash<decltype(topology)>{}(topology);
|
||||
hash += std::hash<decltype(cullMode)>{}(cullMode);
|
||||
|
||||
@ -163,6 +163,7 @@ ext::vulkan::GraphicDescriptor ext::vulkan::RenderMode::bindGraphicDescriptor( c
|
||||
ext::vulkan::GraphicDescriptor descriptor = reference;
|
||||
// descriptor.renderMode = this->getName();
|
||||
descriptor.subpass = pass;
|
||||
descriptor.pipeline = metadata.pipeline;
|
||||
descriptor.parse( metadata.json["descriptor"] );
|
||||
return descriptor;
|
||||
}
|
||||
@ -177,7 +178,7 @@ void ext::vulkan::RenderMode::createCommandBuffers() {
|
||||
if ( !entity->hasComponent<uf::Graphic>() ) continue;
|
||||
ext::vulkan::Graphic& graphic = entity->getComponent<uf::Graphic>();
|
||||
if ( !graphic.initialized || !graphic.process ) continue;
|
||||
graphics.push_back(&graphic);
|
||||
graphics.emplace_back(&graphic);
|
||||
}
|
||||
|
||||
this->synchronize();
|
||||
@ -196,7 +197,7 @@ ext::vulkan::RenderMode::commands_container_t& ext::vulkan::RenderMode::getComma
|
||||
commands.resize( swapchain.buffers );
|
||||
|
||||
VkCommandBufferAllocateInfo cmdBufAllocateInfo = ext::vulkan::initializers::commandBufferAllocateInfo(
|
||||
this->getType() == "Compute" ? device->getCommandPool(Device::QueueEnum::COMPUTE) : device->getCommandPool(Device::QueueEnum::GRAPHICS),
|
||||
device->getCommandPool(this->getType() == "Compute" ? Device::QueueEnum::COMPUTE : Device::QueueEnum::GRAPHICS),
|
||||
VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
||||
static_cast<uint32_t>(commands.size())
|
||||
);
|
||||
@ -219,7 +220,7 @@ void ext::vulkan::RenderMode::bindPipelines() {
|
||||
ext::vulkan::Graphic& graphic = entity->getComponent<uf::Graphic>();
|
||||
if ( !graphic.initialized || !graphic.process ) continue;
|
||||
// if ( graphic.descriptor.renderMode != "" && graphic.descriptor.renderMode != this->getName() ) continue;
|
||||
graphics.push_back(&graphic);
|
||||
graphics.emplace_back(&graphic);
|
||||
}
|
||||
this->synchronize();
|
||||
this->bindPipelines( graphics );
|
||||
@ -230,42 +231,26 @@ void ext::vulkan::RenderMode::bindPipelines( const uf::stl::vector<ext::vulkan::
|
||||
for ( size_t currentPass = 0; currentPass < renderTarget.passes.size(); ++currentPass ) {
|
||||
auto& subpass = renderTarget.passes[currentPass];
|
||||
if ( !subpass.autoBuildPipeline ) continue;
|
||||
|
||||
// bind to this render mode
|
||||
ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic.descriptor, currentPass);
|
||||
// ignore invalidated descriptors
|
||||
if ( descriptor.invalidated ) continue;
|
||||
// ignore if pipeline exists for this render mode
|
||||
if ( graphic.hasPipeline( descriptor ) ) continue;
|
||||
// if pipeline name is specified for the rendermode, check if we have shaders for it
|
||||
size_t shaders = 0;
|
||||
for ( auto& shader : graphic.material.shaders ) {
|
||||
if ( shader.metadata.pipeline == descriptor.pipeline ) ++shaders;
|
||||
for ( auto& pipeline : metadata.pipelines ) {
|
||||
ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic.descriptor, currentPass);
|
||||
descriptor.pipeline = pipeline;
|
||||
// ignore invalidated descriptors
|
||||
if ( descriptor.invalidated ) continue;
|
||||
// ignore if pipeline exists for this render mode
|
||||
if ( graphic.hasPipeline( descriptor ) ) continue;
|
||||
// if pipeline name is specified for the rendermode, check if we have shaders for it
|
||||
size_t shaders = 0;
|
||||
for ( auto& shader : graphic.material.shaders ) if ( shader.metadata.pipeline == descriptor.pipeline ) ++shaders;
|
||||
if ( shaders == 0 ) continue;
|
||||
graphic.initializePipeline( descriptor );
|
||||
}
|
||||
if ( shaders == 0 ) continue;
|
||||
graphic.initializePipeline( descriptor );
|
||||
}
|
||||
}
|
||||
/*
|
||||
size_t subpasses = metadata["subpasses"].as<size_t>();
|
||||
for ( auto* pointer : graphics ) {
|
||||
auto& graphic = *pointer;
|
||||
for ( size_t currentPass = 0; currentPass < subpasses; ++currentPass ) {
|
||||
// bind to this render mode
|
||||
ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic.descriptor, currentPass);
|
||||
// ignore if pipeline exists for this render mode
|
||||
if ( graphic.hasPipeline( descriptor ) ) continue;
|
||||
graphic.initializePipeline( descriptor );
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void ext::vulkan::RenderMode::render() {
|
||||
/*
|
||||
if ( ext::openvr::context ) {
|
||||
ext::openvr::submit();
|
||||
}
|
||||
*/
|
||||
auto& commands = getCommands( this->mostRecentCommandPoolId );
|
||||
// Get next image in the swap chain (back/front buffer)
|
||||
VK_CHECK_RESULT(swapchain.acquireNextImage(&states::currentBuffer, swapchain.presentCompleteSemaphore));
|
||||
@ -308,20 +293,6 @@ void ext::vulkan::RenderMode::initialize( Device& device ) {
|
||||
if ( this->height > 0 ) renderTarget.height = this->height;
|
||||
}
|
||||
|
||||
// Create command buffers
|
||||
/*
|
||||
{
|
||||
commands.resize( swapchain.buffers );
|
||||
|
||||
VkCommandBufferAllocateInfo cmdBufAllocateInfo = ext::vulkan::initializers::commandBufferAllocateInfo(
|
||||
this->getType() == "Compute" ? device.getCommandPool(Device::QueueEnum::COMPUTE) : device.getCommandPool(Device::QueueEnum::GRAPHICS),
|
||||
VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
||||
static_cast<uint32_t>(commands.size())
|
||||
);
|
||||
|
||||
VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, commands.data()));
|
||||
}
|
||||
*/
|
||||
// Set sync objects
|
||||
{
|
||||
// Fences (Used to check draw command buffer completion)
|
||||
@ -343,6 +314,11 @@ void ext::vulkan::RenderMode::initialize( Device& device ) {
|
||||
VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &renderCompleteSemaphore));
|
||||
}
|
||||
}
|
||||
|
||||
if ( std::find( metadata.pipelines.begin(), metadata.pipelines.end(), metadata.pipeline ) == metadata.pipelines.end() ) {
|
||||
metadata.pipelines.emplace_back(metadata.pipeline);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ext::vulkan::RenderMode::tick() {
|
||||
|
||||
@ -104,9 +104,11 @@ void ext::vulkan::ComputeRenderMode::initialize( Device& device ) {
|
||||
0, 1, 2, 2, 3, 0
|
||||
};
|
||||
*/
|
||||
|
||||
blitter.device = &device;
|
||||
blitter.material.device = &device;
|
||||
blitter.descriptor.subpass = 1;
|
||||
blitter.descriptor.inputs.dispatch = { (width / 32) + 1, (height / 32) + 1, 1 };
|
||||
|
||||
blitter.descriptor.depth.test = false;
|
||||
blitter.descriptor.depth.write = false;
|
||||
@ -246,7 +248,6 @@ void ext::vulkan::ComputeRenderMode::createCommandBuffers( ) {
|
||||
for (size_t i = 0; i < commands.size(); ++i) {
|
||||
VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo));
|
||||
pipeline.record(compute, commands[i]);
|
||||
vkCmdDispatch(commands[i], width / dispatchSize.x, height / dispatchSize.y, 1);
|
||||
VK_CHECK_RESULT(vkEndCommandBuffer(commands[i]));
|
||||
}
|
||||
|
||||
|
||||
@ -193,6 +193,8 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
|
||||
{
|
||||
uf::Mesh mesh;
|
||||
mesh.vertex.count = 3;
|
||||
/*
|
||||
mesh.bind<pod::Vertex_2F2F, uint16_t>();
|
||||
mesh.insertVertices<pod::Vertex_2F2F>({
|
||||
{ {-1.0f, 1.0f}, {0.0f, 1.0f}, },
|
||||
@ -203,18 +205,8 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
mesh.insertIndices<uint16_t>({
|
||||
0, 1, 2, 2, 3, 0
|
||||
});
|
||||
/*
|
||||
uf::Mesh<pod::Vertex_2F2F, uint16_t> mesh;
|
||||
mesh.vertices = {
|
||||
{ {-1.0f, 1.0f}, {0.0f, 1.0f}, },
|
||||
{ {-1.0f, -1.0f}, {0.0f, 0.0f}, },
|
||||
{ {1.0f, -1.0f}, {1.0f, 0.0f}, },
|
||||
{ {1.0f, 1.0f}, {1.0f, 1.0f}, }
|
||||
};
|
||||
mesh.indices = {
|
||||
0, 1, 2, 0, 2, 3
|
||||
};
|
||||
*/
|
||||
|
||||
blitter.descriptor.subpass = 1;
|
||||
blitter.descriptor.depth.test = false;
|
||||
blitter.descriptor.depth.write = false;
|
||||
@ -237,20 +229,10 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
{uf::io::resolveURI(vertexShaderFilename), VK_SHADER_STAGE_VERTEX_BIT},
|
||||
{uf::io::resolveURI(fragmentShaderFilename), VK_SHADER_STAGE_FRAGMENT_BIT}
|
||||
});
|
||||
/*
|
||||
uf::stl::string fragmentShaderFilename = ( msaa <= 1 ) ? "no-msaa." : "";
|
||||
if ( ext::vulkan::settings::experimental::vxgi ) {
|
||||
fragmentShaderFilename = ( msaa <= 1 ) ? "vxgi.no-msaa." : "vxgi.";
|
||||
}
|
||||
blitter.material.initializeShaders({
|
||||
{uf::io::root+"/shaders/display/subpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT},
|
||||
{uf::io::root+"/shaders/display/subpass." + fragmentShaderFilename + "frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT}
|
||||
});
|
||||
*/
|
||||
{
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
|
||||
auto& shader = blitter.material.shaders.back();
|
||||
auto& shader = blitter.material.getShader("fragment");
|
||||
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);
|
||||
@ -258,19 +240,35 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
size_t maxTextures3D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["3D"].as<size_t>(128);
|
||||
size_t maxCascades = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["vxgi"]["cascades"].as<size_t>(16);
|
||||
|
||||
// shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.camera );
|
||||
// shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.joint );
|
||||
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.instance );
|
||||
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.material );
|
||||
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.texture );
|
||||
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.light );
|
||||
|
||||
if ( ext::vulkan::settings::experimental::vxgi ) {
|
||||
uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants;
|
||||
for ( auto pair : shader.metadata.definitions.specializationConstants ) {
|
||||
auto& sc = pair.second;
|
||||
if ( sc.name == "TEXTURES" ) sc.value.ui = (specializationConstants[sc.index] = 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;
|
||||
}
|
||||
}
|
||||
/*
|
||||
struct SpecializationConstant {
|
||||
uint32_t maxTextures2D = 512;
|
||||
uint32_t maxTexturesCube = 128;
|
||||
uint32_t maxCascades = 16;
|
||||
};
|
||||
auto& specializationConstants = shader.specializationConstants.get<SpecializationConstant>();
|
||||
specializationConstants.maxTextures2D = maxTextures2D;
|
||||
specializationConstants.maxTexturesCube = maxTexturesCube;
|
||||
specializationConstants.maxCascades = maxCascades;
|
||||
*/
|
||||
uint32_t* specializationConstants = (uint32_t*) (void*) &shader.specializationConstants;
|
||||
uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants;
|
||||
ext::json::forEach( shader.metadata.json["specializationConstants"], [&]( size_t i, ext::json::Value& sc ){
|
||||
uf::stl::string name = sc["name"].as<uf::stl::string>();
|
||||
if ( name == "TEXTURES" ) sc["value"] = (specializationConstants[i] = maxTextures2D);
|
||||
@ -290,17 +288,24 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
else if ( name == "voxelRadiance" ) layout.descriptorCount = maxCascades;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
/*
|
||||
struct SpecializationConstant {
|
||||
uint32_t maxTextures2D = 512;
|
||||
uint32_t maxTexturesCube = 128;
|
||||
};
|
||||
auto& specializationConstants = shader.specializationConstants.get<SpecializationConstant>();
|
||||
specializationConstants.maxTextures2D = maxTextures2D;
|
||||
specializationConstants.maxTexturesCube = maxTexturesCube;
|
||||
*/
|
||||
uint32_t* specializationConstants = (uint32_t*) (void*) &shader.specializationConstants;
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
/*
|
||||
uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants;
|
||||
ext::json::forEach( shader.metadata.json["specializationConstants"], [&]( size_t i, ext::json::Value& sc ){
|
||||
uf::stl::string name = sc["name"].as<uf::stl::string>();
|
||||
if ( name == "TEXTURES" ) sc["value"] = (specializationConstants[i] = maxTextures2D);
|
||||
@ -316,15 +321,15 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
else if ( name == "samplerCubemaps" ) layout.descriptorCount = maxTexturesCube;
|
||||
}
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
uf::stl::vector<pod::Light> lights(maxLights);
|
||||
uf::stl::vector<pod::Material> materials(maxTextures2D);
|
||||
uf::stl::vector<pod::Texture> textures(maxTextures2D);
|
||||
uf::stl::vector<pod::DrawCommand> drawCommands(maxTextures2D);
|
||||
|
||||
for ( auto& material : materials ) material.colorBase = {0,0,0,0};
|
||||
|
||||
metadata.lightBufferIndex = shader.initializeBuffer(
|
||||
(const void*) lights.data(),
|
||||
lights.size() * sizeof(pod::Light),
|
||||
@ -347,6 +352,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
drawCommands.size() * sizeof(pod::DrawCommand),
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
|
||||
);
|
||||
*/
|
||||
}
|
||||
// blitter.initializePipeline();
|
||||
for ( size_t eye = 0; eye < metadata.eyes; ++eye ) {
|
||||
@ -427,10 +433,16 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
|
||||
clearValue.color = { { 0, 0, 0, 0 } };
|
||||
}
|
||||
} else if ( attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) {
|
||||
clearValue.depthStencil = { 0.0f, 0 };
|
||||
if ( uf::matrix::reverseInfiniteProjection ) {
|
||||
clearValue.depthStencil = { 0.0f, 0 };
|
||||
} else {
|
||||
clearValue.depthStencil = { 1.0f, 0 };
|
||||
}
|
||||
}
|
||||
clearValues.push_back(clearValue);
|
||||
}
|
||||
// uf::matrix::reverseInfiniteProjection
|
||||
// descriptor.depth.operation ext::RENDERER::enums::Compare::GREATER_OR_EQUAL
|
||||
|
||||
VkRenderPassBeginInfo renderPassBeginInfo = {};
|
||||
renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
@ -462,8 +474,19 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
|
||||
for ( auto layer : layers ) {
|
||||
layer->pipelineBarrier( commands[i], 0 );
|
||||
}
|
||||
|
||||
|
||||
size_t currentSubpass = 0;
|
||||
|
||||
for ( auto& pipeline : metadata.pipelines ) {
|
||||
if ( pipeline == metadata.pipeline ) continue;
|
||||
for ( auto graphic : graphics ) {
|
||||
if ( graphic->descriptor.renderMode != this->getName() ) continue;
|
||||
ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentSubpass);
|
||||
descriptor.pipeline = pipeline;
|
||||
graphic->record( commands[i], descriptor, 0, metadata.eyes );
|
||||
}
|
||||
}
|
||||
|
||||
vkCmdBeginRenderPass(commands[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
vkCmdSetViewport(commands[i], 0, 1, &viewport);
|
||||
vkCmdSetScissor(commands[i], 0, 1, &scissor);
|
||||
|
||||
@ -42,7 +42,6 @@ ext::vulkan::GraphicDescriptor ext::vulkan::RenderTargetRenderMode::bindGraphicD
|
||||
descriptor.cullMode = VK_CULL_MODE_NONE;
|
||||
descriptor.depth.test = false;
|
||||
descriptor.depth.write = false;
|
||||
descriptor.pipeline = "vxgi";
|
||||
} else if ( metadata.type == "depth" ) {
|
||||
descriptor.cullMode = VK_CULL_MODE_NONE;
|
||||
}
|
||||
@ -304,6 +303,8 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
|
||||
|
||||
if ( blitter.process ) {
|
||||
uf::Mesh mesh;
|
||||
mesh.vertex.count = 3;
|
||||
/*
|
||||
mesh.bind<pod::Vertex_2F2F, uint16_t>();
|
||||
mesh.insertVertices<pod::Vertex_2F2F>({
|
||||
{ {-1.0f, 1.0f}, {0.0f, 1.0f}, },
|
||||
@ -314,6 +315,7 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
|
||||
mesh.insertIndices<uint16_t>({
|
||||
0, 1, 2, 2, 3, 0
|
||||
});
|
||||
*/
|
||||
|
||||
blitter.device = &device;
|
||||
blitter.material.device = &device;
|
||||
@ -412,15 +414,39 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
|
||||
size_t maxCascades = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["vxgi"]["cascades"].as<size_t>(16);
|
||||
|
||||
auto& shader = blitter.material.getShader("compute");
|
||||
// shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.camera );
|
||||
// shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.joint );
|
||||
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.instance );
|
||||
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.material );
|
||||
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.texture );
|
||||
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.light );
|
||||
|
||||
uint32_t* specializationConstants = (uint32_t*) (void*) &shader.specializationConstants;
|
||||
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;
|
||||
}
|
||||
}
|
||||
/*
|
||||
ext::json::forEach( shader.metadata.json["specializationConstants"], [&]( size_t i, ext::json::Value& sc ){
|
||||
uf::stl::string name = sc["name"].as<uf::stl::string>();
|
||||
if ( name == "TEXTURES" ) sc["value"] = (specializationConstants[i] = maxTextures2D);
|
||||
else if ( name == "CUBEMAPS" ) sc["value"] = (specializationConstants[i] = maxTexturesCube);
|
||||
else if ( name == "CASCADES" ) sc["value"] = (specializationConstants[i] = maxCascades);
|
||||
});
|
||||
|
||||
ext::json::forEach( shader.metadata.json["definitions"]["textures"], [&]( ext::json::Value& t ){
|
||||
size_t binding = t["binding"].as<size_t>();
|
||||
uf::stl::string name = t["name"].as<uf::stl::string>();
|
||||
@ -434,36 +460,8 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
|
||||
else if ( name == "voxelRadiance" ) layout.descriptorCount = maxCascades;
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
uf::stl::vector<pod::Light> lights(maxLights);
|
||||
uf::stl::vector<pod::Material> materials(maxTextures2D);
|
||||
uf::stl::vector<pod::Texture> textures(maxTextures2D);
|
||||
uf::stl::vector<pod::DrawCommand> drawCalls(maxTextures2D);
|
||||
|
||||
for ( auto& material : materials ) material.colorBase = {0,0,0,0};
|
||||
|
||||
metadata.lightBufferIndex = shader.initializeBuffer(
|
||||
(const void*) lights.data(),
|
||||
lights.size() * sizeof(pod::Light),
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
|
||||
);
|
||||
metadata.materialBufferIndex = shader.initializeBuffer(
|
||||
(const void*) materials.data(),
|
||||
materials.size() * sizeof(pod::Material),
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
|
||||
);
|
||||
|
||||
metadata.textureBufferIndex = shader.initializeBuffer(
|
||||
(const void*) textures.data(),
|
||||
textures.size() * sizeof(pod::Texture),
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
|
||||
);
|
||||
|
||||
metadata.drawCallBufferIndex = shader.initializeBuffer(
|
||||
(const void*) drawCalls.data(),
|
||||
drawCalls.size() * sizeof(pod::DrawCommand),
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
|
||||
);
|
||||
} else {
|
||||
for ( auto& attachment : renderTarget.attachments ) {
|
||||
if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ) continue;
|
||||
@ -648,7 +646,11 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const uf::stl::v
|
||||
if ( attachment.descriptor.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) {
|
||||
clearValue.color = { { 0.0f, 0.0f, 0.0f, 0.0f } };
|
||||
} else if ( attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) {
|
||||
clearValue.depthStencil = { 0.0f, 0 };
|
||||
if ( uf::matrix::reverseInfiniteProjection ) {
|
||||
clearValue.depthStencil = { 0.0f, 0 };
|
||||
} else {
|
||||
clearValue.depthStencil = { 1.0f, 0 };
|
||||
}
|
||||
}
|
||||
clearValues.push_back(clearValue);
|
||||
}
|
||||
@ -684,6 +686,16 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const uf::stl::v
|
||||
size_t currentPass = 0;
|
||||
// pre-renderpass commands
|
||||
if ( commandBufferCallbacks.count(CALLBACK_BEGIN) > 0 ) commandBufferCallbacks[CALLBACK_BEGIN]( commands[i] );
|
||||
|
||||
for ( auto& pipeline : metadata.pipelines ) {
|
||||
if ( pipeline == metadata.pipeline ) continue;
|
||||
for ( auto graphic : graphics ) {
|
||||
if ( graphic->descriptor.renderMode != this->getTarget() ) continue;
|
||||
ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentPass);
|
||||
descriptor.pipeline = pipeline;
|
||||
graphic->record( commands[i], descriptor, 0, metadata.type == "vxgi" ? 0 : MIN(subpasses,6) );
|
||||
}
|
||||
}
|
||||
|
||||
vkCmdBeginRenderPass(commands[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
vkCmdSetViewport(commands[i], 0, 1, &viewport);
|
||||
|
||||
@ -557,7 +557,7 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl
|
||||
auto& userdata = uniforms.emplace_back();
|
||||
userdata.create( definition.size, nullptr );
|
||||
|
||||
initializeBuffer(
|
||||
if ( metadata.autoInitializeUniforms ) initializeBuffer(
|
||||
(const void*) userdata.data().data,
|
||||
userdata.data().len,
|
||||
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
|
||||
@ -658,19 +658,26 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl
|
||||
}
|
||||
|
||||
size_t specializationSize = 0;
|
||||
uf::stl::vector<VkSpecializationMapEntry> specializationRemap;
|
||||
specializationRemap.resize( comp.get_specialization_constants().size() );
|
||||
|
||||
for ( const auto& constant : comp.get_specialization_constants() ) {
|
||||
const auto& value = comp.get_constant(constant.id);
|
||||
const auto& type = comp.get_type(value.constant_type);
|
||||
uf::stl::string name = comp.get_name (constant.id);
|
||||
size_t size = 4; //comp.get_declared_struct_size(type);
|
||||
|
||||
VkSpecializationMapEntry specializationMapEntry;
|
||||
auto& specializationMapEntry = specializationRemap[constant.constant_id];
|
||||
specializationMapEntry.constantID = constant.constant_id;
|
||||
specializationMapEntry.size = size;
|
||||
specializationMapEntry.offset = specializationSize;
|
||||
specializationMapEntries.emplace_back(specializationMapEntry);
|
||||
specializationSize += size;
|
||||
}
|
||||
if ( specializationSize > 0 ) {
|
||||
specializationRemap.reserve( specializationRemap.size() );
|
||||
for ( auto& specializationMapEntry : specializationRemap ) {
|
||||
specializationMapEntries.emplace_back(specializationMapEntry);
|
||||
}
|
||||
specializationConstants.create( specializationSize );
|
||||
VK_DEBUG_VALIDATION_MESSAGE("Specialization constants size of " << specializationSize << " for shader " << filename);
|
||||
|
||||
|
||||
@ -81,6 +81,7 @@ void ext::vulkan::Texture::initialize( Device& device, size_t width, size_t heig
|
||||
this->height = height;
|
||||
this->depth = depth;
|
||||
this->layers = layers;
|
||||
|
||||
// implicitly set type
|
||||
if ( width > 1 && height > 1 && depth > 1 ) {
|
||||
this->type = ext::vulkan::enums::Image::TYPE_3D;
|
||||
@ -361,8 +362,8 @@ void ext::vulkan::Texture::loadFromImage(
|
||||
(void*) image.getPixelsPtr(),
|
||||
image.getPixels().size(),
|
||||
format,
|
||||
image.getDimensions()[0],
|
||||
image.getDimensions()[1],
|
||||
image.getDimensions().x,
|
||||
image.getDimensions().y,
|
||||
1,
|
||||
1,
|
||||
device,
|
||||
@ -500,29 +501,8 @@ void ext::vulkan::Texture::fromBuffers(
|
||||
device.flushCommandBuffer(commandBuffer);
|
||||
|
||||
this->imageLayout = imageLayout;
|
||||
this->updateDescriptors();
|
||||
}
|
||||
/*
|
||||
if ( this->layers > 1 ) {
|
||||
// Create image view
|
||||
VkImageSubresourceRange subresourceRange = {};
|
||||
subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
subresourceRange.baseMipLevel = 0;
|
||||
subresourceRange.baseArrayLayer = 1;
|
||||
subresourceRange.levelCount = this->mips;
|
||||
subresourceRange.layerCount = this->layers - 1;
|
||||
|
||||
VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
|
||||
setImageLayout(
|
||||
commandBuffer,
|
||||
image,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
imageLayout,
|
||||
subresourceRange
|
||||
);
|
||||
device.flushCommandBuffer(commandBuffer);
|
||||
}
|
||||
*/
|
||||
this->updateDescriptors();
|
||||
}
|
||||
|
||||
@ -588,20 +568,31 @@ void ext::vulkan::Texture::asRenderTarget( Device& device, uint32_t width, uint3
|
||||
this->updateDescriptors();
|
||||
}
|
||||
void ext::vulkan::Texture::aliasTexture( const Texture& texture ) {
|
||||
image = texture.image;
|
||||
view = texture.view;
|
||||
type = texture.type;
|
||||
viewType = texture.viewType;
|
||||
imageLayout = texture.imageLayout;
|
||||
deviceMemory = texture.deviceMemory;
|
||||
width = texture.width;
|
||||
height = texture.height;
|
||||
depth = texture.depth;
|
||||
layers = texture.layers;
|
||||
|
||||
sampler = texture.sampler;
|
||||
sampler.device = NULL;
|
||||
|
||||
*this = {
|
||||
.device = nullptr,
|
||||
.image = texture.image,
|
||||
.view = texture.view,
|
||||
.type = texture.type,
|
||||
.viewType = texture.viewType,
|
||||
.imageLayout = texture.imageLayout,
|
||||
.deviceMemory = texture.deviceMemory,
|
||||
.descriptor = texture.descriptor,
|
||||
.format = texture.format,
|
||||
|
||||
.sampler = texture.sampler,
|
||||
|
||||
.allocation = texture.allocation,
|
||||
.allocationInfo = texture.allocationInfo,
|
||||
|
||||
.width = texture.width,
|
||||
.height = texture.height,
|
||||
.depth = texture.depth,
|
||||
.layers = texture.layers,
|
||||
.mips = texture.mips,
|
||||
};
|
||||
|
||||
sampler.device = nullptr;
|
||||
|
||||
this->updateDescriptors();
|
||||
}
|
||||
void ext::vulkan::Texture::aliasAttachment( const RenderTarget::Attachment& attachment, bool createSampler ) {
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include <uf/ext/vulkan/graphic.h>
|
||||
#include <uf/ext/vulkan/rendermode.h>
|
||||
#include <uf/utils/graphic/graphic.h>
|
||||
#include <uf/engine/graph/graph.h>
|
||||
|
||||
#include <uf/ext/openvr/openvr.h>
|
||||
|
||||
@ -37,9 +38,9 @@ bool ext::vulkan::settings::experimental::deferredAliasOutputToSwapchain = true;
|
||||
bool ext::vulkan::settings::experimental::multiview = true;
|
||||
bool ext::vulkan::settings::experimental::vsync = true;
|
||||
bool ext::vulkan::settings::experimental::hdr = true;
|
||||
bool ext::vulkan::settings::experimental::frustrumCull = false;
|
||||
bool ext::vulkan::settings::experimental::vxgi = true;
|
||||
bool ext::vulkan::settings::experimental::deferredSampling = true;
|
||||
bool ext::vulkan::settings::experimental::culling = false;
|
||||
|
||||
VkColorSpaceKHR ext::vulkan::settings::formats::colorSpace;
|
||||
ext::vulkan::enums::Format::type_t ext::vulkan::settings::formats::color = ext::vulkan::enums::Format::R8G8B8A8_UNORM;
|
||||
@ -213,6 +214,7 @@ void ext::vulkan::removeRenderMode( ext::vulkan::RenderMode* mode, bool free ) {
|
||||
}
|
||||
|
||||
void ext::vulkan::initialize() {
|
||||
ext::vulkan::mutex.lock();
|
||||
device.initialize();
|
||||
swapchain.initialize( device );
|
||||
{
|
||||
@ -260,6 +262,9 @@ void ext::vulkan::initialize() {
|
||||
TextureCube::empty.sampler.descriptor.filter.mag = VK_FILTER_NEAREST;
|
||||
TextureCube::empty.fromBuffers( (void*) &pixels[0], pixels.size(), ext::vulkan::enums::Format::R8G8B8A8_UNORM, 2, 2, 1, 6, ext::vulkan::device, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
|
||||
}
|
||||
|
||||
uf::graph::initialize();
|
||||
|
||||
for ( auto& renderMode : renderModes ) {
|
||||
if ( !renderMode ) continue;
|
||||
renderMode->initialize(device);
|
||||
@ -272,6 +277,7 @@ void ext::vulkan::initialize() {
|
||||
else renderMode->createCommandBuffers();
|
||||
}
|
||||
if ( !jobs.empty() ) uf::thread::batchWorkers( jobs );
|
||||
ext::vulkan::mutex.unlock();
|
||||
}
|
||||
void ext::vulkan::tick() {
|
||||
ext::vulkan::mutex.lock();
|
||||
@ -335,11 +341,13 @@ void ext::vulkan::render() {
|
||||
ext::vulkan::currentRenderMode = renderMode;
|
||||
if ( settings::experimental::multithreadedCommandRendering ) {
|
||||
jobs.emplace_back([&]{
|
||||
uf::graph::render();
|
||||
uf::scene::render();
|
||||
renderMode->render();
|
||||
renderMode->executed = true;
|
||||
});
|
||||
} else {
|
||||
uf::graph::render();
|
||||
uf::scene::render();
|
||||
renderMode->render();
|
||||
renderMode->executed = true;
|
||||
|
||||
@ -4,60 +4,93 @@
|
||||
#endif
|
||||
pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) {
|
||||
#if UF_USE_XATLAS
|
||||
struct Pair {
|
||||
size_t index = 0;
|
||||
size_t command = 0;
|
||||
::xatlas::MeshDecl decl;
|
||||
};
|
||||
|
||||
uf::stl::vector<Pair> entries;
|
||||
entries.reserve(graph.meshes.size());
|
||||
|
||||
uf::stl::vector<uf::Mesh> sources;
|
||||
sources.reserve(graph.meshes.size());
|
||||
|
||||
::xatlas::Atlas* atlas = ::xatlas::Create();
|
||||
#if 0
|
||||
for ( auto& name : graph.meshes ) {
|
||||
for ( auto index = 0; index < graph.meshes.size(); ++index ) {
|
||||
auto& name = graph.meshes[index];
|
||||
auto& mesh = uf::graph::storage.meshes[name];
|
||||
mesh.updateDescriptor();
|
||||
sources.emplace_back(mesh);
|
||||
|
||||
size_t indices = mesh.attributes.index.length;
|
||||
size_t indexStride = mesh.attributes.index.size;
|
||||
uint8_t* indexPointer = (uint8_t*) mesh.attributes.index.pointer;
|
||||
if ( mesh.index.count ) {
|
||||
uf::Mesh::Attribute positionAttribute;
|
||||
uf::Mesh::Attribute uvAttribute;
|
||||
uf::Mesh::Attribute stAttribute;
|
||||
for ( auto& attribute : mesh.vertex.attributes ) {
|
||||
if ( attribute.descriptor.name == "position" ) positionAttribute = attribute;
|
||||
else if ( attribute.descriptor.name == "uv" ) uvAttribute = attribute;
|
||||
else if ( attribute.descriptor.name == "st" ) stAttribute = attribute;
|
||||
}
|
||||
UF_ASSERT( positionAttribute.descriptor.name == "position" && uvAttribute.descriptor.name == "uv" && uvAttribute.descriptor.name == "st" );
|
||||
|
||||
size_t vertices = mesh.attributes.vertex.length;
|
||||
size_t vertexStride = mesh.attributes.vertex.size;
|
||||
uint8_t* vertexPointer = (uint8_t*) mesh.attributes.vertex.pointer;
|
||||
auto& indexAttribute = mesh.index.attributes.front();
|
||||
::xatlas::IndexFormat indexType = ::xatlas::IndexFormat::UInt32;
|
||||
switch ( mesh.index.stride ) {
|
||||
case sizeof(uint16_t): indexType = ::xatlas::IndexFormat::UInt16; break;
|
||||
case sizeof(uint32_t): indexType = ::xatlas::IndexFormat::UInt32; break;
|
||||
default: UF_EXCEPTION("unsupported index type"); break;
|
||||
}
|
||||
|
||||
uf::renderer::AttributeDescriptor vertexAttributePosition,
|
||||
vertexAttributeNormal,
|
||||
vertexAttributeUv,
|
||||
vertexAttributeSt,
|
||||
vertexAttributeId;
|
||||
if ( mesh.indirect.count ) {
|
||||
uf::Mesh::Attribute remappedPositionAttribute;
|
||||
uf::Mesh::Attribute remappedUvAttribute;
|
||||
uf::Mesh::Attribute remappedIndexAttribute;
|
||||
for ( auto i = 0; i < mesh.indirect.count; ++i ) {
|
||||
remappedPositionAttribute = mesh.remapVertexAttribute( positionAttribute, i );
|
||||
remappedUvAttribute = mesh.remapVertexAttribute( uvAttribute, i );
|
||||
remappedIndexAttribute = mesh.remapIndexAttribute( indexAttribute, i );
|
||||
|
||||
for ( auto& attribute : mesh.attributes.vertex.descriptor ) {
|
||||
if ( attribute.name == "position" ) vertexAttributePosition = attribute;
|
||||
else if ( attribute.name == "normal" ) vertexAttributeNormal = attribute;
|
||||
else if ( attribute.name == "uv" ) vertexAttributeUv = attribute;
|
||||
else if ( attribute.name == "st" ) vertexAttributeSt = attribute;
|
||||
else if ( attribute.name == "id" ) vertexAttributeId = attribute;
|
||||
}
|
||||
UF_ASSERT( vertexAttributePosition.name != "" );
|
||||
auto& entry = entries.emplace_back();
|
||||
entry.index = index;
|
||||
entry.command = i;
|
||||
|
||||
::xatlas::MeshDecl meshDecl;
|
||||
meshDecl.vertexCount = vertices; // mesh.vertices.size();
|
||||
meshDecl.vertexPositionData = (uint8_t*) mesh.attributes.vertex.pointer + vertexAttributePosition.offset; /*((uint8_t*) mesh.vertices.data()) + vertexAttributePosition.offset*/
|
||||
meshDecl.vertexPositionStride = vertexStride;
|
||||
if ( vertexAttributeUv.name != "" ) {
|
||||
meshDecl.vertexUvData = (uint8_t*) mesh.attributes.vertex.pointer + vertexAttributeUv.offset;// ((uint8_t*) mesh.vertices.data()) + vertexAttributeUv.offset;
|
||||
meshDecl.vertexUvStride = vertexStride;
|
||||
}
|
||||
/*
|
||||
if ( vertexAttributeNormal.name != "" ) {
|
||||
meshDecl.vertexNormalData = ((uint8_t*) mesh.vertices.data()) + vertexAttributeNormal.offset;
|
||||
meshDecl.vertexNormalStride = mesh.attributes.vertex.size;
|
||||
}
|
||||
*/
|
||||
meshDecl.indexCount = indices; // mesh.indices.size();
|
||||
meshDecl.indexData = mesh.attributes.index.pointer; // mesh.indices.data();
|
||||
meshDecl.indexFormat = indexStride == 4 ? ::xatlas::IndexFormat::UInt32 : ::xatlas::IndexFormat::UInt16;
|
||||
auto& decl = entry.decl;
|
||||
decl.vertexCount = remappedUvAttribute.length;
|
||||
decl.vertexPositionData = remappedPositionAttribute.pointer;
|
||||
decl.vertexPositionStride = remappedPositionAttribute.stride;
|
||||
decl.vertexUvData = remappedUvAttribute.pointer;
|
||||
decl.vertexUvStride = remappedUvAttribute.stride;
|
||||
|
||||
::xatlas::AddMeshError error = ::xatlas::AddMesh(atlas, meshDecl, graph.meshes.size());
|
||||
decl.indexCount = remappedIndexAttribute.length;
|
||||
decl.indexData = remappedIndexAttribute.pointer;
|
||||
decl.indexFormat = indexType;
|
||||
}
|
||||
} else {
|
||||
auto& entry = entries.emplace_back();
|
||||
entry.index = index;
|
||||
|
||||
auto& decl = entry.decl;
|
||||
decl.vertexCount = uvAttribute.length;
|
||||
decl.vertexPositionData = positionAttribute.pointer;
|
||||
decl.vertexPositionStride = positionAttribute.stride;
|
||||
decl.vertexUvData = uvAttribute.pointer;
|
||||
decl.vertexUvStride = uvAttribute.stride;
|
||||
|
||||
decl.indexCount = indexAttribute.length;
|
||||
decl.indexData = indexAttribute.pointer;
|
||||
decl.indexFormat = indexType;
|
||||
decl.indexFormat = indexType;
|
||||
|
||||
}
|
||||
} else UF_EXCEPTION("to-do: not require indices for meshes");
|
||||
}
|
||||
for ( auto& mesh : entries ) {
|
||||
::xatlas::AddMeshError error = ::xatlas::AddMesh(atlas, mesh.decl, entries.size());
|
||||
if (error != ::xatlas::AddMeshError::Success) {
|
||||
::xatlas::Destroy(atlas);
|
||||
UF_MSG_ERROR(::xatlas::StringForEnum(error));
|
||||
return {};
|
||||
UF_EXCEPTION(::xatlas::StringForEnum(error));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::xatlas::ChartOptions chartOptions{};
|
||||
// chartOptions.useInputMeshUvs = true;
|
||||
@ -72,61 +105,79 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) {
|
||||
|
||||
for ( size_t i = 0; i < atlas->meshCount; i++ ) {
|
||||
auto& xmesh = atlas->meshes[i];
|
||||
auto& mesh = uf::graph::storage.meshes[graph.meshes[i]];
|
||||
auto& entry = entries[i];
|
||||
auto& mesh = graph.meshes[entry.index];
|
||||
auto& source = sources[entry.index];
|
||||
source.updateDescriptor();
|
||||
|
||||
size_t indices = mesh.attributes.index.length;
|
||||
size_t indexStride = mesh.attributes.index.size;
|
||||
uint8_t* indexPointer = (uint8_t*) mesh.attributes.index.pointer;
|
||||
|
||||
uf::stl::vector<uint8_t> oldVertexBuffer( (uint8_t*) mesh.attributes.vertex.pointer, (uint8_t*) mesh.attributes.vertex.pointer + mesh.attributes.vertex.length * mesh.attributes.vertex.size );
|
||||
}
|
||||
|
||||
size_t vertices = xmesh.vertexCount;
|
||||
size_t vertexStride = mesh.attributes.vertex.size;
|
||||
|
||||
mesh.resizeVertices( vertices );
|
||||
#if 0
|
||||
for ( size_t i = 0; i < atlas->meshCount; i++ ) {
|
||||
auto& xmesh = atlas->meshes[i];
|
||||
auto& mesh = *meshes[i];
|
||||
|
||||
uint8_t* oldVertexPointer = oldVertexBuffer.data();
|
||||
uint8_t* newvertexPointer = (uint8_t*) mesh.attributes.vertex.pointer;
|
||||
uf::Mesh src;
|
||||
src.buffers = mesh.buffers;
|
||||
src.vertex = mesh.vertex;
|
||||
src.index = mesh.index;
|
||||
src.instance = mesh.instance;
|
||||
src.indirect = mesh.indirect;
|
||||
|
||||
uf::renderer::AttributeDescriptor vertexAttributePosition,
|
||||
vertexAttributeNormal,
|
||||
vertexAttributeUv,
|
||||
vertexAttributeSt;
|
||||
mesh.resizeVertices( xmesh.vertexCount );
|
||||
|
||||
for ( auto& attribute : mesh.attributes.vertex.descriptor ) {
|
||||
if ( attribute.name == "position" ) vertexAttributePosition = attribute;
|
||||
else if ( attribute.name == "normal" ) vertexAttributeNormal = attribute;
|
||||
else if ( attribute.name == "uv" ) vertexAttributeUv = attribute;
|
||||
else if ( attribute.name == "st" ) vertexAttributeSt = attribute;
|
||||
}
|
||||
UF_ASSERT( vertexAttributePosition.name != "" );
|
||||
if ( mesh.isInterleaved( mesh.vertex.interleaved ) ) {
|
||||
for ( auto& attribute : mesh.vertex.attributes ) {
|
||||
if ( attribute.descriptor.name != "st" ) continue;
|
||||
|
||||
for ( size_t v = 0; v < xmesh.vertexCount; v++) {
|
||||
auto& xvertex = xmesh.vertexArray[v];
|
||||
uint8_t* oldVertexSrc = oldVertexPointer + (xvertex.xref * vertexStride);
|
||||
uint8_t* newVertexSrc = newvertexPointer + (v * vertexStride);
|
||||
uint8_t* srcBuffer = src.buffers[mesh.vertex.interleaved].data();
|
||||
uint8_t* dstBuffer = mesh.buffers[mesh.vertex.interleaved].data();
|
||||
for ( auto v = 0; v < xmesh.vertexCount; ++v ) {
|
||||
auto& vertex = xmesh.vertexArray[v];
|
||||
auto ref = vertex.xref;
|
||||
|
||||
memcpy( newVertexSrc, oldVertexSrc, vertexStride );
|
||||
memcpy( dstBuffer + v * mesh.vertex.stride, srcBuffer + ref * mesh.vertex.stride, mesh.vertex.stride );
|
||||
|
||||
pod::Vector2f& st = *((pod::Vector2f*) (newVertexSrc + vertexAttributeSt.offset));
|
||||
st = { xvertex.uv[0] / atlas->width, xvertex.uv[1] / atlas->height };
|
||||
pod::Vector2f& st = *((pod::Vector2f*) dstBuffer + v * mesh.vertex.stride + attribute.descriptor.offset);
|
||||
st = { vertex.uv[0] / atlas->width, vertex.uv[1] / atlas->height };
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
} else for ( auto& attribute : mesh.vertex.attributes ) {
|
||||
uint8_t* srcBuffer = src.buffers[attribute.buffer].data();
|
||||
uint8_t* dstBuffer = mesh.buffers[attribute.buffer].data();
|
||||
for ( auto v = 0; v < xmesh.vertexCount; ++v ) {
|
||||
auto& vertex = xmesh.vertexArray[v];
|
||||
auto ref = vertex.xref;
|
||||
|
||||
if ( attribute.descriptor.name == "st" ) {
|
||||
pod::Vector2f& st = *((pod::Vector2f*) dstBuffer + v * attribute.descriptor.size);
|
||||
st = { vertex.uv[0] / atlas->width, vertex.uv[1] / atlas->height };
|
||||
} else {
|
||||
memcpy( dstBuffer + v * attribute.descriptor.size, srcBuffer + ref * attribute.descriptor.size, attribute.descriptor.size );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ( size_t currentIndex = 0; currentIndex < xmesh.indexCount; ++currentIndex ) {
|
||||
uint32_t index = xmesh.indexArray[currentIndex];
|
||||
uint8_t* indexSrc = indexPointer + (currentIndex * indexStride);
|
||||
switch ( indexStride ) {
|
||||
case sizeof( uint8_t): *(( uint8_t*) indexSrc) = index; break;
|
||||
case sizeof(uint16_t): *((uint16_t*) indexSrc) = index; break;
|
||||
case sizeof(uint32_t): *((uint32_t*) indexSrc) = index; break;
|
||||
{
|
||||
auto& buffer = mesh.buffers[mesh.isInterleaved(mesh.index.interleaved) ? mesh.index.interleaved : mesh.index.attributes.front().buffer];
|
||||
uint8_t* pointer = (uint8_t*) buffer.data();
|
||||
for ( auto index = 0; index < mesh.index.count; ++index ) {
|
||||
switch ( mesh.index.stride ) {
|
||||
case 1: *( uint8_t*) pointer = xmesh.indexArray[index]; break;
|
||||
case 2: *(uint16_t*) pointer = xmesh.indexArray[index]; break;
|
||||
case 4: *(uint32_t*) pointer = xmesh.indexArray[index]; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
pod::Vector2ui size = pod::Vector2ui{ atlas->width, atlas->height };
|
||||
::xatlas::Destroy(atlas);
|
||||
|
||||
return size;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
@ -14,6 +14,7 @@
|
||||
|
||||
// C-tor
|
||||
// Default
|
||||
/*
|
||||
uf::Image::Image() :
|
||||
m_bpp(8),
|
||||
m_channels(4),
|
||||
@ -71,7 +72,7 @@ uf::Image::Image( const Image::container_t& copy, const Image::vec2_t& size ) :
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
*/
|
||||
uf::stl::string uf::Image::getFilename() const {
|
||||
return this->m_filename;
|
||||
}
|
||||
|
||||
@ -48,7 +48,6 @@ UF_VERTEX_DESCRIPTOR(pod::Vertex_3F,
|
||||
)
|
||||
|
||||
bool uf::Mesh::defaultInterleaved = false;
|
||||
|
||||
void uf::Mesh::initialize() {
|
||||
}
|
||||
void uf::Mesh::destroy() {
|
||||
@ -82,23 +81,26 @@ void uf::Mesh::updateDescriptor() {
|
||||
_updateDescriptor(instance);
|
||||
_updateDescriptor(indirect);
|
||||
}
|
||||
void uf::Mesh::insert( const uf::Mesh& mesh ) {
|
||||
insertVertex(mesh);
|
||||
insertIndex(mesh);
|
||||
insertInstance(mesh);
|
||||
insertIndirect(mesh);
|
||||
}
|
||||
/*
|
||||
uint32_t indices = 0; // triangle count
|
||||
uint32_t instances = 0; // instance count
|
||||
uint32_t indexID = 0; // starting triangle position
|
||||
int32_t vertexID = 0; // starting vertex position
|
||||
void uf::Mesh::bind( const uf::Mesh& mesh ) {
|
||||
vertex.attributes = mesh.vertex.attributes;
|
||||
vertex.interleaved = mesh.vertex.interleaved;
|
||||
index.attributes = mesh.index.attributes;
|
||||
index.interleaved = mesh.index.interleaved;
|
||||
instance.attributes = mesh.instance.attributes;
|
||||
instance.interleaved = mesh.instance.interleaved;
|
||||
indirect.attributes = mesh.indirect.attributes;
|
||||
indirect.interleaved = mesh.indirect.interleaved;
|
||||
|
||||
uint32_t instanceID = 0; // starting instance position
|
||||
uint32_t materialID = 0;
|
||||
uint32_t objectID = 0;
|
||||
uint32_t vertices = 0;
|
||||
*/
|
||||
_bind();
|
||||
}
|
||||
void uf::Mesh::insert( const uf::Mesh& mesh ) {
|
||||
if ( vertex.attributes.empty() && index.attributes.empty() && instance.attributes.empty() && indirect.attributes.empty() ) bind( mesh );
|
||||
|
||||
insertVertices(mesh);
|
||||
insertIndices(mesh);
|
||||
insertInstances(mesh);
|
||||
insertIndirects(mesh);
|
||||
}
|
||||
void uf::Mesh::generateIndices() {
|
||||
// deduce type
|
||||
size_t size = sizeof(uint32_t);
|
||||
@ -125,14 +127,16 @@ void uf::Mesh::generateIndirect() {
|
||||
uf::stl::vector<pod::DrawCommand> commands;
|
||||
for ( auto& attribute : index.attributes ) {
|
||||
auto& buffer = buffers[isInterleaved(index.interleaved) ? index.interleaved : attribute.buffer];
|
||||
auto& command = commands.emplace_back();
|
||||
command.indices = buffer.size() / attribute.descriptor.size;
|
||||
command.instances = instance.count == 0 && instance.attributes.empty() ? 1 : instance.count;
|
||||
command.indexID = 0;
|
||||
command.vertexID = 0;
|
||||
command.instanceID = 0;
|
||||
command.objectID = 0;
|
||||
command.vertices = vertex.count;
|
||||
commands.emplace_back(pod::DrawCommand{
|
||||
.indices = buffer.size() / attribute.descriptor.size,
|
||||
.instances = instance.count == 0 && instance.attributes.empty() ? 1 : instance.count,
|
||||
.indexID = 0,
|
||||
.vertexID = 0,
|
||||
.instanceID = 0,
|
||||
// .materialID = 0,
|
||||
// .objectID = 0,
|
||||
// .vertices = vertex.count,
|
||||
});
|
||||
}
|
||||
|
||||
_destroy( indirect );
|
||||
@ -234,8 +238,8 @@ void uf::Mesh::print() const {
|
||||
//
|
||||
void uf::Mesh::_destroy( uf::Mesh::Input& input ) {
|
||||
for ( auto& attribute : input.attributes ) {
|
||||
attribute.descriptor.length = 0;
|
||||
attribute.descriptor.pointer = NULL;
|
||||
attribute.length = 0;
|
||||
attribute.pointer = NULL;
|
||||
attribute.buffer = 0;
|
||||
}
|
||||
input.attributes.clear();
|
||||
@ -262,13 +266,33 @@ void uf::Mesh::_bind( bool interleave ) {
|
||||
void uf::Mesh::_updateDescriptor( uf::Mesh::Input& input ) {
|
||||
input.stride = 0;
|
||||
for ( auto& attribute : input.attributes ) {
|
||||
auto& buffer = buffers[isInterleaved(input.interleaved) ? input.interleaved : attribute.buffer];
|
||||
attribute.descriptor.length = buffer.size();
|
||||
attribute.descriptor.pointer = (void*) (buffer.data());
|
||||
const bool interleaved = isInterleaved(input.interleaved);
|
||||
auto& buffer = buffers[interleaved ? input.interleaved : attribute.buffer];
|
||||
attribute.length = buffer.size();
|
||||
attribute.pointer = (void*) (buffer.data());
|
||||
if ( !interleaved ) attribute.stride = attribute.descriptor.size;
|
||||
input.stride += attribute.descriptor.size;
|
||||
}
|
||||
for ( auto& attribute : input.attributes ) {
|
||||
const bool interleaved = isInterleaved(input.interleaved);
|
||||
if ( interleaved ) attribute.stride = input.stride;
|
||||
}
|
||||
}
|
||||
void uf::Mesh::_insertV( uf::Mesh::Input& input, const uf::Mesh& mesh, const uf::Mesh::Input& srcInput ) {
|
||||
uf::Mesh::Attribute uf::Mesh::_remapAttribute( const uf::Mesh::Input& input, const uf::Mesh::Attribute& attribute, size_t i ) const {
|
||||
uf::Mesh::Attribute res = attribute;
|
||||
if ( i < indirect.count ) {
|
||||
auto& drawCommand = ((const pod::DrawCommand*) buffers[isInterleaved(indirect.interleaved) ? indirect.interleaved : indirect.attributes.front().buffer].data())[i];
|
||||
if ( &input == &vertex ) {
|
||||
res.pointer = (void*) ((uint8_t*) res.pointer + drawCommand.vertexID * res.stride);
|
||||
res.length = drawCommand.vertices;
|
||||
} else if ( &input == &index ) {
|
||||
res.pointer = (void*) ((uint8_t*) res.pointer + drawCommand.indexID * res.stride);
|
||||
res.length = drawCommand.indices;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
void uf::Mesh::_insertVs( uf::Mesh::Input& input, const uf::Mesh& mesh, const uf::Mesh::Input& srcInput ) {
|
||||
if ( !_hasV( input, srcInput ) ) return;
|
||||
_reserveVs( input, input.count += srcInput.count );
|
||||
|
||||
@ -292,7 +316,7 @@ void uf::Mesh::_insertV( uf::Mesh::Input& input, const uf::Mesh& mesh, const uf:
|
||||
}
|
||||
_updateDescriptor( input );
|
||||
}
|
||||
void uf::Mesh::_insertI( uf::Mesh::Input& input, const uf::Mesh& mesh, const uf::Mesh::Input& srcInput ) {
|
||||
void uf::Mesh::_insertIs( uf::Mesh::Input& input, const uf::Mesh& mesh, const uf::Mesh::Input& srcInput ) {
|
||||
// if ( !_hasI( source ) ) return;
|
||||
_reserveIs( input, input.count += srcInput.count );
|
||||
|
||||
@ -339,26 +363,26 @@ void uf::Mesh::_reserveVs( uf::Mesh::Input& input, size_t count ) {
|
||||
if ( isInterleaved(input.interleaved) ) {
|
||||
buffers[input.interleaved].reserve( count * input.stride );
|
||||
for ( auto& attribute : input.attributes ) {
|
||||
attribute.descriptor.length = buffers[input.interleaved].size();
|
||||
attribute.descriptor.pointer = (void*) (buffers[input.interleaved].data());
|
||||
attribute.length = buffers[input.interleaved].size();
|
||||
attribute.pointer = (void*) (buffers[input.interleaved].data());
|
||||
}
|
||||
} else for ( auto& attribute : input.attributes ) {
|
||||
buffers[attribute.buffer].reserve( count * attribute.descriptor.size );
|
||||
attribute.descriptor.length = buffers[attribute.buffer].size();
|
||||
attribute.descriptor.pointer = (void*) (buffers[attribute.buffer].data());
|
||||
attribute.length = buffers[attribute.buffer].size();
|
||||
attribute.pointer = (void*) (buffers[attribute.buffer].data());
|
||||
}
|
||||
}
|
||||
void uf::Mesh::_resizeVs( uf::Mesh::Input& input, size_t count ) {
|
||||
if ( isInterleaved(input.interleaved) ) {
|
||||
buffers[input.interleaved].resize( count * input.stride );
|
||||
for ( auto& attribute : input.attributes ) {
|
||||
attribute.descriptor.length = buffers[input.interleaved].size();
|
||||
attribute.descriptor.pointer = (void*) (buffers[input.interleaved].data());
|
||||
attribute.length = buffers[input.interleaved].size();
|
||||
attribute.pointer = (void*) (buffers[input.interleaved].data());
|
||||
}
|
||||
} else for ( auto& attribute : input.attributes ) {
|
||||
buffers[attribute.buffer].resize( count * attribute.descriptor.size );
|
||||
attribute.descriptor.length = buffers[attribute.buffer].size();
|
||||
attribute.descriptor.pointer = (void*) (buffers[attribute.buffer].data());
|
||||
attribute.length = buffers[attribute.buffer].size();
|
||||
attribute.pointer = (void*) (buffers[attribute.buffer].data());
|
||||
}
|
||||
}
|
||||
void uf::Mesh::_insertV( uf::Mesh::Input& input, const void* data ) {
|
||||
@ -400,14 +424,14 @@ void uf::Mesh::_bindI( uf::Mesh::Input& input, size_t size, ext::RENDERER::enums
|
||||
void uf::Mesh::_reserveIs( uf::Mesh::Input& input, size_t count, size_t i ) {
|
||||
auto& attribute = input.attributes[i];
|
||||
buffers[attribute.buffer].reserve( count * attribute.descriptor.size );
|
||||
attribute.descriptor.length = buffers[attribute.buffer].size();
|
||||
attribute.descriptor.pointer = (void*) (buffers[attribute.buffer].data());
|
||||
attribute.length = buffers[attribute.buffer].size();
|
||||
attribute.pointer = (void*) (buffers[attribute.buffer].data());
|
||||
}
|
||||
void uf::Mesh::_resizeIs( uf::Mesh::Input& input, size_t count, size_t i ) {
|
||||
auto& attribute = input.attributes[i];
|
||||
buffers[attribute.buffer].resize( count * attribute.descriptor.size );
|
||||
attribute.descriptor.length = buffers[attribute.buffer].size();
|
||||
attribute.descriptor.pointer = (void*) (buffers[attribute.buffer].data());
|
||||
attribute.length = buffers[attribute.buffer].size();
|
||||
attribute.pointer = (void*) (buffers[attribute.buffer].data());
|
||||
}
|
||||
void uf::Mesh::_insertI( uf::Mesh::Input& input, const void* data, size_t i ) {
|
||||
auto& attribute = input.attributes[i];
|
||||
|
||||
@ -369,9 +369,9 @@ void ext::BakingBehavior::initialize( uf::Object& self ) {
|
||||
|
||||
// standard pipeline
|
||||
{
|
||||
uf::stl::string vertexShaderFilename = "/gltf/baking/bake.vert.spv";
|
||||
uf::stl::string vertexShaderFilename = "/graph/baking/bake.vert.spv";
|
||||
uf::stl::string geometryShaderFilename = "";
|
||||
uf::stl::string fragmentShaderFilename = "/gltf/baking/bake.frag.spv";
|
||||
uf::stl::string fragmentShaderFilename = "/graph/baking/bake.frag.spv";
|
||||
if ( uf::renderer::settings::experimental::deferredSampling ) {
|
||||
fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", "deferredSampling.frag" );
|
||||
}
|
||||
|
||||
@ -64,6 +64,10 @@ void ext::LightBehavior::initialize( uf::Object& self ) {
|
||||
|
||||
auto& renderMode = this->getComponent<uf::renderer::RenderTargetRenderMode>();
|
||||
renderMode.metadata.type = "depth";
|
||||
renderMode.metadata.pipeline = "depth";
|
||||
if ( uf::renderer::settings::experimental::culling ) {
|
||||
renderMode.metadata.pipelines.emplace_back("culling");
|
||||
}
|
||||
renderMode.metadata.json["descriptor"]["depth bias"] = metadataJson["light"]["bias"];
|
||||
renderMode.metadata.json["descriptor"]["renderMode"] = metadataJson["renderMode"];
|
||||
|
||||
@ -84,6 +88,7 @@ void ext::LightBehavior::initialize( uf::Object& self ) {
|
||||
} else {
|
||||
size = pod::Vector2ui{ uf::renderer::settings::width, uf::renderer::settings::height };
|
||||
}
|
||||
if ( radius.y < radius.x ) radius.y = 256;
|
||||
camera.setProjection( uf::matrix::perspective( fov, (float) size.x / (float) size.y, radius.x, radius.y ) );
|
||||
camera.update(true);
|
||||
|
||||
|
||||
@ -241,7 +241,8 @@ void ext::PlayerBehavior::tick( uf::Object& self ) {
|
||||
if ( stats.menu == "" && keys.paused ) {
|
||||
stats.menu = "paused";
|
||||
metadata.system.control = false;
|
||||
uf::hooks.call("menu:Pause");
|
||||
uf::Serializer payload;
|
||||
uf::hooks.call("menu:Pause", payload);
|
||||
}
|
||||
else if ( !metadata.system.control ) {
|
||||
stats.menu = "menu";
|
||||
|
||||
@ -67,17 +67,14 @@ void ext::ExtSceneBehavior::initialize( uf::Object& self ) {
|
||||
if ( !timer.running() ) timer.start( uf::Time<>(-1000000) );
|
||||
if ( timer.elapsed().asDouble() < 1 ) return;
|
||||
timer.reset();
|
||||
|
||||
uf::Object* manager = (uf::Object*) this->globalFindByName("Gui Manager");
|
||||
if ( !manager ) return;
|
||||
uf::Serializer payload;
|
||||
uf::stl::string config = metadataJson["menus"]["pause"].is<uf::stl::string>() ? metadataJson["menus"]["pause"].as<uf::stl::string>() : "/scenes/worldscape/gui/pause/menu.json";
|
||||
uf::stl::string config = metadataJson["menus"]["pause"].as<uf::stl::string>("/entites/gui/pause/menu.json");
|
||||
uf::Object& gui = manager->loadChild(config, false);
|
||||
payload["uid"] = gui.getUid();
|
||||
|
||||
uf::Serializer& metadataJson = gui.getComponent<uf::Serializer>();
|
||||
metadataJson["menu"] = json["menu"];
|
||||
|
||||
gui.initialize();
|
||||
});
|
||||
this->addHook( "world:Entity.LoadAsset", [&](ext::json::Value& json){
|
||||
@ -318,6 +315,159 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
|
||||
metadata.shader.parameters[metadata.shader.time] = uf::physics::time::current;
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
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::VoxelizerBehavior::Metadata>();
|
||||
auto& metadataJson = this->getComponent<uf::Serializer>();
|
||||
|
||||
struct LightInfo {
|
||||
uf::Entity* entity = NULL;
|
||||
pod::Vector3f position = {0,0,0};
|
||||
float range = 0.0f;
|
||||
pod::Vector3f color = {0,0,0};
|
||||
float intensity = 0.0f;
|
||||
float distance = 0;
|
||||
float bias = 0;
|
||||
int32_t type = 0;
|
||||
bool shadows = false;
|
||||
};
|
||||
|
||||
uf::stl::vector<LightInfo> entities; entities.reserve(graph.size() / 2);
|
||||
|
||||
uf::graph::storage.lights.clear(); uf::graph::storage.lights.reserve(metadata.max.lights);
|
||||
uf::graph::storage.shadow2Ds.clear(); uf::graph::storage.shadow2Ds.reserve(metadata.max.lights);
|
||||
uf::graph::storage.shadowCubes.clear(); uf::graph::storage.shadowCubes.reserve(metadata.max.lights);
|
||||
|
||||
// traverse scene graph
|
||||
for ( auto entity : graph ) {
|
||||
// ignore this scene, our controller, and anything that isn't actually a light
|
||||
if ( entity == this || entity == &controller || !entity->hasComponent<ext::LightBehavior::Metadata>() ) continue;
|
||||
auto& metadata = entity->getComponent<ext::LightBehavior::Metadata>();
|
||||
// disables shadow mappers that activate when in range
|
||||
bool hasRT = entity->hasComponent<uf::renderer::RenderTargetRenderMode>();
|
||||
if ( hasRT ) {
|
||||
auto& renderMode = entity->getComponent<uf::renderer::RenderTargetRenderMode>();
|
||||
if ( metadata.renderer.mode == "in-range" ) renderMode.execute = false;
|
||||
}
|
||||
if ( metadata.power <= 0 ) continue;
|
||||
auto flatten = uf::transform::flatten( entity->getComponent<pod::Transform<>>() );
|
||||
LightInfo& info = entities.emplace_back(LightInfo{
|
||||
.entity = entity,
|
||||
.position = flatten.position,
|
||||
.range = 0,
|
||||
.color = pod::Vector4f{ metadata.color.x, metadata.color.y, metadata.color.z },
|
||||
.intensity = metadata.power,
|
||||
.distance = uf::vector::magnitude( uf::vector::subtract( flatten.position, controllerTransform.position ) ),
|
||||
.bias = metadata.bias,
|
||||
.type = metadata.type,
|
||||
.shadows = metadata.shadows && hasRT,
|
||||
});
|
||||
}
|
||||
// prioritize closer lights; it would be nice to also prioritize lights in view, but because of VXGI it's not really something to do
|
||||
std::sort( entities.begin(), entities.end(), [&]( LightInfo& l, LightInfo& r ){
|
||||
return l.distance < r.distance;
|
||||
});
|
||||
|
||||
int32_t shadowUpdateThreshold = metadata.shadow.update; // how many shadow maps we should update, based on range
|
||||
int32_t shadowCount = metadata.shadow.max; // how many shadow maps we should pass, based on range
|
||||
if ( shadowCount <= 0 ) shadowCount = std::numeric_limits<int32_t>::max();
|
||||
|
||||
// disable shadows if that light is outside our threshold
|
||||
for ( auto& info : entities ) if ( info.shadows && shadowCount-- <= 0 ) info.shadows = false;
|
||||
|
||||
// bind lighting and requested shadow maps
|
||||
for ( uint32_t i = 0; i < entities.size() && uf::graph::storage.lights.size() < metadata.max.lights; ++i ) {
|
||||
auto& info = entities[i];
|
||||
uf::Entity* entity = info.entity;
|
||||
|
||||
if ( !info.shadows ) {
|
||||
uf::graph::storage.lights.emplace_back(pod::Light{
|
||||
.view = uf::matrix::identity(),
|
||||
.projection = uf::matrix::identity(),
|
||||
.position = info.position,
|
||||
.range = info.range,
|
||||
.color = info.color,
|
||||
.intensity = info.intensity,
|
||||
.type = info.type,
|
||||
.typeMap = 0,
|
||||
.indexMap = -1,
|
||||
.depthBias = info.bias,
|
||||
});
|
||||
} else {
|
||||
auto& renderMode = entity->getComponent<uf::renderer::RenderTargetRenderMode>();
|
||||
auto& lightCamera = entity->getComponent<uf::Camera>();
|
||||
auto& lightMetadata = entity->getComponent<ext::LightBehavior::Metadata>();
|
||||
lightMetadata.renderer.rendered = true;
|
||||
// activate our shadow mapper if it's range-basedd
|
||||
if ( lightMetadata.renderer.mode == "in-range" && shadowUpdateThreshold-- > 0 ) renderMode.execute = true;
|
||||
// if point light, and combining is requested
|
||||
if ( metadata.shadow.experimentalMode > 0 && renderMode.renderTarget.views == 6 ) {
|
||||
int32_t index = -1;
|
||||
// separated texture2Ds
|
||||
if ( metadata.shadow.experimentalMode == 2 ) {
|
||||
index = uf::graph::storage.shadow2Ds.size();
|
||||
for ( auto& attachment : renderMode.renderTarget.attachments ) {
|
||||
if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
|
||||
for ( size_t view = 0; view < renderMode.renderTarget.views; ++view ) {
|
||||
uf::graph::storage.shadow2Ds.emplace_back().aliasAttachment(attachment, view);
|
||||
}
|
||||
break;
|
||||
}
|
||||
// cubemapped
|
||||
} else {
|
||||
index = uf::graph::storage.shadowCubes.size();
|
||||
for ( auto& attachment : renderMode.renderTarget.attachments ) {
|
||||
if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
|
||||
uf::graph::storage.shadowCubes.emplace_back().aliasAttachment(attachment);
|
||||
break;
|
||||
}
|
||||
}
|
||||
uf::graph::storage.lights.emplace_back(pod::Light{
|
||||
.view = lightCamera.getView(0),
|
||||
.projection = lightCamera.getProjection(0),
|
||||
.position = info.position,
|
||||
.range = info.range,
|
||||
.color = info.color,
|
||||
.intensity = info.intensity,
|
||||
.type = info.type,
|
||||
.typeMap = metadata.shadow.experimentalMode,
|
||||
.indexMap = index,
|
||||
.depthBias = info.bias,
|
||||
});
|
||||
// any other shadowing light, even point lights, are split by shadow maps
|
||||
} else {
|
||||
for ( auto& attachment : renderMode.renderTarget.attachments ) {
|
||||
if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
|
||||
if ( attachment.descriptor.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) continue;
|
||||
for ( size_t view = 0; view < renderMode.renderTarget.views; ++view ) {
|
||||
uf::graph::storage.lights.emplace_back(pod::Light{
|
||||
.view = lightCamera.getView(view),
|
||||
.projection = lightCamera.getProjection(view),
|
||||
.position = info.position,
|
||||
.range = info.range,
|
||||
.color = info.color,
|
||||
.intensity = info.intensity,
|
||||
.type = info.type,
|
||||
.typeMap = 0,
|
||||
.indexMap = uf::graph::storage.shadow2Ds.size(),
|
||||
.depthBias = info.bias,
|
||||
});
|
||||
uf::graph::storage.shadow2Ds.emplace_back().aliasAttachment(attachment, view);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uf::graph::storage.buffers.light.update( (const void*) uf::graph::storage.lights.data(), uf::graph::storage.lights.size() * sizeof(pod::Light) );
|
||||
}
|
||||
|
||||
/* Update lights */ if ( !uf::renderer::settings::experimental::vxgi ) {
|
||||
ext::ExtSceneBehavior::bindBuffers( *this );
|
||||
}
|
||||
@ -535,18 +685,6 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string
|
||||
alignas(4) uint32_t indexSkybox;
|
||||
};
|
||||
|
||||
struct LightInfo {
|
||||
uf::Entity* entity = NULL;
|
||||
pod::Vector4f color = {0,0,0,0};
|
||||
pod::Vector3f position = {0,0,0};
|
||||
float distance = 0;
|
||||
float bias = 0;
|
||||
int32_t type = 0;
|
||||
bool shadows = false;
|
||||
};
|
||||
uf::stl::vector<LightInfo> entities;
|
||||
entities.reserve(graph.size() / 2);
|
||||
|
||||
// struct that contains our skybox cubemap, noise texture, and VXGI voxels
|
||||
auto& sceneTextures = this->getComponent<pod::SceneTextures>();
|
||||
uf::stl::vector<uf::renderer::Texture> textures2D;
|
||||
@ -558,174 +696,19 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string
|
||||
uf::stl::vector<uf::renderer::Texture> texturesCube;
|
||||
texturesCube.reserve( metadata.max.texturesCube );
|
||||
|
||||
// lighting information
|
||||
uf::stl::vector<pod::Light> lights;
|
||||
lights.reserve( metadata.max.lights );
|
||||
|
||||
// material information
|
||||
uf::stl::vector<pod::Material> materials;
|
||||
materials.reserve( metadata.max.textures2D );
|
||||
materials.emplace_back().colorBase = {0,0,0,0}; // setup our fallback material information
|
||||
// texture information
|
||||
uf::stl::vector<pod::Texture> textures;
|
||||
textures.reserve( metadata.max.textures2D );
|
||||
// drawcall information
|
||||
uf::stl::vector<pod::DrawCommand> drawCommands;
|
||||
drawCommands.reserve( metadata.max.textures2D );
|
||||
|
||||
// bind materials
|
||||
for ( auto pair : uf::graph::storage.materials ) materials.emplace_back(pair.second);
|
||||
for ( auto pair : uf::graph::storage.textures ) textures.emplace_back(pair.second);
|
||||
// bind textures
|
||||
// bind texture2Ds
|
||||
for ( auto pair : uf::graph::storage.images ) {
|
||||
auto& image = pair.second;
|
||||
auto& texture2D = uf::graph::storage.texture2Ds[pair.first];
|
||||
if ( !texture2D.generated() ) texture2D.loadFromImage( pair.second );
|
||||
textures2D.emplace_back().aliasTexture(texture2D);
|
||||
}
|
||||
|
||||
// traverse scene graph
|
||||
for ( auto entity : graph ) {
|
||||
// needed to grab our necessary materials/texture information, until i add it globally
|
||||
#if 0
|
||||
if ( entity->hasComponent<pod::Graph>() ) {
|
||||
auto& graph = entity->getComponent<pod::Graph>();
|
||||
// pass our draw call information, necessary in shader
|
||||
/*
|
||||
drawCommands.emplace_back(pod::DrawCall{
|
||||
materials.size(),
|
||||
textures.size(),
|
||||
textures2D.size(),
|
||||
0,
|
||||
});
|
||||
*/
|
||||
// pass material information
|
||||
for ( auto& material : graph.materials ) {
|
||||
materials.emplace_back( uf::graph::storage.materials[material] );
|
||||
}
|
||||
// pass texture information
|
||||
for ( auto& texture : graph.textures ) {
|
||||
textures.emplace_back( uf::graph::storage.textures[texture] );
|
||||
// attach the actual texture if the texture information requests it
|
||||
// if ( texture.bind ) textures2D.emplace_back().aliasTexture(texture.texture);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// ignore this scene, our controller, and anything that isn't actually a light
|
||||
if ( entity == this || entity == &controller || !entity->hasComponent<ext::LightBehavior::Metadata>() ) continue;
|
||||
auto& metadata = entity->getComponent<ext::LightBehavior::Metadata>();
|
||||
// disables shadow mappers that activate when in range
|
||||
bool hasRT = entity->hasComponent<uf::renderer::RenderTargetRenderMode>();
|
||||
if ( hasRT ) {
|
||||
auto& renderMode = entity->getComponent<uf::renderer::RenderTargetRenderMode>();
|
||||
if ( metadata.renderer.mode == "in-range" ) renderMode.execute = false;
|
||||
}
|
||||
if ( metadata.power <= 0 ) continue;
|
||||
auto flatten = uf::transform::flatten( entity->getComponent<pod::Transform<>>() );
|
||||
LightInfo& info = entities.emplace_back(LightInfo{
|
||||
.entity = entity,
|
||||
.color = pod::Vector4f{ metadata.color.x, metadata.color.y, metadata.color.z, metadata.power },
|
||||
.position = flatten.position,
|
||||
.distance = uf::vector::magnitude( uf::vector::subtract( flatten.position, controllerTransform.position ) ),
|
||||
.bias = metadata.bias,
|
||||
.type = metadata.type,
|
||||
.shadows = metadata.shadows && hasRT,
|
||||
});
|
||||
}
|
||||
// prioritize closer lights; it would be nice to also prioritize lights in view, but because of VXGI it's not really something to do
|
||||
std::sort( entities.begin(), entities.end(), [&]( LightInfo& l, LightInfo& r ){
|
||||
return l.distance < r.distance;
|
||||
});
|
||||
|
||||
int32_t shadowUpdateThreshold = metadata.shadow.update; // how many shadow maps we should update, based on range
|
||||
int32_t shadowCount = metadata.shadow.max; // how many shadow maps we should pass, based on range
|
||||
if ( shadowCount <= 0 ) shadowCount = std::numeric_limits<int32_t>::max();
|
||||
|
||||
// disable shadows if that light is outside our threshold
|
||||
for ( auto& info : entities ) if ( info.shadows && shadowCount-- <= 0 ) info.shadows = false;
|
||||
// bind scene textures
|
||||
for ( auto& key : uf::graph::storage.texture2Ds.keys ) textures2D.emplace_back().aliasTexture( uf::graph::storage.texture2Ds.map[key] );
|
||||
|
||||
// bind shadow maps
|
||||
for ( auto& texture : uf::graph::storage.shadow2Ds ) textures2D.emplace_back().aliasTexture(texture);
|
||||
for ( auto& texture : uf::graph::storage.shadowCubes ) texturesCube.emplace_back().aliasTexture(texture);
|
||||
|
||||
// bind skybox
|
||||
size_t indexSkybox = texturesCube.size();
|
||||
texturesCube.emplace_back().aliasTexture(sceneTextures.skybox);
|
||||
// bind noise texture
|
||||
size_t indexNoise = textures3D.size();
|
||||
textures3D.emplace_back().aliasTexture(sceneTextures.noise);
|
||||
// bind lighting and requested shadow maps
|
||||
for ( uint32_t i = 0; i < entities.size() && lights.size() < metadata.max.lights; ++i ) {
|
||||
auto& info = entities[i];
|
||||
uf::Entity* entity = info.entity;
|
||||
|
||||
if ( !info.shadows ) {
|
||||
lights.emplace_back(pod::Light{
|
||||
.view = uf::matrix::identity(),
|
||||
.projection = uf::matrix::identity(),
|
||||
.position = info.position,
|
||||
.color = info.color,
|
||||
.type = info.type,
|
||||
.typeMap = 0,
|
||||
.indexMap = -1,
|
||||
.depthBias = info.bias,
|
||||
});
|
||||
} else {
|
||||
auto& renderMode = entity->getComponent<uf::renderer::RenderTargetRenderMode>();
|
||||
auto& lightCamera = entity->getComponent<uf::Camera>();
|
||||
auto& lightMetadata = entity->getComponent<ext::LightBehavior::Metadata>();
|
||||
lightMetadata.renderer.rendered = true;
|
||||
// activate our shadow mapper if it's range-basedd
|
||||
if ( lightMetadata.renderer.mode == "in-range" && shadowUpdateThreshold-- > 0 ) renderMode.execute = true;
|
||||
// if point light, and combining is requested
|
||||
if ( metadata.shadow.experimentalMode > 0 && renderMode.renderTarget.views == 6 ) {
|
||||
int32_t index = -1;
|
||||
// separated texture2Ds
|
||||
if ( metadata.shadow.experimentalMode == 2 ) {
|
||||
index = textures2D.size();
|
||||
for ( auto& attachment : renderMode.renderTarget.attachments ) {
|
||||
if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
|
||||
for ( size_t view = 0; view < renderMode.renderTarget.views; ++view ) {
|
||||
textures2D.emplace_back().aliasAttachment(attachment, view);
|
||||
}
|
||||
break;
|
||||
}
|
||||
// cubemapped
|
||||
} else {
|
||||
index = texturesCube.size();
|
||||
for ( auto& attachment : renderMode.renderTarget.attachments ) {
|
||||
if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
|
||||
texturesCube.emplace_back().aliasAttachment(attachment);
|
||||
break;
|
||||
}
|
||||
}
|
||||
lights.emplace_back(pod::Light{
|
||||
.view = lightCamera.getView(0),
|
||||
.projection = lightCamera.getProjection(0),
|
||||
.position = info.position,
|
||||
.color = info.color,
|
||||
.type = info.type,
|
||||
.typeMap = metadata.shadow.experimentalMode,
|
||||
.indexMap = index,
|
||||
.depthBias = info.bias,
|
||||
});
|
||||
// any other shadowing light, even point lights, are split by shadow maps
|
||||
} else {
|
||||
for ( auto& attachment : renderMode.renderTarget.attachments ) {
|
||||
if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
|
||||
if ( attachment.descriptor.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) continue;
|
||||
for ( size_t view = 0; view < renderMode.renderTarget.views; ++view ) {
|
||||
lights.emplace_back(pod::Light{
|
||||
.view = lightCamera.getView(view),
|
||||
.projection = lightCamera.getProjection(view),
|
||||
.position = info.position,
|
||||
.color = info.color,
|
||||
.type = info.type,
|
||||
.typeMap = 0,
|
||||
.indexMap = textures2D.size(),
|
||||
.depthBias = info.bias,
|
||||
});
|
||||
textures2D.emplace_back().aliasAttachment(attachment, view);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// attach VXGI voxels
|
||||
if ( uf::renderer::settings::experimental::vxgi ) {
|
||||
@ -781,10 +764,10 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string
|
||||
};
|
||||
|
||||
uniforms.lengths = UniformDescriptor::Lengths{
|
||||
.lights = MIN( lights.size(), metadata.max.lights ),
|
||||
.materials = MIN( materials.size(), metadata.max.textures2D ),
|
||||
.textures = MIN( textures.size(), metadata.max.textures2D ),
|
||||
// .drawCommands = MIN( drawCommands.size(), metadata.max.textures2D ),
|
||||
.lights = MIN( uf::graph::storage.lights.size(), metadata.max.lights ),
|
||||
.materials = MIN( uf::graph::storage.materials.keys.size(), metadata.max.textures2D ),
|
||||
.textures = MIN( uf::graph::storage.textures.keys.size(), metadata.max.textures2D ),
|
||||
.drawCommands = MIN( 0, metadata.max.textures2D ),
|
||||
};
|
||||
|
||||
uniforms.ambient = metadata.light.ambient;
|
||||
@ -793,7 +776,7 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string
|
||||
uniforms.exposure = metadata.light.exposure;
|
||||
uniforms.msaa = ext::vulkan::settings::msaa;
|
||||
uniforms.shadowSamples = std::min( 0, metadata.shadow.samples );
|
||||
uniforms.indexSkybox = 0;
|
||||
uniforms.indexSkybox = indexSkybox;
|
||||
}
|
||||
|
||||
for ( auto* blitter : blitters ) {
|
||||
@ -817,25 +800,9 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string
|
||||
if ( previousTextures[i] != graphic.material.textures[i].image )
|
||||
shouldUpdate = true;
|
||||
}
|
||||
|
||||
// update lighting buffer
|
||||
shader.updateBuffer( (const void*) lights.data(), uniforms.lengths.lights * sizeof(pod::Light), renderMode.metadata.lightBufferIndex, false );
|
||||
//
|
||||
if ( shouldUpdate ) {
|
||||
shader.updateBuffer( (const void*) materials.data(), uniforms.lengths.materials * sizeof(pod::Material), renderMode.metadata.materialBufferIndex, false );
|
||||
shader.updateBuffer( (const void*) textures.data(), uniforms.lengths.textures * sizeof(pod::Texture), renderMode.metadata.textureBufferIndex, false );
|
||||
shader.updateBuffer( (const void*) drawCommands.data(), uniforms.lengths.drawCommands * sizeof(pod::DrawCommand), renderMode.metadata.drawCallBufferIndex, false );
|
||||
|
||||
graphic.updatePipelines();
|
||||
}
|
||||
if ( shouldUpdate ) graphic.updatePipelines();
|
||||
|
||||
// shader.updateBuffer( (const void*) &uniforms, sizeof(uniforms), shader.getUniformBuffer("UBO") );
|
||||
shader.updateBuffer( uniforms, shader.getUniformBuffer("UBO") );
|
||||
/*
|
||||
auto& uniform = shader.getUniform("UBO");
|
||||
memcpy( (void*) uniform, &uniforms, sizeof(uniforms) );
|
||||
shader.updateUniform( "UBO", uniform );
|
||||
*/
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -82,6 +82,11 @@ void ext::VoxelizerBehavior::initialize( uf::Object& self ) {
|
||||
uf::renderer::addRenderMode( &renderMode, metadata.renderModeName );
|
||||
|
||||
renderMode.metadata.type = "vxgi";
|
||||
renderMode.metadata.pipeline = "vxgi";
|
||||
renderMode.metadata.pipelines.emplace_back("vxgi");
|
||||
if ( uf::renderer::settings::experimental::culling ) {
|
||||
renderMode.metadata.pipelines.emplace_back("culling");
|
||||
}
|
||||
renderMode.metadata.samples = 1;
|
||||
renderMode.metadata.subpasses = metadata.cascades;
|
||||
|
||||
@ -99,6 +104,11 @@ void ext::VoxelizerBehavior::initialize( uf::Object& self ) {
|
||||
renderMode.metadata.json["shaders"]["compute"] = computeShaderFilename;
|
||||
renderMode.blitter.descriptor.renderMode = metadata.renderModeName;
|
||||
renderMode.blitter.descriptor.subpass = -1;
|
||||
renderMode.blitter.descriptor.inputs.dispatch = {
|
||||
(metadata.voxelSize.x / metadata.dispatchSize.x),
|
||||
(metadata.voxelSize.y / metadata.dispatchSize.y),
|
||||
(metadata.voxelSize.z / metadata.dispatchSize.z),
|
||||
};
|
||||
renderMode.blitter.process = true;
|
||||
|
||||
size_t maxTextures2D = ext::config["engine"]["scenes"]["textures"]["max"]["2D"].as<size_t>(512);
|
||||
@ -136,7 +146,7 @@ void ext::VoxelizerBehavior::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);
|
||||
// vkCmdDispatch(commandBuffer, metadata.voxelSize.x / metadata.dispatchSize.x, metadata.voxelSize.y / metadata.dispatchSize.y, metadata.voxelSize.z / metadata.dispatchSize.z);
|
||||
}
|
||||
|
||||
// generate mipmaps
|
||||
@ -198,7 +208,6 @@ void ext::VoxelizerBehavior::tick( uf::Object& self ) {
|
||||
controllerPosition.y = floor(controllerPosition.y);
|
||||
controllerPosition.z = floor(controllerPosition.z);
|
||||
controllerPosition += metadata.extents.min;
|
||||
|
||||
controllerPosition.x = floor(controllerPosition.x);
|
||||
controllerPosition.y = floor(controllerPosition.y);
|
||||
controllerPosition.z = -floor(controllerPosition.z);
|
||||
|
||||
@ -349,7 +349,10 @@ void ext::Gui::load( const uf::Image& image ) {
|
||||
}
|
||||
metadataJson["cull mode"] = "none";
|
||||
graphic.descriptor.parse( metadataJson );
|
||||
|
||||
if ( uf::matrix::reverseInfiniteProjection ) {
|
||||
} else {
|
||||
metadata.depth = -metadata.depth;
|
||||
}
|
||||
if ( metadataJson["flip uv"].as<bool>() ) for ( auto& v : vertices ) v.uv.y = 1 - v.uv.y;
|
||||
if ( metadata.depth != 0.0f ) for ( auto& v : vertices ) v.position.z = metadata.depth;
|
||||
|
||||
@ -816,7 +819,8 @@ void ext::GuiBehavior::tick( uf::Object& self ) {
|
||||
.color = metadata.color,
|
||||
|
||||
.mode = metadata.shader,
|
||||
.depth = 1 - metadata.depth,
|
||||
// .depth = 1 - metadata.depth,
|
||||
.depth = uf::matrix::reverseInfiniteProjection ? 1 - metadata.depth : metadata.depth,
|
||||
};
|
||||
// set glyph-based uniforms
|
||||
if ( isGlyph && uniform.size() == sizeof(::GlyphUniformDescriptor<>) ) {
|
||||
|
||||
24
ext/main.cpp
24
ext/main.cpp
@ -24,6 +24,7 @@
|
||||
#include <uf/utils/http/http.h>
|
||||
|
||||
#include <uf/engine/entity/entity.h>
|
||||
#include <uf/engine/graph/graph.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
@ -241,6 +242,10 @@ void EXT_API ext::initialize() {
|
||||
}
|
||||
uf::allocator::override = ::config["engine"]["memory pool"]["override"].as( uf::allocator::override );
|
||||
}
|
||||
{
|
||||
uf::Mesh::defaultInterleaved = ::config["engine"]["scenes"]["meshes"]["interleaved"].as( uf::Mesh::defaultInterleaved );
|
||||
uf::matrix::reverseInfiniteProjection = ::config["engine"]["scenes"]["matrix"]["reverseInfinite"].as( uf::matrix::reverseInfiniteProjection );
|
||||
}
|
||||
|
||||
/* Create initial scene (kludge) */ {
|
||||
uf::Scene& scene = uf::instantiator::instantiate<uf::Scene>(); //new uf::Scene;
|
||||
@ -348,6 +353,7 @@ void EXT_API ext::initialize() {
|
||||
uf::renderer::settings::experimental::hdr = ::config["engine"]["ext"][RENDERER]["experimental"]["hdr"].as( uf::renderer::settings::experimental::hdr );
|
||||
uf::renderer::settings::experimental::vxgi = ::config["engine"]["ext"][RENDERER]["experimental"]["vxgi"].as( uf::renderer::settings::experimental::vxgi );
|
||||
uf::renderer::settings::experimental::deferredSampling = ::config["engine"]["ext"][RENDERER]["experimental"]["deferred sampling"].as( uf::renderer::settings::experimental::deferredSampling );
|
||||
uf::renderer::settings::experimental::culling = ::config["engine"]["ext"][RENDERER]["experimental"]["culling"].as( uf::renderer::settings::experimental::culling );
|
||||
#define JSON_TO_VKFORMAT( key ) if ( ::config["engine"]["ext"][RENDERER]["formats"][#key].is<uf::stl::string>() ) {\
|
||||
uf::stl::string format = ::config["engine"]["ext"][RENDERER]["formats"][#key].as<uf::stl::string>();\
|
||||
format = uf::string::replace( uf::string::uppercase(format), " ", "_" );\
|
||||
@ -408,7 +414,12 @@ void EXT_API ext::initialize() {
|
||||
if ( ::config["engine"]["render modes"]["deferred"].as<bool>() ) {
|
||||
uf::renderer::addRenderMode( new uf::renderer::DeferredRenderMode, "" );
|
||||
auto& renderMode = uf::renderer::getRenderMode("Deferred", true);
|
||||
if ( ::config["engine"]["render modes"]["stereo deferred"].as<bool>() ) renderMode.metadata.eyes = 2;
|
||||
if ( ::config["engine"]["render modes"]["stereo deferred"].as<bool>() ) {
|
||||
renderMode.metadata.eyes = 2;
|
||||
}
|
||||
if ( uf::renderer::settings::experimental::culling ) {
|
||||
renderMode.metadata.pipelines.emplace_back("culling");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -470,7 +481,6 @@ void EXT_API ext::initialize() {
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
||||
uf::renderer::initialize();
|
||||
}
|
||||
|
||||
@ -622,6 +632,9 @@ void EXT_API ext::tick() {
|
||||
}
|
||||
#endif
|
||||
//UF_TIMER_TRACE("ticking physics");
|
||||
/* Update graph */ {
|
||||
uf::graph::tick();
|
||||
}
|
||||
/* Update entities */ {
|
||||
uf::scene::tick();
|
||||
}
|
||||
@ -740,7 +753,12 @@ void EXT_API ext::terminate() {
|
||||
ext::lua::terminate();
|
||||
}
|
||||
#endif
|
||||
uf::scene::destroy();
|
||||
{
|
||||
uf::graph::destroy();
|
||||
}
|
||||
{
|
||||
uf::scene::destroy();
|
||||
}
|
||||
|
||||
/* Garbage collection */ if ( false ) {
|
||||
uint8_t mode = ::config["engine"]["debug"]["garbage collection"]["mode"].as<uint64_t>();
|
||||
|
||||
@ -1,24 +0,0 @@
|
||||
Stack trace:
|
||||
Frame Function Args
|
||||
000FFFF5848 00180062C9C (000FFFF5A68, 00010000002, 000FFFFCE00, 000FFFFDE50)
|
||||
000FFFF58F0 00180065090 (001800FA0BE, 00100140000, 100000000000101, 00000000000)
|
||||
000FFFF5F70 00180047D1B (00000000000, 00000000000, 00000000000, 00000000000)
|
||||
000FFFF6050 001801711AC (00000000001, 00000000000, 0000000019C, FFFFFFFF00000000)
|
||||
000FFFF99F0 0018014761E (0018035B200, 008000F0610, 008000B36F0, 00000001003)
|
||||
000FFFFAB80 00180148201 (00180352408, 0018037A8A0, 000FFFFAD02, 00000000000)
|
||||
000FFFFAC30 00180065873 (001801B48F6, 000FFFFAE48, 00000000000, FFFFFFFFFFFFFFFF)
|
||||
000FFFFAD90 001801389AB (001801B48F6, 000FFFFAE48, 00000000000, FFFFFFFFFFFFFFFF)
|
||||
000FFFFAD90 0010040E131 (000FFFFAE48, 008000FE8F0, 00000000000, 001FFFFAE48)
|
||||
00100433CA8 0010040E3DB (0080006D408, 008000F0610, 008000ED0A0, 008000B2AF0)
|
||||
00100433CA8 0010040E8E4 (00000000000, 008000E8D43, 00000000008, 008000E8D3A)
|
||||
000FFFFAFF0 0010040F34B (00100000000, 000FFFFB0F0, 00000000000, 00000000001)
|
||||
000FFFFAFF0 0010040FB20 (00000000000, 183A92A3F1E23A87, 000000020C0, 00800063A21)
|
||||
00000000001 0010041A5AF (00100000002, 0010040BA66, 00000000001, 001004335A8)
|
||||
00000000001 0010041A9D9 (0080006CA36, 00000000001, 00000000028, 0080006CF10)
|
||||
00000000001 00100419958 (00800000000, 6176652D2A2D2824, 2D7367616C662D6C, 00000292D2A)
|
||||
001004369F0 0010041ADC7 (00100423B48, 00000000001, 00430B39190, 00000000000)
|
||||
000FFFFB400 00100423FD8 (000FFFFCC90, 00800000160, 00000000000, 00180330BA0)
|
||||
000FFFFCCE0 0018004A01B (00000000000, 00000000000, 00000000000, 00000000000)
|
||||
000FFFFCDA0 0018004794A (00000000000, 00000000000, 00000000000, 00000000000)
|
||||
000FFFFCE50 00180047A0C (00000000000, 00000000000, 00000000000, 00000000000)
|
||||
End of stack trace
|
||||
Loading…
Reference in New Issue
Block a user