mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-11-22 21:02:07 +00:00
Added the ability to dump and load technique sets.
note: techniques should be dumped in seperate files from technique sets, but compiling them all into the techset works as well but is harder to read.
This commit is contained in:
@@ -40,6 +40,7 @@
|
|||||||
#include "Weapon/RawLoaderWeaponT6.h"
|
#include "Weapon/RawLoaderWeaponT6.h"
|
||||||
#include "ZBarrier/GdtLoaderZBarrierT6.h"
|
#include "ZBarrier/GdtLoaderZBarrierT6.h"
|
||||||
#include "ZBarrier/RawLoaderZBarrierT6.h"
|
#include "ZBarrier/RawLoaderZBarrierT6.h"
|
||||||
|
#include "TechniqueSet/LoaderTechniqueSetT6.h"
|
||||||
|
|
||||||
#include <format>
|
#include <format>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -400,7 +401,7 @@ namespace T6
|
|||||||
// collection.AddAssetCreator(std::make_unique<AssetLoaderXAnim>(memory));
|
// collection.AddAssetCreator(std::make_unique<AssetLoaderXAnim>(memory));
|
||||||
collection.AddAssetCreator(CreateXModelLoader(memory, searchPath, zone));
|
collection.AddAssetCreator(CreateXModelLoader(memory, searchPath, zone));
|
||||||
collection.AddAssetCreator(CreateMaterialLoader(memory, searchPath));
|
collection.AddAssetCreator(CreateMaterialLoader(memory, searchPath));
|
||||||
// collection.AddAssetCreator(std::make_unique<AssetLoaderTechniqueSet>(memory));
|
collection.AddAssetCreator(CreateTechniqueSetLoader(memory, searchPath));
|
||||||
collection.AddAssetCreator(CreateImageLoader(memory, searchPath));
|
collection.AddAssetCreator(CreateImageLoader(memory, searchPath));
|
||||||
collection.AddAssetCreator(CreateSoundBankLoader(memory, searchPath));
|
collection.AddAssetCreator(CreateSoundBankLoader(memory, searchPath));
|
||||||
// collection.AddAssetCreator(std::make_unique<AssetLoaderSoundPatch>(memory));
|
// collection.AddAssetCreator(std::make_unique<AssetLoaderSoundPatch>(memory));
|
||||||
|
|||||||
183
src/ObjLoading/Game/T6/TechniqueSet/LoaderTechniqueSetT6.cpp
Normal file
183
src/ObjLoading/Game/T6/TechniqueSet/LoaderTechniqueSetT6.cpp
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
#include "Game/T6/T6.h"
|
||||||
|
#include "LoaderTechniqueSetT6.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <format>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
using namespace T6;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
class TechniqueSetLoader final : public AssetCreator<AssetTechniqueSet>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TechniqueSetLoader(MemoryManager& memory, ISearchPath& searchPath)
|
||||||
|
: m_memory(memory),
|
||||||
|
m_search_path(searchPath)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
|
||||||
|
{
|
||||||
|
const auto fileName = std::format("techniquesets/{}.json", assetName);
|
||||||
|
const auto file = m_search_path.Open(assetName);
|
||||||
|
if (!file.IsOpen())
|
||||||
|
return AssetCreationResult::NoAction();
|
||||||
|
|
||||||
|
MaterialTechniqueSet* techniqueSet = new MaterialTechniqueSet;
|
||||||
|
memset(techniqueSet, 0, sizeof(MaterialTechniqueSet));
|
||||||
|
|
||||||
|
const auto js = nlohmann::json::parse(*file.m_stream.get());
|
||||||
|
|
||||||
|
std::string techSetName = js["name"];
|
||||||
|
techniqueSet->name = _strdup(techSetName.c_str());
|
||||||
|
techniqueSet->worldVertFormat = (unsigned char)js["worldVertFormat"];
|
||||||
|
|
||||||
|
for (int i = 0; i < 36; i++)
|
||||||
|
{
|
||||||
|
nlohmann::json techniqueJs = js["techniques"][i];
|
||||||
|
|
||||||
|
if (techniqueJs.size() == 0)
|
||||||
|
{
|
||||||
|
techniqueSet->techniques[i] = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MaterialTechnique* technique = new MaterialTechnique;
|
||||||
|
techniqueSet->techniques[i] = technique;
|
||||||
|
|
||||||
|
std::string techName = techniqueJs["name"];
|
||||||
|
technique->name = _strdup(techName.c_str());
|
||||||
|
technique->flags = techniqueJs["flags"];
|
||||||
|
technique->passCount = techniqueJs["passCount"];
|
||||||
|
_ASSERT(technique->passCount == 1);
|
||||||
|
|
||||||
|
for (auto passIndex = 0u; passIndex < technique->passCount; passIndex++)
|
||||||
|
{
|
||||||
|
MaterialPass* currPass = &technique->passArray[passIndex];
|
||||||
|
nlohmann::json passJs = techniqueJs["passArray"][passIndex];
|
||||||
|
|
||||||
|
currPass->perPrimArgCount = (unsigned char)passJs["perPrimArgCount"];
|
||||||
|
currPass->perObjArgCount = (unsigned char)passJs["perObjArgCount"];
|
||||||
|
currPass->stableArgCount = (unsigned char)passJs["stableArgCount"];
|
||||||
|
currPass->customSamplerFlags = (unsigned char)passJs["customSamplerFlags"];
|
||||||
|
currPass->precompiledIndex = (unsigned char)passJs["precompiledIndex"];
|
||||||
|
currPass->materialType = (unsigned char)passJs["materialType"];
|
||||||
|
|
||||||
|
int argCount = currPass->perPrimArgCount + currPass->perObjArgCount + currPass->stableArgCount;
|
||||||
|
if (argCount == 0)
|
||||||
|
{
|
||||||
|
currPass->args = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currPass->args = new MaterialShaderArgument[argCount];
|
||||||
|
for (int i = 0; i < argCount; i++)
|
||||||
|
{
|
||||||
|
MaterialShaderArgument* currArg = &currPass->args[i];
|
||||||
|
auto currArgJs = passJs["args"][i];
|
||||||
|
|
||||||
|
currArg->type = currArgJs["type"];
|
||||||
|
currArg->location.offset = currArgJs["location"];
|
||||||
|
currArg->size = currArgJs["size"];
|
||||||
|
currArg->buffer = currArgJs["buffer"];
|
||||||
|
if (currArg->type == MTL_ARG_LITERAL_VERTEX_CONST || currArg->type == MTL_ARG_LITERAL_PIXEL_CONST)
|
||||||
|
{
|
||||||
|
float* consts = new float[4];
|
||||||
|
consts[0] = currArgJs["u"]["const0"];
|
||||||
|
consts[1] = currArgJs["u"]["const1"];
|
||||||
|
consts[2] = currArgJs["u"]["const2"];
|
||||||
|
consts[3] = currArgJs["u"]["const3"];
|
||||||
|
currArg->u.literalConst = (float(*)[4])consts;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currArg->u.nameHash = currArgJs["u"]["value"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (passJs["vertexDecl"].size() == 0)
|
||||||
|
{
|
||||||
|
currPass->vertexDecl = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currPass->vertexDecl = new MaterialVertexDeclaration;
|
||||||
|
currPass->vertexDecl->streamCount = (unsigned char)passJs["vertexDecl"]["streamCount"];
|
||||||
|
currPass->vertexDecl->hasOptionalSource = passJs["vertexDecl"]["hasOptionalSource"];
|
||||||
|
currPass->vertexDecl->isLoaded = passJs["vertexDecl"]["isLoaded"];
|
||||||
|
for (int i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
currPass->vertexDecl->routing.data[i].source = (unsigned char)passJs["vertexDecl"]["routing"][i]["source"];
|
||||||
|
currPass->vertexDecl->routing.data[i].dest = (unsigned char)passJs["vertexDecl"]["routing"][i]["dest"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (passJs["pixelShader"].size() == 0)
|
||||||
|
{
|
||||||
|
currPass->pixelShader = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currPass->pixelShader = new MaterialPixelShader;
|
||||||
|
|
||||||
|
std::string pixelName = passJs["pixelShader"]["name"];
|
||||||
|
currPass->pixelShader->name = _strdup(pixelName.c_str());
|
||||||
|
currPass->pixelShader->prog.ps = NULL;
|
||||||
|
|
||||||
|
const auto psFileName = std::format("techniques/shader_bin/ps_{}", pixelName);
|
||||||
|
const auto psFile = m_search_path.Open(psFileName);
|
||||||
|
if (!psFile.IsOpen())
|
||||||
|
{
|
||||||
|
printf("ERROR: Cant find pixel shader %s\n", psFileName.c_str());
|
||||||
|
return AssetCreationResult::Failure();
|
||||||
|
}
|
||||||
|
currPass->pixelShader->prog.loadDef.programSize = psFile.m_length;
|
||||||
|
currPass->pixelShader->prog.loadDef.program = new char[psFile.m_length];
|
||||||
|
psFile.m_stream->read(currPass->pixelShader->prog.loadDef.program, psFile.m_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (passJs["vertexShader"].size() == 0)
|
||||||
|
{
|
||||||
|
currPass->vertexShader = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currPass->vertexShader = new MaterialVertexShader;
|
||||||
|
|
||||||
|
std::string vertexName = passJs["vertexShader"]["name"];
|
||||||
|
currPass->vertexShader->name = _strdup(vertexName.c_str());
|
||||||
|
currPass->vertexShader->prog.vs = NULL;
|
||||||
|
|
||||||
|
const auto vsFileName = std::format("techniques/shader_bin/vs_{}", vertexName);
|
||||||
|
const auto vsFile = m_search_path.Open(vsFileName);
|
||||||
|
if (!vsFile.IsOpen())
|
||||||
|
{
|
||||||
|
printf("ERROR: Cant find vertex shader %s\n", vsFileName.c_str());
|
||||||
|
return AssetCreationResult::Failure();
|
||||||
|
}
|
||||||
|
currPass->vertexShader->prog.loadDef.programSize = vsFile.m_length;
|
||||||
|
currPass->vertexShader->prog.loadDef.program = new char[vsFile.m_length];
|
||||||
|
vsFile.m_stream->read(currPass->vertexShader->prog.loadDef.program, vsFile.m_length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return AssetCreationResult::Success(context.AddAsset<AssetTechniqueSet>(assetName, techniqueSet));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
MemoryManager& m_memory;
|
||||||
|
ISearchPath& m_search_path;
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace T6
|
||||||
|
{
|
||||||
|
std::unique_ptr<AssetCreator<AssetTechniqueSet>> CreateTechniqueSetLoader(MemoryManager& memory, ISearchPath& searchPath)
|
||||||
|
{
|
||||||
|
return std::make_unique<TechniqueSetLoader>(memory, searchPath);
|
||||||
|
}
|
||||||
|
} // namespace T6
|
||||||
13
src/ObjLoading/Game/T6/TechniqueSet/LoaderTechniqueSetT6.h
Normal file
13
src/ObjLoading/Game/T6/TechniqueSet/LoaderTechniqueSetT6.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Asset/IAssetCreator.h"
|
||||||
|
#include "Game/T6/T6.h"
|
||||||
|
#include "SearchPath/ISearchPath.h"
|
||||||
|
#include "Utils/MemoryManager.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace T6
|
||||||
|
{
|
||||||
|
std::unique_ptr<AssetCreator<AssetTechniqueSet>> CreateTechniqueSetLoader(MemoryManager& memory, ISearchPath& searchPath);
|
||||||
|
} // namespace T6
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "AssetDumperTechniqueSet.h"
|
#include "AssetDumperTechniqueSet.h"
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
@@ -58,7 +59,7 @@ bool AssetDumperTechniqueSet::ShouldDump(XAssetInfo<MaterialTechniqueSet>* asset
|
|||||||
void AssetDumperTechniqueSet::DumpPixelShader(const AssetDumpingContext& context, const MaterialPixelShader* pixelShader)
|
void AssetDumperTechniqueSet::DumpPixelShader(const AssetDumpingContext& context, const MaterialPixelShader* pixelShader)
|
||||||
{
|
{
|
||||||
std::ostringstream ss;
|
std::ostringstream ss;
|
||||||
ss << "shader_bin/ps_" << pixelShader->name << ".cso";
|
ss << "techniquesets/shader_bin/ps_" << pixelShader->name;
|
||||||
|
|
||||||
const auto shaderFile = context.OpenAssetFile(ss.str());
|
const auto shaderFile = context.OpenAssetFile(ss.str());
|
||||||
|
|
||||||
@@ -71,7 +72,7 @@ void AssetDumperTechniqueSet::DumpPixelShader(const AssetDumpingContext& context
|
|||||||
void AssetDumperTechniqueSet::DumpVertexShader(const AssetDumpingContext& context, const MaterialVertexShader* vertexShader)
|
void AssetDumperTechniqueSet::DumpVertexShader(const AssetDumpingContext& context, const MaterialVertexShader* vertexShader)
|
||||||
{
|
{
|
||||||
std::ostringstream ss;
|
std::ostringstream ss;
|
||||||
ss << "shader_bin/vs_" << vertexShader->name << ".cso";
|
ss << "techniquesets/shader_bin/vs_" << vertexShader->name;
|
||||||
|
|
||||||
const auto shaderFile = context.OpenAssetFile(ss.str());
|
const auto shaderFile = context.OpenAssetFile(ss.str());
|
||||||
|
|
||||||
@@ -86,21 +87,110 @@ void AssetDumperTechniqueSet::DumpAsset(AssetDumpingContext& context, XAssetInfo
|
|||||||
const auto* techniqueSet = asset->Asset();
|
const auto* techniqueSet = asset->Asset();
|
||||||
auto* shaderState = context.GetZoneAssetDumperState<ShaderZoneState>();
|
auto* shaderState = context.GetZoneAssetDumperState<ShaderZoneState>();
|
||||||
|
|
||||||
|
const auto assetFile = context.OpenAssetFile(std::format("techniquesets/{}.json", techniqueSet->name));
|
||||||
|
if (!assetFile)
|
||||||
|
return;
|
||||||
|
|
||||||
|
nlohmann::json js;
|
||||||
|
|
||||||
|
js["name"] = techniqueSet->name;
|
||||||
|
js["worldVertFormat"] = techniqueSet->worldVertFormat;
|
||||||
|
|
||||||
|
js["techniques"] = nlohmann::json::array();
|
||||||
for (const auto* technique : techniqueSet->techniques)
|
for (const auto* technique : techniqueSet->techniques)
|
||||||
{
|
{
|
||||||
if (!technique || !shaderState->ShouldDumpTechnique(technique))
|
nlohmann::json techniqueJs = nlohmann::json::object();
|
||||||
continue;
|
|
||||||
|
|
||||||
|
if (technique != NULL)
|
||||||
|
{
|
||||||
|
techniqueJs["name"] = technique->name;
|
||||||
|
techniqueJs["flags"] = technique->flags;
|
||||||
|
techniqueJs["passCount"] = technique->passCount;
|
||||||
|
|
||||||
|
_ASSERT(technique->passCount == 1);
|
||||||
|
|
||||||
|
techniqueJs["passArray"] = nlohmann::json::array();
|
||||||
for (auto passIndex = 0u; passIndex < technique->passCount; passIndex++)
|
for (auto passIndex = 0u; passIndex < technique->passCount; passIndex++)
|
||||||
{
|
{
|
||||||
const auto* pixelShader = technique->passArray[passIndex].pixelShader;
|
const MaterialPass* currPass = &technique->passArray[passIndex];
|
||||||
|
nlohmann::json passJs = nlohmann::json::object();
|
||||||
|
|
||||||
if (pixelShader && shaderState->ShouldDumpPixelShader(pixelShader))
|
passJs["perPrimArgCount"] = currPass->perPrimArgCount;
|
||||||
DumpPixelShader(context, pixelShader);
|
passJs["perObjArgCount"] = currPass->perObjArgCount;
|
||||||
|
passJs["stableArgCount"] = currPass->stableArgCount;
|
||||||
|
passJs["customSamplerFlags"] = currPass->customSamplerFlags;
|
||||||
|
passJs["precompiledIndex"] = currPass->precompiledIndex;
|
||||||
|
passJs["materialType"] = currPass->materialType;
|
||||||
|
|
||||||
const auto* vertexShader = technique->passArray[passIndex].vertexShader;
|
nlohmann::json vertDeclJs = nlohmann::json::object();
|
||||||
if (vertexShader && shaderState->ShouldDumpVertexShader(vertexShader))
|
if (currPass->vertexDecl != NULL)
|
||||||
DumpVertexShader(context, vertexShader);
|
{
|
||||||
|
vertDeclJs["streamCount"] = currPass->vertexDecl->streamCount;
|
||||||
|
vertDeclJs["hasOptionalSource"] = currPass->vertexDecl->hasOptionalSource;
|
||||||
|
vertDeclJs["isLoaded"] = currPass->vertexDecl->isLoaded;
|
||||||
|
for (int i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
vertDeclJs["routing"][i]["source"] = currPass->vertexDecl->routing.data[i].source;
|
||||||
|
vertDeclJs["routing"][i]["dest"] = currPass->vertexDecl->routing.data[i].dest;
|
||||||
|
|
||||||
|
_ASSERT(currPass->vertexDecl->routing.decl[i] == NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
passJs["vertexDecl"] = vertDeclJs;
|
||||||
|
|
||||||
|
passJs["args"] = nlohmann::json::array();
|
||||||
|
if (currPass->args != NULL)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < currPass->perPrimArgCount + currPass->perObjArgCount + currPass->stableArgCount; i++)
|
||||||
|
{
|
||||||
|
nlohmann::json argsJs = nlohmann::json::object();
|
||||||
|
MaterialShaderArgument* currArg = &currPass->args[i];
|
||||||
|
|
||||||
|
argsJs["type"] = currArg->type;
|
||||||
|
argsJs["location"] = currArg->location.offset;
|
||||||
|
argsJs["size"] = currArg->size;
|
||||||
|
argsJs["buffer"] = currArg->buffer;
|
||||||
|
if (currArg->type == MTL_ARG_LITERAL_VERTEX_CONST || currArg->type == MTL_ARG_LITERAL_PIXEL_CONST)
|
||||||
|
{
|
||||||
|
argsJs["u"]["const0"] = currArg->u.literalConst[0];
|
||||||
|
argsJs["u"]["const1"] = currArg->u.literalConst[1];
|
||||||
|
argsJs["u"]["const2"] = currArg->u.literalConst[2];
|
||||||
|
argsJs["u"]["const3"] = currArg->u.literalConst[3];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
argsJs["u"]["value"] = currArg->u.nameHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
passJs["args"].push_back(argsJs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json pixelJs = nlohmann::json::object();
|
||||||
|
if (currPass->pixelShader != NULL)
|
||||||
|
{
|
||||||
|
pixelJs["name"] = currPass->pixelShader->name;
|
||||||
|
if (shaderState->ShouldDumpPixelShader(currPass->pixelShader))
|
||||||
|
DumpPixelShader(context, currPass->pixelShader);
|
||||||
|
}
|
||||||
|
passJs["pixelShader"] = pixelJs;
|
||||||
|
|
||||||
|
nlohmann::json vertexJs = nlohmann::json::object();
|
||||||
|
if (currPass->vertexShader != NULL)
|
||||||
|
{
|
||||||
|
vertexJs["name"] = currPass->vertexShader->name;
|
||||||
|
if (shaderState->ShouldDumpVertexShader(currPass->vertexShader))
|
||||||
|
DumpVertexShader(context, currPass->vertexShader);
|
||||||
|
}
|
||||||
|
passJs["vertexShader"] = vertexJs;
|
||||||
|
|
||||||
|
techniqueJs["passArray"].push_back(passJs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
js["techniques"].push_back(techniqueJs);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string jsonString = js.dump(4);
|
||||||
|
assetFile->write(jsonString.c_str(), jsonString.size());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user