axmol/extensions/Effekseer/EffekseerRendererLLGI/EffekseerRendererLLGI.Mater...

422 lines
12 KiB
C++

#include "EffekseerRendererLLGI.MaterialLoader.h"
#include "EffekseerRendererLLGI.ModelRenderer.h"
#include "EffekseerRendererLLGI.Shader.h"
#include <iostream>
#include <string>
#include "Effekseer/Material/Effekseer.CompiledMaterial.h"
#undef min
namespace EffekseerRendererLLGI
{
static const int LLGI_InstanceCount = 40;
void MaterialLoader::Deserialize(uint8_t* data, uint32_t datasize, LLGI::CompilerResult& result)
{
if (datasize < 4)
return;
uint32_t count = 0;
uint32_t offset = 0;
memcpy(&count, data + offset, sizeof(int32_t));
offset += sizeof(uint32_t);
result.Binary.resize(count);
for (uint32_t i = 0; i < count; i++)
{
uint32_t size = 0;
memcpy(&size, data + offset, sizeof(int32_t));
offset += sizeof(uint32_t);
result.Binary[i].resize(size);
memcpy(result.Binary[i].data(), data + offset, size);
offset += size;
}
}
MaterialLoader::MaterialLoader(Backend::GraphicsDevice* graphicsDevice,
::Effekseer::FileInterfaceRef fileInterface,
::Effekseer::CompiledMaterialPlatformType platformType,
::Effekseer::MaterialCompiler* materialCompiler)
: fileInterface_(fileInterface)
, platformType_(platformType)
, materialCompiler_(materialCompiler)
{
if (fileInterface == nullptr)
{
fileInterface_ = Effekseer::MakeRefPtr<Effekseer::DefaultFileInterface>();
}
graphicsDevice_ = graphicsDevice;
ES_SAFE_ADDREF(graphicsDevice_);
ES_SAFE_ADDREF(materialCompiler_);
}
MaterialLoader ::~MaterialLoader()
{
ES_SAFE_RELEASE(materialCompiler_);
ES_SAFE_RELEASE(graphicsDevice_);
}
::Effekseer::MaterialRef MaterialLoader::Load(const char16_t* path)
{
// code file
{
auto binaryPath = std::u16string(path) + u"d";
auto reader = fileInterface_->OpenRead(binaryPath.c_str());
if (reader != nullptr)
{
size_t size = reader->GetLength();
std::vector<char> data;
data.resize(size);
reader->Read(data.data(), size);
auto material = Load(data.data(), (int32_t)size, ::Effekseer::MaterialFileType::Compiled);
if (material != nullptr)
{
return material;
}
}
}
// code file
if (materialCompiler_ != nullptr)
{
auto reader = fileInterface_->OpenRead(path);
if (reader != nullptr)
{
size_t size = reader->GetLength();
std::vector<char> data;
data.resize(size);
reader->Read(data.data(), size);
auto material = Load(data.data(), (int32_t)size, ::Effekseer::MaterialFileType::Code);
return material;
}
}
return nullptr;
}
::Effekseer::MaterialRef MaterialLoader::LoadAcutually(::Effekseer::MaterialFile& materialFile, ::Effekseer::CompiledMaterialBinary* binary)
{
if (binary == nullptr)
{
return nullptr;
}
auto material = ::Effekseer::MakeRefPtr<::Effekseer::Material>();
material->IsSimpleVertex = materialFile.GetIsSimpleVertex();
material->IsRefractionRequired = materialFile.GetHasRefraction();
std::array<Effekseer::MaterialShaderType, 2> shaderTypes;
std::array<Effekseer::MaterialShaderType, 2> shaderTypesModel;
shaderTypes[0] = Effekseer::MaterialShaderType::Standard;
shaderTypes[1] = Effekseer::MaterialShaderType::Refraction;
shaderTypesModel[0] = Effekseer::MaterialShaderType::Model;
shaderTypesModel[1] = Effekseer::MaterialShaderType::RefractionModel;
int32_t shaderTypeCount = 1;
if (materialFile.GetHasRefraction())
{
shaderTypeCount = 2;
}
for (int32_t st = 0; st < shaderTypeCount; st++)
{
Shader* shader = nullptr;
auto parameterGenerator = EffekseerRenderer::MaterialShaderParameterGenerator(materialFile, false, st, LLGI_InstanceCount);
if (material->IsSimpleVertex)
{
LLGI::CompilerResult resultVS;
LLGI::CompilerResult resultPS;
Deserialize((uint8_t*)binary->GetVertexShaderData(shaderTypes[st]), binary->GetVertexShaderSize(shaderTypes[st]), resultVS);
Deserialize((uint8_t*)binary->GetPixelShaderData(shaderTypes[st]), binary->GetPixelShaderSize(shaderTypes[st]), resultPS);
std::array<LLGI::DataStructure, 4> dataVS;
std::array<LLGI::DataStructure, 4> dataPS;
for (size_t i = 0; i < resultVS.Binary.size(); i++)
{
dataVS[i].Data = resultVS.Binary[i].data();
dataVS[i].Size = static_cast<int32_t>(resultVS.Binary[i].size());
}
for (size_t i = 0; i < resultPS.Binary.size(); i++)
{
dataPS[i].Data = resultPS.Binary[i].data();
dataPS[i].Size = static_cast<int32_t>(resultPS.Binary[i].size());
}
// Pos(3) Color(1) UV(2)
std::vector<VertexLayout> layouts;
layouts.push_back(VertexLayout{LLGI::VertexLayoutFormat::R32G32B32_FLOAT, "POSITION", 0});
layouts.push_back(VertexLayout{LLGI::VertexLayoutFormat::R8G8B8A8_UNORM, "NORMAL", 0});
layouts.push_back(VertexLayout{LLGI::VertexLayoutFormat::R32G32_FLOAT, "TEXCOORD", 0});
shader = Shader::Create(graphicsDevice_,
dataVS.data(),
(int32_t)resultVS.Binary.size(),
dataPS.data(),
(int32_t)resultPS.Binary.size(),
"MaterialStandardRenderer",
layouts,
true);
}
else
{
LLGI::CompilerResult resultVS;
LLGI::CompilerResult resultPS;
Deserialize((uint8_t*)binary->GetVertexShaderData(shaderTypes[st]), binary->GetVertexShaderSize(shaderTypes[st]), resultVS);
Deserialize((uint8_t*)binary->GetPixelShaderData(shaderTypes[st]), binary->GetPixelShaderSize(shaderTypes[st]), resultPS);
std::array<LLGI::DataStructure, 4> dataVS;
std::array<LLGI::DataStructure, 4> dataPS;
for (size_t i = 0; i < resultVS.Binary.size(); i++)
{
dataVS[i].Data = resultVS.Binary[i].data();
dataVS[i].Size = static_cast<int32_t>(resultVS.Binary[i].size());
}
for (size_t i = 0; i < resultPS.Binary.size(); i++)
{
dataPS[i].Data = resultPS.Binary[i].data();
dataPS[i].Size = static_cast<int32_t>(resultPS.Binary[i].size());
}
// Pos(3) Color(1) Normal(1) Tangent(1) UV(2) UV(2)
std::vector<VertexLayout> layouts;
layouts.push_back(VertexLayout{LLGI::VertexLayoutFormat::R32G32B32_FLOAT, "POSITION", 0});
layouts.push_back(VertexLayout{LLGI::VertexLayoutFormat::R8G8B8A8_UNORM, "NORMAL", 0});
layouts.push_back(VertexLayout{LLGI::VertexLayoutFormat::R8G8B8A8_UNORM, "NORMAL", 1});
layouts.push_back(VertexLayout{LLGI::VertexLayoutFormat::R8G8B8A8_UNORM, "NORMAL", 2});
layouts.push_back(VertexLayout{LLGI::VertexLayoutFormat::R32G32_FLOAT, "TEXCOORD", 0});
layouts.push_back(VertexLayout{LLGI::VertexLayoutFormat::R32G32_FLOAT, "TEXCOORD", 1});
int32_t offset = 40;
int count = 6;
int index = 2;
auto getFormat = [](int32_t i) -> LLGI::VertexLayoutFormat {
if (i == 2)
return LLGI::VertexLayoutFormat::R32G32_FLOAT;
if (i == 3)
return LLGI::VertexLayoutFormat::R32G32B32_FLOAT;
if (i == 4)
return LLGI::VertexLayoutFormat::R32G32B32A32_FLOAT;
assert(false);
return LLGI::VertexLayoutFormat::R32_FLOAT;
};
if (materialFile.GetCustomData1Count() > 0)
{
layouts.push_back(VertexLayout{getFormat(materialFile.GetCustomData1Count()), "TEXCOORD", index});
index++;
count++;
offset += sizeof(float) * materialFile.GetCustomData1Count();
}
if (materialFile.GetCustomData2Count() > 0)
{
layouts.push_back(VertexLayout{getFormat(materialFile.GetCustomData2Count()), "TEXCOORD", index});
index++;
count++;
offset += sizeof(float) * materialFile.GetCustomData2Count();
}
shader = Shader::Create(graphicsDevice_,
dataVS.data(),
(int32_t)resultVS.Binary.size(),
dataPS.data(),
(int32_t)resultPS.Binary.size(),
"MaterialStandardRenderer",
layouts,
true);
}
if (shader == nullptr)
return nullptr;
auto vertexUniformSize = parameterGenerator.VertexShaderUniformBufferSize;
auto pixelUniformSize = parameterGenerator.PixelShaderUniformBufferSize;
shader->SetVertexConstantBufferSize(vertexUniformSize);
shader->SetPixelConstantBufferSize(pixelUniformSize);
material->TextureCount = materialFile.GetTextureCount();
material->UniformCount = materialFile.GetUniformCount();
if (st == 0)
{
material->UserPtr = shader;
}
else
{
material->RefractionUserPtr = shader;
}
}
for (int32_t st = 0; st < shaderTypeCount; st++)
{
LLGI::CompilerResult resultVS;
LLGI::CompilerResult resultPS;
Deserialize(
(uint8_t*)binary->GetVertexShaderData(shaderTypesModel[st]), binary->GetVertexShaderSize(shaderTypesModel[st]), resultVS);
Deserialize((uint8_t*)binary->GetPixelShaderData(shaderTypesModel[st]), binary->GetPixelShaderSize(shaderTypesModel[st]), resultPS);
std::array<LLGI::DataStructure, 4> dataVS;
std::array<LLGI::DataStructure, 4> dataPS;
for (size_t i = 0; i < resultVS.Binary.size(); i++)
{
dataVS[i].Data = resultVS.Binary[i].data();
dataVS[i].Size = static_cast<int32_t>(resultVS.Binary[i].size());
}
for (size_t i = 0; i < resultPS.Binary.size(); i++)
{
dataPS[i].Data = resultPS.Binary[i].data();
dataPS[i].Size = static_cast<int32_t>(resultPS.Binary[i].size());
}
auto parameterGenerator = EffekseerRenderer::MaterialShaderParameterGenerator(materialFile, true, st, LLGI_InstanceCount);
std::vector<VertexLayout> layouts;
layouts.push_back(VertexLayout{LLGI::VertexLayoutFormat::R32G32B32_FLOAT, "POSITION", 0});
layouts.push_back(VertexLayout{LLGI::VertexLayoutFormat::R32G32B32_FLOAT, "NORMAL", 0});
layouts.push_back(VertexLayout{LLGI::VertexLayoutFormat::R32G32B32_FLOAT, "NORMAL", 1});
layouts.push_back(VertexLayout{LLGI::VertexLayoutFormat::R32G32B32_FLOAT, "NORMAL", 2});
layouts.push_back(VertexLayout{LLGI::VertexLayoutFormat::R32G32_FLOAT, "TEXCOORD", 0});
layouts.push_back(VertexLayout{LLGI::VertexLayoutFormat::R8G8B8A8_UNORM, "NORMAL", 3});
// compile
std::string log;
auto shader = Shader::Create(graphicsDevice_,
dataVS.data(),
(int32_t)resultVS.Binary.size(),
dataPS.data(),
(int32_t)resultPS.Binary.size(),
"MaterialStandardModelRenderer",
layouts,
true);
if (shader == nullptr)
return nullptr;
auto vertexUniformSize = parameterGenerator.VertexShaderUniformBufferSize;
auto pixelUniformSize = parameterGenerator.PixelShaderUniformBufferSize;
shader->SetVertexConstantBufferSize(vertexUniformSize);
shader->SetPixelConstantBufferSize(pixelUniformSize);
if (st == 0)
{
material->ModelUserPtr = shader;
}
else
{
material->RefractionModelUserPtr = shader;
}
}
material->CustomData1 = materialFile.GetCustomData1Count();
material->CustomData2 = materialFile.GetCustomData2Count();
material->TextureCount = std::min(materialFile.GetTextureCount(), Effekseer::UserTextureSlotMax);
material->UniformCount = materialFile.GetUniformCount();
material->ShadingModel = materialFile.GetShadingModel();
for (int32_t i = 0; i < material->TextureCount; i++)
{
material->TextureWrapTypes.at(i) = materialFile.GetTextureWrap(i);
}
return material;
}
::Effekseer::MaterialRef MaterialLoader::Load(const void* data, int32_t size, Effekseer::MaterialFileType fileType)
{
if (fileType == Effekseer::MaterialFileType::Compiled)
{
auto compiled = Effekseer::CompiledMaterial();
if (!compiled.Load(static_cast<const uint8_t*>(data), size))
{
return nullptr;
}
if (!compiled.GetHasValue(platformType_))
{
return nullptr;
}
// compiled
Effekseer::MaterialFile materialFile;
if (!materialFile.Load((const uint8_t*)compiled.GetOriginalData().data(), static_cast<int32_t>(compiled.GetOriginalData().size())))
{
std::cout << "Error : Invalid material is loaded." << std::endl;
return nullptr;
}
auto binary = compiled.GetBinary(platformType_);
return LoadAcutually(materialFile, binary);
}
else
{
if (materialCompiler_ == nullptr)
{
return nullptr;
}
Effekseer::MaterialFile materialFile;
if (!materialFile.Load((const uint8_t*)data, size))
{
std::cout << "Error : Invalid material is loaded." << std::endl;
return nullptr;
}
auto binary = ::Effekseer::CreateUniqueReference(materialCompiler_->Compile(&materialFile));
return LoadAcutually(materialFile, binary.get());
}
}
void MaterialLoader::Unload(::Effekseer::MaterialRef data)
{
if (data == nullptr)
return;
auto shader = reinterpret_cast<Shader*>(data->UserPtr);
auto modelShader = reinterpret_cast<Shader*>(data->ModelUserPtr);
auto refractionShader = reinterpret_cast<Shader*>(data->RefractionUserPtr);
auto refractionModelShader = reinterpret_cast<Shader*>(data->RefractionModelUserPtr);
ES_SAFE_DELETE(shader);
ES_SAFE_DELETE(modelShader);
ES_SAFE_DELETE(refractionShader);
ES_SAFE_DELETE(refractionModelShader);
data->UserPtr = nullptr;
data->ModelUserPtr = nullptr;
data->RefractionUserPtr = nullptr;
data->RefractionModelUserPtr = nullptr;
}
} // namespace EffekseerRendererLLGI