Commit for 2020.10.21.7z

This commit is contained in:
mrq 2020-10-21 00:00:00 -05:00
parent 1393f1b77a
commit 7027ce2db7
36 changed files with 352 additions and 703 deletions

View File

@ -15,19 +15,19 @@ UF_LIBS =
# EXT_LIBS = -lpng16 -lz -lassimp -lsfml-main -lsfml-system -lsfml-window -lsfml-graphics -llua52
# EXT_LIBS = -lpng16 -lz -lassimp -ljsoncpp -lopenal32 -lalut -lvorbis -lvorbisfile -logg -lfreetype
EXT_LIBS =
#FLAGS = -Og -DUF_DISABLE_ALIGNAS -std=c++20 -Wno-c++11-narrowing -Wno-narrowing -g -DVK_USE_PLATFORM_WIN32_KHR -DUF_USE_VULKAN -DGLM_ENABLE_EXPERIMENTAL -DUF_USE_JSON -DUF_USE_NCURSES -DUF_USE_OPENAL -DUF_USE_VORBIS -DUF_USE_FREETYPE -DUSE_OPENVR_MINGW
FLAGS = -std=c++20 -Wno-c++11-narrowing -Wno-narrowing -g -DVK_USE_PLATFORM_WIN32_KHR -DUF_USE_VULKAN -DGLM_ENABLE_EXPERIMENTAL -DUF_USE_JSON -DUF_USE_NCURSES -DUF_USE_OPENAL -DUF_USE_VORBIS -DUF_USE_FREETYPE -DUSE_OPENVR_MINGW
#FLAGS = -std=c++0x -Wall -g -DUF_USE_JSON -DUF_USE_NCURSES -DUF_USE_OPENGL -DUF_USE_GLEW
FLAGS = -Og -std=c++17 -g -DVK_USE_PLATFORM_WIN32_KHR -DUF_USE_VULKAN -DGLM_ENABLE_EXPERIMENTAL -DUF_USE_JSON -DUF_USE_OPENAL -DUF_USE_VORBIS -DUF_USE_FREETYPE -DUSE_OPENVR_MINGW
#-march=native
LIB_NAME = uf
EXT_LIB_NAME = ext
#VULKAN_WIN64_SDK_PATH = /c/VulkanSDK/1.1.101.0/
#VULKAN_WIN64_SDK_PATH = /c/VulkanSDK/1.1.108.0/
#VULKAN_WIN64_SDK_PATH = /c/VulkanSDK/1.1.114.0/
#VULKAN_WIN64_SDK_PATH = /cygdrive/c/VulkanSDK/1.1.101.0/
#VULKAN_WIN64_SDK_PATH = /cygdrive/c/VulkanSDK/1.1.108.0/
#VULKAN_WIN64_SDK_PATH = /cygdrive/c/VulkanSDK/1.1.114.0/
#VULKAN_WIN64_SDK_PATH = /c/VulkanSDK/1.2.141.2/
VULKAN_WIN64_SDK_PATH = /c/VulkanSDK/1.2.154.0/
WIN64_CC = g++
WIN64_CC = /opt/mingw-w64/x86_64-7.2.0-posix-seh-rt_v5-rev1/mingw64/bin/g++
WIN64_GLSL_VALIDATOR = $(VULKAN_WIN64_SDK_PATH)/Bin32/glslangValidator
# Base Engine's DLL
WIN64_INC_DIR = $(ENGINE_INC_DIR)/win64
@ -39,8 +39,8 @@ WIN64_FLAGS = $(FLAGS) -g
#-Wl,-subsystem,windows
WIN64_LIB_DIR = $(ENGINE_LIB_DIR)/win64/
WIN64_INCS = -I$(ENGINE_INC_DIR) -I$(WIN64_INC_DIR) -I$(VULKAN_WIN64_SDK_PATH)/include
WIN64_LIBS = -L$(ENGINE_LIB_DIR) -L$(WIN64_LIB_DIR) -L$(VULKAN_WIN64_SDK_PATH)/Lib
WIN64_INCS = -I$(ENGINE_INC_DIR) -I$(WIN64_INC_DIR) -I$(VULKAN_WIN64_SDK_PATH)/include -I/mingw64/include
WIN64_LIBS = -L$(ENGINE_LIB_DIR) -L$(WIN64_LIB_DIR) -L$(VULKAN_WIN64_SDK_PATH)/Lib -L/mingw64/lib
SRCS_WIN64_DLL = $(wildcard $(ENGINE_SRC_DIR)/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*/*/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*/*/*/*.cpp)
OBJS_WIN64_DLL = $(patsubst %.cpp,%.win64.o,$(SRCS_WIN64_DLL))
@ -56,8 +56,8 @@ EXT_WIN64_FLAGS = $(FLAGS)
#-Wl,-subsystem,windows
EXT_WIN64_LIB_DIR = $(ENGINE_LIB_DIR)/win64/
EXT_WIN64_INCS = -I$(ENGINE_INC_DIR) -I$(EXT_WIN64_INC_DIR) -I$(VULKAN_WIN64_SDK_PATH)/include
EXT_WIN64_LIBS = -L$(ENGINE_LIB_DIR) -L$(EXT_WIN64_LIB_DIR) -L$(VULKAN_WIN64_SDK_PATH)/Lib
EXT_WIN64_INCS = -I$(ENGINE_INC_DIR) -I$(EXT_WIN64_INC_DIR) -I$(VULKAN_WIN64_SDK_PATH)/include -I/mingw64/include
EXT_WIN64_LIBS = -L$(ENGINE_LIB_DIR) -L$(EXT_WIN64_LIB_DIR) -L$(VULKAN_WIN64_SDK_PATH)/Lib -L/mingw64/lib
SRCS_EXT_WIN64_DLL = $(wildcard $(EXT_SRC_DIR)/*.cpp) $(wildcard $(EXT_SRC_DIR)/*/*.cpp) $(wildcard $(EXT_SRC_DIR)/*/*/*.cpp) $(wildcard $(EXT_SRC_DIR)/*/*/*/*.cpp) $(wildcard $(EXT_SRC_DIR)/*/*/*/*/*.cpp)
OBJS_EXT_WIN64_DLL = $(patsubst %.cpp,%.win64.o,$(SRCS_EXT_WIN64_DLL))
@ -72,10 +72,6 @@ TARGET_WIN64 = $(BIN_DIR)/$(TARGET_NAME).exe
SRCS_SHADERS = $(wildcard bin/data/shaders/*.glsl)
TARGET_SHADERS = $(patsubst %.glsl,%.spv,$(SRCS_SHADERS))
# clang-win64: WIN64_CC=clang++
# make
# gcc-win64: WIN64_CC=g++
# make
win64: $(EX_WIN64_DLL) $(EXT_EX_WIN64_DLL) $(TARGET_WIN64) $(TARGET_SHADERS)
rm-exe64:

View File

@ -32,6 +32,7 @@ struct Light {
vec3 color;
float power;
vec2 type;
vec2 padding;
mat4 view;
mat4 projection;
};
@ -44,6 +45,7 @@ struct State {
struct Fog {
vec2 range;
vec2 padding;
vec4 color;
};

View File

@ -1,10 +1,10 @@
template<typename C>
pod::NamedTypes<C>::type_t pod::NamedTypes<C>::getType( const std::string& name ) {
typename pod::NamedTypes<C>::type_t pod::NamedTypes<C>::getType( const std::string& name ) {
for ( auto pair : names ) if ( pair.second == name ) return pair.first;
return getType<void>();
}
template<typename C>
template<typename T> pod::NamedTypes<C>::type_t pod::NamedTypes<C>::getType() {
template<typename T> typename pod::NamedTypes<C>::type_t pod::NamedTypes<C>::getType() {
return std::type_index(typeid(T));
}
template<typename C>

View File

@ -97,6 +97,8 @@ namespace ext {
};
VkQueue& getQueue( QueueEnum );
VkCommandPool& getCommandPool( QueueEnum );
VkQueue& getQueue( QueueEnum, std::thread::id );
VkCommandPool& getCommandPool( QueueEnum, std::thread::id );
// RAII
void initialize();

View File

@ -104,6 +104,7 @@ namespace ext {
Pipeline& getPipeline( Descriptor& descriptor );
void record( VkCommandBuffer commandBuffer );
void record( VkCommandBuffer commandBuffer, Descriptor& descriptor );
};
}
}

View File

@ -8,6 +8,7 @@ namespace ext {
struct UF_API RenderMode {
bool execute = false;
bool rebuild = false;
uint32_t width = 0, height = 0;
std::string name = "";
@ -16,18 +17,25 @@ namespace ext {
VkSemaphore renderCompleteSemaphore;
std::vector<VkFence> fences;
std::vector<VkCommandBuffer> commands;
typedef std::vector<VkCommandBuffer> commands_container_t;
std::thread::id mostRecentCommandPoolId;
std::unordered_map<std::thread::id, commands_container_t> commands;
// virtual ~RenderMode();
// RAII
virtual std::string getType() const;
const std::string& getName() const;
const std::string& getName( bool = false ) const;
virtual RenderTarget& getRenderTarget(size_t = 0);
virtual const RenderTarget& getRenderTarget(size_t = 0) const;
virtual commands_container_t& getCommands();
virtual commands_container_t& getCommands( std::thread::id );
virtual void initialize( Device& device );
virtual void createCommandBuffers();
virtual void createCommandBuffers( const std::vector<ext::vulkan::Graphic*>& graphics );
virtual void bindPipelines( const std::vector<ext::vulkan::Graphic*>& graphics );
virtual void tick();
virtual void render();
virtual void destroy();

View File

@ -14,6 +14,7 @@ namespace ext {
// RAII
virtual std::string getType() const;
virtual const std::string& getName( bool ) const;
virtual void createCommandBuffers( const std::vector<ext::vulkan::Graphic*>& graphics );
virtual void initialize( Device& device );

View File

@ -25,8 +25,11 @@ namespace uf {
Audio( Audio&& );
Audio( const Audio& );
*/
~Audio();
bool initialized();
bool playing();
void destroy();
void load( const std::string& = "" );
void play();

View File

@ -10,13 +10,11 @@ namespace {
// Sometimes uint isn't declared
typedef unsigned int uint;
}
/*
namespace uf {
namespace math {
template<typename T>
T lerp( const T& from, const T& to, double delta ) {
T lerp( const T& a, const T& b, double f ) {
return a + f * (b - a);
}
}
}
*/

View File

@ -6,6 +6,7 @@
namespace uf {
namespace io {
std::string UF_API absolute( const std::string& );
std::string UF_API filename( const std::string& );
std::string UF_API extension( const std::string& );
std::string UF_API directory( const std::string& );

View File

@ -9,6 +9,7 @@
#include <thread>
#include <vector>
#include <functional>
#include <condition_variable>
namespace pod {
struct UF_API Thread {
@ -22,6 +23,7 @@ namespace pod {
bool running, terminates;
std::mutex* mutex;
std::condition_variable condition;
std::thread thread;
pod::Thread::queue_t temps;
@ -45,6 +47,7 @@ namespace uf {
// void UF_API tick( pod::Thread&, const std::function<void()>& = NULL );
pod::Thread& UF_API fetchWorker( const std::string& name = "Aux" );
void UF_API batchWorkers( const std::vector<pod::Thread::function_t>&, bool = true, const std::string& name = "Aux" );
void UF_API add( pod::Thread&, const pod::Thread::function_t&, bool = false );
void UF_API process( pod::Thread& );

View File

@ -31,6 +31,7 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) {
//
{
size_t assets = metadata["system"]["assets"].size();
if ( metadata["system"]["load"]["ignore"].isBool() ) assets = 0;
metadata["system"]["load"]["progress"] = 0;
metadata["system"]["load"]["total"] = assets;
if ( assets == 0 ) {
@ -62,6 +63,7 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) {
this->addHook( "asset:Load.%UID%", [&](const std::string& event)->std::string{
uf::Serializer json = event;
std::string filename = json["filename"].asString();
bool initialize = json["initialize"].isNull() ? true : json["initialize"].asBool();
if ( uf::io::extension(filename) != "json" ) return "false";
@ -72,7 +74,8 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) {
json["root"] = uf::io::directory(filename);
json["source"] = filename; // uf::io::filename(filename)
json["hot reload"]["mtime"] = uf::io::mtime( filename ) + 10;
if ( this->loadChildUid(json) == -1 ) return "false";
if ( this->loadChildUid(json, initialize) == -1 ) return "false";
return "true";
});

View File

@ -87,6 +87,7 @@ void uf::LoadingBehavior::tick( uf::Object& self ) {
std::function<void(uf::Entity*)> filter = [&]( uf::Entity* entity ) {
if ( !entity || entity->getUid() == 0 || !entity->hasComponent<uf::Serializer>() ) return;
auto& metadata = entity->getComponent<uf::Serializer>();
if ( metadata["system"]["load"]["ignore"].isBool() ) return;
if ( metadata["system"]["load"].isNull() ) return;
++loading;
if ( metadata["system"]["load"]["progress"].asInt() < metadata["system"]["load"]["total"].asInt() ) return;

View File

@ -31,9 +31,11 @@ bool UF_API_CALL ext::AL::initialize() {
}
return this->m_initialized = true;
*/
bool res = this->m_initialized = (alutInit(NULL, NULL) == AL_TRUE);
this->m_initialized = alutInit(NULL, NULL) == AL_TRUE;
auto error = alutGetError();
std::cout << alutGetErrorString(error) << std::endl;
this->checkError(__FUNCTION__, __LINE__);
return res;
return this->m_initialized;
}
bool UF_API_CALL ext::AL::terminate() {
/*
@ -46,7 +48,9 @@ bool UF_API_CALL ext::AL::terminate() {
}
void UF_API_CALL ext::AL::checkError( const std::string& function, int line, const std::string& aux ) const {
std::string error = this->getError();
// if ( error != "AL_NO_ERROR" ) std::cerr << "AL error @ " << function << ":" << line << ": "<<(aux!=""?"("+aux+") ":"")<< error << std::endl;
if ( error != "AL_NO_ERROR" ) std::cerr << "AL error @ " << function << ":" << line << ": "<<(aux!=""?"("+aux+") ":"")<< error << std::endl;
error = alutGetErrorString(alutGetError());
if ( error != "No ALUT error found" ) std::cerr << "AL error @ " << function << ":" << line << ": "<<(aux!=""?"("+aux+") ":"")<< error << std::endl;
}
std::string UF_API_CALL ext::AL::getError() const {
ALCenum error = alGetError();
@ -58,7 +62,7 @@ std::string UF_API_CALL ext::AL::getError() const {
case AL_INVALID_OPERATION: return "AL_INVALID_OPERATION"; // the requested operation is not valid
case AL_OUT_OF_MEMORY: return "AL_OUT_OF_MEMORY"; // the requested operation resulted in OpenAL running out ofmemory
}
return "AL_UNKNOWN";
return "AL_UNKNOWN(" + std::to_string(error) + ")";
}
void UF_API_CALL ext::AL::listener( ALenum name, std::vector<ALfloat> parameters ) {
switch ( parameters.size() ) {
@ -86,13 +90,12 @@ ext::al::Source::~Source() {
void UF_API_CALL ext::al::Source::generate() {
if ( this->m_index ) this->destroy();
alGenSources(1, &this->m_index);
ext::oal.checkError(__FUNCTION__, __LINE__);
alGenSources(1, &this->m_index); ext::oal.checkError(__FUNCTION__, __LINE__);
}
void UF_API_CALL ext::al::Source::destroy() {
if ( this->m_index && alIsSource(this->m_index) ) {
alDeleteSources(1, &this->m_index);
ext::oal.checkError(__FUNCTION__, __LINE__);
if ( this->playing() ) this->stop();
alDeleteSources(1, &this->m_index); ext::oal.checkError(__FUNCTION__, __LINE__);
}
this->m_index = 0;
}

View File

@ -1,12 +1,11 @@
#include <uf/ext/openvr/openvr.h>
#include <uf/utils/io/iostream.h>
#include <uf/utils/string/ext.h>
#include <uf/utils/string/io.h>
#include <uf/ext/vulkan/vulkan.h>
#include <uf/ext/vulkan/rendermodes/stereoscopic_deferred.h>
#include <filesystem>
#include <stdlib.h>
#define DEBUG_MARKER 0
vr::IVRSystem* ext::openvr::context;
@ -156,10 +155,7 @@ bool ext::openvr::initialize( int stage ) {
// load manifest
{
std::filesystem::path p = ext::openvr::driver.manifest;
p = std::filesystem::absolute( p );
ext::openvr::driver.manifest = p.string();
VR_CHECK_INPUT_RESULT( vr::VRInput()->SetActionManifestPath( ext::openvr::driver.manifest.c_str() ) );
VR_CHECK_INPUT_RESULT( vr::VRInput()->SetActionManifestPath( uf::io::absolute(ext::openvr::driver.manifest).c_str() ) );
// configure action handles
{
uf::Serializer manifest;

View File

@ -436,10 +436,15 @@ VkResult ext::vulkan::Device::createBuffer(
return buffer.bind();
}
VkCommandPool& ext::vulkan::Device::getCommandPool( ext::vulkan::Device::QueueEnum queueEnum) {
return this->getCommandPool( queueEnum, std::this_thread::get_id() );
}
VkQueue& ext::vulkan::Device::getQueue( ext::vulkan::Device::QueueEnum queueEnum ) {
return this->getQueue( queueEnum, std::this_thread::get_id() );
}
VkCommandPool& ext::vulkan::Device::getCommandPool( ext::vulkan::Device::QueueEnum queueEnum, std::thread::id id ) {
uint32_t index = 0;
VkCommandPool* pool = NULL;
bool exists = false;
auto id = std::this_thread::get_id();
switch ( queueEnum ) {
case QueueEnum::GRAPHICS:
index = device.queueFamilyIndices.graphics;
@ -468,11 +473,10 @@ VkCommandPool& ext::vulkan::Device::getCommandPool( ext::vulkan::Device::QueueEn
}
return *pool;
}
VkQueue& ext::vulkan::Device::getQueue( ext::vulkan::Device::QueueEnum queueEnum ) {
VkQueue& ext::vulkan::Device::getQueue( ext::vulkan::Device::QueueEnum queueEnum, std::thread::id id ) {
uint32_t index = 0;
VkQueue* queue = NULL;
bool exists = false;
auto id = std::this_thread::get_id();
switch ( queueEnum ) {
case QueueEnum::GRAPHICS:
index = device.queueFamilyIndices.graphics;

View File

@ -479,6 +479,9 @@ void ext::vulkan::Pipeline::update( Graphic& graphic ) {
// generate fallback empty texture
auto& emptyTexture = Texture2D::empty;
RenderMode& renderMode = ext::vulkan::getRenderMode(graphic.descriptor.renderMode, true);
auto& renderTarget = renderMode.getRenderTarget(graphic.descriptor.renderTarget );
std::vector<VkWriteDescriptorSet> writeDescriptorSets;
std::vector<VkDescriptorSetLayoutBinding> descriptorSetLayoutBindings;
std::vector<VkDescriptorImageInfo> inputDescriptors;
@ -488,9 +491,6 @@ void ext::vulkan::Pipeline::update( Graphic& graphic ) {
descriptorSetLayoutBindings.insert( descriptorSetLayoutBindings.begin(), shader.descriptorSetLayoutBindings.begin(), shader.descriptorSetLayoutBindings.end() );
}
RenderMode& renderMode = ext::vulkan::getRenderMode(graphic.descriptor.renderMode, true);
auto& renderTarget = renderMode.getRenderTarget(graphic.descriptor.renderTarget );
if ( graphic.descriptor.subpass < renderTarget.passes.size() ) {
auto& subpass = renderTarget.passes[graphic.descriptor.subpass];
for ( auto& input : subpass.inputs ) {
@ -563,6 +563,8 @@ void ext::vulkan::Pipeline::update( Graphic& graphic ) {
if ( d.imageLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL )
d.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
} else {
// std::cout << "textures == graphic.material.textures.end()" << std::endl;
}
imageInfos.push_back( d );
}
@ -668,10 +670,11 @@ void ext::vulkan::Pipeline::update( Graphic& graphic ) {
for ( auto& descriptor : writeDescriptorSets ) {
if ( descriptor.pBufferInfo ) {
// std::cout << descriptor.pBufferInfo->offset << std::endl;
if ( descriptor.pBufferInfo->offset % device->properties.limits.minUniformBufferOffsetAlignment != 0 ) {
// std::cout << "Unaligned offset! Expecting " << device->properties.limits.minUniformBufferOffsetAlignment << ", got " << descriptor.pBufferInfo->offset << std::endl;
std::cout << "Invalid descriptor for buffer: " << descriptor.pBufferInfo->buffer << " " << descriptor.pBufferInfo->offset << " " << descriptor.pBufferInfo->range << ", invalidating..." << std::endl;
auto pointer = const_cast<VkDescriptorBufferInfo*>(descriptor.pBufferInfo);
for ( size_t i = 0; i < descriptor.descriptorCount; ++i ) {
if ( descriptor.pBufferInfo[i].offset % device->properties.limits.minUniformBufferOffsetAlignment != 0 ) {
// std::cout << "Unaligned offset! Expecting " << device->properties.limits.minUniformBufferOffsetAlignment << ", got " << descriptor.pBufferInfo[i].offset << std::endl;
std::cout << "Invalid descriptor for buffer: " << descriptor.pBufferInfo[i].buffer << " " << descriptor.pBufferInfo[i].offset << " " << descriptor.pBufferInfo[i].range << ", invalidating..." << std::endl;
auto pointer = const_cast<VkDescriptorBufferInfo*>(&descriptor.pBufferInfo[i]);
pointer->offset = 0;
pointer->range = 0;
pointer->buffer = VK_NULL_HANDLE;
@ -680,7 +683,22 @@ void ext::vulkan::Pipeline::update( Graphic& graphic ) {
}
}
}
}
// render mode's command buffer is in flight, queue a rebuild
// ext::vulkan::rebuild = true;
// renderMode.synchronize();
renderMode.rebuild = true;
/*
std::cout << this << ": " << renderMode.getName() << ": " << renderMode.getType() << " " << descriptorSet << std::endl;
for ( auto& descriptor : writeDescriptorSets ) {
for ( size_t i = 0; i < descriptor.descriptorCount; ++i ) {
if ( descriptor.pImageInfo ) {
std::cout << "[" << i << "]: " << descriptor.pImageInfo[i].imageView << std::endl;
}
}
}
*/
vkUpdateDescriptorSets(
*device,
writeDescriptorSets.size(),
@ -780,12 +798,15 @@ ext::vulkan::Pipeline& ext::vulkan::Graphic::getPipeline( Descriptor& descriptor
return pipelines[descriptor.hash()];
}
void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer ) {
return this->record( commandBuffer, descriptor );
}
void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, Descriptor& descriptor ) {
if ( !this->hasPipeline( descriptor ) ) {
std::cout << this << ": has no valid pipeline" << std::endl;
return;
}
auto& pipeline = this->getPipeline();
auto& pipeline = this->getPipeline( descriptor );
assert( buffers.size() >= 2 );
Buffer& vertexBuffer = buffers.at(0);

View File

@ -17,7 +17,7 @@ ext::vulkan::RenderMode::~RenderMode() {
std::string ext::vulkan::RenderMode::getType() const {
return "";
}
const std::string& ext::vulkan::RenderMode::getName() const {
const std::string& ext::vulkan::RenderMode::getName( bool ) const {
return this->name;
}
ext::vulkan::RenderTarget& ext::vulkan::RenderMode::getRenderTarget( size_t i ) {
@ -52,13 +52,78 @@ void ext::vulkan::RenderMode::createCommandBuffers() {
}
this->synchronize();
//VK_CHECK_RESULT(vkWaitForFences(*device, fences.size(), fences.data(), VK_TRUE, UINT64_MAX));
bindPipelines( graphics );
createCommandBuffers( graphics );
this->mostRecentCommandPoolId = std::this_thread::get_id();
this->rebuild = false;
}
ext::vulkan::RenderMode::commands_container_t& ext::vulkan::RenderMode::getCommands() {
return getCommands( std::this_thread::get_id() );
}
ext::vulkan::RenderMode::commands_container_t& ext::vulkan::RenderMode::getCommands( std::thread::id id ) {
bool exists = this->commands.count(id) > 0;
auto& commands = this->commands[id];
if ( !exists ) {
commands.resize( swapchain.buffers );
VkCommandBufferAllocateInfo cmdBufAllocateInfo = ext::vulkan::initializers::commandBufferAllocateInfo(
this->getType() == "Compute" ? device->getCommandPool(Device::QueueEnum::COMPUTE) : device->getCommandPool(Device::QueueEnum::GRAPHICS),
VK_COMMAND_BUFFER_LEVEL_PRIMARY,
static_cast<uint32_t>(commands.size())
);
VK_CHECK_RESULT(vkAllocateCommandBuffers(*device, &cmdBufAllocateInfo, commands.data()));
}
return commands;
/*
VkCommandPool* pool = NULL;
switch ( queueEnum ) {
case QueueEnum::GRAPHICS:
index = device.queueFamilyIndices.graphics;
if ( commandPool.graphics.count(id) > 0 ) exists = true;
pool = &commandPool.graphics[id];
break;
case QueueEnum::COMPUTE:
index = device.queueFamilyIndices.compute;
if ( commandPool.compute.count(id) > 0 ) exists = true;
pool = &commandPool.compute[id];
break;
case QueueEnum::TRANSFER:
index = device.queueFamilyIndices.transfer;
if ( commandPool.transfer.count(id) > 0 ) exists = true;
pool = &commandPool.transfer[id];
break;
}
if ( !exists ) {
VkCommandPoolCreateFlags createFlags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
VkCommandPoolCreateInfo cmdPoolInfo = {};
cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
cmdPoolInfo.queueFamilyIndex = index;
cmdPoolInfo.flags = createFlags;
if ( vkCreateCommandPool( this->logicalDevice, &cmdPoolInfo, nullptr, pool ) != VK_SUCCESS )
throw std::runtime_error("failed to create command pool for graphics!");
}
return *pool;
*/
}
void ext::vulkan::RenderMode::createCommandBuffers( const std::vector<ext::vulkan::Graphic*>& graphics ) {
}
void ext::vulkan::RenderMode::bindPipelines( const std::vector<ext::vulkan::Graphic*>& graphics ) {
for ( auto* pointer : graphics ) {
auto& graphic = *pointer;
// copy descriptor
ext::vulkan::Graphic::Descriptor descriptor = graphic.descriptor;
// bind to this render mode
descriptor.renderMode = this->getName();
// ignore if pipeline exists for this render mode
if ( graphic.hasPipeline( descriptor ) ) continue;
graphic.initializePipeline( descriptor );
}
}
void ext::vulkan::RenderMode::render() {
auto& commands = getCommands( this->mostRecentCommandPoolId );
// Get next image in the swap chain (back/front buffer)
VK_CHECK_RESULT(swapchain.acquireNextImage(&currentBuffer, swapchain.presentCompleteSemaphore));
@ -101,6 +166,7 @@ void ext::vulkan::RenderMode::initialize( Device& device ) {
}
// Create command buffers
/*
{
commands.resize( swapchain.buffers );
@ -112,6 +178,7 @@ void ext::vulkan::RenderMode::initialize( Device& device ) {
VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, commands.data()));
}
*/
// Set sync objects
{
// Fences (Used to check draw command buffer completion)
@ -119,7 +186,7 @@ void ext::vulkan::RenderMode::initialize( Device& device ) {
fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
// Create in signaled state so we don't wait on first render of each command buffer
fenceCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
fences.resize( commands.size() );
fences.resize( swapchain.buffers );
for ( auto& fence : fences ) {
VK_CHECK_RESULT(vkCreateFence(device, &fenceCreateInfo, nullptr, &fence));
}
@ -143,12 +210,16 @@ void ext::vulkan::RenderMode::destroy() {
this->synchronize();
renderTarget.destroy();
/*
if ( commands.size() > 0 ) {
vkFreeCommandBuffers( *device, this->getType() == "Compute" ? device->getCommandPool(Device::QueueEnum::COMPUTE) : device->getCommandPool(Device::QueueEnum::GRAPHICS), static_cast<uint32_t>(commands.size()), commands.data());
}
commands.clear();
*/
for ( auto& pair : this->commands ) {
vkFreeCommandBuffers( *device, device->getCommandPool(this->getType() == "Compute" ? Device::QueueEnum::COMPUTE : Device::QueueEnum::GRAPHICS, pair.first), static_cast<uint32_t>(pair.second.size()), pair.second.data());
pair.second.clear();
}
if ( renderCompleteSemaphore != VK_NULL_HANDLE ) {
vkDestroySemaphore( *device, renderCompleteSemaphore, nullptr);
renderCompleteSemaphore = VK_NULL_HANDLE;

View File

@ -18,9 +18,6 @@ ext::vulkan::BaseRenderMode::~BaseRenderMode() {
std::string ext::vulkan::BaseRenderMode::getType() const {
return "Swapchain";
}
const std::string& ext::vulkan::BaseRenderMode::getName() const {
return this->name;
}
void ext::vulkan::BaseRenderMode::createCommandBuffers( const std::vector<ext::vulkan::Graphic*>& graphics ) {
if ( ext::vulkan::renderModes.size() > 1 ) return;
@ -47,6 +44,7 @@ void ext::vulkan::BaseRenderMode::createCommandBuffers( const std::vector<ext::v
renderPassBeginInfo.renderArea.extent.height = height;
renderPassBeginInfo.clearValueCount = 2;
renderPassBeginInfo.pClearValues = clearValues;
auto& commands = getCommands();
for (size_t i = 0; i < commands.size(); ++i) {
// Set target frame buffer
renderPassBeginInfo.framebuffer = renderTarget.framebuffers[i];

View File

@ -44,25 +44,18 @@ void ext::vulkan::ComputeRenderMode::initialize( Device& device ) {
auto& metadata = scene.getComponent<uf::Serializer>();
auto& shader = compute.material.shaders.front();
/*
struct SpecializationConstant {
int32_t eyes = 2;
int32_t maxLights = 16;
};
auto& specializationConstants = shader.specializationConstants.get<SpecializationConstant>();
specializationConstants.maxLights = metadata["system"]["config"]["engine"]["scenes"]["max lights"].asUInt64();
specializationConstants.eyes = ext::openvr::context ? 2 : 1;
*/
struct SpecializationConstant {
uint32_t eyes = 2;
uint32_t maxLights = 16;
uint32_t eyes = 2;
};
auto* specializationConstants = (SpecializationConstant*) &shader.specializationConstants[0];
specializationConstants->maxLights = metadata["system"]["config"]["engine"]["scenes"]["max lights"].asUInt64();
specializationConstants->eyes = ext::openvr::context ? 2 : 1;
for ( auto& binding : shader.descriptorSetLayoutBindings ) {
if ( binding.descriptorCount > 1 )
binding.descriptorCount = specializationConstants->maxLights;
if ( binding.descriptorCount > 1 ) {
binding.descriptorCount = specializationConstants->eyes;
}
}
}
@ -106,6 +99,7 @@ void ext::vulkan::ComputeRenderMode::initialize( Device& device ) {
void ext::vulkan::ComputeRenderMode::render() {
if ( compute.buffers.empty() ) return;
auto& commands = getCommands( this->mostRecentCommandPoolId );
// Submit compute commands
// Use a fence to ensure that compute command buffer has finished executing before using it again
VK_CHECK_RESULT(vkWaitForFences( *device, 1, &fences[currentBuffer], VK_TRUE, UINT64_MAX ));
@ -143,13 +137,10 @@ void ext::vulkan::ComputeRenderMode::tick() {
texture = computeTexture;
texture.device = NULL;
}
auto& pipeline = blitter.getPipeline();
pipeline.update( blitter );
blitter.getPipeline().update( blitter );
}
// if ( compute.initialized ) {
if ( !compute.buffers.empty() ) {
auto& pipeline = compute.getPipeline();
pipeline.update( compute );
compute.getPipeline().update( compute );
}
}
}
@ -212,14 +203,16 @@ void ext::vulkan::ComputeRenderMode::createCommandBuffers( ) {
float width = this->width > 0 ? this->width : ext::vulkan::width;
float height = this->height > 0 ? this->height : ext::vulkan::height;
if ( compute.buffers.empty() ) return;
VkCommandBufferBeginInfo cmdBufInfo = ext::vulkan::initializers::commandBufferBeginInfo();
auto& pipeline = compute.getPipeline();
auto& commands = getCommands();
if ( compute.buffers.empty() ) return;
for (size_t i = 0; i < commands.size(); ++i) {
VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo));
pipeline.record(compute, commands[i]);
vkCmdDispatch(commands[i], width / dispatchSize.x, height / dispatchSize.y, 1);
VK_CHECK_RESULT(vkEndCommandBuffer(commands[i]));
}
this->mostRecentCommandPoolId = std::this_thread::get_id();
}

View File

@ -160,9 +160,7 @@ void ext::vulkan::DeferredRenderMode::tick() {
renderTarget.initialize( *renderTarget.device );
// update blitter descriptor set
if ( blitter.initialized ) {
auto& pipeline = blitter.getPipeline();
pipeline.update( blitter );
ext::vulkan::rebuild = true;
blitter.getPipeline().update( blitter );
}
}
}
@ -193,6 +191,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vector<ex
std::vector<RenderMode*> layers = ext::vulkan::getRenderModes(std::vector<std::string>{"RenderTarget", "Compute"}, false);
auto& scene = uf::scene::getCurrentScene();
auto& metadata = scene.getComponent<uf::Serializer>();
auto& commands = getCommands();
for (size_t i = 0; i < commands.size(); ++i) {
VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo));
// Fill GBuffer

View File

@ -8,6 +8,9 @@
std::string ext::vulkan::RenderTargetRenderMode::getType() const {
return "RenderTarget";
}
const std::string& ext::vulkan::RenderTargetRenderMode::getName( bool wantsTarget ) const {
return wantsTarget ? this->target : this->name;
}
void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
ext::vulkan::RenderMode::initialize( device );
@ -125,6 +128,7 @@ void ext::vulkan::RenderTargetRenderMode::destroy() {
blitter.destroy();
}
void ext::vulkan::RenderTargetRenderMode::render() {
auto& commands = getCommands( this->mostRecentCommandPoolId );
// Submit commands
// Use a fence to ensure that command buffer has finished executing before using it again
VK_CHECK_RESULT(vkWaitForFences( *device, 1, &fences[currentBuffer], VK_TRUE, UINT64_MAX ));
@ -219,7 +223,7 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const std::vecto
VkCommandBufferBeginInfo cmdBufInfo = {};
cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
cmdBufInfo.pNext = nullptr;
auto& commands = getCommands();
for (size_t i = 0; i < commands.size(); ++i) {
VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo));
{
@ -265,7 +269,9 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const std::vecto
vkCmdSetScissor(commands[i], 0, 1, &scissor);
for ( auto graphic : graphics ) {
if ( graphic->descriptor.renderMode != this->target ) continue;
graphic->record(commands[i] );
ext::vulkan::Graphic::Descriptor descriptor = graphic->descriptor;
descriptor.renderMode = this->name;
graphic->record(commands[i], descriptor );
}
vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE);
vkCmdEndRenderPass(commands[i]);

View File

@ -196,7 +196,7 @@ void ext::vulkan::StereoscopicDeferredRenderMode::createCommandBuffers( const st
auto& scene = uf::scene::getCurrentScene();
auto& metadata = scene.getComponent<uf::Serializer>();
auto& commands = getCommands();
for (size_t i = 0; i < commands.size(); ++i) {
VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo));
struct EYES {

View File

@ -443,7 +443,7 @@ void ext::vulkan::Texture2D::asRenderTarget( Device& device, uint32_t width, uin
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
imageCreateInfo.format = format;
imageCreateInfo.extent = { width, height, 1 };
imageCreateInfo.mipLevels = 1;
imageCreateInfo.mipLevels = this->mips = 1;
imageCreateInfo.arrayLayers = 1;
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;

View File

@ -7,6 +7,7 @@
#include <ostream>
#include <fstream>
#include <atomic>
uint32_t ext::vulkan::width = 1280;
uint32_t ext::vulkan::height = 720;
@ -302,11 +303,23 @@ void ext::vulkan::tick() {
}
renderMode->tick();
}
std::vector<std::function<int()>> jobs;
for ( auto& renderMode : renderModes ) {
if ( !renderMode ) continue;
if ( ext::vulkan::rebuild )
if ( ext::vulkan::rebuild || renderMode->rebuild ) {
jobs.emplace_back([&]{
renderMode->createCommandBuffers();
return 0;
});
}
}
if ( !jobs.empty() ) {
// std::cout << "Batching " << jobs.size() << " command buffer jobs" << std::endl;
uf::thread::batchWorkers( jobs );
// std::cout << "Done" << std::endl;
}
ext::vulkan::rebuild = false;
ext::vulkan::resized = false;
ext::vulkan::mutex.unlock();

View File

@ -3,6 +3,7 @@
#if defined(UF_USE_OPENAL)
#include <uf/ext/vorbis/vorbis.h>
#include <uf/ext/oal/oal.h>
#endif
/*
UF_API uf::Audio::Audio( const std::string& filename ) : m_filename(filename) {
@ -20,11 +21,19 @@ UF_API uf::Audio::Audio( const uf::Audio& copy ) :
{
}
*/
uf::Audio::~Audio() {
this->destroy();
}
bool UF_API uf::Audio::initialized() {
if ( !this->m_source.getIndex() ) return false;
if ( !this->m_buffer.getIndex() ) return false;
return true;
}
void UF_API uf::Audio::destroy() {
this->m_source.destroy();
this->m_buffer.destroy();
}
bool UF_API uf::Audio::playing() {
if ( !this->initialized() ) return false;
if ( !this->m_source.playing() ) return false;
@ -42,22 +51,24 @@ void UF_API uf::Audio::load( const std::string& filename ) { if ( filename != ""
frequency = vorbis.getFrequency();
this->m_duration = vorbis.getDuration();
this->m_buffer.generate();
this->m_source.generate();
this->m_buffer.generate(); ext::oal.checkError(__FUNCTION__, __LINE__);
this->m_source.generate(); ext::oal.checkError(__FUNCTION__, __LINE__);
this->m_buffer.buffer( format, &buffer[0], buffer.size(), frequency );
this->m_source.source( "BUFFER", std::vector<ALint>{ this->m_buffer.getIndex() } );
this->m_buffer.buffer( format, &buffer[0], buffer.size(), frequency ); ext::oal.checkError(__FUNCTION__, __LINE__);
this->m_source.source( "BUFFER", std::vector<ALint>{ this->m_buffer.getIndex() } ); ext::oal.checkError(__FUNCTION__, __LINE__);
this->m_source.source( "PITCH", std::vector<ALfloat>{ 1 } );
this->m_source.source( "GAIN", std::vector<ALfloat>{ 1 } );
this->m_source.source( "LOOPING", std::vector<ALint>{ AL_FALSE } );
this->m_source.source( "PITCH", std::vector<ALfloat>{ 1 } ); ext::oal.checkError(__FUNCTION__, __LINE__);
this->m_source.source( "GAIN", std::vector<ALfloat>{ 1 } ); ext::oal.checkError(__FUNCTION__, __LINE__);
this->m_source.source( "LOOPING", std::vector<ALint>{ AL_FALSE } ); ext::oal.checkError(__FUNCTION__, __LINE__);
}
}
void UF_API uf::Audio::play() {
if ( !this->initialized() ) return;
this->m_source.play();
}
void UF_API uf::Audio::stop() {
if ( !this->initialized() ) return;
this->m_source.stop();
}
const std::string& UF_API uf::Audio::getFilename() const {
@ -66,64 +77,64 @@ const std::string& UF_API uf::Audio::getFilename() const {
float uf::Audio::getDuration() const {
return this->m_duration;
}
#include <uf/ext/oal/oal.h>
ALfloat UF_API uf::Audio::getTime() {
if ( this->playing() ) return 0;
if ( !this->playing() ) return 0;
ALfloat pos;
alGetSourcef(this->m_source.getIndex(), AL_SEC_OFFSET, &pos ); ext::oal.checkError(__FUNCTION__, __LINE__);
return pos;
}
void UF_API uf::Audio::setTime( ALfloat pos ) {
if ( this->playing() ) return;
if ( !this->initialized() ) return;
this->m_source.source("SEC_OFFSET", std::vector<ALfloat>{ pos } );
}
ALfloat UF_API uf::Audio::getPitch() {
if ( this->playing() ) return 0;
if ( !this->initialized() ) return 0;
ALfloat pitch;
alGetSourcef(this->m_source.getIndex(), AL_PITCH, &pitch ); ext::oal.checkError(__FUNCTION__, __LINE__);
return pitch;
}
void UF_API uf::Audio::setPitch( ALfloat pitch ) {
if ( this->playing() ) return;
if ( !this->initialized() ) return;
this->m_source.source("PITCH", std::vector<ALfloat>{ pitch } );
}
ALfloat UF_API uf::Audio::getGain() {
if ( this->playing() ) return 0;
if ( !this->initialized() ) return 0;
ALfloat gain;
alGetSourcef(this->m_source.getIndex(), AL_GAIN, &gain ); ext::oal.checkError(__FUNCTION__, __LINE__);
return gain;
}
void UF_API uf::Audio::setGain( ALfloat gain ) {
if ( this->playing() ) return;
if ( !this->initialized() ) return;
this->m_source.source("GAIN", std::vector<ALfloat>{ gain } );
}
ALfloat UF_API uf::Audio::getRolloffFactor() {
if ( this->playing() ) return 0;
if ( !this->initialized() ) return 0;
ALfloat rolloffFactor;
alGetSourcef(this->m_source.getIndex(), AL_ROLLOFF_FACTOR, &rolloffFactor ); ext::oal.checkError(__FUNCTION__, __LINE__);
return rolloffFactor;
}
void UF_API uf::Audio::setRolloffFactor( ALfloat rolloffFactor ) {
if ( this->playing() ) return;
if ( !this->initialized() ) return;
this->m_source.source("ROLLOFF_FACTOR", std::vector<ALfloat>{ rolloffFactor } );
}
ALfloat UF_API uf::Audio::getMaxDistance() {
if ( this->playing() ) return 0;
if ( !this->initialized() ) return 0;
ALfloat maxDistance;
alGetSourcef(this->m_source.getIndex(), AL_MAX_DISTANCE, &maxDistance ); ext::oal.checkError(__FUNCTION__, __LINE__);
return maxDistance;
}
void UF_API uf::Audio::setMaxDistance( ALfloat maxDistance ) {
if ( this->playing() ) return;
if ( !this->initialized() ) return;
this->m_source.source("MAX_DISTANCE", std::vector<ALfloat>{ maxDistance } );
}
void UF_API uf::Audio::setPosition( const pod::Vector3& position ) {
if ( !this->initialized() ) return;
this->m_source.source("POSITION", std::vector<ALfloat>{position.x, position.y, position.z} );
}
void UF_API uf::Audio::setOrientation( const pod::Quaternion<>& orientation ) {
@ -164,9 +175,9 @@ const uf::SoundEmitter::container_t& UF_API uf::SoundEmitter::get() const {
}
void UF_API uf::SoundEmitter::cleanup( bool purge ) {
/*
for ( uf::Audio& k : this->m_container ) {
if ( !k.playing() ) this->m_container.erase(k);
for ( auto& pair : this->m_container ) {
if ( !pair.second.playing() ) {
this->m_container.erase(pair.first);
}
}
*/
}

View File

@ -7,6 +7,19 @@
#include <fstream>
#include <uf/utils/io/iostream.h>
#ifdef WINDOWS
#include <direct.h>
#define GetCurrentDir _getcwd
#else
#include <unistd.h>
#define GetCurrentDir getcwd
#endif
std::string UF_API uf::io::absolute( const std::string& path ) {
char buff[FILENAME_MAX];
GetCurrentDir( buff, FILENAME_MAX );
return std::string(buff) + path;
}
std::string UF_API uf::io::filename( const std::string& str ) {
return str.substr( str.find_last_of('/') + 1 );
}

View File

@ -54,7 +54,7 @@ pod::Thread& UF_API uf::thread::fetchWorker( const std::string& name ) {
std::string thread = name;
if ( current > 0 ) thread += " " + std::to_string(current);
bool exists = uf::thread::has(thread);
auto& pod = exists ? uf::thread::get(thread) : uf::thread::create( thread, true, false );
auto& pod = exists ? uf::thread::get(thread) : uf::thread::create( thread, true );
if ( !exists ) {
/*
pod.affinity = (current + 1) % threads;
@ -66,7 +66,17 @@ pod::Thread& UF_API uf::thread::fetchWorker( const std::string& name ) {
}
return pod;
}
void UF_API uf::thread::batchWorkers( const std::vector<pod::Thread::function_t>& functions, bool wait, const std::string& name ) {
std::vector<pod::Thread*> workers;
for ( auto& function : functions ) {
auto& worker = uf::thread::fetchWorker( name );
workers.emplace_back(&worker);
uf::thread::add( worker, function, true );
}
if ( wait )
for ( auto& worker : workers )
uf::thread::wait( *worker );
}
/*
void UF_API uf::thread::tick( pod::Thread& thread, const std::function<void()>& callback ) {
while ( thread.running ) {
@ -82,6 +92,7 @@ void UF_API uf::thread::add( pod::Thread& thread, const pod::Thread::function_t&
if ( thread.mutex != NULL ) thread.mutex->unlock();
}
void UF_API uf::thread::process( pod::Thread& thread ) { if ( !uf::thread::has(uf::thread::uid(thread)) ) { if ( UF_THREAD_ANNOUNCE ) uf::iostream << "Bad Thread: " << thread.uid << " " << thread.name << "\n"; return; } //ops
/*
std::function<int()> temps = [&] {
int i = 0;
while ( !thread.temps.empty() ) {
@ -100,17 +111,40 @@ void UF_API uf::thread::process( pod::Thread& thread ) { if ( !uf::thread::has(u
}
return i;
};
if ( thread.mutex != NULL ) thread.mutex->lock();
temps();
consts();
if ( thread.mutex != NULL ) thread.mutex->unlock();
*/
size_t temps = 0;
size_t consts = 0;
while ( !thread.temps.empty() ) {
auto& function = thread.temps.front();
if ( function ) function();
thread.temps.pop();
++temps;
}
for ( auto function : thread.consts ) {
function();
++consts;
}
thread.condition.notify_one();
}
void UF_API uf::thread::wait( pod::Thread& thread ) {
if ( thread.mutex != NULL ) {
std::unique_lock<std::mutex> lock(*thread.mutex);
thread.condition.wait(lock, [&]{return thread.temps.empty();});
return;
}
while ( !thread.temps.empty() );
/*
if ( thread.mutex != NULL ) {
thread.mutex->lock();
thread.mutex->unlock();
return;
}
while ( !thread.temps.empty() );
*/
}
const std::string& UF_API uf::thread::name( const pod::Thread& thread ) {

View File

@ -99,7 +99,7 @@ void ext::LightBehavior::tick( uf::Object& self ) {
float delta = metadata["light"]["fade"]["timer"].asFloat();
delta = std::clamp( delta, 0.f, 1.f );
if ( metadata["light"]["fade"]["power"].isNumeric() ) {
metadata["light"]["power"] = std::lerp( metadata["light"]["backup"]["power"].asFloat(), metadata["light"]["fade"]["power"].asFloat(), delta );
metadata["light"]["power"] = uf::math::lerp( metadata["light"]["backup"]["power"].asFloat(), metadata["light"]["fade"]["power"].asFloat(), delta );
}
if ( metadata["light"]["fade"]["color"].isArray() ) {
pod::Vector3f fadeColor; {

View File

@ -271,6 +271,29 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
uint32_t maxLights = 32;
} specializationConstants;
std::vector<uf::Entity*> entities;
{
std::function<void(uf::Entity*)> filter = [&]( uf::Entity* entity ) {
if ( !entity || entity->getName() != "Light" ) return;
entities.push_back(entity);
};
for ( uf::Scene* scene : uf::renderer::scenes ) { if ( !scene ) continue;
scene->process(filter);
}
{
const pod::Vector3& position = controller.getComponent<pod::Transform<>>().position;
std::sort( entities.begin(), entities.end(), [&]( const uf::Entity* l, const uf::Entity* r ){
if ( !l ) return false; if ( !r ) return true;
if ( !l->hasComponent<pod::Transform<>>() ) return false; if ( !r->hasComponent<pod::Transform<>>() ) return true;
return uf::vector::magnitude( uf::vector::subtract( l->getComponent<pod::Transform<>>().position, position ) ) < uf::vector::magnitude( uf::vector::subtract( r->getComponent<pod::Transform<>>().position, position ) );
} );
}
{
uf::Serializer& metadata = controller.getComponent<uf::Serializer>();
if ( metadata["light"]["should"].asBool() ) entities.push_back(&controller);
}
}
for ( size_t _ = 0; _ < blitters.size(); ++_ ) {
auto& blitter = *blitters[_];
@ -284,7 +307,6 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
buffer = (uint8_t*) (void*) userdata;
len = userdata.data().len;
shader = &_;
// specializationConstants = _.specializationConstants.get<SpecializationConstant>();
specializationConstants = *((SpecializationConstant*) &_.specializationConstants[0]);
}
@ -323,27 +345,6 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
}
}
{
std::vector<uf::Entity*> entities;
std::function<void(uf::Entity*)> filter = [&]( uf::Entity* entity ) {
if ( !entity || entity->getName() != "Light" ) return;
entities.push_back(entity);
};
for ( uf::Scene* scene : uf::renderer::scenes ) { if ( !scene ) continue;
scene->process(filter);
}
{
const pod::Vector3& position = controller.getComponent<pod::Transform<>>().position;
std::sort( entities.begin(), entities.end(), [&]( const uf::Entity* l, const uf::Entity* r ){
if ( !l ) return false; if ( !r ) return true;
if ( !l->hasComponent<pod::Transform<>>() ) return false; if ( !r->hasComponent<pod::Transform<>>() ) return true;
return uf::vector::magnitude( uf::vector::subtract( l->getComponent<pod::Transform<>>().position, position ) ) < uf::vector::magnitude( uf::vector::subtract( r->getComponent<pod::Transform<>>().position, position ) );
} );
}
{
uf::Serializer& metadata = controller.getComponent<uf::Serializer>();
if ( metadata["light"]["should"].asBool() ) entities.push_back(&controller);
}
UniformDescriptor::Light* lights = (UniformDescriptor::Light*) &buffer[sizeof(UniformDescriptor) - sizeof(UniformDescriptor::Light)];
for ( size_t i = 0; i < specializationConstants.maxLights; ++i ) {
UniformDescriptor::Light& light = lights[i];
@ -353,6 +354,10 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
light.depthBias = 0;
}
std::vector<VkImage> previousTextures;
for ( auto& texture : blitter.material.textures ) {
previousTextures.emplace_back(texture.image);
}
blitter.material.textures.clear();
for ( size_t i = 0; i < specializationConstants.maxLights && i < entities.size(); ++i ) {
@ -390,7 +395,6 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
uint8_t i = 0;
for ( auto& attachment : renderTarget.attachments ) {
if ( !(attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
// if ( (attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
if ( (attachment.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) ) continue;
auto& texture = blitter.material.textures.emplace_back();
texture.aliasAttachment(attachment);
@ -399,9 +403,21 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
}
}
}
size_t i = 0;
bool shouldUpdate = blitter.material.textures.size() != previousTextures.size();
while ( !shouldUpdate && i < blitter.material.textures.size() ) {
auto& texture = blitter.material.textures[i];
auto& previousTexture = previousTextures[i];
if ( texture.image != previousTexture ) shouldUpdate = true;
++i;
}
// check if we actually do need to update our pipeline, to avoid the command buffer rebuild cost
if ( shouldUpdate ) {
blitter.getPipeline().update( blitter );
}
}
shader->updateBuffer( (void*) buffer, len, 0, false );
}
}
}

View File

@ -1,528 +0,0 @@
#include "behavior.h"
#include <uf/utils/hook/hook.h>
#include <uf/utils/time/time.h>
#include <uf/utils/serialize/serializer.h>
#include <uf/utils/userdata/userdata.h>
#include <uf/utils/graphic/mesh.h>
#include <uf/utils/graphic/graphic.h>
#include <uf/utils/window/window.h>
#include <uf/utils/camera/camera.h>
#include <uf/utils/renderer/renderer.h>
#include <uf/utils/image/image.h>
#include <uf/engine/asset/asset.h>
#include "../../scenes/worldscape//battle.h"
#include "../../scenes/worldscape//.h"
#include <fstream>
#define PRINT_VECTOR2(v)\
std::cout << #v << ": " << v.x << ", " << v.y << std::endl;
namespace {
pod::Vector3f AXIS_OF_ROTATION = { 0, 0, 1 };
struct Bone {
std::string name = "";
std::string parent = "";
float length = 0;
pod::Vector2f position = { 0, 0 };
float rotation = 0;
};
struct AtlasPiece {
std::string name = "";
struct {
pod::Vector2f min = { 0, 0 };
pod::Vector2f max = { 0, 0 };
} uv;
struct {
pod::Vector2f topLeft = {-0.5f, 0.5f};
pod::Vector2f topRight = { 0.5f, 0.5f};
pod::Vector2f bottomLeft = {-0.5f, -0.5f};
pod::Vector2f bottomRight = { 0.5f, -0.5f};
} position;
pod::Vector2f scale = { 1, 1 };
pod::Vector2f size = { 0, 0 };
pod::Quaternion<> orientation = { 0, 0, 0, 1 };
float rotation = 0;
};
struct {
uf::Serializer animation;
uf::Serializer atlas;
uf::Serializer overrides;
} manifests;
struct {
std::unordered_map<std::string, Bone> skeleton;
std::unordered_map<std::string, AtlasPiece> attachments;
std::unordered_map<std::string, uf::Serializer> skins;
std::unordered_map<std::string, uf::Serializer> slots;
} maps;
float getRotation( const std::string& boneName, bool flatten = false, float start = 0 ) {
if ( manifests.overrides[boneName]["rotation"].isNumeric() ) {
return manifests.overrides[boneName]["rotation"].asFloat();
}
float rotation = start;
if ( maps.skeleton.count(boneName) < 0 ) {
std::cout << "Bone not in skeleton: " << boneName << std::endl;
return rotation;
}
Bone* bone = &maps.skeleton[boneName];
do {
rotation += bone->rotation;
if ( bone->parent == "" ) break;
bone = &maps.skeleton[bone->parent];
} while ( flatten );
return rotation;
}
pod::Quaternion<> getOrientation( const std::string& boneName, bool flatten = false, float start = 0 ) {
float rotation = getRotation( boneName, flatten, start );
return uf::quaternion::axisAngle( AXIS_OF_ROTATION, rotation * 3.14159f / 180.0f );
}
pod::Vector3f getPosition( const std::string& boneName, bool flatten = false ) {
if ( manifests.overrides[boneName]["position"].isArray() ) {
return pod::Vector3f{
manifests.overrides[boneName]["position"][0].asFloat(),
manifests.overrides[boneName]["position"][1].asFloat(),
0,
};
}
pod::Vector3f position = { 0, 0, 0 };
if ( maps.skeleton.count(boneName) < 0 ) {
std::cout << "Bone not in skeleton: " << boneName << std::endl;
return position;
}
Bone* bone = &maps.skeleton[boneName];
std::vector<pod::Vector2f> positions;
do {
if ( bone->parent == "" ) break;
float rotation = getRotation( bone->parent, flatten );
pod::Quaternion<> orientation = uf::quaternion::axisAngle( AXIS_OF_ROTATION, rotation * 3.14159f / 180.0f );
position += uf::quaternion::rotate( orientation, pod::Vector3f{ bone->position.x, bone->position.y, 0 } );
bone = &maps.skeleton[bone->parent];
} while ( flatten );
return position;
}
pod::Matrix4f getMatrix( const std::string& boneName, bool flatten = false, float start = 0 ) {
pod::Matrix4f matrix = uf::matrix::identity();
if ( start > 0.0f ) {
matrix = matrix * uf::quaternion::matrix( uf::quaternion::axisAngle( AXIS_OF_ROTATION, start ) );
}
if ( maps.skeleton.count(boneName) < 0 ) {
std::cout << "Bone not in skeleton: " << boneName << std::endl;
return matrix;
}
Bone* bone = &maps.skeleton[boneName];
do {
pod::Matrix4f translation = uf::matrix::translate( uf::matrix::identity(), {bone->position.x, bone->position.y, 0} );
pod::Matrix4f rotation = uf::quaternion::matrix( uf::quaternion::axisAngle( AXIS_OF_ROTATION, bone->rotation ) );
matrix = matrix * translation * rotation;
if ( bone->parent == "" ) break;
bone = &maps.skeleton[bone->parent];
} while ( flatten );
return matrix;
}
uf::Serializer getSkin( const uf::Serializer& slot ) {
uf::Serializer json;
std::string name = slot["name"].asString();
std::string attachment = slot["attachment"].asString();
if ( !maps.skins["default"][name][attachment].isNull() ) json = maps.skins["default"][name][attachment];
else if ( !maps.skins["normal"][name][attachment].isNull() ) json = maps.skins["normal"][name][attachment];
return json;
}
}
EXT_BEHAVIOR_REGISTER_CPP(LahSpineBehavior)
#define this (&self)
void ext::LahSpineBehavior::initialize( uf::Object& self ) {
uf::Scene& scene = uf::scene::getCurrentScene();
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
uf::Serializer& masterdata = scene.getComponent<uf::Serializer>();
uf::Asset& assetLoader = scene.getComponent<uf::Asset>();
manifests.atlas.readFromFile(metadata["system"]["root"].asString() + "atlas.json");
manifests.animation.readFromFile(metadata["system"]["root"].asString() + "animation.json");
this->addHook( "graphics:Assign.%UID%", [&](const std::string& event)->std::string{
uf::Serializer json = event;
std::string filename = json["filename"].asString();
metadata["system"]["control"] = false;
if ( uf::io::extension(filename) != "png" ) return "false";
uf::Scene& scene = this->getRootParent<uf::Scene>();
uf::Asset& assetLoader = scene.getComponent<uf::Asset>();
const uf::Image* imagePointer = NULL;
try { imagePointer = &assetLoader.get<uf::Image>(filename); } catch ( ... ) {}
if ( !imagePointer ) return "false";
uf::Image image = *imagePointer;
// test overrides
{
manifests.overrides = metadata["atlas"]["overrides"];
}
// assemble skeleton
{
auto& manifest = manifests.animation;
for ( int i = 0; i < manifest["bones"].size(); ++i ) {
auto& entry = manifest["bones"][i];
std::string name = entry["name"].asString();
auto& bone = maps.skeleton[name];
bone.name = name;
if ( entry["parent"].isString() ) bone.parent = entry["parent"].asString();
if ( entry["x"].isNumeric() ) bone.position.x = entry["x"].asFloat();
if ( entry["y"].isNumeric() ) bone.position.y = entry["y"].asFloat();
if ( entry["length"].isNumeric() ) bone.length = entry["length"].asFloat();
if ( entry["rotation"].isNumeric() ) bone.rotation = entry["rotation"].asFloat(); // * 3.14159f / 180.0f;
}
}
// create sprite attachments
{
auto& manifest = manifests.animation;
for ( int i = 0; i < manifest["skins"].size(); ++i ) {
std::string skinName = manifest["skins"][i]["name"].asString();
if ( skinName == "damage" ) continue;
maps.skins[skinName] = manifest["skins"][i]["attachments"];
}
}
// register slots
{
auto& manifest = manifests.animation;
for ( int i = 0; i < manifest["slots"].size(); ++i ) {
std::string slotName = manifest["slots"][i]["name"].asString();
maps.slots[slotName] = manifest["slots"][i];
}
}
// parse atlas
{
auto& manifest = manifests.atlas;
for ( auto it = manifest["pieces"].begin() ; it != manifest["pieces"].end() ; ++it ) {
std::string name = it.key().asString();
pod::Vector2f sheetSize = { manifest["size"][0].asFloat(), manifest["size"][1].asFloat() };
pod::Vector2f xy = { manifest["pieces"][name]["xy"][0].asFloat(), manifest["pieces"][name]["xy"][1].asFloat() };
pod::Vector2f size = { manifest["pieces"][name]["size"][0].asFloat(), manifest["pieces"][name]["size"][1].asFloat() };
float rotation = 0.0f;
auto& piece = maps.attachments[name];
piece.size = size;
if ( manifest["pieces"][name]["rotate"].isNumeric() ) {
auto& rotation = piece.rotation;
auto& orientation = piece.orientation;
rotation = manifest["pieces"][name]["rotate"].asFloat(); // * 3.14159f / 180.0f;
orientation = uf::quaternion::axisAngle( AXIS_OF_ROTATION, rotation * 3.14159f / 180.0f );
pod::Vector3f rotated;
{
rotated = uf::quaternion::rotate( orientation, pod::Vector3f{ size.x, size.y, 0 } );
size.x = fabs(rotated.x);
size.y = fabs(rotated.y);
}
orientation = uf::quaternion::axisAngle( AXIS_OF_ROTATION, (rotation + 90) * 3.14159f / 180.0f );
{
rotated = uf::quaternion::rotate( orientation, pod::Vector3f{ size.x, size.y, 0 } );
piece.size.x = fabs(rotated.x);
piece.size.y = fabs(rotated.y);
}
{
rotated = uf::quaternion::rotate( orientation, pod::Vector3f{ piece.position.topLeft.x, piece.position.topLeft.y, 0 } );
piece.position.topLeft.x = rotated.x;
piece.position.topLeft.y = rotated.y;
}
{
rotated = uf::quaternion::rotate( orientation, pod::Vector3f{ piece.position.topRight.x, piece.position.topRight.y, 0 } );
piece.position.topRight.x = rotated.x;
piece.position.topRight.y = rotated.y;
}
{
rotated = uf::quaternion::rotate( orientation, pod::Vector3f{ piece.position.bottomLeft.x, piece.position.bottomLeft.y, 0 } );
piece.position.bottomLeft.x = rotated.x;
piece.position.bottomLeft.y = rotated.y;
}
{
rotated = uf::quaternion::rotate( orientation, pod::Vector3f{ piece.position.bottomRight.x, piece.position.bottomRight.y, 0 } );
piece.position.bottomRight.x = rotated.x;
piece.position.bottomRight.y = rotated.y;
}
}
piece.name = name;
piece.uv.min = ( xy ) / sheetSize;
piece.uv.max = ( xy + size ) / sheetSize;
piece.scale = size / sheetSize;
}
}
{
std::vector<std::string> whitelist = {};
for ( int i = 0; i < metadata["atlas"]["whitelist"].size(); ++i ) {
whitelist.emplace_back(metadata["atlas"]["whitelist"][i].asString());
}
auto& manifest = manifests.atlas;
for ( auto it = manifest["pieces"].begin() ; it != manifest["pieces"].end() ; ++it ) {
std::string name = it.key().asString();
if ( !whitelist.empty() && std::find( whitelist.begin(), whitelist.end(), name ) == whitelist.end() ) continue;
auto& child = uf::instantiator::instantiate<uf::Object>();
uf::instantiator::bind( "LahSpinePieceBehavior", child );
this->addChild(child);
child.initialize();
uf::Serializer payload;
payload["attachment"]["name"] = name;
payload["attachment"]["useMatrix"] = metadata["atlas"]["useMatrix"];
payload["filename"] = json["filename"];
child.queueHook("graphics:Assign.%UID%", payload);
metadata["attachments"][name] = child.getUid();
}
}
return "true";
});
this->addHook( "asset:Load.%UID%", [&](const std::string& event)->std::string{
this->queueHook("graphics:Assign.%UID%", event, 0.0f);
return "true";
});
}
void ext::LahSpineBehavior::tick( uf::Object& self ) {}
void ext::LahSpineBehavior::render( uf::Object& self ){
}
void ext::LahSpineBehavior::destroy( uf::Object& self ){}
#undef this
EXT_BEHAVIOR_REGISTER_CPP(LahSpinePieceBehavior)
#define this (&self)
void ext::LahSpinePieceBehavior::initialize( uf::Object& self ) {
uf::Scene& scene = uf::scene::getCurrentScene();
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
uf::Serializer& masterdata = scene.getComponent<uf::Serializer>();
uf::Asset& assetLoader = scene.getComponent<uf::Asset>();
this->addHook( "graphics:Assign.%UID%", [&](const std::string& event)->std::string{
uf::Serializer json = event;
std::string filename = json["filename"].asString();
metadata["system"]["control"] = false;
if ( uf::io::extension(filename) != "png" ) return "false";
uf::Scene& scene = this->getRootParent<uf::Scene>();
uf::Asset& assetLoader = scene.getComponent<uf::Asset>();
const uf::Image* imagePointer = NULL;
try { imagePointer = &assetLoader.get<uf::Image>(filename); } catch ( ... ) {}
if ( !imagePointer ) return "false";
uf::Image image = *imagePointer;
uf::Mesh& mesh = this->getComponent<uf::Mesh>();
auto& graphic = this->getComponent<uf::Graphic>();
auto& transform = this->getComponent<pod::Transform<>>();
metadata["attachment"] = json["attachment"];
metadata["color"][0] = 1;
metadata["color"][1] = 1;
metadata["color"][2] = 1;
metadata["color"][3] = 1;
std::string name = metadata["attachment"]["name"].asString();
auto& attachment = maps.attachments[name];
auto& slot = maps.slots[name];
// transform.scale = { attachment.scale.x, attachment.scale.y, 1 };
transform.scale = { 1.0f / 512.0f, 1.0f / 512.0f, 1 };
std::string boneName = slot["bone"].asString();
transform.position = getPosition( boneName, true );
transform.orientation = getOrientation( boneName, true );
std::cout << "\"" << name << "\": {\"position\": [ " << transform.position.x << ", " << transform.position.y << " ], \"rotation\": " << getRotation( name, true ) << " }," << std::endl;
transform.position *= transform.scale;
struct {
pod::Vector2f position;
pod::Vector2f uv;
} topLeft, topRight, bottomLeft, bottomRight;
{
topLeft.position = attachment.size * attachment.position.topLeft;
topRight.position = attachment.size * attachment.position.topRight;
bottomLeft.position = attachment.size * attachment.position.bottomLeft;
bottomRight.position = attachment.size * attachment.position.bottomRight;
}
{
topLeft.uv = { attachment.uv.min.x, 1.0f - attachment.uv.min.y };
topRight.uv = { attachment.uv.max.x, 1.0f - attachment.uv.min.y };
bottomLeft.uv = { attachment.uv.min.x, 1.0f - attachment.uv.max.y };
bottomRight.uv = { attachment.uv.max.x, 1.0f - attachment.uv.max.y };
}
mesh.vertices = {
{ { topLeft.position.x, topLeft.position.y, 0.0f }, topLeft.uv, { 0.0f, 0.0f, -1.0f } },
{ { topRight.position.x, topRight.position.y, 0.0f }, topRight.uv,{ 0.0f, 0.0f, -1.0f } },
{ { bottomRight.position.x, bottomRight.position.y, 0.0f }, bottomRight.uv, { 0.0f, 0.0f, -1.0f } },
{ { bottomRight.position.x, bottomRight.position.y, 0.0f }, bottomRight.uv, { 0.0f, 0.0f, -1.0f } },
{ { bottomLeft.position.x, bottomLeft.position.y, 0.0f }, bottomLeft.uv, { 0.0f, 0.0f, -1.0f } },
{ { topLeft.position.x, topLeft.position.y, 0.0f }, topLeft.uv, { 0.0f, 0.0f, -1.0f } },
};
{
std::cout << name << ". Slot: " << slot << std::endl;
auto skin = getSkin( slot );
struct WeightedVertex {
int boneId;
float weight;
pod::Vector2f position;
};
struct SkinnedVertex {
std::vector<WeightedVertex> weights;
pod::Vector2f position;
pod::Vector2f uv;
};
std::vector<SkinnedVertex> skinnedVertices;
std::cout << name << ", Vertices?:\n";
for ( int i = 0; i < skin["vertices"].size(); ) {
int read = skin["vertices"][i++].asInt();
auto& skinVertex = skinnedVertices.emplace_back();
for ( int j = 0; j < read; ++j ) {
auto& weightedVertex = skinVertex.weights.emplace_back();
weightedVertex.boneId = skin["vertices"][i++].asInt();
weightedVertex.position.x = skin["vertices"][i++].asFloat();
weightedVertex.position.y = skin["vertices"][i++].asFloat();
weightedVertex.weight = skin["vertices"][i++].asFloat();
}
}
for ( int i = 0; i < skinnedVertices.size(); ++i ) {
auto& skinVertex = skinnedVertices.at(i);
skinVertex.uv.x = skin["uvs"][(i*2+0)].asFloat();
skinVertex.uv.y = skin["uvs"][(i*2+1)].asFloat();
// average
for ( auto& weightedVertex : skinVertex.weights ) {
std::string boneName = manifests.animation["bones"][weightedVertex.boneId]["name"].asString();
auto bonePosition = getPosition( boneName, true );
auto boneOrientation = getOrientation( boneName, true );
bonePosition = uf::quaternion::rotate( boneOrientation, bonePosition );
auto rotatedVertex = uf::quaternion::rotate( boneOrientation, pod::Vector3f{ weightedVertex.position.x, weightedVertex.position.y, 0 } );
skinVertex.position.x += (rotatedVertex.x + bonePosition.x) * weightedVertex.weight;
skinVertex.position.y += (rotatedVertex.y + bonePosition.y) * weightedVertex.weight;
// wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight;
}
}
for ( int i = 0; i < skinnedVertices.size(); ++i ) {
auto& skinVertex = skinnedVertices.at(i);
std::cout << "Index " << i << ":\n";
for ( auto& weightedVertex : skinVertex.weights ) {
std::string boneName = manifests.animation["bones"][weightedVertex.boneId]["name"].asString();
std::cout << "\tPosition: " << weightedVertex.position.x << ", " << weightedVertex.position.y << " | Bone ID: " << weightedVertex.boneId << " | Bone Name: " << boneName << " | Weight: " << weightedVertex.weight << "\n";
}
std::cout << "\tUV: " << skinVertex.uv.x << ", " << skinVertex.uv.y << "\n";
std::cout << "\tWeighted Position: " << skinVertex.position.x << ", " << skinVertex.position.y << "\n";
}
std::cout << std::endl;
std::cout << name << ", Triangles:\n";
mesh.vertices.clear();
for ( auto i = 0; i < skin["triangles"].size(); ) {
std::cout << "Triangle:\n";
for ( int j = 0; j < 3; ++j ) {
int index = skin["triangles"][i++].asInt();
auto& skinVertex = skinnedVertices.at(index);
struct {
pod::Vector2f interp;
} position, uv;
uv.interp.x = std::lerp( attachment.uv.min.x, attachment.uv.max.x, skinVertex.uv.x );
uv.interp.y = std::lerp( attachment.uv.min.y, attachment.uv.max.y, skinVertex.uv.y );
// uv.interp = skinVertex.uv;
position.interp.x = (uv.interp.x - 0.5f) * attachment.size.x;
position.interp.y = (uv.interp.y - 0.5f) * attachment.size.y;
std::cout << "\tIndex: " << index << "\tUV: " << uv.interp.x << ", " << uv.interp.y << "\tPosition: " << position.interp.x << ", " << position.interp.y << "\n";
auto& vertex = mesh.vertices.emplace_back();
// vertex.position.x = position.interp.x;
// vertex.position.y = position.interp.y;
vertex.position.x = skinVertex.position.x;
vertex.position.y = skinVertex.position.y;
vertex.position.z = 0;
vertex.uv.x = uv.interp.x;
vertex.uv.y = 1.0f - uv.interp.y;
vertex.normal = { 0, 0, -1 };
}
std::cout << std::endl;
}
/*
std::cout << name << ", Triangles:\n";
for ( auto i = 0; i < skin["triangles"].size(); i += 3 ) {
// std::cout << "\t" << skin["triangles"][i+0].asInt() << " " << skin["triangles"][i+1].asInt() << " " << skin["triangles"][i+2].asInt() << std::endl;
std::cout << "\t" << skin["uvs"][skin["triangles"][i+0].asInt()].asFloat() << " " << skin["uvs"][skin["triangles"][i+1].asInt()].asFloat() << " " << skin["uvs"][skin["triangles"][i+2].asInt()].asFloat()
}
*/
std::cout << name << ", "
<< "UVs: " << skin["uvs"].size() << ", "
<< "Positions: " << skin["vertices"].size() << ", "
<< "Triangles: " << skin["triangles"].size() << ", "
<< "Edges: " << skin["edges"].size() << ", "
<< "Hull: " << skin["hull"]
<< std::endl;
}
graphic.initialize( "Gui" );
graphic.initializeGeometry( mesh );
auto& texture = graphic.material.textures.emplace_back();
texture.loadFromImage( image );
graphic.material.attachShader("./data/shaders/base.stereo.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
graphic.material.attachShader("./data/shaders/base.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
metadata["system"]["control"] = true;
metadata["system"]["loaded"] = true;
return "true";
});
}
void ext::LahSpinePieceBehavior::tick( uf::Object& self ) {}
void ext::LahSpinePieceBehavior::render( uf::Object& self ){
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
if ( !metadata["system"]["loaded"].asBool() ) return;
/* Update uniforms */ if ( this->hasComponent<uf::Graphic>() ) {
auto& mesh = this->getComponent<uf::Mesh>();
auto& scene = uf::scene::getCurrentScene();
auto& graphic = this->getComponent<uf::Graphic>();
auto& transform = this->getComponent<pod::Transform<>>();
auto& camera = scene.getController().getComponent<uf::Camera>();
if ( !graphic.initialized ) return;
auto& uniforms = graphic.material.shaders.front().uniforms.front().get<uf::StereoMeshDescriptor>();
auto translation = uf::matrix::translate( uf::matrix::identity(), transform.position );
auto rotation = uf::quaternion::matrix( transform.orientation );
auto scale = uf::matrix::scale( uf::matrix::identity(), transform.scale );
auto model = translation * rotation * scale;
std::string name = metadata["attachment"]["name"].asString();
auto& attachment = maps.attachments[name];
auto bone = getMatrix( name, true );
uniforms.matrices.model = metadata["attachment"]["useMatrix"].asBool() ? bone : model;
for ( std::size_t i = 0; i < 2; ++i ) {
uniforms.matrices.view[i] = camera.getView( i );
uniforms.matrices.projection[i] = camera.getProjection( i );
}
uniforms.color[0] = metadata["color"][0].asFloat();
uniforms.color[1] = metadata["color"][1].asFloat();
uniforms.color[2] = metadata["color"][2].asFloat();
uniforms.color[3] = metadata["color"][3].asFloat();
graphic.material.shaders.front().updateBuffer( uniforms, 0, false );
};
}
void ext::LahSpinePieceBehavior::destroy( uf::Object& self ){}
#undef this

View File

@ -1,25 +0,0 @@
#pragma once
#include <uf/config.h>
#include <uf/ext/ext.h>
#include <uf/engine/entity/entity.h>
#include <uf/engine/scene/scene.h>
namespace ext {
class EXT_API LahSpineBehavior {
public:
static void attach( uf::Object& );
static void initialize( uf::Object& );
static void tick( uf::Object& );
static void render( uf::Object& );
static void destroy( uf::Object& );
};
class EXT_API LahSpinePieceBehavior {
public:
static void attach( uf::Object& );
static void initialize( uf::Object& );
static void tick( uf::Object& );
static void render( uf::Object& );
static void destroy( uf::Object& );
};
}

View File

@ -11,8 +11,12 @@ EXT_BEHAVIOR_REGISTER_CPP(StaticEmitterBehavior)
#define this ((uf::Object*) &self)
void ext::StaticEmitterBehavior::initialize( uf::Object& self ) {
auto& metadata = this->getComponent<uf::Serializer>();
// this->addHook( "system:Load.Finished.%UID%", [&](const std::string& event)->std::string{
// uf::Serializer json = event;
auto* hud = this->loadChildPointer("/hud.json", true);
metadata["hud"]["uid"] = hud->getUid();
// return "true";
// });
}
void ext::StaticEmitterBehavior::tick( uf::Object& self ) {
auto& scene = uf::scene::getCurrentScene();

View File

@ -825,7 +825,7 @@ void ext::GuiBehavior::initialize( uf::Object& self ) {
// graphic.descriptor.indices = 0;
graphic.initializeGeometry( mesh );
graphic.getPipeline().update( graphic );
uf::renderer::rebuild = true;
// uf::renderer::rebuild = true;
/*
graphic.destroy();

View File

@ -253,9 +253,8 @@ void EXT_API ext::initialize() {
uf::renderer::initialize();
}
/* */ {
pod::Thread& threadMain = uf::thread::has("Main") ? uf::thread::get("Main") : uf::thread::create( "Main", false, true );
// pod::Thread& threadAux = uf::thread::has("Aux") ? uf::thread::get("Aux") : uf::thread::create( "Aux", true, false );
pod::Thread& threadPhysics = uf::thread::has("Physics") ? uf::thread::get("Physics") : uf::thread::create( "Physics", true, false );
pod::Thread& threadMain = uf::thread::has("Main") ? uf::thread::get("Main") : uf::thread::create( "Main", false );
pod::Thread& threadPhysics = uf::thread::has("Physics") ? uf::thread::get("Physics") : uf::thread::create( "Physics", true );
}
/* Discord */ if ( ::config["engine"]["ex"]["discord"]["enabled"].asBool() ) {

View File

@ -89,20 +89,22 @@ void ext::RayTracingSceneBehavior::tick( uf::Object& self ) {
alignas(16) pod::Vector4f ambient;
struct {
alignas(8) pod::Vector2f range;
alignas(8) pod::Vector2f padding;
alignas(16) pod::Vector4f color;
} fog;
struct Light {
alignas(16) pod::Vector4f position;
alignas(16) pod::Vector4f color;
alignas(8) pod::Vector2i type;
alignas(8) pod::Vector2i padding;
alignas(16) pod::Matrix4f view;
alignas(16) pod::Matrix4f projection;
} lights;
};
struct SpecializationConstant {
uint32_t eyes = 2;
uint32_t maxLights = 16;
uint32_t eyes = 2;
} specializationConstants;
auto& shader = renderMode.compute.material.shaders.front();