diff --git a/src/Common/Game/IW4/CommonIW4.h b/src/Common/Game/IW4/CommonIW4.h index a0e32e4c..2309b48b 100644 --- a/src/Common/Game/IW4/CommonIW4.h +++ b/src/Common/Game/IW4/CommonIW4.h @@ -7,6 +7,20 @@ namespace IW4 class Common { public: + static constexpr uint32_t R_HashString(const char* string, const uint32_t hash) + { + const char* v2 = string; // edx@1 + char v3 = *string; // cl@1 + uint32_t result = hash; + + for (; *v2; v3 = *v2) + { + ++v2; + result = 33 * result ^ (v3 | 0x20); + } + return result; + } + static int StringTable_HashString(const char* str); static PackedTexCoords Vec2PackTexCoords(const vec2_t* in); diff --git a/src/Common/Game/IW4/IW4_Assets.h b/src/Common/Game/IW4/IW4_Assets.h index 2eacca29..da48d0d7 100644 --- a/src/Common/Game/IW4/IW4_Assets.h +++ b/src/Common/Game/IW4/IW4_Assets.h @@ -1125,7 +1125,7 @@ namespace IW4 struct CodeConstantSource { const char* name; - unsigned char source; + MaterialConstantSource source; CodeConstantSource* subtable; int arrayCount; int arrayStride; diff --git a/src/ObjCommon/Game/IW4/TechsetConstantsIW4.h b/src/ObjCommon/Game/IW4/TechsetConstantsIW4.h index d64f874c..e4e8424f 100644 --- a/src/ObjCommon/Game/IW4/TechsetConstantsIW4.h +++ b/src/ObjCommon/Game/IW4/TechsetConstantsIW4.h @@ -1,7 +1,9 @@ #pragma once +#include #include +#include "Game/IW4/CommonIW4.h" #include "Game/IW4/IW4.h" namespace IW4 @@ -274,4 +276,58 @@ namespace IW4 {"spotShadowmapPixelAdjust", CONST_SRC_CODE_SPOT_SHADOWMAP_PIXEL_ADJUST, nullptr, 0, 0}, {} }; + + static constexpr std::pair KnownMaterialSource(const char* name) + { + return std::make_pair(Common::R_HashString(name, 0u), name); + } + + inline std::unordered_map knownMaterialSourceNames + { + KnownMaterialSource("colorMap"), + KnownMaterialSource("colorMap0"), + KnownMaterialSource("colorMap1"), + KnownMaterialSource("colorMap2"), + KnownMaterialSource("colorMap3"), + KnownMaterialSource("colorMap4"), + KnownMaterialSource("colorMap5"), + KnownMaterialSource("colorMap6"), + KnownMaterialSource("colorMap7"), + KnownMaterialSource("normalMap"), + KnownMaterialSource("normalMap0"), + KnownMaterialSource("normalMap1"), + KnownMaterialSource("normalMap2"), + KnownMaterialSource("normalMap3"), + KnownMaterialSource("normalMap4"), + KnownMaterialSource("normalMap5"), + KnownMaterialSource("normalMap6"), + KnownMaterialSource("normalMap7"), + KnownMaterialSource("specularMap"), + KnownMaterialSource("specularMap0"), + KnownMaterialSource("specularMap1"), + KnownMaterialSource("specularMap2"), + KnownMaterialSource("specularMap3"), + KnownMaterialSource("specularMap4"), + KnownMaterialSource("specularMap5"), + KnownMaterialSource("specularMap6"), + KnownMaterialSource("specularMap7"), + KnownMaterialSource("detailMap"), + KnownMaterialSource("detailMap0"), + KnownMaterialSource("detailMap1"), + KnownMaterialSource("detailMap2"), + KnownMaterialSource("detailMap3"), + KnownMaterialSource("detailMap4"), + KnownMaterialSource("detailMap5"), + KnownMaterialSource("detailMap6"), + KnownMaterialSource("detailMap7"), + KnownMaterialSource("attenuationMap"), + KnownMaterialSource("attenuationMap0"), + KnownMaterialSource("attenuationMap1"), + KnownMaterialSource("attenuationMap2"), + KnownMaterialSource("attenuationMap3"), + KnownMaterialSource("attenuationMap4"), + KnownMaterialSource("attenuationMap5"), + KnownMaterialSource("attenuationMap6"), + KnownMaterialSource("attenuationMap7"), + }; } diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp index 04fd134f..f4e21721 100644 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp +++ b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp @@ -13,20 +13,82 @@ #include "Pool/GlobalAssetPool.h" #include "Techset/TechniqueFileReader.h" #include "Techset/TechsetFileReader.h" +#include "Shader/D3D9ShaderAnalyser.h" using namespace IW4; namespace IW4 { + class LoadedTechnique + { + public: + MaterialTechnique* m_technique; + std::vector m_dependencies; + + LoadedTechnique(MaterialTechnique* technique, std::vector dependencies) + : m_technique(technique), + m_dependencies(std::move(dependencies)) + { + } + }; + + class TechniqueZoneLoadingState final : public IZoneAssetLoaderState + { + public: + typedef const float (*literal_t)[4]; + + private: + std::unordered_map> m_loaded_techniques; + std::map m_allocated_literals; + + public: + _NODISCARD const LoadedTechnique* FindLoadedTechnique(const std::string& techniqueName) const + { + const auto loadedTechnique = m_loaded_techniques.find(techniqueName); + if (loadedTechnique != m_loaded_techniques.end()) + return loadedTechnique->second.get(); + + return nullptr; + } + + const LoadedTechnique* AddLoadedTechnique(std::string techniqueName, MaterialTechnique* technique, std::vector dependencies) + { + return m_loaded_techniques.emplace(std::make_pair(std::move(techniqueName), std::make_unique(technique, std::move(dependencies)))).first->second.get(); + } + + literal_t GetAllocatedLiteral(MemoryManager* memory, techset::ShaderArgumentLiteralSource source) + { + const auto& existingEntry = m_allocated_literals.find(source); + + if (existingEntry != m_allocated_literals.end()) + return existingEntry->second; + + auto* newLiteral = static_cast(memory->Alloc(sizeof(float) * 4u)); + (*newLiteral)[0] = source.m_value[0]; + (*newLiteral)[1] = source.m_value[1]; + (*newLiteral)[2] = source.m_value[2]; + (*newLiteral)[3] = source.m_value[3]; + m_allocated_literals.emplace(std::make_pair(source, newLiteral)); + + return newLiteral; + } + }; + class TechniqueCreator final : public techset::ITechniqueDefinitionAcceptor { + MemoryManager* const m_memory; IAssetLoadingManager* const m_manager; + TechniqueZoneLoadingState* const m_zone_state; public: struct Pass { XAssetInfo* m_vertex_shader; + std::unique_ptr m_vertex_shader_info; + XAssetInfo* m_pixel_shader; + std::unique_ptr m_pixel_shader_info; + MaterialVertexDeclaration m_vertex_decl; std::vector m_arguments; @@ -41,8 +103,10 @@ namespace IW4 std::vector m_passes; std::vector m_dependencies; - explicit TechniqueCreator(IAssetLoadingManager* manager) - : m_manager(manager) + TechniqueCreator(MemoryManager* memory, IAssetLoadingManager* manager, TechniqueZoneLoadingState* zoneState) + : m_memory(memory), + m_manager(manager), + m_zone_state(zoneState) { m_passes.emplace_back(); } @@ -66,9 +130,13 @@ namespace IW4 return false; } + assert(!m_passes.empty()); auto& pass = m_passes.at(m_passes.size() - 1); pass.m_vertex_shader = reinterpret_cast*>(vertexShaderDependency); + const auto& shaderLoadDef = pass.m_vertex_shader->Asset()->prog.loadDef; + pass.m_vertex_shader_info = d3d9::ShaderAnalyser::GetShaderInfo(shaderLoadDef.program, shaderLoadDef.programSize * sizeof(uint32_t)); + return true; } @@ -81,19 +149,295 @@ namespace IW4 return false; } + assert(!m_passes.empty()); auto& pass = m_passes.at(m_passes.size() - 1); pass.m_pixel_shader = reinterpret_cast*>(pixelShaderDependency); + const auto& shaderLoadDef = pass.m_pixel_shader->Asset()->prog.loadDef; + pass.m_pixel_shader_info = d3d9::ShaderAnalyser::GetShaderInfo(shaderLoadDef.program, shaderLoadDef.programSize * sizeof(uint32_t)); + return true; } - bool AcceptShaderCodeArgument(techset::ShaderSelector shader, techset::ShaderArgument shaderArgument, techset::ShaderArgumentCodeSource source, std::string& errorMessage) override + static bool IsSamplerConstant(const d3d9::ShaderConstant& constant) { + return constant.m_type == d3d9::ParameterType::SAMPLER + || constant.m_type == d3d9::ParameterType::SAMPLER_1D + || constant.m_type == d3d9::ParameterType::SAMPLER_2D + || constant.m_type == d3d9::ParameterType::SAMPLER_3D + || constant.m_type == d3d9::ParameterType::SAMPLER_CUBE; + } + + static const CodeConstantSource* FindCodeConstantSource(const std::vector& accessors, const CodeConstantSource* sourceTable) + { + const CodeConstantSource* foundSource = nullptr; + const CodeConstantSource* currentTable = sourceTable; + for (const auto& accessor : accessors) + { + if (currentTable == nullptr) + return nullptr; + + while (true) + { + if (currentTable->name == nullptr) + return nullptr; + + if (accessor == currentTable->name) + break; + + currentTable++; + } + + foundSource = currentTable; + currentTable = currentTable->subtable; + } + + return foundSource; + } + + static const CodeSamplerSource* FindCodeSamplerSource(const std::vector& accessors, const CodeSamplerSource* sourceTable) + { + const CodeSamplerSource* foundSource = nullptr; + const CodeSamplerSource* currentTable = sourceTable; + for (const auto& accessor : accessors) + { + if (currentTable == nullptr) + return nullptr; + + while (true) + { + if (currentTable->name == nullptr) + return nullptr; + + if (accessor == currentTable->name) + break; + + currentTable++; + } + + foundSource = currentTable; + currentTable = currentTable->subtable; + } + + return foundSource; + } + + bool AcceptVertexShaderCodeArgument(techset::ShaderArgument shaderArgument, const techset::ShaderArgumentCodeSource& source, std::string& errorMessage) + { + assert(!m_passes.empty()); + auto& pass = m_passes.at(m_passes.size() - 1); + + if (!pass.m_vertex_shader_info) + { + errorMessage = "Shader not specified"; + return false; + } + + const auto& shaderInfo = *pass.m_vertex_shader_info; + const auto matchingShaderConstant = std::find_if(shaderInfo.m_constants.begin(), shaderInfo.m_constants.end(), [&shaderArgument](const d3d9::ShaderConstant& constant) + { + return constant.m_name == shaderArgument.m_argument_name; + }); + + if (matchingShaderConstant == shaderInfo.m_constants.end()) + { + errorMessage = "Could not find argument in shader"; + return false; + } + + const auto constantIsSampler = IsSamplerConstant(*matchingShaderConstant); + if (constantIsSampler) + { + errorMessage = "Vertex sampler are unsupported"; + return false; + } + + MaterialShaderArgument argument{}; + argument.type = MTL_ARG_CODE_VERTEX_CONST; + argument.dest = static_cast(matchingShaderConstant->m_register_index); + + const CodeConstantSource* constantSource = FindCodeConstantSource(source.m_accessors, s_codeConsts); + if (!constantSource) + constantSource = FindCodeConstantSource(source.m_accessors, s_defaultCodeConsts); + + if (!constantSource) + { + errorMessage = "Unknown code constant"; + return false; + } + + if (constantSource->arrayCount > 0) + { + if (!source.m_index_accessor_specified) + { + errorMessage = "Code constant must have array index specified"; + return false; + } + + if (source.m_index_accessor >= static_cast(constantSource->arrayCount)) + { + errorMessage = "Code constant array index out of bounds"; + return false; + } + + argument.u.codeConst.index = static_cast(constantSource->source + source.m_index_accessor); + } + else if (source.m_index_accessor_specified) + { + errorMessage = "Code constant cannot have array index specified"; + return false; + } + else + { + argument.u.codeConst.index = static_cast(constantSource->source); + } + argument.u.codeConst.firstRow = 0u; + argument.u.codeConst.rowCount = static_cast(matchingShaderConstant->m_type_rows); + + pass.m_arguments.push_back(argument); + return true; } - bool AcceptShaderLiteralArgument(techset::ShaderSelector shader, techset::ShaderArgument shaderArgument, techset::ShaderArgumentLiteralSource source, std::string& errorMessage) override + bool AcceptPixelShaderCodeArgument(techset::ShaderArgument shaderArgument, const techset::ShaderArgumentCodeSource& source, std::string& errorMessage) { + assert(!m_passes.empty()); + auto& pass = m_passes.at(m_passes.size() - 1); + + if (!pass.m_pixel_shader_info) + { + errorMessage = "Shader not specified"; + return false; + } + + const auto& shaderInfo = *pass.m_pixel_shader_info; + + const auto matchingShaderConstant = std::find_if(shaderInfo.m_constants.begin(), shaderInfo.m_constants.end(), [&shaderArgument](const d3d9::ShaderConstant& constant) + { + return constant.m_name == shaderArgument.m_argument_name; + }); + + if (matchingShaderConstant == shaderInfo.m_constants.end()) + { + errorMessage = "Could not find argument in shader"; + return false; + } + + const auto constantIsSampler = IsSamplerConstant(*matchingShaderConstant); + MaterialShaderArgument argument{}; + argument.type = constantIsSampler ? MTL_ARG_CODE_PIXEL_SAMPLER : MTL_ARG_CODE_PIXEL_CONST; + argument.dest = static_cast(matchingShaderConstant->m_register_index); + + unsigned sourceIndex, arrayCount; + if (constantIsSampler) + { + const CodeSamplerSource* samplerSource = FindCodeSamplerSource(source.m_accessors, s_codeSamplers); + if (!samplerSource) + samplerSource = FindCodeSamplerSource(source.m_accessors, s_defaultCodeSamplers); + + if (!samplerSource) + { + errorMessage = "Unknown code sampler"; + return false; + } + + sourceIndex = static_cast(samplerSource->source); + arrayCount = static_cast(samplerSource->arrayCount); + } + else + { + const CodeConstantSource* constantSource = FindCodeConstantSource(source.m_accessors, s_codeConsts); + if (!constantSource) + constantSource = FindCodeConstantSource(source.m_accessors, s_defaultCodeConsts); + + if (!constantSource) + { + errorMessage = "Unknown code constant"; + return false; + } + + sourceIndex = static_cast(constantSource->source); + arrayCount = static_cast(constantSource->arrayCount); + } + + if (arrayCount > 0u) + { + if (!source.m_index_accessor_specified) + { + errorMessage = "Code constant must have array index specified"; + return false; + } + + if (source.m_index_accessor >= arrayCount) + { + errorMessage = "Code constant array index out of bounds"; + return false; + } + + argument.u.codeConst.index = static_cast(sourceIndex + source.m_index_accessor); + } + else if (source.m_index_accessor_specified) + { + errorMessage = "Code constant cannot have array index specified"; + return false; + } + else + { + argument.u.codeConst.index = static_cast(sourceIndex); + } + argument.u.codeConst.firstRow = 0u; + argument.u.codeConst.rowCount = static_cast(matchingShaderConstant->m_type_rows); + + pass.m_arguments.push_back(argument); + + return true; + } + + bool AcceptShaderCodeArgument(const techset::ShaderSelector shader, const techset::ShaderArgument shaderArgument, const techset::ShaderArgumentCodeSource source, + std::string& errorMessage) override + { + if (shader == techset::ShaderSelector::VERTEX_SHADER) + return AcceptVertexShaderCodeArgument(shaderArgument, source, errorMessage); + + assert(shader == techset::ShaderSelector::PIXEL_SHADER); + return AcceptPixelShaderCodeArgument(shaderArgument, source, errorMessage); + } + + bool AcceptShaderLiteralArgument(const techset::ShaderSelector shader, techset::ShaderArgument shaderArgument, techset::ShaderArgumentLiteralSource source, std::string& errorMessage) override + { + assert(!m_passes.empty()); + auto& pass = m_passes.at(m_passes.size() - 1); + + MaterialShaderArgument argument{}; + const d3d9::ShaderInfo* shaderInfo; + + if (shader == techset::ShaderSelector::VERTEX_SHADER) + { + argument.type = MTL_ARG_LITERAL_VERTEX_CONST; + shaderInfo = pass.m_vertex_shader_info.get(); + } + else + { + assert(shader == techset::ShaderSelector::PIXEL_SHADER); + argument.type = MTL_ARG_LITERAL_PIXEL_CONST; + shaderInfo = pass.m_pixel_shader_info.get(); + } + + if (!shaderInfo) + { + errorMessage = "Shader not specified"; + return false; + } + + const auto matchingShaderConstant = std::find_if(shaderInfo->m_constants.begin(), shaderInfo->m_constants.end(), [&shaderArgument](const d3d9::ShaderConstant& constant) + { + return constant.m_name == shaderArgument.m_argument_name; + }); + + argument.dest = static_cast(matchingShaderConstant->m_register_index); + argument.u.literalConst = m_zone_state->GetAllocatedLiteral(m_memory, source); + pass.m_arguments.push_back(argument); + return true; } @@ -108,39 +452,6 @@ namespace IW4 } }; - class LoadedTechnique - { - public: - MaterialTechnique* m_technique; - std::vector m_dependencies; - - LoadedTechnique(MaterialTechnique* technique, std::vector dependencies) - : m_technique(technique), - m_dependencies(std::move(dependencies)) - { - } - }; - - class TechniqueZoneLoadingState final : public IZoneAssetLoaderState - { - std::unordered_map> m_loaded_techniques; - - public: - _NODISCARD const LoadedTechnique* FindLoadedTechnique(const std::string& techniqueName) const - { - const auto loadedTechnique = m_loaded_techniques.find(techniqueName); - if (loadedTechnique != m_loaded_techniques.end()) - return loadedTechnique->second.get(); - - return nullptr; - } - - const LoadedTechnique* AddLoadedTechnique(std::string techniqueName, MaterialTechnique* technique, std::vector dependencies) - { - return m_loaded_techniques.emplace(std::make_pair(std::move(techniqueName), std::make_unique(technique, std::move(dependencies)))).first->second.get(); - } - }; - class TechniqueLoader { ISearchPath* m_search_path; @@ -155,6 +466,28 @@ namespace IW4 return ss.str(); } + void ConvertPass(MaterialPass& out, const TechniqueCreator::Pass& in) + { + out.vertexShader = in.m_vertex_shader->Asset(); + out.pixelShader = in.m_pixel_shader->Asset(); + } + + MaterialTechnique* ConvertTechnique(const std::string& techniqueName, const std::vector& passes) + { + assert(!passes.empty()); + // TODO: Load technique or use previously loaded one + const auto techniqueSize = sizeof(MaterialTechnique) + (passes.size() - 1u) * sizeof(MaterialPass); + auto* technique = static_cast(m_memory->Alloc(techniqueSize)); + memset(technique, 0, techniqueSize); + technique->name = m_memory->Dup(techniqueName.c_str()); + technique->passCount = static_cast(passes.size()); + + for (auto i = 0u; i < passes.size(); i++) + ConvertPass(technique->passArray[i], passes.at(i)); + + return technique; + } + MaterialTechnique* LoadTechniqueFromRaw(const std::string& techniqueName, std::vector& dependencies) { const auto techniqueFileName = GetTechniqueFileName(techniqueName); @@ -162,12 +495,12 @@ namespace IW4 if (!file.IsOpen()) return nullptr; - TechniqueCreator creator(m_manager); - techset::TechniqueFileReader reader(*file.m_stream, techniqueFileName, &creator); + TechniqueCreator creator(m_memory, m_manager, m_zone_state); + const techset::TechniqueFileReader reader(*file.m_stream, techniqueFileName, &creator); if (!reader.ReadTechniqueDefinition()) return nullptr; - // TODO: Load technique or use previously loaded one - return nullptr; + + return ConvertTechnique(techniqueName, creator.m_passes); } public: @@ -187,7 +520,7 @@ namespace IW4 std::vector dependencies; auto* techniqueFromRaw = LoadTechniqueFromRaw(techniqueName, dependencies); - if (technique == nullptr) + if (techniqueFromRaw == nullptr) return nullptr; return m_zone_state->AddLoadedTechnique(techniqueName, techniqueFromRaw, dependencies); diff --git a/src/ObjLoading/Techset/Parsing/Sequence/TechniqueShaderScopeSequences.cpp b/src/ObjLoading/Techset/Parsing/Sequence/TechniqueShaderScopeSequences.cpp index 93336d3e..55a63abb 100644 --- a/src/ObjLoading/Techset/Parsing/Sequence/TechniqueShaderScopeSequences.cpp +++ b/src/ObjLoading/Techset/Parsing/Sequence/TechniqueShaderScopeSequences.cpp @@ -61,18 +61,26 @@ namespace techset }).Tag(TAG_CODE); } + static std::unique_ptr LiteralValueMatchers(const SimpleMatcherFactory& create) + { + return create.Or({ + create.FloatingPoint(), + create.Integer() + }).Capture(CAPTURE_LITERAL_VALUE); + } + static std::unique_ptr LiteralMatchers(const SimpleMatcherFactory& create) { return create.And({ create.Keyword("float4"), create.Char('('), - create.FloatingPoint().Capture(CAPTURE_LITERAL_VALUE), + LiteralValueMatchers(create), create.Char(','), - create.FloatingPoint().Capture(CAPTURE_LITERAL_VALUE), + LiteralValueMatchers(create), create.Char(','), - create.FloatingPoint().Capture(CAPTURE_LITERAL_VALUE), + LiteralValueMatchers(create), create.Char(','), - create.FloatingPoint().Capture(CAPTURE_LITERAL_VALUE), + LiteralValueMatchers(create), create.Char(')'), }).Tag(TAG_LITERAL); } @@ -142,7 +150,14 @@ namespace techset { float value[4]; for (float& i : value) - i = static_cast(result.NextCapture(CAPTURE_LITERAL_VALUE).FloatingPointValue()); + { + const auto& literalValueToken = result.NextCapture(CAPTURE_LITERAL_VALUE); + + if (literalValueToken.m_type == SimpleParserValueType::FLOATING_POINT) + i = static_cast(literalValueToken.FloatingPointValue()); + else + i = static_cast(literalValueToken.IntegerValue()); + } const ShaderArgumentLiteralSource source(value); std::string errorMessage; @@ -174,16 +189,17 @@ namespace techset const auto& shaderArgumentNameToken = result.NextCapture(CAPTURE_SHADER_ARGUMENT); - size_t index = 0u; + ShaderArgument arg; if (result.HasNextCapture(CAPTURE_SHADER_INDEX)) { const auto& shaderArgumentIndexToken = result.NextCapture(CAPTURE_SHADER_INDEX); if (shaderArgumentIndexToken.IntegerValue() < 0) throw ParsingException(shaderArgumentIndexToken.GetPos(), "Index cannot be negative"); - index = static_cast(shaderArgumentIndexToken.IntegerValue()); + const auto index = static_cast(shaderArgumentIndexToken.IntegerValue()); + arg = ShaderArgument(shaderArgumentNameToken.IdentifierValue(), index); } - - ShaderArgument arg(shaderArgumentNameToken.IdentifierValue(), index); + else + arg = ShaderArgument(shaderArgumentNameToken.IdentifierValue()); const auto typeTag = result.NextTag(); assert(typeTag == TAG_CODE || typeTag == TAG_LITERAL || typeTag == TAG_MATERIAL); diff --git a/src/ObjLoading/Techset/TechniqueDefinitionAcceptor.cpp b/src/ObjLoading/Techset/TechniqueDefinitionAcceptor.cpp index 6aad707a..e103aa33 100644 --- a/src/ObjLoading/Techset/TechniqueDefinitionAcceptor.cpp +++ b/src/ObjLoading/Techset/TechniqueDefinitionAcceptor.cpp @@ -3,12 +3,21 @@ using namespace techset; ShaderArgument::ShaderArgument() - : m_argument_index(0u) + : m_argument_index_specified(false), + m_argument_index(0u) +{ +} + +ShaderArgument::ShaderArgument(std::string argumentName) + : m_argument_name(std::move(argumentName)), + m_argument_index_specified(false), + m_argument_index(0u) { } ShaderArgument::ShaderArgument(std::string argumentName, const size_t argumentIndex) : m_argument_name(std::move(argumentName)), + m_argument_index_specified(true), m_argument_index(argumentIndex) { } diff --git a/src/ObjLoading/Techset/TechniqueDefinitionAcceptor.h b/src/ObjLoading/Techset/TechniqueDefinitionAcceptor.h index 55f4fbf5..3cb4a2ee 100644 --- a/src/ObjLoading/Techset/TechniqueDefinitionAcceptor.h +++ b/src/ObjLoading/Techset/TechniqueDefinitionAcceptor.h @@ -15,9 +15,11 @@ namespace techset { public: std::string m_argument_name; + bool m_argument_index_specified; size_t m_argument_index; ShaderArgument(); + explicit ShaderArgument(std::string argumentName); ShaderArgument(std::string argumentName, size_t argumentIndex); }; diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperTechniqueSet.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperTechniqueSet.cpp index 1ba07bc8..8fc4c36d 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperTechniqueSet.cpp +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperTechniqueSet.cpp @@ -56,7 +56,7 @@ namespace IW4 } else if (currentCodeConst->arrayCount > 0) { - if (currentCodeConst->source <= static_cast(sourceIndexToFind) + if (currentCodeConst->source <= sourceIndexToFind && static_cast(currentCodeConst->source) + currentCodeConst->arrayCount > static_cast(sourceIndexToFind)) { std::ostringstream ss; @@ -150,13 +150,13 @@ namespace IW4 if (codeDestAccessor != codeSourceAccessor) { Indent(); - m_stream << codeDestAccessor << " = code." << codeSourceAccessor << ";\n"; + m_stream << codeDestAccessor << " = constant." << codeSourceAccessor << ";\n"; } else { #ifdef TECHSET_DEBUG Indent(); - m_stream << "// Omitted due to matching accessors: " << codeDestAccessor << " = code." << codeSourceAccessor << ";\n"; + m_stream << "// Omitted due to matching accessors: " << codeDestAccessor << " = constant." << codeSourceAccessor << ";\n"; #endif } } @@ -177,13 +177,13 @@ namespace IW4 if (codeDestAccessor != codeSourceAccessor) { Indent(); - m_stream << codeDestAccessor << " = code." << codeSourceAccessor << ";\n"; + m_stream << codeDestAccessor << " = sampler." << codeSourceAccessor << ";\n"; } else { #ifdef TECHSET_DEBUG Indent(); - m_stream << "// Omitted due to matching accessors: " << codeDestAccessor << " = code." << codeSourceAccessor << ";\n"; + m_stream << "// Omitted due to matching accessors: " << codeDestAccessor << " = sampler." << codeSourceAccessor << ";\n"; #endif } } @@ -209,7 +209,23 @@ namespace IW4 else if (arg.type == MTL_ARG_MATERIAL_PIXEL_CONST || arg.type == MTL_ARG_MATERIAL_VERTEX_CONST || arg.type == MTL_ARG_MATERIAL_PIXEL_SAMPLER) { Indent(); - m_stream << codeDestAccessor << " = material.#0x" << std::hex << arg.u.nameHash << ";\n"; + m_stream << codeDestAccessor << " = material."; + + const auto knownMaterialSource = knownMaterialSourceNames.find(arg.u.nameHash); + if (knownMaterialSource != knownMaterialSourceNames.end()) + { + m_stream << knownMaterialSource->second; + } + else + { + const auto shaderArgNameHash = Common::R_HashString(targetShaderArg->m_name.c_str(), 0u); + if (shaderArgNameHash == arg.u.nameHash) + m_stream << targetShaderArg->m_name; + else + m_stream << "#0x" << std::hex << arg.u.nameHash; + } + + m_stream << ";\n"; } else { @@ -228,7 +244,7 @@ namespace IW4 { const auto loadedVertexShaderFromOtherZone = GlobalAssetPool::GetAssetByName(&vertexShader->name[1]); - if(loadedVertexShaderFromOtherZone == nullptr) + if (loadedVertexShaderFromOtherZone == nullptr) { // Cannot dump when shader is referenced due to unknown constant names and unknown version Indent(); @@ -387,7 +403,7 @@ namespace IW4 if (vertexDecl == nullptr) return; - if(vertexDecl->name && vertexDecl->name[0] == ',') + if (vertexDecl->name && vertexDecl->name[0] == ',') { const auto loadedVertexDeclFromOtherZone = GlobalAssetPool::GetAssetByName(&vertexDecl->name[1]);