mirror of https://github.com/axmolengine/axmol.git
422 lines
12 KiB
C++
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
|