Commit for 2022.05.09 00-07-22.7z
This commit is contained in:
parent
c8853dc1b8
commit
cf3d1eebc1
12
Makefile
12
Makefile
@ -51,11 +51,11 @@ LINKS += $(UF_LIBS) $(EXT_LIBS) $(DEPS)
|
||||
DEPS +=
|
||||
|
||||
ifneq (,$(findstring win64,$(ARCH)))
|
||||
REQ_DEPS += $(RENDERER) json:nlohmann png zlib openal ogg freetype curl luajit reactphysics meshoptimizer xatlas simd ctti # ncurses openvr draco discord bullet ultralight-ux
|
||||
REQ_DEPS += $(RENDERER) json:nlohmann png zlib openal ogg freetype curl luajit reactphysics meshoptimizer xatlas simd ctti gltf # ncurses openvr draco discord bullet ultralight-ux
|
||||
FLAGS +=
|
||||
DEPS += -lgdi32
|
||||
else ifneq (,$(findstring dreamcast,$(ARCH)))
|
||||
REQ_DEPS += simd opengl gldc json:nlohmann lua reactphysics png zlib ctti ogg openal aldc # freetype bullet meshoptimizer draco luajit ultralight-ux ncurses curl openvr discord
|
||||
REQ_DEPS += simd opengl gldc json:nlohmann lua reactphysics png zlib ctti ogg openal aldc # gltf freetype bullet meshoptimizer draco luajit ultralight-ux ncurses curl openvr discord
|
||||
endif
|
||||
ifneq (,$(findstring vulkan,$(REQ_DEPS)))
|
||||
FLAGS += -DVK_USE_PLATFORM_WIN32_KHR -DUF_USE_VULKAN
|
||||
@ -91,6 +91,9 @@ ifneq (,$(findstring json,$(REQ_DEPS)))
|
||||
FLAGS += -DUF_JSON_USE_NLOHMANN
|
||||
endif
|
||||
endif
|
||||
ifneq (,$(findstring gltf,$(REQ_DEPS)))
|
||||
FLAGS += -DUF_USE_GLTF
|
||||
endif
|
||||
ifneq (,$(findstring png,$(REQ_DEPS)))
|
||||
FLAGS += -DUF_USE_PNG -DUF_USE_ZLIB
|
||||
DEPS += -lpng -lz
|
||||
@ -252,9 +255,8 @@ $(EXT_EX_DLL): $(OBJS_EXT_DLL)
|
||||
$(KOS_BASE)/utils/bin2o/bin2o ./bin/dreamcast/romdisk.img romdisk ./bin/dreamcast/romdisk.o
|
||||
|
||||
$(TARGET): $(OBJS) #./bin/dreamcast/romdisk.o
|
||||
# $(CXX) -O2 -fomit-frame-pointer -ml -m4-single-only -ffunction-sections -fdata-sections $(KOS_INC_PATHS) $(INCS) -D_arch_dreamcast -D_arch_sub_pristine -Wall -fno-builtin -ml -m4-single-only -Wl,-Ttext=0x8c010000 -Wl,--gc-sections -T/opt/dreamcast/kos/utils/ldscripts/shlelf.xc -nodefaultlibs $(KOS_LIB_PATHS) $(LIBS) -o $(TARGET) $(OBJS) ./bin/dreamcast/romdisk.o -Wl,--start-group $(DEPS) -Wl,--end-group
|
||||
# $(CXX) -O2 -fomit-frame-pointer -ml -m4-single-only -ffunction-sections -fdata-sections $(KOS_INC_PATHS) $(INCS) -D_arch_dreamcast -D_arch_sub_pristine -Wall -fno-builtin -ml -m4-single-only -Wl,-Ttext=0x8c010000 -Wl,--gc-sections -T/opt/dreamcast/kos/utils/ldscripts/shlelf.xc -nodefaultlibs $(KOS_LIB_PATHS) $(LIBS) -o $(TARGET) $(OBJS) -Wl,--start-group $(DEPS) -Wl,--end-group
|
||||
$(CXX) -ffunction-sections -fdata-sections $(KOS_INC_PATHS) $(INCS) -D_arch_dreamcast -D_arch_sub_pristine -Wall -fno-builtin -ml -m4-single-only -Wl,-Ttext=0x8c010000 -Wl,--gc-sections -T/opt/dreamcast/kos/utils/ldscripts/shlelf.xc -nodefaultlibs $(KOS_LIB_PATHS) $(LIBS) -o $(TARGET) $(OBJS) -Wl,--start-group $(DEPS) -Wl,--end-group
|
||||
$(CXX) $(FLAGS) $(INCS) -D_arch_dreamcast -D_arch_sub_pristine -Wall -fno-builtin -ml -m4-single-only -Wl,-Ttext=0x8c010000 -T/opt/dreamcast/kos/utils/ldscripts/shlelf.xc -nodefaultlibs $(KOS_LIB_PATHS) $(LIBS) -o $(TARGET) $(OBJS) -Wl,--start-group $(DEPS) -Wl,--end-group
|
||||
# $(KOS_STRIP) --strip-unneeded $(TARGET)
|
||||
|
||||
./bin/dreamcast/$(TARGET_NAME).cdi: $(TARGET)
|
||||
cd ./bin/dreamcast/; ./elf2cdi.sh $(TARGET_NAME)
|
||||
|
||||
@ -51,6 +51,10 @@
|
||||
"MessageID = 0x124ffb34", // VUID-VkImageMemoryBarrier-oldLayout-01197
|
||||
"MessageID = 0x8ab1932c", // VUID-VkImageViewCreateInfo-imageViewType-04973
|
||||
|
||||
// "MessageID = 0x8e1000ad", // VUID-vkCmdDrawIndexedIndirect-None-04008 (bitches without nullDescriptor)
|
||||
// "MessageID = 0x9dd97212", // VUID-vkCmdDrawIndexedIndirect-None-02721 (bitches without nullDescriptor)
|
||||
// "MessageID = 0x36481fcb", // VUID-vkCmdBindVertexBuffers-pBuffers-04001 (bitches without nullDescriptor)
|
||||
|
||||
"MessageID = 0x4dae5635", // UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout (false positive for cubemaps)
|
||||
// "MessageID = 0x71500fba", // VUID-vkDestroyDevice-device-00378 (don't care about a clean cleanup)
|
||||
"MessageID = 0x609a13b", // UNASSIGNED-CoreValidation-Shader-OutputNotConsumed (from depth-only calls)
|
||||
@ -101,6 +105,8 @@
|
||||
"nullDescriptor",
|
||||
"fragmentStoresAndAtomics",
|
||||
"geometryShader",
|
||||
"multiViewport",
|
||||
"shaderOutputLayer",
|
||||
// "shaderUniformBufferArrayDynamicIndexing",
|
||||
// "shaderStorageBufferArrayDynamicIndexing",
|
||||
"shaderSampledImageArrayDynamicIndexing",
|
||||
@ -112,7 +118,8 @@
|
||||
"VK_KHR_get_surface_capabilities2"
|
||||
],
|
||||
"device": [
|
||||
"VK_KHR_swapchain"
|
||||
"VK_KHR_swapchain",
|
||||
"VK_EXT_shader_viewport_index_layer"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
@ -29,8 +29,9 @@
|
||||
"enabled": false,
|
||||
"resolution": 8192,
|
||||
"shadows": 1024,
|
||||
"layers": 1,
|
||||
"trigger": { "mode": "rendered" },
|
||||
"output": "./lightmap.png"
|
||||
"output": "./lightmap.%i.png"
|
||||
},
|
||||
"grid": {
|
||||
"/^worldspawn/": {
|
||||
@ -40,8 +41,8 @@
|
||||
"print": true
|
||||
}
|
||||
},
|
||||
// "lightmap": "./lightmap.min.png",
|
||||
// "lightmap": "./lightmap.png",
|
||||
// "lightmap": "./lightmap.%i.min.png",
|
||||
// "lightmap": "./lightmap.%i.png",
|
||||
// "filter": "NEAREST",
|
||||
"flags": {
|
||||
"ATLAS": false,
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
// { "filename": "./models/micro_sci.glb", "delay": 0, "single threaded": false, "category": "models" }
|
||||
// { "filename": "./models/micro_sci/graph.json", "delay": 0, "single threaded": false, "category": "models" }
|
||||
// { "filename": "./models/micro_sci/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" }
|
||||
|
||||
// { "filename": "./craeture.json", "delay": 1 }
|
||||
|
||||
// { "filename": "./models/msci.glb", "delay": 0, "single threaded": false, "category": "models" }
|
||||
@ -21,17 +22,26 @@
|
||||
"metadata": {
|
||||
"model": {
|
||||
"exporter": {
|
||||
"enabled": false
|
||||
"enabled": true
|
||||
},
|
||||
"baking": {
|
||||
"enabled": false,
|
||||
"resolution": 8192,
|
||||
"resolution": 2048, // 8192
|
||||
"shadows": 1024,
|
||||
"layers": 22,
|
||||
"trigger": { "mode": "rendered" },
|
||||
"output": "./lightmap.png"
|
||||
// "trigger": { "mode": "key", "value": "B" },
|
||||
"output": "./lightmap.%i.png"
|
||||
},
|
||||
// "lightmap": "./lightmap.min.png",
|
||||
"filter": "NEAREST",
|
||||
"grid": {
|
||||
"/^worldspawn/": {
|
||||
"size": [3,3,3]
|
||||
}
|
||||
},
|
||||
// "lightmap": "./lightmap.%i.min.png",
|
||||
// "lightmap": false,
|
||||
"lightmap": true,
|
||||
"filter": "LINEAR",
|
||||
"tags": {
|
||||
"worldspawn": { "physics": { "type": "mesh", "static": true } },
|
||||
"worldspawn_20": { "physics": { "type": "mesh", "static": true } },
|
||||
|
||||
@ -107,7 +107,7 @@ struct DrawCommand {
|
||||
int vertexID; // starting vertex position
|
||||
|
||||
uint instanceID; // starting instance position
|
||||
uint padding; //
|
||||
uint auxID; //
|
||||
uint materialID; // material to use for this draw call
|
||||
uint vertices; // number of vertices used
|
||||
};
|
||||
@ -131,7 +131,7 @@ struct Instance {
|
||||
int jointID;
|
||||
int lightmapID;
|
||||
uint imageID;
|
||||
uint padding2;
|
||||
uint auxID;
|
||||
|
||||
Bounds bounds;
|
||||
};
|
||||
|
||||
@ -5,9 +5,10 @@
|
||||
|
||||
layout (constant_id = 0) const uint TEXTURES = 512;
|
||||
layout (constant_id = 1) const uint CUBEMAPS = 128;
|
||||
layout (constant_id = 2) const uint LAYERS = 32;
|
||||
|
||||
layout (binding = 4) uniform sampler2D samplerTextures[TEXTURES];
|
||||
layout (binding = 5) uniform samplerCube samplerCubemaps[CUBEMAPS];
|
||||
layout (binding = 5) uniform sampler2D samplerTextures[TEXTURES];
|
||||
layout (binding = 6) uniform samplerCube samplerCubemaps[CUBEMAPS];
|
||||
|
||||
#define SHADOW_SAMPLES 16
|
||||
#define FRAGMENT 1
|
||||
@ -18,19 +19,21 @@ layout (binding = 5) uniform samplerCube samplerCubemaps[CUBEMAPS];
|
||||
#include "../../common/macros.h"
|
||||
#include "../../common/structs.h"
|
||||
|
||||
layout (std140, binding = 6) readonly buffer Instances {
|
||||
layout (std140, binding = 7) readonly buffer Instances {
|
||||
Instance instances[];
|
||||
};
|
||||
layout (std140, binding = 7) readonly buffer Materials {
|
||||
layout (std140, binding = 8) readonly buffer Materials {
|
||||
Material materials[];
|
||||
};
|
||||
layout (std140, binding = 8) readonly buffer Textures {
|
||||
layout (std140, binding = 9) readonly buffer Textures {
|
||||
Texture textures[];
|
||||
};
|
||||
layout (std140, binding = 9) readonly buffer Lights {
|
||||
layout (std140, binding = 10) readonly buffer Lights {
|
||||
Light lights[];
|
||||
};
|
||||
|
||||
layout (binding = 11, rgba8) uniform volatile coherent image3D outAlbedos;
|
||||
|
||||
#include "../../common/functions.h"
|
||||
#include "../../common/shadows.h"
|
||||
#if PBR
|
||||
@ -44,6 +47,7 @@ layout (location = 3) in vec3 inNormal;
|
||||
layout (location = 4) in mat3 inTBN;
|
||||
layout (location = 7) in vec3 inPosition;
|
||||
layout (location = 8) flat in uvec4 inId;
|
||||
layout (location = 9) flat in uint inLayer;
|
||||
|
||||
layout (location = 0) out vec4 outAlbedo;
|
||||
|
||||
@ -115,4 +119,10 @@ void main() {
|
||||
// surface.fragment.rgb = pow(surface.fragment.rgb, vec3(1.0 / GAMMA));
|
||||
|
||||
outAlbedo = vec4(surface.fragment.rgb, 1);
|
||||
|
||||
{
|
||||
const vec2 st = inSt.xy * imageSize(outAlbedos).xy;
|
||||
const ivec3 uvw = ivec3(int(st.x), int(st.y), int(inLayer));
|
||||
imageStore(outAlbedos, uvw, vec4(surface.fragment.rgb, 1) );
|
||||
}
|
||||
}
|
||||
42
bin/data/shaders/graph/baking/bake.geom.glsl
Normal file
42
bin/data/shaders/graph/baking/bake.geom.glsl
Normal file
@ -0,0 +1,42 @@
|
||||
#version 450
|
||||
#pragma shader_stage(geometry)
|
||||
|
||||
layout(triangles) in;
|
||||
layout(triangle_strip, max_vertices = 3) out;
|
||||
|
||||
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 uvec4 inId[];
|
||||
layout (location = 9) flat in uint inLayer[];
|
||||
|
||||
layout (location = 0) out vec2 outUv;
|
||||
layout (location = 1) out vec2 outSt;
|
||||
layout (location = 2) out vec4 outColor;
|
||||
layout (location = 3) out vec3 outNormal;
|
||||
layout (location = 4) out mat3 outTBN;
|
||||
layout (location = 7) out vec3 outPosition;
|
||||
layout (location = 8) flat out uvec4 outId;
|
||||
layout (location = 9) flat out uint outLayer;
|
||||
|
||||
void main(){
|
||||
for( uint i = 0; i < 3; ++i ){
|
||||
outUv = inUv[i];
|
||||
outSt = inSt[i];
|
||||
outColor = inColor[i];
|
||||
outNormal = inNormal[i];
|
||||
outTBN = inTBN[i];
|
||||
outPosition = inPosition[i];
|
||||
outId = inId[i];
|
||||
outLayer = inLayer[i];
|
||||
|
||||
gl_Position = vec4(inSt[i] * 2.0 - 1.0, 0.0, 1.0);
|
||||
gl_Layer = int(inLayer[i]);
|
||||
|
||||
EmitVertex();
|
||||
}
|
||||
EndPrimitive();
|
||||
}
|
||||
@ -4,5 +4,6 @@
|
||||
#define INSTANCED 1
|
||||
#define SKINNED 0
|
||||
#define BAKING 1
|
||||
#define LAYERED 1
|
||||
|
||||
#include "../base.vert.h"
|
||||
|
||||
@ -8,14 +8,14 @@ layout (constant_id = 0) const uint TEXTURES = 1;
|
||||
#include "../common/macros.h"
|
||||
#include "../common/structs.h"
|
||||
|
||||
layout (binding = 4) uniform sampler2D samplerTextures[TEXTURES];
|
||||
layout (std140, binding = 5) readonly buffer Instances {
|
||||
layout (binding = 5) uniform sampler2D samplerTextures[TEXTURES];
|
||||
layout (std140, binding = 6) readonly buffer Instances {
|
||||
Instance instances[];
|
||||
};
|
||||
layout (std140, binding = 6) readonly buffer Materials {
|
||||
layout (std140, binding = 7) readonly buffer Materials {
|
||||
Material materials[];
|
||||
};
|
||||
layout (std140, binding = 7) readonly buffer Textures {
|
||||
layout (std140, binding = 8) readonly buffer Textures {
|
||||
Texture textures[];
|
||||
};
|
||||
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
layout (constant_id = 0) const uint PASSES = 6;
|
||||
#extension GL_ARB_shader_draw_parameters : enable
|
||||
#if LAYERED
|
||||
#extension GL_ARB_shader_viewport_layer_array : enable
|
||||
#endif
|
||||
#include "../common/structs.h"
|
||||
|
||||
layout (location = 0) in vec3 inPos;
|
||||
@ -23,17 +26,15 @@ layout (binding = 0) uniform Camera {
|
||||
Viewport viewport[PASSES];
|
||||
} camera;
|
||||
#endif
|
||||
/*
|
||||
layout (std140, binding = 1) readonly buffer DrawCommands {
|
||||
DrawCommand drawCommands[];
|
||||
};
|
||||
*/
|
||||
layout (std140, binding = 1) readonly buffer Instances {
|
||||
layout (std140, binding = 2) readonly buffer Instances {
|
||||
Instance instances[];
|
||||
};
|
||||
|
||||
#if SKINNED
|
||||
layout (std140, binding = 2) readonly buffer Joints {
|
||||
layout (std140, binding = 3) readonly buffer Joints {
|
||||
mat4 joints[];
|
||||
};
|
||||
#endif
|
||||
@ -45,6 +46,9 @@ layout (location = 3) out vec3 outNormal;
|
||||
layout (location = 4) out mat3 outTBN;
|
||||
layout (location = 7) out vec3 outPosition;
|
||||
layout (location = 8) out uvec4 outId;
|
||||
#if LAYERED
|
||||
layout (location = 9) out uint outLayer;
|
||||
#endif
|
||||
|
||||
vec4 snap(vec4 vertex, vec2 resolution) {
|
||||
vec4 snappedPos = vertex;
|
||||
@ -58,7 +62,7 @@ void main() {
|
||||
outUv = inUv;
|
||||
outSt = inSt;
|
||||
const uint drawID = gl_DrawIDARB;
|
||||
// const DrawCommand drawCommand = drawCommands[drawID];
|
||||
const DrawCommand drawCommand = drawCommands[drawID];
|
||||
const uint instanceID = gl_InstanceIndex;
|
||||
const Instance instance = instances[instanceID];
|
||||
const uint materialID = instance.materialID;
|
||||
@ -94,4 +98,9 @@ void main() {
|
||||
#else
|
||||
gl_Position = projection * view * model * vec4(inPos.xyz, 1.0);
|
||||
#endif
|
||||
|
||||
#if LAYERED
|
||||
// gl_Layer = int(drawCommand.auxID);
|
||||
outLayer = int(drawCommand.auxID);
|
||||
#endif
|
||||
}
|
||||
@ -10,14 +10,14 @@ layout (constant_id = 0) const uint TEXTURES = 1;
|
||||
#include "../common/macros.h"
|
||||
#include "../common/structs.h"
|
||||
|
||||
layout (binding = 4) uniform sampler2D samplerTextures[TEXTURES];
|
||||
layout (std140, binding = 5) readonly buffer Instances {
|
||||
layout (binding = 5) uniform sampler2D samplerTextures[TEXTURES];
|
||||
layout (std140, binding = 6) readonly buffer Instances {
|
||||
Instance instances[];
|
||||
};
|
||||
layout (std140, binding = 6) readonly buffer Materials {
|
||||
layout (std140, binding = 7) readonly buffer Materials {
|
||||
Material materials[];
|
||||
};
|
||||
layout (std140, binding = 7) readonly buffer Textures {
|
||||
layout (std140, binding = 8) readonly buffer Textures {
|
||||
Texture textures[];
|
||||
};
|
||||
|
||||
|
||||
@ -10,26 +10,26 @@ layout (constant_id = 1) const uint CASCADES = 16;
|
||||
#include "../common/macros.h"
|
||||
#include "../common/structs.h"
|
||||
|
||||
layout (binding = 4) uniform sampler2D samplerTextures[TEXTURES];
|
||||
layout (std140, binding = 5) readonly buffer Instances {
|
||||
layout (binding = 5) uniform sampler2D samplerTextures[TEXTURES];
|
||||
layout (std140, binding = 6) readonly buffer Instances {
|
||||
Instance instances[];
|
||||
};
|
||||
layout (std140, binding = 6) readonly buffer Materials {
|
||||
layout (std140, binding = 7) readonly buffer Materials {
|
||||
Material materials[];
|
||||
};
|
||||
layout (std140, binding = 7) readonly buffer Textures {
|
||||
layout (std140, binding = 8) readonly buffer Textures {
|
||||
Texture textures[];
|
||||
};
|
||||
|
||||
layout (binding = 8, rg16ui) uniform volatile coherent uimage3D voxelId[CASCADES];
|
||||
layout (binding = 9, rg16f) uniform volatile coherent image3D voxelNormal[CASCADES];
|
||||
layout (binding = 9, rg16ui) uniform volatile coherent uimage3D voxelId[CASCADES];
|
||||
layout (binding = 10, rg16f) uniform volatile coherent image3D voxelNormal[CASCADES];
|
||||
#if VXGI_HDR
|
||||
layout (binding = 10, rgba16f) uniform volatile coherent image3D voxelRadiance[CASCADES];
|
||||
layout (binding = 11, rgba16f) uniform volatile coherent image3D voxelRadiance[CASCADES];
|
||||
#else
|
||||
layout (binding = 10, rgba8) uniform volatile coherent image3D voxelRadiance[CASCADES];
|
||||
layout (binding = 11, rgba8) uniform volatile coherent image3D voxelRadiance[CASCADES];
|
||||
#endif
|
||||
#if DEPTH_TEST
|
||||
layout (binding = 11, r16f) uniform volatile coherent image3D voxelDepth[CASCADES];
|
||||
layout (binding = 12, r16f) uniform volatile coherent image3D voxelDepth[CASCADES];
|
||||
#endif
|
||||
|
||||
layout (location = 0) in vec2 inUv;
|
||||
@ -81,12 +81,7 @@ void main() {
|
||||
|
||||
// sample albedo
|
||||
if ( !validTextureIndex( material.indexAlbedo ) ) discard; {
|
||||
if ( surface.instance.imageID <= 0 ) {
|
||||
A = sampleTexture( material.indexAlbedo );
|
||||
} else {
|
||||
const Texture t = textures[material.indexAlbedo];
|
||||
A = texture( samplerTextures[nonuniformEXT(t.index - surface.instance.imageID)], mix( t.lerp.xy, t.lerp.zw, uv ) );
|
||||
}
|
||||
A = sampleTexture( material.indexAlbedo );
|
||||
// alpha mode OPAQUE
|
||||
if ( material.modeAlpha == 0 ) {
|
||||
A.a = 1;
|
||||
|
||||
@ -20,7 +20,7 @@ layout (location = 4) out mat3 outTBN;
|
||||
layout (location = 7) out vec3 outPosition;
|
||||
layout (location = 8) flat out uvec4 outId;
|
||||
|
||||
layout (binding = 3) uniform UBO {
|
||||
layout (binding = 4) uniform UBO {
|
||||
mat4 voxel;
|
||||
float cascadePower;
|
||||
float padding1;
|
||||
|
||||
12
bin/data2/scene/ss2/ambience.json
Normal file
12
bin/data2/scene/ss2/ambience.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"behaviors": [ "SoundEmitterBehavior" ],
|
||||
"metadata": {
|
||||
"audio": {
|
||||
"spatial": true,
|
||||
"loop": true,
|
||||
"volume": 1,
|
||||
"rolloffFactor": 1,
|
||||
"streamed": true
|
||||
}
|
||||
}
|
||||
}
|
||||
13
bin/data2/scene/ss2/camera.json
Normal file
13
bin/data2/scene/ss2/camera.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"assets": [
|
||||
"./scripts/camera.lua",
|
||||
"./audio/soundscape/camera.ogg"
|
||||
],
|
||||
"metadata": {
|
||||
"audio": {
|
||||
"rolloffFactor": 4,
|
||||
"volume": 1.0
|
||||
},
|
||||
"sensitivity": 10
|
||||
}
|
||||
}
|
||||
16
bin/data2/scene/ss2/craeture.json
Normal file
16
bin/data2/scene/ss2/craeture.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "Craeture",
|
||||
"behaviors": [ "CraetureBehavior" ],
|
||||
"assets": [
|
||||
"./textures/craeture.png"
|
||||
],
|
||||
"transform": {
|
||||
"position": [18.3785, 2.41477, 0.859857],
|
||||
"scale": [8, 8, 8]
|
||||
},
|
||||
"metadata": {
|
||||
"model": {
|
||||
"cull mode": "none"
|
||||
}
|
||||
}
|
||||
}
|
||||
13
bin/data2/scene/ss2/lift.json
Normal file
13
bin/data2/scene/ss2/lift.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"assets": [ "./scripts/lift.lua" ],
|
||||
"system": {
|
||||
"physics": {
|
||||
"type": "bounding box",
|
||||
"recenter": true,
|
||||
|
||||
"mass": 100,
|
||||
"restitution": 0,
|
||||
"friction": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
32
bin/data2/scene/ss2/loading.json
Normal file
32
bin/data2/scene/ss2/loading.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "Gui: Loading",
|
||||
"type": "Object",
|
||||
"behaviors": [
|
||||
"GuiBehavior"
|
||||
],
|
||||
"assets": [
|
||||
{ "filename": "./medsci.json", "delay": 0 }
|
||||
],
|
||||
"ignore": false,
|
||||
"transform": {
|
||||
"position": [ -0.830591, -0.699509, 0 ],
|
||||
"rotation": {
|
||||
"axis": [ 1, 0, 0 ],
|
||||
"angle": 0
|
||||
},
|
||||
"scale": [ 0.258737, 0.115371, 1 ]
|
||||
},
|
||||
"metadata": {
|
||||
"uv": [ 0, 0, 1, 1 ],
|
||||
"color": [ 1, 1, 1, 0.1 ],
|
||||
"location": "",
|
||||
"scaling": "relative",
|
||||
"text settings": {
|
||||
"stroke": [ 1, 0.749, 0.368, 1 ],
|
||||
"color": [ 1, 0.749, 0.368, 1 ],
|
||||
|
||||
"string": "Loading...",
|
||||
"string1": "コマンド"
|
||||
}
|
||||
}
|
||||
}
|
||||
58
bin/data2/scene/ss2/medsci.json
Normal file
58
bin/data2/scene/ss2/medsci.json
Normal file
@ -0,0 +1,58 @@
|
||||
{
|
||||
"import": "/model.json",
|
||||
"assets": [
|
||||
// { "filename": "./models/tiny_msci.glb", "delay": 0, "single threaded": false, "category": "models" }
|
||||
// { "filename": "./models/tiny_msci/graph.json", "delay": 0, "single threaded": false, "category": "models" }
|
||||
{ "filename": "./models/tiny_msci/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" }
|
||||
|
||||
// { "filename": "./models/micro_sci.glb", "delay": 0, "single threaded": false, "category": "models" }
|
||||
// { "filename": "./models/micro_sci/graph.json", "delay": 0, "single threaded": false, "category": "models" }
|
||||
// { "filename": "./models/micro_sci/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" }
|
||||
// { "filename": "./craeture.json", "delay": 1 }
|
||||
|
||||
// { "filename": "./models/msci.glb", "delay": 0, "single threaded": false, "category": "models" }
|
||||
// { "filename": "./models/msci/graph.json", "delay": 0, "single threaded": false, "category": "models" }
|
||||
// { "filename": "./models/msci/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" }
|
||||
|
||||
// { "filename": "./models/medsci.glb", "delay": 0, "single threaded": false }
|
||||
// { "filename": "./models/medsci/graph.json", "delay": 0, "single threaded": false, "category": "models" }
|
||||
// { "filename": "./models/medsci/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" }
|
||||
],
|
||||
"metadata": {
|
||||
"model": {
|
||||
"exporter": {
|
||||
"enabled": false
|
||||
},
|
||||
"baking": {
|
||||
"enabled": false,
|
||||
"resolution": 8192,
|
||||
"shadows": 1024,
|
||||
"trigger": { "mode": "rendered" },
|
||||
"output": "./lightmap.png"
|
||||
},
|
||||
// "lightmap": "./lightmap.min.png",
|
||||
"filter": "NEAREST",
|
||||
"tags": {
|
||||
"worldspawn": { "physics": { "type": "mesh", "static": true } },
|
||||
"worldspawn_20": { "physics": { "type": "mesh", "static": true } },
|
||||
// "worldspawn": { "physics": { "type": "bounding boxes", "static": true } },
|
||||
"info_player_spawn": {
|
||||
"action": "attach",
|
||||
"filename": "./player.json",
|
||||
"preserve orientation": true
|
||||
},
|
||||
"ambience_xerxes": { "action": "load", "payload": { "import": "./ambience.json", "assets": [ "./audio/soundscape/xerxes.ogg" ], "metadata": { "audio": { "rolloffFactor": 0.5, "volume": 1.0 } } } },
|
||||
|
||||
"light_30145": { "light": { "power": 120 } },
|
||||
|
||||
"prop_camera_103001_light": { "light": { "shadows": false, "static": false, "dynamic": true, "power": 30 } },
|
||||
"prop_camera_103118_light": { "light": { "shadows": false, "static": false, "dynamic": true, "power": 30 } },
|
||||
"prop_camera_103001": { "action": "load", "payload": { "import": "./camera.json" } },
|
||||
"prop_camera_103118": { "action": "load", "payload": { "import": "./camera.json" } },
|
||||
"func_movelinear_57637": { "action": "load", "payload": { "import": "./lift.json", "metadata": { "delta": [ 0,8.6,0 ] } } },
|
||||
"func_movelinear_82820": { "action": "load", "payload": { "import": "./lift.json", "metadata": { "delta": [ 0,9.2,0 ] } } },
|
||||
"func_movelinear_103114": { "action": "load", "payload": { "import": "./lift.json", "metadata": { "delta": [ 0,-3.0,0 ] } } }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
18
bin/data2/scene/ss2/noise.json
Normal file
18
bin/data2/scene/ss2/noise.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "Test",
|
||||
"assets": [],
|
||||
"behaviors": [
|
||||
"RenderBehavior",
|
||||
"NoiseBehavior"
|
||||
],
|
||||
"transform": {
|
||||
"position": [ 10, 4, 4 ],
|
||||
"orientation": [0, 0, 0, 1]
|
||||
},
|
||||
"metadata": {
|
||||
"size": [ 256, 256, 256 ],
|
||||
"coefficients": [ 3, 3, 3 ],
|
||||
"amplitude": 1.5,
|
||||
"speed": 0.125
|
||||
}
|
||||
}
|
||||
27
bin/data2/scene/ss2/player.json
Normal file
27
bin/data2/scene/ss2/player.json
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"import": "/player.json",
|
||||
"assets": [
|
||||
// { "filename": "/gui/hud/hud.json", "delay": 0 }
|
||||
],
|
||||
"transform": {
|
||||
"position": [ 0, 0, 0 ],
|
||||
"rotation": {
|
||||
"axis": [ 0, 1, 0 ],
|
||||
"angle": 3.1415926
|
||||
},
|
||||
"scale": [ 1, 1, 1 ]
|
||||
},
|
||||
"metadata": {
|
||||
"overlay": {
|
||||
"floating": true
|
||||
},
|
||||
"collider": true,
|
||||
"light": {
|
||||
"should": false,
|
||||
"color": [1, 1, 1],
|
||||
"position": [ 0, 2.5, 0 ],
|
||||
"power": 1,
|
||||
"radius": [0.001, 32]
|
||||
}
|
||||
}
|
||||
}
|
||||
55
bin/data2/scene/ss2/scene.json
Normal file
55
bin/data2/scene/ss2/scene.json
Normal file
@ -0,0 +1,55 @@
|
||||
{
|
||||
"import": "/scene.json",
|
||||
"assets": [
|
||||
{ "filename": "./audio/music/medsci1.ogg", "category": "audio-stream", "override": true, "streamed": true },
|
||||
"./loading.json"
|
||||
],
|
||||
"system": {
|
||||
"hot reload": {
|
||||
"enabled": true
|
||||
},
|
||||
"renderer": {
|
||||
"clear values": [
|
||||
[ 0, 0, 0, 0 ]
|
||||
],
|
||||
"shader": {
|
||||
"mode": 1,
|
||||
"scalar": 16,
|
||||
"parameters": [ 0, 0, 0, "time" ]
|
||||
}
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"menus": {
|
||||
"pause": "/gui/pause/menu.json"
|
||||
},
|
||||
"bloom": {
|
||||
"scale": 1.0,
|
||||
"strength": 0.125,
|
||||
"sigma": 0.8,
|
||||
"samples": 5
|
||||
},
|
||||
"light": {
|
||||
"exposure": 1.0,
|
||||
"gamma": 1.0,
|
||||
"brightnessThreshold": 1.2,
|
||||
|
||||
"ambient": [ 0.0, 0.0, 0.0 ],
|
||||
|
||||
"fog": {
|
||||
"color": [ 0.025, 0.025, 0.1 ],
|
||||
"step scale": 0.0,
|
||||
"range": [ 1, 1 ],
|
||||
"absorbtion": 0.85,
|
||||
"density": {
|
||||
"threshold": 0.5,
|
||||
"multiplier": 5.0,
|
||||
"scale": 50.0,
|
||||
"offset": "time"
|
||||
}
|
||||
},
|
||||
"should": true,
|
||||
"shadows": true
|
||||
}
|
||||
}
|
||||
}
|
||||
191
bin/data2/scene/ss2/scripts/camera.lua
Normal file
191
bin/data2/scene/ss2/scripts/camera.lua
Normal file
@ -0,0 +1,191 @@
|
||||
local scene = entities.currentScene()
|
||||
local controller = entities.controller()
|
||||
local controllerTransform = controller:getComponent("Transform")
|
||||
local timer = Timer.new()
|
||||
if not timer:running() then
|
||||
timer:start();
|
||||
end
|
||||
local metadata = ent:getComponent("Metadata")
|
||||
local soundEmitter = ent:loadChild("./sound.json",true)
|
||||
local playSound = function( key )
|
||||
if not loop then loop = false end
|
||||
local url = "./audio/sfx/" .. key .. ".ogg"
|
||||
soundEmitter:queueHook("sound:Emit.%UID%", {
|
||||
filename = string.resolveURI(url, metadata["system"]["root"]),
|
||||
spatial = true,
|
||||
loop = loop,
|
||||
volume = "sfx",
|
||||
streamed = true
|
||||
}, 0)
|
||||
end
|
||||
local playSoundscape = function( key )
|
||||
local url = "./audio/soundscape/" .. key .. ".ogg"
|
||||
soundEmitter:queueHook("sound:Emit.%UID%", {
|
||||
filename = string.resolveURI(url, metadata["system"]["root"]),
|
||||
spatial = false,
|
||||
volume = "sfx",
|
||||
loop = true,
|
||||
streamed = true
|
||||
}, 0)
|
||||
end
|
||||
local stopSoundscape = function( key )
|
||||
local url = "./audio/soundscape/" .. key .. ".ogg"
|
||||
soundEmitter:queueHook("sound:Stop.%UID%", {
|
||||
filename = string.resolveURI(url, metadata["system"]["root"])
|
||||
}, 0)
|
||||
end
|
||||
|
||||
local target = Vector3f(0,0,0)
|
||||
local transform = ent:getComponent("Transform")
|
||||
local speed = metadata["speed"] or 1.0 / 3.0
|
||||
local angle = metadata["angle"] or 1.5
|
||||
transform.orientation = Quaternion.axisAngle( Vector3f(0,1,0), 1.5 )
|
||||
local starting = transform.orientation:multiply(Quaternion.axisAngle( Vector3f(0,1,0), -angle ))
|
||||
local ending = transform.orientation:multiply(Quaternion.axisAngle( Vector3f(0,1,0), angle ))
|
||||
-- on tick
|
||||
local delta = 0
|
||||
local watch = 0
|
||||
local alerted = false
|
||||
local light = nil
|
||||
local lightOffset = nil
|
||||
|
||||
for k, v in pairs(ent:getChildren()) do
|
||||
if v:uid() ~= soundEmitter:uid() then
|
||||
light = v
|
||||
local transform = v:getComponent("Transform")
|
||||
lightOffset = Vector3f(transform.position) --:magnitude()
|
||||
end
|
||||
end
|
||||
|
||||
ent:bind( "tick", function(self)
|
||||
soundEmitter:getComponent("Transform").position = transform.position
|
||||
|
||||
local angleThreshold = metadata["sensitivity"] or 20
|
||||
|
||||
local controllerPosition = Vector3f(controllerTransform.position.x, 0, controllerTransform.position.z)
|
||||
local cameraPosition = Vector3f(transform.position.x, 0, transform.position.z)
|
||||
local distance = cameraPosition:distance(controllerPosition)
|
||||
local direction = cameraPosition - controllerPosition
|
||||
|
||||
local lightTransform = light and light:getComponent("Transform") or nil
|
||||
local lightMetadata = light and light:getComponent("Metadata") or {}
|
||||
if lightTransform ~= nil then
|
||||
lightTransform.position = transform.orientation:rotate( lightOffset );
|
||||
if lightMetadata and lightMetadata["light"] and lightMetadata["light"]["static"] then
|
||||
lightTransform.position = lightTransform.position + transform.position
|
||||
end
|
||||
end
|
||||
|
||||
local angle = math.acos(transform.orientation:rotate( Vector3f(0,0,1):normalize() ):dot( direction:normalize() )) * 180.0 / 3.1415926
|
||||
if angle < angleThreshold and distance < 16 then
|
||||
if watch == 0 then
|
||||
watch = 6
|
||||
playSound("camera_see")
|
||||
if light then
|
||||
light:callHook( "object:UpdateMetadata.%UID%", {
|
||||
path = "light.color",
|
||||
value = {
|
||||
[1] = 1,
|
||||
[2] = 1,
|
||||
[3] = 0
|
||||
}
|
||||
} )
|
||||
end
|
||||
end
|
||||
watch = watch + time.delta()
|
||||
if watch > 12 and not alerted then
|
||||
playSound("camera_alert")
|
||||
playSound("xerxes_alert")
|
||||
playSoundscape("alarm")
|
||||
alerted = true
|
||||
timer:reset()
|
||||
if light then
|
||||
light:callHook( "object:UpdateMetadata.%UID%", {
|
||||
path = "light.color",
|
||||
value = {
|
||||
[1] = 1,
|
||||
[2] = 0,
|
||||
[3] = 0
|
||||
}
|
||||
} )
|
||||
light:callHook( "object:UpdateMetadata.%UID%", {
|
||||
path = "light.fade",
|
||||
value = {
|
||||
rate = 1,
|
||||
power = 0.01,
|
||||
timeout= 0.5
|
||||
}
|
||||
} )
|
||||
end
|
||||
end
|
||||
else
|
||||
if watch > 0 and not alerted then
|
||||
watch = watch - time.delta()
|
||||
if watch < 0 then
|
||||
io.print("CAMERA LOST")
|
||||
watch = 0
|
||||
speed = metadata["speed"] or 1.0 / 3.0
|
||||
if light then
|
||||
light:callHook( "object:UpdateMetadata.%UID%", {
|
||||
path = "light.color",
|
||||
value = {
|
||||
[1] = 0,
|
||||
[2] = 1,
|
||||
[3] = 0
|
||||
}
|
||||
} )
|
||||
light:callHook( "object:UpdateMetadata.%UID%", {
|
||||
path = "light.fade",
|
||||
value = nil
|
||||
} )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if not alerted and watch > 0 and light then
|
||||
light:callHook( "object:UpdateMetadata.%UID%", {
|
||||
path = "light.fade.rate",
|
||||
value = math.floor(watch / 2),
|
||||
} )
|
||||
light:callHook( "object:UpdateMetadata.%UID%", {
|
||||
path = "light.fade.power",
|
||||
value = 0.01,
|
||||
} )
|
||||
light:callHook( "object:UpdateMetadata.%UID%", {
|
||||
path = "light.fade.timeout",
|
||||
value = 0.5,
|
||||
} )
|
||||
end
|
||||
if alerted and timer:elapsed() >= 60 then
|
||||
timer:reset()
|
||||
alerted = false
|
||||
watch = 0
|
||||
io.print("ALERT OVER")
|
||||
playSound("camera_lost")
|
||||
stopSoundscape("alarm");
|
||||
if light then
|
||||
light:callHook( "object:UpdateMetadata.%UID%", {
|
||||
path = "light.color",
|
||||
value = {
|
||||
[1] = 0,
|
||||
[2] = 1,
|
||||
[3] = 0
|
||||
}
|
||||
} )
|
||||
light:callHook( "object:UpdateMetadata.%UID%", {
|
||||
path = "light.fade",
|
||||
value = nil
|
||||
} )
|
||||
end
|
||||
end
|
||||
|
||||
delta = delta + time.delta() * speed
|
||||
local nextRotation = starting:slerp( ending, math.cos(delta) * 0.5 + 0.5 )
|
||||
-- stop if we are going to look away from player
|
||||
local angleNext = math.acos(nextRotation:rotate( Vector3f(0,0,1):normalize() ):dot( direction:normalize() )) * 180.0 / 3.1415926
|
||||
if watch > 0 and angleNext > angle then
|
||||
delta = delta - time.delta() * speed * 3
|
||||
nextRotation = starting:slerp( ending, math.cos(delta) * 0.5 + 0.5 )
|
||||
end
|
||||
transform.orientation = nextRotation
|
||||
end )
|
||||
84
bin/data2/scene/ss2/scripts/lift.lua
Normal file
84
bin/data2/scene/ss2/scripts/lift.lua
Normal file
@ -0,0 +1,84 @@
|
||||
local scene = entities.currentScene()
|
||||
local controller = entities.controller()
|
||||
|
||||
local timer = Timer.new()
|
||||
if not timer:running() then
|
||||
timer:start();
|
||||
end
|
||||
|
||||
local target = Vector3f(0,0,0)
|
||||
local transform = ent:getComponent("Transform")
|
||||
local metadata = ent:getComponent("Metadata")
|
||||
local physics = ent:getComponent("Physics")
|
||||
local bullet = ent:getComponent("Bullet")
|
||||
-- local velocty = physics:linearVelocity()
|
||||
local speed = metadata["speed"] or 1.0
|
||||
local starting = transform.position + Vector3f(0,0,0)
|
||||
local ending = transform.position + Vector3f( metadata["delta"][1], metadata["delta"][2], metadata["delta"][3] )
|
||||
local wait = 0
|
||||
local direction = 1.0 / math.abs(starting:distance(ending))
|
||||
local alpha = 0
|
||||
local startingSound = true
|
||||
|
||||
local soundEmitter = ent:loadChild("./sound.json",true)
|
||||
local playSound = function( key, loop )
|
||||
if not loop then loop = false end
|
||||
local url = "./audio/sfx/" .. key .. ".ogg"
|
||||
soundEmitter:queueHook("sound:Emit.%UID%", {
|
||||
filename = string.resolveURI(url, metadata["system"]["root"]),
|
||||
spatial = true,
|
||||
streamed = true,
|
||||
volume = "sfx",
|
||||
loop = loop
|
||||
}, 0)
|
||||
end
|
||||
local stopSound = function( key )
|
||||
local url = "./audio/sfx/" .. key .. ".ogg"
|
||||
soundEmitter:queueHook("sound:Stop.%UID%", {
|
||||
filename = string.resolveURI(url, metadata["system"]["root"])
|
||||
}, 0)
|
||||
end
|
||||
local playSoundscape = function( key )
|
||||
local url = "./audio/soundscape/" .. key .. ".ogg"
|
||||
soundEmitter:queueHook("sound:Emit.%UID%", {
|
||||
filename = string.resolveURI(url, metadata["system"]["root"]),
|
||||
spatial = false,
|
||||
volume = "sfx",
|
||||
loop = true,
|
||||
streamed = true
|
||||
}, 0)
|
||||
end
|
||||
local stopSoundscape = function( key )
|
||||
local url = "./audio/soundscape/" .. key .. ".ogg"
|
||||
soundEmitter:queueHook("sound:Stop.%UID%", {
|
||||
filename = string.resolveURI(url, metadata["system"]["root"])
|
||||
}, 0)
|
||||
end
|
||||
soundEmitter:getComponent("Transform"):setReference( transform )
|
||||
-- on tick
|
||||
ent:bind( "tick", function(self)
|
||||
|
||||
if wait > 0 then
|
||||
wait = wait - time.delta()
|
||||
else
|
||||
if startingSound then
|
||||
playSound("lift_start", true)
|
||||
startingSound = false
|
||||
end
|
||||
alpha = alpha + time.delta() * speed * direction
|
||||
if alpha <= 0 or alpha >= 1 then
|
||||
alpha = math.clamp( alpha, 0.0, 1.0 )
|
||||
direction = -direction
|
||||
wait = 6
|
||||
stopSound("lift_start")
|
||||
playSound("lift_stop")
|
||||
startingSound = true
|
||||
-- bullet:setVelocity( Vector3f(0,0,0) )
|
||||
-- physics:setLinearVelocity( Vector3f(0,0,0) )
|
||||
else
|
||||
-- bullet:setVelocity( Vector3f(0,direction,0) )
|
||||
-- physics:setLinearVelocity( Vector3f(0,direction / math.abs(direction),0) )
|
||||
end
|
||||
end
|
||||
transform.position = Vector3f.lerp( starting, ending, alpha )
|
||||
end )
|
||||
34
bin/data2/scene/ss2/sound.json
Normal file
34
bin/data2/scene/ss2/sound.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"type": "Object",
|
||||
"name": "Sound Emitter",
|
||||
"ignore": false,
|
||||
"assets": [
|
||||
],
|
||||
"behaviors": [
|
||||
"SoundEmitterBehavior"
|
||||
],
|
||||
"transform": {
|
||||
"reference": true
|
||||
},
|
||||
"system": {
|
||||
"hot reload": {
|
||||
"enabled": true
|
||||
},
|
||||
"defaults": {
|
||||
"render": true,
|
||||
"asset load": true
|
||||
},
|
||||
"load": {
|
||||
"ignore": true
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"audio": {
|
||||
"spatial": true,
|
||||
"loop": false,
|
||||
"volume": 1,
|
||||
"rolloffFactor": 0.5,
|
||||
"epsilon": 0.5
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,8 +5,8 @@
|
||||
"meshes": { "interleaved": true },
|
||||
"matrix": { "reverseInfinite": false },
|
||||
"lights": {
|
||||
"max": 8,
|
||||
"enabled": true
|
||||
"max": 2,
|
||||
"enabled": false
|
||||
},
|
||||
"shadows": {
|
||||
"enabled": false,
|
||||
@ -74,7 +74,7 @@
|
||||
}
|
||||
},
|
||||
"audio": {
|
||||
"mute": false,
|
||||
"mute": true,
|
||||
"buffers": {
|
||||
"size": 16384,
|
||||
"count": 3
|
||||
|
||||
@ -93,9 +93,11 @@ int main(int argc, char** argv){
|
||||
*/
|
||||
#if UF_ENV_DREAMCAST
|
||||
// UF_TIMER_MULTITRACE_START("Starting");
|
||||
ext::render();
|
||||
// UF_TIMER_MULTITRACE("render");
|
||||
ext::tick();
|
||||
client::tick();
|
||||
// UF_TIMER_MULTITRACE("render");
|
||||
ext::render();
|
||||
client::render();
|
||||
// UF_TIMER_MULTITRACE("tick");
|
||||
// UF_TIMER_MULTITRACE_END("Finished");
|
||||
#else
|
||||
|
||||
@ -29,6 +29,7 @@ namespace ext {
|
||||
uint8_t subpasses = 1;
|
||||
uint8_t samples = 1;
|
||||
uint8_t eyes = 1;
|
||||
uint8_t views = 1;
|
||||
} metadata;
|
||||
|
||||
Device* device = VK_NULL_HANDLE;
|
||||
@ -52,7 +53,7 @@ namespace ext {
|
||||
virtual ext::vulkan::Graphic* getBlitter(size_t = 0);
|
||||
virtual uf::stl::vector<ext::vulkan::Graphic*> getBlitters();
|
||||
|
||||
virtual uf::Image screenshot(size_t = 0);
|
||||
virtual uf::Image screenshot(size_t = 0, size_t = 0);
|
||||
|
||||
virtual commands_container_t& getCommands();
|
||||
virtual commands_container_t& getCommands( std::thread::id );
|
||||
|
||||
@ -12,6 +12,7 @@ namespace ext {
|
||||
VkImageUsageFlags usage;
|
||||
bool blend = false;
|
||||
uint8_t samples = 1;
|
||||
uint8_t layers = 1;
|
||||
bool screenshottable = true;
|
||||
bool aliased = false;
|
||||
} descriptor;
|
||||
|
||||
@ -137,11 +137,15 @@ namespace ext {
|
||||
public:
|
||||
static Texture2D empty;
|
||||
Texture2D();
|
||||
|
||||
uf::Image screenshot( uint32_t layer = 0 );
|
||||
};
|
||||
class UF_API Texture3D : public Texture {
|
||||
public:
|
||||
static Texture3D empty;
|
||||
Texture3D();
|
||||
|
||||
uf::Image screenshot( uint32_t layer = 0 );
|
||||
};
|
||||
class UF_API TextureCube : public Texture {
|
||||
public:
|
||||
|
||||
@ -5,8 +5,7 @@
|
||||
#if UF_USE_XATLAS
|
||||
namespace ext {
|
||||
namespace xatlas {
|
||||
pod::Vector2ui UF_API unwrap( uf::stl::vector<uf::graph::mesh::Skinned>& vertices, uf::stl::vector<uint32_t>& indices );
|
||||
pod::Vector2ui UF_API unwrap( pod::Graph& );
|
||||
size_t UF_API unwrap( pod::Graph&, bool = false );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -120,4 +120,11 @@
|
||||
#define MIN(X, Y) (X) < (Y) ? (X) : (Y)
|
||||
#define MAX(X, Y) (X) > (Y) ? (X) : (Y)
|
||||
#define LENGTH_OF(X) *(&X + 1) - X
|
||||
#define FOR_ARRAY(X) for ( auto i = 0; i < LENGTH_OF(X); ++i )
|
||||
#define FOR_ARRAY(X) for ( auto i = 0; i < LENGTH_OF(X); ++i )
|
||||
|
||||
#if UF_ENV_DREAMCAST
|
||||
#define DC_STATS() {\
|
||||
UF_MSG_DEBUG(spec::dreamcast::malloc_stats());\
|
||||
UF_MSG_DEBUG(spec::dreamcast::pvr_malloc_stats());\
|
||||
}
|
||||
#endif
|
||||
@ -7,7 +7,12 @@
|
||||
#if UF_ENV_DREAMCAST
|
||||
namespace spec {
|
||||
namespace dreamcast {
|
||||
class UF_API Window : public spec::uni::Window {
|
||||
uf::stl::string malloc_stats( bool = false );
|
||||
uf::stl::string pvr_malloc_stats( bool = false );
|
||||
|
||||
class UF_API Window : public spec::uni::Window {
|
||||
protected:
|
||||
spec::dreamcast::Window::context_t* m_context;
|
||||
public:
|
||||
// C-tors
|
||||
UF_API Window();
|
||||
@ -48,8 +53,14 @@ namespace spec {
|
||||
void UF_API setTracking(bool state);
|
||||
static pod::Vector2ui UF_API getResolution();
|
||||
void UF_API toggleFullscreen( bool borderless = false );
|
||||
|
||||
void UF_API display();
|
||||
};
|
||||
}
|
||||
typedef spec::dreamcast::Window Window;
|
||||
}
|
||||
|
||||
namespace uf {
|
||||
using Window = spec::dreamcast::Window;
|
||||
}
|
||||
#endif
|
||||
@ -13,6 +13,7 @@ namespace spec {
|
||||
class UF_API Window {
|
||||
public:
|
||||
typedef void* handle_t;
|
||||
typedef void* context_t;
|
||||
typedef uf::String title_t;
|
||||
typedef pod::Vector2i vector_t;
|
||||
|
||||
@ -24,6 +25,7 @@ namespace spec {
|
||||
// Window::Events m_events;
|
||||
std::queue<Event> m_events;
|
||||
public:
|
||||
#if 0
|
||||
// C-tors
|
||||
void create( const spec::uni::Window::vector_t& size, const spec::uni::Window::title_t& title = L"Window" ) {} ;// = 0;
|
||||
// D-tors
|
||||
@ -48,7 +50,11 @@ namespace spec {
|
||||
bool hasFocus() const;/* = 0;*/
|
||||
// Update
|
||||
void bufferInputs();/* = 0;*/
|
||||
void processEvents();/* = 0;*/
|
||||
|
||||
static bool isKeyPressed( const uf::stl::string& );
|
||||
#endif
|
||||
#if 0
|
||||
void processEvents();
|
||||
|
||||
void pushEvent( const uf::Hooks::name_t& name, const uf::stl::string& payload );
|
||||
void pushEvent( const uf::Hooks::name_t& name, const ext::json::Value& payload );
|
||||
@ -58,7 +64,11 @@ namespace spec {
|
||||
template<typename T> void pushEvent( const uf::Hooks::name_t& name, const T& payload );
|
||||
|
||||
bool pollEvents( bool block = false );
|
||||
static bool isKeyPressed( const uf::stl::string& );
|
||||
#endif
|
||||
|
||||
void pushEvent( const uf::Hooks::name_t& name, const pod::Hook::userdata_t& payload );
|
||||
template<typename T> void pushEvent( const uf::Hooks::name_t& name, const T& payload );
|
||||
static bool focused;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,15 +3,19 @@
|
||||
#include <uf/config.h>
|
||||
#include "universal.h"
|
||||
|
||||
#if UF_ENV_WINDOWS
|
||||
#if UF_USE_VULKAN
|
||||
#include <uf/ext/vulkan/vk.h>
|
||||
#elif UF_USE_OPENGL
|
||||
#endif
|
||||
|
||||
#if UF_ENV_WINDOWS
|
||||
namespace spec {
|
||||
namespace win32 {
|
||||
class UF_API Window : public spec::uni::Window {
|
||||
public:
|
||||
typedef HWND handle_t;
|
||||
typedef void* context_t;
|
||||
|
||||
/*
|
||||
typedef spec::uni::Window::title_t title_t;
|
||||
typedef spec::uni::Window::vector_t vector_t;
|
||||
@ -19,6 +23,7 @@ namespace spec {
|
||||
LONG_PTR m_callback;
|
||||
protected:
|
||||
spec::win32::Window::handle_t m_handle;
|
||||
spec::win32::Window::context_t* m_context;
|
||||
HCURSOR m_cursor;
|
||||
HICON m_icon;
|
||||
|
||||
@ -77,8 +82,14 @@ namespace spec {
|
||||
void UF_API_CALL createSurface( VkInstance instance, VkSurfaceKHR& surface );
|
||||
#endif
|
||||
static uf::stl::string UF_API_CALL getKey(WPARAM key, LPARAM flags);
|
||||
|
||||
void display();
|
||||
};
|
||||
}
|
||||
typedef spec::win32::Window Window;
|
||||
}
|
||||
|
||||
namespace uf {
|
||||
using Window = spec::win32::Window;
|
||||
}
|
||||
#endif
|
||||
@ -80,7 +80,9 @@ namespace uf {
|
||||
|
||||
uf::meshgrid::cleanup( grid );
|
||||
|
||||
size_t atlasID = 0;
|
||||
for ( auto& pair : grid.nodes ) { auto& node = pair.second;
|
||||
++atlasID;
|
||||
for ( auto& pair2 : node.meshlets ) { auto& mlet = pair2.second;
|
||||
if ( mlet.indices.empty() ) continue;
|
||||
|
||||
@ -95,8 +97,8 @@ namespace uf {
|
||||
|
||||
slice.primitive.instance.materialID = meshlet.primitive.instance.materialID;
|
||||
slice.primitive.instance.primitiveID = partitioned.size() - 1;
|
||||
slice.primitive.instance.meshID = meshlet.primitive.instance.meshID;
|
||||
slice.primitive.instance.objectID = 0;
|
||||
slice.primitive.instance.auxID = atlasID;
|
||||
slice.primitive.instance.bounds.min = node.effectiveExtents.min;
|
||||
slice.primitive.instance.bounds.max = node.effectiveExtents.max;
|
||||
|
||||
@ -105,6 +107,7 @@ namespace uf {
|
||||
slice.primitive.drawCommand.indexID = 0;
|
||||
slice.primitive.drawCommand.vertexID = 0;
|
||||
slice.primitive.drawCommand.instanceID = 0;
|
||||
slice.primitive.drawCommand.auxID = atlasID; // meshlet.primitive.instance.meshID;
|
||||
slice.primitive.drawCommand.vertices = slice.vertices.size();
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,15 +48,15 @@ namespace ext {
|
||||
|
||||
namespace pod {
|
||||
struct UF_API DrawCommand {
|
||||
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
|
||||
uint32_t instanceID = 0; // starting instance position
|
||||
alignas(4) uint32_t indices = 0; // triangle count
|
||||
alignas(4) uint32_t instances = 0; // instance count
|
||||
alignas(4) uint32_t indexID = 0; // starting triangle position
|
||||
alignas(4) int32_t vertexID = 0; // starting vertex position
|
||||
alignas(4) uint32_t instanceID = 0; // starting instance position
|
||||
// extra data
|
||||
uint32_t padding1 = 0; //
|
||||
uint32_t padding2 = 0; //
|
||||
uint32_t vertices = 0; //
|
||||
alignas(4) uint32_t auxID = 0; //
|
||||
alignas(4) uint32_t materialID = 0; //
|
||||
alignas(4) uint32_t vertices = 0; //
|
||||
};
|
||||
|
||||
|
||||
@ -72,7 +72,7 @@ namespace pod {
|
||||
alignas(4) int32_t jointID = -1;
|
||||
alignas(4) int32_t lightmapID = -1;
|
||||
alignas(4) uint32_t imageID = 0;
|
||||
alignas(4) uint32_t padding3 = 0;
|
||||
alignas(4) uint32_t auxID = 0;
|
||||
|
||||
struct Bounds {
|
||||
pod::Vector3f min = { std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max() };
|
||||
|
||||
@ -1,61 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include <uf/config.h>
|
||||
#include <uf/spec/window/window.h>
|
||||
#include <uf/spec/context/context.h>
|
||||
|
||||
namespace uf {
|
||||
class UF_API Window : public spec::uni::Window {
|
||||
public:
|
||||
typedef spec::Window window_t;
|
||||
typedef spec::Context context_t;
|
||||
protected:
|
||||
Window::window_t* m_window;
|
||||
Window::context_t* m_context;
|
||||
public:
|
||||
// C-tors
|
||||
UF_API_CALL Window();
|
||||
UF_API_CALL Window( const spec::uni::Window::vector_t& size, const spec::uni::Window::title_t& title = L"Window", const spec::Context::Settings& settings = spec::Context::Settings() );
|
||||
void UF_API_CALL create( const spec::uni::Window::vector_t& size, const spec::uni::Window::title_t& title = L"Window", const spec::Context::Settings& settings = spec::Context::Settings() );
|
||||
// D-tors
|
||||
~Window();
|
||||
void UF_API_CALL terminate();
|
||||
// Gets
|
||||
spec::uni::Window::vector_t UF_API_CALL getPosition() const;
|
||||
spec::uni::Window::vector_t UF_API_CALL getSize() const;
|
||||
size_t UF_API_CALL getRefreshRate() const;
|
||||
// Attribute modifiers
|
||||
void UF_API_CALL setPosition( const spec::uni::Window::vector_t& position );
|
||||
void UF_API_CALL centerWindow();
|
||||
void UF_API_CALL setMousePosition( const spec::uni::Window::vector_t& position );
|
||||
spec::uni::Window::vector_t UF_API_CALL getMousePosition();
|
||||
void UF_API_CALL setSize( const spec::uni::Window::vector_t& size );
|
||||
void UF_API_CALL setTitle( const spec::uni::Window::title_t& title );
|
||||
void UF_API_CALL setIcon( const spec::uni::Window::vector_t& size, uint8_t* pixels );
|
||||
void UF_API_CALL setVisible( bool visibility );
|
||||
void UF_API_CALL setCursorVisible( bool visibility );
|
||||
void UF_API_CALL setKeyRepeatEnabled( bool state );
|
||||
void UF_API_CALL setMouseGrabbed( bool state );
|
||||
|
||||
void UF_API_CALL requestFocus();
|
||||
bool UF_API_CALL hasFocus() const;
|
||||
static pod::Vector2ui UF_API_CALL getResolution();
|
||||
void UF_API_CALL toggleFullscreen( bool borderless = false );
|
||||
|
||||
#if defined(UF_USE_VULKAN) && UF_USE_VULKAN == 1
|
||||
uf::stl::vector<uf::stl::string> getExtensions( bool validationEnabled = true );
|
||||
void createSurface( VkInstance instance, VkSurfaceKHR& surface );
|
||||
#endif
|
||||
|
||||
static bool focused;
|
||||
static bool UF_API_CALL isKeyPressed(const uf::stl::string&);
|
||||
|
||||
void UF_API_CALL bufferInputs();
|
||||
void UF_API_CALL processEvents();
|
||||
bool UF_API_CALL pollEvents(bool block = false);
|
||||
bool UF_API_CALL setActive( bool active = true );
|
||||
void UF_API_CALL display();
|
||||
Window::window_t* UF_API_CALL getHandle();
|
||||
const Window::window_t* UF_API_CALL getHandle() const;
|
||||
};
|
||||
}
|
||||
#include <uf/spec/window/window.h>
|
||||
@ -142,6 +142,7 @@ namespace {
|
||||
instance.materialID = json["materialID"].as( instance.materialID );
|
||||
instance.primitiveID = json["primitiveID"].as( instance.primitiveID );
|
||||
instance.meshID = json["meshID"].as( instance.meshID );
|
||||
instance.auxID = json["auxID"].as( instance.auxID );
|
||||
instance.objectID = json["objectID"].as( instance.objectID );
|
||||
instance.bounds.min = uf::vector::decode( json["bounds"]["min"], instance.bounds.min );
|
||||
instance.bounds.max = uf::vector::decode( json["bounds"]["max"], instance.bounds.max );
|
||||
@ -155,8 +156,8 @@ namespace {
|
||||
drawCommand.indexID = json["indexID"].as( drawCommand.indexID );
|
||||
drawCommand.vertexID = json["vertexID"].as( drawCommand.vertexID );
|
||||
drawCommand.instanceID = json["instanceID"].as( drawCommand.instanceID );
|
||||
// drawCommand.padding1 = json["padding1"].as( drawCommand.padding1 );
|
||||
// drawCommand.padding2 = json["padding2"].as( drawCommand.padding2 );
|
||||
drawCommand.auxID = json["auxID"].as( drawCommand.auxID );
|
||||
drawCommand.materialID = json["materialID"].as( drawCommand.materialID );
|
||||
drawCommand.vertices = json["vertices"].as( drawCommand.vertices );
|
||||
return drawCommand;
|
||||
}
|
||||
@ -225,12 +226,14 @@ namespace {
|
||||
|
||||
// remove extraneous buffers
|
||||
#if UF_USE_OPENGL
|
||||
/*
|
||||
for ( auto& attribute : mesh.vertex.attributes ) {
|
||||
if ( attribute.descriptor.name == "position" ) continue;
|
||||
if ( attribute.descriptor.name == "color" ) continue;
|
||||
if ( attribute.descriptor.name == "uv" ) continue;
|
||||
if ( attribute.descriptor.name == "st" ) continue;
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
|
||||
mesh.updateDescriptor();
|
||||
@ -293,6 +296,7 @@ pod::Graph uf::graph::load( const uf::stl::string& filename, const uf::Serialize
|
||||
auto name = value["name"].as<uf::stl::string>();
|
||||
/*graph.storage*/uf::graph::storage.instances[name] = decodeInstance( value, graph );
|
||||
graph.instances.emplace_back(name);
|
||||
UF_MSG_DEBUG( name );
|
||||
});
|
||||
});
|
||||
jobs.emplace_back([&]{
|
||||
@ -436,5 +440,10 @@ pod::Graph uf::graph::load( const uf::stl::string& filename, const uf::Serialize
|
||||
}
|
||||
}
|
||||
UF_DEBUG_TIMER_MULTITRACE_END("Processing graph...");
|
||||
|
||||
#if UF_ENV_DREAMCAST
|
||||
DC_STATS();
|
||||
#endif
|
||||
|
||||
return graph;
|
||||
}
|
||||
@ -118,6 +118,7 @@ namespace {
|
||||
json["materialID"] = instance.materialID;
|
||||
json["primitiveID"] = instance.primitiveID;
|
||||
json["meshID"] = instance.meshID;
|
||||
json["auxID"] = instance.auxID;
|
||||
json["objectID"] = instance.objectID;
|
||||
|
||||
json["bounds"]["min"] = uf::vector::encode( instance.bounds.min, settings );
|
||||
@ -132,8 +133,8 @@ namespace {
|
||||
json["indexID"] = drawCommand.indexID;
|
||||
json["vertexID"] = drawCommand.vertexID;
|
||||
json["instanceID"] = drawCommand.instanceID;
|
||||
// json["padding1"] = drawCommand.padding1;
|
||||
// json["padding2"] = drawCommand.padding2;
|
||||
json["auxID"] = drawCommand.auxID;
|
||||
json["materialID"] = drawCommand.materialID;
|
||||
json["vertices"] = drawCommand.vertices;
|
||||
return json;
|
||||
}
|
||||
@ -237,11 +238,13 @@ void uf::graph::save( const pod::Graph& graph, const uf::stl::string& filename )
|
||||
};
|
||||
if ( !settings.combined ) uf::io::mkdir(directory);
|
||||
#if UF_USE_XATLAS
|
||||
/*
|
||||
if ( settings.unwrap ) {
|
||||
pod::Graph& g = const_cast<pod::Graph&>(graph);
|
||||
auto size = ext::xatlas::unwrap( g );
|
||||
serializer["wrapped"] = uf::vector::encode( size );
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
|
||||
pod::Thread::container_t jobs;
|
||||
@ -426,11 +429,12 @@ void uf::graph::save( const pod::Graph& graph, const uf::stl::string& filename )
|
||||
#if UF_GRAPH_LOAD_MULTITHREAD
|
||||
if ( !jobs.empty() ) uf::thread::batchWorkers( jobs );
|
||||
#else
|
||||
for ( auto& job : jobs ) return job();
|
||||
for ( auto& job : jobs ) job();
|
||||
#endif
|
||||
|
||||
if ( !settings.combined ) target = directory + "/graph.json";
|
||||
serializer.writeToFile( target, settings );
|
||||
UF_MSG_DEBUG("Saving graph to `" << target << "`");
|
||||
}
|
||||
|
||||
uf::stl::string uf::graph::print( const pod::Graph& graph ) {
|
||||
|
||||
@ -10,12 +10,6 @@
|
||||
#include <uf/utils/memory/map.h>
|
||||
#include <uf/ext/xatlas/xatlas.h>
|
||||
|
||||
#if UF_ENV_DREAMCAST
|
||||
#define UF_GRAPH_LOAD_MULTITHREAD 1
|
||||
#else
|
||||
#define UF_GRAPH_LOAD_MULTITHREAD 1
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
bool newGraphAdded = true;
|
||||
}
|
||||
@ -144,11 +138,18 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity ) {
|
||||
graphic.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT);
|
||||
graphic.material.metadata.autoInitializeUniforms = true;
|
||||
}
|
||||
|
||||
uf::renderer::Buffer* indirect = NULL;
|
||||
for ( auto& buffer : graphic.buffers ) if ( !indirect && buffer.usage & uf::renderer::enums::Buffer::INDIRECT ) indirect = &buffer;
|
||||
|
||||
{
|
||||
auto& shader = graphic.material.getShader("vertex");
|
||||
|
||||
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.camera );
|
||||
// shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.drawCommands );
|
||||
// // shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.drawCommands );
|
||||
#if UF_USE_VULKAN
|
||||
shader.buffers.emplace_back().aliasBuffer( *indirect );
|
||||
#endif
|
||||
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.instance );
|
||||
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.joint );
|
||||
#if UF_USE_VULKAN
|
||||
@ -204,7 +205,9 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity ) {
|
||||
auto& shader = graphic.material.getShader("compute", "culling");
|
||||
|
||||
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.camera );
|
||||
#if UF_USE_VULKAN
|
||||
shader.buffers.emplace_back().aliasBuffer( *indirect );
|
||||
#endif
|
||||
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.instance );
|
||||
}
|
||||
}
|
||||
@ -299,8 +302,10 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity ) {
|
||||
{
|
||||
graphic.material.metadata.autoInitializeUniforms = false;
|
||||
uf::stl::string vertexShaderFilename = uf::io::resolveURI("/graph/baking/bake.vert.spv");
|
||||
uf::stl::string geometryShaderFilename = uf::io::resolveURI("/graph/baking/bake.geom.spv");
|
||||
uf::stl::string fragmentShaderFilename = uf::io::resolveURI("/graph/baking/bake.frag.spv");
|
||||
graphic.material.attachShader(vertexShaderFilename, uf::renderer::enums::Shader::VERTEX, "baking");
|
||||
graphic.material.attachShader(geometryShaderFilename, uf::renderer::enums::Shader::GEOMETRY, "baking");
|
||||
graphic.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT, "baking");
|
||||
graphic.material.metadata.autoInitializeUniforms = true;
|
||||
}
|
||||
@ -316,9 +321,13 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity ) {
|
||||
|
||||
// shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.camera );
|
||||
// shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.drawCommands );
|
||||
#if UF_USE_VULKAN
|
||||
shader.buffers.emplace_back().aliasBuffer( *indirect );
|
||||
#endif
|
||||
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.instance );
|
||||
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.joint );
|
||||
}
|
||||
|
||||
{
|
||||
size_t maxTextures = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["2D"].as<size_t>(512);
|
||||
size_t maxCubemaps = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["cube"].as<size_t>(128);
|
||||
@ -360,15 +369,65 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
|
||||
// process lightmap
|
||||
#if UF_USE_OPENGL
|
||||
#if UF_ENV_DREAMCAST
|
||||
#define UF_GRAPH_DEFAULT_LIGHTMAP "./lightmap.min.png"
|
||||
#else
|
||||
#define UF_GRAPH_DEFAULT_LIGHTMAP "./lightmap.png"
|
||||
#endif
|
||||
#define UF_GRAPH_DEFAULT_LIGHTMAP "./lightmap.%i.min.dtex"
|
||||
#else
|
||||
#define UF_GRAPH_DEFAULT_LIGHTMAP ""
|
||||
#define UF_GRAPH_DEFAULT_LIGHTMAP "./lightmap.%i.png"
|
||||
#endif
|
||||
{
|
||||
if ( graph.metadata["lightmap"].as<bool>() ) {
|
||||
uf::stl::unordered_map<size_t, uf::stl::string> filenames;
|
||||
uf::stl::unordered_map<size_t, size_t> lightmapIDs;
|
||||
|
||||
UF_MSG_DEBUG( graph.instances.size() );
|
||||
|
||||
for ( auto& name : graph.instances ) {
|
||||
auto& instance = uf::graph::storage.instances[name];
|
||||
// if ( !instance.auxID ) break;
|
||||
filenames[instance.auxID] = uf::string::replace(UF_GRAPH_DEFAULT_LIGHTMAP, "%i", std::to_string(instance.auxID));
|
||||
}
|
||||
for ( auto& name : graph.primitives ) {
|
||||
auto& primitives = uf::graph::storage.primitives[name];
|
||||
for ( auto& primitive : primitives ) {
|
||||
// if ( !primitive.instance.auxID ) break;
|
||||
filenames[primitive.instance.auxID] = uf::string::replace(UF_GRAPH_DEFAULT_LIGHTMAP, "%i", std::to_string(primitive.instance.auxID));
|
||||
}
|
||||
}
|
||||
for ( auto& pair : filenames ) {
|
||||
auto i = pair.first;
|
||||
auto f = uf::io::sanitize( pair.second, uf::io::directory( graph.name ) );
|
||||
|
||||
if ( !uf::io::exists( f ) ) {
|
||||
UF_MSG_ERROR( "lightmap does not exist: " << f )
|
||||
continue;
|
||||
}
|
||||
|
||||
auto textureID = graph.textures.size();
|
||||
auto imageID = graph.images.size();
|
||||
|
||||
auto& texture = /*graph.storage*/uf::graph::storage.textures[graph.textures.emplace_back(f)];
|
||||
auto& image = /*graph.storage*/uf::graph::storage.images[graph.images.emplace_back(f)];
|
||||
image.open( f, false );
|
||||
|
||||
texture.index = imageID;
|
||||
|
||||
lightmapIDs[i] = textureID;
|
||||
|
||||
graph.metadata["lightmaps"][i] = f;
|
||||
graph.metadata["baking"]["enabled"] = false;
|
||||
}
|
||||
|
||||
for ( auto& name : graph.instances ) {
|
||||
auto& instance = uf::graph::storage.instances[name];
|
||||
if ( lightmapIDs.count( instance.auxID ) == 0 ) continue;
|
||||
instance.lightmapID = lightmapIDs[instance.auxID];
|
||||
}
|
||||
for ( auto& name : graph.primitives ) {
|
||||
auto& primitives = uf::graph::storage.primitives[name];
|
||||
for ( auto& primitive : primitives ) {
|
||||
if ( lightmapIDs.count( primitive.instance.auxID ) == 0 ) continue;
|
||||
primitive.instance.lightmapID = lightmapIDs[primitive.instance.auxID];
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
const uf::stl::string lightmapFilename = graph.metadata["lightmap"].as<uf::stl::string>(UF_GRAPH_DEFAULT_LIGHTMAP);
|
||||
// load lightmap, if requested
|
||||
if ( lightmapFilename != "" ) {
|
||||
@ -399,6 +458,7 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
graph.metadata["baking"]["enabled"] = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// add atlas
|
||||
|
||||
@ -430,6 +490,7 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
if ( !texture.generated() ) {
|
||||
bool isLightmap = graph.metadata["lightmapped"].as<uf::stl::string>() == key;
|
||||
auto filter = graph.metadata["filter"].as<uf::stl::string>() == "NEAREST" && !isLightmap ? uf::renderer::enums::Filter::NEAREST : uf::renderer::enums::Filter::LINEAR;
|
||||
// auto filter = uf::renderer::enums::Filter::LINEAR;
|
||||
texture.sampler.descriptor.filter.min = filter;
|
||||
texture.sampler.descriptor.filter.mag = filter;
|
||||
|
||||
@ -585,8 +646,8 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
mesh.insertInstances( m );
|
||||
|
||||
// mesh.insertIndirects( m );
|
||||
pod::DrawCommand* dc = (pod::DrawCommand*) m.getBuffer( m.indirect ).data();
|
||||
for ( size_t i = 0; i < m.indirect.count; ++i ) drawCommands.emplace_back( dc[i] );
|
||||
pod::DrawCommand* drawCommand = (pod::DrawCommand*) m.getBuffer( m.indirect ).data();
|
||||
for ( size_t i = 0; i < m.indirect.count; ++i ) drawCommands.emplace_back( drawCommand[i] );
|
||||
}
|
||||
|
||||
// fix up draw command for combined mesh
|
||||
@ -641,32 +702,44 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
|
||||
auto& metadataJson = entity.getComponent<uf::Serializer>();
|
||||
metadataJson["system"]["graph"]["name"] = node.name;
|
||||
metadataJson["system"]["graph"]["index"] = index;
|
||||
|
||||
// on systems where frametime is very, very important, we can set all static nodes to not tick
|
||||
|
||||
// tie to tag
|
||||
if ( !ext::json::isNull( graph.metadata["tags"][node.name] ) ) {
|
||||
auto& info = graph.metadata["tags"][node.name];
|
||||
if ( info["ignore"].as<bool>() ) {
|
||||
return;
|
||||
{
|
||||
ext::json::Value info = ext::json::null();
|
||||
if ( ext::json::isObject( graph.metadata["tags"][node.name] ) ) {
|
||||
info = graph.metadata["tags"][node.name];
|
||||
} else {
|
||||
ext::json::forEach( graph.metadata["tags"], [&]( const uf::stl::string& key, ext::json::Value& value ) {
|
||||
if ( !uf::string::isRegex( key ) ) return;
|
||||
if ( uf::string::matches( node.name, key ).empty() ) return;
|
||||
info = value;
|
||||
});
|
||||
}
|
||||
if ( info["action"].as<uf::stl::string>() == "load" ) {
|
||||
if ( info["filename"].is<uf::stl::string>() ) {
|
||||
if ( ext::json::isObject( info ) ) {
|
||||
if ( info["ignore"].as<bool>() ) return;
|
||||
|
||||
if ( info["action"].as<uf::stl::string>() == "load" ) {
|
||||
if ( info["filename"].is<uf::stl::string>() ) {
|
||||
uf::stl::string filename = uf::io::resolveURI( info["filename"].as<uf::stl::string>(), graph.metadata["root"].as<uf::stl::string>() );
|
||||
entity.load(filename);
|
||||
} else if ( ext::json::isObject( info["payload"] ) ) {
|
||||
uf::Serializer json = info["payload"];
|
||||
json["root"] = graph.metadata["root"];
|
||||
entity.load(json);
|
||||
}
|
||||
} else if ( info["action"].as<uf::stl::string>() == "attach" ) {
|
||||
uf::stl::string filename = uf::io::resolveURI( info["filename"].as<uf::stl::string>(), graph.metadata["root"].as<uf::stl::string>() );
|
||||
entity.load(filename);
|
||||
} else if ( ext::json::isObject( info["payload"] ) ) {
|
||||
uf::Serializer json = info["payload"];
|
||||
json["root"] = graph.metadata["root"];
|
||||
entity.load(json);
|
||||
auto& child = entity.loadChild( filename, false );
|
||||
auto& childTransform = child.getComponent<pod::Transform<>>();
|
||||
auto flatten = uf::transform::flatten( node.transform );
|
||||
if ( !info["preserve position"].as<bool>() ) childTransform.position = flatten.position;
|
||||
if ( !info["preserve orientation"].as<bool>() ) childTransform.orientation = flatten.orientation;
|
||||
}
|
||||
if ( info["static"].is<bool>() ) {
|
||||
metadata.system.ignoreGraph = info["static"].as<bool>();
|
||||
}
|
||||
} else if ( info["action"].as<uf::stl::string>() == "attach" ) {
|
||||
uf::stl::string filename = uf::io::resolveURI( info["filename"].as<uf::stl::string>(), graph.metadata["root"].as<uf::stl::string>() );
|
||||
auto& child = entity.loadChild( filename, false );
|
||||
auto& childTransform = child.getComponent<pod::Transform<>>();
|
||||
auto flatten = uf::transform::flatten( node.transform );
|
||||
if ( !info["preserve position"].as<bool>() ) childTransform.position = flatten.position;
|
||||
if ( !info["preserve orientation"].as<bool>() ) childTransform.orientation = flatten.orientation;
|
||||
}
|
||||
if ( info["static"].is<bool>() ) {
|
||||
metadata.system.ignoreGraph = info["static"].as<bool>();
|
||||
}
|
||||
}
|
||||
// create as light
|
||||
@ -1014,7 +1087,7 @@ void uf::graph::destroy( pod::Graph& graph ) {
|
||||
#endif
|
||||
|
||||
uf::graph::storage.buffers.camera.destroy();
|
||||
// uf::graph::storage.buffers.drawCommands.destroy();
|
||||
uf::graph::storage.buffers.drawCommands.destroy();
|
||||
uf::graph::storage.buffers.instance.destroy();
|
||||
uf::graph::storage.buffers.joint.destroy();
|
||||
uf::graph::storage.buffers.material.destroy();
|
||||
@ -1029,7 +1102,7 @@ void uf::graph::initialize() {
|
||||
const size_t MAX_SIZE = 1024;
|
||||
#endif
|
||||
uf::graph::storage.buffers.camera.initialize( (const void*) nullptr, sizeof(pod::Camera::Viewports), uf::renderer::enums::Buffer::UNIFORM );
|
||||
// uf::graph::storage.buffers.drawCommands.initialize( (const void*) nullptr, sizeof(pod::DrawCommand) * MAX_SIZE, uf::renderer::enums::Buffer::STORAGE );
|
||||
uf::graph::storage.buffers.drawCommands.initialize( (const void*) nullptr, sizeof(pod::DrawCommand) * MAX_SIZE, uf::renderer::enums::Buffer::STORAGE );
|
||||
uf::graph::storage.buffers.instance.initialize( (const void*) nullptr, sizeof(pod::Instance) * MAX_SIZE, uf::renderer::enums::Buffer::STORAGE );
|
||||
uf::graph::storage.buffers.joint.initialize( (const void*) nullptr, sizeof(pod::Matrix4f) * MAX_SIZE, uf::renderer::enums::Buffer::STORAGE );
|
||||
uf::graph::storage.buffers.material.initialize( (const void*) nullptr, sizeof(pod::Material) * MAX_SIZE, uf::renderer::enums::Buffer::STORAGE );
|
||||
@ -1073,7 +1146,7 @@ void uf::graph::tick() {
|
||||
}
|
||||
for ( auto pair : textureOrderedMap ) textures.emplace_back( uf::graph::storage.textures.map[pair.second] );
|
||||
#endif
|
||||
// uf::graph::storage.buffers.drawCommands.update( (const void*) drawCommands.data(), drawCommands.size() * sizeof(pod::DrawCommand) );
|
||||
uf::graph::storage.buffers.drawCommands.update( (const void*) drawCommands.data(), drawCommands.size() * sizeof(pod::DrawCommand) );
|
||||
uf::graph::storage.buffers.material.update( (const void*) materials.data(), materials.size() * sizeof(pod::Material) );
|
||||
uf::graph::storage.buffers.texture.update( (const void*) textures.data(), textures.size() * sizeof(pod::Texture) );
|
||||
::newGraphAdded = false;
|
||||
|
||||
@ -19,6 +19,9 @@
|
||||
|
||||
#include <gltf/tiny_gltf.h>
|
||||
#include <uf/ext/gltf/gltf.h>
|
||||
#if UF_USE_XATLAS
|
||||
#include <uf/ext/xatlas/xatlas.h>
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
decltype(auto) getWrapMode(int32_t wrapMode) {
|
||||
@ -500,8 +503,18 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
|
||||
texture.index = atlasImageIndex;
|
||||
}
|
||||
}
|
||||
// generate STs
|
||||
#if UF_USE_XATLAS
|
||||
{
|
||||
UF_MSG_DEBUG( "Generating ST's..." );
|
||||
size_t atlases = ext::xatlas::unwrap( graph );
|
||||
UF_MSG_DEBUG( "Generated ST's for " << atlases << " lightmaps" );
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( graph.metadata["exporter"]["enabled"].as<bool>() ) uf::graph::save( graph, filename );
|
||||
if ( graph.metadata["exporter"]["enabled"].as<bool>() ) {
|
||||
uf::graph::save( graph, filename );
|
||||
}
|
||||
return graph;
|
||||
}
|
||||
#endif
|
||||
@ -171,7 +171,9 @@ for ( auto& p : m.primitives ) {
|
||||
|
||||
if ( meshgrid.grid.divisions.x > 1 && meshgrid.grid.divisions.y > 1 && meshgrid.grid.divisions.z > 1 ) {
|
||||
auto partitioned = uf::meshgrid::partition( meshgrid.grid, meshlets, meshgrid.eps );
|
||||
if ( meshgrid.print ) UF_MSG_DEBUG( "Draw commands: " << m.name << ": " << meshlets.size() << " -> " << partitioned.size() );
|
||||
if ( meshgrid.print ) UF_MSG_DEBUG( "Draw commands: " << m.name << ": " << meshlets.size() << " -> " << partitioned.size() << " | Partitions: " <<
|
||||
(meshgrid.grid.divisions.x * meshgrid.grid.divisions.y * meshgrid.grid.divisions.z) << " -> " << meshgrid.grid.nodes.size()
|
||||
);
|
||||
meshlets = std::move( partitioned );
|
||||
}
|
||||
|
||||
@ -183,16 +185,17 @@ if ( meshgrid.grid.divisions.x > 1 && meshgrid.grid.divisions.y > 1 && meshgrid.
|
||||
mesh.bind<UF_GRAPH_MESH_FORMAT>();
|
||||
|
||||
for ( auto& meshlet : meshlets ) {
|
||||
drawCommands.emplace_back(pod::DrawCommand{
|
||||
auto& drawCommand = drawCommands.emplace_back(pod::DrawCommand{
|
||||
.indices = meshlet.indices.size(),
|
||||
.instances = 1,
|
||||
.indexID = indexID,
|
||||
.vertexID = vertexID,
|
||||
.instanceID = 0,
|
||||
|
||||
|
||||
.auxID = meshlet.primitive.drawCommand.auxID,
|
||||
.materialID = meshlet.primitive.drawCommand.materialID,
|
||||
.vertices = meshlet.vertices.size(),
|
||||
});
|
||||
//UF_MSG_DEBUG( );
|
||||
|
||||
primitives.emplace_back( meshlet.primitive );
|
||||
|
||||
|
||||
@ -295,10 +295,11 @@ void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer::
|
||||
GL_ERROR_CHECK(glEnable(drawInfo.textures.primary.viewType));
|
||||
GL_ERROR_CHECK(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
|
||||
GL_ERROR_CHECK(glBindTexture(drawInfo.textures.primary.viewType, drawInfo.textures.primary.image));
|
||||
GL_ERROR_CHECK(glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE));
|
||||
GL_ERROR_CHECK(glTexCoordPointer(2, GL_FLOAT, drawInfo.attributes.uv.stride, (drawInfo.attributes.uv.pointer + drawInfo.attributes.uv.stride * drawInfo.descriptor.inputs.vertex.first)));
|
||||
|
||||
if ( drawInfo.textures.secondary.image && drawInfo.attributes.st.pointer ) {
|
||||
GL_ERROR_CHECK(glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE));
|
||||
|
||||
// static GLuint previous = 0;
|
||||
// if ( previous != drawInfo.textures.secondary.image ) previous = drawInfo.textures.secondary.image;
|
||||
|
||||
|
||||
@ -137,7 +137,7 @@ spec::Context& ext::opengl::Device::activateContext( std::thread::id id ) {
|
||||
bool exists = this->contexts.has(id);
|
||||
auto& context = this->contexts.get(id);
|
||||
if ( !exists ) {
|
||||
context = (spec::Context*) spec::uni::Context::create( contextSettings, *this->window->getHandle() );
|
||||
context = (spec::Context*) spec::uni::Context::create( contextSettings, *this->window );
|
||||
}
|
||||
context->setActive(true);
|
||||
return *context;
|
||||
|
||||
@ -74,7 +74,8 @@ void ext::opengl::BaseRenderMode::initialize( Device& device ) {
|
||||
GL_ERROR_CHECK(glEnable(GL_BLEND));
|
||||
GL_ERROR_CHECK(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||
|
||||
// GL_ERROR_CHECK(glEnable(GL_LIGHTING));
|
||||
GL_ERROR_CHECK(glEnable(GL_LIGHTING));
|
||||
|
||||
// GL_ERROR_CHECK(glEnable(GL_NORMALIZE));
|
||||
// GL_ERROR_CHECK(glEnable(GL_COLOR_MATERIAL));
|
||||
// GL_ERROR_CHECK(glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE));
|
||||
|
||||
@ -210,13 +210,25 @@ void ext::opengl::Texture::fromBuffers(
|
||||
this->initialize(device, viewType, texWidth, texHeight, texDepth, layers);
|
||||
this->format = format;
|
||||
|
||||
#if !UF_ENV_DREAMCAST
|
||||
#if UF_ENV_DREAMCAST
|
||||
if ( internalFormat > 0 ) {
|
||||
this->mips = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( this->mips == 0 ) {
|
||||
this->mips = 1;
|
||||
} else if ( this->depth == 1 ) {
|
||||
this->mips = static_cast<uint32_t>(std::floor(std::log2(std::max(texWidth, texHeight)))) + 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( this->mips > 1 ) {
|
||||
switch ( sampler.descriptor.filter.min ) {
|
||||
case GL_LINEAR: sampler.descriptor.filter.min = GL_LINEAR_MIPMAP_LINEAR; break;
|
||||
case GL_NEAREST: sampler.descriptor.filter.min = GL_NEAREST_MIPMAP_NEAREST; break;
|
||||
}
|
||||
}
|
||||
|
||||
// Create sampler
|
||||
sampler.descriptor.mip.min = 0;
|
||||
sampler.descriptor.mip.max = static_cast<float>(this->mips);
|
||||
@ -267,6 +279,7 @@ void ext::opengl::Texture::update( void* data, size_t bufferSize, uint32_t layer
|
||||
GL_MUTEX_LOCK();
|
||||
GL_ERROR_CHECK(glBindTexture(viewType, image));
|
||||
GL_ERROR_CHECK(glCompressedTexImage2DARB( viewType, 0, internalFormat, width, height, 0, bufferSize, data));
|
||||
if ( this->mips > 1 ) GL_ERROR_CHECK(glGenerateMipmapEXT(GL_TEXTURE_2D));
|
||||
GL_ERROR_CHECK(glBindTexture(viewType, 0));
|
||||
GL_MUTEX_UNLOCK();
|
||||
return;
|
||||
@ -305,6 +318,7 @@ void ext::opengl::Texture::update( void* data, size_t bufferSize, uint32_t layer
|
||||
case enums::Image::VIEW_TYPE_3D: { GL_ERROR_CHECK(glTexImage3D(viewType, 0, format, width, height, depth, 0, format, type, data)); } break;
|
||||
#endif
|
||||
}
|
||||
if ( this->mips > 1 ) GL_ERROR_CHECK(glGenerateMipmapEXT(GL_TEXTURE_2D));
|
||||
GL_ERROR_CHECK(glBindTexture(viewType, 0));
|
||||
GL_MUTEX_UNLOCK();
|
||||
}
|
||||
|
||||
@ -760,6 +760,7 @@ void ext::vulkan::Device::initialize() {
|
||||
VkPhysicalDeviceFeatures2 physicalDeviceFeatures2{};
|
||||
VkPhysicalDeviceDescriptorIndexingFeatures descriptorIndexingFeatures{};
|
||||
VkPhysicalDeviceShaderDrawParametersFeatures shaderDrawParametersFeatures{};
|
||||
VkPhysicalDeviceRobustness2FeaturesEXT robustnessFeatures{};
|
||||
{
|
||||
deviceCreateInfo.pEnabledFeatures = nullptr;
|
||||
deviceCreateInfo.pNext = &physicalDeviceFeatures2;
|
||||
@ -780,6 +781,11 @@ void ext::vulkan::Device::initialize() {
|
||||
{
|
||||
shaderDrawParametersFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES;
|
||||
shaderDrawParametersFeatures.shaderDrawParameters = VK_TRUE;
|
||||
shaderDrawParametersFeatures.pNext = &robustnessFeatures;
|
||||
}
|
||||
{
|
||||
robustnessFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT;
|
||||
robustnessFeatures.nullDescriptor = VK_TRUE;
|
||||
}
|
||||
|
||||
if ( vkCreateDevice( this->physicalDevice, &deviceCreateInfo, nullptr, &this->logicalDevice) != VK_SUCCESS ) {
|
||||
|
||||
@ -364,6 +364,7 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
|
||||
|
||||
uf::stl::vector<VkDescriptorImageInfo> image;
|
||||
uf::stl::vector<VkDescriptorImageInfo> image2D;
|
||||
uf::stl::vector<VkDescriptorImageInfo> image2DA;
|
||||
uf::stl::vector<VkDescriptorImageInfo> imageCube;
|
||||
uf::stl::vector<VkDescriptorImageInfo> image3D;
|
||||
uf::stl::vector<VkDescriptorImageInfo> imageUnknown;
|
||||
@ -393,6 +394,7 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
|
||||
infos.image.emplace_back(texture.descriptor);
|
||||
switch ( texture.viewType ) {
|
||||
case VK_IMAGE_VIEW_TYPE_2D: infos.image2D.emplace_back(texture.descriptor); break;
|
||||
case VK_IMAGE_VIEW_TYPE_2D_ARRAY: infos.image2DA.emplace_back(texture.descriptor); break;
|
||||
case VK_IMAGE_VIEW_TYPE_CUBE: infos.imageCube.emplace_back(texture.descriptor); break;
|
||||
case VK_IMAGE_VIEW_TYPE_3D: infos.image3D.emplace_back(texture.descriptor); break;
|
||||
default: infos.imageUnknown.emplace_back(texture.descriptor); break;
|
||||
@ -424,6 +426,7 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
|
||||
}
|
||||
|
||||
size_t maxTextures2D = 0;
|
||||
size_t maxTextures2DA = 0;
|
||||
size_t maxTextures3D = 0;
|
||||
size_t maxTexturesCube = 0;
|
||||
size_t maxTexturesUnknown = 0;
|
||||
@ -431,10 +434,12 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
|
||||
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 if ( type == ext::vulkan::enums::Image::VIEW_TYPE_2D_ARRAY ) ++maxTextures2DA;
|
||||
else ++maxTexturesUnknown;
|
||||
}
|
||||
|
||||
while ( infos.image2D.size() < maxTextures2D ) infos.image2D.emplace_back(Texture2D::empty.descriptor);
|
||||
while ( infos.image2DA.size() < maxTextures2DA ) infos.image2DA.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);
|
||||
@ -452,6 +457,7 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
|
||||
|
||||
auto imageInfo = infos.image.begin();
|
||||
auto image2DInfo = infos.image2D.begin();
|
||||
auto image2DAInfo = infos.image2DA.begin();
|
||||
auto imageCubeInfo = infos.imageCube.begin();
|
||||
auto image3DInfo = infos.image3D.begin();
|
||||
auto imageUnknownInfo = infos.imageUnknown.begin();
|
||||
@ -476,6 +482,16 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
|
||||
layout.descriptorCount
|
||||
));
|
||||
image2DInfo += layout.descriptorCount;
|
||||
} else if ( imageType == ext::vulkan::enums::Image::VIEW_TYPE_2D_ARRAY ) {
|
||||
UF_ASSERT_BREAK_MSG( image2DAInfo != infos.image2DA.end(), "Filename: " << shader->filename << "\tCount: " << layout.descriptorCount )
|
||||
writeDescriptorSets.emplace_back(ext::vulkan::initializers::writeDescriptorSet(
|
||||
descriptorSet,
|
||||
layout.descriptorType,
|
||||
layout.binding,
|
||||
&(*image2DAInfo),
|
||||
layout.descriptorCount
|
||||
));
|
||||
image2DAInfo += layout.descriptorCount;
|
||||
} else if ( imageType == ext::vulkan::enums::Image::VIEW_TYPE_CUBE ) {
|
||||
UF_ASSERT_BREAK_MSG( imageCubeInfo != infos.imageCube.end(), "Filename: " << shader->filename << "\tCount: " << layout.descriptorCount )
|
||||
writeDescriptorSets.emplace_back(ext::vulkan::initializers::writeDescriptorSet(
|
||||
|
||||
@ -41,10 +41,10 @@ uf::stl::vector<ext::vulkan::Graphic*> ext::vulkan::RenderMode::getBlitters() {
|
||||
return {};
|
||||
}
|
||||
|
||||
uf::Image ext::vulkan::RenderMode::screenshot( size_t i ) {
|
||||
uf::Image ext::vulkan::RenderMode::screenshot( size_t attachmentID, size_t layerID ) {
|
||||
uf::Image image;
|
||||
if ( !device || renderTarget.attachments.size() < i ) return image;
|
||||
auto& attachment = renderTarget.attachments[i];
|
||||
if ( !device || renderTarget.attachments.size() < attachmentID ) return image;
|
||||
auto& attachment = renderTarget.attachments[attachmentID];
|
||||
|
||||
bool blitting = true;
|
||||
VkFormatProperties formatProperties;
|
||||
@ -92,6 +92,7 @@ uf::Image ext::vulkan::RenderMode::screenshot( size_t i ) {
|
||||
vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
|
||||
|
||||
imageMemoryBarrier.image = attachment.image;
|
||||
imageMemoryBarrier.subresourceRange.baseArrayLayer = layerID;
|
||||
imageMemoryBarrier.oldLayout = attachment.descriptor.layout;
|
||||
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
|
||||
@ -104,9 +105,11 @@ uf::Image ext::vulkan::RenderMode::screenshot( size_t i ) {
|
||||
|
||||
VkImageResolve imageResolveRegion{};
|
||||
imageResolveRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
imageResolveRegion.srcSubresource.baseArrayLayer = layerID;
|
||||
imageResolveRegion.srcSubresource.layerCount = 1;
|
||||
// imageResolveRegion.srcOffsets[1] = blitSize;
|
||||
imageResolveRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
imageResolveRegion.dstSubresource.baseArrayLayer = 0;
|
||||
imageResolveRegion.dstSubresource.layerCount = 1;
|
||||
// imageResolveRegion.dstOffsets[1] = blitSize;
|
||||
imageResolveRegion.extent = { renderTarget.width, renderTarget.height, 1 };
|
||||
@ -120,9 +123,11 @@ uf::Image ext::vulkan::RenderMode::screenshot( size_t i ) {
|
||||
|
||||
VkImageBlit imageBlit{};
|
||||
imageBlit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
imageBlit.srcSubresource.baseArrayLayer = layerID;
|
||||
imageBlit.srcSubresource.layerCount = 1;
|
||||
imageBlit.srcOffsets[1] = blitSize;
|
||||
imageBlit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
imageBlit.dstSubresource.baseArrayLayer = 0;
|
||||
imageBlit.dstSubresource.layerCount = 1;
|
||||
imageBlit.dstOffsets[1] = blitSize;
|
||||
|
||||
@ -130,8 +135,10 @@ uf::Image ext::vulkan::RenderMode::screenshot( size_t i ) {
|
||||
} else {
|
||||
VkImageCopy imageCopy{};
|
||||
imageCopy.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
imageCopy.srcSubresource.baseArrayLayer = layerID;
|
||||
imageCopy.srcSubresource.layerCount = 1;
|
||||
imageCopy.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
imageCopy.dstSubresource.baseArrayLayer = 0;
|
||||
imageCopy.dstSubresource.layerCount = 1;
|
||||
imageCopy.extent = { renderTarget.width, renderTarget.height, 1 };
|
||||
|
||||
@ -141,11 +148,13 @@ uf::Image ext::vulkan::RenderMode::screenshot( size_t i ) {
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
|
||||
|
||||
imageMemoryBarrier.image = temporary;
|
||||
imageMemoryBarrier.subresourceRange.baseArrayLayer = 0;
|
||||
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
|
||||
|
||||
imageMemoryBarrier.image = attachment.image;
|
||||
imageMemoryBarrier.subresourceRange.baseArrayLayer = layerID;
|
||||
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
imageMemoryBarrier.newLayout = attachment.descriptor.layout;
|
||||
vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
|
||||
|
||||
@ -61,6 +61,7 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
|
||||
uint8_t msaa = ext::vulkan::sampleCount(metadata.samples);
|
||||
if ( metadata.subpasses == 0 ) metadata.subpasses = 1;
|
||||
renderTarget.device = &device;
|
||||
renderTarget.views = metadata.views;
|
||||
if ( metadata.type == "depth" || metadata.type == "vxgi" ) {
|
||||
renderTarget.views = metadata.subpasses;
|
||||
struct {
|
||||
|
||||
@ -100,7 +100,10 @@ size_t ext::vulkan::RenderTarget::attach( const Attachment::Descriptor& descript
|
||||
}
|
||||
VkImageViewCreateInfo imageView = {};
|
||||
imageView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
imageView.viewType = this->views == 6 ? VK_IMAGE_VIEW_TYPE_CUBE : VK_IMAGE_VIEW_TYPE_2D;
|
||||
imageView.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
if ( this->views > 1 ) {
|
||||
imageView.viewType = this->views == 6 ? VK_IMAGE_VIEW_TYPE_CUBE : VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||
}
|
||||
imageView.format = attachment->descriptor.format;
|
||||
imageView.subresourceRange = {};
|
||||
imageView.subresourceRange.aspectMask = aspectMask;
|
||||
|
||||
@ -85,6 +85,18 @@ void ext::vulkan::Texture::initialize( Device& device, size_t width, size_t heig
|
||||
this->layers = layers;
|
||||
|
||||
// implicitly set type
|
||||
if ( width > 1 && height == 1 && depth == 1 ) {
|
||||
this->type = ext::vulkan::enums::Image::TYPE_1D;
|
||||
this->viewType = layers == 1 ? ext::vulkan::enums::Image::VIEW_TYPE_1D : ext::vulkan::enums::Image::VIEW_TYPE_1D_ARRAY;
|
||||
} else if ( height > 1 && depth == 1 ) {
|
||||
this->type = ext::vulkan::enums::Image::TYPE_2D;
|
||||
this->viewType = layers == 1 ? ext::vulkan::enums::Image::VIEW_TYPE_2D : ext::vulkan::enums::Image::VIEW_TYPE_2D_ARRAY;
|
||||
if ( layers == 6 ) this->viewType = ext::vulkan::enums::Image::VIEW_TYPE_CUBE;
|
||||
} else {
|
||||
this->type = ext::vulkan::enums::Image::TYPE_3D;
|
||||
this->viewType = layers == 6 ? ext::vulkan::enums::Image::VIEW_TYPE_CUBE_ARRAY : ext::vulkan::enums::Image::VIEW_TYPE_3D;
|
||||
}
|
||||
/*
|
||||
if ( width > 1 && height > 1 && depth > 1 ) {
|
||||
this->type = ext::vulkan::enums::Image::TYPE_3D;
|
||||
} else if ( (width == 1 && height > 1 && depth > 1) || (width > 1 && height == 1 && depth > 1) || (width > 1 && height > 1 && depth == 1) ) {
|
||||
@ -92,6 +104,7 @@ void ext::vulkan::Texture::initialize( Device& device, size_t width, size_t heig
|
||||
} else if ( (width > 1 && height == 1 && depth == 1) || (width == 1 && height > 1 && depth == 1) || (width == 1 && height == 1 && depth > 1) ) {
|
||||
this->type = ext::vulkan::enums::Image::TYPE_1D;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
if ( layers > 1 ) {
|
||||
if ( viewType == ext::vulkan::enums::Image::VIEW_TYPE_1D ) viewType = ext::vulkan::enums::Image::VIEW_TYPE_1D_ARRAY;
|
||||
@ -818,6 +831,227 @@ void ext::vulkan::Texture::generateMipmaps( VkCommandBuffer commandBuffer, uint3
|
||||
}
|
||||
}
|
||||
|
||||
uf::Image ext::vulkan::Texture2D::screenshot( uint32_t layerID ) {
|
||||
uf::Image image;
|
||||
if ( !device ) return image;
|
||||
|
||||
bool blitting = true;
|
||||
VkFormatProperties formatProperties;
|
||||
vkGetPhysicalDeviceFormatProperties(device->physicalDevice, this->format, &formatProperties);
|
||||
if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_SRC_BIT)) blitting = false;
|
||||
vkGetPhysicalDeviceFormatProperties(device->physicalDevice, VK_FORMAT_R8G8B8A8_UNORM, &formatProperties);
|
||||
if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT)) blitting = false;
|
||||
|
||||
VkImage temporary;
|
||||
VkImageCreateInfo imageCreateInfo = {};
|
||||
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
|
||||
imageCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
imageCreateInfo.extent = { this->width, this->height, 1 };
|
||||
imageCreateInfo.mipLevels = 1;
|
||||
imageCreateInfo.arrayLayers = 1;
|
||||
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
imageCreateInfo.tiling = VK_IMAGE_TILING_LINEAR;
|
||||
imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
VmaAllocation allocation;
|
||||
VmaAllocationInfo allocationInfo;
|
||||
VmaAllocationCreateInfo allocationCreateInfo = {};
|
||||
allocationCreateInfo.usage = VMA_MEMORY_USAGE_GPU_TO_CPU;
|
||||
VK_CHECK_RESULT(vmaCreateImage(allocator, &imageCreateInfo, &allocationCreateInfo, &temporary, &allocation, &allocationInfo));
|
||||
VkDeviceMemory temporaryMemory = allocationInfo.deviceMemory;
|
||||
|
||||
VkCommandBuffer copyCmd = device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
|
||||
|
||||
VkImageMemoryBarrier imageMemoryBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
|
||||
imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics; //VK_QUEUE_FAMILY_IGNORED
|
||||
imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics; //VK_QUEUE_FAMILY_IGNORED
|
||||
imageMemoryBarrier.subresourceRange.baseMipLevel = 0;
|
||||
imageMemoryBarrier.subresourceRange.levelCount = 1;
|
||||
imageMemoryBarrier.subresourceRange.baseArrayLayer = 0;
|
||||
imageMemoryBarrier.subresourceRange.layerCount = 1;
|
||||
imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
imageMemoryBarrier.srcAccessMask = 0;
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
|
||||
imageMemoryBarrier.image = temporary;
|
||||
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
|
||||
|
||||
imageMemoryBarrier.image = this->image;
|
||||
imageMemoryBarrier.subresourceRange.baseArrayLayer = layerID;
|
||||
imageMemoryBarrier.oldLayout = descriptor.imageLayout;
|
||||
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
|
||||
|
||||
if ( blitting ) {
|
||||
VkOffset3D blitSize;
|
||||
blitSize.x = this->width;
|
||||
blitSize.y = this->height;
|
||||
blitSize.z = 1;
|
||||
|
||||
VkImageBlit imageBlit{};
|
||||
imageBlit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
imageBlit.srcSubresource.baseArrayLayer = layerID;
|
||||
imageBlit.srcSubresource.layerCount = 1;
|
||||
imageBlit.srcOffsets[1] = blitSize;
|
||||
imageBlit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
imageBlit.dstSubresource.baseArrayLayer = 0;
|
||||
imageBlit.dstSubresource.layerCount = 1;
|
||||
imageBlit.dstOffsets[1] = blitSize;
|
||||
|
||||
vkCmdBlitImage( copyCmd, this->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, temporary, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageBlit, VK_FILTER_NEAREST);
|
||||
} else {
|
||||
VkImageCopy imageCopy{};
|
||||
imageCopy.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
imageCopy.srcSubresource.baseArrayLayer = layerID;
|
||||
imageCopy.srcSubresource.layerCount = 1;
|
||||
imageCopy.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
imageCopy.dstSubresource.baseArrayLayer = 0;
|
||||
imageCopy.dstSubresource.layerCount = 1;
|
||||
imageCopy.extent = { this->width, this->height, 1 };
|
||||
|
||||
vkCmdCopyImage( copyCmd, this->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, temporary, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageCopy );
|
||||
}
|
||||
imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
|
||||
|
||||
imageMemoryBarrier.image = temporary;
|
||||
imageMemoryBarrier.subresourceRange.baseArrayLayer = 0;
|
||||
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
|
||||
|
||||
imageMemoryBarrier.image = this->image;
|
||||
imageMemoryBarrier.subresourceRange.baseArrayLayer = layerID;
|
||||
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
imageMemoryBarrier.newLayout = descriptor.imageLayout;
|
||||
vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
|
||||
device->flushCommandBuffer(copyCmd, true);
|
||||
|
||||
const uint8_t* data;
|
||||
vmaMapMemory( allocator, allocation, (void**)&data );
|
||||
image.loadFromBuffer( data, {this->width, this->height}, 8, 4, false );
|
||||
vmaUnmapMemory( allocator, allocation );
|
||||
vmaDestroyImage(allocator, temporary, allocation);
|
||||
return image;
|
||||
}
|
||||
|
||||
uf::Image ext::vulkan::Texture3D::screenshot( uint32_t layerID ) {
|
||||
uf::Image image;
|
||||
if ( !device ) return image;
|
||||
|
||||
bool blitting = true;
|
||||
VkFormatProperties formatProperties;
|
||||
vkGetPhysicalDeviceFormatProperties(device->physicalDevice, this->format, &formatProperties);
|
||||
if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_SRC_BIT)) blitting = false;
|
||||
vkGetPhysicalDeviceFormatProperties(device->physicalDevice, VK_FORMAT_R8G8B8A8_UNORM, &formatProperties);
|
||||
if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT)) blitting = false;
|
||||
|
||||
VkImage temporary;
|
||||
VkImageCreateInfo imageCreateInfo = {};
|
||||
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
|
||||
imageCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
imageCreateInfo.extent = { this->width, this->height, 1 };
|
||||
imageCreateInfo.mipLevels = 1;
|
||||
imageCreateInfo.arrayLayers = 1;
|
||||
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
imageCreateInfo.tiling = VK_IMAGE_TILING_LINEAR;
|
||||
imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
VmaAllocation allocation;
|
||||
VmaAllocationInfo allocationInfo;
|
||||
VmaAllocationCreateInfo allocationCreateInfo = {};
|
||||
allocationCreateInfo.usage = VMA_MEMORY_USAGE_GPU_TO_CPU;
|
||||
VK_CHECK_RESULT(vmaCreateImage(allocator, &imageCreateInfo, &allocationCreateInfo, &temporary, &allocation, &allocationInfo));
|
||||
VkDeviceMemory temporaryMemory = allocationInfo.deviceMemory;
|
||||
|
||||
VkCommandBuffer copyCmd = device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
|
||||
|
||||
VkImageMemoryBarrier imageMemoryBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
|
||||
imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics; //VK_QUEUE_FAMILY_IGNORED
|
||||
imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics; //VK_QUEUE_FAMILY_IGNORED
|
||||
imageMemoryBarrier.subresourceRange.baseMipLevel = 0;
|
||||
imageMemoryBarrier.subresourceRange.levelCount = 1;
|
||||
imageMemoryBarrier.subresourceRange.baseArrayLayer = 0;
|
||||
imageMemoryBarrier.subresourceRange.layerCount = 1;
|
||||
imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
imageMemoryBarrier.srcAccessMask = 0;
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
|
||||
imageMemoryBarrier.image = temporary;
|
||||
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
|
||||
|
||||
imageMemoryBarrier.image = this->image;
|
||||
imageMemoryBarrier.subresourceRange.baseArrayLayer = 0;
|
||||
imageMemoryBarrier.oldLayout = descriptor.imageLayout;
|
||||
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
|
||||
|
||||
if ( blitting ) {
|
||||
VkOffset3D blitSize;
|
||||
blitSize.x = this->width;
|
||||
blitSize.y = this->height;
|
||||
blitSize.z = 1;
|
||||
|
||||
VkImageBlit imageBlit{};
|
||||
imageBlit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
imageBlit.srcSubresource.baseArrayLayer = 0;
|
||||
imageBlit.srcSubresource.layerCount = 1;
|
||||
imageBlit.srcOffsets[0] = { 0, 0, layerID };
|
||||
imageBlit.srcOffsets[1] = { this->width, this->height, layerID + 1 };
|
||||
imageBlit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
imageBlit.dstSubresource.baseArrayLayer = 0;
|
||||
imageBlit.dstSubresource.layerCount = 1;
|
||||
imageBlit.dstOffsets[0] = { 0, 0, 0 };
|
||||
imageBlit.dstOffsets[1] = { this->width, this->height, 1 };
|
||||
|
||||
vkCmdBlitImage( copyCmd, this->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, temporary, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageBlit, VK_FILTER_NEAREST);
|
||||
} else {
|
||||
VkImageCopy imageCopy{};
|
||||
imageCopy.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
imageCopy.srcSubresource.baseArrayLayer = 0;
|
||||
imageCopy.srcSubresource.layerCount = 1;
|
||||
imageCopy.srcOffset = { 0, 0, layerID };
|
||||
|
||||
imageCopy.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
imageCopy.dstSubresource.baseArrayLayer = 0;
|
||||
imageCopy.dstSubresource.layerCount = 1;
|
||||
imageCopy.dstOffset = { 0, 0, 0 };
|
||||
imageCopy.extent = { this->width, this->height, 1 };
|
||||
|
||||
vkCmdCopyImage( copyCmd, this->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, temporary, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageCopy );
|
||||
}
|
||||
imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
|
||||
|
||||
imageMemoryBarrier.image = temporary;
|
||||
imageMemoryBarrier.subresourceRange.baseArrayLayer = 0;
|
||||
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
|
||||
|
||||
imageMemoryBarrier.image = this->image;
|
||||
imageMemoryBarrier.subresourceRange.baseArrayLayer = 0;
|
||||
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
imageMemoryBarrier.newLayout = descriptor.imageLayout;
|
||||
vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
|
||||
device->flushCommandBuffer(copyCmd, true);
|
||||
|
||||
const uint8_t* data;
|
||||
vmaMapMemory( allocator, allocation, (void**)&data );
|
||||
image.loadFromBuffer( data, {this->width, this->height}, 8, 4, false );
|
||||
vmaUnmapMemory( allocator, allocation );
|
||||
vmaDestroyImage(allocator, temporary, allocation);
|
||||
return image;
|
||||
}
|
||||
|
||||
ext::vulkan::Texture2D::Texture2D() {
|
||||
type = ext::vulkan::enums::Image::TYPE_2D;
|
||||
viewType = ext::vulkan::enums::Image::VIEW_TYPE_2D;
|
||||
|
||||
@ -2,38 +2,37 @@
|
||||
#if UF_USE_XATLAS
|
||||
#include <xatlas/xatlas.h>
|
||||
|
||||
pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) {
|
||||
struct Pair {
|
||||
size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) {
|
||||
struct Entry {
|
||||
size_t index = 0;
|
||||
size_t command = 0;
|
||||
size_t commandID = 0;
|
||||
::xatlas::MeshDecl decl;
|
||||
};
|
||||
struct Atlas {
|
||||
::xatlas::Atlas* pointer = NULL;
|
||||
uf::stl::vector<Entry> entries;
|
||||
size_t vertexOffset = 0;
|
||||
};
|
||||
|
||||
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();
|
||||
uf::stl::unordered_map<size_t, Atlas> atlases;
|
||||
atlases.reserve(graph.meshes.size());
|
||||
|
||||
uf::stl::vector<size_t> sizes( graph.meshes.size(), 0 );
|
||||
|
||||
// copy source meshes
|
||||
// create mesh decls for passing to xatlas
|
||||
for ( auto index = 0; index < graph.meshes.size(); ++index ) {
|
||||
auto& name = graph.meshes[index];
|
||||
auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name];
|
||||
|
||||
/*
|
||||
if ( mesh.isInterleaved() ) {
|
||||
sources.emplace_back(mesh.convert()).updateDescriptor();
|
||||
} else {
|
||||
sources.emplace_back(mesh).updateDescriptor();
|
||||
}
|
||||
*/
|
||||
if ( mesh.isInterleaved() ) {
|
||||
UF_EXCEPTION("unwrapping interleaved mesh is not supported");
|
||||
}
|
||||
sources.emplace_back(mesh).updateDescriptor();
|
||||
|
||||
|
||||
uf::Mesh::Input vertexInput = mesh.vertex;
|
||||
|
||||
uf::Mesh::Attribute positionAttribute;
|
||||
@ -59,13 +58,19 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) {
|
||||
}
|
||||
|
||||
if ( mesh.indirect.count ) {
|
||||
auto& primitives = /*graph.storage*/uf::graph::storage.primitives[name];
|
||||
pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data();
|
||||
|
||||
for ( auto i = 0; i < mesh.indirect.count; ++i ) {
|
||||
size_t atlasID = combined ? 0 : drawCommands[i].auxID;
|
||||
|
||||
vertexInput = mesh.remapVertexInput( i );
|
||||
indexInput = mesh.remapIndexInput( i );
|
||||
|
||||
auto& entry = entries.emplace_back();
|
||||
auto& atlas = atlases[atlasID];
|
||||
auto& entry = atlas.entries.emplace_back();
|
||||
entry.index = index;
|
||||
entry.command = i;
|
||||
entry.commandID = i;
|
||||
|
||||
auto& decl = entry.decl;
|
||||
|
||||
@ -82,7 +87,9 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) {
|
||||
decl.indexFormat = indexType;
|
||||
}
|
||||
} else {
|
||||
auto& entry = entries.emplace_back();
|
||||
size_t atlasID = 0;
|
||||
auto& atlas = atlases[atlasID];
|
||||
auto& entry = atlas.entries.emplace_back();
|
||||
entry.index = index;
|
||||
|
||||
auto& decl = entry.decl;
|
||||
@ -101,11 +108,18 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) {
|
||||
} 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_EXCEPTION(::xatlas::StringForEnum(error));
|
||||
// add mesh decls to mesh atlases
|
||||
// done after the fact since we'll know the total amount of meshes added
|
||||
for ( auto& pair : atlases ) {
|
||||
auto& atlas = pair.second;
|
||||
if ( !atlas.pointer ) atlas.pointer = ::xatlas::Create();
|
||||
|
||||
for ( auto& entry : atlas.entries ) {
|
||||
::xatlas::AddMeshError error = ::xatlas::AddMesh(atlas.pointer, entry.decl, atlas.entries.size());
|
||||
if (error != ::xatlas::AddMeshError::Success) {
|
||||
::xatlas::Destroy(atlas.pointer);
|
||||
UF_EXCEPTION(::xatlas::StringForEnum(error));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,150 +133,173 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) {
|
||||
packOptions.blockAlign = true;
|
||||
packOptions.bilinear = true;
|
||||
|
||||
::xatlas::Generate(atlas, chartOptions, packOptions);
|
||||
// pack
|
||||
for ( auto& pair : atlases ) {
|
||||
auto& atlas = pair.second;
|
||||
::xatlas::Generate(atlas.pointer, chartOptions, packOptions);
|
||||
|
||||
uf::stl::vector<size_t> sizes( graph.meshes.size(), 0 );
|
||||
for ( auto i = 0; i < atlas->meshCount; ++i ) {
|
||||
auto& xmesh = atlas->meshes[i];
|
||||
auto& entry = entries[i];
|
||||
sizes[entry.index] += xmesh.vertexCount;
|
||||
// get vertices size ahead of time
|
||||
for ( auto i = 0; i < atlas.pointer->meshCount; ++i ) {
|
||||
auto& xmesh = atlas.pointer->meshes[i];
|
||||
auto& entry = atlas.entries[i];
|
||||
// atlas.vertices += xmesh.vertexCount;
|
||||
sizes[entry.index] += xmesh.vertexCount;
|
||||
}
|
||||
}
|
||||
|
||||
// resize vertices
|
||||
for ( auto i = 0; i < graph.meshes.size(); ++i ) {
|
||||
auto& name = graph.meshes[i];
|
||||
auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name];
|
||||
|
||||
mesh.resizeVertices( sizes[i] );
|
||||
mesh.updateDescriptor();
|
||||
}
|
||||
|
||||
if ( mesh.indirect.count ) {
|
||||
auto& primitive = /*graph.storage*/uf::graph::storage.primitives[name];
|
||||
pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data();
|
||||
// update vertices
|
||||
for ( auto& pair : atlases ) {
|
||||
auto& atlas = pair.second;
|
||||
for ( auto i = 0; i < atlas.pointer->meshCount; i++ ) {
|
||||
auto& xmesh = atlas.pointer->meshes[i];
|
||||
auto& entry = atlas.entries[i];
|
||||
auto& name = graph.meshes[entry.index];
|
||||
auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name];
|
||||
auto& source = sources[entry.index];
|
||||
|
||||
size_t vertexOffset = 0;
|
||||
for ( auto j = 0; j < atlas->meshCount; ++j ) {
|
||||
auto& entry = entries[j];
|
||||
if ( entry.index != i ) continue;
|
||||
// draw commands
|
||||
if ( mesh.indirect.count ) {
|
||||
// vertices
|
||||
auto srcInput = source.remapVertexInput( entry.commandID );
|
||||
auto dstInput = mesh.remapVertexInput( entry.commandID );
|
||||
auto vertexCount = xmesh.vertexCount;
|
||||
|
||||
auto vertexCount = atlas->meshes[j].vertexCount;
|
||||
auto& primitives = /*graph.storage*/uf::graph::storage.primitives[name];
|
||||
pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data();
|
||||
|
||||
drawCommands[entry.command].vertices = vertexCount;
|
||||
drawCommands[entry.command].vertexID = vertexOffset;
|
||||
|
||||
primitive[entry.command].drawCommand.vertices = vertexCount;
|
||||
primitive[entry.command].drawCommand.vertexID = vertexOffset;
|
||||
drawCommands[entry.commandID].vertices = vertexCount;
|
||||
primitives[entry.commandID].drawCommand.vertices = vertexCount;
|
||||
|
||||
vertexOffset += vertexCount;
|
||||
for ( auto j = 0; j < xmesh.vertexCount; ++j ) {
|
||||
auto& vertex = xmesh.vertexArray[j];
|
||||
auto ref = vertex.xref;
|
||||
for ( auto k = 0; k < mesh.vertex.attributes.size(); ++k ) {
|
||||
// auto srcAttribute = source.remapVertexAttribute( source.vertex.attributes[k], entry.commandID );
|
||||
// auto dstAttribute = mesh.remapVertexAttribute( mesh.vertex.attributes[k], entry.commandID );
|
||||
|
||||
auto srcAttribute = source.vertex.attributes[k];
|
||||
auto dstAttribute = mesh.vertex.attributes[k];
|
||||
|
||||
if ( dstAttribute.descriptor.name == "st" ) {
|
||||
pod::Vector2f& st = *(pod::Vector2f*) ( static_cast<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * (j + dstInput.first) );
|
||||
st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };
|
||||
} else {
|
||||
memcpy( static_cast<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * (j + dstInput.first), static_cast<uint8_t*>(srcAttribute.pointer) + srcAttribute.stride * (ref + srcInput.first), srcAttribute.stride );
|
||||
}
|
||||
}
|
||||
}
|
||||
// indices
|
||||
if ( mesh.index.count ) {
|
||||
uf::Mesh::Input indexInput = mesh.remapIndexInput( entry.commandID );
|
||||
uf::Mesh::Attribute indexAttribute = mesh.index.attributes.front();
|
||||
// uf::Mesh::Attribute indexAttribute = mesh.remapIndexAttribute( mesh.index.attributes.front(), entry.commandID );
|
||||
uint8_t* pointer = (uint8_t*) static_cast<uint8_t*>(indexAttribute.pointer) + indexAttribute.stride * indexInput.first;
|
||||
for ( auto index = 0; index < xmesh.indexCount; ++index ) {
|
||||
switch ( mesh.index.size ) {
|
||||
case 1: (( uint8_t*) pointer)[index] = xmesh.indexArray[index]; break;
|
||||
case 2: ((uint16_t*) pointer)[index] = xmesh.indexArray[index]; break;
|
||||
case 4: ((uint32_t*) pointer)[index] = xmesh.indexArray[index]; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uf::Mesh::Attribute stAttribute;
|
||||
for ( auto& attribute : mesh.vertex.attributes ) if ( attribute.descriptor.name == "st" ) stAttribute = attribute;
|
||||
UF_ASSERT( stAttribute.descriptor.name == "st" );
|
||||
|
||||
// vertices
|
||||
for ( auto j = 0; j < xmesh.vertexCount; ++j ) {
|
||||
auto& vertex = xmesh.vertexArray[j];
|
||||
auto ref = vertex.xref;
|
||||
|
||||
for ( auto k = 0; k < mesh.vertex.attributes.size(); ++k ) {
|
||||
auto srcAttribute = source.vertex.attributes[k];
|
||||
auto dstAttribute = mesh.vertex.attributes[k];
|
||||
|
||||
if ( dstAttribute.descriptor.name == "st" ) {
|
||||
pod::Vector2f& st = *(pod::Vector2f*) ( ((uint8_t*) dstAttribute.pointer) + dstAttribute.stride * j);
|
||||
st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };
|
||||
} else {
|
||||
memcpy( static_cast<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * j, static_cast<uint8_t*>(srcAttribute.pointer) + srcAttribute.stride * ref, srcAttribute.stride );
|
||||
}
|
||||
}
|
||||
/*
|
||||
if ( mesh.isInterleaved( mesh.vertex.interleaved ) ) {
|
||||
uint8_t* srcAttribute = source.buffers[mesh.vertex.interleaved].data() + j * mesh.vertex.size;
|
||||
uint8_t* dstAttribute = mesh.buffers[mesh.vertex.interleaved].data() + j * mesh.vertex.size;
|
||||
|
||||
memcpy( dstAttribute, srcAttribute, mesh.vertex.size );
|
||||
|
||||
pod::Vector2f& st = *(pod::Vector2f*) (dstAttribute + stAttribute.descriptor.offset);
|
||||
st = { vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };
|
||||
} else for ( auto& attribute : mesh.vertex.attributes ) {
|
||||
uint8_t* srcAttribute = source.buffers[attribute.buffer].data() + j * attribute.descriptor.size;
|
||||
uint8_t* dstAttribute = mesh.buffers[attribute.buffer].data() + j * attribute.descriptor.size;
|
||||
|
||||
if ( attribute.descriptor.name == "st" ) {
|
||||
pod::Vector2f& st = *(pod::Vector2f*) dstAttribute;
|
||||
st = { vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };
|
||||
} else {
|
||||
memcpy( dstAttribute, srcAttribute, attribute.descriptor.size );
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
// indices
|
||||
if ( mesh.index.count ) {
|
||||
uint8_t* pointer = (uint8_t*) mesh.buffers[mesh.isInterleaved(mesh.index.interleaved) ? mesh.index.interleaved : mesh.index.attributes.front().buffer].data();
|
||||
for ( auto index = 0; index < xmesh.indexCount; ++index ) {
|
||||
switch ( mesh.index.size ) {
|
||||
case 1: (( uint8_t*) pointer)[index] = xmesh.indexArray[index]; break;
|
||||
case 2: ((uint16_t*) pointer)[index] = xmesh.indexArray[index]; break;
|
||||
case 4: ((uint32_t*) pointer)[index] = xmesh.indexArray[index]; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mesh.updateDescriptor();
|
||||
}
|
||||
}
|
||||
|
||||
for ( auto i = 0; i < atlas->meshCount; i++ ) {
|
||||
auto& xmesh = atlas->meshes[i];
|
||||
auto& entry = entries[i];
|
||||
auto& name = graph.meshes[entry.index];
|
||||
// update vertexID offsets for indirect commands
|
||||
for ( auto index = 0; index < graph.meshes.size(); ++index ) {
|
||||
auto& name = graph.meshes[index];
|
||||
auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name];
|
||||
auto& source = sources[entry.index];
|
||||
|
||||
if ( !mesh.indirect.count ) continue;
|
||||
|
||||
// draw commands
|
||||
if ( mesh.indirect.count ) {
|
||||
// vertices
|
||||
for ( auto j = 0; j < xmesh.vertexCount; ++j ) {
|
||||
auto& vertex = xmesh.vertexArray[j];
|
||||
auto ref = vertex.xref;
|
||||
for ( auto k = 0; k < mesh.vertex.attributes.size(); ++k ) {
|
||||
// auto srcAttribute = source.remapVertexAttribute( source.vertex.attributes[k], entry.command );
|
||||
// auto dstAttribute = mesh.remapVertexAttribute( mesh.vertex.attributes[k], entry.command );
|
||||
auto& primitives = /*graph.storage*/uf::graph::storage.primitives[name];
|
||||
pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data();
|
||||
|
||||
auto srcInput = source.remapVertexInput( entry.command );
|
||||
auto dstInput = mesh.remapVertexInput( entry.command );
|
||||
size_t vertexID = 0;
|
||||
for ( auto i = 0; i < mesh.indirect.count; ++i ) {
|
||||
auto& primitive = primitives[i];
|
||||
auto& drawCommand = drawCommands[i];
|
||||
|
||||
auto srcAttribute = source.vertex.attributes[k];
|
||||
auto dstAttribute = mesh.vertex.attributes[k];
|
||||
drawCommand.vertexID = vertexID;
|
||||
primitive.drawCommand.vertexID = vertexID;
|
||||
|
||||
if ( dstAttribute.descriptor.name == "st" ) {
|
||||
pod::Vector2f& st = *(pod::Vector2f*) ( static_cast<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * (j + dstInput.first) );
|
||||
st = pod::Vector2f{ vertex.uv[0] / atlas->width, vertex.uv[1] / atlas->height };
|
||||
} else {
|
||||
memcpy( static_cast<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * (j + dstInput.first), static_cast<uint8_t*>(srcAttribute.pointer) + srcAttribute.stride * (ref + srcInput.first), srcAttribute.stride );
|
||||
}
|
||||
}
|
||||
}
|
||||
// indices
|
||||
if ( mesh.index.count ) {
|
||||
uf::Mesh::Input indexInput = mesh.remapIndexInput( entry.command );
|
||||
uf::Mesh::Attribute indexAttribute = mesh.index.attributes.front();
|
||||
// uf::Mesh::Attribute indexAttribute = mesh.remapIndexAttribute( mesh.index.attributes.front(), entry.command );
|
||||
uint8_t* pointer = (uint8_t*) static_cast<uint8_t*>(indexAttribute.pointer) + indexAttribute.stride * indexInput.first;
|
||||
for ( auto index = 0; index < xmesh.indexCount; ++index ) {
|
||||
switch ( mesh.index.size ) {
|
||||
case 1: (( uint8_t*) pointer)[index] = xmesh.indexArray[index]; break;
|
||||
case 2: ((uint16_t*) pointer)[index] = xmesh.indexArray[index]; break;
|
||||
case 4: ((uint32_t*) pointer)[index] = xmesh.indexArray[index]; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uf::Mesh::Attribute stAttribute;
|
||||
for ( auto& attribute : mesh.vertex.attributes ) if ( attribute.descriptor.name == "st" ) stAttribute = attribute;
|
||||
UF_ASSERT( stAttribute.descriptor.name == "st" );
|
||||
|
||||
// vertices
|
||||
for ( auto j = 0; j < xmesh.vertexCount; ++j ) {
|
||||
auto& vertex = xmesh.vertexArray[j];
|
||||
auto ref = vertex.xref;
|
||||
|
||||
for ( auto k = 0; k < mesh.vertex.attributes.size(); ++k ) {
|
||||
auto srcAttribute = source.vertex.attributes[k];
|
||||
auto dstAttribute = mesh.vertex.attributes[k];
|
||||
|
||||
if ( dstAttribute.descriptor.name == "st" ) {
|
||||
pod::Vector2f& st = *(pod::Vector2f*) ( ((uint8_t*) dstAttribute.pointer) + dstAttribute.stride * j);
|
||||
st = pod::Vector2f{ vertex.uv[0] / atlas->width, vertex.uv[1] / atlas->height };
|
||||
} else {
|
||||
memcpy( static_cast<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * j, static_cast<uint8_t*>(srcAttribute.pointer) + srcAttribute.stride * ref, srcAttribute.stride );
|
||||
}
|
||||
}
|
||||
/*
|
||||
if ( mesh.isInterleaved( mesh.vertex.interleaved ) ) {
|
||||
uint8_t* srcAttribute = source.buffers[mesh.vertex.interleaved].data() + j * mesh.vertex.size;
|
||||
uint8_t* dstAttribute = mesh.buffers[mesh.vertex.interleaved].data() + j * mesh.vertex.size;
|
||||
|
||||
memcpy( dstAttribute, srcAttribute, mesh.vertex.size );
|
||||
|
||||
pod::Vector2f& st = *(pod::Vector2f*) (dstAttribute + stAttribute.descriptor.offset);
|
||||
st = { vertex.uv[0] / atlas->width, vertex.uv[1] / atlas->height };
|
||||
} else for ( auto& attribute : mesh.vertex.attributes ) {
|
||||
uint8_t* srcAttribute = source.buffers[attribute.buffer].data() + j * attribute.descriptor.size;
|
||||
uint8_t* dstAttribute = mesh.buffers[attribute.buffer].data() + j * attribute.descriptor.size;
|
||||
|
||||
if ( attribute.descriptor.name == "st" ) {
|
||||
pod::Vector2f& st = *(pod::Vector2f*) dstAttribute;
|
||||
st = { vertex.uv[0] / atlas->width, vertex.uv[1] / atlas->height };
|
||||
} else {
|
||||
memcpy( dstAttribute, srcAttribute, attribute.descriptor.size );
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
// indices
|
||||
if ( mesh.index.count ) {
|
||||
uint8_t* pointer = (uint8_t*) mesh.buffers[mesh.isInterleaved(mesh.index.interleaved) ? mesh.index.interleaved : mesh.index.attributes.front().buffer].data();
|
||||
for ( auto index = 0; index < xmesh.indexCount; ++index ) {
|
||||
switch ( mesh.index.size ) {
|
||||
case 1: (( uint8_t*) pointer)[index] = xmesh.indexArray[index]; break;
|
||||
case 2: ((uint16_t*) pointer)[index] = xmesh.indexArray[index]; break;
|
||||
case 4: ((uint32_t*) pointer)[index] = xmesh.indexArray[index]; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
vertexID += drawCommand.vertices;
|
||||
}
|
||||
|
||||
mesh.updateDescriptor();
|
||||
}
|
||||
|
||||
pod::Vector2ui size = pod::Vector2ui{ atlas->width, atlas->height };
|
||||
::xatlas::Destroy(atlas);
|
||||
|
||||
return size;
|
||||
// cleanup
|
||||
size_t atlasCount = 0;
|
||||
for ( auto& pair : atlases ) {
|
||||
auto& atlas = pair.second;
|
||||
::xatlas::Destroy(atlas.pointer);
|
||||
++atlasCount;
|
||||
}
|
||||
return atlasCount;
|
||||
}
|
||||
#endif
|
||||
@ -5,6 +5,9 @@
|
||||
#include <uf/utils/window/payloads.h>
|
||||
#include <uf/utils/io/inputs.h>
|
||||
|
||||
#define UF_OPENGL_CONTEXT_IN_WINDOW 0
|
||||
#include <uf/spec/context/context.h>
|
||||
|
||||
#if UF_ENV_DREAMCAST
|
||||
|
||||
/*
|
||||
@ -269,14 +272,71 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
UF_API_CALL spec::dreamcast::Window::Window() {}
|
||||
#include <dc/pvr.h>
|
||||
uf::stl::string spec::dreamcast::malloc_stats( bool verbose ) {
|
||||
std::stringstream str;
|
||||
|
||||
if ( verbose ) {
|
||||
str << "malloc Info:\n"
|
||||
"\tarena " << uf::string::si( mallinfo().arena, "B" ) << " (non-mmapped space allocated from system)\n"
|
||||
"\tordblks " << uf::string::si( mallinfo().ordblks, "B" ) << " (number of free chunks)\n"
|
||||
"\tsmblks " << uf::string::si( mallinfo().smblks, "B" ) << " (number of fastbin blocks)\n"
|
||||
"\tusmblks " << uf::string::si( mallinfo().usmblks, "B" ) << " (maximum total allocated space)\n"
|
||||
"\tfsmblks " << uf::string::si( mallinfo().fsmblks, "B" ) << " (space available in freed fastbin blocks)\n"
|
||||
"\tuordblks " << uf::string::si( mallinfo().uordblks, "B" ) << " (total allocated space)\n"
|
||||
"\tfordblks " << uf::string::si( mallinfo().fordblks, "B" ) << " (total free space)\n"
|
||||
"\tkeepcost " << uf::string::si( mallinfo().keepcost, "B" ) << " (top-most, releasable (via malloc_trim) space)\n";
|
||||
} else {
|
||||
str << "malloc Info: Free: " << uf::string::si( mallinfo().arena - mallinfo().uordblks, "B" ) << " | Used: " << uf::string::si( mallinfo().uordblks, "B" );
|
||||
}
|
||||
|
||||
return str.str();
|
||||
}
|
||||
|
||||
uf::stl::string spec::dreamcast::pvr_malloc_stats( bool verbose ) {
|
||||
std::stringstream str;
|
||||
|
||||
if ( verbose ) {
|
||||
/*
|
||||
"PVR malloc Info:\n"
|
||||
"PVR malloc Info:\n"
|
||||
"\tarena " << uf::string::si( pvr_int_mallinfo().arena, "B" ) << " (non-mmapped space allocated from system)\n"
|
||||
"\tordblks " << uf::string::si( pvr_int_mallinfo().ordblks, "B" ) << " (number of free chunks)\n"
|
||||
"\tsmblks " << uf::string::si( pvr_int_mallinfo().smblks, "B" ) << " (number of fastbin blocks)\n"
|
||||
"\tusmblks " << uf::string::si( pvr_int_mallinfo().usmblks, "B" ) << " (maximum total allocated space)\n"
|
||||
"\tfsmblks " << uf::string::si( pvr_int_mallinfo().fsmblks, "B" ) << " (space available in freed fastbin blocks)\n"
|
||||
"\tuordblks " << uf::string::si( pvr_int_mallinfo().uordblks, "B" ) << " (total allocated space)\n"
|
||||
"\tfordblks " << uf::string::si( pvr_int_mallinfo().fordblks, "B" ) << " (total free space)\n"
|
||||
"\tkeepcost " << uf::string::si( pvr_int_mallinfo().keepcost, "B" ) << " (top-most, releasable (via malloc_trim) space)";
|
||||
*/
|
||||
} else {
|
||||
str << "PVR malloc Info: Free: " << uf::string::si( pvr_mem_available(), "B" );
|
||||
}
|
||||
|
||||
|
||||
return str.str();
|
||||
}
|
||||
|
||||
UF_API_CALL spec::dreamcast::Window::Window() : m_context(NULL) {}
|
||||
void UF_API_CALL spec::dreamcast::Window::create( const spec::dreamcast::Window::vector_t& _size, const spec::dreamcast::Window::title_t& title ) {
|
||||
::keyboard.device = maple_enum_type(1, MAPLE_FUNC_KEYBOARD);
|
||||
|
||||
this->setSize(_size);
|
||||
|
||||
#if UF_USE_OPENGL && UF_OPENGL_CONTEXT_IN_WINDOW
|
||||
this->m_context = (void*) spec::uni::Context::create( settings, *this );
|
||||
#endif
|
||||
}
|
||||
|
||||
spec::dreamcast::Window::~Window() {
|
||||
#if UF_OPENGL_CONTEXT_IN_WINDOW
|
||||
if ( this->m_context ) {
|
||||
spec::Context* context = (spec::Context*) this->m_context;
|
||||
context->terminate();
|
||||
delete context;
|
||||
this->m_context = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void UF_API_CALL spec::dreamcast::Window::terminate() {
|
||||
}
|
||||
@ -339,12 +399,15 @@ void UF_API_CALL spec::dreamcast::Window::setKeyRepeatEnabled( bool state ) {
|
||||
void UF_API_CALL spec::dreamcast::Window::requestFocus() {
|
||||
}
|
||||
bool UF_API_CALL spec::dreamcast::Window::hasFocus() const {
|
||||
return true;
|
||||
// return (uf::Window::focused = true);
|
||||
return uf::Window::focused;
|
||||
}
|
||||
|
||||
|
||||
#include <uf/utils/serialize/serializer.h>
|
||||
void UF_API_CALL spec::dreamcast::Window::bufferInputs() {
|
||||
uf::Window::focused = true;
|
||||
|
||||
uf::inputs::kbm::states::LShift = GetModifier(KBD_MOD_LSHIFT);
|
||||
uf::inputs::kbm::states::RShift = GetModifier(KBD_MOD_RSHIFT);
|
||||
|
||||
@ -357,109 +420,109 @@ void UF_API_CALL spec::dreamcast::Window::bufferInputs() {
|
||||
uf::inputs::kbm::states::LSystem = GetModifier(KBD_MOD_S1);
|
||||
uf::inputs::kbm::states::RSystem = GetModifier(KBD_MOD_S2);
|
||||
|
||||
// uf::inputs::kbm::states::Menu = KBD_KEY_APPS;
|
||||
uf::inputs::kbm::states::SemiColon = KBD_KEY_SEMICOLON;
|
||||
uf::inputs::kbm::states::Slash = KBD_KEY_SLASH;
|
||||
// uf::inputs::kbm::states::Equal = KBD_KEY_EQUAL;
|
||||
uf::inputs::kbm::states::Dash = KBD_KEY_MINUS;
|
||||
uf::inputs::kbm::states::LBracket = KBD_KEY_LBRACKET;
|
||||
uf::inputs::kbm::states::RBracket = KBD_KEY_RBRACKET;
|
||||
uf::inputs::kbm::states::Comma = KBD_KEY_COMMA;
|
||||
uf::inputs::kbm::states::Period = KBD_KEY_PERIOD;
|
||||
uf::inputs::kbm::states::Quote = KBD_KEY_QUOTE;
|
||||
uf::inputs::kbm::states::BackSlash = KBD_KEY_BACKSLASH;
|
||||
uf::inputs::kbm::states::Tilde = KBD_KEY_TILDE;
|
||||
// uf::inputs::kbm::states::Menu = GetKeyState(KBD_KEY_APPS);
|
||||
uf::inputs::kbm::states::SemiColon = GetKeyState(KBD_KEY_SEMICOLON);
|
||||
uf::inputs::kbm::states::Slash = GetKeyState(KBD_KEY_SLASH);
|
||||
// uf::inputs::kbm::states::Equal = GetKeyState(KBD_KEY_EQUAL);
|
||||
uf::inputs::kbm::states::Dash = GetKeyState(KBD_KEY_MINUS);
|
||||
uf::inputs::kbm::states::LBracket = GetKeyState(KBD_KEY_LBRACKET);
|
||||
uf::inputs::kbm::states::RBracket = GetKeyState(KBD_KEY_RBRACKET);
|
||||
uf::inputs::kbm::states::Comma = GetKeyState(KBD_KEY_COMMA);
|
||||
uf::inputs::kbm::states::Period = GetKeyState(KBD_KEY_PERIOD);
|
||||
uf::inputs::kbm::states::Quote = GetKeyState(KBD_KEY_QUOTE);
|
||||
uf::inputs::kbm::states::BackSlash = GetKeyState(KBD_KEY_BACKSLASH);
|
||||
uf::inputs::kbm::states::Tilde = GetKeyState(KBD_KEY_TILDE);
|
||||
|
||||
uf::inputs::kbm::states::Escape = KBD_KEY_ESCAPE;
|
||||
uf::inputs::kbm::states::Space = KBD_KEY_SPACE;
|
||||
uf::inputs::kbm::states::Enter = KBD_KEY_ENTER;
|
||||
uf::inputs::kbm::states::BackSpace = KBD_KEY_BACKSPACE;
|
||||
uf::inputs::kbm::states::Tab = KBD_KEY_TAB;
|
||||
uf::inputs::kbm::states::PageUp = KBD_KEY_PGUP;
|
||||
uf::inputs::kbm::states::PageDown = KBD_KEY_PGDOWN;
|
||||
uf::inputs::kbm::states::End = KBD_KEY_END;
|
||||
uf::inputs::kbm::states::Home = KBD_KEY_HOME;
|
||||
uf::inputs::kbm::states::Insert = KBD_KEY_INSERT;
|
||||
uf::inputs::kbm::states::Delete = KBD_KEY_DEL;
|
||||
uf::inputs::kbm::states::Add = KBD_KEY_PAD_PLUS;
|
||||
uf::inputs::kbm::states::Subtract = KBD_KEY_PAD_MINUS;
|
||||
uf::inputs::kbm::states::Multiply = KBD_KEY_PAD_MULTIPLY;
|
||||
uf::inputs::kbm::states::Divide = KBD_KEY_PAD_DIVIDE;
|
||||
uf::inputs::kbm::states::Pause = KBD_KEY_PAUSE;
|
||||
uf::inputs::kbm::states::Escape = GetKeyState(KBD_KEY_ESCAPE);
|
||||
uf::inputs::kbm::states::Space = GetKeyState(KBD_KEY_SPACE);
|
||||
uf::inputs::kbm::states::Enter = GetKeyState(KBD_KEY_ENTER);
|
||||
uf::inputs::kbm::states::BackSpace = GetKeyState(KBD_KEY_BACKSPACE);
|
||||
uf::inputs::kbm::states::Tab = GetKeyState(KBD_KEY_TAB);
|
||||
uf::inputs::kbm::states::PageUp = GetKeyState(KBD_KEY_PGUP);
|
||||
uf::inputs::kbm::states::PageDown = GetKeyState(KBD_KEY_PGDOWN);
|
||||
uf::inputs::kbm::states::End = GetKeyState(KBD_KEY_END);
|
||||
uf::inputs::kbm::states::Home = GetKeyState(KBD_KEY_HOME);
|
||||
uf::inputs::kbm::states::Insert = GetKeyState(KBD_KEY_INSERT);
|
||||
uf::inputs::kbm::states::Delete = GetKeyState(KBD_KEY_DEL);
|
||||
uf::inputs::kbm::states::Add = GetKeyState(KBD_KEY_PAD_PLUS);
|
||||
uf::inputs::kbm::states::Subtract = GetKeyState(KBD_KEY_PAD_MINUS);
|
||||
uf::inputs::kbm::states::Multiply = GetKeyState(KBD_KEY_PAD_MULTIPLY);
|
||||
uf::inputs::kbm::states::Divide = GetKeyState(KBD_KEY_PAD_DIVIDE);
|
||||
uf::inputs::kbm::states::Pause = GetKeyState(KBD_KEY_PAUSE);
|
||||
|
||||
uf::inputs::kbm::states::F1 = KBD_KEY_F1;
|
||||
uf::inputs::kbm::states::F2 = KBD_KEY_F2;
|
||||
uf::inputs::kbm::states::F3 = KBD_KEY_F3;
|
||||
uf::inputs::kbm::states::F4 = KBD_KEY_F4;
|
||||
uf::inputs::kbm::states::F5 = KBD_KEY_F5;
|
||||
uf::inputs::kbm::states::F6 = KBD_KEY_F6;
|
||||
uf::inputs::kbm::states::F7 = KBD_KEY_F7;
|
||||
uf::inputs::kbm::states::F8 = KBD_KEY_F8;
|
||||
uf::inputs::kbm::states::F9 = KBD_KEY_F9;
|
||||
uf::inputs::kbm::states::F10 = KBD_KEY_F10;
|
||||
uf::inputs::kbm::states::F11 = KBD_KEY_F11;
|
||||
uf::inputs::kbm::states::F12 = KBD_KEY_F12;
|
||||
// uf::inputs::kbm::states::F13 = KBD_KEY_F13;
|
||||
// uf::inputs::kbm::states::F14 = KBD_KEY_F14;
|
||||
// uf::inputs::kbm::states::F15 = KBD_KEY_F15;
|
||||
uf::inputs::kbm::states::F1 = GetKeyState(KBD_KEY_F1);
|
||||
uf::inputs::kbm::states::F2 = GetKeyState(KBD_KEY_F2);
|
||||
uf::inputs::kbm::states::F3 = GetKeyState(KBD_KEY_F3);
|
||||
uf::inputs::kbm::states::F4 = GetKeyState(KBD_KEY_F4);
|
||||
uf::inputs::kbm::states::F5 = GetKeyState(KBD_KEY_F5);
|
||||
uf::inputs::kbm::states::F6 = GetKeyState(KBD_KEY_F6);
|
||||
uf::inputs::kbm::states::F7 = GetKeyState(KBD_KEY_F7);
|
||||
uf::inputs::kbm::states::F8 = GetKeyState(KBD_KEY_F8);
|
||||
uf::inputs::kbm::states::F9 = GetKeyState(KBD_KEY_F9);
|
||||
uf::inputs::kbm::states::F10 = GetKeyState(KBD_KEY_F10);
|
||||
uf::inputs::kbm::states::F11 = GetKeyState(KBD_KEY_F11);
|
||||
uf::inputs::kbm::states::F12 = GetKeyState(KBD_KEY_F12);
|
||||
// uf::inputs::kbm::states::F13 = GetKeyState(KBD_KEY_F13);
|
||||
// uf::inputs::kbm::states::F14 = GetKeyState(KBD_KEY_F14);
|
||||
// uf::inputs::kbm::states::F15 = GetKeyState(KBD_KEY_F15);
|
||||
|
||||
uf::inputs::kbm::states::Left = KBD_KEY_LEFT;
|
||||
uf::inputs::kbm::states::Right = KBD_KEY_RIGHT;
|
||||
uf::inputs::kbm::states::Up = KBD_KEY_UP;
|
||||
uf::inputs::kbm::states::Down = KBD_KEY_DOWN;
|
||||
uf::inputs::kbm::states::Left = GetKeyState(KBD_KEY_LEFT);
|
||||
uf::inputs::kbm::states::Right = GetKeyState(KBD_KEY_RIGHT);
|
||||
uf::inputs::kbm::states::Up = GetKeyState(KBD_KEY_UP);
|
||||
uf::inputs::kbm::states::Down = GetKeyState(KBD_KEY_DOWN);
|
||||
|
||||
uf::inputs::kbm::states::Numpad0 = KBD_KEY_PAD_0;
|
||||
uf::inputs::kbm::states::Numpad1 = KBD_KEY_PAD_1;
|
||||
uf::inputs::kbm::states::Numpad2 = KBD_KEY_PAD_2;
|
||||
uf::inputs::kbm::states::Numpad3 = KBD_KEY_PAD_3;
|
||||
uf::inputs::kbm::states::Numpad4 = KBD_KEY_PAD_4;
|
||||
uf::inputs::kbm::states::Numpad5 = KBD_KEY_PAD_5;
|
||||
uf::inputs::kbm::states::Numpad6 = KBD_KEY_PAD_6;
|
||||
uf::inputs::kbm::states::Numpad7 = KBD_KEY_PAD_7;
|
||||
uf::inputs::kbm::states::Numpad8 = KBD_KEY_PAD_8;
|
||||
uf::inputs::kbm::states::Numpad9 = KBD_KEY_PAD_9;
|
||||
uf::inputs::kbm::states::Numpad0 = GetKeyState(KBD_KEY_PAD_0);
|
||||
uf::inputs::kbm::states::Numpad1 = GetKeyState(KBD_KEY_PAD_1);
|
||||
uf::inputs::kbm::states::Numpad2 = GetKeyState(KBD_KEY_PAD_2);
|
||||
uf::inputs::kbm::states::Numpad3 = GetKeyState(KBD_KEY_PAD_3);
|
||||
uf::inputs::kbm::states::Numpad4 = GetKeyState(KBD_KEY_PAD_4);
|
||||
uf::inputs::kbm::states::Numpad5 = GetKeyState(KBD_KEY_PAD_5);
|
||||
uf::inputs::kbm::states::Numpad6 = GetKeyState(KBD_KEY_PAD_6);
|
||||
uf::inputs::kbm::states::Numpad7 = GetKeyState(KBD_KEY_PAD_7);
|
||||
uf::inputs::kbm::states::Numpad8 = GetKeyState(KBD_KEY_PAD_8);
|
||||
uf::inputs::kbm::states::Numpad9 = GetKeyState(KBD_KEY_PAD_9);
|
||||
|
||||
uf::inputs::kbm::states::Q = KBD_KEY_Q;
|
||||
uf::inputs::kbm::states::W = KBD_KEY_W;
|
||||
uf::inputs::kbm::states::E = KBD_KEY_E;
|
||||
uf::inputs::kbm::states::R = KBD_KEY_R;
|
||||
uf::inputs::kbm::states::T = KBD_KEY_T;
|
||||
uf::inputs::kbm::states::Y = KBD_KEY_Y;
|
||||
uf::inputs::kbm::states::U = KBD_KEY_U;
|
||||
uf::inputs::kbm::states::I = KBD_KEY_I;
|
||||
uf::inputs::kbm::states::O = KBD_KEY_O;
|
||||
uf::inputs::kbm::states::P = KBD_KEY_P;
|
||||
uf::inputs::kbm::states::Q = GetKeyState(KBD_KEY_Q);
|
||||
uf::inputs::kbm::states::W = GetKeyState(KBD_KEY_W);
|
||||
uf::inputs::kbm::states::E = GetKeyState(KBD_KEY_E);
|
||||
uf::inputs::kbm::states::R = GetKeyState(KBD_KEY_R);
|
||||
uf::inputs::kbm::states::T = GetKeyState(KBD_KEY_T);
|
||||
uf::inputs::kbm::states::Y = GetKeyState(KBD_KEY_Y);
|
||||
uf::inputs::kbm::states::U = GetKeyState(KBD_KEY_U);
|
||||
uf::inputs::kbm::states::I = GetKeyState(KBD_KEY_I);
|
||||
uf::inputs::kbm::states::O = GetKeyState(KBD_KEY_O);
|
||||
uf::inputs::kbm::states::P = GetKeyState(KBD_KEY_P);
|
||||
|
||||
uf::inputs::kbm::states::A = KBD_KEY_A;
|
||||
uf::inputs::kbm::states::S = KBD_KEY_S;
|
||||
uf::inputs::kbm::states::D = KBD_KEY_D;
|
||||
uf::inputs::kbm::states::F = KBD_KEY_F;
|
||||
uf::inputs::kbm::states::G = KBD_KEY_G;
|
||||
uf::inputs::kbm::states::H = KBD_KEY_H;
|
||||
uf::inputs::kbm::states::J = KBD_KEY_J;
|
||||
uf::inputs::kbm::states::K = KBD_KEY_K;
|
||||
uf::inputs::kbm::states::L = KBD_KEY_L;
|
||||
uf::inputs::kbm::states::A = GetKeyState(KBD_KEY_A);
|
||||
uf::inputs::kbm::states::S = GetKeyState(KBD_KEY_S);
|
||||
uf::inputs::kbm::states::D = GetKeyState(KBD_KEY_D);
|
||||
uf::inputs::kbm::states::F = GetKeyState(KBD_KEY_F);
|
||||
uf::inputs::kbm::states::G = GetKeyState(KBD_KEY_G);
|
||||
uf::inputs::kbm::states::H = GetKeyState(KBD_KEY_H);
|
||||
uf::inputs::kbm::states::J = GetKeyState(KBD_KEY_J);
|
||||
uf::inputs::kbm::states::K = GetKeyState(KBD_KEY_K);
|
||||
uf::inputs::kbm::states::L = GetKeyState(KBD_KEY_L);
|
||||
|
||||
uf::inputs::kbm::states::Z = KBD_KEY_Z;
|
||||
uf::inputs::kbm::states::X = KBD_KEY_X;
|
||||
uf::inputs::kbm::states::C = KBD_KEY_C;
|
||||
uf::inputs::kbm::states::V = KBD_KEY_V;
|
||||
uf::inputs::kbm::states::B = KBD_KEY_B;
|
||||
uf::inputs::kbm::states::N = KBD_KEY_N;
|
||||
uf::inputs::kbm::states::M = KBD_KEY_M;
|
||||
uf::inputs::kbm::states::Z = GetKeyState(KBD_KEY_Z);
|
||||
uf::inputs::kbm::states::X = GetKeyState(KBD_KEY_X);
|
||||
uf::inputs::kbm::states::C = GetKeyState(KBD_KEY_C);
|
||||
uf::inputs::kbm::states::V = GetKeyState(KBD_KEY_V);
|
||||
uf::inputs::kbm::states::B = GetKeyState(KBD_KEY_B);
|
||||
uf::inputs::kbm::states::N = GetKeyState(KBD_KEY_N);
|
||||
uf::inputs::kbm::states::M = GetKeyState(KBD_KEY_M);
|
||||
|
||||
uf::inputs::kbm::states::Num1 = KBD_KEY_1;
|
||||
uf::inputs::kbm::states::Num2 = KBD_KEY_2;
|
||||
uf::inputs::kbm::states::Num3 = KBD_KEY_3;
|
||||
uf::inputs::kbm::states::Num4 = KBD_KEY_4;
|
||||
uf::inputs::kbm::states::Num5 = KBD_KEY_5;
|
||||
uf::inputs::kbm::states::Num6 = KBD_KEY_6;
|
||||
uf::inputs::kbm::states::Num7 = KBD_KEY_7;
|
||||
uf::inputs::kbm::states::Num8 = KBD_KEY_8;
|
||||
uf::inputs::kbm::states::Num9 = KBD_KEY_9;
|
||||
uf::inputs::kbm::states::Num0 = KBD_KEY_0;
|
||||
uf::inputs::kbm::states::Num1 = GetKeyState(KBD_KEY_1);
|
||||
uf::inputs::kbm::states::Num2 = GetKeyState(KBD_KEY_2);
|
||||
uf::inputs::kbm::states::Num3 = GetKeyState(KBD_KEY_3);
|
||||
uf::inputs::kbm::states::Num4 = GetKeyState(KBD_KEY_4);
|
||||
uf::inputs::kbm::states::Num5 = GetKeyState(KBD_KEY_5);
|
||||
uf::inputs::kbm::states::Num6 = GetKeyState(KBD_KEY_6);
|
||||
uf::inputs::kbm::states::Num7 = GetKeyState(KBD_KEY_7);
|
||||
uf::inputs::kbm::states::Num8 = GetKeyState(KBD_KEY_8);
|
||||
uf::inputs::kbm::states::Num9 = GetKeyState(KBD_KEY_9);
|
||||
uf::inputs::kbm::states::Num0 = GetKeyState(KBD_KEY_0);
|
||||
}
|
||||
void UF_API_CALL spec::dreamcast::Window::processEvents() {
|
||||
void UF_API_CALL spec::dreamcast::Window::processEvents() {
|
||||
if ( !::keyboard.device ) ::keyboard.device = maple_enum_type(0, MAPLE_FUNC_KEYBOARD);
|
||||
if ( ::keyboard.device ) ::keyboard.state = (kbd_state_t*) maple_dev_status(::keyboard.device);
|
||||
|
||||
@ -569,7 +632,18 @@ void UF_API_CALL spec::dreamcast::Window::toggleFullscreen( bool borderless ) {
|
||||
bool UF_API_CALL spec::dreamcast::Window::isKeyPressed(const uf::stl::string& key) {
|
||||
auto code = GetKeyCode(key);
|
||||
auto keys = GetKeys();
|
||||
UF_MSG_DEBUG( key << " " << code << " " << keys.size() );
|
||||
for ( auto key : keys ) if ( key == code ) return true;
|
||||
return false;
|
||||
return false;//
|
||||
}
|
||||
|
||||
void UF_API_CALL spec::dreamcast::Window::display() {
|
||||
#if UF_USE_OPENGL && UF_OPENGL_CONTEXT_IN_WINDOW
|
||||
if ( this->m_context ){
|
||||
spec::Context* context = (spec::Context*) this->m_context;
|
||||
if ( context->setActive(true) ) context->display();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -4,6 +4,8 @@
|
||||
|
||||
#include <uf/utils/serialize/serializer.h>
|
||||
#include <sstream>
|
||||
|
||||
bool spec::uni::Window::focused = false;
|
||||
/*
|
||||
void UF_API_CALL spec::uni::Window::pushEvent( const uf::ReadableHook::name_t& name, const uf::ReadableHook::argument_t& argument ) {
|
||||
if ( !uf::hooks.prefersReadable() ) return;
|
||||
@ -76,6 +78,7 @@ void UF_API_CALL spec::uni::Window::pushEvent( const pod::Hook::userdata_t& payl
|
||||
this->m_events.push({ header.type, std::move(payload) });
|
||||
}
|
||||
*/
|
||||
#if 0
|
||||
void UF_API_CALL spec::uni::Window::processEvents() {
|
||||
}
|
||||
bool UF_API_CALL spec::uni::Window::isKeyPressed(const uf::stl::string& key) {
|
||||
@ -151,4 +154,5 @@ bool UF_API_CALL spec::uni::Window::pollEvents( bool block ) {
|
||||
}
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -6,6 +6,9 @@
|
||||
#include <uf/utils/io/inputs.h>
|
||||
#include <uf/utils/string/ext.h>
|
||||
|
||||
#define UF_OPENGL_CONTEXT_IN_WINDOW 0
|
||||
#include <uf/spec/context/context.h>
|
||||
|
||||
#define UF_HOOK_USE_USERDATA 1
|
||||
#define UF_HOOK_USE_JSON 0
|
||||
|
||||
@ -421,6 +424,7 @@ namespace {
|
||||
|
||||
UF_API_CALL spec::win32::Window::Window() :
|
||||
m_handle (NULL),
|
||||
m_context (NULL),
|
||||
m_callback (0),
|
||||
m_cursor (NULL),
|
||||
m_icon (NULL),
|
||||
@ -453,6 +457,7 @@ UF_API_CALL spec::win32::Window::Window( spec::win32::Window::handle_t handle )
|
||||
}
|
||||
UF_API_CALL spec::win32::Window::Window( const spec::win32::Window::vector_t& size, const spec::win32::Window::title_t& title ) :
|
||||
m_handle (NULL),
|
||||
m_context (NULL),
|
||||
m_callback (0),
|
||||
m_cursor (NULL),
|
||||
m_icon (NULL),
|
||||
@ -506,6 +511,10 @@ void UF_API_CALL spec::win32::Window::create( const spec::win32::Window::vector_
|
||||
// m_callback = SetWindowLongPtrW(this->m_handle, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&::globalOnEvent));
|
||||
|
||||
++windowCount;
|
||||
|
||||
#if UF_USE_OPENGL && UF_OPENGL_CONTEXT_IN_WINDOW
|
||||
this->m_context = (void*) spec::uni::Context::create( settings, *this );
|
||||
#endif
|
||||
}
|
||||
|
||||
spec::win32::Window::~Window() {
|
||||
@ -516,6 +525,15 @@ spec::win32::Window::~Window() {
|
||||
} else {
|
||||
SetWindowLongPtrW( this->m_handle, GWLP_WNDPROC, this->m_callback );
|
||||
}
|
||||
|
||||
#if UF_OPENGL_CONTEXT_IN_WINDOW
|
||||
if ( this->m_context ) {
|
||||
spec::Context* context = (spec::Context*) this->m_context;
|
||||
context->terminate();
|
||||
delete context;
|
||||
this->m_context = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void UF_API_CALL spec::win32::Window::terminate() {
|
||||
if ( this == (spec::win32::Window*) fullscreenWindow ) {
|
||||
@ -663,6 +681,8 @@ bool UF_API_CALL spec::win32::Window::hasFocus() const {
|
||||
}
|
||||
|
||||
void UF_API_CALL spec::win32::Window::bufferInputs() {
|
||||
uf::Window::focused = this->hasFocus();
|
||||
|
||||
uf::inputs::kbm::states::LShift = GetAsyncKeyState(VK_LSHIFT) & 0x8000;
|
||||
uf::inputs::kbm::states::RShift = GetAsyncKeyState(VK_RSHIFT) & 0x8000;
|
||||
|
||||
@ -1450,7 +1470,7 @@ void UF_API_CALL spec::win32::Window::toggleFullscreen( bool borderless ) {
|
||||
}
|
||||
|
||||
bool UF_API_CALL spec::win32::Window::isKeyPressed(const uf::stl::string& key) {
|
||||
return GetAsyncKeyState( GetKeyCode( key ) ) & 0x8000;
|
||||
return uf::Window::focused && (GetAsyncKeyState( GetKeyCode( key ) ) & 0x8000);
|
||||
}
|
||||
uf::stl::string UF_API_CALL spec::win32::Window::getKey(WPARAM key, LPARAM flags) {
|
||||
return GetKeyName( key, flags );
|
||||
@ -1469,4 +1489,14 @@ void UF_API_CALL spec::win32::Window::createSurface( VkInstance instance, VkSurf
|
||||
vkCreateWin32SurfaceKHR( instance, &surfaceCreateInfo, nullptr, &surface);
|
||||
}
|
||||
#endif
|
||||
|
||||
void UF_API_CALL spec::win32::Window::display() {
|
||||
#if UF_USE_OPENGL && UF_OPENGL_CONTEXT_IN_WINDOW
|
||||
if ( this->m_context ){
|
||||
spec::Context* context = (spec::Context*) this->m_context;
|
||||
if ( context->setActive(true) ) context->display();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -284,11 +284,11 @@ std::string uf::Mesh::printInstances( bool full ) const {
|
||||
}
|
||||
std::string uf::Mesh::printIndirects( bool full ) const {
|
||||
std::stringstream str;
|
||||
str << "Indirect: " << PRINT_HEADER( indirect ) << "{ indices, instances, indexID, vertexID, instanceID, padding1, padding2, vertices }\n";
|
||||
str << "Indirect: " << PRINT_HEADER( indirect ) << "{ indices, instances, indexID, vertexID, instanceID, auxID, materialID, vertices }\n";
|
||||
if ( full ) for ( auto i = 0; i < indirect.count; ++i ) {
|
||||
auto& buffer = getBuffer( indirect );
|
||||
auto& drawCommand = *(const pod::DrawCommand*) (&buffer[i * indirect.size]);
|
||||
str << "[" << i << "]: {" << drawCommand.indices << ", " << drawCommand.instances << ", " << drawCommand.indexID << ", " << drawCommand.vertexID << ", " << drawCommand.instanceID << ", " << drawCommand.padding1 << ", " << drawCommand.padding2 << ", " << drawCommand.vertices << "}\n";
|
||||
str << "[" << i << "]: {" << drawCommand.indices << ", " << drawCommand.instances << ", " << drawCommand.indexID << ", " << drawCommand.vertexID << ", " << drawCommand.instanceID << ", " << drawCommand.auxID << ", " << drawCommand.materialID << ", " << drawCommand.vertices << "}\n";
|
||||
}
|
||||
return str.str();
|
||||
}
|
||||
|
||||
@ -1,175 +0,0 @@
|
||||
#include <uf/config.h>
|
||||
#if !UF_USE_SFML
|
||||
#define UF_OPENGL_CONTEXT_IN_WINDOW 0
|
||||
#include <uf/utils/window/window.h>
|
||||
#include <uf/utils/io/iostream.h>
|
||||
bool uf::Window::focused = false;
|
||||
|
||||
// C-tors
|
||||
UF_API_CALL uf::Window::Window() :
|
||||
m_window(NULL),
|
||||
m_context(NULL)
|
||||
{
|
||||
|
||||
}
|
||||
UF_API_CALL uf::Window::Window( const spec::uni::Window::vector_t& size, const spec::uni::Window::title_t& title, const spec::Context::Settings& settings ) : Window() {
|
||||
this->create(size, title, settings);
|
||||
}
|
||||
void UF_API_CALL uf::Window::create( const spec::uni::Window::vector_t& size, const spec::uni::Window::title_t& title, const spec::Context::Settings& settings ) {
|
||||
this->m_window = new uf::Window::window_t;
|
||||
this->m_window->create( size, title );
|
||||
#if UF_USE_OPENGL && UF_OPENGL_CONTEXT_IN_WINDOW
|
||||
this->m_context = (spec::Context*) spec::uni::Context::create( settings, *this->m_window );
|
||||
#endif
|
||||
}
|
||||
// D-tors
|
||||
uf::Window::~Window() {
|
||||
this->terminate();
|
||||
}
|
||||
void UF_API_CALL uf::Window::terminate() {
|
||||
#if UF_OPENGL_CONTEXT_IN_WINDOW
|
||||
if ( this->m_context ) {
|
||||
this->m_context->terminate();
|
||||
delete this->m_context;
|
||||
this->m_context = NULL;
|
||||
}
|
||||
#endif
|
||||
if ( this->m_window ) {
|
||||
this->m_window->terminate();
|
||||
delete this->m_window;
|
||||
this->m_window = NULL;
|
||||
}
|
||||
}
|
||||
// Gets
|
||||
spec::uni::Window::vector_t UF_API_CALL uf::Window::getPosition() const {
|
||||
static spec::uni::Window::vector_t null = {};
|
||||
return this->m_window ? this->m_window->getPosition() : null;
|
||||
}
|
||||
spec::uni::Window::vector_t UF_API_CALL uf::Window::getSize() const {
|
||||
static spec::uni::Window::vector_t null = {};
|
||||
return this->m_window ? this->m_window->getSize() : null;
|
||||
}
|
||||
size_t UF_API_CALL uf::Window::getRefreshRate() const {
|
||||
static spec::uni::Window::vector_t null = {};
|
||||
return this->m_window ? this->m_window->getRefreshRate() : 0;
|
||||
}
|
||||
// Attribute modifiers
|
||||
void UF_API_CALL uf::Window::setPosition( const spec::uni::Window::vector_t& position ) {
|
||||
if ( !this->m_window ) return;
|
||||
this->m_window->setPosition(position);
|
||||
}
|
||||
void UF_API_CALL uf::Window::centerWindow() {
|
||||
if ( !this->m_window ) return;
|
||||
this->m_window->centerWindow();
|
||||
}
|
||||
void UF_API_CALL uf::Window::setMousePosition( const spec::uni::Window::vector_t& position ) {
|
||||
if ( !this->m_window ) return;
|
||||
this->m_window->setMousePosition(position);
|
||||
}
|
||||
spec::uni::Window::vector_t UF_API_CALL uf::Window::getMousePosition() {
|
||||
return this->m_window ? this->m_window->getMousePosition() : spec::uni::Window::vector_t{ 0, 0 };
|
||||
}
|
||||
void UF_API_CALL uf::Window::setSize( const spec::uni::Window::vector_t& size ) {
|
||||
if ( !this->m_window ) return;
|
||||
this->m_window->setSize(size);
|
||||
}
|
||||
void UF_API_CALL uf::Window::setTitle( const spec::uni::Window::title_t& title ) {
|
||||
if ( !this->m_window ) return;
|
||||
this->m_window->setTitle(title);
|
||||
|
||||
ext::json::Value json;
|
||||
uf::stl::string hook = "window:Title.Changed";
|
||||
json["type"] = hook;
|
||||
json["invoker"] = "os";
|
||||
json["window"]["title"] = uf::stl::string(title);
|
||||
uf::hooks.call( hook, json );
|
||||
}
|
||||
void UF_API_CALL uf::Window::setIcon( const spec::uni::Window::vector_t& size, uint8_t* pixels ) {
|
||||
if ( !this->m_window ) return;
|
||||
this->m_window->setIcon(size, pixels);
|
||||
}
|
||||
void UF_API_CALL uf::Window::setVisible( bool visibility ) {
|
||||
if ( !this->m_window ) return;
|
||||
this->m_window->setVisible(visibility);
|
||||
}
|
||||
void UF_API_CALL uf::Window::setCursorVisible( bool visibility ) {
|
||||
if ( !this->m_window ) return;
|
||||
this->m_window->setCursorVisible(visibility);
|
||||
}
|
||||
void UF_API_CALL uf::Window::setKeyRepeatEnabled( bool state ) {
|
||||
if ( !this->m_window ) return;
|
||||
this->m_window->setKeyRepeatEnabled(state);
|
||||
}
|
||||
void UF_API_CALL uf::Window::setMouseGrabbed( bool state ) {
|
||||
if ( !this->m_window ) return;
|
||||
this->m_window->setMouseGrabbed(state);
|
||||
}
|
||||
|
||||
void UF_API_CALL uf::Window::requestFocus() {
|
||||
if ( !this->m_window ) return;
|
||||
this->m_window->requestFocus();
|
||||
}
|
||||
bool UF_API_CALL uf::Window::hasFocus() const {
|
||||
return uf::Window::focused = (this->m_window ? this->m_window->hasFocus() : false);
|
||||
}
|
||||
pod::Vector2ui UF_API_CALL uf::Window::getResolution() {
|
||||
return uf::Window::window_t::getResolution();
|
||||
}
|
||||
void UF_API_CALL uf::Window::toggleFullscreen( bool borderless ) {
|
||||
if ( !this->m_window ) return;
|
||||
this->m_window->toggleFullscreen( borderless );
|
||||
}
|
||||
// Update
|
||||
void UF_API_CALL uf::Window::bufferInputs() {
|
||||
if ( !this->m_window ) return;
|
||||
this->m_window->bufferInputs();
|
||||
}
|
||||
void UF_API_CALL uf::Window::processEvents() {
|
||||
if ( !this->m_window ) return;
|
||||
this->m_window->processEvents();
|
||||
}
|
||||
bool UF_API_CALL uf::Window::pollEvents( bool block ) {
|
||||
return this->m_window ? this->m_window->pollEvents(block) : false;
|
||||
}
|
||||
bool UF_API_CALL uf::Window::isKeyPressed( const uf::stl::string& key ) {
|
||||
return uf::Window::focused && uf::Window::window_t::isKeyPressed(key);
|
||||
}
|
||||
bool UF_API_CALL uf::Window::setActive(bool active) {
|
||||
#if UF_USE_OPENGL && UF_OPENGL_CONTEXT_IN_WINDOW
|
||||
if ( this->m_context ) {
|
||||
if ( this->m_context->setActive(active) ) return true;
|
||||
uf::iostream << "[" << uf::IoStream::Color()("Red") << "ERROR" << "]" << "Failed to activate the window's context" << "\n";
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
#if UF_USE_VULKAN
|
||||
uf::stl::vector<uf::stl::string> UF_API_CALL uf::Window::getExtensions( bool x ) {
|
||||
return this->m_window->getExtensions( x );
|
||||
}
|
||||
void UF_API_CALL uf::Window::createSurface( VkInstance instance, VkSurfaceKHR& surface ) {
|
||||
this->m_window->createSurface( instance, surface );
|
||||
}
|
||||
#endif
|
||||
|
||||
/*virtual*/ uf::Window::window_t* UF_API_CALL uf::Window::getHandle() {
|
||||
return this->m_window;
|
||||
}
|
||||
/*virtual*/ const uf::Window::window_t* UF_API_CALL uf::Window::getHandle() const {
|
||||
return this->m_window;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <uf/utils/time/time.h>
|
||||
void UF_API_CALL uf::Window::display() {
|
||||
#if UF_USE_OPENGL && UF_OPENGL_CONTEXT_IN_WINDOW
|
||||
if ( this->m_context && this->setActive() ) this->m_context->display();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,5 +1,5 @@
|
||||
#include <uf/config.h>
|
||||
#if !UF_ENV_DREAMCAST
|
||||
#if UF_USE_VULKAN
|
||||
#include "behavior.h"
|
||||
|
||||
#include <uf/utils/renderer/renderer.h>
|
||||
@ -57,7 +57,7 @@ void ext::BakingBehavior::initialize( uf::Object& self ) {
|
||||
renderMode.metadata.type = "single";
|
||||
renderMode.metadata.pipeline = "baking";
|
||||
renderMode.metadata.samples = 1;
|
||||
// renderMode.metadata.layers = metadata.max.layers;
|
||||
// renderMode.metadata.views = metadata.max.layers; // gl_Layer doesn't work
|
||||
renderMode.metadata.json["descriptor"]["cull mode"] = "none";
|
||||
|
||||
renderMode.width = metadata.size.x;
|
||||
@ -74,6 +74,8 @@ void ext::BakingBehavior::initialize( uf::Object& self ) {
|
||||
for ( auto& texture : uf::graph::storage.shadow2Ds ) textures2D.emplace_back().aliasTexture(texture);
|
||||
for ( auto& texture : uf::graph::storage.shadowCubes ) texturesCube.emplace_back().aliasTexture(texture);
|
||||
|
||||
metadata.buffers.baked.fromBuffers( NULL, 0, uf::renderer::enums::Format::R8G8B8A8_UNORM, metadata.size.x, metadata.size.y, metadata.max.layers, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
|
||||
|
||||
scene.process([&]( uf::Entity* entity ) {
|
||||
if ( !entity->hasComponent<uf::Graphic>() ) return;
|
||||
auto& graphic = entity->getComponent<uf::Graphic>();
|
||||
@ -81,6 +83,8 @@ void ext::BakingBehavior::initialize( uf::Object& self ) {
|
||||
|
||||
for ( auto& t : textures2D ) shader.textures.emplace_back().aliasTexture( t );
|
||||
for ( auto& t : texturesCube ) shader.textures.emplace_back().aliasTexture( t );
|
||||
|
||||
shader.textures.emplace_back().aliasTexture( metadata.buffers.baked );
|
||||
});
|
||||
UF_MSG_DEBUG("Finished initialiation.");
|
||||
});
|
||||
@ -116,10 +120,13 @@ SAVE: {
|
||||
#if 1
|
||||
renderMode.execute = false;
|
||||
UF_MSG_DEBUG("Baking...");
|
||||
auto image = renderMode.screenshot();
|
||||
uf::stl::string filename = metadata.output;
|
||||
bool status = image.save(filename);
|
||||
UF_MSG_DEBUG("Writing to " << filename << ": " << status);
|
||||
for ( size_t i = 0; i < metadata.max.layers; ++i ) {
|
||||
// auto image = renderMode.screenshot(0, i);
|
||||
auto image = metadata.buffers.baked.screenshot(i);
|
||||
uf::stl::string filename = uf::string::replace( metadata.output, "%i", std::to_string(i) );
|
||||
bool status = image.save(filename);
|
||||
UF_MSG_DEBUG("Writing to " << filename << ": " << status);
|
||||
}
|
||||
UF_MSG_DEBUG("Baked.");
|
||||
metadata.initialized.map = true;
|
||||
|
||||
|
||||
@ -22,6 +22,8 @@ namespace ext {
|
||||
size_t material = 0;
|
||||
size_t texture = 0;
|
||||
size_t light = 0;
|
||||
|
||||
uf::renderer::Texture3D baked;
|
||||
} buffers;
|
||||
struct {
|
||||
size_t textures2D = 1024;
|
||||
|
||||
@ -314,7 +314,70 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
|
||||
metadata.shader.parameters[metadata.shader.time] = uf::physics::time::current;
|
||||
}
|
||||
#endif
|
||||
#if UF_USE_VULKAN
|
||||
#if UF_USE_OPENGL
|
||||
if ( metadata.light.enabled ) {
|
||||
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::Vector4f position = {0,0,0,1}; // OpenGL requires a W
|
||||
pod::Vector4f color = {0,0,0,1}; // OpenGL requires an alpha
|
||||
float distance = 0;
|
||||
float power = 0;
|
||||
};
|
||||
uf::stl::vector<LightInfo> entities;
|
||||
for ( auto entity : graph ) {
|
||||
if ( entity == this || entity == &controller || !entity->hasComponent<ext::LightBehavior::Metadata>() ) continue;
|
||||
auto& metadata = entity->getComponent<ext::LightBehavior::Metadata>();
|
||||
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,
|
||||
.color = metadata.color,
|
||||
.distance = uf::vector::magnitude( uf::vector::subtract( flatten.position, controllerTransform.position ) ),
|
||||
.power = metadata.power,
|
||||
});
|
||||
info.position.w = 1;
|
||||
info.color.w = 1;
|
||||
}
|
||||
std::sort( entities.begin(), entities.end(), [&]( LightInfo& l, LightInfo& r ){
|
||||
return l.distance < r.distance;
|
||||
});
|
||||
|
||||
static GLint glMaxLights = 0;
|
||||
if ( !glMaxLights ) glGetIntegerv(GL_MAX_LIGHTS, &glMaxLights);
|
||||
metadata.light.max = std::min( (uint32_t) glMaxLights, metadata.light.max );
|
||||
|
||||
// add lighting
|
||||
{
|
||||
uint32_t i = 0;
|
||||
for ( ; i < entities.size() && i < metadata.light.max; ++i ) {
|
||||
auto& info = entities[i];
|
||||
// uf::Entity* entity = info.entity;
|
||||
GLenum target = GL_LIGHT0+i;
|
||||
GL_ERROR_CHECK(glEnable(target));
|
||||
GL_ERROR_CHECK(glLightfv(target, GL_AMBIENT, &metadata.light.ambient[0]));
|
||||
GL_ERROR_CHECK(glLightfv(target, GL_SPECULAR, &metadata.light.specular[0]));
|
||||
GL_ERROR_CHECK(glLightfv(target, GL_DIFFUSE, &info.color[0]));
|
||||
GL_ERROR_CHECK(glLightfv(target, GL_POSITION, &info.position[0]));
|
||||
GL_ERROR_CHECK(glLightf(target, GL_CONSTANT_ATTENUATION, 0.0f));
|
||||
GL_ERROR_CHECK(glLightf(target, GL_LINEAR_ATTENUATION, 0));
|
||||
GL_ERROR_CHECK(glLightf(target, GL_QUADRATIC_ATTENUATION, 1.0f / info.power));
|
||||
|
||||
// UF_MSG_DEBUG( i << " | " << uf::vector::toString( metadata.light.ambient ) << " | " << uf::vector::toString( metadata.light.specular ) << " | " << uf::vector::toString( info.color ) << " | " << uf::vector::toString( info.position ) << " | " << info.power );
|
||||
}
|
||||
for ( ; i < metadata.light.max; ++i ) GL_ERROR_CHECK(glDisable(GL_LIGHT0+i));
|
||||
}
|
||||
}
|
||||
#elif UF_USE_VULKAN
|
||||
{
|
||||
auto& graph = this->getGraph();
|
||||
auto& controller = this->getController();
|
||||
@ -562,6 +625,11 @@ void ext::ExtSceneBehavior::Metadata::deserialize( uf::Object& self, uf::Seriali
|
||||
}
|
||||
#if UF_USE_OPENGL_FIXED_FUNCTION
|
||||
uf::renderer::states::rebuild = true;
|
||||
if ( light.enabled ) {
|
||||
GL_ERROR_CHECK(glEnable(GL_LIGHTING));
|
||||
} else {
|
||||
GL_ERROR_CHECK(glDisable(GL_LIGHTING));
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( uf::renderer::settings::experimental::bloom ) {
|
||||
@ -608,58 +676,8 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string
|
||||
|
||||
auto& renderMode = uf::renderer::getRenderMode(renderModeName, true);
|
||||
auto blitters = renderMode.getBlitters();
|
||||
|
||||
#if UF_USE_OPENGL
|
||||
struct LightInfo {
|
||||
uf::Entity* entity = NULL;
|
||||
pod::Vector3f position = {0,0,0};
|
||||
float w = 1; // OpenGL requires a W
|
||||
pod::Vector4f color = {0,0,0,1}; // OpenGL requires an alpha
|
||||
float distance = 0;
|
||||
float power = 0;
|
||||
};
|
||||
uf::stl::vector<LightInfo> entities;
|
||||
for ( auto entity : graph ) {
|
||||
if ( entity == this || entity == &controller || !entity->hasComponent<ext::LightBehavior::Metadata>() ) continue;
|
||||
auto& metadata = entity->getComponent<ext::LightBehavior::Metadata>();
|
||||
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,
|
||||
.w = 1,
|
||||
.color = metadata.color,
|
||||
.distance = uf::vector::magnitude( uf::vector::subtract( flatten.position, controllerTransform.position ) ),
|
||||
.power = metadata.power,
|
||||
});
|
||||
}
|
||||
std::sort( entities.begin(), entities.end(), [&]( LightInfo& l, LightInfo& r ){
|
||||
return l.distance < r.distance;
|
||||
});
|
||||
|
||||
static GLint glMaxLights = 0;
|
||||
if ( !glMaxLights ) glGetIntegerv(GL_MAX_LIGHTS, &glMaxLights);
|
||||
metadata.light.max = std::min( (uint32_t) glMaxLights, metadata.light.max );
|
||||
|
||||
// add lighting
|
||||
{
|
||||
uint32_t i = 0;
|
||||
for ( ; i < entities.size() && i < metadata.light.max; ++i ) {
|
||||
auto& info = entities[i];
|
||||
uf::Entity* entity = info.entity;
|
||||
GLenum target = GL_LIGHT0+i;
|
||||
GL_ERROR_CHECK(glEnable(target));
|
||||
GL_ERROR_CHECK(glLightfv(target, GL_AMBIENT, &metadata.light.ambient[0]));
|
||||
GL_ERROR_CHECK(glLightfv(target, GL_SPECULAR, &metadata.light.specular[0]));
|
||||
GL_ERROR_CHECK(glLightfv(target, GL_DIFFUSE, &info.color[0]));
|
||||
GL_ERROR_CHECK(glLightfv(target, GL_POSITION, &info.position[0]));
|
||||
GL_ERROR_CHECK(glLightf(target, GL_CONSTANT_ATTENUATION, 0.0f));
|
||||
GL_ERROR_CHECK(glLightf(target, GL_LINEAR_ATTENUATION, 0));
|
||||
GL_ERROR_CHECK(glLightf(target, GL_QUADRATIC_ATTENUATION, 1.0f / info.power));
|
||||
}
|
||||
for ( ; i < metadata.light.max; ++i ) GL_ERROR_CHECK(glDisable(GL_LIGHT0+i));
|
||||
}
|
||||
#elif UF_USE_VULKAN
|
||||
#if UF_USE_VULKAN
|
||||
struct UniformDescriptor {
|
||||
struct Matrices {
|
||||
alignas(16) pod::Matrix4f view;
|
||||
|
||||
@ -659,6 +659,9 @@ void EXT_API ext::tick() {
|
||||
++::times.total.frames;
|
||||
TIMER( ::config.engine.fps.every ) {
|
||||
UF_MSG_DEBUG("System: " << (::config.engine.fps.every * 1000.0/::times.frames) << " ms/frame | Time: " << time << " | Frames: " << ::times.frames << " | FPS: " << ::times.frames / time);
|
||||
#if UF_ENV_DREAMCAST
|
||||
DC_STATS();
|
||||
#endif
|
||||
::times.frames = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@ CDIR =
|
||||
CC = gcc
|
||||
CXX = $(KOS_CCPLUS)
|
||||
TARGET_EXTENSION = elf
|
||||
OPTIMIZATIONS = -Os -fstrict-aliasing -ffast-math -flto -DUF_NO_EXCEPTIONS -fno-unroll-all-loops -fno-optimize-sibling-calls -fschedule-insns2 -fomit-frame-pointer
|
||||
OPTIMIZATIONS = -Os -g -ffunction-sections -fdata-sections -Wl,--gc-sections -fstrict-aliasing -ffast-math -flto -DUF_NO_EXCEPTIONS -fno-unroll-all-loops -fno-optimize-sibling-calls -fschedule-insns2 -fomit-frame-pointer
|
||||
WARNINGS = -Wno-attributes -Wno-conversion-null
|
||||
FLAGS += $(KOS_CPPFLAGS) -std=c++17 $(OPTIMIZATIONS) $(WARNINGS) -fdiagnostics-color=always
|
||||
INCS += $(KOS_INC_PATHS) -I/opt/dreamcast/sh-elf/sh-elf/include
|
||||
|
||||
@ -2,6 +2,6 @@ ARCH = win64
|
||||
CDIR =
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
OPTIMIZATIONS = -O3 -fstrict-aliasing -flto
|
||||
OPTIMIZATIONS = -O3 -g -fstrict-aliasing #-flto
|
||||
WARNINGS = -Wall -Wno-unknown-pragmas -Wno-unused-function -Wno-unused-variable -Wno-switch -Wno-reorder -Wno-sign-compare -Wno-unused-but-set-variable -Wno-ignored-attributes -Wno-narrowing -Wno-misleading-indentation
|
||||
FLAGS += -std=c++17 $(OPTIMIZATIONS) $(WARNINGS) -fdiagnostics-color=always
|
||||
Loading…
Reference in New Issue
Block a user