saving
This commit is contained in:
parent
fc6b0a154a
commit
653f61e8d9
70
build.zig
70
build.zig
|
|
@ -13,12 +13,12 @@ const engineDepList = [_][]const u8{
|
||||||
"assets",
|
"assets",
|
||||||
"audio",
|
"audio",
|
||||||
"core",
|
"core",
|
||||||
"graphics",
|
|
||||||
"papyrus",
|
"papyrus",
|
||||||
"platform",
|
"platform",
|
||||||
"physics",
|
"physics",
|
||||||
"ui",
|
// "graphics",
|
||||||
"vkImgui",
|
// "ui",
|
||||||
|
// "vkImgui",
|
||||||
};
|
};
|
||||||
|
|
||||||
const BuildSystem = @This();
|
const BuildSystem = @This();
|
||||||
|
|
@ -110,20 +110,64 @@ pub fn addProgram(self: *BuildSystem, opts: AddProgramOptions) *std.Build.Step.C
|
||||||
mod.addImport("Backlog", self.nw_mod);
|
mod.addImport("Backlog", self.nw_mod);
|
||||||
exe.root_module.addOptions("BacklogOptions", self.options);
|
exe.root_module.addOptions("BacklogOptions", self.options);
|
||||||
|
|
||||||
self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/graphics/shaders/triangle_mesh.vert"), "triangle_mesh_vert");
|
// I want to generate definitions from the spirv-reflect-tool during pre-build.
|
||||||
self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/graphics/shaders/default_lit.frag"), "default_lit");
|
//
|
||||||
|
// shaders will now be part of content, not code. However. .zig code definitions will be generated
|
||||||
|
// from content via the build.zig script.
|
||||||
|
//
|
||||||
|
// heres some thoughts:
|
||||||
|
//
|
||||||
|
// -Dupdate_shaders=true
|
||||||
|
//
|
||||||
|
// -Dupdate_shaders basically adds a run step to the build process 'python', 'tools/scripts/cook-shaders.py'
|
||||||
|
//
|
||||||
|
// 1. ensure spirv-reflect is compiled.
|
||||||
|
// 2. shadercross cooker generates all shader outputs - specifically spv files. they are output to content/_shaders/
|
||||||
|
// - search paths for shaders:
|
||||||
|
// - content/shaders/**
|
||||||
|
// - engine/<module names>/shaders/**
|
||||||
|
// - shaders must have a unique name across the entire project, naming scheme should be <module>.shadername.<stage>.hlsl
|
||||||
|
// 3. spirv-cross --reflect is called on each shader, updating the content/_shaders/defs/shader-name.json folder with up to date .json files
|
||||||
|
//
|
||||||
|
// final tree
|
||||||
|
//
|
||||||
|
// engine/
|
||||||
|
// - ui/
|
||||||
|
// - shaders/
|
||||||
|
// - papyrus.rect.vert.hlsl
|
||||||
|
// content/
|
||||||
|
// - _shaders/
|
||||||
|
// - def/
|
||||||
|
// papyrus.rect.vert.json
|
||||||
|
// - msl/
|
||||||
|
// papyrus.rect.vert.msl
|
||||||
|
// - spv/
|
||||||
|
// papyrus.rect.vert.spv
|
||||||
|
// - dxil/
|
||||||
|
// papyrus.rect.vert.dxil
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// During build:
|
||||||
|
// 1. spirv-reflect is called on each json in each folder and .zig shader interfaces added to the executable as a global import.
|
||||||
|
// 2. if -Dupdate_shaders is not
|
||||||
|
//
|
||||||
|
// At any time:
|
||||||
|
// asset-cooker will cook shaders and place them under content/_shaders/<msl|dxil|dxil>/<shader-name>.<msl|spv|dxil>
|
||||||
|
|
||||||
self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/graphics/shaders/debug.vert"), "debug_vert");
|
// self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/graphics/shaders/triangle_mesh.vert"), "triangle_mesh_vert");
|
||||||
self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/graphics/shaders/debug.frag"), "debug_frag");
|
// self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/graphics/shaders/default_lit.frag"), "default_lit");
|
||||||
|
|
||||||
self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/graphics/shaders/skybox/skybox.vert"), "skybox_vert");
|
// self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/graphics/shaders/debug.vert"), "debug_vert");
|
||||||
self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/graphics/shaders/skybox/skybox.frag"), "skybox_frag");
|
// self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/graphics/shaders/debug.frag"), "debug_frag");
|
||||||
|
|
||||||
self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/ui/shaders/PapyrusRect.vert"), "papyrus_vk_vert");
|
// self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/graphics/shaders/skybox/skybox.vert"), "skybox_vert");
|
||||||
self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/ui/shaders/PapyrusRect.frag"), "papyrus_vk_frag");
|
// self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/graphics/shaders/skybox/skybox.frag"), "skybox_frag");
|
||||||
|
|
||||||
self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/ui/shaders/FontSDF.vert"), "FontSDF_vert");
|
// self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/ui/shaders/PapyrusRect.vert"), "papyrus_vk_vert");
|
||||||
self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/ui/shaders/FontSDF.frag"), "FontSDF_frag");
|
// self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/ui/shaders/PapyrusRect.frag"), "papyrus_vk_frag");
|
||||||
|
|
||||||
|
// self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/ui/shaders/FontSDF.vert"), "FontSDF_vert");
|
||||||
|
// self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/ui/shaders/FontSDF.frag"), "FontSDF_frag");
|
||||||
|
|
||||||
b.getInstallStep().dependOn(self.nw_builder.getInstallStep());
|
b.getInstallStep().dependOn(self.nw_builder.getInstallStep());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,17 @@
|
||||||
.{
|
.{
|
||||||
.name = "Backlog",
|
.name = .Backlog,
|
||||||
.version = "0.0.0",
|
.version = "0.0.0",
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
.assets = .{ .path = "engine/assets" },
|
.assets = .{ .path = "engine/assets" },
|
||||||
.audio = .{ .path = "engine/audio" },
|
.audio = .{ .path = "engine/audio" },
|
||||||
.core = .{ .path = "engine/core" },
|
.core = .{ .path = "engine/core" },
|
||||||
.graphics = .{ .path = "engine/graphics" },
|
|
||||||
.papyrus = .{ .path = "engine/papyrus" },
|
.papyrus = .{ .path = "engine/papyrus" },
|
||||||
.physics = .{ .path = "engine/physics" },
|
.physics = .{ .path = "engine/physics" },
|
||||||
.platform = .{ .path = "engine/platform" },
|
.platform = .{ .path = "engine/platform" },
|
||||||
.ui = .{ .path = "engine/ui" },
|
|
||||||
.vkImgui = .{ .path = "engine/vkImgui" },
|
// .graphics = .{ .path = "engine/graphics" },
|
||||||
|
// .ui = .{ .path = "engine/ui" },
|
||||||
|
// .vkImgui = .{ .path = "engine/vkImgui" },
|
||||||
|
|
||||||
.SpirvReflect = .{ .path = "lib/spirv-reflect-zig" },
|
.SpirvReflect = .{ .path = "lib/spirv-reflect-zig" },
|
||||||
.ozz = .{ .path = "lib/ozz" },
|
.ozz = .{ .path = "lib/ozz" },
|
||||||
|
|
@ -18,4 +19,5 @@
|
||||||
.paths = .{
|
.paths = .{
|
||||||
"",
|
"",
|
||||||
},
|
},
|
||||||
|
.fingerprint = 0xcf9bab998abe37e3
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,21 @@
|
||||||
.{
|
.{
|
||||||
.name = "graphics",
|
.name = "graphics",
|
||||||
.version = "0.0.0",
|
.version = "0.0.0",
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
//
|
//
|
||||||
.vulkan = .{ .path = "../../lib/vulkan" },
|
.vulkan = .{ .path = "../../lib/vulkan" },
|
||||||
.vma = .{ .path = "../../lib/vma" },
|
.vma = .{ .path = "../../lib/vma" },
|
||||||
.glfw3 = .{ .path = "../../lib/glfw3" },
|
.glfw3 = .{ .path = "../../lib/glfw3" },
|
||||||
.cgltf = .{ .path = "../../lib/cgltf" },
|
.cgltf = .{ .path = "../../lib/cgltf" },
|
||||||
.objLoader = .{ .path = "../../lib/objLoader" },
|
.objLoader = .{ .path = "../../lib/objLoader" },
|
||||||
.SpirvReflect = .{ .path = "../../lib/spirv-reflect-zig" },
|
.SpirvReflect = .{ .path = "../../lib/spirv-reflect-zig" },
|
||||||
.ozz = .{ .path = "../../lib/ozz" },
|
.ozz = .{ .path = "../../lib/ozz" },
|
||||||
// core
|
// core
|
||||||
.core = .{ .path = "../core" },
|
.core = .{ .path = "../core" },
|
||||||
.assets = .{ .path = "../assets" },
|
.assets = .{ .path = "../assets" },
|
||||||
.platform = .{ .path = "../platform" },
|
.platform = .{ .path = "../platform" },
|
||||||
},
|
},
|
||||||
.paths = .{
|
.paths = .{
|
||||||
"",
|
"",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
|
@ -1,32 +1,32 @@
|
||||||
//glsl version 4.5
|
//glsl version 4.5
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout (location = 0) in vec3 in_color;
|
layout (location = 0) in vec3 in_color;
|
||||||
layout (location = 1) in vec2 texCoord;
|
layout (location = 1) in vec2 texCoord;
|
||||||
layout (location = 2) in vec3 worldPosition;
|
layout (location = 2) in vec3 worldPosition;
|
||||||
|
|
||||||
layout (location = 0) out vec4 outFragColor;
|
layout (location = 0) out vec4 outFragColor;
|
||||||
|
|
||||||
layout (set = 0, binding = 0) uniform CameraBuffer{
|
layout (set = 0, binding = 0) uniform CameraBuffer{
|
||||||
mat4 view;
|
mat4 view;
|
||||||
mat4 proj;
|
mat4 proj;
|
||||||
mat4 viewproj;
|
mat4 viewproj;
|
||||||
vec4 position;
|
vec4 position;
|
||||||
} cameraData;
|
} cameraData;
|
||||||
|
|
||||||
layout(set = 0, binding = 1) uniform SceneData{
|
layout(set = 0, binding = 1) uniform SceneData{
|
||||||
vec4 fogColor; // w is for exponent
|
vec4 fogColor; // w is for exponent
|
||||||
vec4 fogDistances; //x for min, y for max, zw unused.
|
vec4 fogDistances; //x for min, y for max, zw unused.
|
||||||
vec4 ambientColor;
|
vec4 ambientColor;
|
||||||
vec4 sunlightDirection; //w for sun power
|
vec4 sunlightDirection; //w for sun power
|
||||||
vec4 sunlightColor;
|
vec4 sunlightColor;
|
||||||
} sceneData;
|
} sceneData;
|
||||||
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec3 color = in_color.rgb;
|
vec3 color = in_color.rgb;
|
||||||
float cameraDist = length(cameraData.position.xyz - worldPosition);
|
float cameraDist = length(cameraData.position.xyz - worldPosition);
|
||||||
float opacity = (1.0) - (cameraDist / 300);
|
float opacity = (1.0) - (cameraDist / 300);
|
||||||
outFragColor = vec4(color, opacity * 1.0);
|
outFragColor = vec4(color, opacity * 1.0);
|
||||||
}
|
}
|
||||||
|
|
@ -1,40 +1,40 @@
|
||||||
#version 460
|
#version 460
|
||||||
|
|
||||||
layout (location = 0) in vec3 vPosition;
|
layout (location = 0) in vec3 vPosition;
|
||||||
layout (location = 1) in vec3 vNormal;
|
layout (location = 1) in vec3 vNormal;
|
||||||
layout (location = 2) in vec4 vColor;
|
layout (location = 2) in vec4 vColor;
|
||||||
layout (location = 3) in vec2 vTexCoord;
|
layout (location = 3) in vec2 vTexCoord;
|
||||||
|
|
||||||
layout (location = 0) out vec3 outColor;
|
layout (location = 0) out vec3 outColor;
|
||||||
layout (location = 1) out vec2 texCoord;
|
layout (location = 1) out vec2 texCoord;
|
||||||
layout (location = 2) out vec3 worldPosition;
|
layout (location = 2) out vec3 worldPosition;
|
||||||
|
|
||||||
layout (set = 0, binding = 0) uniform CameraBuffer{
|
layout (set = 0, binding = 0) uniform CameraBuffer{
|
||||||
mat4 view;
|
mat4 view;
|
||||||
mat4 proj;
|
mat4 proj;
|
||||||
mat4 viewproj;
|
mat4 viewproj;
|
||||||
vec4 position;
|
vec4 position;
|
||||||
} cameraData;
|
} cameraData;
|
||||||
|
|
||||||
// size: 16 x 4 + 3 x 4 = 76 => 128 bytes per object per alignment
|
// size: 16 x 4 + 3 x 4 = 76 => 128 bytes per object per alignment
|
||||||
struct ObjectData {
|
struct ObjectData {
|
||||||
mat4 model;
|
mat4 model;
|
||||||
vec4 color;
|
vec4 color;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(std140, set = 1, binding = 0) readonly buffer ObjectBuffer{
|
layout(std140, set = 1, binding = 0) readonly buffer ObjectBuffer{
|
||||||
ObjectData objects[];
|
ObjectData objects[];
|
||||||
} objectBuffer;
|
} objectBuffer;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
ObjectData object = objectBuffer.objects[gl_BaseInstance];
|
ObjectData object = objectBuffer.objects[gl_BaseInstance];
|
||||||
mat4 modelMatrix = object.model;
|
mat4 modelMatrix = object.model;
|
||||||
mat4 final = (cameraData.viewproj * modelMatrix);
|
mat4 final = (cameraData.viewproj * modelMatrix);
|
||||||
vec4 position = final * vec4(vPosition, 1.0f);
|
vec4 position = final * vec4(vPosition, 1.0f);
|
||||||
gl_Position = position;
|
gl_Position = position;
|
||||||
outColor = object.color.xyz;
|
outColor = object.color.xyz;
|
||||||
texCoord = vTexCoord;
|
texCoord = vTexCoord;
|
||||||
vec4 modelPos = modelMatrix * vec4(vPosition, 1.0f);
|
vec4 modelPos = modelMatrix * vec4(vPosition, 1.0f);
|
||||||
worldPosition = modelPos.xyz;
|
worldPosition = modelPos.xyz;
|
||||||
}
|
}
|
||||||
|
|
@ -1,47 +1,47 @@
|
||||||
//glsl version 4.5
|
//glsl version 4.5
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
#extension GL_EXT_nonuniform_qualifier : require
|
#extension GL_EXT_nonuniform_qualifier : require
|
||||||
|
|
||||||
layout (location = 0) in vec3 in_color;
|
layout (location = 0) in vec3 in_color;
|
||||||
layout (location = 1) in vec2 texCoord;
|
layout (location = 1) in vec2 texCoord;
|
||||||
layout (location = 2) in vec3 worldPosition;
|
layout (location = 2) in vec3 worldPosition;
|
||||||
layout (location = 3) flat in uint textureId;
|
layout (location = 3) flat in uint textureId;
|
||||||
layout (location = 4) flat in uint baseInstance;
|
layout (location = 4) flat in uint baseInstance;
|
||||||
|
|
||||||
layout (location = 0) out vec4 outFragColor;
|
layout (location = 0) out vec4 outFragColor;
|
||||||
|
|
||||||
|
|
||||||
#include "globalSet.glsl"
|
#include "globalSet.glsl"
|
||||||
|
|
||||||
#include "sharedSsbo.glsl"
|
#include "sharedSsbo.glsl"
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
// outFragColor = vec4(in_color + 0.25 * sceneData.ambientColor.xyz,1.0f);
|
// outFragColor = vec4(in_color + 0.25 * sceneData.ambientColor.xyz,1.0f);
|
||||||
// outFragColor = vec4(texCoord.x, texCoord.y, 0.5f, 1.0f);
|
// outFragColor = vec4(texCoord.x, texCoord.y, 0.5f, 1.0f);
|
||||||
|
|
||||||
// vec4 color = texture(tex1, texCoord).xyzw;
|
// vec4 color = texture(tex1, texCoord).xyzw;
|
||||||
vec4 color = texture(gTex[textureId], texCoord).xyzw;
|
vec4 color = texture(gTex[textureId], texCoord).xyzw;
|
||||||
|
|
||||||
if(color.w < 0.05f)
|
if(color.w < 0.05f)
|
||||||
{
|
{
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
|
|
||||||
float cameraDist = length(cameraData.position.xyz - worldPosition);
|
float cameraDist = length(cameraData.position.xyz - worldPosition);
|
||||||
float opacity = clamp((1.f) - (clamp(cameraDist - 300, 0, 300) / 300.f), 0.f, 1.f);
|
float opacity = clamp((1.f) - (clamp(cameraDist - 300, 0, 300) / 300.f), 0.f, 1.f);
|
||||||
|
|
||||||
//float opacity = 1.0;
|
//float opacity = 1.0;
|
||||||
if(opacity < 0.05f)
|
if(opacity < 0.05f)
|
||||||
{
|
{
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
|
|
||||||
// outFragColor = vec4(mix(sceneData.fogColor.xyz, color.xyz, opacity), color.w);
|
// outFragColor = vec4(mix(sceneData.fogColor.xyz, color.xyz, opacity), color.w);
|
||||||
outFragColor = vec4(color.xyz, opacity);
|
outFragColor = vec4(color.xyz, opacity);
|
||||||
|
|
||||||
//vec3 mixed = mix(normalize(vec3(0.5, 0.3, 0.2)) * 3, vec3(0.2, 0.2, 1) * 3, texCoord.y * 2);
|
//vec3 mixed = mix(normalize(vec3(0.5, 0.3, 0.2)) * 3, vec3(0.2, 0.2, 1) * 3, texCoord.y * 2);
|
||||||
//outFragColor = vec4(color.xyz, 1.0f);
|
//outFragColor = vec4(color.xyz, 1.0f);
|
||||||
//outFragColor = vec4(0.0, 1.0, 0.0, 1.0f);
|
//outFragColor = vec4(0.0, 1.0, 0.0, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
layout (set = 0, binding = 0) uniform CameraBuffer{
|
layout (set = 0, binding = 0) uniform CameraBuffer{
|
||||||
mat4 view;
|
mat4 view;
|
||||||
mat4 proj;
|
mat4 proj;
|
||||||
mat4 viewproj;
|
mat4 viewproj;
|
||||||
mat4 viewprojAlt;
|
mat4 viewprojAlt;
|
||||||
vec4 position;
|
vec4 position;
|
||||||
} cameraData;
|
} cameraData;
|
||||||
|
|
||||||
|
|
||||||
layout(set = 0, binding = 1) uniform SceneData{
|
layout(set = 0, binding = 1) uniform SceneData{
|
||||||
vec4 fogColor; // w is for exponent
|
vec4 fogColor; // w is for exponent
|
||||||
vec4 fogDistances; //x for min, y for max, zw unused.
|
vec4 fogDistances; //x for min, y for max, zw unused.
|
||||||
vec4 ambientColor;
|
vec4 ambientColor;
|
||||||
vec4 sunlightDirection; //w for sun power
|
vec4 sunlightDirection; //w for sun power
|
||||||
vec4 sunlightColor;
|
vec4 sunlightColor;
|
||||||
} sceneData;
|
} sceneData;
|
||||||
|
|
||||||
layout(set = 0, binding = 2) uniform sampler2D[] gTex;
|
layout(set = 0, binding = 2) uniform sampler2D[] gTex;
|
||||||
|
|
@ -1,25 +1,25 @@
|
||||||
struct ObjectData {
|
struct ObjectData {
|
||||||
mat4 model;
|
mat4 model;
|
||||||
uint textureId;
|
uint textureId;
|
||||||
int animation; // this is the index offset of the first matrix in the animation finals buffer.
|
int animation; // this is the index offset of the first matrix in the animation finals buffer.
|
||||||
uint flags0;
|
uint flags0;
|
||||||
// packed flags0 flags;
|
// packed flags0 flags;
|
||||||
// [0,0]: alwaysInFront
|
// [0,0]: alwaysInFront
|
||||||
// [1,1]: useAltCamera
|
// [1,1]: useAltCamera
|
||||||
uint pad1;
|
uint pad1;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(std140, set = 1, binding = 0) readonly buffer ObjectBuffer{
|
layout(std140, set = 1, binding = 0) readonly buffer ObjectBuffer{
|
||||||
ObjectData objects[];
|
ObjectData objects[];
|
||||||
} objectBuffer;
|
} objectBuffer;
|
||||||
|
|
||||||
|
|
||||||
uint flag0_AlwaysInFront(uint flags)
|
uint flag0_AlwaysInFront(uint flags)
|
||||||
{
|
{
|
||||||
return flags & 0x1;
|
return flags & 0x1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint flag0_useAltFov(uint flags)
|
uint flag0_useAltFov(uint flags)
|
||||||
{
|
{
|
||||||
return (flags >> 1) & 0x1;
|
return (flags >> 1) & 0x1;
|
||||||
}
|
}
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
layout(std140, set = 1, binding = 1) readonly buffer BoneBuffer{
|
layout(std140, set = 1, binding = 1) readonly buffer BoneBuffer{
|
||||||
mat4 finals[];
|
mat4 finals[];
|
||||||
} animationBuffer;
|
} animationBuffer;
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
#include "../globalSet.glsl"
|
#include "../globalSet.glsl"
|
||||||
|
|
||||||
|
|
||||||
layout(set = 1, binding = 0) uniform samplerCube cubemap;
|
layout(set = 1, binding = 0) uniform samplerCube cubemap;
|
||||||
|
|
||||||
layout (location = 0) in vec3 inUVW;
|
layout (location = 0) in vec3 inUVW;
|
||||||
|
|
||||||
layout (location = 0) out vec4 outFragColor;
|
layout (location = 0) out vec4 outFragColor;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
outFragColor = texture(cubemap, inUVW);
|
outFragColor = texture(cubemap, inUVW);
|
||||||
}
|
}
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
#include "../vertexInput.glsl"
|
#include "../vertexInput.glsl"
|
||||||
#include "../globalSet.glsl"
|
#include "../globalSet.glsl"
|
||||||
|
|
||||||
|
|
||||||
layout (location = 0) out vec3 outUVW;
|
layout (location = 0) out vec3 outUVW;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
outUVW = vPosition;
|
outUVW = vPosition;
|
||||||
// Convert cubemap coordinates into Vulkan coordinate space
|
// Convert cubemap coordinates into Vulkan coordinate space
|
||||||
|
|
||||||
// Remove translation from view matrix
|
// Remove translation from view matrix
|
||||||
mat4 viewMat = mat4(mat3(cameraData.view));
|
mat4 viewMat = mat4(mat3(cameraData.view));
|
||||||
gl_Position = cameraData.proj * viewMat * vec4(vPosition.xyz, 1.0);
|
gl_Position = cameraData.proj * viewMat * vec4(vPosition.xyz, 1.0);
|
||||||
}
|
}
|
||||||
|
|
@ -1,66 +1,66 @@
|
||||||
#version 460
|
#version 460
|
||||||
|
|
||||||
|
|
||||||
#include "vertexInput.glsl"
|
#include "vertexInput.glsl"
|
||||||
|
|
||||||
layout (location = 0) out vec3 outColor;
|
layout (location = 0) out vec3 outColor;
|
||||||
layout (location = 1) out vec2 texCoord;
|
layout (location = 1) out vec2 texCoord;
|
||||||
layout (location = 2) out vec3 worldPosition;
|
layout (location = 2) out vec3 worldPosition;
|
||||||
layout (location = 3) flat out uint textureId;
|
layout (location = 3) flat out uint textureId;
|
||||||
layout (location = 4) flat out uint baseInstance;
|
layout (location = 4) flat out uint baseInstance;
|
||||||
|
|
||||||
#include "globalSet.glsl"
|
#include "globalSet.glsl"
|
||||||
#include "sharedSsbo.glsl"
|
#include "sharedSsbo.glsl"
|
||||||
#include "skeletalBuffers.glsl"
|
#include "skeletalBuffers.glsl"
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec3 vertexPos = vec3(0.0);
|
vec3 vertexPos = vec3(0.0);
|
||||||
int animation = objectBuffer.objects[gl_BaseInstance].animation;
|
int animation = objectBuffer.objects[gl_BaseInstance].animation;
|
||||||
|
|
||||||
if(animation == -1)
|
if(animation == -1)
|
||||||
{
|
{
|
||||||
vertexPos = vPosition;
|
vertexPos = vPosition;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint animation = objectBuffer.objects[gl_BaseInstance].animation;
|
uint animation = objectBuffer.objects[gl_BaseInstance].animation;
|
||||||
|
|
||||||
for(int i = 0; i < 4; i += 1)
|
for(int i = 0; i < 4; i += 1)
|
||||||
{
|
{
|
||||||
uint boneIndex = bones[i];
|
uint boneIndex = bones[i];
|
||||||
float weight = float(weights[i]) / 255;
|
float weight = float(weights[i]) / 255;
|
||||||
|
|
||||||
// this will depend on ozz's finals format
|
// this will depend on ozz's finals format
|
||||||
mat4 boneTransform = animationBuffer.finals[animation + boneIndex];
|
mat4 boneTransform = animationBuffer.finals[animation + boneIndex];
|
||||||
vertexPos += weight * ( boneTransform * vec4(vPosition, 1.0) ).xyz;
|
vertexPos += weight * ( boneTransform * vec4(vPosition, 1.0) ).xyz;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mat4 modelMatrix = objectBuffer.objects[gl_BaseInstance].model;
|
mat4 modelMatrix = objectBuffer.objects[gl_BaseInstance].model;
|
||||||
|
|
||||||
mat4 final;
|
mat4 final;
|
||||||
|
|
||||||
if(flag0_useAltFov(objectBuffer.objects[gl_BaseInstance].flags0) == 1)
|
if(flag0_useAltFov(objectBuffer.objects[gl_BaseInstance].flags0) == 1)
|
||||||
{
|
{
|
||||||
final = (cameraData.viewprojAlt * modelMatrix);
|
final = (cameraData.viewprojAlt * modelMatrix);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
final = (cameraData.viewproj * modelMatrix);
|
final = (cameraData.viewproj * modelMatrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec4 position = final * vec4(vertexPos, 1.0f);
|
vec4 position = final * vec4(vertexPos, 1.0f);
|
||||||
|
|
||||||
if( flag0_AlwaysInFront(objectBuffer.objects[gl_BaseInstance].flags0) == 1)
|
if( flag0_AlwaysInFront(objectBuffer.objects[gl_BaseInstance].flags0) == 1)
|
||||||
{
|
{
|
||||||
position.z *= 0.0001;
|
position.z *= 0.0001;
|
||||||
}
|
}
|
||||||
|
|
||||||
baseInstance = gl_BaseInstance;
|
baseInstance = gl_BaseInstance;
|
||||||
gl_Position = position;
|
gl_Position = position;
|
||||||
textureId = objectBuffer.objects[gl_BaseInstance].textureId;
|
textureId = objectBuffer.objects[gl_BaseInstance].textureId;
|
||||||
outColor = vec3(vColor.x, vColor.y, vColor.z);
|
outColor = vec3(vColor.x, vColor.y, vColor.z);
|
||||||
texCoord = vTexCoord;
|
texCoord = vTexCoord;
|
||||||
worldPosition = (modelMatrix * vec4(0,0,0,1)).xyz;
|
worldPosition = (modelMatrix * vec4(0,0,0,1)).xyz;
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#extension GL_EXT_shader_explicit_arithmetic_types_int8 : enable
|
#extension GL_EXT_shader_explicit_arithmetic_types_int8 : enable
|
||||||
layout (location = 0) in vec3 vPosition;
|
layout (location = 0) in vec3 vPosition;
|
||||||
layout (location = 1) in vec3 vNormal;
|
layout (location = 1) in vec3 vNormal;
|
||||||
layout (location = 2) in vec4 vColor;
|
layout (location = 2) in vec4 vColor;
|
||||||
layout (location = 3) in vec2 vTexCoord;
|
layout (location = 3) in vec2 vTexCoord;
|
||||||
layout (location = 4) in u8vec4 bones;
|
layout (location = 4) in u8vec4 bones;
|
||||||
layout (location = 5) in u8vec4 weights;
|
layout (location = 5) in u8vec4 weights;
|
||||||
|
|
@ -1,32 +1,32 @@
|
||||||
pixels: []u8,
|
pixels: []u8,
|
||||||
extent: core.Vector2i,
|
extent: core.Vector2i,
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const core = @import("core");
|
const core = @import("core");
|
||||||
const colors = core.colors;
|
const colors = core.colors;
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator, extent: core.Vector2i) !@This() {
|
pub fn init(allocator: std.mem.Allocator, extent: core.Vector2i) !@This() {
|
||||||
return .{
|
return .{
|
||||||
.pixels = try allocator.alignedAlloc(u8, 8, @intCast(extent.x * extent.y * 4)),
|
.pixels = try allocator.alignedAlloc(u8, 8, @intCast(extent.x * extent.y * 4)),
|
||||||
.extent = extent,
|
.extent = extent,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear(self: *@This(), clearColor: colors.ColorRGBA8) void {
|
pub fn clear(self: *@This(), clearColor: colors.ColorRGBA8) void {
|
||||||
var as32: []u32 = undefined;
|
var as32: []u32 = undefined;
|
||||||
as32.len = self.pixels.len / 4;
|
as32.len = self.pixels.len / 4;
|
||||||
as32.ptr = @alignCast(@ptrCast(self.pixels.ptr));
|
as32.ptr = @alignCast(@ptrCast(self.pixels.ptr));
|
||||||
|
|
||||||
@memset(as32, @as(u32, @bitCast(clearColor)));
|
@memset(as32, @as(u32, @bitCast(clearColor)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *@This(), allocator: std.mem.Allocator) void {
|
pub fn deinit(self: *@This(), allocator: std.mem.Allocator) void {
|
||||||
allocator.free(self.pixels);
|
allocator.free(self.pixels);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub inline fn getPixel(self: *@This(), position: core.Vector2i) *colors.ColorRGBA8 {
|
pub inline fn getPixel(self: *@This(), position: core.Vector2i) *colors.ColorRGBA8 {
|
||||||
const offset = position.x * position.y * 4;
|
const offset = position.x * position.y * 4;
|
||||||
const r: *u8 = &self.pixels[@intCast(offset)];
|
const r: *u8 = &self.pixels[@intCast(offset)];
|
||||||
|
|
||||||
return @as(*colors.ColorRGBA8, @alignCast(@ptrCast(r)));
|
return @as(*colors.ColorRGBA8, @alignCast(@ptrCast(r)));
|
||||||
}
|
}
|
||||||
|
|
@ -1,232 +1,232 @@
|
||||||
pub const AnimResolverRef = core.Reference(AnimResolverInterface);
|
pub const AnimResolverRef = core.Reference(AnimResolverInterface);
|
||||||
pub const AnimResolverInterface = core.MakeInterface("AnimResolverVTable", struct {
|
pub const AnimResolverInterface = core.MakeInterface("AnimResolverVTable", struct {
|
||||||
// this tick function should evaluate the current state of the resolver
|
// this tick function should evaluate the current state of the resolver
|
||||||
// and then update the animator's finals[] matrix list.
|
// and then update the animator's finals[] matrix list.
|
||||||
resolve: *const fn (*anyopaque, f64, *Animator) void,
|
resolve: *const fn (*anyopaque, f64, *Animator) void,
|
||||||
onSkeletonSet: ?*const fn (*anyopaque, *Animator) void = null,
|
onSkeletonSet: ?*const fn (*anyopaque, *Animator) void = null,
|
||||||
|
|
||||||
create: *const fn (std.mem.Allocator) core.EngineDataEventError!*anyopaque,
|
create: *const fn (std.mem.Allocator) core.EngineDataEventError!*anyopaque,
|
||||||
destroy: *const fn (*anyopaque) void,
|
destroy: *const fn (*anyopaque) void,
|
||||||
|
|
||||||
pub fn Implement(comptime TargetType: type) @This() {
|
pub fn Implement(comptime TargetType: type) @This() {
|
||||||
const Wrap = struct {
|
const Wrap = struct {
|
||||||
pub fn create(allocator: std.mem.Allocator) core.EngineDataEventError!*anyopaque {
|
pub fn create(allocator: std.mem.Allocator) core.EngineDataEventError!*anyopaque {
|
||||||
const new = TargetType.create(allocator) catch return core.EngineDataEventError.BadInit;
|
const new = TargetType.create(allocator) catch return core.EngineDataEventError.BadInit;
|
||||||
return @ptrCast(new);
|
return @ptrCast(new);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy(p: *anyopaque) void {
|
pub fn destroy(p: *anyopaque) void {
|
||||||
const ptr: *TargetType = @ptrCast(@alignCast(p));
|
const ptr: *TargetType = @ptrCast(@alignCast(p));
|
||||||
ptr.destroy();
|
ptr.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn onSkeletonSet(p: *anyopaque, a: *Animator) void {
|
pub fn onSkeletonSet(p: *anyopaque, a: *Animator) void {
|
||||||
const ptr: *TargetType = @ptrCast(@alignCast(p));
|
const ptr: *TargetType = @ptrCast(@alignCast(p));
|
||||||
ptr.onSkeletonSet(a) catch unreachable;
|
ptr.onSkeletonSet(a) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve(p: *anyopaque, dt: f64, a: *Animator) void {
|
pub fn resolve(p: *anyopaque, dt: f64, a: *Animator) void {
|
||||||
const ptr: *TargetType = @ptrCast(@alignCast(p));
|
const ptr: *TargetType = @ptrCast(@alignCast(p));
|
||||||
ptr.resolve(dt, a) catch unreachable;
|
ptr.resolve(dt, a) catch unreachable;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return .{
|
return .{
|
||||||
.destroy = Wrap.destroy,
|
.destroy = Wrap.destroy,
|
||||||
.create = Wrap.create,
|
.create = Wrap.create,
|
||||||
.resolve = Wrap.resolve,
|
.resolve = Wrap.resolve,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
pub const AnimSampler = struct {
|
pub const AnimSampler = struct {
|
||||||
name: ?core.Name = null,
|
name: ?core.Name = null,
|
||||||
track: ?*AnimationTrack = null,
|
track: ?*AnimationTrack = null,
|
||||||
playbackRate: f32 = 1.0,
|
playbackRate: f32 = 1.0,
|
||||||
time: f32 = 0.0,
|
time: f32 = 0.0,
|
||||||
outputLocals: std.ArrayListUnmanaged(ozz.SoaTransform) = .{},
|
outputLocals: std.ArrayListUnmanaged(ozz.SoaTransform) = .{},
|
||||||
|
|
||||||
// other features
|
// other features
|
||||||
// paused: bool = false,
|
// paused: bool = false,
|
||||||
pub fn deinit(self: *@This(), allocator: std.mem.Allocator) void {
|
pub fn deinit(self: *@This(), allocator: std.mem.Allocator) void {
|
||||||
self.outputLocals.deinit(allocator);
|
self.outputLocals.deinit(allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getOutput(self: *@This()) []ozz.SoaTransform {
|
pub fn getOutput(self: *@This()) []ozz.SoaTransform {
|
||||||
return self.outputLocals.items;
|
return self.outputLocals.items;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sampleAndAdvance(self: *@This(), allocator: std.mem.Allocator, dt: f64, animator: *Animator) void {
|
pub fn sampleAndAdvance(self: *@This(), allocator: std.mem.Allocator, dt: f64, animator: *Animator) void {
|
||||||
self.sample(allocator, animator);
|
self.sample(allocator, animator);
|
||||||
self.advance(dt);
|
self.advance(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn advance(self: *@This(), dt: f64) void {
|
pub fn advance(self: *@This(), dt: f64) void {
|
||||||
if (self.track == null) {
|
if (self.track == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FloatHelpers.updateTrackTime(&self.time, dt, self.playbackRate, self.track.?.endTime);
|
FloatHelpers.updateTrackTime(&self.time, dt, self.playbackRate, self.track.?.endTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setName(self: *@This(), name: core.Name) void {
|
pub fn setName(self: *@This(), name: core.Name) void {
|
||||||
self.name = name;
|
self.name = name;
|
||||||
self.track = null;
|
self.track = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sample(self: *@This(), allocator: std.mem.Allocator, animator: *Animator) void {
|
pub fn sample(self: *@This(), allocator: std.mem.Allocator, animator: *Animator) void {
|
||||||
if (self.name == null) {
|
if (self.name == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.track == null) {
|
if (self.track == null) {
|
||||||
self.track = animation_system.gAnimationSys.animTracks.get(self.name.?.handle());
|
self.track = animation_system.gAnimationSys.animTracks.get(self.name.?.handle());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.outputLocals.resize(allocator, animator.jointLength) catch return;
|
self.outputLocals.resize(allocator, animator.jointLength) catch return;
|
||||||
|
|
||||||
if (self.track) |track| {
|
if (self.track) |track| {
|
||||||
if (track.endTime < 0.01) {
|
if (track.endTime < 0.01) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
animator.sampleAnimation(self.time, track, self.outputLocals.items);
|
animator.sampleAnimation(self.time, track, self.outputLocals.items);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const BlenderList = struct {
|
pub const BlenderList = struct {
|
||||||
backing: std.mem.Allocator,
|
backing: std.mem.Allocator,
|
||||||
arena: std.heap.ArenaAllocator,
|
arena: std.heap.ArenaAllocator,
|
||||||
|
|
||||||
jobLayers: std.ArrayListUnmanaged(ozz.Layer) = .{},
|
jobLayers: std.ArrayListUnmanaged(ozz.Layer) = .{},
|
||||||
jobLayersAdditive: std.ArrayListUnmanaged(ozz.Layer) = .{},
|
jobLayersAdditive: std.ArrayListUnmanaged(ozz.Layer) = .{},
|
||||||
useAdditive: bool = false,
|
useAdditive: bool = false,
|
||||||
|
|
||||||
threshold: f32 = 0.01,
|
threshold: f32 = 0.01,
|
||||||
jointLength: usize = 0,
|
jointLength: usize = 0,
|
||||||
blendingJob: ozz.BlendingJob = .{},
|
blendingJob: ozz.BlendingJob = .{},
|
||||||
|
|
||||||
pub fn create(backingAllocator: std.mem.Allocator) !*@This() {
|
pub fn create(backingAllocator: std.mem.Allocator) !*@This() {
|
||||||
const self = try backingAllocator.create(@This());
|
const self = try backingAllocator.create(@This());
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.backing = backingAllocator,
|
.backing = backingAllocator,
|
||||||
.arena = std.heap.ArenaAllocator.init(backingAllocator),
|
.arena = std.heap.ArenaAllocator.init(backingAllocator),
|
||||||
};
|
};
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy(self: *@This()) void {
|
pub fn destroy(self: *@This()) void {
|
||||||
self.arena.deinit();
|
self.arena.deinit();
|
||||||
self.backing.destroy(self);
|
self.backing.destroy(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn updateRestPose(self: *@This(), animator: *Animator) !void {
|
pub fn updateRestPose(self: *@This(), animator: *Animator) !void {
|
||||||
if (animator.skeleton) |skeleton| {
|
if (animator.skeleton) |skeleton| {
|
||||||
self.jointLength = skeleton.sk.numJoints();
|
self.jointLength = skeleton.sk.numJoints();
|
||||||
self.blendingJob.rest_pose = skeleton.sk.getRestPoseModel();
|
self.blendingJob.rest_pose = skeleton.sk.getRestPoseModel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clearLayers(self: *@This()) void {
|
pub fn clearLayers(self: *@This()) void {
|
||||||
self.jobLayersAdditive.clearRetainingCapacity();
|
self.jobLayersAdditive.clearRetainingCapacity();
|
||||||
self.jobLayers.clearRetainingCapacity();
|
self.jobLayers.clearRetainingCapacity();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addLayer(self: *@This(), transform: []ozz.SoaTransform, weight: f32, settings: anytype) void {
|
pub fn addLayer(self: *@This(), transform: []ozz.SoaTransform, weight: f32, settings: anytype) void {
|
||||||
const layer = self.jobLayers.addOne(self.arena.allocator()) catch unreachable;
|
const layer = self.jobLayers.addOne(self.arena.allocator()) catch unreachable;
|
||||||
layer.* = .{
|
layer.* = .{
|
||||||
.weight = weight,
|
.weight = weight,
|
||||||
.transform = ozz.makeSpan(transform),
|
.transform = ozz.makeSpan(transform),
|
||||||
};
|
};
|
||||||
_ = settings;
|
_ = settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn updateAndRun(self: *@This(), output: []ozz.SoaTransform) void {
|
pub fn updateAndRun(self: *@This(), output: []ozz.SoaTransform) void {
|
||||||
self.updateBlendingJob();
|
self.updateBlendingJob();
|
||||||
self.runBlendingJob(output) catch return;
|
self.runBlendingJob(output) catch return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn updateBlendingJob(self: *@This()) void {
|
pub fn updateBlendingJob(self: *@This()) void {
|
||||||
self.blendingJob.threshold = self.threshold;
|
self.blendingJob.threshold = self.threshold;
|
||||||
self.blendingJob.layers = ozz.makeSpan(self.jobLayers.items);
|
self.blendingJob.layers = ozz.makeSpan(self.jobLayers.items);
|
||||||
//self.blendingJob.additive_layers = if (self.useAdditive) ozz.makeSpan(self.jobLayersAdditive.items) else .{};
|
//self.blendingJob.additive_layers = if (self.useAdditive) ozz.makeSpan(self.jobLayersAdditive.items) else .{};
|
||||||
self.blendingJob.additive_layers = .{};
|
self.blendingJob.additive_layers = .{};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn runBlendingJob(self: *@This(), output: []ozz.SoaTransform) !void {
|
pub fn runBlendingJob(self: *@This(), output: []ozz.SoaTransform) !void {
|
||||||
self.blendingJob.output = ozz.makeSpan(output);
|
self.blendingJob.output = ozz.makeSpan(output);
|
||||||
if (!self.blendingJob.run()) {
|
if (!self.blendingJob.run()) {
|
||||||
core.engine_logs("blending job failed");
|
core.engine_logs("blending job failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// resolver helpers
|
// resolver helpers
|
||||||
pub const FloatHelpers = struct {
|
pub const FloatHelpers = struct {
|
||||||
pub inline fn updateTrackTime(target: *f32, dt: f64, rate: f32, endTime: f32) void {
|
pub inline fn updateTrackTime(target: *f32, dt: f64, rate: f32, endTime: f32) void {
|
||||||
target.* += @as(f32, @floatCast(dt)) * rate;
|
target.* += @as(f32, @floatCast(dt)) * rate;
|
||||||
while (target.* > endTime) {
|
while (target.* > endTime) {
|
||||||
target.* -= endTime;
|
target.* -= endTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// samples a single animation, same as the default behaviour.
|
// samples a single animation, same as the default behaviour.
|
||||||
// used as a test for the resolver system
|
// used as a test for the resolver system
|
||||||
pub const SingleAnimationResolver = struct {
|
pub const SingleAnimationResolver = struct {
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
locals: std.ArrayListUnmanaged(ozz.SoaTransform) = .{},
|
locals: std.ArrayListUnmanaged(ozz.SoaTransform) = .{},
|
||||||
|
|
||||||
track: ?*AnimationTrack = null,
|
track: ?*AnimationTrack = null,
|
||||||
playback: f32 = 0.0,
|
playback: f32 = 0.0,
|
||||||
playbackRate: f32 = 1.0,
|
playbackRate: f32 = 1.0,
|
||||||
|
|
||||||
pub const AnimResolverVTable = AnimResolverInterface.Implement(@This());
|
pub const AnimResolverVTable = AnimResolverInterface.Implement(@This());
|
||||||
|
|
||||||
pub fn create(allocator: std.mem.Allocator) !*@This() {
|
pub fn create(allocator: std.mem.Allocator) !*@This() {
|
||||||
const self = try allocator.create(@This());
|
const self = try allocator.create(@This());
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
};
|
};
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn onSkeletonSet(self: *@This(), animator: *Animator) !void {
|
pub fn onSkeletonSet(self: *@This(), animator: *Animator) !void {
|
||||||
if (animator.skeleton) |skeleton| {
|
if (animator.skeleton) |skeleton| {
|
||||||
try self.locals.resize(self.allocator, skeleton.sk.numSoaJoints());
|
try self.locals.resize(self.allocator, skeleton.sk.numSoaJoints());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve(self: *@This(), dt: f64, animator: *Animator) !void {
|
pub fn resolve(self: *@This(), dt: f64, animator: *Animator) !void {
|
||||||
self.track = animator.track;
|
self.track = animator.track;
|
||||||
if (self.track == null) {
|
if (self.track == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const track = self.track.?;
|
const track = self.track.?;
|
||||||
if (track.endTime < 0.01) {
|
if (track.endTime < 0.01) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FloatHelpers.updateTrackTime(&self.playback, dt, self.playbackRate, track.endTime);
|
FloatHelpers.updateTrackTime(&self.playback, dt, self.playbackRate, track.endTime);
|
||||||
animator.sampleAnimation(self.playback, track, self.locals.items);
|
animator.sampleAnimation(self.playback, track, self.locals.items);
|
||||||
animator.commitLocalToModel(self.locals.items);
|
animator.commitLocalToModel(self.locals.items);
|
||||||
animator.modelToFinal();
|
animator.modelToFinal();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy(self: *@This()) void {
|
pub fn destroy(self: *@This()) void {
|
||||||
self.locals.deinit(self.allocator);
|
self.locals.deinit(self.allocator);
|
||||||
self.allocator.destroy(self);
|
self.allocator.destroy(self);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const animation_system = @import("animationSystem.zig");
|
const animation_system = @import("animationSystem.zig");
|
||||||
const Animator = animation_system.Animator;
|
const Animator = animation_system.Animator;
|
||||||
const AnimationTrack = animation_system.AnimationTrack;
|
const AnimationTrack = animation_system.AnimationTrack;
|
||||||
|
|
||||||
const core = @import("core");
|
const core = @import("core");
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const ozz = @import("ozz");
|
const ozz = @import("ozz");
|
||||||
|
|
@ -1,480 +1,480 @@
|
||||||
// big main sy.itemsstem for animation
|
// big main sy.itemsstem for animation
|
||||||
|
|
||||||
const ozz = @import("ozz");
|
const ozz = @import("ozz");
|
||||||
const core = @import("core");
|
const core = @import("core");
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
pub const BoneHandle = enum(u8) { _ };
|
pub const BoneHandle = enum(u8) { _ };
|
||||||
|
|
||||||
pub const Skeleton = struct {
|
pub const Skeleton = struct {
|
||||||
sk: *ozz.Skeleton,
|
sk: *ozz.Skeleton,
|
||||||
inverseBinds: std.ArrayListUnmanaged(core.Mat) = .{},
|
inverseBinds: std.ArrayListUnmanaged(core.Mat) = .{},
|
||||||
jointMapping: std.StringHashMapUnmanaged(u8) = .{},
|
jointMapping: std.StringHashMapUnmanaged(u8) = .{},
|
||||||
|
|
||||||
pub fn buildJointMap(self: *@This(), allocator: std.mem.Allocator) !void {
|
pub fn buildJointMap(self: *@This(), allocator: std.mem.Allocator) !void {
|
||||||
for (self.sk.getJointsList(), 0..) |jointName, i| {
|
for (self.sk.getJointsList(), 0..) |jointName, i| {
|
||||||
// std.debug.print("jointName {d} {s}\n", .{ i, jointName });
|
// std.debug.print("jointName {d} {s}\n", .{ i, jointName });
|
||||||
const str = std.mem.span(jointName);
|
const str = std.mem.span(jointName);
|
||||||
try self.jointMapping.put(allocator, str, @intCast(i));
|
try self.jointMapping.put(allocator, str, @intCast(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getBoneHandleByName(self: @This(), string: []const u8) ?BoneHandle {
|
pub fn getBoneHandleByName(self: @This(), string: []const u8) ?BoneHandle {
|
||||||
if (self.jointMapping.get(string)) |x| {
|
if (self.jointMapping.get(string)) |x| {
|
||||||
return @enumFromInt(x);
|
return @enumFromInt(x);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *@This()) void {
|
pub fn deinit(self: *@This()) void {
|
||||||
self.sk.destroy();
|
self.sk.destroy();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const AnimationTrack = struct {
|
pub const AnimationTrack = struct {
|
||||||
animation: *ozz.Animation,
|
animation: *ozz.Animation,
|
||||||
endTime: f32 = 1.0,
|
endTime: f32 = 1.0,
|
||||||
|
|
||||||
pub fn deinit(self: *@This()) void {
|
pub fn deinit(self: *@This()) void {
|
||||||
self.animation.destroy();
|
self.animation.destroy();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const PlaybackTrack = struct {
|
pub const PlaybackTrack = struct {
|
||||||
track: ?*AnimationTrack = null,
|
track: ?*AnimationTrack = null,
|
||||||
playback: f32 = 0.0,
|
playback: f32 = 0.0,
|
||||||
playbackRate: f32 = 1.0,
|
playbackRate: f32 = 1.0,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Animator = struct {
|
pub const Animator = struct {
|
||||||
jointRemap: ?[]u8 = null,
|
jointRemap: ?[]u8 = null,
|
||||||
animationName: ?core.Name = null,
|
animationName: ?core.Name = null,
|
||||||
skeleton: ?*Skeleton = null,
|
skeleton: ?*Skeleton = null,
|
||||||
skeletonName: ?core.Name = null,
|
skeletonName: ?core.Name = null,
|
||||||
sjc: *ozz.SamplingJobContext = undefined,
|
sjc: *ozz.SamplingJobContext = undefined,
|
||||||
|
|
||||||
track: ?*AnimationTrack = null,
|
track: ?*AnimationTrack = null,
|
||||||
playback: f32 = 0.0,
|
playback: f32 = 0.0,
|
||||||
playbackRate: f32 = 1.0,
|
playbackRate: f32 = 1.0,
|
||||||
|
|
||||||
// todo.. implement blending
|
// todo.. implement blending
|
||||||
// animations: [4]*ozz.Animation = undefined,
|
// animations: [4]*ozz.Animation = undefined,
|
||||||
// timelines: [4]f32 = .{ 0, 0, 0, 0 },
|
// timelines: [4]f32 = .{ 0, 0, 0, 0 },
|
||||||
animationCount: u32 = 0,
|
animationCount: u32 = 0,
|
||||||
|
|
||||||
locals: std.ArrayListUnmanaged(ozz.SoaTransform) = .{},
|
locals: std.ArrayListUnmanaged(ozz.SoaTransform) = .{},
|
||||||
models: std.ArrayListUnmanaged(ozz.Float4x4) = .{},
|
models: std.ArrayListUnmanaged(ozz.Float4x4) = .{},
|
||||||
finals: std.ArrayListUnmanaged(core.Mat) = .{},
|
finals: std.ArrayListUnmanaged(core.Mat) = .{},
|
||||||
finalsSpan: core.Span = undefined,
|
finalsSpan: core.Span = undefined,
|
||||||
|
|
||||||
entity: core.Entity = undefined,
|
entity: core.Entity = undefined,
|
||||||
jointLength: usize = 0,
|
jointLength: usize = 0,
|
||||||
|
|
||||||
resolverRef: ?AnimResolverRef = null,
|
resolverRef: ?AnimResolverRef = null,
|
||||||
|
|
||||||
pub var allocator: std.mem.Allocator = undefined;
|
pub var allocator: std.mem.Allocator = undefined;
|
||||||
// oh god if I want to support multiple animation blending...
|
// oh god if I want to support multiple animation blending...
|
||||||
// maybe the kernel should contain a fixed amount of animations?
|
// maybe the kernel should contain a fixed amount of animations?
|
||||||
|
|
||||||
pub fn initECS(self: *@This(), handle: core.SetHandle) void {
|
pub fn initECS(self: *@This(), handle: core.SetHandle) void {
|
||||||
// get the mesh component
|
// get the mesh component
|
||||||
self.entity = core.Entity{ .handle = handle };
|
self.entity = core.Entity{ .handle = handle };
|
||||||
|
|
||||||
if (self.entity.get(graphics.StaticMesh)) |mesh| {
|
if (self.entity.get(graphics.StaticMesh)) |mesh| {
|
||||||
mesh.animated = true; //todo
|
mesh.animated = true; //todo
|
||||||
mesh.animator = self;
|
mesh.animator = self;
|
||||||
self.sjc = ozz.SamplingJobContext.createMaxTracks(256);
|
self.sjc = ozz.SamplingJobContext.createMaxTracks(256);
|
||||||
} else {
|
} else {
|
||||||
@panic("animator added to an entity that does not have a mesh component");
|
@panic("animator added to an entity that does not have a mesh component");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getBoneTransform(self: *@This(), handle: BoneHandle) core.Mat {
|
pub fn getBoneTransform(self: *@This(), handle: BoneHandle) core.Mat {
|
||||||
return @bitCast(self.models.items[@intFromEnum(handle)]);
|
return @bitCast(self.models.items[@intFromEnum(handle)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setSkeletonByName(self: *@This(), skName: core.Name) !void {
|
pub fn setSkeletonByName(self: *@This(), skName: core.Name) !void {
|
||||||
if (self.skeleton != null) {
|
if (self.skeleton != null) {
|
||||||
// return the previous span and allocate a new one.
|
// return the previous span and allocate a new one.
|
||||||
gAnimationSys.slots.removeSpan(self.finalsSpan);
|
gAnimationSys.slots.removeSpan(self.finalsSpan);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.skeletonName = skName;
|
self.skeletonName = skName;
|
||||||
self.skeleton = gAnimationSys.skeletons.get(self.skeletonName.?.handle()).?;
|
self.skeleton = gAnimationSys.skeletons.get(self.skeletonName.?.handle()).?;
|
||||||
const numJoints = self.skeleton.?.sk.numJoints();
|
const numJoints = self.skeleton.?.sk.numJoints();
|
||||||
self.jointLength = numJoints;
|
self.jointLength = numJoints;
|
||||||
|
|
||||||
self.sjc.resize(@intCast(numJoints));
|
self.sjc.resize(@intCast(numJoints));
|
||||||
try self.locals.resize(allocator, self.skeleton.?.sk.numSoaJoints());
|
try self.locals.resize(allocator, self.skeleton.?.sk.numSoaJoints());
|
||||||
try self.models.resize(allocator, numJoints);
|
try self.models.resize(allocator, numJoints);
|
||||||
try self.finals.resize(allocator, numJoints);
|
try self.finals.resize(allocator, numJoints);
|
||||||
self.finalsSpan = try gAnimationSys.slots.allocate(@intCast(numJoints));
|
self.finalsSpan = try gAnimationSys.slots.allocate(@intCast(numJoints));
|
||||||
|
|
||||||
if (self.resolverRef) |ref| {
|
if (self.resolverRef) |ref| {
|
||||||
if (ref.vtable.onSkeletonSet) |f| {
|
if (ref.vtable.onSkeletonSet) |f| {
|
||||||
f(ref.ptr, self);
|
f(ref.ptr, self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.jointRemap = null;
|
self.jointRemap = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setSkeleton(self: *@This(), skeleton: []const u8) void {
|
pub fn setSkeleton(self: *@This(), skeleton: []const u8) void {
|
||||||
self.setSkeletonByName(core.MakeName(skeleton)) catch unreachable;
|
self.setSkeletonByName(core.MakeName(skeleton)) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addResolver(self: *@This(), comptime Resolver: type) !*Resolver {
|
pub fn addResolver(self: *@This(), comptime Resolver: type) !*Resolver {
|
||||||
const resolver = try Resolver.create(allocator);
|
const resolver = try Resolver.create(allocator);
|
||||||
try resolver.onSkeletonSet(self);
|
try resolver.onSkeletonSet(self);
|
||||||
|
|
||||||
self.resolverRef = core.refFromPtr(AnimResolverInterface, resolver);
|
self.resolverRef = core.refFromPtr(AnimResolverInterface, resolver);
|
||||||
|
|
||||||
return resolver;
|
return resolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn removeResolver(self: *@This()) void {
|
pub fn removeResolver(self: *@This()) void {
|
||||||
if (self.resolverRef) |ref| {
|
if (self.resolverRef) |ref| {
|
||||||
ref.vtable.destroy(ref.ptr);
|
ref.vtable.destroy(ref.ptr);
|
||||||
self.resolverRef = null;
|
self.resolverRef = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(self: *@This(), dt: f64) void {
|
pub fn update(self: *@This(), dt: f64) void {
|
||||||
if (self.skeleton == null) {
|
if (self.skeleton == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if a resolver is present, use that to update my the finals instead of the default function below
|
// if a resolver is present, use that to update my the finals instead of the default function below
|
||||||
if (self.resolverRef) |ref| {
|
if (self.resolverRef) |ref| {
|
||||||
ref.vtable.resolve(ref.ptr, dt, self);
|
ref.vtable.resolve(ref.ptr, dt, self);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!self.defaultSample(dt)) {
|
if (!self.defaultSample(dt)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.modelToFinal();
|
self.modelToFinal();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn defaultSample(self: *@This(), dt: f64) bool {
|
fn defaultSample(self: *@This(), dt: f64) bool {
|
||||||
if (self.track == null)
|
if (self.track == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const track = self.track.?;
|
const track = self.track.?;
|
||||||
if (track.endTime < 0.01)
|
if (track.endTime < 0.01)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const skeleton = self.skeleton.?;
|
const skeleton = self.skeleton.?;
|
||||||
self.playback += @as(f32, @floatCast(dt)) * self.playbackRate;
|
self.playback += @as(f32, @floatCast(dt)) * self.playbackRate;
|
||||||
|
|
||||||
while (self.playback > track.endTime) {
|
while (self.playback > track.endTime) {
|
||||||
self.playback -= track.endTime;
|
self.playback -= track.endTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
var samplingJob: ozz.SamplingJob = .{
|
var samplingJob: ozz.SamplingJob = .{
|
||||||
.ratio = self.playback / track.endTime,
|
.ratio = self.playback / track.endTime,
|
||||||
.animation = track.animation,
|
.animation = track.animation,
|
||||||
.context = self.sjc,
|
.context = self.sjc,
|
||||||
.output = ozz.makeSpan(self.locals.items),
|
.output = ozz.makeSpan(self.locals.items),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!samplingJob.run()) {
|
if (!samplingJob.run()) {
|
||||||
core.engine_errs("sampling job failed");
|
core.engine_errs("sampling job failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var ltmJob: ozz.LocalToModelJob = .{
|
var ltmJob: ozz.LocalToModelJob = .{
|
||||||
.skeleton = skeleton.sk,
|
.skeleton = skeleton.sk,
|
||||||
.input = ozz.makeSpan(self.locals.items),
|
.input = ozz.makeSpan(self.locals.items),
|
||||||
.output = ozz.makeSpan(self.models.items),
|
.output = ozz.makeSpan(self.models.items),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!ltmJob.run()) {
|
if (!ltmJob.run()) {
|
||||||
core.engine_errs("local to model job failed");
|
core.engine_errs("local to model job failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn commitLocalToModel(self: *@This(), input: []ozz.SoaTransform) void {
|
pub fn commitLocalToModel(self: *@This(), input: []ozz.SoaTransform) void {
|
||||||
self.localToModel(input, self.models.items);
|
self.localToModel(input, self.models.items);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn localToModel(self: *@This(), input: []ozz.SoaTransform, output: []ozz.Float4x4) void {
|
pub fn localToModel(self: *@This(), input: []ozz.SoaTransform, output: []ozz.Float4x4) void {
|
||||||
var ltmJob: ozz.LocalToModelJob = .{
|
var ltmJob: ozz.LocalToModelJob = .{
|
||||||
.skeleton = self.skeleton.?.sk,
|
.skeleton = self.skeleton.?.sk,
|
||||||
.input = ozz.makeSpan(input),
|
.input = ozz.makeSpan(input),
|
||||||
.output = ozz.makeSpan(output),
|
.output = ozz.makeSpan(output),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!ltmJob.run()) {
|
if (!ltmJob.run()) {
|
||||||
core.engine_errs("local to model job failed");
|
core.engine_errs("local to model job failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sampleAnimation(self: *@This(), time: f32, track: *AnimationTrack, output: []ozz.SoaTransform) void {
|
pub fn sampleAnimation(self: *@This(), time: f32, track: *AnimationTrack, output: []ozz.SoaTransform) void {
|
||||||
var samplingJob: ozz.SamplingJob = .{
|
var samplingJob: ozz.SamplingJob = .{
|
||||||
.ratio = time / track.endTime,
|
.ratio = time / track.endTime,
|
||||||
.animation = track.animation,
|
.animation = track.animation,
|
||||||
.context = self.sjc,
|
.context = self.sjc,
|
||||||
.output = ozz.makeSpan(output),
|
.output = ozz.makeSpan(output),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!samplingJob.run()) {
|
if (!samplingJob.run()) {
|
||||||
core.engine_errs("sampling job failed");
|
core.engine_errs("sampling job failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn modelToFinal(self: *@This()) void {
|
pub fn modelToFinal(self: *@This()) void {
|
||||||
if (self.jointRemap == null) {
|
if (self.jointRemap == null) {
|
||||||
if (self.entity.get(graphics.StaticMesh)) |meshComponent| {
|
if (self.entity.get(graphics.StaticMesh)) |meshComponent| {
|
||||||
if (meshComponent.mesh) |mesh| {
|
if (meshComponent.mesh) |mesh| {
|
||||||
self.jointRemap = mesh.jointRemap;
|
self.jointRemap = mesh.jointRemap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const skeleton = self.skeleton.?;
|
const skeleton = self.skeleton.?;
|
||||||
for (self.models.items, 0..) |model, i| {
|
for (self.models.items, 0..) |model, i| {
|
||||||
const transform: core.Mat = @bitCast(model);
|
const transform: core.Mat = @bitCast(model);
|
||||||
|
|
||||||
// const p: core.zm.Vec = .{ 0, 0, 0, 1 };
|
// const p: core.zm.Vec = .{ 0, 0, 0, 1 };
|
||||||
// graphics.debugSphere(core.Vectorf.fromZm(core.zm.mul(p, transform)), 0.03, .{
|
// graphics.debugSphere(core.Vectorf.fromZm(core.zm.mul(p, transform)), 0.03, .{
|
||||||
// .color = if (i == 15) .{ .x = 1 } else .{ .y = 1 },
|
// .color = if (i == 15) .{ .x = 1 } else .{ .y = 1 },
|
||||||
// });
|
// });
|
||||||
|
|
||||||
const final = core.zm.mul(skeleton.inverseBinds.items[i], transform);
|
const final = core.zm.mul(skeleton.inverseBinds.items[i], transform);
|
||||||
// joint remap ozz -> gltf
|
// joint remap ozz -> gltf
|
||||||
if (self.jointRemap) |jr| {
|
if (self.jointRemap) |jr| {
|
||||||
// core.engine_log("{d} xx {d}", .{ i, jr[i] });
|
// core.engine_log("{d} xx {d}", .{ i, jr[i] });
|
||||||
self.finals.items[@intCast(jr[i])] = final;
|
self.finals.items[@intCast(jr[i])] = final;
|
||||||
} else {
|
} else {
|
||||||
self.finals.items[i] = final;
|
self.finals.items[i] = final;
|
||||||
}
|
}
|
||||||
// core.engine_log(
|
// core.engine_log(
|
||||||
// "[{d}] {d} {d} {d} {d}, {d} {d} {d} {d}",
|
// "[{d}] {d} {d} {d} {d}, {d} {d} {d} {d}",
|
||||||
// .{ i, transform[0][0], transform[0][1], transform[0][2], transform[0][3], transform[1][0], transform[1][1], transform[1][2], transform[1][3] },
|
// .{ i, transform[0][0], transform[0][1], transform[0][2], transform[0][3], transform[1][0], transform[1][1], transform[1][2], transform[1][3] },
|
||||||
// );
|
// );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setAnimationByName(self: *@This(), _name: core.Name) !void {
|
pub fn setAnimationByName(self: *@This(), _name: core.Name) !void {
|
||||||
var name = _name;
|
var name = _name;
|
||||||
self.track = gAnimationSys.animTracks.get(name.handle());
|
self.track = gAnimationSys.animTracks.get(name.handle());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setAnimation(self: *@This(), path: []const u8) void {
|
pub fn setAnimation(self: *@This(), path: []const u8) void {
|
||||||
const name = core.MakeName(path);
|
const name = core.MakeName(path);
|
||||||
self.setAnimationByName(name) catch unreachable;
|
self.setAnimationByName(name) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *@This()) void {
|
pub fn deinit(self: *@This()) void {
|
||||||
self.sjc.destroy();
|
self.sjc.destroy();
|
||||||
self.removeResolver();
|
self.removeResolver();
|
||||||
self.finals.deinit(allocator);
|
self.finals.deinit(allocator);
|
||||||
self.locals.deinit(allocator);
|
self.locals.deinit(allocator);
|
||||||
self.models.deinit(allocator);
|
self.models.deinit(allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub var BaseContainer: *core.SparseMap(@This()) = undefined;
|
pub var BaseContainer: *core.SparseMap(@This()) = undefined;
|
||||||
pub const ComponentName = "Animator";
|
pub const ComponentName = "Animator";
|
||||||
pub const ScriptExports: []const []const u8 = &.{};
|
pub const ScriptExports: []const []const u8 = &.{};
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const AnimationSystem = struct {
|
pub const AnimationSystem = struct {
|
||||||
backingAllocator: std.mem.Allocator,
|
backingAllocator: std.mem.Allocator,
|
||||||
|
|
||||||
arena: std.heap.ArenaAllocator,
|
arena: std.heap.ArenaAllocator,
|
||||||
slots: MergedSpans,
|
slots: MergedSpans,
|
||||||
|
|
||||||
// Only AnimationTrack and Skeletons are made using the ArenaAllocator
|
// Only AnimationTrack and Skeletons are made using the ArenaAllocator
|
||||||
animTracks: std.AutoHashMapUnmanaged(u32, *AnimationTrack) = .{},
|
animTracks: std.AutoHashMapUnmanaged(u32, *AnimationTrack) = .{},
|
||||||
skeletons: std.AutoHashMapUnmanaged(u32, *Skeleton) = .{},
|
skeletons: std.AutoHashMapUnmanaged(u32, *Skeleton) = .{},
|
||||||
|
|
||||||
sharedArena: [2]std.heap.ArenaAllocator, // could be a good usecase for a fat bump arena
|
sharedArena: [2]std.heap.ArenaAllocator, // could be a good usecase for a fat bump arena
|
||||||
shared: [2]std.ArrayListUnmanaged(MatrixUploads) = .{ .{}, .{} },
|
shared: [2]std.ArrayListUnmanaged(MatrixUploads) = .{ .{}, .{} },
|
||||||
sharedLocks: [2]std.Thread.Mutex = .{ .{}, .{} }, // could be a good usecase for a fat bump arena
|
sharedLocks: [2]std.Thread.Mutex = .{ .{}, .{} }, // could be a good usecase for a fat bump arena
|
||||||
|
|
||||||
pub const MatrixUploads = struct {
|
pub const MatrixUploads = struct {
|
||||||
offset: u32,
|
offset: u32,
|
||||||
matrices: std.ArrayListUnmanaged(core.Mat) = .{},
|
matrices: std.ArrayListUnmanaged(core.Mat) = .{},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This());
|
pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This());
|
||||||
pub const RendererInterfaceVTable = graphics.RendererInterface.from(@This());
|
pub const RendererInterfaceVTable = graphics.RendererInterface.from(@This());
|
||||||
|
|
||||||
pub fn preTick(self: *@This(), dt: f64) !void {
|
pub fn preTick(self: *@This(), dt: f64) !void {
|
||||||
_ = self;
|
_ = self;
|
||||||
var z1 = core.tracy.ZoneN(@src(), "animation system tick");
|
var z1 = core.tracy.ZoneN(@src(), "animation system tick");
|
||||||
defer z1.End();
|
defer z1.End();
|
||||||
|
|
||||||
for (Animator.BaseContainer.list.items) |animator| {
|
for (Animator.BaseContainer.list.items) |animator| {
|
||||||
animator.update(dt);
|
animator.update(dt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn newAnimTrack(self: *@This(), _name: core.Name, anim: *ozz.Animation) !void {
|
pub fn newAnimTrack(self: *@This(), _name: core.Name, anim: *ozz.Animation) !void {
|
||||||
var name = _name;
|
var name = _name;
|
||||||
const new = try self.arenaAllocator().create(AnimationTrack);
|
const new = try self.arenaAllocator().create(AnimationTrack);
|
||||||
new.* = .{
|
new.* = .{
|
||||||
.animation = anim,
|
.animation = anim,
|
||||||
.endTime = anim.getDuration(),
|
.endTime = anim.getDuration(),
|
||||||
};
|
};
|
||||||
try self.animTracks.put(self.backingAllocator, name.handle(), new);
|
try self.animTracks.put(self.backingAllocator, name.handle(), new);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn newSkeleton(self: *@This(), _name: core.Name, sk: *ozz.Skeleton) !void {
|
pub fn newSkeleton(self: *@This(), _name: core.Name, sk: *ozz.Skeleton) !void {
|
||||||
const new = try self.arenaAllocator().create(Skeleton);
|
const new = try self.arenaAllocator().create(Skeleton);
|
||||||
new.* = .{
|
new.* = .{
|
||||||
.sk = sk,
|
.sk = sk,
|
||||||
};
|
};
|
||||||
var name = _name;
|
var name = _name;
|
||||||
|
|
||||||
try new.buildJointMap(self.arenaAllocator());
|
try new.buildJointMap(self.arenaAllocator());
|
||||||
|
|
||||||
try new.inverseBinds.resize(self.arenaAllocator(), new.sk.numJoints());
|
try new.inverseBinds.resize(self.arenaAllocator(), new.sk.numJoints());
|
||||||
|
|
||||||
if (new.inverseBinds.items.len > 256) {
|
if (new.inverseBinds.items.len > 256) {
|
||||||
@panic("too many bones in skeleton, not supported");
|
@panic("too many bones in skeleton, not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
var bindModels = std.ArrayList(ozz.Float4x4).init(self.backingAllocator);
|
var bindModels = std.ArrayList(ozz.Float4x4).init(self.backingAllocator);
|
||||||
defer bindModels.deinit();
|
defer bindModels.deinit();
|
||||||
|
|
||||||
try bindModels.resize(new.sk.numJoints());
|
try bindModels.resize(new.sk.numJoints());
|
||||||
|
|
||||||
var ltmJob: ozz.LocalToModelJob = .{
|
var ltmJob: ozz.LocalToModelJob = .{
|
||||||
.skeleton = new.sk,
|
.skeleton = new.sk,
|
||||||
.input = new.sk.getRestPoseModel(),
|
.input = new.sk.getRestPoseModel(),
|
||||||
.output = ozz.makeSpan(bindModels.items),
|
.output = ozz.makeSpan(bindModels.items),
|
||||||
};
|
};
|
||||||
|
|
||||||
core.engine_log("creating bind pose {d} joints", .{new.inverseBinds.items.len});
|
core.engine_log("creating bind pose {d} joints", .{new.inverseBinds.items.len});
|
||||||
|
|
||||||
if (!ltmJob.run()) {
|
if (!ltmJob.run()) {
|
||||||
core.engine_logs("unable to get bind pose");
|
core.engine_logs("unable to get bind pose");
|
||||||
return error.UnableToLoad;
|
return error.UnableToLoad;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (bindModels.items, 0..) |bind, i| {
|
for (bindModels.items, 0..) |bind, i| {
|
||||||
// const p: core.zm.Vec = .{ 0, 0, 0, 1 };
|
// const p: core.zm.Vec = .{ 0, 0, 0, 1 };
|
||||||
// graphics.debugSphere(core.Vectorf.fromZm(core.zm.mul(p, @as(core.Mat, @bitCast(bind)))), 0.1, .{ .duration = 100 });
|
// graphics.debugSphere(core.Vectorf.fromZm(core.zm.mul(p, @as(core.Mat, @bitCast(bind)))), 0.1, .{ .duration = 100 });
|
||||||
|
|
||||||
new.inverseBinds.items[i] = core.zm.inverse(@as(core.Mat, @bitCast(bind)));
|
new.inverseBinds.items[i] = core.zm.inverse(@as(core.Mat, @bitCast(bind)));
|
||||||
}
|
}
|
||||||
|
|
||||||
try self.skeletons.put(self.backingAllocator, name.handle(), new);
|
try self.skeletons.put(self.backingAllocator, name.handle(), new);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn arenaAllocator(self: *@This()) std.mem.Allocator {
|
pub fn arenaAllocator(self: *@This()) std.mem.Allocator {
|
||||||
return self.arena.allocator();
|
return self.arena.allocator();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getShared(self: @This(), fi: u32) []const MatrixUploads {
|
pub fn getShared(self: @This(), fi: u32) []const MatrixUploads {
|
||||||
return self.shared[fi].items;
|
return self.shared[fi].items;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sendShared(self: *@This(), frameIndex: u32) void {
|
pub fn sendShared(self: *@This(), frameIndex: u32) void {
|
||||||
const fi: usize = @intCast(frameIndex);
|
const fi: usize = @intCast(frameIndex);
|
||||||
|
|
||||||
self.sharedLocks[fi].lock();
|
self.sharedLocks[fi].lock();
|
||||||
defer self.sharedLocks[fi].unlock();
|
defer self.sharedLocks[fi].unlock();
|
||||||
|
|
||||||
_ = self.sharedArena[fi].reset(.retain_capacity);
|
_ = self.sharedArena[fi].reset(.retain_capacity);
|
||||||
|
|
||||||
const allocator = self.sharedArena[fi].allocator();
|
const allocator = self.sharedArena[fi].allocator();
|
||||||
const shared = &self.shared[fi];
|
const shared = &self.shared[fi];
|
||||||
shared.* = .{};
|
shared.* = .{};
|
||||||
|
|
||||||
for (Animator.BaseContainer.list.items) |animator| {
|
for (Animator.BaseContainer.list.items) |animator| {
|
||||||
var upload: MatrixUploads = .{ .offset = animator.finalsSpan.start };
|
var upload: MatrixUploads = .{ .offset = animator.finalsSpan.start };
|
||||||
// core.engine_log(
|
// core.engine_log(
|
||||||
// "finalsSpan size offset{d} {d} animator finals {d}\n",
|
// "finalsSpan size offset{d} {d} animator finals {d}\n",
|
||||||
// .{
|
// .{
|
||||||
// animator.finalsSpan.start,
|
// animator.finalsSpan.start,
|
||||||
// animator.finalsSpan.size,
|
// animator.finalsSpan.size,
|
||||||
// animator.finals.items.len
|
// animator.finals.items.len
|
||||||
// });
|
// });
|
||||||
|
|
||||||
upload.matrices.resize(allocator, animator.finalsSpan.size) catch unreachable;
|
upload.matrices.resize(allocator, animator.finalsSpan.size) catch unreachable;
|
||||||
|
|
||||||
for (animator.finals.items, 0..) |final, i| {
|
for (animator.finals.items, 0..) |final, i| {
|
||||||
upload.matrices.items[i] = final;
|
upload.matrices.items[i] = final;
|
||||||
}
|
}
|
||||||
|
|
||||||
shared.append(allocator, upload) catch unreachable;
|
shared.append(allocator, upload) catch unreachable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(alloc: std.mem.Allocator) !*@This() {
|
pub fn init(alloc: std.mem.Allocator) !*@This() {
|
||||||
const self = try alloc.create(@This());
|
const self = try alloc.create(@This());
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.backingAllocator = alloc,
|
.backingAllocator = alloc,
|
||||||
.arena = std.heap.ArenaAllocator.init(alloc),
|
.arena = std.heap.ArenaAllocator.init(alloc),
|
||||||
.sharedArena = .{
|
.sharedArena = .{
|
||||||
std.heap.ArenaAllocator.init(alloc),
|
std.heap.ArenaAllocator.init(alloc),
|
||||||
std.heap.ArenaAllocator.init(alloc),
|
std.heap.ArenaAllocator.init(alloc),
|
||||||
},
|
},
|
||||||
.slots = try MergedSpans.init(alloc, vk_constants.MAX_SKIN_SLOTS),
|
.slots = try MergedSpans.init(alloc, vk_constants.MAX_SKIN_SLOTS),
|
||||||
};
|
};
|
||||||
|
|
||||||
gAnimationSys = self;
|
gAnimationSys = self;
|
||||||
Animator.allocator = alloc;
|
Animator.allocator = alloc;
|
||||||
|
|
||||||
try core.defineComponent(Animator, alloc);
|
try core.defineComponent(Animator, alloc);
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *@This()) void {
|
pub fn deinit(self: *@This()) void {
|
||||||
core.engine_logs("deinitializing animation system");
|
core.engine_logs("deinitializing animation system");
|
||||||
{
|
{
|
||||||
core.engine_log("skeleton count {d}", .{self.skeletons.count()});
|
core.engine_log("skeleton count {d}", .{self.skeletons.count()});
|
||||||
var iter = self.skeletons.iterator();
|
var iter = self.skeletons.iterator();
|
||||||
while (iter.next()) |i| {
|
while (iter.next()) |i| {
|
||||||
i.value_ptr.*.deinit();
|
i.value_ptr.*.deinit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
core.engine_log("animTracks count {d}", .{self.animTracks.count()});
|
core.engine_log("animTracks count {d}", .{self.animTracks.count()});
|
||||||
var iter = self.animTracks.iterator();
|
var iter = self.animTracks.iterator();
|
||||||
while (iter.next()) |i| {
|
while (iter.next()) |i| {
|
||||||
i.value_ptr.*.deinit();
|
i.value_ptr.*.deinit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (self.sharedArena) |arena| {
|
for (self.sharedArena) |arena| {
|
||||||
arena.deinit();
|
arena.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Animator.BaseContainer.list.items) |animator| {
|
for (Animator.BaseContainer.list.items) |animator| {
|
||||||
animator.deinit();
|
animator.deinit();
|
||||||
}
|
}
|
||||||
self.slots.deinit();
|
self.slots.deinit();
|
||||||
core.undefineComponent(Animator);
|
core.undefineComponent(Animator);
|
||||||
self.arena.deinit();
|
self.arena.deinit();
|
||||||
self.skeletons.deinit(self.backingAllocator);
|
self.skeletons.deinit(self.backingAllocator);
|
||||||
self.animTracks.deinit(self.backingAllocator);
|
self.animTracks.deinit(self.backingAllocator);
|
||||||
self.backingAllocator.destroy(self);
|
self.backingAllocator.destroy(self);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub var gAnimationSys: *AnimationSystem = undefined;
|
pub var gAnimationSys: *AnimationSystem = undefined;
|
||||||
|
|
||||||
pub fn getSkeletonByName(_name: core.Name) ?*Skeleton {
|
pub fn getSkeletonByName(_name: core.Name) ?*Skeleton {
|
||||||
var name = _name;
|
var name = _name;
|
||||||
return gAnimationSys.skeletons.get(name.handle());
|
return gAnimationSys.skeletons.get(name.handle());
|
||||||
}
|
}
|
||||||
|
|
||||||
const graphics = @import("../graphics.zig");
|
const graphics = @import("../graphics.zig");
|
||||||
const MergedSpans = core.MergedSpans;
|
const MergedSpans = core.MergedSpans;
|
||||||
const vk_constants = @import("../vk_constants.zig");
|
const vk_constants = @import("../vk_constants.zig");
|
||||||
|
|
||||||
const anim_resolver = @import("animResolver.zig");
|
const anim_resolver = @import("animResolver.zig");
|
||||||
const AnimResolverRef = anim_resolver.AnimResolverRef;
|
const AnimResolverRef = anim_resolver.AnimResolverRef;
|
||||||
const AnimResolverInterface = anim_resolver.AnimResolverInterface;
|
const AnimResolverInterface = anim_resolver.AnimResolverInterface;
|
||||||
|
|
@ -1,86 +1,86 @@
|
||||||
pub const AnimationLoader = struct {
|
pub const AnimationLoader = struct {
|
||||||
pub var LoaderInterfaceVTable: assets.AssetLoaderInterface = assets.AssetLoaderInterface.from("Animation", @This());
|
pub var LoaderInterfaceVTable: assets.AssetLoaderInterface = assets.AssetLoaderInterface.from("Animation", @This());
|
||||||
pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This());
|
pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This());
|
||||||
|
|
||||||
sys: *animation_system.AnimationSystem,
|
sys: *animation_system.AnimationSystem,
|
||||||
|
|
||||||
pub fn discardAll(self: *@This()) void {
|
pub fn discardAll(self: *@This()) void {
|
||||||
_ = self;
|
_ = self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn loadAsset(self: *@This(), assetRef: assets.AssetRef, propertiesBag: ?assets.AssetPropertiesBag) assets.AssetLoaderError!void {
|
pub fn loadAsset(self: *@This(), assetRef: assets.AssetRef, propertiesBag: ?assets.AssetPropertiesBag) assets.AssetLoaderError!void {
|
||||||
const animation = ozz.Animation.create();
|
const animation = ozz.Animation.create();
|
||||||
|
|
||||||
const mapping = core.fs().loadFile(propertiesBag.?.path) catch return error.UnableToLoad;
|
const mapping = core.fs().loadFile(propertiesBag.?.path) catch return error.UnableToLoad;
|
||||||
defer core.fs().unmap(mapping);
|
defer core.fs().unmap(mapping);
|
||||||
animation.loadFromBytes(mapping.bytes);
|
animation.loadFromBytes(mapping.bytes);
|
||||||
|
|
||||||
self.sys.newAnimTrack(assetRef.name, animation) catch return error.UnableToLoad;
|
self.sys.newAnimTrack(assetRef.name, animation) catch return error.UnableToLoad;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator) !*@This() {
|
pub fn init(allocator: std.mem.Allocator) !*@This() {
|
||||||
const self = try allocator.create(@This());
|
const self = try allocator.create(@This());
|
||||||
|
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.sys = animation_system.gAnimationSys,
|
.sys = animation_system.gAnimationSys,
|
||||||
};
|
};
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy(self: *@This(), allocator: std.mem.Allocator) void {
|
pub fn destroy(self: *@This(), allocator: std.mem.Allocator) void {
|
||||||
allocator.destroy(self);
|
allocator.destroy(self);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const SkeletonLoader = struct {
|
pub const SkeletonLoader = struct {
|
||||||
pub var LoaderInterfaceVTable: assets.AssetLoaderInterface = assets.AssetLoaderInterface.from("Skeleton", @This());
|
pub var LoaderInterfaceVTable: assets.AssetLoaderInterface = assets.AssetLoaderInterface.from("Skeleton", @This());
|
||||||
pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This());
|
pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This());
|
||||||
|
|
||||||
sys: *animation_system.AnimationSystem,
|
sys: *animation_system.AnimationSystem,
|
||||||
|
|
||||||
pub fn discardAll(self: *@This()) void {
|
pub fn discardAll(self: *@This()) void {
|
||||||
_ = self;
|
_ = self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn loadAsset(self: *@This(), assetRef: assets.AssetRef, propertiesBag: ?assets.AssetPropertiesBag) assets.AssetLoaderError!void {
|
pub fn loadAsset(self: *@This(), assetRef: assets.AssetRef, propertiesBag: ?assets.AssetPropertiesBag) assets.AssetLoaderError!void {
|
||||||
const sk = ozz.Skeleton.create();
|
const sk = ozz.Skeleton.create();
|
||||||
|
|
||||||
const mapping = core.fs().loadFile(propertiesBag.?.path) catch return error.UnableToLoad;
|
const mapping = core.fs().loadFile(propertiesBag.?.path) catch return error.UnableToLoad;
|
||||||
defer core.fs().unmap(mapping);
|
defer core.fs().unmap(mapping);
|
||||||
sk.loadFromBytes(mapping.bytes);
|
sk.loadFromBytes(mapping.bytes);
|
||||||
|
|
||||||
self.sys.newSkeleton(assetRef.name, sk) catch return error.UnableToLoad;
|
self.sys.newSkeleton(assetRef.name, sk) catch return error.UnableToLoad;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator) !*@This() {
|
pub fn init(allocator: std.mem.Allocator) !*@This() {
|
||||||
const self = try allocator.create(@This());
|
const self = try allocator.create(@This());
|
||||||
|
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.sys = animation_system.gAnimationSys,
|
.sys = animation_system.gAnimationSys,
|
||||||
};
|
};
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy(self: *@This(), allocator: std.mem.Allocator) void {
|
pub fn destroy(self: *@This(), allocator: std.mem.Allocator) void {
|
||||||
allocator.destroy(self);
|
allocator.destroy(self);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub var gSkeletonLoader: *SkeletonLoader = undefined;
|
pub var gSkeletonLoader: *SkeletonLoader = undefined;
|
||||||
pub var gAnimationLoader: *AnimationLoader = undefined;
|
pub var gAnimationLoader: *AnimationLoader = undefined;
|
||||||
|
|
||||||
pub fn initLoaders() !void {
|
pub fn initLoaders() !void {
|
||||||
gSkeletonLoader = try core.createObject(SkeletonLoader, .{});
|
gSkeletonLoader = try core.createObject(SkeletonLoader, .{});
|
||||||
gAnimationLoader = try core.createObject(AnimationLoader, .{});
|
gAnimationLoader = try core.createObject(AnimationLoader, .{});
|
||||||
|
|
||||||
try assets.gAssetSys.registerLoader(gSkeletonLoader);
|
try assets.gAssetSys.registerLoader(gSkeletonLoader);
|
||||||
try assets.gAssetSys.registerLoader(gAnimationLoader);
|
try assets.gAssetSys.registerLoader(gAnimationLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
const animation_system = @import("animationSystem.zig");
|
const animation_system = @import("animationSystem.zig");
|
||||||
const assets = @import("assets");
|
const assets = @import("assets");
|
||||||
const core = @import("core");
|
const core = @import("core");
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const ozz = @import("ozz");
|
const ozz = @import("ozz");
|
||||||
|
|
@ -1,239 +1,239 @@
|
||||||
const MeshConfig = struct {
|
const MeshConfig = struct {
|
||||||
info: CookInfo = .{ .assetType = "Mesh" }, // there must always be a CookInfo field
|
info: CookInfo = .{ .assetType = "Mesh" }, // there must always be a CookInfo field
|
||||||
sourceType: []const u8 = "obj",
|
sourceType: []const u8 = "obj",
|
||||||
animated: bool = false,
|
animated: bool = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const extList = [_][]const u8{ "gltf", "obj", "glb" };
|
const extList = [_][]const u8{ "gltf", "obj", "glb" };
|
||||||
pub fn generateFunction(allocator: std.mem.Allocator, path: []const u8, out: *std.ArrayList(u8)) GenerateError!void {
|
pub fn generateFunction(allocator: std.mem.Allocator, path: []const u8, out: *std.ArrayList(u8)) GenerateError!void {
|
||||||
_ = allocator;
|
_ = allocator;
|
||||||
out.clearRetainingCapacity();
|
out.clearRetainingCapacity();
|
||||||
const ext = core.getFileExtension(path)[1..];
|
const ext = core.getFileExtension(path)[1..];
|
||||||
|
|
||||||
var config: MeshConfig = .{};
|
var config: MeshConfig = .{};
|
||||||
|
|
||||||
for (extList) |e| {
|
for (extList) |e| {
|
||||||
if (std.mem.eql(u8, e, ext)) {
|
if (std.mem.eql(u8, e, ext)) {
|
||||||
config.sourceType = e;
|
config.sourceType = e;
|
||||||
|
|
||||||
if (std.mem.eql(u8, e, "glb")) {
|
if (std.mem.eql(u8, e, "glb")) {
|
||||||
config.sourceType = "gltf";
|
config.sourceType = "gltf";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std.json.stringify(
|
std.json.stringify(
|
||||||
config,
|
config,
|
||||||
.{ .whitespace = .indent_4 },
|
.{ .whitespace = .indent_4 },
|
||||||
out.writer(),
|
out.writer(),
|
||||||
) catch return GenerateError.UnableToGenerate;
|
) catch return GenerateError.UnableToGenerate;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cookObj(allocator: std.mem.Allocator, dir: std.fs.Dir, path: []const u8) cook.CookResult {
|
fn cookObj(allocator: std.mem.Allocator, dir: std.fs.Dir, path: []const u8) cook.CookResult {
|
||||||
const rawFileBytes = cook.loadFileAlloc(allocator, dir, path) catch unreachable;
|
const rawFileBytes = cook.loadFileAlloc(allocator, dir, path) catch unreachable;
|
||||||
defer allocator.free(rawFileBytes);
|
defer allocator.free(rawFileBytes);
|
||||||
|
|
||||||
var out = std.ArrayList(u8).init(allocator);
|
var out = std.ArrayList(u8).init(allocator);
|
||||||
|
|
||||||
var vertices = std.ArrayList(Vertex).init(allocator);
|
var vertices = std.ArrayList(Vertex).init(allocator);
|
||||||
defer vertices.deinit();
|
defer vertices.deinit();
|
||||||
|
|
||||||
var objs = obj.loadObjBytes(rawFileBytes, allocator) catch unreachable;
|
var objs = obj.loadObjBytes(rawFileBytes, allocator) catch unreachable;
|
||||||
defer objs.deinit();
|
defer objs.deinit();
|
||||||
|
|
||||||
if (objs.meshes.items.len > 0) {
|
if (objs.meshes.items.len > 0) {
|
||||||
mesh.loadObjMeshVertices(&vertices, objs.meshes.items[0]) catch unreachable;
|
mesh.loadObjMeshVertices(&vertices, objs.meshes.items[0]) catch unreachable;
|
||||||
for (vertices.items) |vert| {
|
for (vertices.items) |vert| {
|
||||||
out.appendSlice(&@as([@sizeOf(Vertex)]u8, @bitCast(vert))) catch unreachable;
|
out.appendSlice(&@as([@sizeOf(Vertex)]u8, @bitCast(vert))) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.bytes = out,
|
.bytes = out,
|
||||||
.result = .Success,
|
.result = .Success,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return .{
|
return .{
|
||||||
.bytes = out,
|
.bytes = out,
|
||||||
.result = .Failure,
|
.result = .Failure,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ensureGltf2ozz(allocator: std.mem.Allocator) !void {
|
fn ensureGltf2ozz(allocator: std.mem.Allocator) !void {
|
||||||
const suffix = if (builtin.os.tag == .windows) ".exe" else "";
|
const suffix = if (builtin.os.tag == .windows) ".exe" else "";
|
||||||
std.fs.cwd().access("zig-out/tools/gltf2ozz" ++ suffix, .{}) catch {
|
std.fs.cwd().access("zig-out/tools/gltf2ozz" ++ suffix, .{}) catch {
|
||||||
const argv: []const []const u8 = &.{ "zig", "build", "tools" };
|
const argv: []const []const u8 = &.{ "zig", "build", "tools" };
|
||||||
|
|
||||||
core.engine_log("gltf2ozz missing, building it...", .{});
|
core.engine_log("gltf2ozz missing, building it...", .{});
|
||||||
|
|
||||||
var child = std.process.Child.init(argv, allocator);
|
var child = std.process.Child.init(argv, allocator);
|
||||||
child.stdin_behavior = .Ignore;
|
child.stdin_behavior = .Ignore;
|
||||||
child.stdout_behavior = .Pipe;
|
child.stdout_behavior = .Pipe;
|
||||||
child.stderr_behavior = .Pipe;
|
child.stderr_behavior = .Pipe;
|
||||||
child.cwd = ".";
|
child.cwd = ".";
|
||||||
|
|
||||||
switch (try child.spawnAndWait()) {
|
switch (try child.spawnAndWait()) {
|
||||||
.Exited => |value| {
|
.Exited => |value| {
|
||||||
if (value == 0) {
|
if (value == 0) {
|
||||||
core.engine_log("gltf2ozz built", .{});
|
core.engine_log("gltf2ozz built", .{});
|
||||||
} else {
|
} else {
|
||||||
core.engine_logs("unable to build gltf2ozz");
|
core.engine_logs("unable to build gltf2ozz");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.Signal => {
|
.Signal => {
|
||||||
core.engine_logs("unable to build gltf2ozz");
|
core.engine_logs("unable to build gltf2ozz");
|
||||||
},
|
},
|
||||||
.Stopped => {},
|
.Stopped => {},
|
||||||
.Unknown => {
|
.Unknown => {
|
||||||
unreachable;
|
unreachable;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
core.engine_log("gltf2ozz found", .{});
|
core.engine_log("gltf2ozz found", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cookAnimations(allocator: std.mem.Allocator, dir: std.fs.Dir, path: []const u8, config: MeshConfig) !void {
|
fn cookAnimations(allocator: std.mem.Allocator, dir: std.fs.Dir, path: []const u8, config: MeshConfig) !void {
|
||||||
_ = config;
|
_ = config;
|
||||||
|
|
||||||
// 1. check if it has an associated .ozzconfig file.
|
// 1. check if it has an associated .ozzconfig file.
|
||||||
|
|
||||||
const gltf2OzzAbs = try std.fs.cwd().realpathAlloc(allocator, "zig-out/tools/gltf2ozz.exe");
|
const gltf2OzzAbs = try std.fs.cwd().realpathAlloc(allocator, "zig-out/tools/gltf2ozz.exe");
|
||||||
defer allocator.free(gltf2OzzAbs);
|
defer allocator.free(gltf2OzzAbs);
|
||||||
|
|
||||||
const ozzconfig = try std.fmt.allocPrint(allocator, "{s}.ozzconfig", .{path});
|
const ozzconfig = try std.fmt.allocPrint(allocator, "{s}.ozzconfig", .{path});
|
||||||
defer allocator.free(ozzconfig);
|
defer allocator.free(ozzconfig);
|
||||||
|
|
||||||
const fileArg = try std.fmt.allocPrint(allocator, "--file={s}", .{core.getBasePath(path)});
|
const fileArg = try std.fmt.allocPrint(allocator, "--file={s}", .{core.getBasePath(path)});
|
||||||
defer allocator.free(fileArg);
|
defer allocator.free(fileArg);
|
||||||
|
|
||||||
const configArg = try std.fmt.allocPrint(allocator, "--config_file={s}", .{core.getBasePath(ozzconfig)});
|
const configArg = try std.fmt.allocPrint(allocator, "--config_file={s}", .{core.getBasePath(ozzconfig)});
|
||||||
defer allocator.free(configArg);
|
defer allocator.free(configArg);
|
||||||
|
|
||||||
// todo, fix this later, idrc right now.
|
// todo, fix this later, idrc right now.
|
||||||
const newConfigArg = try std.fmt.allocPrint(allocator, "--config_dump_reference={s}", .{core.getBasePath(ozzconfig)});
|
const newConfigArg = try std.fmt.allocPrint(allocator, "--config_dump_reference={s}", .{core.getBasePath(ozzconfig)});
|
||||||
defer allocator.free(newConfigArg);
|
defer allocator.free(newConfigArg);
|
||||||
|
|
||||||
const absFile = try dir.realpathAlloc(allocator, path);
|
const absFile = try dir.realpathAlloc(allocator, path);
|
||||||
defer allocator.free(absFile);
|
defer allocator.free(absFile);
|
||||||
|
|
||||||
var argv: []const []const u8 = &.{
|
var argv: []const []const u8 = &.{
|
||||||
gltf2OzzAbs,
|
gltf2OzzAbs,
|
||||||
fileArg,
|
fileArg,
|
||||||
configArg,
|
configArg,
|
||||||
};
|
};
|
||||||
|
|
||||||
dir.access(ozzconfig, .{}) catch {
|
dir.access(ozzconfig, .{}) catch {
|
||||||
argv = &.{
|
argv = &.{
|
||||||
gltf2OzzAbs,
|
gltf2OzzAbs,
|
||||||
fileArg,
|
fileArg,
|
||||||
newConfigArg,
|
newConfigArg,
|
||||||
};
|
};
|
||||||
|
|
||||||
core.engine_log("creating ozz config for file, marked as animated but no animation data", .{});
|
core.engine_log("creating ozz config for file, marked as animated but no animation data", .{});
|
||||||
};
|
};
|
||||||
|
|
||||||
// std.debug.print("{s} {s} {s} cwd = {s}\n", .{ argv[0], argv[1], argv[2], core.getFolder(absFile) });
|
// std.debug.print("{s} {s} {s} cwd = {s}\n", .{ argv[0], argv[1], argv[2], core.getFolder(absFile) });
|
||||||
|
|
||||||
const result = try std.process.Child.run(.{
|
const result = try std.process.Child.run(.{
|
||||||
.argv = argv,
|
.argv = argv,
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.cwd = core.getFolder(absFile),
|
.cwd = core.getFolder(absFile),
|
||||||
.max_output_bytes = 150 * 1024 * 1024,
|
.max_output_bytes = 150 * 1024 * 1024,
|
||||||
});
|
});
|
||||||
|
|
||||||
defer allocator.free(result.stdout);
|
defer allocator.free(result.stdout);
|
||||||
defer allocator.free(result.stderr);
|
defer allocator.free(result.stderr);
|
||||||
|
|
||||||
var success: bool = true;
|
var success: bool = true;
|
||||||
switch (result.term) {
|
switch (result.term) {
|
||||||
.Exited => |value| {
|
.Exited => |value| {
|
||||||
if (value != 0) {
|
if (value != 0) {
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.Signal => {
|
.Signal => {
|
||||||
success = false;
|
success = false;
|
||||||
},
|
},
|
||||||
.Stopped => {
|
.Stopped => {
|
||||||
success = false;
|
success = false;
|
||||||
// no-op should be ok?
|
// no-op should be ok?
|
||||||
},
|
},
|
||||||
.Unknown => {
|
.Unknown => {
|
||||||
unreachable;
|
unreachable;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
core.engine_log("generated animations for {s}", .{path});
|
core.engine_log("generated animations for {s}", .{path});
|
||||||
} else {
|
} else {
|
||||||
core.engine_log("error generating animations {s} stdout:\n{s}\n stderr:{s}\n", .{ path, result.stdout, result.stderr });
|
core.engine_log("error generating animations {s} stdout:\n{s}\n stderr:{s}\n", .{ path, result.stdout, result.stderr });
|
||||||
}
|
}
|
||||||
// 2. if so, run it through gltf2ozz with that file.
|
// 2. if so, run it through gltf2ozz with that file.
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cookGltf(allocator: std.mem.Allocator, dir: std.fs.Dir, path: []const u8, config: MeshConfig) cook.CookResult {
|
fn cookGltf(allocator: std.mem.Allocator, dir: std.fs.Dir, path: []const u8, config: MeshConfig) cook.CookResult {
|
||||||
core.engine_logs("gltf cooking not implemeted");
|
core.engine_logs("gltf cooking not implemeted");
|
||||||
const out = std.ArrayList(u8).init(allocator);
|
const out = std.ArrayList(u8).init(allocator);
|
||||||
|
|
||||||
// check if it's animated. if it's animated, then invoke gltf2ozz and create a .ozzconfig file and
|
// check if it's animated. if it's animated, then invoke gltf2ozz and create a .ozzconfig file and
|
||||||
// make a subfolder called
|
// make a subfolder called
|
||||||
|
|
||||||
if (config.animated) {
|
if (config.animated) {
|
||||||
// if gltf2ozz isn't there then we have to call zig build tools
|
// if gltf2ozz isn't there then we have to call zig build tools
|
||||||
ensureGltf2ozz(allocator) catch unreachable;
|
ensureGltf2ozz(allocator) catch unreachable;
|
||||||
|
|
||||||
cookAnimations(allocator, dir, path, config) catch unreachable;
|
cookAnimations(allocator, dir, path, config) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
return .{ .bytes = out, .result = .Failure };
|
return .{ .bytes = out, .result = .Failure };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cookFunction(
|
pub fn cookFunction(
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
dir: std.fs.Dir,
|
dir: std.fs.Dir,
|
||||||
path: []const u8,
|
path: []const u8,
|
||||||
params: cook.CookParams,
|
params: cook.CookParams,
|
||||||
) cook.CookResult {
|
) cook.CookResult {
|
||||||
core.engine_log("{s}", .{params.cookFileName});
|
core.engine_log("{s}", .{params.cookFileName});
|
||||||
const fc = cook.loadFileAlloc(allocator, dir, params.cookFileName) catch unreachable;
|
const fc = cook.loadFileAlloc(allocator, dir, params.cookFileName) catch unreachable;
|
||||||
defer allocator.free(fc);
|
defer allocator.free(fc);
|
||||||
|
|
||||||
const config = std.json.parseFromSlice(MeshConfig, allocator, fc[0 .. fc.len - 1], .{}) catch unreachable;
|
const config = std.json.parseFromSlice(MeshConfig, allocator, fc[0 .. fc.len - 1], .{}) catch unreachable;
|
||||||
defer config.deinit();
|
defer config.deinit();
|
||||||
|
|
||||||
if (std.mem.eql(u8, config.value.sourceType, "obj")) {
|
if (std.mem.eql(u8, config.value.sourceType, "obj")) {
|
||||||
return cookObj(allocator, dir, path);
|
return cookObj(allocator, dir, path);
|
||||||
} else {
|
} else {
|
||||||
return cookGltf(allocator, dir, path, config.value);
|
return cookGltf(allocator, dir, path, config.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initCooker(allocator: std.mem.Allocator) !void {
|
pub fn initCooker(allocator: std.mem.Allocator) !void {
|
||||||
_ = allocator;
|
_ = allocator;
|
||||||
const registry = assets.cook.getRegistry();
|
const registry = assets.cook.getRegistry();
|
||||||
|
|
||||||
try registry.install("Mesh", generateFunction, cookFunction, &.{
|
try registry.install("Mesh", generateFunction, cookFunction, &.{
|
||||||
".obj",
|
".obj",
|
||||||
".gltf",
|
".gltf",
|
||||||
".glb",
|
".glb",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinitCooker() void {
|
pub fn deinitCooker() void {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const assets = @import("assets");
|
const assets = @import("assets");
|
||||||
const cook = assets.cook;
|
const cook = assets.cook;
|
||||||
const CookInfo = assets.cook.CookInfo;
|
const CookInfo = assets.cook.CookInfo;
|
||||||
const GenerateError = assets.cook.GenerateError;
|
const GenerateError = assets.cook.GenerateError;
|
||||||
const core = @import("core");
|
const core = @import("core");
|
||||||
const obj = @import("objLoader");
|
const obj = @import("objLoader");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const mesh = @import("../mesh.zig");
|
const mesh = @import("../mesh.zig");
|
||||||
const Mesh = mesh.Mesh;
|
const Mesh = mesh.Mesh;
|
||||||
const Vertex = mesh.MeshVertex;
|
const Vertex = mesh.MeshVertex;
|
||||||
|
|
@ -1,60 +1,60 @@
|
||||||
const TextureConfig = struct {
|
const TextureConfig = struct {
|
||||||
info: CookInfo = .{ .assetType = "Texture" }, // there must always be a CookInfo field
|
info: CookInfo = .{ .assetType = "Texture" }, // there must always be a CookInfo field
|
||||||
sourceType: []const u8 = "png",
|
sourceType: []const u8 = "png",
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn generateFunction(allocator: std.mem.Allocator, path: []const u8, out: *std.ArrayList(u8)) GenerateError!void {
|
pub fn generateFunction(allocator: std.mem.Allocator, path: []const u8, out: *std.ArrayList(u8)) GenerateError!void {
|
||||||
_ = allocator;
|
_ = allocator;
|
||||||
_ = path;
|
_ = path;
|
||||||
|
|
||||||
out.clearRetainingCapacity();
|
out.clearRetainingCapacity();
|
||||||
std.json.stringify(
|
std.json.stringify(
|
||||||
TextureConfig{},
|
TextureConfig{},
|
||||||
.{ .whitespace = .indent_4 },
|
.{ .whitespace = .indent_4 },
|
||||||
out.writer(),
|
out.writer(),
|
||||||
) catch return GenerateError.UnableToGenerate;
|
) catch return GenerateError.UnableToGenerate;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cookFunction(
|
pub fn cookFunction(
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
dir: std.fs.Dir,
|
dir: std.fs.Dir,
|
||||||
path: []const u8,
|
path: []const u8,
|
||||||
params: cook.CookParams,
|
params: cook.CookParams,
|
||||||
) cook.CookResult {
|
) cook.CookResult {
|
||||||
_ = params;
|
_ = params;
|
||||||
|
|
||||||
const rawFileBytes = cook.loadFileAlloc(allocator, dir, path) catch unreachable;
|
const rawFileBytes = cook.loadFileAlloc(allocator, dir, path) catch unreachable;
|
||||||
defer allocator.free(rawFileBytes);
|
defer allocator.free(rawFileBytes);
|
||||||
// 1. load the file, and create a bytes buffer
|
// 1. load the file, and create a bytes buffer
|
||||||
var contents = png.PngContents.initFromBytes(allocator, path, rawFileBytes) catch unreachable;
|
var contents = png.PngContents.initFromBytes(allocator, path, rawFileBytes) catch unreachable;
|
||||||
defer contents.deinit();
|
defer contents.deinit();
|
||||||
|
|
||||||
// png.PngContents.initFromBytes(allocator: std.mem.Allocator, pathName: []const u8, pngFileContents: []const u8)
|
// png.PngContents.initFromBytes(allocator: std.mem.Allocator, pathName: []const u8, pngFileContents: []const u8)
|
||||||
// 2. use the PngContents function to cook it.
|
// 2. use the PngContents function to cook it.
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.bytes = contents.toBuffer() catch unreachable,
|
.bytes = contents.toBuffer() catch unreachable,
|
||||||
.result = .Success,
|
.result = .Success,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initCooker(allocator: std.mem.Allocator) !void {
|
pub fn initCooker(allocator: std.mem.Allocator) !void {
|
||||||
_ = allocator;
|
_ = allocator;
|
||||||
const registry = assets.cook.getRegistry();
|
const registry = assets.cook.getRegistry();
|
||||||
|
|
||||||
try registry.install("Texture", generateFunction, cookFunction, &.{
|
try registry.install("Texture", generateFunction, cookFunction, &.{
|
||||||
".png",
|
".png",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinitCooker() void {
|
pub fn deinitCooker() void {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const assets = @import("assets");
|
const assets = @import("assets");
|
||||||
const cook = assets.cook;
|
const cook = assets.cook;
|
||||||
const CookInfo = assets.cook.CookInfo;
|
const CookInfo = assets.cook.CookInfo;
|
||||||
const GenerateError = assets.cook.GenerateError;
|
const GenerateError = assets.cook.GenerateError;
|
||||||
const core = @import("core");
|
const core = @import("core");
|
||||||
const png = core.png;
|
const png = core.png;
|
||||||
|
|
@ -1,52 +1,52 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
const core = @import("core");
|
const core = @import("core");
|
||||||
const VkConstants = @import("vk_constants.zig");
|
const VkConstants = @import("vk_constants.zig");
|
||||||
const meshes = @import("mesh.zig");
|
const meshes = @import("mesh.zig");
|
||||||
const NeonVkContext = @import("vk_renderer.zig").NeonVkContext;
|
const NeonVkContext = @import("vk_renderer.zig").NeonVkContext;
|
||||||
const vk_pipeline = @import("vk_pipeline.zig");
|
const vk_pipeline = @import("vk_pipeline.zig");
|
||||||
|
|
||||||
const NeonVkPipelineBuilder = vk_pipeline.NeonVkPipelineBuilder;
|
const NeonVkPipelineBuilder = vk_pipeline.NeonVkPipelineBuilder;
|
||||||
const EulerAngles = core.EulerAngles;
|
const EulerAngles = core.EulerAngles;
|
||||||
const Mat = core.Mat;
|
const Mat = core.Mat;
|
||||||
const Vectorf = core.Vectorf;
|
const Vectorf = core.Vectorf;
|
||||||
const Quat = core.Quat;
|
const Quat = core.Quat;
|
||||||
const zm = core.zm;
|
const zm = core.zm;
|
||||||
const mul = zm.mul;
|
const mul = zm.mul;
|
||||||
|
|
||||||
pub const Material = struct {
|
pub const Material = struct {
|
||||||
materialName: core.Name,
|
materialName: core.Name,
|
||||||
textureSet: vk.DescriptorSet = .null_handle,
|
textureSet: vk.DescriptorSet = .null_handle,
|
||||||
pipeline: vk.Pipeline,
|
pipeline: vk.Pipeline,
|
||||||
layout: vk.PipelineLayout,
|
layout: vk.PipelineLayout,
|
||||||
|
|
||||||
pub fn deinit(self: *Material, ctx: *NeonVkContext) void {
|
pub fn deinit(self: *Material, ctx: *NeonVkContext) void {
|
||||||
ctx.vkd.destroyPipeline(ctx.dev, self.pipeline, null);
|
ctx.vkd.destroyPipeline(ctx.dev, self.pipeline, null);
|
||||||
ctx.vkAllocator.destroyPipelineLayout(ctx.dev, self.layout);
|
ctx.vkAllocator.destroyPipelineLayout(ctx.dev, self.layout);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const MaterialBuilder = struct {
|
pub const MaterialBuilder = struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
ctx: *NeonVkContext,
|
ctx: *NeonVkContext,
|
||||||
pipelineBuilder: NeonVkPipelineBuilder,
|
pipelineBuilder: NeonVkPipelineBuilder,
|
||||||
|
|
||||||
pub fn init(ctx: *NeonVkContext) MaterialBuilder {
|
pub fn init(ctx: *NeonVkContext) MaterialBuilder {
|
||||||
const self = MaterialBuilder{
|
const self = MaterialBuilder{
|
||||||
.allocator = ctx.allocator,
|
.allocator = ctx.allocator,
|
||||||
.ctx = ctx,
|
.ctx = ctx,
|
||||||
};
|
};
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(self: *Self) !void {
|
pub fn build(self: *Self) !void {
|
||||||
_ = self;
|
_ = self;
|
||||||
// try self.ctx.add_material();
|
// try self.ctx.add_material();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Self) void {
|
pub fn deinit(self: *Self) void {
|
||||||
_ = self;
|
_ = self;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -1,96 +1,96 @@
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
cubeMapShared: [graphics.NumFrames]?vk.DescriptorSet = .{ null, null },
|
cubeMapShared: [graphics.NumFrames]?vk.DescriptorSet = .{ null, null },
|
||||||
cubeMapTextureSet: ?vk.DescriptorSet = null,
|
cubeMapTextureSet: ?vk.DescriptorSet = null,
|
||||||
cubeMapName: ?core.Name = null,
|
cubeMapName: ?core.Name = null,
|
||||||
material: *graphics.Material = undefined,
|
material: *graphics.Material = undefined,
|
||||||
mesh: ?graphics.IndexedMesh = null,
|
mesh: ?graphics.IndexedMesh = null,
|
||||||
|
|
||||||
pub const RendererInterfaceVTable = graphics.RendererInterface.from(@This());
|
pub const RendererInterfaceVTable = graphics.RendererInterface.from(@This());
|
||||||
|
|
||||||
pub var gSkybox: *@This() = undefined;
|
pub var gSkybox: *@This() = undefined;
|
||||||
|
|
||||||
pub fn create(allocator: std.mem.Allocator) !*@This() {
|
pub fn create(allocator: std.mem.Allocator) !*@This() {
|
||||||
const self = try allocator.create(@This());
|
const self = try allocator.create(@This());
|
||||||
|
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
};
|
};
|
||||||
|
|
||||||
gSkybox = self;
|
gSkybox = self;
|
||||||
try self.initPipeline();
|
try self.initPipeline();
|
||||||
try graphics.registerRendererPlugin(self);
|
try graphics.registerRendererPlugin(self);
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sendShared(self: *@This(), fi: u32) void {
|
pub fn sendShared(self: *@This(), fi: u32) void {
|
||||||
if (self.cubeMapName == null) {
|
if (self.cubeMapName == null) {
|
||||||
self.cubeMapShared[fi] = self.cubeMapTextureSet;
|
self.cubeMapShared[fi] = self.cubeMapTextureSet;
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (self.mesh == null)
|
if (self.mesh == null)
|
||||||
self.mesh = graphics.getIndexedMeshByName(core.MakeName("m_skybox"));
|
self.mesh = graphics.getIndexedMeshByName(core.MakeName("m_skybox"));
|
||||||
|
|
||||||
if (self.cubeMapTextureSet == null) {
|
if (self.cubeMapTextureSet == null) {
|
||||||
const handle = self.cubeMapName.?.handle();
|
const handle = self.cubeMapName.?.handle();
|
||||||
self.cubeMapTextureSet = graphics.getContext().textureSets.get(handle);
|
self.cubeMapTextureSet = graphics.getContext().textureSets.get(handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.cubeMapShared[fi] = self.cubeMapTextureSet;
|
self.cubeMapShared[fi] = self.cubeMapTextureSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initPipeline(self: *@This()) !void {
|
pub fn initPipeline(self: *@This()) !void {
|
||||||
const gc = graphics.getContext();
|
const gc = graphics.getContext();
|
||||||
|
|
||||||
var pipelineBuilder = try graphics.NeonVkPipelineBuilder.init(
|
var pipelineBuilder = try graphics.NeonVkPipelineBuilder.init(
|
||||||
gc.dev,
|
gc.dev,
|
||||||
gc.vkd,
|
gc.vkd,
|
||||||
self.allocator,
|
self.allocator,
|
||||||
gc.vkAllocator,
|
gc.vkAllocator,
|
||||||
skybox_vert.spv(),
|
skybox_vert.spv(),
|
||||||
skybox_frag.spv(),
|
skybox_frag.spv(),
|
||||||
);
|
);
|
||||||
defer pipelineBuilder.deinit();
|
defer pipelineBuilder.deinit();
|
||||||
|
|
||||||
try pipelineBuilder.add_mesh_description();
|
try pipelineBuilder.add_mesh_description();
|
||||||
try pipelineBuilder.add_layout(gc.globalDescriptorLayout);
|
try pipelineBuilder.add_layout(gc.globalDescriptorLayout);
|
||||||
try pipelineBuilder.add_layout(gc.singleTextureSetLayout);
|
try pipelineBuilder.add_layout(gc.singleTextureSetLayout);
|
||||||
try pipelineBuilder.add_depth_stencil(); // todo.. we might not want this for a skybox.
|
try pipelineBuilder.add_depth_stencil(); // todo.. we might not want this for a skybox.
|
||||||
try pipelineBuilder.init_triangle_pipeline(gc.actual_extent);
|
try pipelineBuilder.init_triangle_pipeline(gc.actual_extent);
|
||||||
pipelineBuilder.pdsci.?.depth_write_enable = vk.FALSE;
|
pipelineBuilder.pdsci.?.depth_write_enable = vk.FALSE;
|
||||||
pipelineBuilder.pdsci.?.depth_test_enable = vk.FALSE;
|
pipelineBuilder.pdsci.?.depth_test_enable = vk.FALSE;
|
||||||
pipelineBuilder.pdsci.?.depth_compare_op = .never;
|
pipelineBuilder.pdsci.?.depth_compare_op = .never;
|
||||||
|
|
||||||
const materialName = core.MakeName("Mat_skybox");
|
const materialName = core.MakeName("Mat_skybox");
|
||||||
self.material = try self.allocator.create(graphics.Material);
|
self.material = try self.allocator.create(graphics.Material);
|
||||||
self.material.* = graphics.Material{
|
self.material.* = graphics.Material{
|
||||||
.materialName = materialName,
|
.materialName = materialName,
|
||||||
.pipeline = (try pipelineBuilder.build(gc.renderPass)).?,
|
.pipeline = (try pipelineBuilder.build(gc.renderPass)).?,
|
||||||
.layout = pipelineBuilder.pipelineLayout,
|
.layout = pipelineBuilder.pipelineLayout,
|
||||||
};
|
};
|
||||||
|
|
||||||
try gc.add_material(self.material);
|
try gc.add_material(self.material);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setSkybox(textureName: []const u8) !void {
|
pub fn setSkybox(textureName: []const u8) !void {
|
||||||
const name = core.MakeName(textureName);
|
const name = core.MakeName(textureName);
|
||||||
gSkybox.cubeMapName = name;
|
gSkybox.cubeMapName = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy(self: *@This()) void {
|
pub fn destroy(self: *@This()) void {
|
||||||
self.allocator.destroy(self);
|
self.allocator.destroy(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
const vk_renderer_interface = @import("vk_renderer/vk_renderer_interface.zig");
|
const vk_renderer_interface = @import("vk_renderer/vk_renderer_interface.zig");
|
||||||
const RendererInterface = vk_renderer_interface.RendererInterface;
|
const RendererInterface = vk_renderer_interface.RendererInterface;
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
const graphics = @import("graphics.zig");
|
const graphics = @import("graphics.zig");
|
||||||
const core = @import("core");
|
const core = @import("core");
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
const skybox_vert = @import("skybox_vert");
|
const skybox_vert = @import("skybox_vert");
|
||||||
const skybox_frag = @import("skybox_frag");
|
const skybox_frag = @import("skybox_frag");
|
||||||
|
|
||||||
const vkinit = @import("vk_init.zig");
|
const vkinit = @import("vk_init.zig");
|
||||||
|
|
@ -1,39 +1,39 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const core = @import("core");
|
const core = @import("core");
|
||||||
const vk_renderer = @import("vk_renderer.zig");
|
const vk_renderer = @import("vk_renderer.zig");
|
||||||
const vma = @import("vma");
|
const vma = @import("vma");
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
const vkinit = @import("vk_init.zig");
|
const vkinit = @import("vk_init.zig");
|
||||||
|
|
||||||
const NeonVkContext = vk_renderer.NeonVkContext;
|
const NeonVkContext = vk_renderer.NeonVkContext;
|
||||||
const NeonVkBuffer = vk_renderer.NeonVkBuffer;
|
const NeonVkBuffer = vk_renderer.NeonVkBuffer;
|
||||||
const NeonVkImage = vk_renderer.NeonVkImage;
|
const NeonVkImage = vk_renderer.NeonVkImage;
|
||||||
|
|
||||||
pub const PixelPos = struct {
|
pub const PixelPos = struct {
|
||||||
x: u32,
|
x: u32,
|
||||||
y: u32,
|
y: u32,
|
||||||
|
|
||||||
/// returns y/x of the pixel position
|
/// returns y/x of the pixel position
|
||||||
pub fn ratio(self: @This()) f32 {
|
pub fn ratio(self: @This()) f32 {
|
||||||
return @as(f32, @floatFromInt(self.y)) / @as(f32, @floatFromInt(self.x));
|
return @as(f32, @floatFromInt(self.y)) / @as(f32, @floatFromInt(self.x));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// This is a simple display texture
|
// This is a simple display texture
|
||||||
pub const Texture = struct {
|
pub const Texture = struct {
|
||||||
image: NeonVkImage,
|
image: NeonVkImage,
|
||||||
imageView: vk.ImageView,
|
imageView: vk.ImageView,
|
||||||
isCube: bool = false,
|
isCube: bool = false,
|
||||||
|
|
||||||
pub fn deinit(self: *@This(), ctx: *NeonVkContext) void {
|
pub fn deinit(self: *@This(), ctx: *NeonVkContext) void {
|
||||||
ctx.vkd.destroyImageView(ctx.dev, self.imageView, null);
|
ctx.vkd.destroyImageView(ctx.dev, self.imageView, null);
|
||||||
self.image.deinit(ctx.vkAllocator);
|
self.image.deinit(ctx.vkAllocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getDimensions(self: @This()) PixelPos {
|
pub fn getDimensions(self: @This()) PixelPos {
|
||||||
return .{
|
return .{
|
||||||
.x = self.image.pixelWidth,
|
.x = self.image.pixelWidth,
|
||||||
.y = self.image.pixelHeight,
|
.y = self.image.pixelHeight,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
// global api
|
// global api
|
||||||
//
|
//
|
||||||
// i hate lugging these variables around.
|
// i hate lugging these variables around.
|
||||||
// device and cmd buffers are fine,
|
// device and cmd buffers are fine,
|
||||||
// but the dispatch variables are going to be kept here and easily accessible.
|
// but the dispatch variables are going to be kept here and easily accessible.
|
||||||
|
|
||||||
pub var _vkb: constants.BaseDispatch = undefined;
|
pub var _vkb: constants.BaseDispatch = undefined;
|
||||||
pub var _vki: constants.InstanceDispatch = undefined;
|
pub var _vki: constants.InstanceDispatch = undefined;
|
||||||
pub var _vkd: constants.DeviceDispatch = undefined;
|
pub var _vkd: constants.DeviceDispatch = undefined;
|
||||||
|
|
||||||
pub const vkb = &_vkb;
|
pub const vkb = &_vkb;
|
||||||
pub const vki = &_vki;
|
pub const vki = &_vki;
|
||||||
pub const vkd = &_vkd;
|
pub const vkd = &_vkd;
|
||||||
|
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
const constants = @import("vk_constants.zig");
|
const constants = @import("vk_constants.zig");
|
||||||
|
|
@ -1,373 +1,373 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
const graphics = @import("graphics.zig");
|
const graphics = @import("graphics.zig");
|
||||||
|
|
||||||
const core = @import("core");
|
const core = @import("core");
|
||||||
const assets = @import("assets");
|
const assets = @import("assets");
|
||||||
const vk_utils = @import("vk_utils.zig");
|
const vk_utils = @import("vk_utils.zig");
|
||||||
const vkinit = @import("vk_init.zig");
|
const vkinit = @import("vk_init.zig");
|
||||||
const vk_cubemap = @import("vk_renderer/vk_cubemap.zig");
|
const vk_cubemap = @import("vk_renderer/vk_cubemap.zig");
|
||||||
|
|
||||||
const tracy = core.tracy;
|
const tracy = core.tracy;
|
||||||
const materials = @import("materials.zig");
|
const materials = @import("materials.zig");
|
||||||
const vk_renderer = @import("vk_renderer.zig");
|
const vk_renderer = @import("vk_renderer.zig");
|
||||||
const mesh = @import("mesh.zig");
|
const mesh = @import("mesh.zig");
|
||||||
const texture = @import("texture.zig");
|
const texture = @import("texture.zig");
|
||||||
|
|
||||||
const NeonVkContext = vk_renderer.NeonVkContext;
|
const NeonVkContext = vk_renderer.NeonVkContext;
|
||||||
const Material = materials.Material;
|
const Material = materials.Material;
|
||||||
const Mesh = mesh.Mesh;
|
const Mesh = mesh.Mesh;
|
||||||
const Texture = texture.Texture;
|
const Texture = texture.Texture;
|
||||||
|
|
||||||
pub const TextureLoader = struct {
|
pub const TextureLoader = struct {
|
||||||
pub var LoaderInterfaceVTable: assets.AssetLoaderInterface = assets.AssetLoaderInterface.from("Texture", @This());
|
pub var LoaderInterfaceVTable: assets.AssetLoaderInterface = assets.AssetLoaderInterface.from("Texture", @This());
|
||||||
pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This());
|
pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This());
|
||||||
|
|
||||||
const StagedTextureDescription = struct {
|
const StagedTextureDescription = struct {
|
||||||
name: core.Name,
|
name: core.Name,
|
||||||
stagingResults: vk_utils.LoadAndStageImage,
|
stagingResults: vk_utils.LoadAndStageImage,
|
||||||
textureListResults: ?[]vk_utils.LoadAndStageImage = null,
|
textureListResults: ?[]vk_utils.LoadAndStageImage = null,
|
||||||
assetRef: assets.AssetRef,
|
assetRef: assets.AssetRef,
|
||||||
properties: assets.AssetPropertiesBag,
|
properties: assets.AssetPropertiesBag,
|
||||||
|
|
||||||
pub fn deinit(self: *@This(), gc: *NeonVkContext) void {
|
pub fn deinit(self: *@This(), gc: *NeonVkContext) void {
|
||||||
self.stagingResults.deinit(gc.vkAllocator);
|
self.stagingResults.deinit(gc.vkAllocator);
|
||||||
if (self.textureListResults) |results| {
|
if (self.textureListResults) |results| {
|
||||||
for (results) |*result| {
|
for (results) |*result| {
|
||||||
result.deinit(gc.vkAllocator);
|
result.deinit(gc.vkAllocator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const RTAssetsReady = struct {
|
const RTAssetsReady = struct {
|
||||||
name: core.Name,
|
name: core.Name,
|
||||||
texture: *Texture,
|
texture: *Texture,
|
||||||
textureSet: vk.DescriptorSet,
|
textureSet: vk.DescriptorSet,
|
||||||
textureId: u32,
|
textureId: u32,
|
||||||
};
|
};
|
||||||
|
|
||||||
gc: *NeonVkContext,
|
gc: *NeonVkContext,
|
||||||
assetsReady: core.RingQueue(StagedTextureDescription),
|
assetsReady: core.RingQueue(StagedTextureDescription),
|
||||||
rtAssetsReady: core.RingQueue(RTAssetsReady),
|
rtAssetsReady: core.RingQueue(RTAssetsReady),
|
||||||
discarding: std.atomic.Value(bool) = std.atomic.Value(bool).init(false),
|
discarding: std.atomic.Value(bool) = std.atomic.Value(bool).init(false),
|
||||||
|
|
||||||
pub fn loadAsset(self: *@This(), assetRef: assets.AssetRef, props: ?assets.AssetPropertiesBag) assets.AssetLoaderError!void {
|
pub fn loadAsset(self: *@This(), assetRef: assets.AssetRef, props: ?assets.AssetPropertiesBag) assets.AssetLoaderError!void {
|
||||||
if (self.discarding.load(.seq_cst)) {
|
if (self.discarding.load(.seq_cst)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var z = tracy.ZoneN(@src(), "TextureLoader loadAsset");
|
var z = tracy.ZoneN(@src(), "TextureLoader loadAsset");
|
||||||
const Lambda = struct {
|
const Lambda = struct {
|
||||||
loader: *TextureLoader,
|
loader: *TextureLoader,
|
||||||
assetRef: assets.AssetRef,
|
assetRef: assets.AssetRef,
|
||||||
gc: *NeonVkContext,
|
gc: *NeonVkContext,
|
||||||
properties: assets.AssetPropertiesBag,
|
properties: assets.AssetPropertiesBag,
|
||||||
|
|
||||||
pub fn eFunc(ctx: @This()) !void {
|
pub fn eFunc(ctx: @This()) !void {
|
||||||
var z1 = tracy.ZoneN(@src(), "Loading file from TextureLoader");
|
var z1 = tracy.ZoneN(@src(), "Loading file from TextureLoader");
|
||||||
const gc = ctx.gc;
|
const gc = ctx.gc;
|
||||||
defer {
|
defer {
|
||||||
_ = ctx.gc.outstandingJobsCount.fetchSub(1, .seq_cst);
|
_ = ctx.gc.outstandingJobsCount.fetchSub(1, .seq_cst);
|
||||||
}
|
}
|
||||||
|
|
||||||
var loadAndStageResults: vk_utils.LoadAndStageImage = undefined;
|
var loadAndStageResults: vk_utils.LoadAndStageImage = undefined;
|
||||||
if (!ctx.properties.textureCube) {
|
if (!ctx.properties.textureCube) {
|
||||||
loadAndStageResults = try vk_utils.load_and_stage_image_from_file(gc, ctx.properties.path);
|
loadAndStageResults = try vk_utils.load_and_stage_image_from_file(gc, ctx.properties.path);
|
||||||
errdefer loadAndStageResults.deinit(gc.vkAllocator);
|
errdefer loadAndStageResults.deinit(gc.vkAllocator);
|
||||||
} else {
|
} else {
|
||||||
loadAndStageResults = try vk_cubemap.stageCubeTexture(ctx.properties.textureList.?);
|
loadAndStageResults = try vk_cubemap.stageCubeTexture(ctx.properties.textureList.?);
|
||||||
errdefer loadAndStageResults.deinit(gc.vkAllocator);
|
errdefer loadAndStageResults.deinit(gc.vkAllocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
var assetRefName = ctx.assetRef.name;
|
var assetRefName = ctx.assetRef.name;
|
||||||
|
|
||||||
tracy.Message(assetRefName.utf8());
|
tracy.Message(assetRefName.utf8());
|
||||||
tracy.Message(ctx.properties.path);
|
tracy.Message(ctx.properties.path);
|
||||||
|
|
||||||
core.engine_log("loaded: {s} from: {s}", .{ assetRefName.utf8(), ctx.properties.path });
|
core.engine_log("loaded: {s} from: {s}", .{ assetRefName.utf8(), ctx.properties.path });
|
||||||
var loadedDescription = StagedTextureDescription{
|
var loadedDescription = StagedTextureDescription{
|
||||||
.name = ctx.assetRef.name,
|
.name = ctx.assetRef.name,
|
||||||
.stagingResults = loadAndStageResults,
|
.stagingResults = loadAndStageResults,
|
||||||
.assetRef = ctx.assetRef,
|
.assetRef = ctx.assetRef,
|
||||||
.properties = ctx.properties,
|
.properties = ctx.properties,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (ctx.properties.textureList) |textureList| {
|
if (ctx.properties.textureList) |textureList| {
|
||||||
const tlResults = try ctx.gc.allocator.alloc(vk_utils.LoadAndStageImage, textureList.len);
|
const tlResults = try ctx.gc.allocator.alloc(vk_utils.LoadAndStageImage, textureList.len);
|
||||||
errdefer ctx.gc.allocator.free(tlResults);
|
errdefer ctx.gc.allocator.free(tlResults);
|
||||||
|
|
||||||
for (textureList, 0..) |tPath, i| {
|
for (textureList, 0..) |tPath, i| {
|
||||||
const rv = vk_utils.load_and_stage_image_from_file(gc, tPath) catch {
|
const rv = vk_utils.load_and_stage_image_from_file(gc, tPath) catch {
|
||||||
core.engine_log("unable to load file {s}", .{tPath});
|
core.engine_log("unable to load file {s}", .{tPath});
|
||||||
return error.FailedToLoad;
|
return error.FailedToLoad;
|
||||||
};
|
};
|
||||||
errdefer rv.deinit();
|
errdefer rv.deinit();
|
||||||
tlResults[i] = rv;
|
tlResults[i] = rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
loadedDescription.textureListResults = tlResults;
|
loadedDescription.textureListResults = tlResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
z1.End();
|
z1.End();
|
||||||
|
|
||||||
ctx.loader.assetsReady.pushLocked(loadedDescription) catch unreachable;
|
ctx.loader.assetsReady.pushLocked(loadedDescription) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn func(ctx: @This(), _: *core.JobContext) void {
|
pub fn func(ctx: @This(), _: *core.JobContext) void {
|
||||||
ctx.eFunc() catch unreachable;
|
ctx.eFunc() catch unreachable;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_ = self.gc.outstandingJobsCount.fetchAdd(1, .seq_cst);
|
_ = self.gc.outstandingJobsCount.fetchAdd(1, .seq_cst);
|
||||||
core.dispatchJob(Lambda{
|
core.dispatchJob(Lambda{
|
||||||
.loader = self,
|
.loader = self,
|
||||||
.gc = self.gc,
|
.gc = self.gc,
|
||||||
.assetRef = assetRef,
|
.assetRef = assetRef,
|
||||||
.properties = props.?,
|
.properties = props.?,
|
||||||
}) catch return error.UnableToLoad;
|
}) catch return error.UnableToLoad;
|
||||||
|
|
||||||
z.End();
|
z.End();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn processRenderThreadEvents(ptr: *anyopaque) void {
|
pub fn processRenderThreadEvents(ptr: *anyopaque) void {
|
||||||
const self: *@This() = @ptrCast(@alignCast(ptr));
|
const self: *@This() = @ptrCast(@alignCast(ptr));
|
||||||
self.processEventInner() catch {};
|
self.processEventInner() catch {};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn createImageFromStagingResult(self: *@This(), name: core.Name, stagingResults: *vk_utils.LoadAndStageImage, properties: assets.AssetPropertiesBag) core.EngineDataEventError!void {
|
pub fn createImageFromStagingResult(self: *@This(), name: core.Name, stagingResults: *vk_utils.LoadAndStageImage, properties: assets.AssetPropertiesBag) core.EngineDataEventError!void {
|
||||||
const gc = self.gc;
|
const gc = self.gc;
|
||||||
var stagingBuffer = stagingResults.stagingBuffer;
|
var stagingBuffer = stagingResults.stagingBuffer;
|
||||||
const image = stagingResults.image;
|
const image = stagingResults.image;
|
||||||
|
|
||||||
if (stagingResults.cubeOffsets != null) {
|
if (stagingResults.cubeOffsets != null) {
|
||||||
vk_cubemap.submitTextureCube(&gc.uploader, stagingResults) catch return error.UnknownStatePanic;
|
vk_cubemap.submitTextureCube(&gc.uploader, stagingResults) catch return error.UnknownStatePanic;
|
||||||
stagingBuffer.deinit(gc.vkAllocator);
|
stagingBuffer.deinit(gc.vkAllocator);
|
||||||
|
|
||||||
var ivc = vkinit.imageViewCreateInfo(
|
var ivc = vkinit.imageViewCreateInfo(
|
||||||
.r8g8b8a8_srgb,
|
.r8g8b8a8_srgb,
|
||||||
image.image,
|
image.image,
|
||||||
.{ .color_bit = true },
|
.{ .color_bit = true },
|
||||||
stagingResults.mipLevel,
|
stagingResults.mipLevel,
|
||||||
);
|
);
|
||||||
ivc.view_type = .cube;
|
ivc.view_type = .cube;
|
||||||
ivc.subresource_range.layer_count = 6;
|
ivc.subresource_range.layer_count = 6;
|
||||||
const imageView = gc.vkd.createImageView(gc.dev, &ivc, null) catch return error.UnknownStatePanic;
|
const imageView = gc.vkd.createImageView(gc.dev, &ivc, null) catch return error.UnknownStatePanic;
|
||||||
const newTexture = gc.allocator.create(Texture) catch return error.UnknownStatePanic;
|
const newTexture = gc.allocator.create(Texture) catch return error.UnknownStatePanic;
|
||||||
newTexture.* = Texture{
|
newTexture.* = Texture{
|
||||||
.image = image,
|
.image = image,
|
||||||
.imageView = imageView,
|
.imageView = imageView,
|
||||||
};
|
};
|
||||||
|
|
||||||
const rv = vk_utils.createDescriptorSetForImage(
|
const rv = vk_utils.createDescriptorSetForImage(
|
||||||
gc.dev,
|
gc.dev,
|
||||||
gc.descriptorPool,
|
gc.descriptorPool,
|
||||||
gc.singleTextureSetLayout,
|
gc.singleTextureSetLayout,
|
||||||
imageView,
|
imageView,
|
||||||
gc.cubeSampler,
|
gc.cubeSampler,
|
||||||
false,
|
false,
|
||||||
) catch return error.UnknownStatePanic;
|
) catch return error.UnknownStatePanic;
|
||||||
|
|
||||||
self.rtAssetsReady.pushLocked(.{
|
self.rtAssetsReady.pushLocked(.{
|
||||||
.name = name,
|
.name = name,
|
||||||
.texture = newTexture,
|
.texture = newTexture,
|
||||||
.textureSet = rv.textureSet,
|
.textureSet = rv.textureSet,
|
||||||
.textureId = rv.textureId,
|
.textureId = rv.textureId,
|
||||||
}) catch return error.UnknownStatePanic;
|
}) catch return error.UnknownStatePanic;
|
||||||
} else {
|
} else {
|
||||||
vk_utils.submit_copy_from_staging(gc, stagingBuffer, image, stagingResults.mipLevel) catch return error.UnknownStatePanic;
|
vk_utils.submit_copy_from_staging(gc, stagingBuffer, image, stagingResults.mipLevel) catch return error.UnknownStatePanic;
|
||||||
stagingBuffer.deinit(gc.vkAllocator);
|
stagingBuffer.deinit(gc.vkAllocator);
|
||||||
|
|
||||||
var imageViewCreate = vkinit.imageViewCreateInfo(
|
var imageViewCreate = vkinit.imageViewCreateInfo(
|
||||||
.r8g8b8a8_srgb,
|
.r8g8b8a8_srgb,
|
||||||
image.image,
|
image.image,
|
||||||
.{ .color_bit = true },
|
.{ .color_bit = true },
|
||||||
stagingResults.mipLevel,
|
stagingResults.mipLevel,
|
||||||
);
|
);
|
||||||
const imageView = gc.vkd.createImageView(gc.dev, &imageViewCreate, null) catch return error.UnknownStatePanic;
|
const imageView = gc.vkd.createImageView(gc.dev, &imageViewCreate, null) catch return error.UnknownStatePanic;
|
||||||
const newTexture = gc.allocator.create(Texture) catch return error.UnknownStatePanic;
|
const newTexture = gc.allocator.create(Texture) catch return error.UnknownStatePanic;
|
||||||
|
|
||||||
newTexture.* = Texture{
|
newTexture.* = Texture{
|
||||||
.image = image,
|
.image = image,
|
||||||
.imageView = imageView,
|
.imageView = imageView,
|
||||||
};
|
};
|
||||||
|
|
||||||
const sampler = if (properties.textureUseBlockySampler) gc.blockySampler else gc.linearSampler;
|
const sampler = if (properties.textureUseBlockySampler) gc.blockySampler else gc.linearSampler;
|
||||||
const rv = vk_utils.createDescriptorSetForImage(
|
const rv = vk_utils.createDescriptorSetForImage(
|
||||||
gc.dev,
|
gc.dev,
|
||||||
gc.descriptorPool,
|
gc.descriptorPool,
|
||||||
gc.singleTextureSetLayout,
|
gc.singleTextureSetLayout,
|
||||||
imageView,
|
imageView,
|
||||||
sampler,
|
sampler,
|
||||||
true,
|
true,
|
||||||
) catch return error.UnknownStatePanic;
|
) catch return error.UnknownStatePanic;
|
||||||
|
|
||||||
self.rtAssetsReady.pushLocked(.{
|
self.rtAssetsReady.pushLocked(.{
|
||||||
.name = name,
|
.name = name,
|
||||||
.texture = newTexture,
|
.texture = newTexture,
|
||||||
.textureSet = rv.textureSet,
|
.textureSet = rv.textureSet,
|
||||||
.textureId = rv.textureId,
|
.textureId = rv.textureId,
|
||||||
}) catch return error.UnknownStatePanic;
|
}) catch return error.UnknownStatePanic;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn processEventInner(self: *@This()) core.EngineDataEventError!void {
|
fn processEventInner(self: *@This()) core.EngineDataEventError!void {
|
||||||
if (self.assetsReady.count() > 0) {
|
if (self.assetsReady.count() > 0) {
|
||||||
self.assetsReady.lock();
|
self.assetsReady.lock();
|
||||||
defer self.assetsReady.unlock();
|
defer self.assetsReady.unlock();
|
||||||
while (self.assetsReady.popFromUnlocked()) |ar| {
|
while (self.assetsReady.popFromUnlocked()) |ar| {
|
||||||
var assetReady = ar;
|
var assetReady = ar;
|
||||||
var z1 = tracy.ZoneN(@src(), "Uploading asset loaded by TextureLoader");
|
var z1 = tracy.ZoneN(@src(), "Uploading asset loaded by TextureLoader");
|
||||||
tracy.Message("TextureLoader");
|
tracy.Message("TextureLoader");
|
||||||
tracy.Message(assetReady.assetRef.name.utf8());
|
tracy.Message(assetReady.assetRef.name.utf8());
|
||||||
tracy.Message(assetReady.properties.path);
|
tracy.Message(assetReady.properties.path);
|
||||||
core.engine_log("async texture load complete registry: {s}", .{assetReady.name.utf8()});
|
core.engine_log("async texture load complete registry: {s}", .{assetReady.name.utf8()});
|
||||||
try self.createImageFromStagingResult(assetReady.name, &assetReady.stagingResults, assetReady.properties);
|
try self.createImageFromStagingResult(assetReady.name, &assetReady.stagingResults, assetReady.properties);
|
||||||
|
|
||||||
if (assetReady.textureListResults) |results| {
|
if (assetReady.textureListResults) |results| {
|
||||||
var buf: [256]u8 = undefined;
|
var buf: [256]u8 = undefined;
|
||||||
for (results, 0..) |res, i| {
|
for (results, 0..) |res, i| {
|
||||||
var r = res;
|
var r = res;
|
||||||
var arName = assetReady.name;
|
var arName = assetReady.name;
|
||||||
const newName = std.fmt.bufPrint(&buf, "{s}[{d}]", .{ arName.utf8(), i }) catch return core.EngineDataEventError.OutOfMemory;
|
const newName = std.fmt.bufPrint(&buf, "{s}[{d}]", .{ arName.utf8(), i }) catch return core.EngineDataEventError.OutOfMemory;
|
||||||
|
|
||||||
try self.createImageFromStagingResult(core.MakeName(newName), &r, assetReady.properties);
|
try self.createImageFromStagingResult(core.MakeName(newName), &r, assetReady.properties);
|
||||||
}
|
}
|
||||||
self.gc.allocator.free(results);
|
self.gc.allocator.free(results);
|
||||||
}
|
}
|
||||||
|
|
||||||
z1.End();
|
z1.End();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// processing events, some should really be processing events rather than
|
// processing events, some should really be processing events rather than
|
||||||
pub fn processEvents(self: *@This(), frameNumber: u64) core.EngineDataEventError!void {
|
pub fn processEvents(self: *@This(), frameNumber: u64) core.EngineDataEventError!void {
|
||||||
_ = frameNumber;
|
_ = frameNumber;
|
||||||
if (self.rtAssetsReady.count() > 0) {
|
if (self.rtAssetsReady.count() > 0) {
|
||||||
self.rtAssetsReady.lock();
|
self.rtAssetsReady.lock();
|
||||||
defer self.rtAssetsReady.unlock();
|
defer self.rtAssetsReady.unlock();
|
||||||
while (self.rtAssetsReady.popFromUnlocked()) |a| {
|
while (self.rtAssetsReady.popFromUnlocked()) |a| {
|
||||||
self.gc.install_texture_into_registry(a.name, a.texture, a.textureSet, a.textureId) catch return error.UnknownStatePanic;
|
self.gc.install_texture_into_registry(a.name, a.texture, a.textureSet, a.textureId) catch return error.UnknownStatePanic;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn discardAll(self: *@This()) void {
|
pub fn discardAll(self: *@This()) void {
|
||||||
self.discarding.store(true, .seq_cst);
|
self.discarding.store(true, .seq_cst);
|
||||||
core.graphics_log("discarding {d} outstanding jobs", .{self.assetsReady.count()});
|
core.graphics_log("discarding {d} outstanding jobs", .{self.assetsReady.count()});
|
||||||
|
|
||||||
self.assetsReady.lock();
|
self.assetsReady.lock();
|
||||||
defer self.assetsReady.unlock();
|
defer self.assetsReady.unlock();
|
||||||
|
|
||||||
while (self.assetsReady.popFromUnlocked()) |assetReady| {
|
while (self.assetsReady.popFromUnlocked()) |assetReady| {
|
||||||
var copy = assetReady;
|
var copy = assetReady;
|
||||||
StagedTextureDescription.deinit(©, self.gc);
|
StagedTextureDescription.deinit(©, self.gc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator) !*@This() {
|
pub fn init(allocator: std.mem.Allocator) !*@This() {
|
||||||
const self = try allocator.create(@This());
|
const self = try allocator.create(@This());
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.gc = vk_renderer.gContext,
|
.gc = vk_renderer.gContext,
|
||||||
//todo: the EngineObjectVTable init function should have a handleable error
|
//todo: the EngineObjectVTable init function should have a handleable error
|
||||||
.assetsReady = core.RingQueue(StagedTextureDescription).init(allocator, 1024) catch unreachable,
|
.assetsReady = core.RingQueue(StagedTextureDescription).init(allocator, 1024) catch unreachable,
|
||||||
.rtAssetsReady = core.RingQueue(RTAssetsReady).init(allocator, 1024) catch unreachable,
|
.rtAssetsReady = core.RingQueue(RTAssetsReady).init(allocator, 1024) catch unreachable,
|
||||||
};
|
};
|
||||||
|
|
||||||
try self.gc.renderthread.installListener(self, processRenderThreadEvents);
|
try self.gc.renderthread.installListener(self, processRenderThreadEvents);
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy(self: *@This(), allocator: std.mem.Allocator) void {
|
pub fn destroy(self: *@This(), allocator: std.mem.Allocator) void {
|
||||||
self.assetsReady.deinit();
|
self.assetsReady.deinit();
|
||||||
self.rtAssetsReady.deinit();
|
self.rtAssetsReady.deinit();
|
||||||
allocator.destroy(self);
|
allocator.destroy(self);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const MeshLoader = struct {
|
pub const MeshLoader = struct {
|
||||||
pub var LoaderInterfaceVTable = assets.AssetLoaderInterface.from("Mesh", @This());
|
pub var LoaderInterfaceVTable = assets.AssetLoaderInterface.from("Mesh", @This());
|
||||||
pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This());
|
pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This());
|
||||||
gc: *NeonVkContext,
|
gc: *NeonVkContext,
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator) !*@This() {
|
pub fn init(allocator: std.mem.Allocator) !*@This() {
|
||||||
const self = try allocator.create(@This());
|
const self = try allocator.create(@This());
|
||||||
|
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.gc = vk_renderer.gContext,
|
.gc = vk_renderer.gContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn loadAsset(self: *@This(), assetRef: assets.AssetRef, propertiesBag: ?assets.AssetPropertiesBag) assets.AssetLoaderError!void {
|
pub fn loadAsset(self: *@This(), assetRef: assets.AssetRef, propertiesBag: ?assets.AssetPropertiesBag) assets.AssetLoaderError!void {
|
||||||
_ = self;
|
_ = self;
|
||||||
const sourceType = getSourceType(propertiesBag);
|
const sourceType = getSourceType(propertiesBag);
|
||||||
core.engine_log("loading mesh asset {s} [{s}]", .{ propertiesBag.?.path, if (sourceType) |s| @tagName(s) else "default" });
|
core.engine_log("loading mesh asset {s} [{s}]", .{ propertiesBag.?.path, if (sourceType) |s| @tagName(s) else "default" });
|
||||||
graphics.loadIndexedMeshForPooling(assetRef.name, .{
|
graphics.loadIndexedMeshForPooling(assetRef.name, .{
|
||||||
.path = propertiesBag.?.path,
|
.path = propertiesBag.?.path,
|
||||||
.sourceType = getSourceType(propertiesBag),
|
.sourceType = getSourceType(propertiesBag),
|
||||||
.skeletonName = if (propertiesBag.?.skeletonName) |skName| core.MakeName(skName) else null,
|
.skeletonName = if (propertiesBag.?.skeletonName) |skName| core.MakeName(skName) else null,
|
||||||
}) catch return error.UnableToLoad;
|
}) catch return error.UnableToLoad;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getSourceType(propertiesBag: ?assets.AssetPropertiesBag) ?graphics.MeshSourceType {
|
fn getSourceType(propertiesBag: ?assets.AssetPropertiesBag) ?graphics.MeshSourceType {
|
||||||
if (propertiesBag) |bag| {
|
if (propertiesBag) |bag| {
|
||||||
if (bag.meshType) |meshType| {
|
if (bag.meshType) |meshType| {
|
||||||
if (std.mem.eql(u8, meshType, "obj")) {
|
if (std.mem.eql(u8, meshType, "obj")) {
|
||||||
return graphics.MeshSourceType.obj;
|
return graphics.MeshSourceType.obj;
|
||||||
}
|
}
|
||||||
if (std.mem.eql(u8, meshType, "gltf")) {
|
if (std.mem.eql(u8, meshType, "gltf")) {
|
||||||
return graphics.MeshSourceType.gltf;
|
return graphics.MeshSourceType.gltf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to deduce it by file name, if nothing is set.
|
// try to deduce it by file name, if nothing is set.
|
||||||
const ext = core.getFileExtension(bag.path);
|
const ext = core.getFileExtension(bag.path);
|
||||||
if (std.mem.eql(u8, ext, ".obj")) {
|
if (std.mem.eql(u8, ext, ".obj")) {
|
||||||
return graphics.MeshSourceType.obj;
|
return graphics.MeshSourceType.obj;
|
||||||
}
|
}
|
||||||
if (std.mem.eql(u8, ext, ".gltf")) {
|
if (std.mem.eql(u8, ext, ".gltf")) {
|
||||||
return graphics.MeshSourceType.gltf;
|
return graphics.MeshSourceType.gltf;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std.mem.eql(u8, ext, ".glb")) {
|
if (std.mem.eql(u8, ext, ".glb")) {
|
||||||
return graphics.MeshSourceType.gltf;
|
return graphics.MeshSourceType.gltf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn discardAll(self: *@This()) void {
|
pub fn discardAll(self: *@This()) void {
|
||||||
// totally synchronous, nothing to do for a discard
|
// totally synchronous, nothing to do for a discard
|
||||||
_ = self;
|
_ = self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy(self: *@This(), allocator: std.mem.Allocator) void {
|
pub fn destroy(self: *@This(), allocator: std.mem.Allocator) void {
|
||||||
allocator.destroy(self);
|
allocator.destroy(self);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub var gTextureLoader: *TextureLoader = undefined;
|
pub var gTextureLoader: *TextureLoader = undefined;
|
||||||
pub var gMeshLoader: *MeshLoader = undefined;
|
pub var gMeshLoader: *MeshLoader = undefined;
|
||||||
|
|
||||||
pub fn init_loaders(allocator: std.mem.Allocator) !void {
|
pub fn init_loaders(allocator: std.mem.Allocator) !void {
|
||||||
gTextureLoader = try core.createObject(TextureLoader, .{
|
gTextureLoader = try core.createObject(TextureLoader, .{
|
||||||
.responds_to_events = true,
|
.responds_to_events = true,
|
||||||
});
|
});
|
||||||
|
|
||||||
gMeshLoader = try allocator.create(MeshLoader);
|
gMeshLoader = try allocator.create(MeshLoader);
|
||||||
gMeshLoader.* = .{ .gc = vk_renderer.gContext };
|
gMeshLoader.* = .{ .gc = vk_renderer.gContext };
|
||||||
|
|
||||||
try assets.gAssetSys.registerLoader(gTextureLoader);
|
try assets.gAssetSys.registerLoader(gTextureLoader);
|
||||||
try assets.gAssetSys.registerLoader(gMeshLoader);
|
try assets.gAssetSys.registerLoader(gMeshLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
// submit an abort message to TextureLoader and MeshLoader
|
// submit an abort message to TextureLoader and MeshLoader
|
||||||
pub fn discardAll() void {
|
pub fn discardAll() void {
|
||||||
gTextureLoader.discardAll();
|
gTextureLoader.discardAll();
|
||||||
gMeshLoader.discardAll();
|
gMeshLoader.discardAll();
|
||||||
}
|
}
|
||||||
|
|
@ -1,25 +1,25 @@
|
||||||
// higher level descriptor and SSBO wrangling libraries.
|
// higher level descriptor and SSBO wrangling libraries.
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const core = @import("core");
|
const core = @import("core");
|
||||||
const vk_renderer = @import("vk_renderer.zig");
|
const vk_renderer = @import("vk_renderer.zig");
|
||||||
const vma = @import("vma");
|
const vma = @import("vma");
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
const obj_loader = @import("objLoader");
|
const obj_loader = @import("objLoader");
|
||||||
const vkinit = @import("vk_init.zig");
|
const vkinit = @import("vk_init.zig");
|
||||||
const vk_constants = @import("vk_constants.zig");
|
const vk_constants = @import("vk_constants.zig");
|
||||||
const tracy = core.tracy;
|
const tracy = core.tracy;
|
||||||
|
|
||||||
const spng = core.spng;
|
const spng = core.spng;
|
||||||
|
|
||||||
const ObjMesh = obj_loader.ObjMesh;
|
const ObjMesh = obj_loader.ObjMesh;
|
||||||
const ArrayList = std.ArrayList;
|
const ArrayList = std.ArrayList;
|
||||||
const Vectorf = core.Vectorf;
|
const Vectorf = core.Vectorf;
|
||||||
const NeonVkContext = vk_renderer.NeonVkContext;
|
const NeonVkContext = vk_renderer.NeonVkContext;
|
||||||
const NeonVkBuffer = vk_renderer.NeonVkBuffer;
|
const NeonVkBuffer = vk_renderer.NeonVkBuffer;
|
||||||
const NeonVkImage = vk_renderer.NeonVkImage;
|
const NeonVkImage = vk_renderer.NeonVkImage;
|
||||||
const NumFrames = vk_constants.NUM_FRAMES;
|
const NumFrames = vk_constants.NUM_FRAMES;
|
||||||
|
|
||||||
pub const DescriptorSetLayoutInfo = struct {
|
pub const DescriptorSetLayoutInfo = struct {
|
||||||
bindingCount: u32,
|
bindingCount: u32,
|
||||||
};
|
};
|
||||||
|
|
@ -1,435 +1,435 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const core = @import("core");
|
const core = @import("core");
|
||||||
const vk_renderer = @import("vk_renderer.zig");
|
const vk_renderer = @import("vk_renderer.zig");
|
||||||
const vma = @import("vma");
|
const vma = @import("vma");
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
const obj_loader = @import("objLoader");
|
const obj_loader = @import("objLoader");
|
||||||
const constants = @import("vk_constants.zig");
|
const constants = @import("vk_constants.zig");
|
||||||
const vk_utils = @import("vk_utils.zig");
|
const vk_utils = @import("vk_utils.zig");
|
||||||
|
|
||||||
const NeonVkUploader = vk_utils.NeonVkUploader;
|
const NeonVkUploader = vk_utils.NeonVkUploader;
|
||||||
const NeonVkBuffer = vk_renderer.NeonVkBuffer;
|
const NeonVkBuffer = vk_renderer.NeonVkBuffer;
|
||||||
const ObjMesh = obj_loader.ObjMesh;
|
const ObjMesh = obj_loader.ObjMesh;
|
||||||
const ArrayList = std.ArrayList;
|
const ArrayList = std.ArrayList;
|
||||||
const Vectorf = core.Vectorf;
|
const Vectorf = core.Vectorf;
|
||||||
const Vector2f = core.Vector2f;
|
const Vector2f = core.Vector2f;
|
||||||
const LinearColor = core.colors.Color;
|
const LinearColor = core.colors.Color;
|
||||||
const NeonVkContext = vk_renderer.NeonVkContext;
|
const NeonVkContext = vk_renderer.NeonVkContext;
|
||||||
|
|
||||||
const mesh = @import("mesh.zig");
|
const mesh = @import("mesh.zig");
|
||||||
const MeshVertex = mesh.MeshVertex;
|
const MeshVertex = mesh.MeshVertex;
|
||||||
|
|
||||||
const debug_struct = core.debug_struct;
|
const debug_struct = core.debug_struct;
|
||||||
|
|
||||||
pub const DynamicMeshManager = struct {
|
pub const DynamicMeshManager = struct {
|
||||||
gc: *NeonVkContext,
|
gc: *NeonVkContext,
|
||||||
|
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
dynMeshes: std.ArrayListUnmanaged(*DynamicMesh) = .{},
|
dynMeshes: std.ArrayListUnmanaged(*DynamicMesh) = .{},
|
||||||
uploader: NeonVkUploader,
|
uploader: NeonVkUploader,
|
||||||
|
|
||||||
first: bool = true,
|
first: bool = true,
|
||||||
|
|
||||||
pub fn init(gc: *NeonVkContext) !*@This() {
|
pub fn init(gc: *NeonVkContext) !*@This() {
|
||||||
const self = try gc.allocator.create(@This());
|
const self = try gc.allocator.create(@This());
|
||||||
self.* = @This(){
|
self.* = @This(){
|
||||||
.gc = gc,
|
.gc = gc,
|
||||||
.allocator = gc.allocator,
|
.allocator = gc.allocator,
|
||||||
.uploader = try NeonVkUploader.init(gc, "dynamic mesh manager uploader"),
|
.uploader = try NeonVkUploader.init(gc, "dynamic mesh manager uploader"),
|
||||||
};
|
};
|
||||||
|
|
||||||
// core.graphics_log("creating the mesh manager", .{});
|
// core.graphics_log("creating the mesh manager", .{});
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *@This()) void {
|
pub fn deinit(self: *@This()) void {
|
||||||
self.uploader.deinit();
|
self.uploader.deinit();
|
||||||
self.dynMeshes.deinit(self.allocator);
|
self.dynMeshes.deinit(self.allocator);
|
||||||
self.allocator.destroy(self);
|
self.allocator.destroy(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addDynamicMesh(self: *@This(), dynamicMesh: *DynamicMesh) !void {
|
pub fn addDynamicMesh(self: *@This(), dynamicMesh: *DynamicMesh) !void {
|
||||||
try self.dynMeshes.append(self.allocator, dynamicMesh);
|
try self.dynMeshes.append(self.allocator, dynamicMesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn updateMeshes(self: *@This(), cmd: vk.CommandBuffer) !void {
|
pub fn updateMeshes(self: *@This(), cmd: vk.CommandBuffer) !void {
|
||||||
for (self.dynMeshes.items) |dynMesh| {
|
for (self.dynMeshes.items) |dynMesh| {
|
||||||
try dynMesh.maybeUpdateVertices(cmd);
|
try dynMesh.maybeUpdateVertices(cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn finishUpload(self: *@This()) !void {
|
pub fn finishUpload(self: *@This()) !void {
|
||||||
if (self.uploader.isActive) {
|
if (self.uploader.isActive) {
|
||||||
var t3 = core.tracy.ZoneN(@src(), "finishing dynamic mesh upload context");
|
var t3 = core.tracy.ZoneN(@src(), "finishing dynamic mesh upload context");
|
||||||
defer t3.End();
|
defer t3.End();
|
||||||
|
|
||||||
try self.uploader.waitForFences();
|
try self.uploader.waitForFences();
|
||||||
|
|
||||||
for (self.dynMeshes.items) |dynMesh| {
|
for (self.dynMeshes.items) |dynMesh| {
|
||||||
if (dynMesh.isDirty) {
|
if (dynMesh.isDirty) {
|
||||||
dynMesh.bumpSwapId();
|
dynMesh.bumpSwapId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const DynamicMesh = struct {
|
pub const DynamicMesh = struct {
|
||||||
pub const GeometryMode = enum { quads, triangles };
|
pub const GeometryMode = enum { quads, triangles };
|
||||||
|
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
gc: *NeonVkContext,
|
gc: *NeonVkContext,
|
||||||
|
|
||||||
vertices: []MeshVertex = undefined,
|
vertices: []MeshVertex = undefined,
|
||||||
geometryMode: GeometryMode = .quads, // geometry elaboration mode
|
geometryMode: GeometryMode = .quads, // geometry elaboration mode
|
||||||
indicesMaxCount: u32 = 0,
|
indicesMaxCount: u32 = 0,
|
||||||
|
|
||||||
indexBuffers: [2]NeonVkBuffer = undefined,
|
indexBuffers: [2]NeonVkBuffer = undefined,
|
||||||
indexBufferLen: [2]u32 = .{ 0, 0 },
|
indexBufferLen: [2]u32 = .{ 0, 0 },
|
||||||
|
|
||||||
vertexBuffers: [2]NeonVkBuffer = undefined,
|
vertexBuffers: [2]NeonVkBuffer = undefined,
|
||||||
vertexBufferLen: [2]u32 = .{ 0, 0 },
|
vertexBufferLen: [2]u32 = .{ 0, 0 },
|
||||||
|
|
||||||
swapId: usize = 0, // the index of the previously uploaded vertex buffer
|
swapId: usize = 0, // the index of the previously uploaded vertex buffer
|
||||||
vertexCount: u32 = 0, //
|
vertexCount: u32 = 0, //
|
||||||
|
|
||||||
stagingVertexBuffer: NeonVkBuffer = undefined,
|
stagingVertexBuffer: NeonVkBuffer = undefined,
|
||||||
stagingIndexBuffer: NeonVkBuffer = undefined,
|
stagingIndexBuffer: NeonVkBuffer = undefined,
|
||||||
|
|
||||||
isDirty: bool = true,
|
isDirty: bool = true,
|
||||||
|
|
||||||
maxVertexCount: u32,
|
maxVertexCount: u32,
|
||||||
|
|
||||||
pub fn init(gc: *NeonVkContext, allocator: std.mem.Allocator, opts: struct {
|
pub fn init(gc: *NeonVkContext, allocator: std.mem.Allocator, opts: struct {
|
||||||
maxVertexCount: u32 = 4096,
|
maxVertexCount: u32 = 4096,
|
||||||
maxIndexCount: u32 = 4096 * 6 / 4,
|
maxIndexCount: u32 = 4096 * 6 / 4,
|
||||||
mode: GeometryMode = .quads,
|
mode: GeometryMode = .quads,
|
||||||
}) !*@This() {
|
}) !*@This() {
|
||||||
var self = try allocator.create(@This());
|
var self = try allocator.create(@This());
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.maxVertexCount = opts.maxVertexCount,
|
.maxVertexCount = opts.maxVertexCount,
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.vertices = try allocator.alloc(MeshVertex, opts.maxVertexCount),
|
.vertices = try allocator.alloc(MeshVertex, opts.maxVertexCount),
|
||||||
.gc = gc,
|
.gc = gc,
|
||||||
.geometryMode = opts.mode,
|
.geometryMode = opts.mode,
|
||||||
};
|
};
|
||||||
|
|
||||||
try gc.dynamicMeshManager.addDynamicMesh(self);
|
try gc.dynamicMeshManager.addDynamicMesh(self);
|
||||||
|
|
||||||
self.allocator = allocator;
|
self.allocator = allocator;
|
||||||
self.gc = gc;
|
self.gc = gc;
|
||||||
|
|
||||||
{
|
{
|
||||||
self.stagingIndexBuffer = try gc.vkAllocator.createStagingBuffer(opts.maxIndexCount * @sizeOf(u32), "DynamicMesh.init - index staging");
|
self.stagingIndexBuffer = try gc.vkAllocator.createStagingBuffer(opts.maxIndexCount * @sizeOf(u32), "DynamicMesh.init - index staging");
|
||||||
self.stagingVertexBuffer = try gc.vkAllocator.createStagingBuffer(opts.maxVertexCount * @sizeOf(MeshVertex), "DynamicMesh.init - vertex staging");
|
self.stagingVertexBuffer = try gc.vkAllocator.createStagingBuffer(opts.maxVertexCount * @sizeOf(MeshVertex), "DynamicMesh.init - vertex staging");
|
||||||
|
|
||||||
inline for (0..2) |i| {
|
inline for (0..2) |i| {
|
||||||
self.indexBuffers[i] = try gc.vkAllocator.createGpuBuffer(opts.maxIndexCount * @sizeOf(u32), .{
|
self.indexBuffers[i] = try gc.vkAllocator.createGpuBuffer(opts.maxIndexCount * @sizeOf(u32), .{
|
||||||
.index_buffer_bit = true,
|
.index_buffer_bit = true,
|
||||||
}, "DynamicMesh.init - gpu indexBuffer" ++ std.fmt.comptimePrint("[{d}]", .{i}));
|
}, "DynamicMesh.init - gpu indexBuffer" ++ std.fmt.comptimePrint("[{d}]", .{i}));
|
||||||
|
|
||||||
self.vertexBuffers[i] = try gc.vkAllocator.createGpuBuffer(opts.maxVertexCount * @sizeOf(MeshVertex), .{
|
self.vertexBuffers[i] = try gc.vkAllocator.createGpuBuffer(opts.maxVertexCount * @sizeOf(MeshVertex), .{
|
||||||
.vertex_buffer_bit = true,
|
.vertex_buffer_bit = true,
|
||||||
}, "DynamicMesh.init - gpu vertexBuffer" ++ std.fmt.comptimePrint("[{d}]", .{i}));
|
}, "DynamicMesh.init - gpu vertexBuffer" ++ std.fmt.comptimePrint("[{d}]", .{i}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getIndexBuffer(self: *@This()) NeonVkBuffer {
|
pub fn getIndexBuffer(self: *@This()) NeonVkBuffer {
|
||||||
return self.indexBuffers[self.swapId];
|
return self.indexBuffers[self.swapId];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getVertexBuffer(self: *@This()) NeonVkBuffer {
|
pub fn getVertexBuffer(self: *@This()) NeonVkBuffer {
|
||||||
return self.vertexBuffers[self.swapId];
|
return self.vertexBuffers[self.swapId];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getIndexBufferLen(self: *@This()) u32 {
|
pub fn getIndexBufferLen(self: *@This()) u32 {
|
||||||
return self.indexBufferLen[self.swapId];
|
return self.indexBufferLen[self.swapId];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getVertexBufferLen(self: *@This()) u32 {
|
pub fn getVertexBufferLen(self: *@This()) u32 {
|
||||||
return self.vertexBufferLen[self.swapId];
|
return self.vertexBufferLen[self.swapId];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn maybeUpdateVertices(self: *@This(), cmd: vk.CommandBuffer) !void {
|
pub fn maybeUpdateVertices(self: *@This(), cmd: vk.CommandBuffer) !void {
|
||||||
if (!self.isDirty) {
|
if (!self.isDirty) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var t1 = core.tracy.ZoneN(@src(), "Dynamic Mesh upload with barriers");
|
var t1 = core.tracy.ZoneN(@src(), "Dynamic Mesh upload with barriers");
|
||||||
defer t1.End();
|
defer t1.End();
|
||||||
self.isDirty = false;
|
self.isDirty = false;
|
||||||
|
|
||||||
try self.stageDirtyVertices();
|
try self.stageDirtyVertices();
|
||||||
if (self.indexBufferLen[self.swapId] == 0 or self.vertexCount == 0) {
|
if (self.indexBufferLen[self.swapId] == 0 or self.vertexCount == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var vkd = self.gc.vkd;
|
var vkd = self.gc.vkd;
|
||||||
|
|
||||||
var copy = vk.BufferCopy{
|
var copy = vk.BufferCopy{
|
||||||
.dst_offset = 0,
|
.dst_offset = 0,
|
||||||
.src_offset = 0,
|
.src_offset = 0,
|
||||||
.size = self.indexBufferLen[self.swapId] * @as(u32, @intCast(@sizeOf(u32))),
|
.size = self.indexBufferLen[self.swapId] * @as(u32, @intCast(@sizeOf(u32))),
|
||||||
};
|
};
|
||||||
|
|
||||||
// submit index Buffer
|
// submit index Buffer
|
||||||
self.gc.vkd.cmdCopyBuffer(
|
self.gc.vkd.cmdCopyBuffer(
|
||||||
cmd,
|
cmd,
|
||||||
self.stagingIndexBuffer.buffer,
|
self.stagingIndexBuffer.buffer,
|
||||||
self.indexBuffers[self.swapId].buffer,
|
self.indexBuffers[self.swapId].buffer,
|
||||||
1,
|
1,
|
||||||
@as([*]const vk.BufferCopy, @ptrCast(©)),
|
@as([*]const vk.BufferCopy, @ptrCast(©)),
|
||||||
);
|
);
|
||||||
|
|
||||||
var indexMemoryBarrier = vk.BufferMemoryBarrier{
|
var indexMemoryBarrier = vk.BufferMemoryBarrier{
|
||||||
.buffer = self.indexBuffers[self.swapId].buffer,
|
.buffer = self.indexBuffers[self.swapId].buffer,
|
||||||
.src_access_mask = .{ .transfer_read_bit = true },
|
.src_access_mask = .{ .transfer_read_bit = true },
|
||||||
.dst_access_mask = .{ .index_read_bit = true },
|
.dst_access_mask = .{ .index_read_bit = true },
|
||||||
.src_queue_family_index = 0,
|
.src_queue_family_index = 0,
|
||||||
.dst_queue_family_index = 0,
|
.dst_queue_family_index = 0,
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
.size = copy.size,
|
.size = copy.size,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Insert Barrier for indexBuffer
|
// Insert Barrier for indexBuffer
|
||||||
vkd.cmdPipelineBarrier(
|
vkd.cmdPipelineBarrier(
|
||||||
cmd,
|
cmd,
|
||||||
.{ .transfer_bit = true },
|
.{ .transfer_bit = true },
|
||||||
.{ .vertex_input_bit = true },
|
.{ .vertex_input_bit = true },
|
||||||
.{},
|
.{},
|
||||||
0,
|
0,
|
||||||
undefined,
|
undefined,
|
||||||
1,
|
1,
|
||||||
@ptrCast(&indexMemoryBarrier),
|
@ptrCast(&indexMemoryBarrier),
|
||||||
0,
|
0,
|
||||||
undefined,
|
undefined,
|
||||||
);
|
);
|
||||||
|
|
||||||
copy.size = self.vertexCount * @as(u32, @intCast(@sizeOf(MeshVertex)));
|
copy.size = self.vertexCount * @as(u32, @intCast(@sizeOf(MeshVertex)));
|
||||||
|
|
||||||
// submit vertex Buffer
|
// submit vertex Buffer
|
||||||
self.gc.vkd.cmdCopyBuffer(
|
self.gc.vkd.cmdCopyBuffer(
|
||||||
cmd,
|
cmd,
|
||||||
self.stagingVertexBuffer.buffer,
|
self.stagingVertexBuffer.buffer,
|
||||||
self.vertexBuffers[self.swapId].buffer,
|
self.vertexBuffers[self.swapId].buffer,
|
||||||
1,
|
1,
|
||||||
@as([*]const vk.BufferCopy, @ptrCast(©)),
|
@as([*]const vk.BufferCopy, @ptrCast(©)),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Insert Barrier for vertexBuffer
|
// Insert Barrier for vertexBuffer
|
||||||
var vertexMemoryBarrier = vk.BufferMemoryBarrier{
|
var vertexMemoryBarrier = vk.BufferMemoryBarrier{
|
||||||
.buffer = self.vertexBuffers[self.swapId].buffer,
|
.buffer = self.vertexBuffers[self.swapId].buffer,
|
||||||
.src_access_mask = .{
|
.src_access_mask = .{
|
||||||
.transfer_read_bit = true,
|
.transfer_read_bit = true,
|
||||||
},
|
},
|
||||||
.dst_access_mask = .{
|
.dst_access_mask = .{
|
||||||
// .transfer_write_bit = true,
|
// .transfer_write_bit = true,
|
||||||
.vertex_attribute_read_bit = true,
|
.vertex_attribute_read_bit = true,
|
||||||
},
|
},
|
||||||
.src_queue_family_index = 0,
|
.src_queue_family_index = 0,
|
||||||
.dst_queue_family_index = 0,
|
.dst_queue_family_index = 0,
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
.size = copy.size,
|
.size = copy.size,
|
||||||
};
|
};
|
||||||
|
|
||||||
vkd.cmdPipelineBarrier(
|
vkd.cmdPipelineBarrier(
|
||||||
cmd,
|
cmd,
|
||||||
.{ .transfer_bit = true },
|
.{ .transfer_bit = true },
|
||||||
.{ .vertex_input_bit = true },
|
.{ .vertex_input_bit = true },
|
||||||
.{},
|
.{},
|
||||||
0,
|
0,
|
||||||
undefined,
|
undefined,
|
||||||
1,
|
1,
|
||||||
@ptrCast(&vertexMemoryBarrier),
|
@ptrCast(&vertexMemoryBarrier),
|
||||||
0,
|
0,
|
||||||
undefined,
|
undefined,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stageDirtyVertices(self: *@This()) !void {
|
pub fn stageDirtyVertices(self: *@This()) !void {
|
||||||
const newSwapId = (self.swapId + 1) % 2;
|
const newSwapId = (self.swapId + 1) % 2;
|
||||||
// map buffers
|
// map buffers
|
||||||
|
|
||||||
var slice = try self.gc.vkAllocator.mapMemorySlice(MeshVertex, self.stagingVertexBuffer, self.vertices.len);
|
var slice = try self.gc.vkAllocator.mapMemorySlice(MeshVertex, self.stagingVertexBuffer, self.vertices.len);
|
||||||
var indexSlice = try self.gc.vkAllocator.mapMemorySlice(u32, self.stagingIndexBuffer, self.vertices.len * 6 / 4);
|
var indexSlice = try self.gc.vkAllocator.mapMemorySlice(u32, self.stagingIndexBuffer, self.vertices.len * 6 / 4);
|
||||||
|
|
||||||
defer self.gc.vkAllocator.unmapMemory(self.stagingVertexBuffer);
|
defer self.gc.vkAllocator.unmapMemory(self.stagingVertexBuffer);
|
||||||
defer self.gc.vkAllocator.unmapMemory(self.stagingIndexBuffer);
|
defer self.gc.vkAllocator.unmapMemory(self.stagingIndexBuffer);
|
||||||
|
|
||||||
// copy over vertices to mapped buffer
|
// copy over vertices to mapped buffer
|
||||||
for (0..self.vertexCount) |i| {
|
for (0..self.vertexCount) |i| {
|
||||||
slice[i] = self.vertices[i];
|
slice[i] = self.vertices[i];
|
||||||
}
|
}
|
||||||
self.vertexBufferLen[newSwapId] = self.vertexCount;
|
self.vertexBufferLen[newSwapId] = self.vertexCount;
|
||||||
|
|
||||||
// interpret vertices as quads.
|
// interpret vertices as quads.
|
||||||
if (self.geometryMode == .quads) {
|
if (self.geometryMode == .quads) {
|
||||||
var index: u32 = 0;
|
var index: u32 = 0;
|
||||||
var vertex: u32 = 0;
|
var vertex: u32 = 0;
|
||||||
while (vertex < self.vertexCount) {
|
while (vertex < self.vertexCount) {
|
||||||
indexSlice[index + 0] = vertex + 0;
|
indexSlice[index + 0] = vertex + 0;
|
||||||
indexSlice[index + 1] = vertex + 1;
|
indexSlice[index + 1] = vertex + 1;
|
||||||
indexSlice[index + 2] = vertex + 2;
|
indexSlice[index + 2] = vertex + 2;
|
||||||
|
|
||||||
indexSlice[index + 3] = vertex + 2;
|
indexSlice[index + 3] = vertex + 2;
|
||||||
indexSlice[index + 4] = vertex + 3;
|
indexSlice[index + 4] = vertex + 3;
|
||||||
indexSlice[index + 5] = vertex + 0;
|
indexSlice[index + 5] = vertex + 0;
|
||||||
|
|
||||||
vertex += 4;
|
vertex += 4;
|
||||||
index += 6;
|
index += 6;
|
||||||
}
|
}
|
||||||
self.indexBufferLen[newSwapId] = index;
|
self.indexBufferLen[newSwapId] = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.swapId = newSwapId;
|
self.swapId = newSwapId;
|
||||||
}
|
}
|
||||||
|
|
||||||
// a stream-like interface for creating vertices
|
// a stream-like interface for creating vertices
|
||||||
// pub fn uploadVertices(self: *@This(), uploader: *NeonVkUploader) !void {
|
// pub fn uploadVertices(self: *@This(), uploader: *NeonVkUploader) !void {
|
||||||
// if (!self.isDirty) {
|
// if (!self.isDirty) {
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// self.dirty = false;
|
// self.dirty = false;
|
||||||
|
|
||||||
// const newSwapId = (self.swapId + 1) % 2;
|
// const newSwapId = (self.swapId + 1) % 2;
|
||||||
// // map buffers
|
// // map buffers
|
||||||
|
|
||||||
// var slice = try self.gc.vkAllocator.mapMemorySlice(MeshVertex, self.stagingVertexBuffer, self.vertices.len);
|
// var slice = try self.gc.vkAllocator.mapMemorySlice(MeshVertex, self.stagingVertexBuffer, self.vertices.len);
|
||||||
// var indexSlice = try self.gc.vkAllocator.mapMemorySlice(u32, self.stagingIndexBuffer, self.vertices.len * 6 / 4);
|
// var indexSlice = try self.gc.vkAllocator.mapMemorySlice(u32, self.stagingIndexBuffer, self.vertices.len * 6 / 4);
|
||||||
|
|
||||||
// defer self.gc.vkAllocator.unmapMemory(self.stagingVertexBuffer);
|
// defer self.gc.vkAllocator.unmapMemory(self.stagingVertexBuffer);
|
||||||
// defer self.gc.vkAllocator.unmapMemory(self.stagingIndexBuffer);
|
// defer self.gc.vkAllocator.unmapMemory(self.stagingIndexBuffer);
|
||||||
|
|
||||||
// // copy over vertices to mapped buffer
|
// // copy over vertices to mapped buffer
|
||||||
// // so... this right here would need to lock.. actually this would be a try-lock
|
// // so... this right here would need to lock.. actually this would be a try-lock
|
||||||
// // if we fail to lock it... that's ok. we can just try again at the end of the frame.
|
// // if we fail to lock it... that's ok. we can just try again at the end of the frame.
|
||||||
// // what happens if we always fail to lock it?
|
// // what happens if we always fail to lock it?
|
||||||
|
|
||||||
// for (0..self.vertexCount) |i| {
|
// for (0..self.vertexCount) |i| {
|
||||||
// slice[i] = self.vertices[i];
|
// slice[i] = self.vertices[i];
|
||||||
// }
|
// }
|
||||||
// self.vertexBufferLen[newSwapId] = self.vertexCount;
|
// self.vertexBufferLen[newSwapId] = self.vertexCount;
|
||||||
|
|
||||||
// // interpret vertices as quads.
|
// // interpret vertices as quads.
|
||||||
// if (self.geometryMode == .quads) {
|
// if (self.geometryMode == .quads) {
|
||||||
// var index: u32 = 0;
|
// var index: u32 = 0;
|
||||||
// var vertex: u32 = 0;
|
// var vertex: u32 = 0;
|
||||||
// while (vertex < self.vertexCount) {
|
// while (vertex < self.vertexCount) {
|
||||||
// indexSlice[index + 0] = vertex + 0;
|
// indexSlice[index + 0] = vertex + 0;
|
||||||
// indexSlice[index + 1] = vertex + 1;
|
// indexSlice[index + 1] = vertex + 1;
|
||||||
// indexSlice[index + 2] = vertex + 2;
|
// indexSlice[index + 2] = vertex + 2;
|
||||||
|
|
||||||
// indexSlice[index + 3] = vertex + 2;
|
// indexSlice[index + 3] = vertex + 2;
|
||||||
// indexSlice[index + 4] = vertex + 3;
|
// indexSlice[index + 4] = vertex + 3;
|
||||||
// indexSlice[index + 5] = vertex + 0;
|
// indexSlice[index + 5] = vertex + 0;
|
||||||
|
|
||||||
// vertex += 4;
|
// vertex += 4;
|
||||||
// index += 6;
|
// index += 6;
|
||||||
// }
|
// }
|
||||||
// self.indexBufferLen[newSwapId] = index;
|
// self.indexBufferLen[newSwapId] = index;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// // upload index and vertex buffers
|
// // upload index and vertex buffers
|
||||||
// try uploader.addBufferUpload(
|
// try uploader.addBufferUpload(
|
||||||
// self.stagingIndexBuffer,
|
// self.stagingIndexBuffer,
|
||||||
// self.indexBuffers[newSwapId],
|
// self.indexBuffers[newSwapId],
|
||||||
// self.indexBufferLen[newSwapId] * @as(u32, @intCast(@sizeOf(u32))),
|
// self.indexBufferLen[newSwapId] * @as(u32, @intCast(@sizeOf(u32))),
|
||||||
// );
|
// );
|
||||||
|
|
||||||
// try uploader.addBufferUpload(
|
// try uploader.addBufferUpload(
|
||||||
// self.stagingVertexBuffer,
|
// self.stagingVertexBuffer,
|
||||||
// self.vertexBuffers[newSwapId],
|
// self.vertexBuffers[newSwapId],
|
||||||
// self.vertexCount * @as(u32, @intCast(@sizeOf(MeshVertex))),
|
// self.vertexCount * @as(u32, @intCast(@sizeOf(MeshVertex))),
|
||||||
// );
|
// );
|
||||||
// }
|
// }
|
||||||
|
|
||||||
pub fn bumpSwapId(self: *@This()) void {
|
pub fn bumpSwapId(self: *@This()) void {
|
||||||
self.swapId = (self.swapId + 1) % 2;
|
self.swapId = (self.swapId + 1) % 2;
|
||||||
self.isDirty = false;
|
self.isDirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clearVertices(self: *@This()) void {
|
pub fn clearVertices(self: *@This()) void {
|
||||||
self.vertexCount = 0;
|
self.vertexCount = 0;
|
||||||
self.isDirty = true;
|
self.isDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addVertexList(self: *@This(), list: []const MeshVertex) void {
|
pub fn addVertexList(self: *@This(), list: []const MeshVertex) void {
|
||||||
if (list.len > 0) {
|
if (list.len > 0) {
|
||||||
self.isDirty = true;
|
self.isDirty = true;
|
||||||
}
|
}
|
||||||
for (list) |v| {
|
for (list) |v| {
|
||||||
self.vertices[self.vertexCount] = v;
|
self.vertices[self.vertexCount] = v;
|
||||||
self.vertexCount += 1;
|
self.vertexCount += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// adds a quad only in the X and y Space,
|
// adds a quad only in the X and y Space,
|
||||||
pub fn addQuad2D(
|
pub fn addQuad2D(
|
||||||
self: *@This(),
|
self: *@This(),
|
||||||
_topLeft: core.Vectorf, // only x and y is considered
|
_topLeft: core.Vectorf, // only x and y is considered
|
||||||
_size: core.Vectorf, // only x and y is considered
|
_size: core.Vectorf, // only x and y is considered
|
||||||
topLeftUV: core.Vector2f,
|
topLeftUV: core.Vector2f,
|
||||||
uvSize: core.Vector2f,
|
uvSize: core.Vector2f,
|
||||||
color: LinearColor,
|
color: LinearColor,
|
||||||
) void {
|
) void {
|
||||||
var topLeft = _topLeft;
|
var topLeft = _topLeft;
|
||||||
var size = _size;
|
var size = _size;
|
||||||
|
|
||||||
topLeft.z = 0;
|
topLeft.z = 0;
|
||||||
size.z = 0;
|
size.z = 0;
|
||||||
|
|
||||||
const normal = Vectorf{ .x = 0, .y = 0, .z = -1 };
|
const normal = Vectorf{ .x = 0, .y = 0, .z = -1 };
|
||||||
|
|
||||||
var vertices: [4]MeshVertex = undefined;
|
var vertices: [4]MeshVertex = undefined;
|
||||||
|
|
||||||
vertices[0] = .{
|
vertices[0] = .{
|
||||||
.position = topLeft,
|
.position = topLeft,
|
||||||
.normal = normal,
|
.normal = normal,
|
||||||
.uv = topLeftUV,
|
.uv = topLeftUV,
|
||||||
.color = color,
|
.color = color,
|
||||||
};
|
};
|
||||||
|
|
||||||
vertices[1] = .{
|
vertices[1] = .{
|
||||||
.position = topLeft.add(.{ .x = size.x }),
|
.position = topLeft.add(.{ .x = size.x }),
|
||||||
.normal = normal,
|
.normal = normal,
|
||||||
.uv = topLeftUV.add(core.Vector2f{ .x = uvSize.x }),
|
.uv = topLeftUV.add(core.Vector2f{ .x = uvSize.x }),
|
||||||
.color = color,
|
.color = color,
|
||||||
};
|
};
|
||||||
|
|
||||||
vertices[2] = .{
|
vertices[2] = .{
|
||||||
.position = topLeft.add(size),
|
.position = topLeft.add(size),
|
||||||
.normal = normal,
|
.normal = normal,
|
||||||
.uv = topLeftUV.add(uvSize),
|
.uv = topLeftUV.add(uvSize),
|
||||||
.color = color,
|
.color = color,
|
||||||
};
|
};
|
||||||
|
|
||||||
vertices[3] = .{
|
vertices[3] = .{
|
||||||
.position = topLeft.add(.{ .y = size.y }),
|
.position = topLeft.add(.{ .y = size.y }),
|
||||||
.normal = normal,
|
.normal = normal,
|
||||||
.uv = topLeftUV.add(core.Vector2f{ .y = uvSize.y }),
|
.uv = topLeftUV.add(core.Vector2f{ .y = uvSize.y }),
|
||||||
.color = color,
|
.color = color,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.addVertexList(&vertices);
|
self.addVertexList(&vertices);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *@This()) void {
|
pub fn deinit(self: *@This()) void {
|
||||||
self.allocator.free(self.vertices);
|
self.allocator.free(self.vertices);
|
||||||
|
|
||||||
const vkAllocator = self.gc.vkAllocator;
|
const vkAllocator = self.gc.vkAllocator;
|
||||||
|
|
||||||
self.stagingVertexBuffer.deinit(vkAllocator);
|
self.stagingVertexBuffer.deinit(vkAllocator);
|
||||||
self.stagingIndexBuffer.deinit(vkAllocator);
|
self.stagingIndexBuffer.deinit(vkAllocator);
|
||||||
|
|
||||||
for (0..self.indexBuffers.len) |i| {
|
for (0..self.indexBuffers.len) |i| {
|
||||||
self.indexBuffers[i].deinit(vkAllocator);
|
self.indexBuffers[i].deinit(vkAllocator);
|
||||||
self.vertexBuffers[i].deinit(vkAllocator);
|
self.vertexBuffers[i].deinit(vkAllocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.allocator.destroy(self);
|
self.allocator.destroy(self);
|
||||||
// should remove ourselves from the manager
|
// should remove ourselves from the manager
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,174 +1,174 @@
|
||||||
pub fn MakeCubeMapList(
|
pub fn MakeCubeMapList(
|
||||||
comptime left: []const u8,
|
comptime left: []const u8,
|
||||||
comptime up: []const u8,
|
comptime up: []const u8,
|
||||||
comptime down: []const u8,
|
comptime down: []const u8,
|
||||||
comptime front: []const u8,
|
comptime front: []const u8,
|
||||||
comptime back: []const u8,
|
comptime back: []const u8,
|
||||||
) []const []const u8 {
|
) []const []const u8 {
|
||||||
return &.{
|
return &.{
|
||||||
left,
|
left,
|
||||||
up,
|
up,
|
||||||
down,
|
down,
|
||||||
front,
|
front,
|
||||||
back,
|
back,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const CubeMapDirs = enum(u8) {
|
pub const CubeMapDirs = enum(u8) {
|
||||||
right,
|
right,
|
||||||
left,
|
left,
|
||||||
up,
|
up,
|
||||||
down,
|
down,
|
||||||
front,
|
front,
|
||||||
back,
|
back,
|
||||||
};
|
};
|
||||||
|
|
||||||
const vk_utils = @import("../vk_utils.zig");
|
const vk_utils = @import("../vk_utils.zig");
|
||||||
const LoadAndStageImage = vk_utils.LoadAndStageImage;
|
const LoadAndStageImage = vk_utils.LoadAndStageImage;
|
||||||
|
|
||||||
pub fn stageCubeTexture(list: []const []const u8) !LoadAndStageImage {
|
pub fn stageCubeTexture(list: []const []const u8) !LoadAndStageImage {
|
||||||
try core.assert(list.len == 6);
|
try core.assert(list.len == 6);
|
||||||
|
|
||||||
const gc = graphics.getContext();
|
const gc = graphics.getContext();
|
||||||
const allocator = gc.allocator;
|
const allocator = gc.allocator;
|
||||||
|
|
||||||
var pngs: [6]core.png.PngContents = undefined;
|
var pngs: [6]core.png.PngContents = undefined;
|
||||||
|
|
||||||
for (0..6) |i| {
|
for (0..6) |i| {
|
||||||
pngs[i] = try core.png.PngContents.initFromPathSpec(list[i], allocator);
|
pngs[i] = try core.png.PngContents.initFromPathSpec(list[i], allocator);
|
||||||
}
|
}
|
||||||
defer {
|
defer {
|
||||||
for (&pngs) |*png| {
|
for (&pngs) |*png| {
|
||||||
png.deinit();
|
png.deinit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const width = pngs[0].size.x;
|
const width = pngs[0].size.x;
|
||||||
const height = pngs[0].size.y;
|
const height = pngs[0].size.y;
|
||||||
try core.assert(width == height);
|
try core.assert(width == height);
|
||||||
core.engine_log("cubemap dimensionss {d}x{d}", .{ width, height });
|
core.engine_log("cubemap dimensionss {d}x{d}", .{ width, height });
|
||||||
|
|
||||||
var totalLen: u32 = 0;
|
var totalLen: u32 = 0;
|
||||||
for (pngs) |png| {
|
for (pngs) |png| {
|
||||||
try core.assertf(width == png.size.x, "inconsistent cubemap dimensions", .{});
|
try core.assertf(width == png.size.x, "inconsistent cubemap dimensions", .{});
|
||||||
try core.assertf(height == png.size.y, "inconsistent cubemap dimensions", .{});
|
try core.assertf(height == png.size.y, "inconsistent cubemap dimensions", .{});
|
||||||
totalLen += @intCast(png.pixels.len);
|
totalLen += @intCast(png.pixels.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
const stagingBuffer = try gc.vkAllocator.createStagingBuffer(totalLen, "cubemap creation staging texture map");
|
const stagingBuffer = try gc.vkAllocator.createStagingBuffer(totalLen, "cubemap creation staging texture map");
|
||||||
const pixelBuffer = try gc.vkAllocator.mapBuffer(u8, stagingBuffer);
|
const pixelBuffer = try gc.vkAllocator.mapBuffer(u8, stagingBuffer);
|
||||||
|
|
||||||
var offset: u32 = 0;
|
var offset: u32 = 0;
|
||||||
|
|
||||||
var bufferOffsets: [6]u32 = undefined;
|
var bufferOffsets: [6]u32 = undefined;
|
||||||
for (pngs, 0..) |png, i| {
|
for (pngs, 0..) |png, i| {
|
||||||
const dest = pixelBuffer[offset .. offset + png.pixels.len];
|
const dest = pixelBuffer[offset .. offset + png.pixels.len];
|
||||||
bufferOffsets[i] = offset;
|
bufferOffsets[i] = offset;
|
||||||
offset += @intCast(png.pixels.len);
|
offset += @intCast(png.pixels.len);
|
||||||
@memcpy(dest, png.pixels);
|
@memcpy(dest, png.pixels);
|
||||||
}
|
}
|
||||||
|
|
||||||
const imageExtent = vk.Extent3D{
|
const imageExtent = vk.Extent3D{
|
||||||
.width = @as(u32, @intCast(width)),
|
.width = @as(u32, @intCast(width)),
|
||||||
.height = @as(u32, @intCast(height)),
|
.height = @as(u32, @intCast(height)),
|
||||||
.depth = 1,
|
.depth = 1,
|
||||||
};
|
};
|
||||||
//const mipLevel = std.math.log2(@max(imageExtent.width, imageExtent.height)) + 1;
|
//const mipLevel = std.math.log2(@max(imageExtent.width, imageExtent.height)) + 1;
|
||||||
const mipLevel = 1;
|
const mipLevel = 1;
|
||||||
|
|
||||||
var imgCreateInfo = vkinit.imageCreateInfo(.r8g8b8a8_srgb, .{
|
var imgCreateInfo = vkinit.imageCreateInfo(.r8g8b8a8_srgb, .{
|
||||||
.sampled_bit = true,
|
.sampled_bit = true,
|
||||||
.transfer_dst_bit = true,
|
.transfer_dst_bit = true,
|
||||||
}, imageExtent, mipLevel);
|
}, imageExtent, mipLevel);
|
||||||
imgCreateInfo.array_layers = 6;
|
imgCreateInfo.array_layers = 6;
|
||||||
imgCreateInfo.flags.cube_compatible_bit = true;
|
imgCreateInfo.flags.cube_compatible_bit = true;
|
||||||
|
|
||||||
if (mipLevel > 1) {
|
if (mipLevel > 1) {
|
||||||
imgCreateInfo.usage.transfer_src_bit = true;
|
imgCreateInfo.usage.transfer_src_bit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const imgAllocInfo = vma.AllocationCreateInfo{
|
const imgAllocInfo = vma.AllocationCreateInfo{
|
||||||
.requiredFlags = .{},
|
.requiredFlags = .{},
|
||||||
.usage = .gpuOnly,
|
.usage = .gpuOnly,
|
||||||
};
|
};
|
||||||
const newImage = try gc.vkAllocator.createImage(imgCreateInfo, imgAllocInfo, "cubemap creation image");
|
const newImage = try gc.vkAllocator.createImage(imgCreateInfo, imgAllocInfo, "cubemap creation image");
|
||||||
|
|
||||||
gc.vkAllocator.unmapMemory(stagingBuffer);
|
gc.vkAllocator.unmapMemory(stagingBuffer);
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.stagingBuffer = stagingBuffer,
|
.stagingBuffer = stagingBuffer,
|
||||||
.image = newImage,
|
.image = newImage,
|
||||||
.mipLevel = mipLevel,
|
.mipLevel = mipLevel,
|
||||||
.cubeOffsets = bufferOffsets,
|
.cubeOffsets = bufferOffsets,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn submitTextureCube(uploader: *vk_utils.NeonVkUploader, state: *const LoadAndStageImage) !void {
|
pub fn submitTextureCube(uploader: *vk_utils.NeonVkUploader, state: *const LoadAndStageImage) !void {
|
||||||
try core.assert(state.cubeOffsets != null);
|
try core.assert(state.cubeOffsets != null);
|
||||||
|
|
||||||
if (state.cubeOffsets) |cubeOffsets| {
|
if (state.cubeOffsets) |cubeOffsets| {
|
||||||
try uploader.startUploadContext();
|
try uploader.startUploadContext();
|
||||||
{
|
{
|
||||||
const newImage = state.image;
|
const newImage = state.image;
|
||||||
const mipLevel = state.mipLevel;
|
const mipLevel = state.mipLevel;
|
||||||
const cmd = uploader.commandBuffer;
|
const cmd = uploader.commandBuffer;
|
||||||
transitions.into_transferDst(cmd, newImage.image, mipLevel, 0, 6);
|
transitions.into_transferDst(cmd, newImage.image, mipLevel, 0, 6);
|
||||||
for (cubeOffsets, 0..) |offset, face| {
|
for (cubeOffsets, 0..) |offset, face| {
|
||||||
var copyRegion = vk.BufferImageCopy{
|
var copyRegion = vk.BufferImageCopy{
|
||||||
.buffer_offset = offset,
|
.buffer_offset = offset,
|
||||||
.buffer_row_length = 0,
|
.buffer_row_length = 0,
|
||||||
.buffer_image_height = 0,
|
.buffer_image_height = 0,
|
||||||
.image_offset = std.mem.zeroes(vk.Offset3D),
|
.image_offset = std.mem.zeroes(vk.Offset3D),
|
||||||
.image_subresource = .{
|
.image_subresource = .{
|
||||||
.aspect_mask = .{ .color_bit = true },
|
.aspect_mask = .{ .color_bit = true },
|
||||||
.mip_level = 0,
|
.mip_level = 0,
|
||||||
.base_array_layer = @intCast(face),
|
.base_array_layer = @intCast(face),
|
||||||
.layer_count = 1,
|
.layer_count = 1,
|
||||||
},
|
},
|
||||||
.image_extent = .{
|
.image_extent = .{
|
||||||
.width = newImage.pixelWidth,
|
.width = newImage.pixelWidth,
|
||||||
.height = newImage.pixelHeight,
|
.height = newImage.pixelHeight,
|
||||||
.depth = 1,
|
.depth = 1,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
vkd.cmdCopyBufferToImage(
|
vkd.cmdCopyBufferToImage(
|
||||||
cmd,
|
cmd,
|
||||||
state.stagingBuffer.buffer,
|
state.stagingBuffer.buffer,
|
||||||
newImage.image,
|
newImage.image,
|
||||||
.transfer_dst_optimal,
|
.transfer_dst_optimal,
|
||||||
1,
|
1,
|
||||||
@ptrCast(©Region),
|
@ptrCast(©Region),
|
||||||
);
|
);
|
||||||
|
|
||||||
try vk_utils.generateMipMaps(cmd, newImage, mipLevel, 0);
|
try vk_utils.generateMipMaps(cmd, newImage, mipLevel, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
transitions.transferDst_into_shaderReadOnly(cmd, newImage.image, mipLevel, 0, 6);
|
transitions.transferDst_into_shaderReadOnly(cmd, newImage.image, mipLevel, 0, 6);
|
||||||
}
|
}
|
||||||
try uploader.finishUploadContext();
|
try uploader.finishUploadContext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn createDescriptorSet(
|
pub fn createDescriptorSet(
|
||||||
dev: vk.Device,
|
dev: vk.Device,
|
||||||
) struct {
|
) struct {
|
||||||
layout: vk.DescriptorSetLayout,
|
layout: vk.DescriptorSetLayout,
|
||||||
descriptorSet: vk.DescriptorSet,
|
descriptorSet: vk.DescriptorSet,
|
||||||
} {
|
} {
|
||||||
_ = dev;
|
_ = dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
const core = @import("core");
|
const core = @import("core");
|
||||||
const vk_renderer = @import("../vk_renderer.zig");
|
const vk_renderer = @import("../vk_renderer.zig");
|
||||||
|
|
||||||
const vma = @import("vma");
|
const vma = @import("vma");
|
||||||
const graphics = @import("../graphics.zig");
|
const graphics = @import("../graphics.zig");
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
const vkinit = @import("../vk_init.zig");
|
const vkinit = @import("../vk_init.zig");
|
||||||
const vk_constants = @import("../vk_constants.zig");
|
const vk_constants = @import("../vk_constants.zig");
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const vkd = vk_api.vkd;
|
const vkd = vk_api.vkd;
|
||||||
const vk_api = @import("../vk_api.zig");
|
const vk_api = @import("../vk_api.zig");
|
||||||
|
|
||||||
const transitions = @import("../vk_transitions.zig");
|
const transitions = @import("../vk_transitions.zig");
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,72 +1,72 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
|
|
||||||
const core = @import("core");
|
const core = @import("core");
|
||||||
|
|
||||||
const vk_renderer = @import("../vk_renderer.zig");
|
const vk_renderer = @import("../vk_renderer.zig");
|
||||||
const NeonVkContext = vk_renderer.NeonVkContext;
|
const NeonVkContext = vk_renderer.NeonVkContext;
|
||||||
|
|
||||||
const vk_allocator = @import("../vk_allocator.zig");
|
const vk_allocator = @import("../vk_allocator.zig");
|
||||||
const vk_constants = @import("../vk_constants.zig");
|
const vk_constants = @import("../vk_constants.zig");
|
||||||
|
|
||||||
pub const NeonVkQueue = struct {
|
pub const NeonVkQueue = struct {
|
||||||
handle: vk.Queue,
|
handle: vk.Queue,
|
||||||
family: u32,
|
family: u32,
|
||||||
|
|
||||||
pub fn init(vkd: vk_constants.DeviceDispatch, dev: vk.Device, family: u32, index: u32) @This() {
|
pub fn init(vkd: vk_constants.DeviceDispatch, dev: vk.Device, family: u32, index: u32) @This() {
|
||||||
return .{
|
return .{
|
||||||
.handle = vkd.getDeviceQueue(dev, family, index),
|
.handle = vkd.getDeviceQueue(dev, family, index),
|
||||||
.family = family,
|
.family = family,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const NeonVkFrameData = struct {
|
pub const NeonVkFrameData = struct {
|
||||||
// descriptors
|
// descriptors
|
||||||
globalDescriptorSet: vk.DescriptorSet,
|
globalDescriptorSet: vk.DescriptorSet,
|
||||||
objectDescriptorSet: vk.DescriptorSet,
|
objectDescriptorSet: vk.DescriptorSet,
|
||||||
spriteDescriptorSet: vk.DescriptorSet,
|
spriteDescriptorSet: vk.DescriptorSet,
|
||||||
|
|
||||||
// buffers
|
// buffers
|
||||||
spriteBuffer: vk_allocator.NeonVkBuffer,
|
spriteBuffer: vk_allocator.NeonVkBuffer,
|
||||||
objectBuffer: vk_allocator.NeonVkBuffer,
|
objectBuffer: vk_allocator.NeonVkBuffer,
|
||||||
animationsBuffer: vk_allocator.NeonVkBuffer,
|
animationsBuffer: vk_allocator.NeonVkBuffer,
|
||||||
cameraBuffer: vk_allocator.NeonVkBuffer,
|
cameraBuffer: vk_allocator.NeonVkBuffer,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const triangle_mesh_vert = @import("triangle_mesh_vert");
|
pub const triangle_mesh_vert = @import("triangle_mesh_vert");
|
||||||
pub const NeonVkObjectDataGpu = triangle_mesh_vert.ObjectData;
|
pub const NeonVkObjectDataGpu = triangle_mesh_vert.ObjectData;
|
||||||
pub const VertexBoneData = triangle_mesh_vert.VertexBoneData;
|
pub const VertexBoneData = triangle_mesh_vert.VertexBoneData;
|
||||||
|
|
||||||
pub const NeonVkSceneDataGpu = struct {
|
pub const NeonVkSceneDataGpu = struct {
|
||||||
fogColor: core.zm.Vec = .{ 0.0, 0.0, 0.0, 0.0 },
|
fogColor: core.zm.Vec = .{ 0.0, 0.0, 0.0, 0.0 },
|
||||||
fogDistances: core.zm.Vec = .{ 0.0, 0.0, 0.0, 0.0 },
|
fogDistances: core.zm.Vec = .{ 0.0, 0.0, 0.0, 0.0 },
|
||||||
ambientColor: core.zm.Vec = .{ 0.0, 0.0, 0.0, 0.0 },
|
ambientColor: core.zm.Vec = .{ 0.0, 0.0, 0.0, 0.0 },
|
||||||
sunlightDirection: core.zm.Vec = .{ 0.0, 0.0, 0.0, 0.0 },
|
sunlightDirection: core.zm.Vec = .{ 0.0, 0.0, 0.0, 0.0 },
|
||||||
sunlightColor: core.zm.Vec = .{ 0.0, 0.0, 0.0, 0.0 },
|
sunlightColor: core.zm.Vec = .{ 0.0, 0.0, 0.0, 0.0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const descriptorPoolSizes = [_]vk.DescriptorPoolSize{
|
pub const descriptorPoolSizes = [_]vk.DescriptorPoolSize{
|
||||||
.{ .type = .uniform_buffer, .descriptor_count = 1000 },
|
.{ .type = .uniform_buffer, .descriptor_count = 1000 },
|
||||||
.{ .type = .uniform_buffer_dynamic, .descriptor_count = 1000 },
|
.{ .type = .uniform_buffer_dynamic, .descriptor_count = 1000 },
|
||||||
.{ .type = .storage_buffer, .descriptor_count = 1000 },
|
.{ .type = .storage_buffer, .descriptor_count = 1000 },
|
||||||
.{ .type = .combined_image_sampler, .descriptor_count = 2000 },
|
.{ .type = .combined_image_sampler, .descriptor_count = 2000 },
|
||||||
.{ .type = .sampler, .descriptor_count = 1000 },
|
.{ .type = .sampler, .descriptor_count = 1000 },
|
||||||
.{ .type = .sampled_image, .descriptor_count = 1000 },
|
.{ .type = .sampled_image, .descriptor_count = 1000 },
|
||||||
.{ .type = .storage_image, .descriptor_count = 1000 },
|
.{ .type = .storage_image, .descriptor_count = 1000 },
|
||||||
|
|
||||||
// .{ .type = .sampler, .descriptor_count = 1000 },
|
// .{ .type = .sampler, .descriptor_count = 1000 },
|
||||||
// .{ .type = .combined_image_sampler, .descriptor_count = 1000 },
|
// .{ .type = .combined_image_sampler, .descriptor_count = 1000 },
|
||||||
// .{ .type = .sampled_image, .descriptor_count = 1000 },
|
// .{ .type = .sampled_image, .descriptor_count = 1000 },
|
||||||
// .{ .type = .storage_image, .descriptor_count = 1000 },
|
// .{ .type = .storage_image, .descriptor_count = 1000 },
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const NeonVkSwapImage = struct {
|
pub const NeonVkSwapImage = struct {
|
||||||
image: vk.Image,
|
image: vk.Image,
|
||||||
view: vk.ImageView,
|
view: vk.ImageView,
|
||||||
imageIndex: usize,
|
imageIndex: usize,
|
||||||
|
|
||||||
pub fn deinit(self: *NeonVkSwapImage, vkd: vk_constants.DeviceDispatch, dev: vk.Device) void {
|
pub fn deinit(self: *NeonVkSwapImage, vkd: vk_constants.DeviceDispatch, dev: vk.Device) void {
|
||||||
vkd.destroyImageView(dev, self.view, null);
|
vkd.destroyImageView(dev, self.view, null);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -1,44 +1,44 @@
|
||||||
pub const SkeletalBuffers = struct {
|
pub const SkeletalBuffers = struct {
|
||||||
descriptorSet: vk.DescriptorSet,
|
descriptorSet: vk.DescriptorSet,
|
||||||
gc: *NeonVkContext,
|
gc: *NeonVkContext,
|
||||||
vkAllocator: *NeonVkAllocator,
|
vkAllocator: *NeonVkAllocator,
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
|
|
||||||
finalsBuffer: [2]NeonVkBuffer = undefined,
|
finalsBuffer: [2]NeonVkBuffer = undefined,
|
||||||
|
|
||||||
pub fn init(gc: *NeonVkContext) !*@This() {
|
pub fn init(gc: *NeonVkContext) !*@This() {
|
||||||
const self = try gc.allocator.create(@This());
|
const self = try gc.allocator.create(@This());
|
||||||
|
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.gc = gc,
|
.gc = gc,
|
||||||
.allocator = gc.allocator,
|
.allocator = gc.allocator,
|
||||||
.vkAllocator = gc.vkAllocator,
|
.vkAllocator = gc.vkAllocator,
|
||||||
.skeletalPipeData = undefined,
|
.skeletalPipeData = undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.buildBuffers();
|
self.buildBuffers();
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn buildBuffers(self: *@This()) !void {
|
pub fn buildBuffers(self: *@This()) !void {
|
||||||
const vkAllocator: *NeonVkAllocator = self.vkAllocator;
|
const vkAllocator: *NeonVkAllocator = self.vkAllocator;
|
||||||
|
|
||||||
// 100k animated skeletal mesh vertices ought to be enough for anyone right?
|
// 100k animated skeletal mesh vertices ought to be enough for anyone right?
|
||||||
for (0..2) |i| {
|
for (0..2) |i| {
|
||||||
self.finalsBuffer[i] = try vkAllocator.createSsboBuffer(@sizeOf(core.Mat) * vk_constants.MAX_SKIN_SLOTS, "bones buffer.");
|
self.finalsBuffer[i] = try vkAllocator.createSsboBuffer(@sizeOf(core.Mat) * vk_constants.MAX_SKIN_SLOTS, "bones buffer.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const core = @import("core");
|
const core = @import("core");
|
||||||
const assets = @import("assets");
|
const assets = @import("assets");
|
||||||
const graphics = @import("../graphics.zig");
|
const graphics = @import("../graphics.zig");
|
||||||
const vk_renderer_types = @import("vk_renderer_types.zig");
|
const vk_renderer_types = @import("vk_renderer_types.zig");
|
||||||
const VertexBoneData = vk_renderer_types.VertexBoneData;
|
const VertexBoneData = vk_renderer_types.VertexBoneData;
|
||||||
const gpd = graphics.gpu_pipe_data;
|
const gpd = graphics.gpu_pipe_data;
|
||||||
const NeonVkContext = graphics.NeonVkContext;
|
const NeonVkContext = graphics.NeonVkContext;
|
||||||
const NeonVkBuffer = graphics.NeonVkBuffer;
|
const NeonVkBuffer = graphics.NeonVkBuffer;
|
||||||
const NeonVkAllocator = graphics.NeonVkAllocator;
|
const NeonVkAllocator = graphics.NeonVkAllocator;
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
const vk_constants = @import("../vk_constants.zig");
|
const vk_constants = @import("../vk_constants.zig");
|
||||||
|
|
@ -1,87 +1,87 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
const core = @import("core");
|
const core = @import("core");
|
||||||
const vk_constants = @import("../vk_constants.zig");
|
const vk_constants = @import("../vk_constants.zig");
|
||||||
const vk_renderer_types = @import("vk_renderer_types.zig");
|
const vk_renderer_types = @import("vk_renderer_types.zig");
|
||||||
|
|
||||||
const vk_api = @import("../vk_api.zig");
|
const vk_api = @import("../vk_api.zig");
|
||||||
const vkd = vk_api.vkd;
|
const vkd = vk_api.vkd;
|
||||||
const vki = vk_api.vki;
|
const vki = vk_api.vki;
|
||||||
const vkb = vk_api.vkb;
|
const vkb = vk_api.vkb;
|
||||||
|
|
||||||
const force_mailbox = core.BuildOption("force_mailbox");
|
const force_mailbox = core.BuildOption("force_mailbox");
|
||||||
|
|
||||||
pub fn findSurfaceFormat(
|
pub fn findSurfaceFormat(
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
pdev: vk.PhysicalDevice,
|
pdev: vk.PhysicalDevice,
|
||||||
surface: vk.SurfaceKHR,
|
surface: vk.SurfaceKHR,
|
||||||
) !vk.SurfaceFormatKHR {
|
) !vk.SurfaceFormatKHR {
|
||||||
const preferred = vk.SurfaceFormatKHR{
|
const preferred = vk.SurfaceFormatKHR{
|
||||||
.format = .b8g8r8a8_srgb,
|
.format = .b8g8r8a8_srgb,
|
||||||
.color_space = .srgb_nonlinear_khr,
|
.color_space = .srgb_nonlinear_khr,
|
||||||
};
|
};
|
||||||
|
|
||||||
var count: u32 = 0;
|
var count: u32 = 0;
|
||||||
|
|
||||||
_ = try vki.getPhysicalDeviceSurfaceFormatsKHR(pdev, surface, &count, null);
|
_ = try vki.getPhysicalDeviceSurfaceFormatsKHR(pdev, surface, &count, null);
|
||||||
|
|
||||||
const surface_formats = try allocator.alloc(vk.SurfaceFormatKHR, count);
|
const surface_formats = try allocator.alloc(vk.SurfaceFormatKHR, count);
|
||||||
defer allocator.free(surface_formats);
|
defer allocator.free(surface_formats);
|
||||||
|
|
||||||
_ = try vki.getPhysicalDeviceSurfaceFormatsKHR(pdev, surface, &count, surface_formats.ptr);
|
_ = try vki.getPhysicalDeviceSurfaceFormatsKHR(pdev, surface, &count, surface_formats.ptr);
|
||||||
|
|
||||||
for (surface_formats) |sfmt| {
|
for (surface_formats) |sfmt| {
|
||||||
if (std.meta.eql(sfmt, preferred)) {
|
if (std.meta.eql(sfmt, preferred)) {
|
||||||
return preferred;
|
return preferred;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const rv = surface_formats[0];
|
const rv = surface_formats[0];
|
||||||
|
|
||||||
core.graphics_log("Selected surface format\n {any}", .{rv});
|
core.graphics_log("Selected surface format\n {any}", .{rv});
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn findPresentMode(
|
pub fn findPresentMode(
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
pdev: vk.PhysicalDevice,
|
pdev: vk.PhysicalDevice,
|
||||||
surface: vk.SurfaceKHR,
|
surface: vk.SurfaceKHR,
|
||||||
) !vk.PresentModeKHR {
|
) !vk.PresentModeKHR {
|
||||||
var count: u32 = undefined;
|
var count: u32 = undefined;
|
||||||
_ = try vki.getPhysicalDeviceSurfacePresentModesKHR(pdev, surface, &count, null);
|
_ = try vki.getPhysicalDeviceSurfacePresentModesKHR(pdev, surface, &count, null);
|
||||||
const present_modes = try allocator.alloc(vk.PresentModeKHR, count);
|
const present_modes = try allocator.alloc(vk.PresentModeKHR, count);
|
||||||
defer allocator.free(present_modes);
|
defer allocator.free(present_modes);
|
||||||
_ = try vki.getPhysicalDeviceSurfacePresentModesKHR(pdev, surface, &count, present_modes.ptr);
|
_ = try vki.getPhysicalDeviceSurfacePresentModesKHR(pdev, surface, &count, present_modes.ptr);
|
||||||
|
|
||||||
const preferred = [_]vk.PresentModeKHR{
|
const preferred = [_]vk.PresentModeKHR{
|
||||||
.fifo_khr,
|
.fifo_khr,
|
||||||
.mailbox_khr,
|
.mailbox_khr,
|
||||||
.immediate_khr,
|
.immediate_khr,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (force_mailbox) {
|
if (force_mailbox) {
|
||||||
return .mailbox_khr;
|
return .mailbox_khr;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (preferred) |mode| {
|
for (preferred) |mode| {
|
||||||
if (std.mem.indexOfScalar(vk.PresentModeKHR, present_modes, mode) != null) {
|
if (std.mem.indexOfScalar(vk.PresentModeKHR, present_modes, mode) != null) {
|
||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return error.UnableToFindPresentMode;
|
return error.UnableToFindPresentMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn findActualExtent(
|
pub fn findActualExtent(
|
||||||
extent: vk.Extent2D,
|
extent: vk.Extent2D,
|
||||||
caps: vk.SurfaceCapabilitiesKHR,
|
caps: vk.SurfaceCapabilitiesKHR,
|
||||||
) !vk.Extent2D {
|
) !vk.Extent2D {
|
||||||
if (caps.current_extent.width != 0xFFFF_FFFF) {
|
if (caps.current_extent.width != 0xFFFF_FFFF) {
|
||||||
return caps.current_extent;
|
return caps.current_extent;
|
||||||
} else {
|
} else {
|
||||||
return .{
|
return .{
|
||||||
.width = std.math.clamp(extent.width, caps.min_image_extent.width, caps.max_image_extent.width),
|
.width = std.math.clamp(extent.width, caps.min_image_extent.width, caps.max_image_extent.width),
|
||||||
.height = std.math.clamp(extent.height, caps.min_image_extent.height, caps.max_image_extent.height),
|
.height = std.math.clamp(extent.height, caps.min_image_extent.height, caps.max_image_extent.height),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,128 +1,128 @@
|
||||||
// this implements the global texture list
|
// this implements the global texture list
|
||||||
|
|
||||||
const gTextureList: *TextureList = undefined;
|
const gTextureList: *TextureList = undefined;
|
||||||
|
|
||||||
pub const ArrayedTexture = struct {};
|
pub const ArrayedTexture = struct {};
|
||||||
|
|
||||||
pub const TextureList = struct {
|
pub const TextureList = struct {
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
textures: std.AutoHashMapUnmanaged(u32, *Texture),
|
textures: std.AutoHashMapUnmanaged(u32, *Texture),
|
||||||
gc: *NeonVkContext,
|
gc: *NeonVkContext,
|
||||||
listSet: vk.DescriptorSet = undefined,
|
listSet: vk.DescriptorSet = undefined,
|
||||||
dsl: vk.DescriptorSetLayout = undefined,
|
dsl: vk.DescriptorSetLayout = undefined,
|
||||||
// descriptorPool: vk.DescriptorPool = undefined,
|
// descriptorPool: vk.DescriptorPool = undefined,
|
||||||
|
|
||||||
// const descriptorPoolSizes = [_]vk.DescriptorPoolSize{
|
// const descriptorPoolSizes = [_]vk.DescriptorPoolSize{
|
||||||
// .{ .type = .sampler, .descriptor_count = 1000 },
|
// .{ .type = .sampler, .descriptor_count = 1000 },
|
||||||
// .{ .type = .combined_image_sampler, .descriptor_count = 1000 },
|
// .{ .type = .combined_image_sampler, .descriptor_count = 1000 },
|
||||||
// .{ .type = .sampled_image, .descriptor_count = 1000 },
|
// .{ .type = .sampled_image, .descriptor_count = 1000 },
|
||||||
// .{ .type = .storage_image, .descriptor_count = 1000 },
|
// .{ .type = .storage_image, .descriptor_count = 1000 },
|
||||||
// };
|
// };
|
||||||
|
|
||||||
pub fn create(gc: *NeonVkContext) !*@This() {
|
pub fn create(gc: *NeonVkContext) !*@This() {
|
||||||
const self = try gc.allocator.create(@This());
|
const self = try gc.allocator.create(@This());
|
||||||
|
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.allocator = gc.allocator,
|
.allocator = gc.allocator,
|
||||||
.textures = .{},
|
.textures = .{},
|
||||||
.gc = gc,
|
.gc = gc,
|
||||||
};
|
};
|
||||||
|
|
||||||
try self.initTextureList();
|
try self.initTextureList();
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initTextureList(self: *@This()) !void {
|
pub fn initTextureList(self: *@This()) !void {
|
||||||
// var poolInfo = vk.DescriptorPoolCreateInfo{
|
// var poolInfo = vk.DescriptorPoolCreateInfo{
|
||||||
// .flags = .{},
|
// .flags = .{},
|
||||||
// .max_sets = 1000,
|
// .max_sets = 1000,
|
||||||
// .pool_size_count = @intCast(descriptorPoolSizes.len),
|
// .pool_size_count = @intCast(descriptorPoolSizes.len),
|
||||||
// .p_pool_sizes = &descriptorPoolSizes,
|
// .p_pool_sizes = &descriptorPoolSizes,
|
||||||
// };
|
// };
|
||||||
|
|
||||||
// self.descriptorPool = try vkd.createDescriptorPool(self.gc.dev, &poolInfo, null);
|
// self.descriptorPool = try vkd.createDescriptorPool(self.gc.dev, &poolInfo, null);
|
||||||
|
|
||||||
const bindings = [_]vk.DescriptorSetLayoutBinding{
|
const bindings = [_]vk.DescriptorSetLayoutBinding{
|
||||||
.{
|
.{
|
||||||
.binding = 0,
|
.binding = 0,
|
||||||
.descriptor_type = .storage_buffer,
|
.descriptor_type = .storage_buffer,
|
||||||
.descriptor_count = 500,
|
.descriptor_count = 500,
|
||||||
.stage_flags = .{
|
.stage_flags = .{
|
||||||
.vertex_bit = true,
|
.vertex_bit = true,
|
||||||
.geometry_bit = true,
|
.geometry_bit = true,
|
||||||
.compute_bit = true,
|
.compute_bit = true,
|
||||||
.fragment_bit = true,
|
.fragment_bit = true,
|
||||||
},
|
},
|
||||||
.p_immutable_samplers = null,
|
.p_immutable_samplers = null,
|
||||||
},
|
},
|
||||||
.{
|
.{
|
||||||
.binding = 1,
|
.binding = 1,
|
||||||
.descriptor_type = .combined_image_sampler,
|
.descriptor_type = .combined_image_sampler,
|
||||||
.descriptor_count = 500,
|
.descriptor_count = 500,
|
||||||
.stage_flags = .{
|
.stage_flags = .{
|
||||||
.vertex_bit = true,
|
.vertex_bit = true,
|
||||||
.geometry_bit = true,
|
.geometry_bit = true,
|
||||||
.compute_bit = true,
|
.compute_bit = true,
|
||||||
.fragment_bit = true,
|
.fragment_bit = true,
|
||||||
},
|
},
|
||||||
.p_immutable_samplers = null,
|
.p_immutable_samplers = null,
|
||||||
},
|
},
|
||||||
.{
|
.{
|
||||||
.binding = 2,
|
.binding = 2,
|
||||||
.descriptor_type = .storage_image,
|
.descriptor_type = .storage_image,
|
||||||
.descriptor_count = 500,
|
.descriptor_count = 500,
|
||||||
.stage_flags = .{
|
.stage_flags = .{
|
||||||
.vertex_bit = true,
|
.vertex_bit = true,
|
||||||
.geometry_bit = true,
|
.geometry_bit = true,
|
||||||
.compute_bit = true,
|
.compute_bit = true,
|
||||||
.fragment_bit = true,
|
.fragment_bit = true,
|
||||||
},
|
},
|
||||||
.p_immutable_samplers = null,
|
.p_immutable_samplers = null,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const flags = [_]vk.DescriptorBindingFlags{
|
const flags = [_]vk.DescriptorBindingFlags{
|
||||||
.{ .partially_bound_bit = true },
|
.{ .partially_bound_bit = true },
|
||||||
.{ .partially_bound_bit = true },
|
.{ .partially_bound_bit = true },
|
||||||
.{ .partially_bound_bit = true },
|
.{ .partially_bound_bit = true },
|
||||||
};
|
};
|
||||||
const fci = vk.DescriptorSetLayoutBindingFlagsCreateInfo{ .binding_count = 3, .p_binding_flags = @ptrCast(&flags) };
|
const fci = vk.DescriptorSetLayoutBindingFlagsCreateInfo{ .binding_count = 3, .p_binding_flags = @ptrCast(&flags) };
|
||||||
|
|
||||||
const dsci = vk.DescriptorSetLayoutCreateInfo{
|
const dsci = vk.DescriptorSetLayoutCreateInfo{
|
||||||
.flags = .{},
|
.flags = .{},
|
||||||
.binding_count = bindings.len,
|
.binding_count = bindings.len,
|
||||||
.p_bindings = @ptrCast(&bindings),
|
.p_bindings = @ptrCast(&bindings),
|
||||||
.p_next = &fci,
|
.p_next = &fci,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.dsl = try vkd.createDescriptorSetLayout(self.gc.dev, &dsci, null);
|
self.dsl = try vkd.createDescriptorSetLayout(self.gc.dev, &dsci, null);
|
||||||
|
|
||||||
const dsai = vk.DescriptorSetAllocateInfo{
|
const dsai = vk.DescriptorSetAllocateInfo{
|
||||||
.descriptor_pool = self.gc.descriptorPool,
|
.descriptor_pool = self.gc.descriptorPool,
|
||||||
.descriptor_set_count = 1,
|
.descriptor_set_count = 1,
|
||||||
.p_set_layouts = @ptrCast(&self.dsl),
|
.p_set_layouts = @ptrCast(&self.dsl),
|
||||||
};
|
};
|
||||||
|
|
||||||
try vkd.allocateDescriptorSets(self.gc.dev, &dsai, @ptrCast(&self.listSet));
|
try vkd.allocateDescriptorSets(self.gc.dev, &dsai, @ptrCast(&self.listSet));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy(self: *@This()) void {
|
pub fn destroy(self: *@This()) void {
|
||||||
vkd.destroyDescriptorSetLayout(self.gc.dev, self.dsl, null);
|
vkd.destroyDescriptorSetLayout(self.gc.dev, self.dsl, null);
|
||||||
// vkd.destroyDescriptorPool(self.gc.dev, self.descriptorPool, null);
|
// vkd.destroyDescriptorPool(self.gc.dev, self.descriptorPool, null);
|
||||||
self.textures.deinit(self.allocator);
|
self.textures.deinit(self.allocator);
|
||||||
self.allocator.destroy(self);
|
self.allocator.destroy(self);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const graphics = @import("../graphics.zig");
|
const graphics = @import("../graphics.zig");
|
||||||
const NeonVkContext = graphics.NeonVkContext;
|
const NeonVkContext = graphics.NeonVkContext;
|
||||||
|
|
||||||
const texture = @import("../texture.zig");
|
const texture = @import("../texture.zig");
|
||||||
const Texture = texture.Texture;
|
const Texture = texture.Texture;
|
||||||
|
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
const vk_api = @import("../vk_api.zig");
|
const vk_api = @import("../vk_api.zig");
|
||||||
const vkd = vk_api.vkd;
|
const vkd = vk_api.vkd;
|
||||||
|
|
@ -1,35 +1,35 @@
|
||||||
const vk_constants = @import("../vk_constants.zig");
|
const vk_constants = @import("../vk_constants.zig");
|
||||||
const vk_api = @import("../vk_api.zig");
|
const vk_api = @import("../vk_api.zig");
|
||||||
const vkd = vk_api.vkd;
|
const vkd = vk_api.vkd;
|
||||||
const vki = vk_api.vki;
|
const vki = vk_api.vki;
|
||||||
const vkb = vk_api.vkb;
|
const vkb = vk_api.vkb;
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
|
|
||||||
const graphics = @import("../graphics.zig");
|
const graphics = @import("../graphics.zig");
|
||||||
const NeonVkBuffer = graphics.NeonVkBuffer;
|
const NeonVkBuffer = graphics.NeonVkBuffer;
|
||||||
|
|
||||||
pub fn copyStagingSlice(
|
pub fn copyStagingSlice(
|
||||||
comptime Element: type,
|
comptime Element: type,
|
||||||
cmd: vk.CommandBuffer,
|
cmd: vk.CommandBuffer,
|
||||||
params: struct {
|
params: struct {
|
||||||
src: *NeonVkBuffer,
|
src: *NeonVkBuffer,
|
||||||
dst: *NeonVkBuffer,
|
dst: *NeonVkBuffer,
|
||||||
size: u32, // in element count
|
size: u32, // in element count
|
||||||
src_offset: u32 = 0, // in element counts
|
src_offset: u32 = 0, // in element counts
|
||||||
dst_offset: u32 = 0, // in element counts
|
dst_offset: u32 = 0, // in element counts
|
||||||
},
|
},
|
||||||
) void {
|
) void {
|
||||||
const elementSize = @sizeOf(Element);
|
const elementSize = @sizeOf(Element);
|
||||||
var copy = vk.BufferCopy{
|
var copy = vk.BufferCopy{
|
||||||
.dst_offset = params.dst_offset * elementSize,
|
.dst_offset = params.dst_offset * elementSize,
|
||||||
.src_offset = params.src_offset * elementSize,
|
.src_offset = params.src_offset * elementSize,
|
||||||
.size = params.size * elementSize,
|
.size = params.size * elementSize,
|
||||||
};
|
};
|
||||||
vkd.cmdCopyBuffer(
|
vkd.cmdCopyBuffer(
|
||||||
cmd,
|
cmd,
|
||||||
params.src.buffer,
|
params.src.buffer,
|
||||||
params.dst.buffer,
|
params.dst.buffer,
|
||||||
1,
|
1,
|
||||||
@as([*]const vk.BufferCopy, @ptrCast(©)),
|
@as([*]const vk.BufferCopy, @ptrCast(©)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const core = @import("core");
|
const core = @import("core");
|
||||||
const graphics = @import("graphics.zig");
|
const graphics = @import("graphics.zig");
|
||||||
const PixelBufferRGA8 = @import("PixelBufferRGBA8.zig");
|
const PixelBufferRGA8 = @import("PixelBufferRGBA8.zig");
|
||||||
|
|
||||||
pub fn updateTextureFromPixelsSync(
|
pub fn updateTextureFromPixelsSync(
|
||||||
textureName: core.Name,
|
textureName: core.Name,
|
||||||
pixelBuffer: PixelBufferRGA8,
|
pixelBuffer: PixelBufferRGA8,
|
||||||
) void {
|
) void {
|
||||||
graphics.getContext().updateTextureFromPixelsSync(textureName, pixelBuffer);
|
graphics.getContext().updateTextureFromPixelsSync(textureName, pixelBuffer);
|
||||||
}
|
}
|
||||||
|
|
@ -1 +1 @@
|
||||||
// vk_virtual
|
// vk_virtual
|
||||||
|
|
@ -1,95 +1,95 @@
|
||||||
// REEEEEEEEEEEEEE
|
// REEEEEEEEEEEEEE
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const core = @import("core");
|
const core = @import("core");
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
const vma = @import("vma");
|
const vma = @import("vma");
|
||||||
const vk_constants = @import("vk_constants.zig");
|
const vk_constants = @import("vk_constants.zig");
|
||||||
const vk_api = @import("vk_api.zig");
|
const vk_api = @import("vk_api.zig");
|
||||||
const vkd = vk_api.vkd;
|
const vkd = vk_api.vkd;
|
||||||
|
|
||||||
pub fn transferDst_into_shaderReadOnly(
|
pub fn transferDst_into_shaderReadOnly(
|
||||||
cmd: vk.CommandBuffer,
|
cmd: vk.CommandBuffer,
|
||||||
image: vk.Image,
|
image: vk.Image,
|
||||||
mipLevel: u32,
|
mipLevel: u32,
|
||||||
baseArrayLayer: u32,
|
baseArrayLayer: u32,
|
||||||
layerCount: u32,
|
layerCount: u32,
|
||||||
) void {
|
) void {
|
||||||
if (mipLevel == 0) {
|
if (mipLevel == 0) {
|
||||||
core.engine_logs("mipLevel 0 detected into_shaderReadOnly");
|
core.engine_logs("mipLevel 0 detected into_shaderReadOnly");
|
||||||
}
|
}
|
||||||
|
|
||||||
const range = vk.ImageSubresourceRange{
|
const range = vk.ImageSubresourceRange{
|
||||||
.aspect_mask = .{ .color_bit = true },
|
.aspect_mask = .{ .color_bit = true },
|
||||||
.base_mip_level = 0,
|
.base_mip_level = 0,
|
||||||
.level_count = mipLevel,
|
.level_count = mipLevel,
|
||||||
.base_array_layer = baseArrayLayer,
|
.base_array_layer = baseArrayLayer,
|
||||||
.layer_count = layerCount,
|
.layer_count = layerCount,
|
||||||
};
|
};
|
||||||
|
|
||||||
var imageBarrier_toReadable = vk.ImageMemoryBarrier{
|
var imageBarrier_toReadable = vk.ImageMemoryBarrier{
|
||||||
.old_layout = .undefined,
|
.old_layout = .undefined,
|
||||||
.new_layout = .shader_read_only_optimal,
|
.new_layout = .shader_read_only_optimal,
|
||||||
.image = image,
|
.image = image,
|
||||||
.subresource_range = range,
|
.subresource_range = range,
|
||||||
.src_access_mask = .{ .transfer_write_bit = true },
|
.src_access_mask = .{ .transfer_write_bit = true },
|
||||||
.dst_access_mask = .{ .shader_read_bit = false },
|
.dst_access_mask = .{ .shader_read_bit = false },
|
||||||
.src_queue_family_index = 0,
|
.src_queue_family_index = 0,
|
||||||
.dst_queue_family_index = 0,
|
.dst_queue_family_index = 0,
|
||||||
};
|
};
|
||||||
vkd.cmdPipelineBarrier(
|
vkd.cmdPipelineBarrier(
|
||||||
cmd,
|
cmd,
|
||||||
.{ .transfer_bit = true },
|
.{ .transfer_bit = true },
|
||||||
.{ .fragment_shader_bit = true },
|
.{ .fragment_shader_bit = true },
|
||||||
.{},
|
.{},
|
||||||
0,
|
0,
|
||||||
undefined,
|
undefined,
|
||||||
0,
|
0,
|
||||||
undefined,
|
undefined,
|
||||||
1,
|
1,
|
||||||
@ptrCast(&imageBarrier_toReadable),
|
@ptrCast(&imageBarrier_toReadable),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_transferDst(
|
pub fn into_transferDst(
|
||||||
cmd: vk.CommandBuffer,
|
cmd: vk.CommandBuffer,
|
||||||
image: vk.Image,
|
image: vk.Image,
|
||||||
mipLevel: u32,
|
mipLevel: u32,
|
||||||
baseArrayLayer: u32,
|
baseArrayLayer: u32,
|
||||||
layerCount: u32,
|
layerCount: u32,
|
||||||
) void {
|
) void {
|
||||||
if (mipLevel == 0) {
|
if (mipLevel == 0) {
|
||||||
core.engine_logs("mipLevel 0 detected into_transferDst");
|
core.engine_logs("mipLevel 0 detected into_transferDst");
|
||||||
}
|
}
|
||||||
const range = vk.ImageSubresourceRange{
|
const range = vk.ImageSubresourceRange{
|
||||||
.aspect_mask = .{ .color_bit = true },
|
.aspect_mask = .{ .color_bit = true },
|
||||||
.base_mip_level = 0,
|
.base_mip_level = 0,
|
||||||
.level_count = mipLevel,
|
.level_count = mipLevel,
|
||||||
.base_array_layer = baseArrayLayer,
|
.base_array_layer = baseArrayLayer,
|
||||||
.layer_count = layerCount,
|
.layer_count = layerCount,
|
||||||
};
|
};
|
||||||
|
|
||||||
var imageBarrier_toTransfer = vk.ImageMemoryBarrier{
|
var imageBarrier_toTransfer = vk.ImageMemoryBarrier{
|
||||||
.old_layout = .undefined,
|
.old_layout = .undefined,
|
||||||
.new_layout = .transfer_dst_optimal,
|
.new_layout = .transfer_dst_optimal,
|
||||||
.image = image,
|
.image = image,
|
||||||
.subresource_range = range,
|
.subresource_range = range,
|
||||||
.src_access_mask = .{},
|
.src_access_mask = .{},
|
||||||
.dst_access_mask = .{ .transfer_write_bit = true },
|
.dst_access_mask = .{ .transfer_write_bit = true },
|
||||||
.src_queue_family_index = 0,
|
.src_queue_family_index = 0,
|
||||||
.dst_queue_family_index = 0,
|
.dst_queue_family_index = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
vkd.cmdPipelineBarrier(
|
vkd.cmdPipelineBarrier(
|
||||||
cmd,
|
cmd,
|
||||||
.{ .top_of_pipe_bit = true },
|
.{ .top_of_pipe_bit = true },
|
||||||
.{ .transfer_bit = true },
|
.{ .transfer_bit = true },
|
||||||
.{},
|
.{},
|
||||||
0,
|
0,
|
||||||
undefined,
|
undefined,
|
||||||
0,
|
0,
|
||||||
undefined,
|
undefined,
|
||||||
1,
|
1,
|
||||||
@ptrCast(&imageBarrier_toTransfer),
|
@ptrCast(&imageBarrier_toTransfer),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1,143 +1,143 @@
|
||||||
// Game: Deathwish
|
// Game: Deathwish
|
||||||
// Format: Standard
|
// Format: Standard
|
||||||
// entity 0
|
// entity 0
|
||||||
{
|
{
|
||||||
"classname" "worldspawn"
|
"classname" "worldspawn"
|
||||||
// brush 0
|
// brush 0
|
||||||
{
|
{
|
||||||
( -224 -32 -16 ) ( -224 -31 -16 ) ( -224 -32 -15 ) ProtoFloor 0 -16 0 1 1
|
( -224 -32 -16 ) ( -224 -31 -16 ) ( -224 -32 -15 ) ProtoFloor 0 -16 0 1 1
|
||||||
( -224 -32 -16 ) ( -224 -32 -15 ) ( -223 -32 -16 ) ProtoFloor 0 -16 0 1 1
|
( -224 -32 -16 ) ( -224 -32 -15 ) ( -223 -32 -16 ) ProtoFloor 0 -16 0 1 1
|
||||||
( -224 -32 -16 ) ( -223 -32 -16 ) ( -224 -31 -16 ) ProtoFloor 0 0 0 1 1
|
( -224 -32 -16 ) ( -223 -32 -16 ) ( -224 -31 -16 ) ProtoFloor 0 0 0 1 1
|
||||||
( -192 32 0 ) ( -192 33 0 ) ( -191 32 0 ) ProtoFloor 0 0 0 1 1
|
( -192 32 0 ) ( -192 33 0 ) ( -191 32 0 ) ProtoFloor 0 0 0 1 1
|
||||||
( -192 32 0 ) ( -191 32 0 ) ( -192 32 1 ) ProtoFloor 0 -16 0 1 1
|
( -192 32 0 ) ( -191 32 0 ) ( -192 32 1 ) ProtoFloor 0 -16 0 1 1
|
||||||
( -64 32 0 ) ( -64 32 1 ) ( -64 33 0 ) ProtoFloor 0 -16 0 1 1
|
( -64 32 0 ) ( -64 32 1 ) ( -64 33 0 ) ProtoFloor 0 -16 0 1 1
|
||||||
}
|
}
|
||||||
// brush 1
|
// brush 1
|
||||||
{
|
{
|
||||||
( -576 -160 -32 ) ( -576 -159 -32 ) ( -576 -160 -31 ) ProtoGrass 16 -16 0 1 1
|
( -576 -160 -32 ) ( -576 -159 -32 ) ( -576 -160 -31 ) ProtoGrass 16 -16 0 1 1
|
||||||
( 0 -400 -32 ) ( 0 -400 -31 ) ( 1 -400 -32 ) ProtoGrass -16 -16 0 1 1
|
( 0 -400 -32 ) ( 0 -400 -31 ) ( 1 -400 -32 ) ProtoGrass -16 -16 0 1 1
|
||||||
( 0 -160 -32 ) ( 1 -160 -32 ) ( 0 -159 -32 ) ProtoGrass -16 -16 0 1 1
|
( 0 -160 -32 ) ( 1 -160 -32 ) ( 0 -159 -32 ) ProtoGrass -16 -16 0 1 1
|
||||||
( 48 -144 -16 ) ( 48 -143 -16 ) ( 49 -144 -16 ) ProtoGrass -16 -16 0 1 1
|
( 48 -144 -16 ) ( 48 -143 -16 ) ( 49 -144 -16 ) ProtoGrass -16 -16 0 1 1
|
||||||
( 48 224 -16 ) ( 49 224 -16 ) ( 48 224 -15 ) ProtoGrass -16 -16 0 1 1
|
( 48 224 -16 ) ( 49 224 -16 ) ( 48 224 -15 ) ProtoGrass -16 -16 0 1 1
|
||||||
( 224 -144 -16 ) ( 224 -144 -15 ) ( 224 -143 -16 ) ProtoGrass 16 -16 0 1 1
|
( 224 -144 -16 ) ( 224 -144 -15 ) ( 224 -143 -16 ) ProtoGrass 16 -16 0 1 1
|
||||||
}
|
}
|
||||||
// brush 2
|
// brush 2
|
||||||
{
|
{
|
||||||
( -48 -144 -32 ) ( -48 -143 -32 ) ( -48 -144 -31 ) ProtoFloor 0 -32 0 1 1
|
( -48 -144 -32 ) ( -48 -143 -32 ) ( -48 -144 -31 ) ProtoFloor 0 -32 0 1 1
|
||||||
( -48 -144 -32 ) ( -48 -144 -31 ) ( -47 -144 -32 ) ProtoFloor 0 -32 0 1 1
|
( -48 -144 -32 ) ( -48 -144 -31 ) ( -47 -144 -32 ) ProtoFloor 0 -32 0 1 1
|
||||||
( -48 -144 -32 ) ( -47 -144 -32 ) ( -48 -143 -32 ) ProtoFloor 0 0 0 1 1
|
( -48 -144 -32 ) ( -47 -144 -32 ) ( -48 -143 -32 ) ProtoFloor 0 0 0 1 1
|
||||||
( 80 -64 0 ) ( 80 -63 0 ) ( 81 -64 0 ) ProtoFloor 0 0 0 1 1
|
( 80 -64 0 ) ( 80 -63 0 ) ( 81 -64 0 ) ProtoFloor 0 0 0 1 1
|
||||||
( 80 -64 -16 ) ( 81 -64 -16 ) ( 80 -64 -15 ) ProtoFloor 0 -32 0 1 1
|
( 80 -64 -16 ) ( 81 -64 -16 ) ( 80 -64 -15 ) ProtoFloor 0 -32 0 1 1
|
||||||
( 80 -64 -16 ) ( 80 -64 -15 ) ( 80 -63 -16 ) ProtoFloor 0 -32 0 1 1
|
( 80 -64 -16 ) ( 80 -64 -15 ) ( 80 -63 -16 ) ProtoFloor 0 -32 0 1 1
|
||||||
}
|
}
|
||||||
// brush 3
|
// brush 3
|
||||||
{
|
{
|
||||||
( -48 -48 -32 ) ( -48 -47 -32 ) ( -48 -48 -31 ) ProtoFloor 32 -32 0 1 1
|
( -48 -48 -32 ) ( -48 -47 -32 ) ( -48 -48 -31 ) ProtoFloor 32 -32 0 1 1
|
||||||
( -48 -48 -32 ) ( -48 -48 -31 ) ( -47 -48 -32 ) ProtoFloor 0 -32 0 1 1
|
( -48 -48 -32 ) ( -48 -48 -31 ) ( -47 -48 -32 ) ProtoFloor 0 -32 0 1 1
|
||||||
( -48 -48 -32 ) ( -47 -48 -32 ) ( -48 -47 -32 ) ProtoFloor 0 -32 0 1 1
|
( -48 -48 -32 ) ( -47 -48 -32 ) ( -48 -47 -32 ) ProtoFloor 0 -32 0 1 1
|
||||||
( 80 32 16 ) ( 80 33 16 ) ( 81 32 16 ) ProtoFloor 0 -32 0 1 1
|
( 80 32 16 ) ( 80 33 16 ) ( 81 32 16 ) ProtoFloor 0 -32 0 1 1
|
||||||
( 80 32 -16 ) ( 81 32 -16 ) ( 80 32 -15 ) ProtoFloor 0 -32 0 1 1
|
( 80 32 -16 ) ( 81 32 -16 ) ( 80 32 -15 ) ProtoFloor 0 -32 0 1 1
|
||||||
( 80 32 -16 ) ( 80 32 -15 ) ( 80 33 -16 ) ProtoFloor 32 -32 0 1 1
|
( 80 32 -16 ) ( 80 32 -15 ) ( 80 33 -16 ) ProtoFloor 32 -32 0 1 1
|
||||||
}
|
}
|
||||||
// brush 4
|
// brush 4
|
||||||
{
|
{
|
||||||
( -448 -96 -16 ) ( -448 -95 -16 ) ( -448 -96 -15 ) ProtoWallsGrey 0 0 0 1 1
|
( -448 -96 -16 ) ( -448 -95 -16 ) ( -448 -96 -15 ) ProtoWallsGrey 0 0 0 1 1
|
||||||
( -448 -96 -16 ) ( -448 -96 -15 ) ( -447 -96 -16 ) ProtoWallsGrey 0 0 0 1 1
|
( -448 -96 -16 ) ( -448 -96 -15 ) ( -447 -96 -16 ) ProtoWallsGrey 0 0 0 1 1
|
||||||
( -448 -96 -16 ) ( -447 -96 -16 ) ( -448 -95 -16 ) ProtoWallsGrey 0 0 0 1 1
|
( -448 -96 -16 ) ( -447 -96 -16 ) ( -448 -95 -16 ) ProtoWallsGrey 0 0 0 1 1
|
||||||
( -432 80 48 ) ( -432 81 48 ) ( -431 80 48 ) ProtoWallsGrey 0 0 0 1 1
|
( -432 80 48 ) ( -432 81 48 ) ( -431 80 48 ) ProtoWallsGrey 0 0 0 1 1
|
||||||
( -432 80 0 ) ( -431 80 0 ) ( -432 80 1 ) ProtoWallsGrey 0 0 0 1 1
|
( -432 80 0 ) ( -431 80 0 ) ( -432 80 1 ) ProtoWallsGrey 0 0 0 1 1
|
||||||
( -432 80 0 ) ( -432 80 1 ) ( -432 81 0 ) ProtoWallsGrey 0 0 0 1 1
|
( -432 80 0 ) ( -432 80 1 ) ( -432 81 0 ) ProtoWallsGrey 0 0 0 1 1
|
||||||
}
|
}
|
||||||
// brush 5
|
// brush 5
|
||||||
{
|
{
|
||||||
( -416 -256 -16 ) ( -416 -255 -16 ) ( -416 -256 -15 ) ProtoWallsOrange 0 0 0 1 1
|
( -416 -256 -16 ) ( -416 -255 -16 ) ( -416 -256 -15 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
( -496 -256 -16 ) ( -496 -256 -15 ) ( -495 -256 -16 ) ProtoWallsOrange 0 0 0 1 1
|
( -496 -256 -16 ) ( -496 -256 -15 ) ( -495 -256 -16 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
( -496 -256 -16 ) ( -495 -256 -16 ) ( -496 -255 -16 ) ProtoWallsOrange 0 0 0 1 1
|
( -496 -256 -16 ) ( -495 -256 -16 ) ( -496 -255 -16 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
( -304 -240 96 ) ( -304 -239 96 ) ( -303 -240 96 ) ProtoWallsOrange 0 0 0 1 1
|
( -304 -240 96 ) ( -304 -239 96 ) ( -303 -240 96 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
( -304 -240 0 ) ( -303 -240 0 ) ( -304 -240 1 ) ProtoWallsOrange 0 0 0 1 1
|
( -304 -240 0 ) ( -303 -240 0 ) ( -304 -240 1 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
( -304 -240 0 ) ( -304 -240 1 ) ( -304 -239 0 ) ProtoWallsOrange 0 0 0 1 1
|
( -304 -240 0 ) ( -304 -240 1 ) ( -304 -239 0 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
}
|
}
|
||||||
// brush 6
|
// brush 6
|
||||||
{
|
{
|
||||||
( -320 -384 -16 ) ( -320 -383 -16 ) ( -320 -384 -15 ) ProtoWallsOrange 0 0 0 1 1
|
( -320 -384 -16 ) ( -320 -383 -16 ) ( -320 -384 -15 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
( -320 -320 -16 ) ( -320 -320 -15 ) ( -319 -320 -16 ) ProtoWallsOrange 0 0 0 1 1
|
( -320 -320 -16 ) ( -320 -320 -15 ) ( -319 -320 -16 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
( -320 -384 -16 ) ( -319 -384 -16 ) ( -320 -383 -16 ) ProtoWallsOrange 0 0 0 1 1
|
( -320 -384 -16 ) ( -319 -384 -16 ) ( -320 -383 -16 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
( -304 -256 96 ) ( -304 -255 96 ) ( -303 -256 96 ) ProtoWallsOrange 0 0 0 1 1
|
( -304 -256 96 ) ( -304 -255 96 ) ( -303 -256 96 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
( -304 -256 0 ) ( -303 -256 0 ) ( -304 -256 1 ) ProtoWallsOrange 0 0 0 1 1
|
( -304 -256 0 ) ( -303 -256 0 ) ( -304 -256 1 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
( -304 -256 0 ) ( -304 -256 1 ) ( -304 -255 0 ) ProtoWallsOrange 0 0 0 1 1
|
( -304 -256 0 ) ( -304 -256 1 ) ( -304 -255 0 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
}
|
}
|
||||||
// brush 7
|
// brush 7
|
||||||
{
|
{
|
||||||
( -480 -256 80 ) ( -480 -255 80 ) ( -480 -256 81 ) ProtoWallsOrange 0 0 0 1 1
|
( -480 -256 80 ) ( -480 -255 80 ) ( -480 -256 81 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
( -432 -256 80 ) ( -432 -256 81 ) ( -431 -256 80 ) ProtoWallsOrange 0 0 0 1 1
|
( -432 -256 80 ) ( -432 -256 81 ) ( -431 -256 80 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
( -432 -256 64 ) ( -431 -256 64 ) ( -432 -255 64 ) ProtoWallsOrange 0 0 0 1 1
|
( -432 -256 64 ) ( -431 -256 64 ) ( -432 -255 64 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
( -416 -240 96 ) ( -416 -239 96 ) ( -415 -240 96 ) ProtoWallsOrange 0 0 0 1 1
|
( -416 -240 96 ) ( -416 -239 96 ) ( -415 -240 96 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
( -416 -240 96 ) ( -415 -240 96 ) ( -416 -240 97 ) ProtoWallsOrange 0 0 0 1 1
|
( -416 -240 96 ) ( -415 -240 96 ) ( -416 -240 97 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
( -416 -240 96 ) ( -416 -240 97 ) ( -416 -239 96 ) ProtoWallsOrange 0 0 0 1 1
|
( -416 -240 96 ) ( -416 -240 97 ) ( -416 -239 96 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
}
|
}
|
||||||
// brush 8
|
// brush 8
|
||||||
{
|
{
|
||||||
( -576 -256 -16 ) ( -576 -255 -16 ) ( -576 -256 -15 ) ProtoWallsOrange 0 0 0 1 1
|
( -576 -256 -16 ) ( -576 -255 -16 ) ( -576 -256 -15 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
( -672 -256 -16 ) ( -672 -256 -15 ) ( -671 -256 -16 ) ProtoWallsOrange -16 0 0 1 1
|
( -672 -256 -16 ) ( -672 -256 -15 ) ( -671 -256 -16 ) ProtoWallsOrange -16 0 0 1 1
|
||||||
( -672 -256 -16 ) ( -671 -256 -16 ) ( -672 -255 -16 ) ProtoWallsOrange -16 0 0 1 1
|
( -672 -256 -16 ) ( -671 -256 -16 ) ( -672 -255 -16 ) ProtoWallsOrange -16 0 0 1 1
|
||||||
( -480 -240 96 ) ( -480 -239 96 ) ( -479 -240 96 ) ProtoWallsOrange -16 0 0 1 1
|
( -480 -240 96 ) ( -480 -239 96 ) ( -479 -240 96 ) ProtoWallsOrange -16 0 0 1 1
|
||||||
( -480 -240 0 ) ( -479 -240 0 ) ( -480 -240 1 ) ProtoWallsOrange -16 0 0 1 1
|
( -480 -240 0 ) ( -479 -240 0 ) ( -480 -240 1 ) ProtoWallsOrange -16 0 0 1 1
|
||||||
( -480 -240 0 ) ( -480 -240 1 ) ( -480 -239 0 ) ProtoWallsOrange 0 0 0 1 1
|
( -480 -240 0 ) ( -480 -240 1 ) ( -480 -239 0 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
}
|
}
|
||||||
// brush 9
|
// brush 9
|
||||||
{
|
{
|
||||||
( -416 -400 -16 ) ( -416 -399 -16 ) ( -416 -400 -15 ) ProtoWallsOrange 16 0 0 1 1
|
( -416 -400 -16 ) ( -416 -399 -16 ) ( -416 -400 -15 ) ProtoWallsOrange 16 0 0 1 1
|
||||||
( -496 -400 -16 ) ( -496 -400 -15 ) ( -495 -400 -16 ) ProtoWallsOrange 0 0 0 1 1
|
( -496 -400 -16 ) ( -496 -400 -15 ) ( -495 -400 -16 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
( -496 -400 -16 ) ( -495 -400 -16 ) ( -496 -399 -16 ) ProtoWallsOrange 0 -16 0 1 1
|
( -496 -400 -16 ) ( -495 -400 -16 ) ( -496 -399 -16 ) ProtoWallsOrange 0 -16 0 1 1
|
||||||
( -304 -384 96 ) ( -304 -383 96 ) ( -303 -384 96 ) ProtoWallsOrange 0 -16 0 1 1
|
( -304 -384 96 ) ( -304 -383 96 ) ( -303 -384 96 ) ProtoWallsOrange 0 -16 0 1 1
|
||||||
( -304 -384 0 ) ( -303 -384 0 ) ( -304 -384 1 ) ProtoWallsOrange 0 0 0 1 1
|
( -304 -384 0 ) ( -303 -384 0 ) ( -304 -384 1 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
( -304 -384 0 ) ( -304 -384 1 ) ( -304 -383 0 ) ProtoWallsOrange 16 0 0 1 1
|
( -304 -384 0 ) ( -304 -384 1 ) ( -304 -383 0 ) ProtoWallsOrange 16 0 0 1 1
|
||||||
}
|
}
|
||||||
// brush 10
|
// brush 10
|
||||||
{
|
{
|
||||||
( -320 -384 80 ) ( -320 -383 80 ) ( -320 -384 81 ) ProtoWallsOrange 0 0 0 1 1
|
( -320 -384 80 ) ( -320 -383 80 ) ( -320 -384 81 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
( -320 -384 80 ) ( -320 -384 81 ) ( -319 -384 80 ) ProtoWallsOrange 0 0 0 1 1
|
( -320 -384 80 ) ( -320 -384 81 ) ( -319 -384 80 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
( -320 -384 64 ) ( -319 -384 64 ) ( -320 -383 64 ) ProtoWallsOrange 0 0 0 1 1
|
( -320 -384 64 ) ( -319 -384 64 ) ( -320 -383 64 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
( -288 -352 96 ) ( -288 -351 96 ) ( -287 -352 96 ) ProtoWallsOrange 0 0 0 1 1
|
( -288 -352 96 ) ( -288 -351 96 ) ( -287 -352 96 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
( -288 -320 96 ) ( -287 -320 96 ) ( -288 -320 97 ) ProtoWallsOrange 0 0 0 1 1
|
( -288 -320 96 ) ( -287 -320 96 ) ( -288 -320 97 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
( -304 -352 96 ) ( -304 -352 97 ) ( -304 -351 96 ) ProtoWallsOrange 0 0 0 1 1
|
( -304 -352 96 ) ( -304 -352 97 ) ( -304 -351 96 ) ProtoWallsOrange 0 0 0 1 1
|
||||||
}
|
}
|
||||||
// brush 11
|
// brush 11
|
||||||
{
|
{
|
||||||
( -208 -304 -16 ) ( -208 -303 -16 ) ( -208 -304 -15 ) ProtoWallsGrey 32 0 0 1 1
|
( -208 -304 -16 ) ( -208 -303 -16 ) ( -208 -304 -15 ) ProtoWallsGrey 32 0 0 1 1
|
||||||
( -208 -304 -16 ) ( -208 -304 -15 ) ( -207 -304 -16 ) ProtoWallsGrey -16 0 0 1 1
|
( -208 -304 -16 ) ( -208 -304 -15 ) ( -207 -304 -16 ) ProtoWallsGrey -16 0 0 1 1
|
||||||
( -208 -304 -16 ) ( -207 -304 -16 ) ( -208 -303 -16 ) ProtoWallsGrey -16 -32 0 1 1
|
( -208 -304 -16 ) ( -207 -304 -16 ) ( -208 -303 -16 ) ProtoWallsGrey -16 -32 0 1 1
|
||||||
( -144 -256 80 ) ( -144 -255 80 ) ( -143 -256 80 ) ProtoWallsGrey -16 -32 0 1 1
|
( -144 -256 80 ) ( -144 -255 80 ) ( -143 -256 80 ) ProtoWallsGrey -16 -32 0 1 1
|
||||||
( -144 -208 0 ) ( -143 -208 0 ) ( -144 -208 1 ) ProtoWallsGrey -16 0 0 1 1
|
( -144 -208 0 ) ( -143 -208 0 ) ( -144 -208 1 ) ProtoWallsGrey -16 0 0 1 1
|
||||||
( -32 -256 0 ) ( -32 -256 1 ) ( -32 -255 0 ) ProtoWallsGrey 32 0 0 1 1
|
( -32 -256 0 ) ( -32 -256 1 ) ( -32 -255 0 ) ProtoWallsGrey 32 0 0 1 1
|
||||||
}
|
}
|
||||||
// brush 12
|
// brush 12
|
||||||
{
|
{
|
||||||
( -544 -384 96 ) ( -544 -383 96 ) ( -544 -384 97 ) ProtoWallsGrey 0 0 0 1 1
|
( -544 -384 96 ) ( -544 -383 96 ) ( -544 -384 97 ) ProtoWallsGrey 0 0 0 1 1
|
||||||
( -544 -384 96 ) ( -544 -384 97 ) ( -543 -384 96 ) ProtoWallsGrey 0 0 0 1 1
|
( -544 -384 96 ) ( -544 -384 97 ) ( -543 -384 96 ) ProtoWallsGrey 0 0 0 1 1
|
||||||
( -544 -384 96 ) ( -543 -384 96 ) ( -544 -383 96 ) ProtoWallsGrey 0 0 0 1 1
|
( -544 -384 96 ) ( -543 -384 96 ) ( -544 -383 96 ) ProtoWallsGrey 0 0 0 1 1
|
||||||
( -304 -256 112 ) ( -304 -255 112 ) ( -303 -256 112 ) ProtoWallsGrey 0 0 0 1 1
|
( -304 -256 112 ) ( -304 -255 112 ) ( -303 -256 112 ) ProtoWallsGrey 0 0 0 1 1
|
||||||
( -304 -256 112 ) ( -303 -256 112 ) ( -304 -256 113 ) ProtoWallsGrey 0 0 0 1 1
|
( -304 -256 112 ) ( -303 -256 112 ) ( -304 -256 113 ) ProtoWallsGrey 0 0 0 1 1
|
||||||
( -304 -256 112 ) ( -304 -256 113 ) ( -304 -255 112 ) ProtoWallsGrey 0 0 0 1 1
|
( -304 -256 112 ) ( -304 -256 113 ) ( -304 -255 112 ) ProtoWallsGrey 0 0 0 1 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// entity 1
|
// entity 1
|
||||||
{
|
{
|
||||||
"classname" "enemy_spawn"
|
"classname" "enemy_spawn"
|
||||||
"origin" "-480 64 8"
|
"origin" "-480 64 8"
|
||||||
}
|
}
|
||||||
// entity 2
|
// entity 2
|
||||||
{
|
{
|
||||||
"classname" "info_player_start"
|
"classname" "info_player_start"
|
||||||
"origin" "176 -224 8"
|
"origin" "176 -224 8"
|
||||||
}
|
}
|
||||||
// entity 3
|
// entity 3
|
||||||
{
|
{
|
||||||
"classname" "enemy_spawn"
|
"classname" "enemy_spawn"
|
||||||
"origin" "-480 -16 8"
|
"origin" "-480 -16 8"
|
||||||
}
|
}
|
||||||
// entity 4
|
// entity 4
|
||||||
{
|
{
|
||||||
"classname" "enemy_spawn"
|
"classname" "enemy_spawn"
|
||||||
"origin" "-352 -288 8"
|
"origin" "-352 -288 8"
|
||||||
}
|
}
|
||||||
|
|
@ -1,46 +1,46 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const graphics = @import("graphics");
|
const graphics = @import("graphics");
|
||||||
const core = @import("core");
|
const core = @import("core");
|
||||||
const platform = @import("platform");
|
const platform = @import("platform");
|
||||||
const QuakeMap = graphics.QuakeMap;
|
const QuakeMap = graphics.QuakeMap;
|
||||||
|
|
||||||
test "simple_integration" {
|
test "simple_integration" {
|
||||||
// this doesn't really do anything other than just a simple compile check
|
// this doesn't really do anything other than just a simple compile check
|
||||||
std.debug.print("sizeof NeonVkContext = {d}\n", .{@sizeOf(graphics.NeonVkContext)});
|
std.debug.print("sizeof NeonVkContext = {d}\n", .{@sizeOf(graphics.NeonVkContext)});
|
||||||
std.debug.print("sizeof triangle_mesh_vert.ObjectData = {d}\n", .{@sizeOf(graphics.vk_renderer.triangle_mesh_vert.ObjectData)});
|
std.debug.print("sizeof triangle_mesh_vert.ObjectData = {d}\n", .{@sizeOf(graphics.vk_renderer.triangle_mesh_vert.ObjectData)});
|
||||||
}
|
}
|
||||||
|
|
||||||
test "renderthread queue" {
|
test "renderthread queue" {
|
||||||
const allocator = std.testing.allocator;
|
const allocator = std.testing.allocator;
|
||||||
try core.start_module(.{}, .{}, allocator);
|
try core.start_module(.{}, .{}, allocator);
|
||||||
defer core.shutdown_module(allocator);
|
defer core.shutdown_module(allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "quake map loading" {
|
test "quake map loading" {
|
||||||
// const TestMap = @embedFile("testmap.map");
|
// const TestMap = @embedFile("testmap.map");
|
||||||
|
|
||||||
const testmapFile =
|
const testmapFile =
|
||||||
\\{
|
\\{
|
||||||
\\"spawnflags" "0"
|
\\"spawnflags" "0"
|
||||||
\\"classname" "worldspawn"
|
\\"classname" "worldspawn"
|
||||||
\\"wad" "E:\q1maps\Q.wad"
|
\\"wad" "E:\q1maps\Q.wad"
|
||||||
\\{
|
\\{
|
||||||
\\( 256 64 16 ) ( 256 64 0 ) ( 256 0 16 ) mmetal1_2 0 0 0 1 1
|
\\( 256 64 16 ) ( 256 64 0 ) ( 256 0 16 ) mmetal1_2 0 0 0 1 1
|
||||||
\\( 0 0 0 ) ( 0 64 0 ) ( 0 0 16 ) mmetal1_2 0 0 0 1 1
|
\\( 0 0 0 ) ( 0 64 0 ) ( 0 0 16 ) mmetal1_2 0 0 0 1 1
|
||||||
\\( 64 256 16 ) ( 0 256 16 ) ( 64 256 0 ) mmetal1_2 0 0 0 1 1
|
\\( 64 256 16 ) ( 0 256 16 ) ( 64 256 0 ) mmetal1_2 0 0 0 1 1
|
||||||
\\( 0 0 0 ) ( 0 0 16 ) ( 64 0 0 ) mmetal1_2 0 0 0 1 1
|
\\( 0 0 0 ) ( 0 0 16 ) ( 64 0 0 ) mmetal1_2 0 0 0 1 1
|
||||||
\\( 64 64 0 ) ( 64 0 0 ) ( 0 64 0 ) mmetal1_2 0 0 0 1 1
|
\\( 64 64 0 ) ( 64 0 0 ) ( 0 64 0 ) mmetal1_2 0 0 0 1 1
|
||||||
\\( 0 0 -64 ) ( 64 0 -64 ) ( 0 64 -64 ) mmetal1_2 0 0 0 1 1
|
\\( 0 0 -64 ) ( 64 0 -64 ) ( 0 64 -64 ) mmetal1_2 0 0 0 1 1
|
||||||
\\}
|
\\}
|
||||||
\\}
|
\\}
|
||||||
\\{
|
\\{
|
||||||
\\"spawnflags" "0"
|
\\"spawnflags" "0"
|
||||||
\\"classname" "info_player_start"
|
\\"classname" "info_player_start"
|
||||||
\\"origin" "32 32 24"
|
\\"origin" "32 32 24"
|
||||||
\\}
|
\\}
|
||||||
;
|
;
|
||||||
|
|
||||||
var err: QuakeMap.ErrorInfo = undefined;
|
var err: QuakeMap.ErrorInfo = undefined;
|
||||||
var map = try QuakeMap.read(std.testing.allocator, testmapFile, &err);
|
var map = try QuakeMap.read(std.testing.allocator, testmapFile, &err);
|
||||||
defer map.deinit();
|
defer map.deinit();
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
plunder these ones for features to
|
||||||
|
implement in rend
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
.{
|
.{
|
||||||
.name = "ui",
|
.name = "ui",
|
||||||
.version = "0.0.0",
|
.version = "0.0.0",
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
.vulkan = .{ .path = "../../lib/vulkan" },
|
.vulkan = .{ .path = "../../lib/vulkan" },
|
||||||
.SpirvReflect = .{ .path = "../../lib/spirv-reflect-zig" },
|
.SpirvReflect = .{ .path = "../../lib/spirv-reflect-zig" },
|
||||||
|
|
||||||
.papyrus = .{ .path = "../papyrus" },
|
.papyrus = .{ .path = "../papyrus" },
|
||||||
.assets = .{ .path = "../assets" },
|
.assets = .{ .path = "../assets" },
|
||||||
.platform = .{ .path = "../platform" },
|
.platform = .{ .path = "../platform" },
|
||||||
.core = .{ .path = "../core" },
|
.core = .{ .path = "../core" },
|
||||||
.graphics = .{ .path = "../graphics" },
|
.graphics = .{ .path = "../graphics" },
|
||||||
},
|
},
|
||||||
.paths = .{
|
.paths = .{
|
||||||
"",
|
"",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -1,69 +1,69 @@
|
||||||
#version 460
|
#version 460
|
||||||
|
|
||||||
layout (location = 0) in vec4 color;
|
layout (location = 0) in vec4 color;
|
||||||
layout (location = 1) in vec2 texCoord;
|
layout (location = 1) in vec2 texCoord;
|
||||||
layout (location = 2) flat in int instanceId;
|
layout (location = 2) flat in int instanceId;
|
||||||
layout (location = 3) in vec2 pixelPosition;
|
layout (location = 3) in vec2 pixelPosition;
|
||||||
|
|
||||||
layout (location = 0) out vec4 outFragColor;
|
layout (location = 0) out vec4 outFragColor;
|
||||||
|
|
||||||
layout (set = 1, binding = 0) uniform sampler2D tex;
|
layout (set = 1, binding = 0) uniform sampler2D tex;
|
||||||
|
|
||||||
#include "FontSDFShared.glsl"
|
#include "FontSDFShared.glsl"
|
||||||
#include "FragmentHelpers.glsl"
|
#include "FragmentHelpers.glsl"
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec4 tex = texture(tex, texCoord);
|
vec4 tex = texture(tex, texCoord);
|
||||||
|
|
||||||
uint isSdf = fontBuffer.fontInfo[instanceId].isSdf;
|
uint isSdf = fontBuffer.fontInfo[instanceId].isSdf;
|
||||||
vec2 position = fontBuffer.fontInfo[instanceId].position;
|
vec2 position = fontBuffer.fontInfo[instanceId].position;
|
||||||
vec2 size = fontBuffer.fontInfo[instanceId].size;
|
vec2 size = fontBuffer.fontInfo[instanceId].size;
|
||||||
|
|
||||||
if(!scissor(pixelPosition, position, size))
|
if(!scissor(pixelPosition, position, size))
|
||||||
{
|
{
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isSdf == 1)
|
if(isSdf == 1)
|
||||||
{
|
{
|
||||||
float dist = tex.r;
|
float dist = tex.r;
|
||||||
float width = fwidth(dist);
|
float width = fwidth(dist);
|
||||||
vec4 textColor = clamp(color, 0.0, 1.0);
|
vec4 textColor = clamp(color, 0.0, 1.0);
|
||||||
float outerEdge = 1.0f - (120.0f / 255.0f);
|
float outerEdge = 1.0f - (120.0f / 255.0f);
|
||||||
|
|
||||||
float alpha = contour(dist, outerEdge, width);
|
float alpha = contour(dist, outerEdge, width);
|
||||||
|
|
||||||
float dscale = 0.354; // half of 1/sqrt2; you can play with this
|
float dscale = 0.354; // half of 1/sqrt2; you can play with this
|
||||||
vec2 uv = texCoord.xy;
|
vec2 uv = texCoord.xy;
|
||||||
vec2 duv = dscale * (dFdx(uv) + dFdy(uv));
|
vec2 duv = dscale * (dFdx(uv) + dFdy(uv));
|
||||||
vec4 box = vec4(uv - duv, uv + duv);
|
vec4 box = vec4(uv - duv, uv + duv);
|
||||||
|
|
||||||
float asum = getSample(box.xy, outerEdge, width)
|
float asum = getSample(box.xy, outerEdge, width)
|
||||||
+ getSample(box.zw, outerEdge, width)
|
+ getSample(box.zw, outerEdge, width)
|
||||||
+ getSample(box.xw, outerEdge, width)
|
+ getSample(box.xw, outerEdge, width)
|
||||||
+ getSample(box.zy, outerEdge, width);
|
+ getSample(box.zy, outerEdge, width);
|
||||||
|
|
||||||
// weighted average, with 4 extra points having 0.5 weight each,
|
// weighted average, with 4 extra points having 0.5 weight each,
|
||||||
// so 1 + 0.5*4 = 3 is the divisor
|
// so 1 + 0.5*4 = 3 is the divisor
|
||||||
alpha = (alpha + 0.5 * asum) / 3.0;
|
alpha = (alpha + 0.5 * asum) / 3.0;
|
||||||
|
|
||||||
textColor = vec4(color.xyz, alpha);//textColor.* alpha);
|
textColor = vec4(color.xyz, alpha);//textColor.* alpha);
|
||||||
textColor.xyz = pow(textColor.xyz, vec3(2.2)); // gamma correction
|
textColor.xyz = pow(textColor.xyz, vec3(2.2)); // gamma correction
|
||||||
|
|
||||||
// Premultiplied alpha output.
|
// Premultiplied alpha output.
|
||||||
outFragColor = textColor;
|
outFragColor = textColor;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
float alpha = 1.0;
|
float alpha = 1.0;
|
||||||
float gray = dot(color.xyz, vec3(0.2126, 0.7152, 0.0722));
|
float gray = dot(color.xyz, vec3(0.2126, 0.7152, 0.0722));
|
||||||
outFragColor = vec4(color.xyz , pow(tex.x / gray, 1/(2.2)) );//textColor.* alpha);
|
outFragColor = vec4(color.xyz , pow(tex.x / gray, 1/(2.2)) );//textColor.* alpha);
|
||||||
//outFragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
//outFragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* debug test.
|
/* debug test.
|
||||||
if(!rect(pixelPosition, position, size))
|
if(!rect(pixelPosition, position, size))
|
||||||
{
|
{
|
||||||
outFragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
outFragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
@ -1,28 +1,28 @@
|
||||||
#version 460
|
#version 460
|
||||||
|
|
||||||
layout(location = 0) in vec3 texPosition;
|
layout(location = 0) in vec3 texPosition;
|
||||||
layout(location = 1) in vec3 texNormal;
|
layout(location = 1) in vec3 texNormal;
|
||||||
layout(location = 2) in vec4 texColor;
|
layout(location = 2) in vec4 texColor;
|
||||||
layout(location = 3) in vec2 texCoord;
|
layout(location = 3) in vec2 texCoord;
|
||||||
|
|
||||||
layout (location = 0) out vec4 fragColor;
|
layout (location = 0) out vec4 fragColor;
|
||||||
layout (location = 1) out vec2 texCoords;
|
layout (location = 1) out vec2 texCoords;
|
||||||
layout (location = 2) out int instanceId;
|
layout (location = 2) out int instanceId;
|
||||||
layout (location = 3) out vec2 pixelPosition;
|
layout (location = 3) out vec2 pixelPosition;
|
||||||
|
|
||||||
#include "FontSDFShared.glsl"
|
#include "FontSDFShared.glsl"
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec2 pos = fontBuffer.fontInfo[gl_BaseInstance].position;
|
vec2 pos = fontBuffer.fontInfo[gl_BaseInstance].position;
|
||||||
vec2 size = fontBuffer.fontInfo[gl_BaseInstance].size;
|
vec2 size = fontBuffer.fontInfo[gl_BaseInstance].size;
|
||||||
|
|
||||||
vec2 t = texPosition.xy + pos;
|
vec2 t = texPosition.xy + pos;
|
||||||
pixelPosition = t;
|
pixelPosition = t;
|
||||||
//gl_Position = vec4(( (texPosition.xy + pos) / PushConstants.extent) * 2 + vec2(-1.0f, -1.0f), texPosition.z, 1.0);
|
//gl_Position = vec4(( (texPosition.xy + pos) / PushConstants.extent) * 2 + vec2(-1.0f, -1.0f), texPosition.z, 1.0);
|
||||||
gl_Position = vec4((t / PushConstants.extent) * 2 + vec2(-1.0f, -1.0f), texPosition.z, 1.0);
|
gl_Position = vec4((t / PushConstants.extent) * 2 + vec2(-1.0f, -1.0f), texPosition.z, 1.0);
|
||||||
|
|
||||||
texCoords = texCoord;
|
texCoords = texCoord;
|
||||||
fragColor = texColor;
|
fragColor = texColor;
|
||||||
instanceId = gl_BaseInstance;
|
instanceId = gl_BaseInstance;
|
||||||
}
|
}
|
||||||
|
|
@ -1,111 +1,111 @@
|
||||||
#version 460
|
#version 460
|
||||||
|
|
||||||
//shader input
|
//shader input
|
||||||
layout (location = 0) in vec4 fragColor;
|
layout (location = 0) in vec4 fragColor;
|
||||||
layout (location = 1) in vec2 texCoord;
|
layout (location = 1) in vec2 texCoord;
|
||||||
layout (location = 2) in vec2 panelPixelPosition; // relative to the topleft
|
layout (location = 2) in vec2 panelPixelPosition; // relative to the topleft
|
||||||
layout (location = 3) flat in int instanceId;
|
layout (location = 3) flat in int instanceId;
|
||||||
|
|
||||||
layout (location = 0) out vec4 outFragColor;
|
layout (location = 0) out vec4 outFragColor;
|
||||||
|
|
||||||
layout (set = 1, binding = 0) uniform sampler2D tex;
|
layout (set = 1, binding = 0) uniform sampler2D tex;
|
||||||
|
|
||||||
|
|
||||||
#include "PapyrusRectShared.glsl"
|
#include "PapyrusRectShared.glsl"
|
||||||
#include "FragmentHelpers.glsl"
|
#include "FragmentHelpers.glsl"
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec2 imageSize = objectBuffer.objects[instanceId].imageSize;
|
vec2 imageSize = objectBuffer.objects[instanceId].imageSize;
|
||||||
vec4 rounding = objectBuffer.objects[instanceId].rounding;
|
vec4 rounding = objectBuffer.objects[instanceId].rounding;
|
||||||
vec4 borderColor = objectBuffer.objects[instanceId].borderColor;
|
vec4 borderColor = objectBuffer.objects[instanceId].borderColor;
|
||||||
float borderWidth = objectBuffer.objects[instanceId].borderWidth;
|
float borderWidth = objectBuffer.objects[instanceId].borderWidth;
|
||||||
float alpha = fragColor.w;
|
float alpha = fragColor.w;
|
||||||
uint usesImage = objectBuffer.objects[instanceId].flags & 1;
|
uint usesImage = objectBuffer.objects[instanceId].flags & 1;
|
||||||
|
|
||||||
// check to discard topleft
|
// check to discard topleft
|
||||||
vec3 color = fragColor.xyz;
|
vec3 color = fragColor.xyz;
|
||||||
if(panelPixelPosition.x < rounding.x && panelPixelPosition.y < rounding.y)
|
if(panelPixelPosition.x < rounding.x && panelPixelPosition.y < rounding.y)
|
||||||
{
|
{
|
||||||
float dist = distance(panelPixelPosition, vec2(rounding.x, rounding.x));
|
float dist = distance(panelPixelPosition, vec2(rounding.x, rounding.x));
|
||||||
if(dist > (rounding.x ))
|
if(dist > (rounding.x ))
|
||||||
{
|
{
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
else if(somewhatEqual(dist, rounding.x))
|
else if(somewhatEqual(dist, rounding.x))
|
||||||
{
|
{
|
||||||
color = borderColor.xyz;
|
color = borderColor.xyz;
|
||||||
alpha = borderColor.w;
|
alpha = borderColor.w;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// top right
|
// top right
|
||||||
if(panelPixelPosition.x > imageSize.x - rounding.y && panelPixelPosition.y < rounding.y )
|
if(panelPixelPosition.x > imageSize.x - rounding.y && panelPixelPosition.y < rounding.y )
|
||||||
{
|
{
|
||||||
float dist = distance(panelPixelPosition, vec2(imageSize.x - rounding.y, rounding.y));
|
float dist = distance(panelPixelPosition, vec2(imageSize.x - rounding.y, rounding.y));
|
||||||
if(dist > rounding.y)
|
if(dist > rounding.y)
|
||||||
{
|
{
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
else if(somewhatEqual(dist, rounding.y))
|
else if(somewhatEqual(dist, rounding.y))
|
||||||
{
|
{
|
||||||
color = borderColor.xyz;
|
color = borderColor.xyz;
|
||||||
alpha = borderColor.w;
|
alpha = borderColor.w;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// bottom Left
|
// bottom Left
|
||||||
if(panelPixelPosition.x < rounding.x && panelPixelPosition.y > imageSize.y - rounding.y)
|
if(panelPixelPosition.x < rounding.x && panelPixelPosition.y > imageSize.y - rounding.y)
|
||||||
{
|
{
|
||||||
float dist = distance(panelPixelPosition, vec2(rounding.x, imageSize.y - rounding.y));
|
float dist = distance(panelPixelPosition, vec2(rounding.x, imageSize.y - rounding.y));
|
||||||
if(dist > rounding.y)
|
if(dist > rounding.y)
|
||||||
{
|
{
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
else if(somewhatEqual(dist, rounding.y))
|
else if(somewhatEqual(dist, rounding.y))
|
||||||
{
|
{
|
||||||
color = borderColor.xyz;
|
color = borderColor.xyz;
|
||||||
alpha = borderColor.w;
|
alpha = borderColor.w;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// bottom right
|
// bottom right
|
||||||
if(panelPixelPosition.x > imageSize.x - rounding.a && imageSize.y - panelPixelPosition.y < rounding.a )
|
if(panelPixelPosition.x > imageSize.x - rounding.a && imageSize.y - panelPixelPosition.y < rounding.a )
|
||||||
{
|
{
|
||||||
float dist = distance(panelPixelPosition, vec2(imageSize.x - rounding.x, imageSize.y - rounding.y));
|
float dist = distance(panelPixelPosition, vec2(imageSize.x - rounding.x, imageSize.y - rounding.y));
|
||||||
if(dist > rounding.y)
|
if(dist > rounding.y)
|
||||||
{
|
{
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
else if(somewhatEqual(dist, rounding.y))
|
else if(somewhatEqual(dist, rounding.y))
|
||||||
{
|
{
|
||||||
color = borderColor.xyz;
|
color = borderColor.xyz;
|
||||||
alpha = borderColor.w;
|
alpha = borderColor.w;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check to discard topright
|
// check to discard topright
|
||||||
|
|
||||||
// determine border colors
|
// determine border colors
|
||||||
|
|
||||||
if( panelPixelPosition.x < borderWidth
|
if( panelPixelPosition.x < borderWidth
|
||||||
|| panelPixelPosition.x > imageSize.x - borderWidth
|
|| panelPixelPosition.x > imageSize.x - borderWidth
|
||||||
|| panelPixelPosition.y < borderWidth
|
|| panelPixelPosition.y < borderWidth
|
||||||
|| panelPixelPosition.y > imageSize.y - borderWidth
|
|| panelPixelPosition.y > imageSize.y - borderWidth
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
color = borderColor.xyz;
|
color = borderColor.xyz;
|
||||||
alpha = borderColor.w;
|
alpha = borderColor.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
// scale the color
|
// scale the color
|
||||||
if(usesImage > 0)
|
if(usesImage > 0)
|
||||||
{
|
{
|
||||||
vec4 sampledColor = texture(tex, vec2(texCoord.x, 1 - texCoord.y));
|
vec4 sampledColor = texture(tex, vec2(texCoord.x, 1 - texCoord.y));
|
||||||
outFragColor = vec4(sampledColor.rgb, sampledColor.a * alpha);
|
outFragColor = vec4(sampledColor.rgb, sampledColor.a * alpha);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
outFragColor = vec4(pow(color, vec3(2.2)), alpha);
|
outFragColor = vec4(pow(color, vec3(2.2)), alpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,46 +1,46 @@
|
||||||
//we will be using glsl version 4.5 syntax
|
//we will be using glsl version 4.5 syntax
|
||||||
#version 460
|
#version 460
|
||||||
|
|
||||||
layout (location = 0) in vec3 vPosition;
|
layout (location = 0) in vec3 vPosition;
|
||||||
layout (location = 1) in vec3 vNormal;
|
layout (location = 1) in vec3 vNormal;
|
||||||
layout (location = 2) in vec4 vColor;
|
layout (location = 2) in vec4 vColor;
|
||||||
layout (location = 3) in vec2 vTexCoord;
|
layout (location = 3) in vec2 vTexCoord;
|
||||||
|
|
||||||
layout (location = 0) out vec4 outColor;
|
layout (location = 0) out vec4 outColor;
|
||||||
layout (location = 1) out vec2 texCoord;
|
layout (location = 1) out vec2 texCoord;
|
||||||
layout (location = 2) out vec2 panelPixelPosition;
|
layout (location = 2) out vec2 panelPixelPosition;
|
||||||
layout (location = 3) out int instanceId;
|
layout (location = 3) out int instanceId;
|
||||||
|
|
||||||
#include "PapyrusRectShared.glsl"
|
#include "PapyrusRectShared.glsl"
|
||||||
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec2 imagePosition = objectBuffer.objects[gl_BaseInstance].imagePosition;
|
vec2 imagePosition = objectBuffer.objects[gl_BaseInstance].imagePosition;
|
||||||
vec2 imageSize = objectBuffer.objects[gl_BaseInstance].imageSize;
|
vec2 imageSize = objectBuffer.objects[gl_BaseInstance].imageSize;
|
||||||
vec2 anchor = objectBuffer.objects[gl_BaseInstance].anchorPoint;
|
vec2 anchor = objectBuffer.objects[gl_BaseInstance].anchorPoint;
|
||||||
vec2 scale = objectBuffer.objects[gl_BaseInstance].scale;
|
vec2 scale = objectBuffer.objects[gl_BaseInstance].scale;
|
||||||
float alpha = objectBuffer.objects[gl_BaseInstance].alpha;
|
float alpha = objectBuffer.objects[gl_BaseInstance].alpha;
|
||||||
vec4 baseColor = objectBuffer.objects[gl_BaseInstance].baseColor;
|
vec4 baseColor = objectBuffer.objects[gl_BaseInstance].baseColor;
|
||||||
|
|
||||||
vec2 finalSize = (imageSize / PushConstants.extent);
|
vec2 finalSize = (imageSize / PushConstants.extent);
|
||||||
//float zLevel = objectBuffer.objects[gl_BaseInstance].zLevel;
|
//float zLevel = objectBuffer.objects[gl_BaseInstance].zLevel;
|
||||||
|
|
||||||
vec2 finalPos = ((imagePosition / PushConstants.extent) * 2 - 1) - anchor * finalSize * scale;
|
vec2 finalPos = ((imagePosition / PushConstants.extent) * 2 - 1) - anchor * finalSize * scale;
|
||||||
|
|
||||||
outColor = baseColor;
|
outColor = baseColor;
|
||||||
//outColor = vec3(vColor.x, vColor.y, vColor.z);
|
//outColor = vec3(vColor.x, vColor.y, vColor.z);
|
||||||
vec4 fp = vec4(
|
vec4 fp = vec4(
|
||||||
finalPos.x + ( vPosition.x * finalSize.x * scale.x),
|
finalPos.x + ( vPosition.x * finalSize.x * scale.x),
|
||||||
finalPos.y + (-vPosition.y * finalSize.y * scale.y),
|
finalPos.y + (-vPosition.y * finalSize.y * scale.y),
|
||||||
vPosition.z, 1.0
|
vPosition.z, 1.0
|
||||||
);
|
);
|
||||||
//1.0);
|
//1.0);
|
||||||
gl_Position = fp;
|
gl_Position = fp;
|
||||||
//gl_Position = vec4( ((position.x) - 1.3) * 0.3 * 1.3, (-position.y + 0.05) * 1.3, position.z, 1.0); // + vec4(imagePosition, 0.0f, 1.0f);
|
//gl_Position = vec4( ((position.x) - 1.3) * 0.3 * 1.3, (-position.y + 0.05) * 1.3, position.z, 1.0); // + vec4(imagePosition, 0.0f, 1.0f);
|
||||||
texCoord = vec2(1 - vTexCoord.x, vTexCoord.y);
|
texCoord = vec2(1 - vTexCoord.x, vTexCoord.y);
|
||||||
panelPixelPosition = (vPosition.xy - anchor) / 2 * imageSize;
|
panelPixelPosition = (vPosition.xy - anchor) / 2 * imageSize;
|
||||||
panelPixelPosition.y = imageSize.y - panelPixelPosition.y;
|
panelPixelPosition.y = imageSize.y - panelPixelPosition.y;
|
||||||
instanceId = gl_BaseInstance;
|
instanceId = gl_BaseInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
|
|
||||||
pub const VkCommand = union(enum(u8)) {
|
pub const VkCommand = union(enum(u8)) {
|
||||||
image: struct {
|
image: struct {
|
||||||
index: u32,
|
index: u32,
|
||||||
imageSet: ?vk.DescriptorSet,
|
imageSet: ?vk.DescriptorSet,
|
||||||
},
|
},
|
||||||
text: struct {
|
text: struct {
|
||||||
index: u32,
|
index: u32,
|
||||||
small: bool,
|
small: bool,
|
||||||
ssbo: u32,
|
ssbo: u32,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -1,46 +1,46 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const core = @import("core");
|
const core = @import("core");
|
||||||
const graphics = @import("graphics");
|
const graphics = @import("graphics");
|
||||||
const memory = core.MemoryTracker;
|
const memory = core.MemoryTracker;
|
||||||
|
|
||||||
pub const papyrus = @import("papyrus");
|
pub const papyrus = @import("papyrus");
|
||||||
pub const HandlerError = papyrus.HandlerError;
|
pub const HandlerError = papyrus.HandlerError;
|
||||||
pub const NodeHandle = papyrus.NodeHandle;
|
pub const NodeHandle = papyrus.NodeHandle;
|
||||||
pub const LocText = papyrus.LocText;
|
pub const LocText = papyrus.LocText;
|
||||||
pub const PressedType = papyrus.PressedType;
|
pub const PressedType = papyrus.PressedType;
|
||||||
pub const PapyrusSystem = @import("PapyrusIntegration.zig");
|
pub const PapyrusSystem = @import("PapyrusIntegration.zig");
|
||||||
|
|
||||||
var gPapyrus: *PapyrusSystem = undefined;
|
var gPapyrus: *PapyrusSystem = undefined;
|
||||||
|
|
||||||
pub const Module: core.ModuleDescription = .{
|
pub const Module: core.ModuleDescription = .{
|
||||||
.name = "ui",
|
.name = "ui",
|
||||||
.enabledByDefault = true,
|
.enabledByDefault = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn getSystem() *PapyrusSystem {
|
pub fn getSystem() *PapyrusSystem {
|
||||||
return gPapyrus;
|
return gPapyrus;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getContext() *papyrus.Context {
|
pub fn getContext() *papyrus.Context {
|
||||||
return gPapyrus.papyrusCtx;
|
return gPapyrus.papyrusCtx;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_module(comptime spec: anytype, args: anytype, allocator: std.mem.Allocator) !void {
|
pub fn start_module(comptime spec: anytype, args: anytype, allocator: std.mem.Allocator) !void {
|
||||||
_ = args;
|
_ = args;
|
||||||
_ = spec;
|
_ = spec;
|
||||||
_ = allocator;
|
_ = allocator;
|
||||||
|
|
||||||
// no initialization
|
// no initialization
|
||||||
if (core.isUtility()) {
|
if (core.isUtility()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gPapyrus = try core.gEngine.createObject(PapyrusSystem, .{ .can_tick = true });
|
gPapyrus = try core.gEngine.createObject(PapyrusSystem, .{ .can_tick = true });
|
||||||
try gPapyrus.setup(graphics.getContext());
|
try gPapyrus.setup(graphics.getContext());
|
||||||
core.engine_logs("ui start_module");
|
core.engine_logs("ui start_module");
|
||||||
memory.MTPrintStatsDelta();
|
memory.MTPrintStatsDelta();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shutdown_module(allocator: std.mem.Allocator) void {
|
pub fn shutdown_module(allocator: std.mem.Allocator) void {
|
||||||
_ = allocator;
|
_ = allocator;
|
||||||
}
|
}
|
||||||
|
|
@ -1,86 +1,86 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
// very tiny, not intended to build anything just to run tests linked with libc
|
// very tiny, not intended to build anything just to run tests linked with libc
|
||||||
pub fn build(b: *std.Build) void {
|
pub fn build(b: *std.Build) void {
|
||||||
const target = b.standardTargetOptions(.{});
|
const target = b.standardTargetOptions(.{});
|
||||||
const optimize = b.standardOptimizeOption(.{});
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
|
||||||
const mod = b.addModule("vkImgui", .{
|
const mod = b.addModule("vkImgui", .{
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
.link_libc = true,
|
.link_libc = true,
|
||||||
.root_source_file = b.path("src/vkImgui.zig"),
|
.root_source_file = b.path("src/vkImgui.zig"),
|
||||||
});
|
});
|
||||||
|
|
||||||
mod.addIncludePath(b.path("cimgui"));
|
mod.addIncludePath(b.path("cimgui"));
|
||||||
mod.addIncludePath(b.path("cimplot"));
|
mod.addIncludePath(b.path("cimplot"));
|
||||||
mod.addIncludePath(b.path("cimgui/imgui"));
|
mod.addIncludePath(b.path("cimgui/imgui"));
|
||||||
mod.addIncludePath(b.path("cimgui/imgui/backends"));
|
mod.addIncludePath(b.path("cimgui/imgui/backends"));
|
||||||
|
|
||||||
const cimgui = b.addStaticLibrary(.{
|
const cimgui = b.addStaticLibrary(.{
|
||||||
.name = "cimgui",
|
.name = "cimgui",
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
cimgui.linkLibC();
|
cimgui.linkLibC();
|
||||||
if (target.result.abi != .msvc)
|
if (target.result.abi != .msvc)
|
||||||
cimgui.linkLibCpp();
|
cimgui.linkLibCpp();
|
||||||
cimgui.addIncludePath(b.path("cimgui"));
|
cimgui.addIncludePath(b.path("cimgui"));
|
||||||
cimgui.addIncludePath(b.path("cimplot"));
|
cimgui.addIncludePath(b.path("cimplot"));
|
||||||
cimgui.addIncludePath(b.path("cimgui/imgui"));
|
cimgui.addIncludePath(b.path("cimgui/imgui"));
|
||||||
cimgui.addIncludePath(b.path("cimgui/imgui/backends"));
|
cimgui.addIncludePath(b.path("cimgui/imgui/backends"));
|
||||||
|
|
||||||
cimgui.addCSourceFiles(.{
|
cimgui.addCSourceFiles(.{
|
||||||
.root = b.path("cimgui/imgui"),
|
.root = b.path("cimgui/imgui"),
|
||||||
.files = &[_][]const u8{
|
.files = &[_][]const u8{
|
||||||
"cimgui.cpp",
|
"cimgui.cpp",
|
||||||
"cimgui_compat.cpp",
|
"cimgui_compat.cpp",
|
||||||
"imgui.cpp",
|
"imgui.cpp",
|
||||||
"imgui_demo.cpp",
|
"imgui_demo.cpp",
|
||||||
"imgui_draw.cpp",
|
"imgui_draw.cpp",
|
||||||
"imgui_tables.cpp",
|
"imgui_tables.cpp",
|
||||||
"imgui_widgets.cpp",
|
"imgui_widgets.cpp",
|
||||||
"backends/imgui_impl_vulkan.cpp",
|
"backends/imgui_impl_vulkan.cpp",
|
||||||
"backends/imgui_impl_glfw.cpp",
|
"backends/imgui_impl_glfw.cpp",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
cimgui.addCSourceFiles(.{
|
cimgui.addCSourceFiles(.{
|
||||||
.root = b.path("cimplot"),
|
.root = b.path("cimplot"),
|
||||||
.files = &[_][]const u8{
|
.files = &[_][]const u8{
|
||||||
"cimplot.cpp",
|
"cimplot.cpp",
|
||||||
"implot/implot.cpp",
|
"implot/implot.cpp",
|
||||||
"implot/implot_demo.cpp",
|
"implot/implot_demo.cpp",
|
||||||
"implot/implot_items.cpp",
|
"implot/implot_items.cpp",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const depList = [_][]const u8{
|
const depList = [_][]const u8{
|
||||||
"core",
|
"core",
|
||||||
"graphics",
|
"graphics",
|
||||||
"platform",
|
"platform",
|
||||||
"vulkan",
|
"vulkan",
|
||||||
};
|
};
|
||||||
|
|
||||||
for (depList) |depName| {
|
for (depList) |depName| {
|
||||||
const dep = b.dependency(depName, .{ .target = target, .optimize = optimize });
|
const dep = b.dependency(depName, .{ .target = target, .optimize = optimize });
|
||||||
const depMod = dep.module(depName);
|
const depMod = dep.module(depName);
|
||||||
mod.addImport(depName, depMod);
|
mod.addImport(depName, depMod);
|
||||||
}
|
}
|
||||||
|
|
||||||
mod.linkLibrary(cimgui);
|
mod.linkLibrary(cimgui);
|
||||||
|
|
||||||
// I could've made cimgui a seperate lib,
|
// I could've made cimgui a seperate lib,
|
||||||
// I can seperate it out later if needed.
|
// I can seperate it out later if needed.
|
||||||
const test_step = b.step("test", "run unit tests for ui");
|
const test_step = b.step("test", "run unit tests for ui");
|
||||||
const tests = b.addTest(.{
|
const tests = b.addTest(.{
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
.root_source_file = b.path("tests/tests.zig"),
|
.root_source_file = b.path("tests/tests.zig"),
|
||||||
});
|
});
|
||||||
|
|
||||||
tests.root_module.addImport("vkImgui", mod);
|
tests.root_module.addImport("vkImgui", mod);
|
||||||
const runArtifact = b.addRunArtifact(tests);
|
const runArtifact = b.addRunArtifact(tests);
|
||||||
test_step.dependOn(&runArtifact.step);
|
test_step.dependOn(&runArtifact.step);
|
||||||
b.installArtifact(tests);
|
b.installArtifact(tests);
|
||||||
}
|
}
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
.{
|
.{
|
||||||
.name = "imgui",
|
.name = "imgui",
|
||||||
.version = "0.0.0",
|
.version = "0.0.0",
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
.core = .{ .path = "../core" },
|
.core = .{ .path = "../core" },
|
||||||
.graphics = .{ .path = "../graphics" },
|
.graphics = .{ .path = "../graphics" },
|
||||||
.platform = .{ .path = "../platform" },
|
.platform = .{ .path = "../platform" },
|
||||||
.vulkan = .{ .path = "../../lib/vulkan" },
|
.vulkan = .{ .path = "../../lib/vulkan" },
|
||||||
},
|
},
|
||||||
.paths = .{
|
.paths = .{
|
||||||
"",
|
"",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue