try support asset loader
This commit is contained in:
parent
e6d4313f90
commit
67b41a4eee
3
engine/3rdparty/zlib/include/refl/macro.h
vendored
3
engine/3rdparty/zlib/include/refl/macro.h
vendored
@ -28,6 +28,9 @@
|
|||||||
#define USING_OVERLOAD_CLASS_FUNC(R, Class, ...) using USING_FUNC_NAME = R(Class::*)(__VA_ARGS__);
|
#define USING_OVERLOAD_CLASS_FUNC(R, Class, ...) using USING_FUNC_NAME = R(Class::*)(__VA_ARGS__);
|
||||||
|
|
||||||
#define REGISTER_META_TABLE(Class) refl::UClass::MetaTable.emplace(type_name<Class>().View(), &refl::TypeInfo<Class>::StaticClass);
|
#define REGISTER_META_TABLE(Class) refl::UClass::MetaTable.emplace(type_name<Class>().View(), &refl::TypeInfo<Class>::StaticClass);
|
||||||
|
|
||||||
|
#define REFL_FRIEND(Class) friend class refl_impl::_Static<Class, refl_impl::Meta>;\
|
||||||
|
friend class refl_impl::_Meta<Class, refl_impl::Meta>;
|
||||||
/*
|
/*
|
||||||
struct vec3{
|
struct vec3{
|
||||||
USING_OVERLOAD_CTOR(vec3)
|
USING_OVERLOAD_CTOR(vec3)
|
||||||
|
|||||||
0
engine/assets/file_flag.meta
Normal file
0
engine/assets/file_flag.meta
Normal file
2
engine/assets/models/.asset
Normal file
2
engine/assets/models/.asset
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- name: engineapi::Mesh
|
||||||
|
data: ""
|
||||||
2
engine/assets/models/box.ply.asset
Normal file
2
engine/assets/models/box.ply.asset
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- name: engineapi::Mesh
|
||||||
|
data: "mMaterial:\n guid: 00000000-0000-0000-0000-000000000000"
|
||||||
9
engine/assets/models/box.ply.meta
Normal file
9
engine/assets/models/box.ply.meta
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
metadatas:
|
||||||
|
- guid: a5943c25-1ce8-44dc-ae99-4071d07ecb63
|
||||||
|
name: ""
|
||||||
|
t_hash: engineapi::Model
|
||||||
|
t_meta: ""
|
||||||
|
- guid: 77b7a000-ed3c-4271-ae30-5e91346e09f4
|
||||||
|
name: ""
|
||||||
|
t_hash: engineapi::Asset
|
||||||
|
t_meta: engineapi::Mesh
|
||||||
2
engine/assets/models/cube.obj.asset
Normal file
2
engine/assets/models/cube.obj.asset
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- name: engineapi::Mesh
|
||||||
|
data: ""
|
||||||
9
engine/assets/models/cube.obj.meta
Normal file
9
engine/assets/models/cube.obj.meta
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
metadatas:
|
||||||
|
- guid: 80671c54-88f9-41c7-948a-a72cdf3727d3
|
||||||
|
name: ""
|
||||||
|
t_hash: engineapi::Model
|
||||||
|
t_meta: ""
|
||||||
|
- guid: 54e69c4b-16ea-4fb8-87d6-0e2383d093b0
|
||||||
|
name: defaultobject
|
||||||
|
t_hash: engineapi::Asset
|
||||||
|
t_meta: engineapi::Mesh
|
||||||
5
engine/assets/shader/simple.frag.meta
Normal file
5
engine/assets/shader/simple.frag.meta
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
metadatas:
|
||||||
|
- guid: eb1c9b43-a86b-40cb-9b3d-a3296d168c70
|
||||||
|
name: ""
|
||||||
|
t_hash: engineapi::ShaderProgram
|
||||||
|
metadata: ""
|
||||||
5
engine/assets/shader/simple.vert.meta
Normal file
5
engine/assets/shader/simple.vert.meta
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
metadatas:
|
||||||
|
- guid: 9419e2a5-ddc4-414f-aa76-d08e9b162492
|
||||||
|
name: ""
|
||||||
|
t_hash: engineapi::ShaderProgram
|
||||||
|
metadata: ""
|
||||||
22
engine/cpp_input.h
Normal file
22
engine/cpp_input.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
//#include "meta/variant.inl"
|
||||||
|
//#include "meta/tuple.inl"
|
||||||
|
//#include "meta/comparable.inl"
|
||||||
|
//#include "meta/hash.h"
|
||||||
|
//#include "zstd/span.h"
|
||||||
|
//#include "zstd/table.h"
|
||||||
|
//#include <vector>
|
||||||
|
//#include <optional>
|
||||||
|
namespace engineapi {
|
||||||
|
using namespace meta;
|
||||||
|
using zstd::span;
|
||||||
|
using std::vector;
|
||||||
|
using std::array;
|
||||||
|
using zstd::table;
|
||||||
|
using zstd::hash_table;
|
||||||
|
template<typename T>
|
||||||
|
using opt = std::optional<T>;
|
||||||
|
template<bool val>
|
||||||
|
using sfinae = std::enable_if_t<val>;
|
||||||
|
}
|
||||||
@ -28,6 +28,9 @@ namespace engineapi {
|
|||||||
for (auto system : SystemList) {
|
for (auto system : SystemList) {
|
||||||
system->Init();
|
system->Init();
|
||||||
}
|
}
|
||||||
|
for (auto system : SystemList) {
|
||||||
|
system->LateInit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void App::Shutdown()
|
void App::Shutdown()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
|
#include "asset_loader.h"
|
||||||
#include "render/asset/shader.h"
|
#include "render/asset/shader.h"
|
||||||
|
#include "render/asset/model.h"
|
||||||
#include "resource_manager.h"
|
#include "resource_manager.h"
|
||||||
|
#include "object/loader/assimp_loader.h"
|
||||||
|
#include "yaml/yaml.h"
|
||||||
namespace engineapi {
|
namespace engineapi {
|
||||||
MetaBundle ResourceManager::GetVisitMeta(const ResourceBundle& bundle)
|
MetaBundle ResourceManager::GetVisitMeta(const ResourceBundle& bundle)
|
||||||
{
|
{
|
||||||
@ -9,4 +13,10 @@ namespace engineapi {
|
|||||||
std::visit([&](auto& handle) { new_meta.Add(handle); }, elem);
|
std::visit([&](auto& handle) { new_meta.Add(handle); }, elem);
|
||||||
return new_meta;
|
return new_meta;
|
||||||
}
|
}
|
||||||
|
void Asset::__Init__()
|
||||||
|
{
|
||||||
|
YAML::TextArchive::Register<Guid>();
|
||||||
|
AssimpLoader::Init();
|
||||||
|
AssetLoader::Init();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1,11 +1,22 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "render/asset_struct.h"
|
#include "render/asset_struct.h"
|
||||||
#include "res/resource_handle.h"
|
#include "resource_manager.h"
|
||||||
#include "res/package_path.h"
|
|
||||||
namespace engineapi {
|
namespace engineapi {
|
||||||
class Asset : public Resource<Asset> {
|
class Asset : public Resource<Asset> {
|
||||||
|
private:
|
||||||
|
static void __Init__();
|
||||||
|
friend class FileManager;
|
||||||
public:
|
public:
|
||||||
using Base = Resource<Asset>;
|
using Base = Resource<Asset>;
|
||||||
using Base::Base;
|
const refl::UClass* meta;
|
||||||
|
Asset(const refl::UClass* meta): Base(), meta(meta){}
|
||||||
};
|
};
|
||||||
|
template<>
|
||||||
|
inline void MetaBundle::Add(RscHandle<Asset> h)
|
||||||
|
{
|
||||||
|
if (h)
|
||||||
|
{
|
||||||
|
metadatas.emplace_back(SerializedMeta{ h.guid, string(h->Name()), string(type_name<Asset>().View()), string(h->meta->name)});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
25
engine/src/engine/asset/asset_loader.cpp
Normal file
25
engine/src/engine/asset/asset_loader.cpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#include "asset_loader.h"
|
||||||
|
#include "file_manager.h"
|
||||||
|
#include "yaml/yaml.h"
|
||||||
|
#include <fstream>
|
||||||
|
namespace engineapi {
|
||||||
|
void AssetLoader::Init() {
|
||||||
|
ResourceManager::GetSingleton().RegisterLoader<AssetLoader>(".asset");
|
||||||
|
}
|
||||||
|
ResourceBundle AssetLoader::LoadFile(PackagePath handle, const MetaBundle& meta)
|
||||||
|
{
|
||||||
|
return ResourceBundle();
|
||||||
|
}
|
||||||
|
void AssetLoader::SaveFile(PackagePath handle, const ResourceBundle& bundle)
|
||||||
|
{
|
||||||
|
YAML::Node result;
|
||||||
|
for (auto& elem : bundle.GetAll<Asset>()) {
|
||||||
|
RscHandle<Asset> handle = elem.AsHandle<Asset>();
|
||||||
|
YAML::Node meta;
|
||||||
|
meta["name"] = string(handle->meta->name);
|
||||||
|
meta["data"] = YAML::Text_Serialize(refl::Any{handle.res, handle->meta});
|
||||||
|
result.push_back(meta);
|
||||||
|
}
|
||||||
|
FileManager::SaveTextFile(handle, YAML::Dump(result));
|
||||||
|
}
|
||||||
|
}
|
||||||
10
engine/src/engine/asset/asset_loader.h
Normal file
10
engine/src/engine/asset/asset_loader.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "asset.h"
|
||||||
|
namespace engineapi {
|
||||||
|
class AssetLoader :public IFileLoader{
|
||||||
|
public:
|
||||||
|
static void Init();
|
||||||
|
ResourceBundle LoadFile(PackagePath handle, const MetaBundle& meta) override;
|
||||||
|
void SaveFile(PackagePath handle, const ResourceBundle& bundle) override;
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -7,12 +7,13 @@ namespace engineapi {
|
|||||||
{
|
{
|
||||||
std::filesystem::path path = std::filesystem::current_path();
|
std::filesystem::path path = std::filesystem::current_path();
|
||||||
Mount("engine", path.string());
|
Mount("engine", path.string());
|
||||||
|
Asset::__Init__();
|
||||||
}
|
}
|
||||||
void FileManager::Shutdown()
|
void FileManager::Shutdown()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
string FileManager::real_path(const PackagePath& pack_path)
|
string FileManager::RealPath(const PackagePath& pack_path)
|
||||||
{
|
{
|
||||||
string_view name = pack_path.ParsePackage();
|
string_view name = pack_path.ParsePackage();
|
||||||
string_view pre_path = FindMountPath(name);
|
string_view pre_path = FindMountPath(name);
|
||||||
@ -40,7 +41,7 @@ namespace engineapi {
|
|||||||
file.exceptions(ifstream::failbit | ifstream::badbit);
|
file.exceptions(ifstream::failbit | ifstream::badbit);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string path = real_path(pack_path);
|
string path = RealPath(pack_path);
|
||||||
file.open(path);
|
file.open(path);
|
||||||
stringstream stream;
|
stringstream stream;
|
||||||
stream << file.rdbuf();
|
stream << file.rdbuf();
|
||||||
@ -54,7 +55,7 @@ namespace engineapi {
|
|||||||
}
|
}
|
||||||
result<vector<char>,FileFlag> FileManager::LoadBinaryFile(const PackagePath& pack_path)
|
result<vector<char>,FileFlag> FileManager::LoadBinaryFile(const PackagePath& pack_path)
|
||||||
{
|
{
|
||||||
string path = real_path(pack_path);
|
string path = RealPath(pack_path);
|
||||||
// ate:在文件末尾开始读取,从文件末尾开始读取的优点是我们可以使用读取位置来确定文件的大小并分配缓冲区
|
// ate:在文件末尾开始读取,从文件末尾开始读取的优点是我们可以使用读取位置来确定文件的大小并分配缓冲区
|
||||||
ifstream file(path, std::ios::ate | std::ios::binary);
|
ifstream file(path, std::ios::ate | std::ios::binary);
|
||||||
if (!file.is_open()) {
|
if (!file.is_open()) {
|
||||||
@ -74,7 +75,7 @@ namespace engineapi {
|
|||||||
}
|
}
|
||||||
result<json, FileFlag> FileManager::LoadJsonFile(const PackagePath& pack_path)
|
result<json, FileFlag> FileManager::LoadJsonFile(const PackagePath& pack_path)
|
||||||
{
|
{
|
||||||
string path = real_path(pack_path);
|
string path = RealPath(pack_path);
|
||||||
std::ifstream f(path);
|
std::ifstream f(path);
|
||||||
if (!f.is_open())
|
if (!f.is_open())
|
||||||
{
|
{
|
||||||
@ -96,7 +97,7 @@ namespace engineapi {
|
|||||||
}
|
}
|
||||||
void FileManager::SaveTextFile(const PackagePath& pack_path,const string& value)
|
void FileManager::SaveTextFile(const PackagePath& pack_path,const string& value)
|
||||||
{
|
{
|
||||||
string path = real_path(pack_path);
|
string path = RealPath(pack_path);
|
||||||
std::ofstream of(path);
|
std::ofstream of(path);
|
||||||
of.write(value.data(), value.size());
|
of.write(value.data(), value.size());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -63,9 +63,10 @@ namespace engineapi
|
|||||||
private:
|
private:
|
||||||
inline static table<NameID, std::pair<string, string>> MountMap;
|
inline static table<NameID, std::pair<string, string>> MountMap;
|
||||||
inline static table<NameID, FileControlBlock> FileMap;
|
inline static table<NameID, FileControlBlock> FileMap;
|
||||||
//外界不应该使用绝对路径
|
|
||||||
static string real_path(const PackagePath& pack_path);
|
|
||||||
public:
|
public:
|
||||||
|
//外界不应该使用绝对路径
|
||||||
|
static string RealPath(const PackagePath& pack_path);
|
||||||
|
|
||||||
static FileFlag LoadErrorFlag(const PackagePath& pack_path);
|
static FileFlag LoadErrorFlag(const PackagePath& pack_path);
|
||||||
|
|
||||||
static result<string, FileFlag> LoadTextFile(const PackagePath& pack_path);
|
static result<string, FileFlag> LoadTextFile(const PackagePath& pack_path);
|
||||||
|
|||||||
@ -13,9 +13,9 @@ namespace engineapi
|
|||||||
UPROPERTY({})
|
UPROPERTY({})
|
||||||
string t_hash{};
|
string t_hash{};
|
||||||
UPROPERTY({})
|
UPROPERTY({})
|
||||||
string metadata;
|
string t_meta;
|
||||||
bool operator==(const SerializedMeta& other)const{
|
bool operator==(const SerializedMeta& other)const{
|
||||||
return guid == other.guid && name == other.name && t_hash == other.t_hash && metadata == other.metadata;
|
return guid == other.guid && name == other.name && t_hash == other.t_hash && t_meta == other.t_meta;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
struct ResourceBundle;
|
struct ResourceBundle;
|
||||||
@ -29,6 +29,8 @@ namespace engineapi
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
const SerializedMeta* FetchMeta() const;
|
const SerializedMeta* FetchMeta() const;
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
const SerializedMeta* FetchMeta(const string_view& asset_name) const;
|
||||||
|
template<typename T>
|
||||||
void Add(RscHandle<T>);
|
void Add(RscHandle<T>);
|
||||||
bool operator==(const MetaBundle& other)const;
|
bool operator==(const MetaBundle& other)const;
|
||||||
bool operator!=(const MetaBundle& other)const;
|
bool operator!=(const MetaBundle& other)const;
|
||||||
|
|||||||
@ -4,10 +4,21 @@ namespace engineapi
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
inline const SerializedMeta* MetaBundle::FetchMeta() const
|
inline const SerializedMeta* MetaBundle::FetchMeta() const
|
||||||
{
|
{
|
||||||
string_view name = type_name<T>().View();
|
string_view name = type_name<typename T::BaseResource>().View();
|
||||||
for (auto& elem : metadatas)
|
for (auto& elem : metadatas)
|
||||||
{
|
{
|
||||||
if (string_view(elem.t_hash) == name)
|
if (elem.t_hash == name)
|
||||||
|
return &elem;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
inline const SerializedMeta* MetaBundle::FetchMeta(const string_view& asset_name) const
|
||||||
|
{
|
||||||
|
string_view name = type_name<typename T::BaseResource>().View();
|
||||||
|
for (auto& elem : metadatas)
|
||||||
|
{
|
||||||
|
if (elem.t_hash == name && asset_name == elem.name)
|
||||||
return &elem;
|
return &elem;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -17,7 +28,7 @@ namespace engineapi
|
|||||||
{
|
{
|
||||||
if (h)
|
if (h)
|
||||||
{
|
{
|
||||||
metadatas.emplace_back(SerializedMeta{ h.guid, string{h->Name()}, string{type_name<T>().View()}});
|
metadatas.emplace_back(SerializedMeta{ h.guid, string(h->Name()), string(type_name<T>().View()) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -17,5 +17,9 @@ namespace engineapi {
|
|||||||
{
|
{
|
||||||
return PackagePath{ FileManager::FindPathView(path) };
|
return PackagePath{ FileManager::FindPathView(path) };
|
||||||
}
|
}
|
||||||
|
string PackagePath::RealPath() const
|
||||||
|
{
|
||||||
|
return FileManager::RealPath(*this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -23,6 +23,7 @@ namespace engineapi
|
|||||||
PackagePath() {};
|
PackagePath() {};
|
||||||
PackagePath(const char* path) : path(path) {}
|
PackagePath(const char* path) : path(path) {}
|
||||||
PackagePath(const string_view& path) : path(path) {}
|
PackagePath(const string_view& path) : path(path) {}
|
||||||
|
PackagePath(const string& path) : path(path) {}
|
||||||
PackagePath(const string&& path) : path(path) {}
|
PackagePath(const string&& path) : path(path) {}
|
||||||
size_t size() const{
|
size_t size() const{
|
||||||
return path.size();
|
return path.size();
|
||||||
@ -54,5 +55,6 @@ namespace engineapi
|
|||||||
}
|
}
|
||||||
PackagePath ToSuffixPath(const string_view& suffix)const;
|
PackagePath ToSuffixPath(const string_view& suffix)const;
|
||||||
PackagePath SafePath()const;
|
PackagePath SafePath()const;
|
||||||
|
string RealPath()const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -3,7 +3,6 @@
|
|||||||
namespace engineapi
|
namespace engineapi
|
||||||
{
|
{
|
||||||
struct GenericResourceHandle;
|
struct GenericResourceHandle;
|
||||||
|
|
||||||
struct ResourceBundle
|
struct ResourceBundle
|
||||||
{
|
{
|
||||||
ResourceBundle() = default;
|
ResourceBundle() = default;
|
||||||
@ -13,6 +12,7 @@ namespace engineapi
|
|||||||
template<typename T> void Add(RscHandle<T> handle);
|
template<typename T> void Add(RscHandle<T> handle);
|
||||||
template<typename T> RscHandle<T> Get() const; // get a resource from the bundle
|
template<typename T> RscHandle<T> Get() const; // get a resource from the bundle
|
||||||
span<const GenericResourceHandle> GetAll() const; // gets absolutely all resources
|
span<const GenericResourceHandle> GetAll() const; // gets absolutely all resources
|
||||||
|
template<typename T> span<const GenericResourceHandle> GetAll() const; // get all resources of one type
|
||||||
private:
|
private:
|
||||||
struct sub_array { short index = 0, count = 0; };
|
struct sub_array { short index = 0, count = 0; };
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "resource_bundle.h"
|
|
||||||
namespace engineapi
|
namespace engineapi
|
||||||
{
|
{
|
||||||
template<typename Res>
|
template<typename Res>
|
||||||
@ -31,9 +30,13 @@ namespace engineapi
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline RscHandle<T> engineapi::ResourceBundle::Get() const
|
inline RscHandle<T> ResourceBundle::Get() const
|
||||||
{
|
{
|
||||||
auto& subarray = subarrays[ResourceID<T>];
|
auto& subarray = subarrays[ResourceID<T>];
|
||||||
return subarray.count > 0 ? handles[subarray.index].template AsHandle<T>() : RscHandle<T>();
|
return subarray.count > 0 ? handles[subarray.index].template AsHandle<T>() : RscHandle<T>();
|
||||||
}
|
}
|
||||||
|
template<typename T> span<const GenericResourceHandle> ResourceBundle::GetAll() const {
|
||||||
|
auto& subarray = subarrays[ResourceID<T>];
|
||||||
|
return span<const GenericResourceHandle>{handles.data() + subarray.index, handles.data() + subarray.index + subarray.count};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "type.h"
|
#include "type.h"
|
||||||
namespace engineapi {
|
namespace engineapi {
|
||||||
|
class Guid;
|
||||||
template<typename Res>
|
template<typename Res>
|
||||||
struct RscHandle;
|
struct RscHandle;
|
||||||
template<typename Res>
|
template<typename Res>
|
||||||
@ -8,7 +9,7 @@ namespace engineapi {
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using BaseResource = Res;
|
using BaseResource = Res;
|
||||||
|
Guid GetGuid()const;
|
||||||
RscHandle<Res> GetHandle() const { return mHandle; }
|
RscHandle<Res> GetHandle() const { return mHandle; }
|
||||||
Resource() = default;
|
Resource() = default;
|
||||||
|
|
||||||
@ -21,6 +22,7 @@ namespace engineapi {
|
|||||||
};
|
};
|
||||||
using Resources = std::tuple<
|
using Resources = std::tuple<
|
||||||
class ShaderProgram
|
class ShaderProgram
|
||||||
|
, class Model
|
||||||
, class Asset
|
, class Asset
|
||||||
>;
|
>;
|
||||||
template<typename Resource>
|
template<typename Resource>
|
||||||
|
|||||||
@ -4,18 +4,21 @@
|
|||||||
|
|
||||||
namespace engineapi
|
namespace engineapi
|
||||||
{
|
{
|
||||||
|
struct RscHandleBase {
|
||||||
|
UPROPERTY({})
|
||||||
|
Guid guid;
|
||||||
|
void* res;
|
||||||
|
};
|
||||||
template<typename Res>
|
template<typename Res>
|
||||||
struct RscHandle
|
struct RscHandle : public RscHandleBase
|
||||||
{
|
{
|
||||||
Guid guid{};
|
|
||||||
void* res{};
|
|
||||||
constexpr size_t RscID()const { return ResourceID<Res>; }
|
constexpr size_t RscID()const { return ResourceID<Res>; }
|
||||||
constexpr RscHandle() noexcept = default;
|
constexpr RscHandle() noexcept = default;
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr RscHandle(const RscHandle<T>& other) noexcept : guid{ other.guid }, res(other.res) {};
|
constexpr RscHandle(const RscHandle<T>& other) noexcept : RscHandleBase(other.guid, other.res) {};
|
||||||
constexpr RscHandle(const Guid& guid, Res* res) noexcept : guid{ guid }, res(res) { ((Resource<Res>*)res)->mHandle = *this; }
|
constexpr RscHandle(const Guid& guid, Res* res) noexcept : RscHandleBase(guid, res) { ((Resource<Res>*)res)->mHandle = *this; }
|
||||||
void Init();
|
void Init();
|
||||||
void Clear(){ res = nullptr; };
|
void Clear() { res = nullptr; };
|
||||||
Res* operator->() { if (!res && guid) Init(); return (Res*)res; }
|
Res* operator->() { if (!res && guid) Init(); return (Res*)res; }
|
||||||
Res& operator*() { if (!res && guid) Init(); return *(Res*)res; }
|
Res& operator*() { if (!res && guid) Init(); return *(Res*)res; }
|
||||||
operator bool() { if (!res && guid) Init(); return res; }
|
operator bool() { if (!res && guid) Init(); return res; }
|
||||||
@ -23,34 +26,6 @@ namespace engineapi
|
|||||||
Res& operator*()const { return *(Res*)res; }
|
Res& operator*()const { return *(Res*)res; }
|
||||||
operator bool() const { return res; }
|
operator bool() const { return res; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GenericResourceHandle
|
|
||||||
: variant_wrap_t<tuple_to_variant_t<Resources>, RscHandle>
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
using Base = variant_wrap_t<tuple_to_variant_t<Resources>, RscHandle>;
|
|
||||||
public:
|
|
||||||
using Base::Base;
|
|
||||||
using Base::operator=;
|
|
||||||
template<typename T>
|
|
||||||
GenericResourceHandle(RscHandle<T> handle) : Base(RscHandle<typename T::BaseResource>{handle}) {}
|
|
||||||
GenericResourceHandle(string_view type_name, Guid guid);
|
|
||||||
template<typename T> RscHandle<T> AsHandle() const {
|
|
||||||
return std::get<ResourceID<T>>(*this);
|
|
||||||
}
|
|
||||||
Guid guid() const;
|
|
||||||
size_t resource_id() const;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
// hashtable support
|
#include "resource_handle.inl"
|
||||||
namespace std
|
#include "resource_handle_gen.inl"
|
||||||
{
|
|
||||||
template<typename Res>
|
|
||||||
struct hash <engineapi::RscHandle<Res>>
|
|
||||||
{
|
|
||||||
size_t operator()(const engineapi::RscHandle<Res>& res) const noexcept
|
|
||||||
{
|
|
||||||
return std::hash<engineapi::Guid>()(res.guid);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
43
engine/src/engine/asset/res/resource_handle.inl
Normal file
43
engine/src/engine/asset/res/resource_handle.inl
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#pragma once
|
||||||
|
namespace engineapi{
|
||||||
|
template<typename Res>
|
||||||
|
inline Guid Resource<Res>::GetGuid() const
|
||||||
|
{
|
||||||
|
return GetHandle().guid;
|
||||||
|
}
|
||||||
|
struct GenericResourceHandle
|
||||||
|
: variant_wrap_t<tuple_to_variant_t<Resources>, RscHandle>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
using Base = variant_wrap_t<tuple_to_variant_t<Resources>, RscHandle>;
|
||||||
|
public:
|
||||||
|
using Base::Base;
|
||||||
|
using Base::operator=;
|
||||||
|
template<typename T>
|
||||||
|
GenericResourceHandle(RscHandle<T> handle) : Base(RscHandle<typename T::BaseResource>{handle}) {}
|
||||||
|
GenericResourceHandle(string_view type_name, Guid guid);
|
||||||
|
template<typename T> RscHandle<T> AsHandle() const {
|
||||||
|
return std::get<ResourceID<T>>(*this);
|
||||||
|
}
|
||||||
|
Guid guid() const;
|
||||||
|
size_t resource_id() const;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// hashtable support
|
||||||
|
namespace std
|
||||||
|
{
|
||||||
|
template<typename Res>
|
||||||
|
struct hash <engineapi::RscHandle<Res>>
|
||||||
|
{
|
||||||
|
size_t operator()(const engineapi::RscHandle<Res>& res) const noexcept
|
||||||
|
{
|
||||||
|
return std::hash<engineapi::Guid>()(res.guid);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
namespace refl {
|
||||||
|
template<typename T>
|
||||||
|
struct real_type<engineapi::RscHandle<T>> {
|
||||||
|
using type = engineapi::RscHandleBase;
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -7,6 +7,11 @@ namespace engineapi {
|
|||||||
mResourceTable = detail::ResourceHelper::GenResourceTables();
|
mResourceTable = detail::ResourceHelper::GenResourceTables();
|
||||||
LoadFileFlag();
|
LoadFileFlag();
|
||||||
}
|
}
|
||||||
|
void ResourceManager::LateInit()
|
||||||
|
{
|
||||||
|
SaveFileFlag();
|
||||||
|
SaveDirtyFiles();
|
||||||
|
}
|
||||||
void ResourceManager::Shutdown()
|
void ResourceManager::Shutdown()
|
||||||
{
|
{
|
||||||
constexpr static auto release_tables = detail::ResourceHelper::ReleaseTableResources();
|
constexpr static auto release_tables = detail::ResourceHelper::ReleaseTableResources();
|
||||||
@ -30,23 +35,26 @@ namespace engineapi {
|
|||||||
return it->second.bundle;
|
return it->second.bundle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
auto& res = mFileTable[path.path];
|
||||||
Name ext = path.GetExtension();
|
Name ext = path.GetExtension();
|
||||||
IFileLoader* loader = GetLoader(ext);
|
IFileLoader* loader = GetLoader(ext);
|
||||||
MetaBundle meta = GetMeta(path);
|
MetaBundle meta = GetMeta(path);
|
||||||
ResourceBundle bundle = loader->LoadFile(path, meta);
|
ResourceBundle bundle = loader->LoadFile(path, meta);
|
||||||
MetaBundle new_meta = GetVisitMeta(bundle);
|
MetaBundle new_meta = GetVisitMeta(bundle);
|
||||||
bool is_dirty_meta = meta != new_meta;
|
bool is_dirty_meta = meta != new_meta;
|
||||||
mFileTable[path.path] = {bundle, path.SafePath(), false, is_dirty_meta};
|
|
||||||
auto& res = mFileTable[path.path];
|
|
||||||
for (auto& elem : bundle.GetAll()) {
|
for (auto& elem : bundle.GetAll()) {
|
||||||
std::visit([&](auto& handle) {
|
std::visit([&](auto& handle) {
|
||||||
using T = std::decay_t<decltype(*handle)>;
|
using T = std::decay_t<decltype(*handle)>;
|
||||||
GetControlBlock<T>(handle)->file = &res;
|
GetControlBlock<T>(handle)->file = &res;
|
||||||
}, elem);
|
}, elem);
|
||||||
}
|
}
|
||||||
if (is_dirty_meta) {
|
if (is_dirty_meta || res.is_dirty) {
|
||||||
mDirtyBlocks.push_back(&res);
|
mDirtyBlocks.push_back(&res);
|
||||||
}
|
}
|
||||||
|
res.path = path.SafePath();
|
||||||
|
res.bundle = bundle;
|
||||||
|
res.is_meta_dirty = is_dirty_meta;
|
||||||
|
res.bundle = bundle;
|
||||||
return res.bundle;
|
return res.bundle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +82,7 @@ namespace engineapi {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
string text = YAML::Text_Serialize(bundle);
|
string text = YAML::Text_Serialize(bundle);
|
||||||
FileManager::SaveTextFile(path, text);
|
FileManager::SaveTextFile(path + ".meta", text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void ResourceManager::SaveDirtyFiles()
|
void ResourceManager::SaveDirtyFiles()
|
||||||
|
|||||||
@ -37,6 +37,7 @@ namespace engineapi {
|
|||||||
vector<FileControlBlock*> mDirtyBlocks;
|
vector<FileControlBlock*> mDirtyBlocks;
|
||||||
public:
|
public:
|
||||||
void Init() override;
|
void Init() override;
|
||||||
|
void LateInit()override;
|
||||||
void Shutdown() override;
|
void Shutdown() override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -47,8 +48,9 @@ namespace engineapi {
|
|||||||
auto& GetTable() {
|
auto& GetTable() {
|
||||||
return *reinterpret_cast<ResourceStorage<Res>*> (mResourceTable[ResourceID<Res>].get());
|
return *reinterpret_cast<ResourceStorage<Res>*> (mResourceTable[ResourceID<Res>].get());
|
||||||
}
|
}
|
||||||
template<typename Res>
|
template<typename Res>
|
||||||
ResourceControlBlock<Res>* GetControlBlock(RscHandle<Res> handle);
|
ResourceControlBlock<Res>* GetControlBlock(RscHandle<Res> handle);
|
||||||
|
FileControlBlock& GetFileBlock(PackagePath path);
|
||||||
|
|
||||||
template<typename Res, typename ... Args>
|
template<typename Res, typename ... Args>
|
||||||
[[nodiscard]] RscHandle<Res> LoaderEmplaceResource(Args&& ... args) {
|
[[nodiscard]] RscHandle<Res> LoaderEmplaceResource(Args&& ... args) {
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
#include "resource_manager.h"
|
|
||||||
#pragma once
|
#pragma once
|
||||||
namespace engineapi {
|
namespace engineapi {
|
||||||
class IFileLoader
|
class IFileLoader
|
||||||
@ -97,6 +96,9 @@ namespace engineapi {
|
|||||||
auto& table = GetTable<Res>();
|
auto& table = GetTable<Res>();
|
||||||
return &table[handle.guid];
|
return &table[handle.guid];
|
||||||
}
|
}
|
||||||
|
inline ResourceManager::FileControlBlock& ResourceManager::GetFileBlock(PackagePath path) {
|
||||||
|
return mFileTable[NameID(path.path)];
|
||||||
|
}
|
||||||
template<typename Res>
|
template<typename Res>
|
||||||
inline void RscHandle<Res>::Init()
|
inline void RscHandle<Res>::Init()
|
||||||
{
|
{
|
||||||
|
|||||||
149
engine/src/engine/object/loader/assimp_loader.cpp
Normal file
149
engine/src/engine/object/loader/assimp_loader.cpp
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
#include "zlog.h"
|
||||||
|
#include "assimp_loader.h"
|
||||||
|
#include "asset/file_manager.h"
|
||||||
|
#include "asset/resource_manager.h"
|
||||||
|
#include "assimp/Importer.hpp"
|
||||||
|
#include "assimp/scene.h"
|
||||||
|
#include "assimp/postprocess.h"
|
||||||
|
#include <fstream>
|
||||||
|
namespace engineapi {
|
||||||
|
void AssimpLoader::Init()
|
||||||
|
{
|
||||||
|
ResourceManager::GetSingleton().RegisterLoader<AssimpLoader>(".obj");
|
||||||
|
ResourceManager::GetSingleton().RegisterLoader<AssimpLoader>(".ply");
|
||||||
|
}
|
||||||
|
ResourceBundle AssimpLoader::LoadFile(PackagePath handle, const MetaBundle& meta)
|
||||||
|
{
|
||||||
|
auto m = meta.FetchMeta<Model>();
|
||||||
|
auto asset = m ? ResourceManager::GetSingleton().LoaderEmplaceResource<Model>(m->guid)
|
||||||
|
: ResourceManager::GetSingleton().LoaderEmplaceResource<Model>();
|
||||||
|
uint32_t flag = FileManager::FindPathFlag(handle);
|
||||||
|
if (flag & FileFlag::File_Http) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
LoadModel(handle, *asset, meta);
|
||||||
|
ResourceBundle bundle{ asset };
|
||||||
|
for (auto& mesh : asset->GetMeshs()) {
|
||||||
|
bundle.Add(mesh);
|
||||||
|
}
|
||||||
|
PackagePath asset_handle(handle + ".asset");
|
||||||
|
std::ifstream file(asset_handle.RealPath());
|
||||||
|
if (!file.good()) {
|
||||||
|
auto& block = ResourceManager::GetSingleton().GetFileBlock(handle);
|
||||||
|
block.is_dirty = true;
|
||||||
|
}
|
||||||
|
return bundle;
|
||||||
|
}
|
||||||
|
void AssimpLoader::SaveFile(PackagePath handle, const ResourceBundle& bundle)
|
||||||
|
{
|
||||||
|
auto loader = ResourceManager::GetSingleton().GetLoader(".asset");
|
||||||
|
if(loader)
|
||||||
|
loader->SaveFile(handle + ".asset", bundle);
|
||||||
|
}
|
||||||
|
void AssimpLoader::LoadModel(PackagePath handle, Model& model, const MetaBundle& meta)
|
||||||
|
{
|
||||||
|
// 用ASSIMP加载模型文件
|
||||||
|
Assimp::Importer importer;
|
||||||
|
const aiScene* scene = importer.ReadFile(handle.RealPath(), aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_CalcTangentSpace
|
||||||
|
| aiProcess_FixInfacingNormals | aiProcess_FlipWindingOrder | aiProcess_LimitBoneWeights);
|
||||||
|
|
||||||
|
// 检查异常
|
||||||
|
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
|
||||||
|
{
|
||||||
|
zlog::error("ASSIMP: {}", importer.GetErrorString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ProcessNode(model, meta, scene->mRootNode, scene);
|
||||||
|
}
|
||||||
|
void AssimpLoader::ProcessNode(Model& model, const MetaBundle& meta, const aiNode* pNode, const aiScene* pScene)
|
||||||
|
{
|
||||||
|
// 处理Mesh数据
|
||||||
|
auto& meshs = model.GetMeshs();
|
||||||
|
for (unsigned int i = 0; i < pNode->mNumMeshes; i++)
|
||||||
|
{
|
||||||
|
// aiNode仅包含索引来获取aiScene中的实际对象
|
||||||
|
// aiScene包含所有数据,aiNode只是为了让数据组织起来(比如记录节点之间的关系)
|
||||||
|
aiMesh* mesh = pScene->mMeshes[pNode->mMeshes[i]];
|
||||||
|
auto m = meta.FetchMeta<Mesh>(mesh->mName.C_Str());
|
||||||
|
meshs.push_back(ProcessMesh(m, mesh));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载骨骼数据
|
||||||
|
//pBoneNode->name = pNode->mName.C_Str();
|
||||||
|
//pBoneNode->transform = aiMatrix4x4ToMatrix4(pNode->mTransformation);
|
||||||
|
|
||||||
|
// 递归处理子节点
|
||||||
|
for (unsigned int i = 0; i < pNode->mNumChildren; i++)
|
||||||
|
{
|
||||||
|
//pBoneNode->children.push_back(new BoneNode());
|
||||||
|
ProcessNode(model, meta, pNode->mChildren[i], pScene);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RscHandle<Mesh> AssimpLoader::ProcessMesh(const SerializedMeta* m, const aiMesh* mesh)
|
||||||
|
{
|
||||||
|
// data to fill
|
||||||
|
vector<BoneVertex> vertices;
|
||||||
|
vector<uint32_t> indices;
|
||||||
|
// Walk through each of the mesh's vertices
|
||||||
|
for (unsigned int i = 0; i < mesh->mNumVertices; i++)
|
||||||
|
{
|
||||||
|
BoneVertex vertex;
|
||||||
|
Vector3 vector; // we declare a placeholder vector since assimp uses its own vector class that doesn't directly convert to Vector3 class so we transfer the data to this placeholder Vector3 first.
|
||||||
|
|
||||||
|
// positions
|
||||||
|
vector.x = mesh->mVertices[i].x;
|
||||||
|
vector.y = mesh->mVertices[i].y;
|
||||||
|
vector.z = mesh->mVertices[i].z;
|
||||||
|
vertex.Position = vector;
|
||||||
|
|
||||||
|
// normals
|
||||||
|
vector.x = mesh->mNormals[i].x;
|
||||||
|
vector.y = mesh->mNormals[i].y;
|
||||||
|
vector.z = mesh->mNormals[i].z;
|
||||||
|
vertex.Normal = vector;
|
||||||
|
|
||||||
|
// texture coordinates
|
||||||
|
if (mesh->mTextureCoords[0]) // does the mesh contain texture coordinates?
|
||||||
|
{
|
||||||
|
Vector2 vec;
|
||||||
|
// a vertex can contain up to 8 different texture coordinates. We thus make the assumption that we won't
|
||||||
|
// use models where a vertex can have multiple texture coordinates so we always take the first set (0).
|
||||||
|
vec.x = mesh->mTextureCoords[0][i].x;
|
||||||
|
vec.y = mesh->mTextureCoords[0][i].y;
|
||||||
|
vertex.TexCoords = vec;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vertex.TexCoords = Vector2(0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// tangent and bitangent
|
||||||
|
if (mesh->HasTangentsAndBitangents())
|
||||||
|
{
|
||||||
|
vector.x = mesh->mTangents[i].x;
|
||||||
|
vector.y = mesh->mTangents[i].y;
|
||||||
|
vector.z = mesh->mTangents[i].z;
|
||||||
|
vertex.Tangent = vector;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vertex.Tangent = Vector3(0.0f, 0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
vertices.push_back(vertex);
|
||||||
|
}
|
||||||
|
// now wak through each of the mesh's faces (a face is a mesh its triangle) and retrieve the corresponding vertex indices.
|
||||||
|
for (unsigned int i = 0; i < mesh->mNumFaces; i++)
|
||||||
|
{
|
||||||
|
const aiFace& face = mesh->mFaces[i];
|
||||||
|
// retrieve all indices of the face and store them in the indices vector
|
||||||
|
for (unsigned int j = 0; j < face.mNumIndices; j++)
|
||||||
|
{
|
||||||
|
indices.push_back(face.mIndices[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto asset = m ? ResourceManager::GetSingleton().LoaderEmplaceResource<Mesh>(m->guid, vertices, indices)
|
||||||
|
: ResourceManager::GetSingleton().LoaderEmplaceResource<Mesh>(vertices, indices);
|
||||||
|
asset->Name(mesh->mName.C_Str());
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
}
|
||||||
20
engine/src/engine/object/loader/assimp_loader.h
Normal file
20
engine/src/engine/object/loader/assimp_loader.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "render/asset/model.h"
|
||||||
|
#include "asset/resource_manager.h"
|
||||||
|
class aiNode;
|
||||||
|
class aiMesh;
|
||||||
|
class aiScene;
|
||||||
|
namespace engineapi {
|
||||||
|
class AssimpLoader : public IFileLoader
|
||||||
|
{
|
||||||
|
inline static table<Guid, void*> ShaderTable;
|
||||||
|
public:
|
||||||
|
static void Init();
|
||||||
|
ResourceBundle LoadFile(PackagePath handle, const MetaBundle& meta) override;
|
||||||
|
void SaveFile(PackagePath handle, const ResourceBundle& bundle) override;
|
||||||
|
|
||||||
|
void LoadModel(PackagePath handle, Model& model, const MetaBundle& meta);
|
||||||
|
void ProcessNode(Model& model, const MetaBundle& meta, const aiNode* pNode, const aiScene* pScene);
|
||||||
|
RscHandle<Mesh> ProcessMesh(const SerializedMeta* m, const aiMesh* mesh);
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
#include "actor.h"
|
#include "actor.h"
|
||||||
|
#include "asset/resource_manager.h"
|
||||||
#include "data/property/actor_property.h"
|
#include "data/property/actor_property.h"
|
||||||
namespace engineapi {
|
namespace engineapi {
|
||||||
ActorMesh::ActorMesh(Model& model, ActorProperty& property)
|
ActorMesh::ActorMesh(Model& model, ActorProperty& property)
|
||||||
@ -9,9 +10,8 @@ namespace engineapi {
|
|||||||
}
|
}
|
||||||
ActorMesh* ActorMesh::New(ActorProperty& property)
|
ActorMesh* ActorMesh::New(ActorProperty& property)
|
||||||
{
|
{
|
||||||
//Model* model = AssetManager::GetSingletonPtr()->LoadAsset<Model>(property.path, property.flags);
|
auto res = ResourceManager::GetSingleton().Load<Model>(property.path);
|
||||||
//return new ActorMesh(*model, property);
|
return new ActorMesh(*res, property);
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
ActorMesh* ActorMesh::New(uint32_t id)
|
ActorMesh* ActorMesh::New(uint32_t id)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -8,6 +8,6 @@ namespace engineapi {
|
|||||||
}
|
}
|
||||||
void StaticMesh::LoadMesh()
|
void StaticMesh::LoadMesh()
|
||||||
{
|
{
|
||||||
|
mPtr.BeginLoad();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -12,18 +12,19 @@ namespace engineapi {
|
|||||||
mCamera = new Camera();
|
mCamera = new Camera();
|
||||||
int flags = 1;
|
int flags = 1;
|
||||||
auto shader = ResourceManager::GetSingleton().LoaderEmplaceResource<Shader>();
|
auto shader = ResourceManager::GetSingleton().LoaderEmplaceResource<Shader>();
|
||||||
shader->mVertexName = type_name<BoneVertex>().View();
|
shader->Name(type_name<BoneVertex>().View());
|
||||||
shader->mVert = ResourceManager::GetSingleton().Load<ShaderProgram>("/engine/assets/shader/simple.vert");
|
shader->mVert = ResourceManager::GetSingleton().Load<ShaderProgram>("/engine/assets/shader/simple.vert");
|
||||||
shader->mFrag = ResourceManager::GetSingleton().Load<ShaderProgram>("/engine/assets/shader/simple.frag");
|
shader->mFrag = ResourceManager::GetSingleton().Load<ShaderProgram>("/engine/assets/shader/simple.frag");
|
||||||
RenderAPI::GetSingleton().LoadShader(&*shader);
|
RenderAPI::GetSingleton().LoadShader(*shader);
|
||||||
Material* material = new Material("/engine/assets/shader/simple.shader", flags);
|
//Material* material = new Material("/engine/assets/shader/simple.shader", flags);
|
||||||
{
|
{
|
||||||
ActorProperty property;
|
ActorProperty property;
|
||||||
property.id = 1;
|
property.id = 1;
|
||||||
property.flags = flags;
|
property.flags = flags;
|
||||||
property.path = "/engine/assets/models/cube.obj";
|
property.path = "/engine/assets/models/cube.obj";
|
||||||
actor1 = ActorMesh::New(property);
|
actor1 = ActorMesh::New(property);
|
||||||
actor1->Ptr().SetMaterial(material);
|
actor1->LoadMesh();
|
||||||
|
//actor1->Ptr().SetMaterial(material);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ActorProperty property;
|
ActorProperty property;
|
||||||
@ -31,7 +32,7 @@ namespace engineapi {
|
|||||||
property.flags = flags;
|
property.flags = flags;
|
||||||
property.path = "/engine/assets/models/box.ply";
|
property.path = "/engine/assets/models/box.ply";
|
||||||
actor2 = ActorMesh::New(property);
|
actor2 = ActorMesh::New(property);
|
||||||
actor2->Ptr().SetMaterial(material);
|
//actor2->Ptr().SetMaterial(material);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Scene::~Scene()
|
Scene::~Scene()
|
||||||
@ -43,11 +44,10 @@ namespace engineapi {
|
|||||||
void Scene::Render()
|
void Scene::Render()
|
||||||
{
|
{
|
||||||
RenderAPI::GetSingletonPtr()->Render(*mCamera);
|
RenderAPI::GetSingletonPtr()->Render(*mCamera);
|
||||||
auto meshs = actor1->Ptr().GetMeshs();
|
//auto meshs = actor1->Ptr().GetMeshs();
|
||||||
for (auto it : meshs) {
|
//for (auto it : meshs) {
|
||||||
RenderAPI::GetSingletonPtr()->DrawStaticMesh(it);
|
//RenderAPI::GetSingletonPtr()->DrawStaticMesh(*it);
|
||||||
}
|
//}
|
||||||
//RenderAPI::GetSingletonPtr()->DrawStaticMesh(actor2);
|
|
||||||
}
|
}
|
||||||
void Scene::AddGameObject(GameObject* gameObject)
|
void Scene::AddGameObject(GameObject* gameObject)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -2,9 +2,9 @@
|
|||||||
#include "shader.h"
|
#include "shader.h"
|
||||||
#include "../renderapi.h"
|
#include "../renderapi.h"
|
||||||
namespace engineapi {
|
namespace engineapi {
|
||||||
Material::Material(string_view name, uint32_t flags)
|
Material::Material() : Asset(&refl::TypeInfo<Material>::StaticClass)
|
||||||
{
|
{
|
||||||
//mShader = new Shader(name, flags);
|
|
||||||
}
|
}
|
||||||
Material::~Material()
|
Material::~Material()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,15 +1,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "asset/asset.h"
|
#include "asset/asset.h"
|
||||||
|
#include "shader.h"
|
||||||
namespace engineapi {
|
namespace engineapi {
|
||||||
class Shader;
|
|
||||||
class Material : public Asset {
|
class Material : public Asset {
|
||||||
protected:
|
protected:
|
||||||
uint32_t mId{0};
|
REFL_FRIEND(Material)
|
||||||
Shader* mShader;
|
UPROPERTY()
|
||||||
|
RscHandle<Shader> mShader;
|
||||||
public:
|
public:
|
||||||
Material(string_view name, uint32_t flags);
|
Material();
|
||||||
~Material();
|
~Material();
|
||||||
|
RscHandle<Shader> GetShader() {
|
||||||
|
return mShader;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
#include "material_gen.inl"
|
||||||
@ -3,6 +3,6 @@
|
|||||||
namespace engineapi {
|
namespace engineapi {
|
||||||
void Mesh::BeginLoad()
|
void Mesh::BeginLoad()
|
||||||
{
|
{
|
||||||
RenderAPI::GetSingletonPtr()->SetStaticMesh(this);
|
RenderAPI::GetSingletonPtr()->SetStaticMesh(*this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,30 +1,28 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "material.h"
|
||||||
|
#include "vertex.h"
|
||||||
#include "refl/std/parray.h"
|
#include "refl/std/parray.h"
|
||||||
#include "asset/asset.h"
|
|
||||||
#include "../meta/vertex.h"
|
|
||||||
namespace engineapi {
|
namespace engineapi {
|
||||||
using refl::parray;
|
using refl::parray;
|
||||||
class Texture;
|
class Mesh : public Asset{
|
||||||
class Material;
|
|
||||||
class Mesh : public Asset {
|
|
||||||
protected:
|
protected:
|
||||||
uint32_t VAO = 0;
|
REFL_FRIEND(Mesh)
|
||||||
|
UPROPERTY()
|
||||||
|
RscHandle<Material> mMaterial;
|
||||||
parray<Vertex> mVertices;
|
parray<Vertex> mVertices;
|
||||||
vector<uint32_t> mIndices;
|
vector<uint32_t> mIndices;
|
||||||
public:
|
public:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
requires std::is_base_of_v<Vertex, T>
|
requires std::is_base_of_v<Vertex, T>
|
||||||
Mesh(vector<T>& vertices, vector<uint32_t>& indices)
|
Mesh(vector<T>& vertices, vector<uint32_t>& indices);
|
||||||
: mVertices(vertices)
|
|
||||||
, mIndices(indices)
|
|
||||||
{
|
|
||||||
BeginLoad();
|
|
||||||
}
|
|
||||||
void BeginLoad();
|
void BeginLoad();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
uint32_t& GetVAO() {
|
Guid GetShaderGuid() {
|
||||||
return VAO;
|
return mMaterial->GetShader().guid;
|
||||||
|
}
|
||||||
|
RscHandle<Material> GetMaterial() {
|
||||||
|
return mMaterial;
|
||||||
}
|
}
|
||||||
parray<Vertex>& GetVertices() {
|
parray<Vertex>& GetVertices() {
|
||||||
return mVertices;
|
return mVertices;
|
||||||
@ -33,4 +31,14 @@ namespace engineapi {
|
|||||||
return mIndices;
|
return mIndices;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
#include "mesh_gen.inl"
|
||||||
|
namespace engineapi {
|
||||||
|
template<typename T>
|
||||||
|
requires std::is_base_of_v<Vertex, T>
|
||||||
|
inline Mesh::Mesh(vector<T>& vertices, vector<uint32_t>& indices)
|
||||||
|
: Asset(&refl::TypeInfo<Mesh>::StaticClass), mVertices(vertices), mIndices(indices)
|
||||||
|
{
|
||||||
|
auto cls = &refl::TypeInfo<Mesh>::StaticClass;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,109 +1,10 @@
|
|||||||
#include "model.h"
|
#include "model.h"
|
||||||
#include "zlog.h"
|
|
||||||
#include "assimp/Importer.hpp"
|
|
||||||
#include "assimp/scene.h"
|
|
||||||
#include "assimp/postprocess.h"
|
|
||||||
namespace engineapi {
|
namespace engineapi {
|
||||||
void Model::BeginLoad()
|
void Model::BeginLoad()
|
||||||
{
|
{
|
||||||
string mName = "";
|
for (auto mesh : mMeshes) {
|
||||||
// 用ASSIMP加载模型文件
|
mesh->BeginLoad();
|
||||||
Assimp::Importer importer;
|
|
||||||
const aiScene* scene = importer.ReadFile(mName, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_CalcTangentSpace
|
|
||||||
| aiProcess_FixInfacingNormals | aiProcess_FlipWindingOrder | aiProcess_LimitBoneWeights);
|
|
||||||
|
|
||||||
// 检查异常
|
|
||||||
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
|
|
||||||
{
|
|
||||||
zlog::error("ASSIMP: {}", importer.GetErrorString());
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
ProcessNode(scene->mRootNode, scene);
|
|
||||||
}
|
|
||||||
void Model::ProcessNode(const aiNode* pNode, const aiScene* pScene)
|
|
||||||
{
|
|
||||||
// 处理Mesh数据
|
|
||||||
for (unsigned int i = 0; i < pNode->mNumMeshes; i++)
|
|
||||||
{
|
|
||||||
// aiNode仅包含索引来获取aiScene中的实际对象
|
|
||||||
// aiScene包含所有数据,aiNode只是为了让数据组织起来(比如记录节点之间的关系)
|
|
||||||
aiMesh* mesh = pScene->mMeshes[pNode->mMeshes[i]];
|
|
||||||
mMeshes.push_back(ProcessMesh(mesh));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 加载骨骼数据
|
|
||||||
//pBoneNode->name = pNode->mName.C_Str();
|
|
||||||
//pBoneNode->transform = aiMatrix4x4ToMatrix4(pNode->mTransformation);
|
|
||||||
|
|
||||||
// 递归处理子节点
|
|
||||||
for (unsigned int i = 0; i < pNode->mNumChildren; i++)
|
|
||||||
{
|
|
||||||
//pBoneNode->children.push_back(new BoneNode());
|
|
||||||
ProcessNode(pNode->mChildren[i], pScene);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Mesh* Model::ProcessMesh(const aiMesh* mesh) {
|
|
||||||
// data to fill
|
|
||||||
vector<BoneVertex> vertices;
|
|
||||||
vector<uint32_t> indices;
|
|
||||||
// Walk through each of the mesh's vertices
|
|
||||||
for (unsigned int i = 0; i < mesh->mNumVertices; i++)
|
|
||||||
{
|
|
||||||
BoneVertex vertex;
|
|
||||||
Vector3 vector; // we declare a placeholder vector since assimp uses its own vector class that doesn't directly convert to Vector3 class so we transfer the data to this placeholder Vector3 first.
|
|
||||||
|
|
||||||
// positions
|
|
||||||
vector.x = mesh->mVertices[i].x;
|
|
||||||
vector.y = mesh->mVertices[i].y;
|
|
||||||
vector.z = mesh->mVertices[i].z;
|
|
||||||
vertex.Position = vector;
|
|
||||||
|
|
||||||
// normals
|
|
||||||
vector.x = mesh->mNormals[i].x;
|
|
||||||
vector.y = mesh->mNormals[i].y;
|
|
||||||
vector.z = mesh->mNormals[i].z;
|
|
||||||
vertex.Normal = vector;
|
|
||||||
|
|
||||||
// texture coordinates
|
|
||||||
if (mesh->mTextureCoords[0]) // does the mesh contain texture coordinates?
|
|
||||||
{
|
|
||||||
Vector2 vec;
|
|
||||||
// a vertex can contain up to 8 different texture coordinates. We thus make the assumption that we won't
|
|
||||||
// use models where a vertex can have multiple texture coordinates so we always take the first set (0).
|
|
||||||
vec.x = mesh->mTextureCoords[0][i].x;
|
|
||||||
vec.y = mesh->mTextureCoords[0][i].y;
|
|
||||||
vertex.TexCoords = vec;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
vertex.TexCoords = Vector2(0.0f, 0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
// tangent and bitangent
|
|
||||||
if (mesh->HasTangentsAndBitangents())
|
|
||||||
{
|
|
||||||
vector.x = mesh->mTangents[i].x;
|
|
||||||
vector.y = mesh->mTangents[i].y;
|
|
||||||
vector.z = mesh->mTangents[i].z;
|
|
||||||
vertex.Tangent = vector;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
vertex.Tangent = Vector3(0.0f, 0.0f, 0.0f);
|
|
||||||
}
|
|
||||||
vertices.push_back(vertex);
|
|
||||||
}
|
|
||||||
// now wak through each of the mesh's faces (a face is a mesh its triangle) and retrieve the corresponding vertex indices.
|
|
||||||
for (unsigned int i = 0; i < mesh->mNumFaces; i++)
|
|
||||||
{
|
|
||||||
const aiFace& face = mesh->mFaces[i];
|
|
||||||
// retrieve all indices of the face and store them in the indices vector
|
|
||||||
for (unsigned int j = 0; j < face.mNumIndices; j++)
|
|
||||||
{
|
|
||||||
indices.push_back(face.mIndices[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new Mesh(vertices, indices);
|
|
||||||
}
|
}
|
||||||
void Model::Use()
|
void Model::Use()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,26 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "asset/asset.h"
|
|
||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
#include "material.h"
|
|
||||||
class aiNode;
|
|
||||||
class aiMesh;
|
|
||||||
class aiScene;
|
|
||||||
namespace engineapi {
|
namespace engineapi {
|
||||||
class Model : public Asset {
|
class Model : public Resource<Model> {
|
||||||
protected:
|
protected:
|
||||||
vector<Mesh*> mMeshes;
|
vector<RscHandle<Mesh>> mMeshes;
|
||||||
Material* mMaterial;
|
|
||||||
public:
|
public:
|
||||||
using Asset::Asset;
|
|
||||||
void BeginLoad();
|
void BeginLoad();
|
||||||
void ProcessNode(const aiNode* pNode, const aiScene* pScene);
|
vector<RscHandle<Mesh>>& GetMeshs() {
|
||||||
Mesh* ProcessMesh(const aiMesh* mesh);
|
|
||||||
vector<Mesh*>& GetMeshs() {
|
|
||||||
return mMeshes;
|
return mMeshes;
|
||||||
}
|
}
|
||||||
void SetMaterial(Material* material) {
|
|
||||||
mMaterial = material;
|
|
||||||
}
|
|
||||||
void Use();
|
void Use();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -1,8 +1,6 @@
|
|||||||
#include "shader.h"
|
#include "shader.h"
|
||||||
#include "asset/file_manager.h"
|
|
||||||
#include "../renderapi.h"
|
|
||||||
namespace engineapi {
|
namespace engineapi {
|
||||||
Shader::Shader()
|
Shader::Shader() : Asset(&refl::TypeInfo<Shader>::StaticClass)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,10 +5,12 @@ namespace engineapi {
|
|||||||
class ShaderProgram : public Resource<ShaderProgram> {};
|
class ShaderProgram : public Resource<ShaderProgram> {};
|
||||||
class Shader : public Asset {
|
class Shader : public Asset {
|
||||||
private:
|
private:
|
||||||
|
REFL_FRIEND(Shader)
|
||||||
uint32_t mId;
|
uint32_t mId;
|
||||||
ShaderInfo mInfo;
|
ShaderInfo mInfo;
|
||||||
string mVertexName;
|
UPROPERTY()
|
||||||
RscHandle<ShaderProgram> mVert;
|
RscHandle<ShaderProgram> mVert;
|
||||||
|
UPROPERTY()
|
||||||
RscHandle<ShaderProgram> mFrag;
|
RscHandle<ShaderProgram> mFrag;
|
||||||
friend class Scene;
|
friend class Scene;
|
||||||
public:
|
public:
|
||||||
@ -20,9 +22,6 @@ namespace engineapi {
|
|||||||
ShaderInfo& GetInfo() {
|
ShaderInfo& GetInfo() {
|
||||||
return mInfo;
|
return mInfo;
|
||||||
}
|
}
|
||||||
string_view GetVertexName() {
|
|
||||||
return mVertexName;
|
|
||||||
}
|
|
||||||
template<typename T = ShaderProgram>
|
template<typename T = ShaderProgram>
|
||||||
RscHandle<T> GetVertHandle() {
|
RscHandle<T> GetVertHandle() {
|
||||||
return mVert;
|
return mVert;
|
||||||
@ -32,4 +31,5 @@ namespace engineapi {
|
|||||||
return mFrag;
|
return mFrag;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
#include "shader_gen.inl"
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
#include "texture.h"
|
||||||
|
namespace engineapi {
|
||||||
|
Texture::Texture() : Asset(&refl::TypeInfo<Texture>::StaticClass)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,6 +3,6 @@
|
|||||||
|
|
||||||
namespace engineapi {
|
namespace engineapi {
|
||||||
class Texture : public Asset {
|
class Texture : public Asset {
|
||||||
|
Texture();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "../asset/material.h"
|
#include "../asset/material.h"
|
||||||
#include "../asset/mesh.h"
|
|
||||||
#include "../asset/texture.h"
|
#include "../asset/texture.h"
|
||||||
#include "../render_context.h"
|
#include "../render_context.h"
|
||||||
namespace engineapi {
|
namespace engineapi {
|
||||||
|
|||||||
@ -31,10 +31,10 @@ namespace engineapi
|
|||||||
virtual void BeginFrame() = 0;
|
virtual void BeginFrame() = 0;
|
||||||
virtual void Render(Camera& camera);
|
virtual void Render(Camera& camera);
|
||||||
virtual void EndFrame() = 0;
|
virtual void EndFrame() = 0;
|
||||||
virtual void SetStaticMesh(Mesh* mesh) = 0;
|
virtual void SetStaticMesh(Mesh& mesh) = 0;
|
||||||
virtual void DrawStaticMesh(Mesh* mesh) = 0;
|
virtual void DrawStaticMesh(Mesh& mesh) = 0;
|
||||||
|
|
||||||
virtual void LoadShader(Shader* shader) = 0;
|
virtual void LoadShader(Shader& shader) = 0;
|
||||||
virtual void SwitchContext() = 0;
|
virtual void SwitchContext() = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
#include "vulkanapi/tool/glsl_to_spirv.h"
|
#include "vulkanapi/tool/glsl_to_spirv.h"
|
||||||
#include "vulkanapi/vulkanapi.h"
|
#include "vulkanapi/vulkanapi.h"
|
||||||
#include "asset/file_manager.h"
|
#include "asset/file_manager.h"
|
||||||
#include "render/meta/vertex.h"
|
#include "render/asset/vertex.h"
|
||||||
#include "vkmeta_vertex_gen.inl"
|
#include "vkmeta_vertex_gen.inl"
|
||||||
#include <spirv_cross/spirv_reflect.hpp>
|
#include <spirv_cross/spirv_reflect.hpp>
|
||||||
using namespace engineapi;
|
using namespace engineapi;
|
||||||
@ -56,7 +56,7 @@ namespace vulkanapi {
|
|||||||
auto spirv = GlslToSpirv::spirv(glsl, shader_enum, handle.GetFileName());
|
auto spirv = GlslToSpirv::spirv(glsl, shader_enum, handle.GetFileName());
|
||||||
if (spirv) {
|
if (spirv) {
|
||||||
program->Load(*spirv);
|
program->Load(*spirv);
|
||||||
LoadShaderInfo(program->GetHandle().guid, *spirv);
|
LoadShaderInfo(program->GetGuid(), *spirv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -64,13 +64,13 @@ namespace vulkanapi {
|
|||||||
{
|
{
|
||||||
swapchain->Present(context);
|
swapchain->Present(context);
|
||||||
}
|
}
|
||||||
void RenderVulkanAPI::SetStaticMesh(Mesh* mesh)
|
void RenderVulkanAPI::SetStaticMesh(Mesh& mesh)
|
||||||
{
|
{
|
||||||
auto Indices = mesh->GetIndices();
|
auto Indices = mesh.GetIndices();
|
||||||
auto Vertices = mesh->GetVertices();
|
auto Vertices = mesh.GetVertices();
|
||||||
auto meshBuffer = GetNextVAO(mesh->GetVAO());
|
VulkanVAO& meshBuffer = VAOTable[mesh.GetGuid()];
|
||||||
meshBuffer->indexCount = Indices.size();
|
meshBuffer.indexCount = Indices.size();
|
||||||
meshBuffer->vertexCount = Vertices.size();
|
meshBuffer.vertexCount = Vertices.size();
|
||||||
|
|
||||||
// ----------------------------------------------- Vertex Buffer -----------------------------------------------
|
// ----------------------------------------------- Vertex Buffer -----------------------------------------------
|
||||||
VkDeviceSize vertexBufferSize = Vertices.capicty();
|
VkDeviceSize vertexBufferSize = Vertices.capicty();
|
||||||
@ -84,7 +84,7 @@ namespace vulkanapi {
|
|||||||
VkBufferUsageFlags vertexFlags = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;//加入光线追踪
|
VkBufferUsageFlags vertexFlags = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;//加入光线追踪
|
||||||
VmaAllocationCreateInfo vertexVmaCreateInfo = {};
|
VmaAllocationCreateInfo vertexVmaCreateInfo = {};
|
||||||
VkBufferCreateInfo vertexCreateInfo = Buffer::MakeDeviceInfo(vertexVmaCreateInfo, vertexBufferSize, vertexFlags);
|
VkBufferCreateInfo vertexCreateInfo = Buffer::MakeDeviceInfo(vertexVmaCreateInfo, vertexBufferSize, vertexFlags);
|
||||||
meshBuffer->vertexBuffer = Buffer::CreateBuffer(vertexCreateInfo, vertexVmaCreateInfo, meshBuffer->vertexBufferAlloc);
|
meshBuffer.vertexBuffer = Buffer::CreateBuffer(vertexCreateInfo, vertexVmaCreateInfo, meshBuffer.vertexBufferAlloc);
|
||||||
|
|
||||||
// ----------------------------------------------- Index Buffer -----------------------------------------------
|
// ----------------------------------------------- Index Buffer -----------------------------------------------
|
||||||
VkDeviceSize indexBufferSize = sizeof(uint32_t) * Indices.size();
|
VkDeviceSize indexBufferSize = sizeof(uint32_t) * Indices.size();
|
||||||
@ -96,11 +96,11 @@ namespace vulkanapi {
|
|||||||
|
|
||||||
VmaAllocationCreateInfo indexVmaCreateInfo = {};
|
VmaAllocationCreateInfo indexVmaCreateInfo = {};
|
||||||
VkBufferCreateInfo indexCreateInfo = Buffer::MakeDeviceInfo(indexVmaCreateInfo, indexBufferSize, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
|
VkBufferCreateInfo indexCreateInfo = Buffer::MakeDeviceInfo(indexVmaCreateInfo, indexBufferSize, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
|
||||||
meshBuffer->indexBuffer = Buffer::CreateBuffer(indexCreateInfo, indexVmaCreateInfo, meshBuffer->vertexBufferAlloc);
|
meshBuffer.indexBuffer = Buffer::CreateBuffer(indexCreateInfo, indexVmaCreateInfo, meshBuffer.vertexBufferAlloc);
|
||||||
|
|
||||||
auto fn = [=](CommandBuffer& cmd) {
|
auto fn = [=](CommandBuffer& cmd) {
|
||||||
cmd.CmdCopyBuffer(vertexStagingBuffer, meshBuffer->vertexBuffer, vertexBufferSize);
|
cmd.CmdCopyBuffer(vertexStagingBuffer, meshBuffer.vertexBuffer, vertexBufferSize);
|
||||||
cmd.CmdCopyBuffer(indexStagingBuffer, meshBuffer->indexBuffer, indexBufferSize);
|
cmd.CmdCopyBuffer(indexStagingBuffer, meshBuffer.indexBuffer, indexBufferSize);
|
||||||
};
|
};
|
||||||
auto callback = [=]() {
|
auto callback = [=]() {
|
||||||
// 销毁StagingBuffer
|
// 销毁StagingBuffer
|
||||||
@ -115,16 +115,16 @@ namespace vulkanapi {
|
|||||||
Backend::TransferWorker->ImmediatelyExecute(fn, callback);
|
Backend::TransferWorker->ImmediatelyExecute(fn, callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void RenderVulkanAPI::DrawStaticMesh(Mesh* mesh)
|
void RenderVulkanAPI::DrawStaticMesh(Mesh& mesh)
|
||||||
{
|
{
|
||||||
auto vulkanVAO = VAOList[mesh->GetVAO()];
|
VulkanVAO& vulkanVAO = VAOTable[mesh.GetGuid()];
|
||||||
auto pipeline = PiPelineList[0];
|
VulkanPipeline& pipeline = PipelineTable[mesh.GetShaderGuid()];
|
||||||
uint32_t frame = context.frame;
|
uint32_t frame = context.frame;
|
||||||
context.Pass->SetViewPort(mViewPortInfo.width, mViewPortInfo.height, mViewPortInfo.xOffset, mViewPortInfo.yOffset);
|
context.Pass->SetViewPort(mViewPortInfo.width, mViewPortInfo.height, mViewPortInfo.xOffset, mViewPortInfo.yOffset);
|
||||||
Backend::RenderWorker->Draw([=](CommandBuffer& cmd) {
|
Backend::RenderWorker->Draw([=](CommandBuffer& cmd) {
|
||||||
VkCommandBuffer ptr = cmd.Ptr();
|
VkCommandBuffer ptr = cmd.Ptr();
|
||||||
context.Pass->BeginPass(cmd, frame);
|
context.Pass->BeginPass(cmd, frame);
|
||||||
VkBuffer vertexBuffers[] = { vulkanVAO->vertexBuffer };
|
VkBuffer vertexBuffers[] = { vulkanVAO.vertexBuffer };
|
||||||
VkDeviceSize offsets[] = { 0 };
|
VkDeviceSize offsets[] = { 0 };
|
||||||
VkViewport viewport = {};
|
VkViewport viewport = {};
|
||||||
viewport.x = static_cast<float>(mViewPortInfo.xOffset);
|
viewport.x = static_cast<float>(mViewPortInfo.xOffset);
|
||||||
@ -141,22 +141,22 @@ namespace vulkanapi {
|
|||||||
vkCmdSetScissor(ptr, 0, 1, &scissor);
|
vkCmdSetScissor(ptr, 0, 1, &scissor);
|
||||||
|
|
||||||
vkCmdBindVertexBuffers(ptr, 0, 1, vertexBuffers, offsets);
|
vkCmdBindVertexBuffers(ptr, 0, 1, vertexBuffers, offsets);
|
||||||
vkCmdBindIndexBuffer(ptr, vulkanVAO->indexBuffer, 0, VK_INDEX_TYPE_UINT32);
|
vkCmdBindIndexBuffer(ptr, vulkanVAO.indexBuffer, 0, VK_INDEX_TYPE_UINT32);
|
||||||
vkCmdBindPipeline(ptr, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline);
|
vkCmdBindPipeline(ptr, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline);
|
||||||
vkCmdBindDescriptorSets(ptr, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipelineLayout, 0, 1, &pipeline->descriptorSet, 0, VK_NULL_HANDLE);
|
vkCmdBindDescriptorSets(ptr, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipelineLayout, 0, 1, &pipeline.descriptorSet, 0, VK_NULL_HANDLE);
|
||||||
vkCmdDrawIndexed(ptr, 3, 1, 0, 0, 0);
|
vkCmdDrawIndexed(ptr, 3, 1, 0, 0, 0);
|
||||||
context.Pass->EndPass(cmd);
|
context.Pass->EndPass(cmd);
|
||||||
});
|
});
|
||||||
Backend::RenderWorker->Flush();
|
Backend::RenderWorker->Flush();
|
||||||
}
|
}
|
||||||
void RenderVulkanAPI::LoadShader(Shader* shader)
|
void RenderVulkanAPI::LoadShader(Shader& shader)
|
||||||
{
|
{
|
||||||
vector<VkPipelineShaderStageCreateInfo> shaderStages;
|
vector<VkPipelineShaderStageCreateInfo> shaderStages;
|
||||||
std::map<VkShaderStageFlagBits, VkShaderModule> shaderModules;
|
std::map<VkShaderStageFlagBits, VkShaderModule> shaderModules;
|
||||||
auto device = backend.GetDevice();
|
auto device = backend.GetDevice();
|
||||||
auto vertModule = shader->GetVertHandle<vkShaderProgram>()->Ptr();
|
auto vertModule = shader.GetVertHandle<vkShaderProgram>()->Ptr();
|
||||||
shaderModules.insert(make_pair(VK_SHADER_STAGE_VERTEX_BIT, vertModule));
|
shaderModules.insert(make_pair(VK_SHADER_STAGE_VERTEX_BIT, vertModule));
|
||||||
auto fragModule = shader->GetVertHandle<vkShaderProgram>()->Ptr();
|
auto fragModule = shader.GetFragHandle<vkShaderProgram>()->Ptr();
|
||||||
shaderModules.insert(make_pair(VK_SHADER_STAGE_FRAGMENT_BIT, fragModule));
|
shaderModules.insert(make_pair(VK_SHADER_STAGE_FRAGMENT_BIT, fragModule));
|
||||||
for (auto& shaderModule : shaderModules)
|
for (auto& shaderModule : shaderModules)
|
||||||
{
|
{
|
||||||
@ -167,7 +167,7 @@ namespace vulkanapi {
|
|||||||
shaderStageInfo.pName = "main";
|
shaderStageInfo.pName = "main";
|
||||||
shaderStages.push_back(shaderStageInfo);
|
shaderStages.push_back(shaderStageInfo);
|
||||||
}
|
}
|
||||||
auto it = refl::UClass::MetaTable.find(shader->GetVertexName());
|
auto it = refl::UClass::MetaTable.find(shader.Name());
|
||||||
auto meta = it->second->vtable.GetMeta("vkMeta");
|
auto meta = it->second->vtable.GetMeta("vkMeta");
|
||||||
// 设置顶点输入格式
|
// 设置顶点输入格式
|
||||||
VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
|
VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
|
||||||
@ -277,7 +277,7 @@ namespace vulkanapi {
|
|||||||
depthStencilInfo.front = {};
|
depthStencilInfo.front = {};
|
||||||
depthStencilInfo.back = {};
|
depthStencilInfo.back = {};
|
||||||
|
|
||||||
auto descriptorSetLayout = VulkanContext::CreateDescriptorSetLayout(shader->GetInfo());
|
auto descriptorSetLayout = VulkanContext::CreateDescriptorSetLayout(shader.GetInfo());
|
||||||
auto pipelineLayout = VulkanContext::CreatePipelineLayout({ descriptorSetLayout }, {});
|
auto pipelineLayout = VulkanContext::CreatePipelineLayout({ descriptorSetLayout }, {});
|
||||||
|
|
||||||
VkGraphicsPipelineCreateInfo pipelineInfo{};
|
VkGraphicsPipelineCreateInfo pipelineInfo{};
|
||||||
@ -302,48 +302,16 @@ namespace vulkanapi {
|
|||||||
if (vkCreateGraphicsPipelines(device.Ptr(), VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeLine) != VK_SUCCESS)
|
if (vkCreateGraphicsPipelines(device.Ptr(), VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeLine) != VK_SUCCESS)
|
||||||
throw std::runtime_error("failed to create graphics pipeline!");
|
throw std::runtime_error("failed to create graphics pipeline!");
|
||||||
|
|
||||||
//for (auto& shaderModule : shaderModules)
|
for (auto& shaderModule : shaderModules)
|
||||||
//vkDestroyShaderModule(device.Ptr(), shaderModule.second, nullptr);
|
vkDestroyShaderModule(device.Ptr(), shaderModule.second, nullptr);
|
||||||
|
|
||||||
auto vulkan_pipeline = GetNextPipeline(shader->GetID());
|
VulkanPipeline& vulkan_pipeline = PipelineTable[shader.GetGuid()];
|
||||||
vulkan_pipeline->name = "";//shader->GetName();
|
vulkan_pipeline.name = shader.Name();
|
||||||
vulkan_pipeline->pipeline = pipeLine;
|
vulkan_pipeline.pipeline = pipeLine;
|
||||||
vulkan_pipeline->inUse = true;
|
vulkan_pipeline.inUse = true;
|
||||||
vulkan_pipeline->pipelineLayout = pipelineLayout;
|
vulkan_pipeline.pipelineLayout = pipelineLayout;
|
||||||
vulkan_pipeline->descriptorSetLayout = descriptorSetLayout;
|
vulkan_pipeline.descriptorSetLayout = descriptorSetLayout;
|
||||||
vulkan_pipeline->descriptorSet = backend.GetPool().Allocate(descriptorSetLayout);
|
vulkan_pipeline.descriptorSet = backend.GetPool().Allocate(descriptorSetLayout);
|
||||||
}
|
}
|
||||||
VulkanVAO* RenderVulkanAPI::GetNextVAO(uint32_t& index)
|
|
||||||
{
|
|
||||||
uint32_t length = (uint32_t)VAOList.size();
|
|
||||||
for (uint32_t i = 0; i < length; i++)
|
|
||||||
{
|
|
||||||
if (!VAOList[i]->inUse) {
|
|
||||||
index = i;
|
|
||||||
return VAOList[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
index = length;
|
|
||||||
auto vao = new VulkanVAO();
|
|
||||||
VAOList.push_back(vao);
|
|
||||||
return vao;
|
|
||||||
}
|
|
||||||
|
|
||||||
VulkanPipeline* RenderVulkanAPI::GetNextPipeline(uint32_t& index)
|
|
||||||
{
|
|
||||||
uint32_t length = (uint32_t)PiPelineList.size();
|
|
||||||
for (uint32_t i = 0; i < length; i++)
|
|
||||||
{
|
|
||||||
if (!PiPelineList[i]->inUse) {
|
|
||||||
index = i;
|
|
||||||
return PiPelineList[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
index = length;
|
|
||||||
auto info = new VulkanPipeline();
|
|
||||||
PiPelineList.push_back(info);
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,8 +4,10 @@
|
|||||||
#include "render/renderapi.h"
|
#include "render/renderapi.h"
|
||||||
#include "vulkan_struct.h"
|
#include "vulkan_struct.h"
|
||||||
#include "vulkan_context.h"
|
#include "vulkan_context.h"
|
||||||
|
#include "asset/res/guid.h"
|
||||||
namespace vulkanapi
|
namespace vulkanapi
|
||||||
{
|
{
|
||||||
|
using engineapi::Guid;
|
||||||
class RenderTarget;
|
class RenderTarget;
|
||||||
class Swapchain;
|
class Swapchain;
|
||||||
class RenderVulkanAPI : public RenderAPI
|
class RenderVulkanAPI : public RenderAPI
|
||||||
@ -15,10 +17,9 @@ namespace vulkanapi
|
|||||||
VulkanContext context;
|
VulkanContext context;
|
||||||
Swapchain* swapchain{nullptr};
|
Swapchain* swapchain{nullptr};
|
||||||
vector<RenderTarget*> TargetList;
|
vector<RenderTarget*> TargetList;
|
||||||
vector<VulkanVAO*> VAOList;
|
|
||||||
vector<RenderPass*> PassList;
|
vector<RenderPass*> PassList;
|
||||||
vector<VulkanPipeline*> PiPelineList;
|
hash_table<Guid, VulkanPipeline> PipelineTable;
|
||||||
hash_table<Guid, void*> ShaderInfoList;
|
hash_table<Guid, VulkanVAO> VAOTable;
|
||||||
public:
|
public:
|
||||||
RenderVulkanAPI();
|
RenderVulkanAPI();
|
||||||
~RenderVulkanAPI()override;
|
~RenderVulkanAPI()override;
|
||||||
@ -36,13 +37,10 @@ namespace vulkanapi
|
|||||||
|
|
||||||
void BeginFrame()override;
|
void BeginFrame()override;
|
||||||
void EndFrame()override;
|
void EndFrame()override;
|
||||||
void SetStaticMesh(Mesh* mesh)override;
|
void SetStaticMesh(Mesh& mesh)override;
|
||||||
void DrawStaticMesh(Mesh* mesh)override;
|
void DrawStaticMesh(Mesh& mesh)override;
|
||||||
|
|
||||||
void LoadShader(Shader* shader)override;
|
void LoadShader(Shader& shader)override;
|
||||||
public:
|
|
||||||
VulkanVAO* GetNextVAO(uint32_t& index);
|
|
||||||
VulkanPipeline* GetNextPipeline(uint32_t& index);
|
|
||||||
public:
|
public:
|
||||||
static RenderVulkanAPI* GetSingletonPtr() {
|
static RenderVulkanAPI* GetSingletonPtr() {
|
||||||
return (RenderVulkanAPI*)RenderAPI::GetSingletonPtr();
|
return (RenderVulkanAPI*)RenderAPI::GetSingletonPtr();
|
||||||
|
|||||||
@ -7,9 +7,8 @@ target("zengine")
|
|||||||
set_rundir(".")
|
set_rundir(".")
|
||||||
add_rules("volk.env", "glsl.env")
|
add_rules("volk.env", "glsl.env")
|
||||||
add_rules("c++.codegen",{
|
add_rules("c++.codegen",{
|
||||||
files = {"src/engine/render/meta/*.h",
|
files = {"src/engine/render/asset/*.h",
|
||||||
"src/engine/asset/res/guid.h",
|
"src/engine/asset/res/*.h"}
|
||||||
"src/engine/asset/res/meta_bundle.h",}
|
|
||||||
})
|
})
|
||||||
add_deps("zlog","zlib")
|
add_deps("zlog","zlib")
|
||||||
add_defines("VULKAN_API")
|
add_defines("VULKAN_API")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user