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 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{
|
||||
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) {
|
||||
system->Init();
|
||||
}
|
||||
for (auto system : SystemList) {
|
||||
system->LateInit();
|
||||
}
|
||||
}
|
||||
void App::Shutdown()
|
||||
{
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
#include "assert.h"
|
||||
#include "asset_loader.h"
|
||||
#include "render/asset/shader.h"
|
||||
#include "render/asset/model.h"
|
||||
#include "resource_manager.h"
|
||||
#include "object/loader/assimp_loader.h"
|
||||
#include "yaml/yaml.h"
|
||||
namespace engineapi {
|
||||
MetaBundle ResourceManager::GetVisitMeta(const ResourceBundle& bundle)
|
||||
{
|
||||
@ -9,4 +13,10 @@ namespace engineapi {
|
||||
std::visit([&](auto& handle) { new_meta.Add(handle); }, elem);
|
||||
return new_meta;
|
||||
}
|
||||
void Asset::__Init__()
|
||||
{
|
||||
YAML::TextArchive::Register<Guid>();
|
||||
AssimpLoader::Init();
|
||||
AssetLoader::Init();
|
||||
}
|
||||
}
|
||||
@ -1,11 +1,22 @@
|
||||
#pragma once
|
||||
#include "render/asset_struct.h"
|
||||
#include "res/resource_handle.h"
|
||||
#include "res/package_path.h"
|
||||
#include "resource_manager.h"
|
||||
namespace engineapi {
|
||||
class Asset : public Resource<Asset> {
|
||||
private:
|
||||
static void __Init__();
|
||||
friend class FileManager;
|
||||
public:
|
||||
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();
|
||||
Mount("engine", path.string());
|
||||
Asset::__Init__();
|
||||
}
|
||||
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 pre_path = FindMountPath(name);
|
||||
@ -40,7 +41,7 @@ namespace engineapi {
|
||||
file.exceptions(ifstream::failbit | ifstream::badbit);
|
||||
try
|
||||
{
|
||||
string path = real_path(pack_path);
|
||||
string path = RealPath(pack_path);
|
||||
file.open(path);
|
||||
stringstream stream;
|
||||
stream << file.rdbuf();
|
||||
@ -54,7 +55,7 @@ namespace engineapi {
|
||||
}
|
||||
result<vector<char>,FileFlag> FileManager::LoadBinaryFile(const PackagePath& pack_path)
|
||||
{
|
||||
string path = real_path(pack_path);
|
||||
string path = RealPath(pack_path);
|
||||
// ate:在文件末尾开始读取,从文件末尾开始读取的优点是我们可以使用读取位置来确定文件的大小并分配缓冲区
|
||||
ifstream file(path, std::ios::ate | std::ios::binary);
|
||||
if (!file.is_open()) {
|
||||
@ -74,7 +75,7 @@ namespace engineapi {
|
||||
}
|
||||
result<json, FileFlag> FileManager::LoadJsonFile(const PackagePath& pack_path)
|
||||
{
|
||||
string path = real_path(pack_path);
|
||||
string path = RealPath(pack_path);
|
||||
std::ifstream f(path);
|
||||
if (!f.is_open())
|
||||
{
|
||||
@ -96,7 +97,7 @@ namespace engineapi {
|
||||
}
|
||||
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);
|
||||
of.write(value.data(), value.size());
|
||||
}
|
||||
|
||||
@ -63,9 +63,10 @@ namespace engineapi
|
||||
private:
|
||||
inline static table<NameID, std::pair<string, string>> MountMap;
|
||||
inline static table<NameID, FileControlBlock> FileMap;
|
||||
//外界不应该使用绝对路径
|
||||
static string real_path(const PackagePath& pack_path);
|
||||
public:
|
||||
//外界不应该使用绝对路径
|
||||
static string RealPath(const PackagePath& pack_path);
|
||||
|
||||
static FileFlag LoadErrorFlag(const PackagePath& pack_path);
|
||||
|
||||
static result<string, FileFlag> LoadTextFile(const PackagePath& pack_path);
|
||||
|
||||
@ -13,9 +13,9 @@ namespace engineapi
|
||||
UPROPERTY({})
|
||||
string t_hash{};
|
||||
UPROPERTY({})
|
||||
string metadata;
|
||||
string t_meta;
|
||||
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;
|
||||
@ -29,6 +29,8 @@ namespace engineapi
|
||||
template<typename T>
|
||||
const SerializedMeta* FetchMeta() const;
|
||||
template<typename T>
|
||||
const SerializedMeta* FetchMeta(const string_view& asset_name) const;
|
||||
template<typename T>
|
||||
void Add(RscHandle<T>);
|
||||
bool operator==(const MetaBundle& other)const;
|
||||
bool operator!=(const MetaBundle& other)const;
|
||||
|
||||
@ -4,10 +4,21 @@ namespace engineapi
|
||||
template<typename T>
|
||||
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)
|
||||
{
|
||||
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 nullptr;
|
||||
@ -17,7 +28,7 @@ namespace engineapi
|
||||
{
|
||||
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) };
|
||||
}
|
||||
string PackagePath::RealPath() const
|
||||
{
|
||||
return FileManager::RealPath(*this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -23,6 +23,7 @@ namespace engineapi
|
||||
PackagePath() {};
|
||||
PackagePath(const char* path) : path(path) {}
|
||||
PackagePath(const string_view& path) : path(path) {}
|
||||
PackagePath(const string& path) : path(path) {}
|
||||
PackagePath(const string&& path) : path(path) {}
|
||||
size_t size() const{
|
||||
return path.size();
|
||||
@ -54,5 +55,6 @@ namespace engineapi
|
||||
}
|
||||
PackagePath ToSuffixPath(const string_view& suffix)const;
|
||||
PackagePath SafePath()const;
|
||||
string RealPath()const;
|
||||
};
|
||||
}
|
||||
@ -3,7 +3,6 @@
|
||||
namespace engineapi
|
||||
{
|
||||
struct GenericResourceHandle;
|
||||
|
||||
struct ResourceBundle
|
||||
{
|
||||
ResourceBundle() = default;
|
||||
@ -13,6 +12,7 @@ namespace engineapi
|
||||
template<typename T> void Add(RscHandle<T> handle);
|
||||
template<typename T> RscHandle<T> Get() const; // get a resource from the bundle
|
||||
span<const GenericResourceHandle> GetAll() const; // gets absolutely all resources
|
||||
template<typename T> span<const GenericResourceHandle> GetAll() const; // get all resources of one type
|
||||
private:
|
||||
struct sub_array { short index = 0, count = 0; };
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
#pragma once
|
||||
#include "resource_bundle.h"
|
||||
namespace engineapi
|
||||
{
|
||||
template<typename Res>
|
||||
@ -31,9 +30,13 @@ namespace engineapi
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline RscHandle<T> engineapi::ResourceBundle::Get() const
|
||||
inline RscHandle<T> ResourceBundle::Get() const
|
||||
{
|
||||
auto& subarray = subarrays[ResourceID<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
|
||||
#include "type.h"
|
||||
namespace engineapi {
|
||||
class Guid;
|
||||
template<typename Res>
|
||||
struct RscHandle;
|
||||
template<typename Res>
|
||||
@ -8,7 +9,7 @@ namespace engineapi {
|
||||
{
|
||||
public:
|
||||
using BaseResource = Res;
|
||||
|
||||
Guid GetGuid()const;
|
||||
RscHandle<Res> GetHandle() const { return mHandle; }
|
||||
Resource() = default;
|
||||
|
||||
@ -21,6 +22,7 @@ namespace engineapi {
|
||||
};
|
||||
using Resources = std::tuple<
|
||||
class ShaderProgram
|
||||
, class Model
|
||||
, class Asset
|
||||
>;
|
||||
template<typename Resource>
|
||||
|
||||
@ -4,18 +4,21 @@
|
||||
|
||||
namespace engineapi
|
||||
{
|
||||
struct RscHandleBase {
|
||||
UPROPERTY({})
|
||||
Guid guid;
|
||||
void* res;
|
||||
};
|
||||
template<typename Res>
|
||||
struct RscHandle
|
||||
struct RscHandle : public RscHandleBase
|
||||
{
|
||||
Guid guid{};
|
||||
void* res{};
|
||||
constexpr size_t RscID()const { return ResourceID<Res>; }
|
||||
constexpr RscHandle() noexcept = default;
|
||||
template<typename T>
|
||||
constexpr RscHandle(const RscHandle<T>& other) noexcept : guid{ other.guid }, res(other.res) {};
|
||||
constexpr RscHandle(const Guid& guid, Res* res) noexcept : guid{ guid }, res(res) { ((Resource<Res>*)res)->mHandle = *this; }
|
||||
constexpr RscHandle(const RscHandle<T>& other) noexcept : RscHandleBase(other.guid, other.res) {};
|
||||
constexpr RscHandle(const Guid& guid, Res* res) noexcept : RscHandleBase(guid, res) { ((Resource<Res>*)res)->mHandle = *this; }
|
||||
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; }
|
||||
operator bool() { if (!res && guid) Init(); return res; }
|
||||
@ -23,34 +26,6 @@ namespace engineapi
|
||||
Res& operator*()const { return *(Res*)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
|
||||
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);
|
||||
}
|
||||
};
|
||||
}
|
||||
#include "resource_handle.inl"
|
||||
#include "resource_handle_gen.inl"
|
||||
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();
|
||||
LoadFileFlag();
|
||||
}
|
||||
void ResourceManager::LateInit()
|
||||
{
|
||||
SaveFileFlag();
|
||||
SaveDirtyFiles();
|
||||
}
|
||||
void ResourceManager::Shutdown()
|
||||
{
|
||||
constexpr static auto release_tables = detail::ResourceHelper::ReleaseTableResources();
|
||||
@ -30,23 +35,26 @@ namespace engineapi {
|
||||
return it->second.bundle;
|
||||
}
|
||||
}
|
||||
auto& res = mFileTable[path.path];
|
||||
Name ext = path.GetExtension();
|
||||
IFileLoader* loader = GetLoader(ext);
|
||||
MetaBundle meta = GetMeta(path);
|
||||
ResourceBundle bundle = loader->LoadFile(path, meta);
|
||||
MetaBundle new_meta = GetVisitMeta(bundle);
|
||||
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()) {
|
||||
std::visit([&](auto& handle) {
|
||||
using T = std::decay_t<decltype(*handle)>;
|
||||
GetControlBlock<T>(handle)->file = &res;
|
||||
}, elem);
|
||||
}
|
||||
if (is_dirty_meta) {
|
||||
if (is_dirty_meta || res.is_dirty) {
|
||||
mDirtyBlocks.push_back(&res);
|
||||
}
|
||||
res.path = path.SafePath();
|
||||
res.bundle = bundle;
|
||||
res.is_meta_dirty = is_dirty_meta;
|
||||
res.bundle = bundle;
|
||||
return res.bundle;
|
||||
}
|
||||
|
||||
@ -74,7 +82,7 @@ namespace engineapi {
|
||||
}
|
||||
else {
|
||||
string text = YAML::Text_Serialize(bundle);
|
||||
FileManager::SaveTextFile(path, text);
|
||||
FileManager::SaveTextFile(path + ".meta", text);
|
||||
}
|
||||
}
|
||||
void ResourceManager::SaveDirtyFiles()
|
||||
|
||||
@ -37,6 +37,7 @@ namespace engineapi {
|
||||
vector<FileControlBlock*> mDirtyBlocks;
|
||||
public:
|
||||
void Init() override;
|
||||
void LateInit()override;
|
||||
void Shutdown() override;
|
||||
|
||||
public:
|
||||
@ -47,8 +48,9 @@ namespace engineapi {
|
||||
auto& GetTable() {
|
||||
return *reinterpret_cast<ResourceStorage<Res>*> (mResourceTable[ResourceID<Res>].get());
|
||||
}
|
||||
template<typename Res>
|
||||
template<typename Res>
|
||||
ResourceControlBlock<Res>* GetControlBlock(RscHandle<Res> handle);
|
||||
FileControlBlock& GetFileBlock(PackagePath path);
|
||||
|
||||
template<typename Res, typename ... Args>
|
||||
[[nodiscard]] RscHandle<Res> LoaderEmplaceResource(Args&& ... args) {
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
#include "resource_manager.h"
|
||||
#pragma once
|
||||
namespace engineapi {
|
||||
class IFileLoader
|
||||
@ -97,6 +96,9 @@ namespace engineapi {
|
||||
auto& table = GetTable<Res>();
|
||||
return &table[handle.guid];
|
||||
}
|
||||
inline ResourceManager::FileControlBlock& ResourceManager::GetFileBlock(PackagePath path) {
|
||||
return mFileTable[NameID(path.path)];
|
||||
}
|
||||
template<typename Res>
|
||||
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 "asset/resource_manager.h"
|
||||
#include "data/property/actor_property.h"
|
||||
namespace engineapi {
|
||||
ActorMesh::ActorMesh(Model& model, ActorProperty& property)
|
||||
@ -9,9 +10,8 @@ namespace engineapi {
|
||||
}
|
||||
ActorMesh* ActorMesh::New(ActorProperty& property)
|
||||
{
|
||||
//Model* model = AssetManager::GetSingletonPtr()->LoadAsset<Model>(property.path, property.flags);
|
||||
//return new ActorMesh(*model, property);
|
||||
return nullptr;
|
||||
auto res = ResourceManager::GetSingleton().Load<Model>(property.path);
|
||||
return new ActorMesh(*res, property);
|
||||
}
|
||||
ActorMesh* ActorMesh::New(uint32_t id)
|
||||
{
|
||||
|
||||
@ -8,6 +8,6 @@ namespace engineapi {
|
||||
}
|
||||
void StaticMesh::LoadMesh()
|
||||
{
|
||||
|
||||
mPtr.BeginLoad();
|
||||
}
|
||||
}
|
||||
@ -12,18 +12,19 @@ namespace engineapi {
|
||||
mCamera = new Camera();
|
||||
int flags = 1;
|
||||
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->mFrag = ResourceManager::GetSingleton().Load<ShaderProgram>("/engine/assets/shader/simple.frag");
|
||||
RenderAPI::GetSingleton().LoadShader(&*shader);
|
||||
Material* material = new Material("/engine/assets/shader/simple.shader", flags);
|
||||
RenderAPI::GetSingleton().LoadShader(*shader);
|
||||
//Material* material = new Material("/engine/assets/shader/simple.shader", flags);
|
||||
{
|
||||
ActorProperty property;
|
||||
property.id = 1;
|
||||
property.flags = flags;
|
||||
property.path = "/engine/assets/models/cube.obj";
|
||||
actor1 = ActorMesh::New(property);
|
||||
actor1->Ptr().SetMaterial(material);
|
||||
actor1->LoadMesh();
|
||||
//actor1->Ptr().SetMaterial(material);
|
||||
}
|
||||
{
|
||||
ActorProperty property;
|
||||
@ -31,7 +32,7 @@ namespace engineapi {
|
||||
property.flags = flags;
|
||||
property.path = "/engine/assets/models/box.ply";
|
||||
actor2 = ActorMesh::New(property);
|
||||
actor2->Ptr().SetMaterial(material);
|
||||
//actor2->Ptr().SetMaterial(material);
|
||||
}
|
||||
}
|
||||
Scene::~Scene()
|
||||
@ -43,11 +44,10 @@ namespace engineapi {
|
||||
void Scene::Render()
|
||||
{
|
||||
RenderAPI::GetSingletonPtr()->Render(*mCamera);
|
||||
auto meshs = actor1->Ptr().GetMeshs();
|
||||
for (auto it : meshs) {
|
||||
RenderAPI::GetSingletonPtr()->DrawStaticMesh(it);
|
||||
}
|
||||
//RenderAPI::GetSingletonPtr()->DrawStaticMesh(actor2);
|
||||
//auto meshs = actor1->Ptr().GetMeshs();
|
||||
//for (auto it : meshs) {
|
||||
//RenderAPI::GetSingletonPtr()->DrawStaticMesh(*it);
|
||||
//}
|
||||
}
|
||||
void Scene::AddGameObject(GameObject* gameObject)
|
||||
{
|
||||
|
||||
@ -2,9 +2,9 @@
|
||||
#include "shader.h"
|
||||
#include "../renderapi.h"
|
||||
namespace engineapi {
|
||||
Material::Material(string_view name, uint32_t flags)
|
||||
Material::Material() : Asset(&refl::TypeInfo<Material>::StaticClass)
|
||||
{
|
||||
//mShader = new Shader(name, flags);
|
||||
|
||||
}
|
||||
Material::~Material()
|
||||
{
|
||||
|
||||
@ -1,15 +1,18 @@
|
||||
#pragma once
|
||||
#include "asset/asset.h"
|
||||
|
||||
#include "shader.h"
|
||||
namespace engineapi {
|
||||
class Shader;
|
||||
class Material : public Asset {
|
||||
protected:
|
||||
uint32_t mId{0};
|
||||
Shader* mShader;
|
||||
REFL_FRIEND(Material)
|
||||
UPROPERTY()
|
||||
RscHandle<Shader> mShader;
|
||||
public:
|
||||
Material(string_view name, uint32_t flags);
|
||||
Material();
|
||||
~Material();
|
||||
|
||||
RscHandle<Shader> GetShader() {
|
||||
return mShader;
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
#include "material_gen.inl"
|
||||
@ -3,6 +3,6 @@
|
||||
namespace engineapi {
|
||||
void Mesh::BeginLoad()
|
||||
{
|
||||
RenderAPI::GetSingletonPtr()->SetStaticMesh(this);
|
||||
RenderAPI::GetSingletonPtr()->SetStaticMesh(*this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,30 +1,28 @@
|
||||
#pragma once
|
||||
#include "material.h"
|
||||
#include "vertex.h"
|
||||
#include "refl/std/parray.h"
|
||||
#include "asset/asset.h"
|
||||
#include "../meta/vertex.h"
|
||||
namespace engineapi {
|
||||
using refl::parray;
|
||||
class Texture;
|
||||
class Material;
|
||||
class Mesh : public Asset {
|
||||
class Mesh : public Asset{
|
||||
protected:
|
||||
uint32_t VAO = 0;
|
||||
REFL_FRIEND(Mesh)
|
||||
UPROPERTY()
|
||||
RscHandle<Material> mMaterial;
|
||||
parray<Vertex> mVertices;
|
||||
vector<uint32_t> mIndices;
|
||||
public:
|
||||
template<typename T>
|
||||
requires std::is_base_of_v<Vertex, T>
|
||||
Mesh(vector<T>& vertices, vector<uint32_t>& indices)
|
||||
: mVertices(vertices)
|
||||
, mIndices(indices)
|
||||
{
|
||||
BeginLoad();
|
||||
}
|
||||
Mesh(vector<T>& vertices, vector<uint32_t>& indices);
|
||||
void BeginLoad();
|
||||
|
||||
public:
|
||||
uint32_t& GetVAO() {
|
||||
return VAO;
|
||||
Guid GetShaderGuid() {
|
||||
return mMaterial->GetShader().guid;
|
||||
}
|
||||
RscHandle<Material> GetMaterial() {
|
||||
return mMaterial;
|
||||
}
|
||||
parray<Vertex>& GetVertices() {
|
||||
return mVertices;
|
||||
@ -33,4 +31,14 @@ namespace engineapi {
|
||||
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 "zlog.h"
|
||||
#include "assimp/Importer.hpp"
|
||||
#include "assimp/scene.h"
|
||||
#include "assimp/postprocess.h"
|
||||
namespace engineapi {
|
||||
void Model::BeginLoad()
|
||||
{
|
||||
string mName = "";
|
||||
// 用ASSIMP加载模型文件
|
||||
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;
|
||||
for (auto mesh : mMeshes) {
|
||||
mesh->BeginLoad();
|
||||
}
|
||||
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()
|
||||
{
|
||||
|
||||
@ -1,26 +1,14 @@
|
||||
#pragma once
|
||||
#include "asset/asset.h"
|
||||
#include "mesh.h"
|
||||
#include "material.h"
|
||||
class aiNode;
|
||||
class aiMesh;
|
||||
class aiScene;
|
||||
namespace engineapi {
|
||||
class Model : public Asset {
|
||||
class Model : public Resource<Model> {
|
||||
protected:
|
||||
vector<Mesh*> mMeshes;
|
||||
Material* mMaterial;
|
||||
vector<RscHandle<Mesh>> mMeshes;
|
||||
public:
|
||||
using Asset::Asset;
|
||||
void BeginLoad();
|
||||
void ProcessNode(const aiNode* pNode, const aiScene* pScene);
|
||||
Mesh* ProcessMesh(const aiMesh* mesh);
|
||||
vector<Mesh*>& GetMeshs() {
|
||||
vector<RscHandle<Mesh>>& GetMeshs() {
|
||||
return mMeshes;
|
||||
}
|
||||
void SetMaterial(Material* material) {
|
||||
mMaterial = material;
|
||||
}
|
||||
void Use();
|
||||
};
|
||||
};
|
||||
@ -1,8 +1,6 @@
|
||||
#include "shader.h"
|
||||
#include "asset/file_manager.h"
|
||||
#include "../renderapi.h"
|
||||
namespace engineapi {
|
||||
Shader::Shader()
|
||||
Shader::Shader() : Asset(&refl::TypeInfo<Shader>::StaticClass)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@ -5,10 +5,12 @@ namespace engineapi {
|
||||
class ShaderProgram : public Resource<ShaderProgram> {};
|
||||
class Shader : public Asset {
|
||||
private:
|
||||
REFL_FRIEND(Shader)
|
||||
uint32_t mId;
|
||||
ShaderInfo mInfo;
|
||||
string mVertexName;
|
||||
UPROPERTY()
|
||||
RscHandle<ShaderProgram> mVert;
|
||||
UPROPERTY()
|
||||
RscHandle<ShaderProgram> mFrag;
|
||||
friend class Scene;
|
||||
public:
|
||||
@ -20,9 +22,6 @@ namespace engineapi {
|
||||
ShaderInfo& GetInfo() {
|
||||
return mInfo;
|
||||
}
|
||||
string_view GetVertexName() {
|
||||
return mVertexName;
|
||||
}
|
||||
template<typename T = ShaderProgram>
|
||||
RscHandle<T> GetVertHandle() {
|
||||
return mVert;
|
||||
@ -32,4 +31,5 @@ namespace engineapi {
|
||||
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 {
|
||||
class Texture : public Asset {
|
||||
|
||||
Texture();
|
||||
};
|
||||
};
|
||||
@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
#include "../asset/material.h"
|
||||
#include "../asset/mesh.h"
|
||||
#include "../asset/texture.h"
|
||||
#include "../render_context.h"
|
||||
namespace engineapi {
|
||||
|
||||
@ -31,10 +31,10 @@ namespace engineapi
|
||||
virtual void BeginFrame() = 0;
|
||||
virtual void Render(Camera& camera);
|
||||
virtual void EndFrame() = 0;
|
||||
virtual void SetStaticMesh(Mesh* mesh) = 0;
|
||||
virtual void DrawStaticMesh(Mesh* mesh) = 0;
|
||||
virtual void SetStaticMesh(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;
|
||||
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#include "vulkanapi/tool/glsl_to_spirv.h"
|
||||
#include "vulkanapi/vulkanapi.h"
|
||||
#include "asset/file_manager.h"
|
||||
#include "render/meta/vertex.h"
|
||||
#include "render/asset/vertex.h"
|
||||
#include "vkmeta_vertex_gen.inl"
|
||||
#include <spirv_cross/spirv_reflect.hpp>
|
||||
using namespace engineapi;
|
||||
@ -56,7 +56,7 @@ namespace vulkanapi {
|
||||
auto spirv = GlslToSpirv::spirv(glsl, shader_enum, handle.GetFileName());
|
||||
if (spirv) {
|
||||
program->Load(*spirv);
|
||||
LoadShaderInfo(program->GetHandle().guid, *spirv);
|
||||
LoadShaderInfo(program->GetGuid(), *spirv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,13 +64,13 @@ namespace vulkanapi {
|
||||
{
|
||||
swapchain->Present(context);
|
||||
}
|
||||
void RenderVulkanAPI::SetStaticMesh(Mesh* mesh)
|
||||
void RenderVulkanAPI::SetStaticMesh(Mesh& mesh)
|
||||
{
|
||||
auto Indices = mesh->GetIndices();
|
||||
auto Vertices = mesh->GetVertices();
|
||||
auto meshBuffer = GetNextVAO(mesh->GetVAO());
|
||||
meshBuffer->indexCount = Indices.size();
|
||||
meshBuffer->vertexCount = Vertices.size();
|
||||
auto Indices = mesh.GetIndices();
|
||||
auto Vertices = mesh.GetVertices();
|
||||
VulkanVAO& meshBuffer = VAOTable[mesh.GetGuid()];
|
||||
meshBuffer.indexCount = Indices.size();
|
||||
meshBuffer.vertexCount = Vertices.size();
|
||||
|
||||
// ----------------------------------------------- Vertex Buffer -----------------------------------------------
|
||||
VkDeviceSize vertexBufferSize = Vertices.capicty();
|
||||
@ -84,7 +84,7 @@ namespace vulkanapi {
|
||||
VkBufferUsageFlags vertexFlags = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;//加入光线追踪
|
||||
VmaAllocationCreateInfo vertexVmaCreateInfo = {};
|
||||
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 -----------------------------------------------
|
||||
VkDeviceSize indexBufferSize = sizeof(uint32_t) * Indices.size();
|
||||
@ -96,11 +96,11 @@ namespace vulkanapi {
|
||||
|
||||
VmaAllocationCreateInfo indexVmaCreateInfo = {};
|
||||
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) {
|
||||
cmd.CmdCopyBuffer(vertexStagingBuffer, meshBuffer->vertexBuffer, vertexBufferSize);
|
||||
cmd.CmdCopyBuffer(indexStagingBuffer, meshBuffer->indexBuffer, indexBufferSize);
|
||||
cmd.CmdCopyBuffer(vertexStagingBuffer, meshBuffer.vertexBuffer, vertexBufferSize);
|
||||
cmd.CmdCopyBuffer(indexStagingBuffer, meshBuffer.indexBuffer, indexBufferSize);
|
||||
};
|
||||
auto callback = [=]() {
|
||||
// 销毁StagingBuffer
|
||||
@ -115,16 +115,16 @@ namespace vulkanapi {
|
||||
Backend::TransferWorker->ImmediatelyExecute(fn, callback);
|
||||
}
|
||||
}
|
||||
void RenderVulkanAPI::DrawStaticMesh(Mesh* mesh)
|
||||
void RenderVulkanAPI::DrawStaticMesh(Mesh& mesh)
|
||||
{
|
||||
auto vulkanVAO = VAOList[mesh->GetVAO()];
|
||||
auto pipeline = PiPelineList[0];
|
||||
VulkanVAO& vulkanVAO = VAOTable[mesh.GetGuid()];
|
||||
VulkanPipeline& pipeline = PipelineTable[mesh.GetShaderGuid()];
|
||||
uint32_t frame = context.frame;
|
||||
context.Pass->SetViewPort(mViewPortInfo.width, mViewPortInfo.height, mViewPortInfo.xOffset, mViewPortInfo.yOffset);
|
||||
Backend::RenderWorker->Draw([=](CommandBuffer& cmd) {
|
||||
VkCommandBuffer ptr = cmd.Ptr();
|
||||
context.Pass->BeginPass(cmd, frame);
|
||||
VkBuffer vertexBuffers[] = { vulkanVAO->vertexBuffer };
|
||||
VkBuffer vertexBuffers[] = { vulkanVAO.vertexBuffer };
|
||||
VkDeviceSize offsets[] = { 0 };
|
||||
VkViewport viewport = {};
|
||||
viewport.x = static_cast<float>(mViewPortInfo.xOffset);
|
||||
@ -141,22 +141,22 @@ namespace vulkanapi {
|
||||
vkCmdSetScissor(ptr, 0, 1, &scissor);
|
||||
|
||||
vkCmdBindVertexBuffers(ptr, 0, 1, vertexBuffers, offsets);
|
||||
vkCmdBindIndexBuffer(ptr, vulkanVAO->indexBuffer, 0, VK_INDEX_TYPE_UINT32);
|
||||
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);
|
||||
vkCmdBindIndexBuffer(ptr, vulkanVAO.indexBuffer, 0, VK_INDEX_TYPE_UINT32);
|
||||
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);
|
||||
vkCmdDrawIndexed(ptr, 3, 1, 0, 0, 0);
|
||||
context.Pass->EndPass(cmd);
|
||||
});
|
||||
Backend::RenderWorker->Flush();
|
||||
}
|
||||
void RenderVulkanAPI::LoadShader(Shader* shader)
|
||||
void RenderVulkanAPI::LoadShader(Shader& shader)
|
||||
{
|
||||
vector<VkPipelineShaderStageCreateInfo> shaderStages;
|
||||
std::map<VkShaderStageFlagBits, VkShaderModule> shaderModules;
|
||||
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));
|
||||
auto fragModule = shader->GetVertHandle<vkShaderProgram>()->Ptr();
|
||||
auto fragModule = shader.GetFragHandle<vkShaderProgram>()->Ptr();
|
||||
shaderModules.insert(make_pair(VK_SHADER_STAGE_FRAGMENT_BIT, fragModule));
|
||||
for (auto& shaderModule : shaderModules)
|
||||
{
|
||||
@ -167,7 +167,7 @@ namespace vulkanapi {
|
||||
shaderStageInfo.pName = "main";
|
||||
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");
|
||||
// 设置顶点输入格式
|
||||
VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
|
||||
@ -277,7 +277,7 @@ namespace vulkanapi {
|
||||
depthStencilInfo.front = {};
|
||||
depthStencilInfo.back = {};
|
||||
|
||||
auto descriptorSetLayout = VulkanContext::CreateDescriptorSetLayout(shader->GetInfo());
|
||||
auto descriptorSetLayout = VulkanContext::CreateDescriptorSetLayout(shader.GetInfo());
|
||||
auto pipelineLayout = VulkanContext::CreatePipelineLayout({ descriptorSetLayout }, {});
|
||||
|
||||
VkGraphicsPipelineCreateInfo pipelineInfo{};
|
||||
@ -302,48 +302,16 @@ namespace vulkanapi {
|
||||
if (vkCreateGraphicsPipelines(device.Ptr(), VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeLine) != VK_SUCCESS)
|
||||
throw std::runtime_error("failed to create graphics pipeline!");
|
||||
|
||||
//for (auto& shaderModule : shaderModules)
|
||||
//vkDestroyShaderModule(device.Ptr(), shaderModule.second, nullptr);
|
||||
for (auto& shaderModule : shaderModules)
|
||||
vkDestroyShaderModule(device.Ptr(), shaderModule.second, nullptr);
|
||||
|
||||
auto vulkan_pipeline = GetNextPipeline(shader->GetID());
|
||||
vulkan_pipeline->name = "";//shader->GetName();
|
||||
vulkan_pipeline->pipeline = pipeLine;
|
||||
vulkan_pipeline->inUse = true;
|
||||
vulkan_pipeline->pipelineLayout = pipelineLayout;
|
||||
vulkan_pipeline->descriptorSetLayout = descriptorSetLayout;
|
||||
vulkan_pipeline->descriptorSet = backend.GetPool().Allocate(descriptorSetLayout);
|
||||
VulkanPipeline& vulkan_pipeline = PipelineTable[shader.GetGuid()];
|
||||
vulkan_pipeline.name = shader.Name();
|
||||
vulkan_pipeline.pipeline = pipeLine;
|
||||
vulkan_pipeline.inUse = true;
|
||||
vulkan_pipeline.pipelineLayout = pipelineLayout;
|
||||
vulkan_pipeline.descriptorSetLayout = 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 "vulkan_struct.h"
|
||||
#include "vulkan_context.h"
|
||||
#include "asset/res/guid.h"
|
||||
namespace vulkanapi
|
||||
{
|
||||
using engineapi::Guid;
|
||||
class RenderTarget;
|
||||
class Swapchain;
|
||||
class RenderVulkanAPI : public RenderAPI
|
||||
@ -15,10 +17,9 @@ namespace vulkanapi
|
||||
VulkanContext context;
|
||||
Swapchain* swapchain{nullptr};
|
||||
vector<RenderTarget*> TargetList;
|
||||
vector<VulkanVAO*> VAOList;
|
||||
vector<RenderPass*> PassList;
|
||||
vector<VulkanPipeline*> PiPelineList;
|
||||
hash_table<Guid, void*> ShaderInfoList;
|
||||
hash_table<Guid, VulkanPipeline> PipelineTable;
|
||||
hash_table<Guid, VulkanVAO> VAOTable;
|
||||
public:
|
||||
RenderVulkanAPI();
|
||||
~RenderVulkanAPI()override;
|
||||
@ -36,13 +37,10 @@ namespace vulkanapi
|
||||
|
||||
void BeginFrame()override;
|
||||
void EndFrame()override;
|
||||
void SetStaticMesh(Mesh* mesh)override;
|
||||
void DrawStaticMesh(Mesh* mesh)override;
|
||||
void SetStaticMesh(Mesh& mesh)override;
|
||||
void DrawStaticMesh(Mesh& mesh)override;
|
||||
|
||||
void LoadShader(Shader* shader)override;
|
||||
public:
|
||||
VulkanVAO* GetNextVAO(uint32_t& index);
|
||||
VulkanPipeline* GetNextPipeline(uint32_t& index);
|
||||
void LoadShader(Shader& shader)override;
|
||||
public:
|
||||
static RenderVulkanAPI* GetSingletonPtr() {
|
||||
return (RenderVulkanAPI*)RenderAPI::GetSingletonPtr();
|
||||
|
||||
@ -7,9 +7,8 @@ target("zengine")
|
||||
set_rundir(".")
|
||||
add_rules("volk.env", "glsl.env")
|
||||
add_rules("c++.codegen",{
|
||||
files = {"src/engine/render/meta/*.h",
|
||||
"src/engine/asset/res/guid.h",
|
||||
"src/engine/asset/res/meta_bundle.h",}
|
||||
files = {"src/engine/render/asset/*.h",
|
||||
"src/engine/asset/res/*.h"}
|
||||
})
|
||||
add_deps("zlog","zlib")
|
||||
add_defines("VULKAN_API")
|
||||
|
||||
Loading…
Reference in New Issue
Block a user