diff --git a/hecl/blender/BlenderConnection.cpp b/hecl/blender/BlenderConnection.cpp index d32ffbad4..3e0bdb614 100644 --- a/hecl/blender/BlenderConnection.cpp +++ b/hecl/blender/BlenderConnection.cpp @@ -591,6 +591,20 @@ BlenderConnection::DataStream::Mesh::Material::Material conn.m_loadedBlend.getProject().getProjectRootPath().getProjectRelativeFromAbsolute(absolute); texs.emplace_back(conn.m_loadedBlend.getProject().getProjectWorkingPath(), relative); } + + uint32_t iPropCount; + conn._readBuf(&iPropCount, 4); + iprops.reserve(iPropCount); + for (uint32_t i=0 ; i #include #include +#include #include "HECL/HECL.hpp" #include @@ -311,6 +312,7 @@ public: std::string name; std::string source; std::vector texs; + std::unordered_map iprops; Material(BlenderConnection& conn); }; diff --git a/hecl/blender/hecl/hmdl/HMDLShader.py b/hecl/blender/hecl/hmdl/HMDLShader.py index 8aeeea91d..5958c3975 100644 --- a/hecl/blender/hecl/hmdl/HMDLShader.py +++ b/hecl/blender/hecl/hmdl/HMDLShader.py @@ -141,7 +141,7 @@ def recursive_color_trace(mat_obj, mesh_obj, tex_list, node, socket=None): if socket.name == 'Value': if matrix_str: uvsource_str = matrix_str % uvsource_str - return 'Texture(%d, %s).a' % (get_texmap_idx(tex_list, node.texture.name), uvsource_str) + return 'Texture(%d, %s).aaa' % (get_texmap_idx(tex_list, node.texture.name), uvsource_str) if socket.name == 'Color': if matrix_str: uvsource_str = matrix_str % uvsource_str @@ -297,7 +297,7 @@ def recursive_alpha_trace(mat_obj, mesh_obj, tex_list, node, socket=None): if socket.name == 'Value': if matrix_str: uvsource_str = matrix_str % uvsource_str - return 'Texture(%d, %s).a' % (get_texmap_idx(tex_list, node.texture.name), uvsource_str) + return 'Texture(%d, %s).aaa' % (get_texmap_idx(tex_list, node.texture.name), uvsource_str) else: raise RuntimeError("Only the 'Value' output sockets may be used from Texture nodes") @@ -321,7 +321,7 @@ def recursive_alpha_trace(mat_obj, mesh_obj, tex_list, node, socket=None): if node.label.startswith('DYNAMIC_'): dynamic_index = int(node.label[8:]) - return 'ColorReg(%d).a' % dynamic_index + return 'ColorReg(%d).aaa' % dynamic_index return '%g' % node.outputs['Value'].default_value diff --git a/hecl/blender/hecl/hmdl/__init__.py b/hecl/blender/hecl/hmdl/__init__.py index b3aa8f972..b9d44729b 100644 --- a/hecl/blender/hecl/hmdl/__init__.py +++ b/hecl/blender/hecl/hmdl/__init__.py @@ -65,6 +65,28 @@ def generate_skeleton_info(armature, endian_char='<'): return info_bytes +def write_out_material(writebuf, mat, mesh_obj): + hecl_str, texs = HMDLShader.shader(mat, mesh_obj) + writebuf(struct.pack('I', len(mat.name))) + writebuf(mat.name.encode()) + writebuf(struct.pack('I', len(hecl_str))) + writebuf(hecl_str.encode()) + writebuf(struct.pack('I', len(texs))) + for tex in texs: + writebuf(struct.pack('I', len(tex))) + writebuf(tex.encode()) + + prop_count = 0 + for prop in mat.items(): + if isinstance(prop[1], int): + prop_count += 1 + writebuf(struct.pack('I', prop_count)) + prop_count = 0 + for prop in mat.items(): + if isinstance(prop[1], int): + writebuf(struct.pack('I', len(prop[0]))) + writebuf(prop[0].encode()) + writebuf(struct.pack('i', prop[1])) # Takes a Blender 'Mesh' object (not the datablock) # and performs a one-shot conversion process to HMDL; packaging @@ -126,15 +148,7 @@ def cook(writebuf, mesh_obj, max_skin_banks, max_octant_length=None): found = False for mat in bpy.data.materials: if mat.name.endswith('_%u_%u' % (grp_idx, mat_idx)): - hecl_str, texs = HMDLShader.shader(mat, mesh_obj) - writebuf(struct.pack('I', len(mat.name))) - writebuf(mat.name.encode()) - writebuf(struct.pack('I', len(hecl_str))) - writebuf(hecl_str.encode()) - writebuf(struct.pack('I', len(texs))) - for tex in texs: - writebuf(struct.pack('I', len(tex))) - writebuf(tex.encode()) + write_out_material(writebuf, mat, mesh_obj) found = True break if not found: @@ -143,15 +157,7 @@ def cook(writebuf, mesh_obj, max_skin_banks, max_octant_length=None): writebuf(struct.pack('II', 1, len(sorted_material_idxs))) for mat_idx in sorted_material_idxs: mat = mesh_obj.data.materials[mat_idx] - hecl_str, texs = HMDLShader.shader(mat, mesh_obj) - writebuf(struct.pack('I', len(mat.name))) - writebuf(mat.name.encode()) - writebuf(struct.pack('I', len(hecl_str))) - writebuf(hecl_str.encode()) - writebuf(struct.pack('I', len(texs))) - for tex in texs: - writebuf(struct.pack('I', len(tex))) - writebuf(tex.encode()) + write_out_material(writebuf, mat, mesh_obj) # Output vert pool vert_pool.write_out(writebuf, mesh_obj.vertex_groups) diff --git a/hecl/include/HECL/Backend/GX.hpp b/hecl/include/HECL/Backend/GX.hpp index f95adfd0a..26160a835 100644 --- a/hecl/include/HECL/Backend/GX.hpp +++ b/hecl/include/HECL/Backend/GX.hpp @@ -2,7 +2,7 @@ #define HECLBACKEND_GX_HPP #include "Backend.hpp" -#include +#include #include #include #include @@ -14,6 +14,14 @@ namespace Backend struct GX : IBackend { + enum AttrType + { + NONE, + DIRECT, + INDEX8, + INDEX16 + }; + enum TevOp { TEV_ADD = 0, @@ -30,6 +38,36 @@ struct GX : IBackend TEV_COMP_A8_EQ = TEV_COMP_RGB8_EQ // for alpha channel }; + enum TevBias + { + TB_ZERO = 0, + TB_ADDHALF = 1, + TB_SUBHALF = 2, + }; + + enum TevScale + { + CS_SCALE_1 = 0, + CS_SCALE_2 = 1, + CS_SCALE_4 = 2, + CS_DIVIDE_2 = 3 + }; + + enum TexGenType + { + TG_MTX3x4 = 0, + TG_MTX2x4, + TG_BUMP0, + TG_BUMP1, + TG_BUMP2, + TG_BUMP3, + TG_BUMP4, + TG_BUMP5, + TG_BUMP6, + TG_BUMP7, + TG_SRTG + }; + enum TevRegID { TEVPREV = 0, @@ -189,6 +227,56 @@ struct GX : IBackend IDENTITY = 60 }; + enum PTTexMtx + { + PTTEXMTX0 = 64, + PTTEXMTX1 = 67, + PTTEXMTX2 = 70, + PTTEXMTX3 = 73, + PTTEXMTX4 = 76, + PTTEXMTX5 = 79, + PTTEXMTX6 = 82, + PTTEXMTX7 = 85, + PTTEXMTX8 = 88, + PTTEXMTX9 = 91, + PTTEXMTX10 = 94, + PTTEXMTX11 = 97, + PTTEXMTX12 = 100, + PTTEXMTX13 = 103, + PTTEXMTX14 = 106, + PTTEXMTX15 = 109, + PTTEXMTX16 = 112, + PTTEXMTX17 = 115, + PTTEXMTX18 = 118, + PTTEXMTX19 = 121, + PTIDENTITY = 125 + }; + + enum DiffuseFn + { + DF_NONE = 0, + DF_SIGN, + DF_CLAMP + }; + + enum AttnFn + { + AF_SPEC = 0, + AF_SPOT = 1, + AF_NONE + }; + + enum Primitive + { + POINTS = 0xb8, + LINES = 0xa8, + LINESTRIP = 0xb0, + TRIANGLES = 0x90, + TRIANGLESTRIP = 0x98, + TRIANGLEFAN = 0xa0, + QUADS = 0x80 + }; + struct TexCoordGen { TexGenSrc m_src = TG_TEX0; @@ -207,15 +295,18 @@ struct GX : IBackend struct TEVStage { - TevOp m_op = TEV_ADD; + TevOp m_cop = TEV_ADD; + TevOp m_aop = TEV_ADD; TevColorArg m_color[4] = {CC_ZERO, CC_ZERO, CC_ZERO, CC_ZERO}; TevAlphaArg m_alpha[4] = {CA_ZERO, CA_ZERO, CA_ZERO, CA_ZERO}; TevKColorSel m_kColor = TEV_KCSEL_1; TevKAlphaSel m_kAlpha = TEV_KASEL_1; - TevRegID m_regOut = TEVPREV; + TevRegID m_cRegOut = TEVPREV; + TevRegID m_aRegOut = TEVPREV; int m_lazyCInIdx = -1; int m_lazyAInIdx = -1; - int m_lazyOutIdx = -1; + int m_lazyCOutIdx = -1; + int m_lazyAOutIdx = -1; int m_texMapIdx = -1; int m_texGenIdx = -1; @@ -240,6 +331,9 @@ struct GX : IBackend int m_cRegMask = 0; int m_cRegLazy = 0; + int m_aRegMask = 0; + int m_aRegLazy = 0; + int pickCLazy(Diagnostics& diag, const SourceLocation& loc, int stageIdx) const { int regMask = m_cRegMask; @@ -248,17 +342,11 @@ struct GX : IBackend const TEVStage& stage = m_tevs[i]; for (int c=0 ; c<4 ; ++c) { - if (stage.m_color[c] == CC_C0 || - stage.m_color[c] == CC_A0 || - stage.m_alpha[c] == CA_A0) + if (stage.m_color[c] == CC_C0) regMask |= 1; - if (stage.m_color[c] == CC_C1 || - stage.m_color[c] == CC_A1 || - stage.m_alpha[c] == CA_A1) + if (stage.m_color[c] == CC_C1) regMask |= 2; - if (stage.m_color[c] == CC_C2 || - stage.m_color[c] == CC_A2 || - stage.m_alpha[c] == CA_A2) + if (stage.m_color[c] == CC_C2) regMask |= 4; } } @@ -271,6 +359,34 @@ struct GX : IBackend return -1; } + int pickALazy(Diagnostics& diag, const SourceLocation& loc, int stageIdx) const + { + int regMask = m_aRegMask; + for (int i=stageIdx+1 ; i { union { @@ -315,6 +431,11 @@ struct GX : IBackend bool operator!=(const Color& other) const {return num != other.num;} uint8_t operator[](size_t idx) const {return color[idx];} uint8_t& operator[](size_t idx) {return color[idx];} + + void read(Athena::io::IStreamReader& reader) + {reader.readUBytesToBuf(&num, 4);} + void write(Athena::io::IStreamWriter& writer) const + {writer.writeUBytes(reinterpret_cast(&num), 4);} }; unsigned m_kcolorCount = 0; Color m_kcolors[4]; diff --git a/hecl/lib/Backend/GX.cpp b/hecl/lib/Backend/GX.cpp index 53b1256e9..b152adf92 100644 --- a/hecl/lib/Backend/GX.cpp +++ b/hecl/lib/Backend/GX.cpp @@ -132,7 +132,10 @@ GX::TraceResult GX::RecursiveTraceColor(const IR& ir, Diagnostics& diag, const I { const IR::Instruction& idxInst = inst.getChildInst(ir, 0); unsigned idx = unsigned(idxInst.getImmVec().vec[0]); - m_cRegMask |= 1 << idx; + if (swizzleAlpha) + m_aRegMask |= 1 << idx; + else + m_cRegMask |= 1 << idx; return TraceResult(TevColorArg((swizzleAlpha ? CC_A0 : CC_C0) + idx * 2)); } else if (!name.compare("Lighting")) @@ -207,10 +210,10 @@ GX::TraceResult GX::RecursiveTraceColor(const IR& ir, Diagnostics& diag, const I TEVStage* b = bTrace.tevStage; if (b->m_prev != a) { - a->m_regOut = TEVLAZY; + a->m_cRegOut = TEVLAZY; b->m_color[3] = CC_LAZY; b->m_lazyCInIdx = m_cRegLazy; - a->m_lazyOutIdx = m_cRegLazy++; + a->m_lazyCOutIdx = m_cRegLazy++; } else if (b == &m_tevs[m_tevCount-1] && a->m_texMapIdx == b->m_texMapIdx && a->m_texGenIdx == b->m_texGenIdx && @@ -255,14 +258,14 @@ GX::TraceResult GX::RecursiveTraceColor(const IR& ir, Diagnostics& diag, const I TEVStage* b = bTrace.tevStage; if (b->m_prev != a) { - a->m_regOut = TEVLAZY; + a->m_cRegOut = TEVLAZY; b->m_color[3] = CC_LAZY; b->m_lazyCInIdx = m_cRegLazy; - a->m_lazyOutIdx = m_cRegLazy++; + a->m_lazyCOutIdx = m_cRegLazy++; } else b->m_color[3] = CC_CPREV; - b->m_op = TEV_SUB; + b->m_cop = TEV_SUB; return TraceResult(b); } else if (aTrace.type == TraceResult::TraceTEVStage && @@ -273,7 +276,7 @@ GX::TraceResult GX::RecursiveTraceColor(const IR& ir, Diagnostics& diag, const I diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for subtract combine"); a->m_color[3] = bTrace.tevColorArg; a->m_kColor = newKColor; - a->m_op = TEV_SUB; + a->m_cop = TEV_SUB; return TraceResult(a); } break; @@ -289,10 +292,10 @@ GX::TraceResult GX::RecursiveTraceColor(const IR& ir, Diagnostics& diag, const I diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for multiply combine"); if (b->m_prev != a) { - a->m_regOut = TEVLAZY; + a->m_cRegOut = TEVLAZY; b->m_color[2] = CC_LAZY; b->m_lazyCInIdx = m_cRegLazy; - a->m_lazyOutIdx = m_cRegLazy++; + a->m_lazyCOutIdx = m_cRegLazy++; } else b->m_color[2] = CC_CPREV; @@ -316,7 +319,7 @@ GX::TraceResult GX::RecursiveTraceColor(const IR& ir, Diagnostics& diag, const I TEVStage* a = aTrace.tevStage; if (a->m_color[1] != CC_ZERO) { - if (a->m_regOut != TEVPREV) + if (a->m_cRegOut != TEVPREV) diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for multiply combine"); TEVStage& stage = addTEVStage(diag, inst.m_loc); stage.m_color[1] = CC_CPREV; @@ -336,7 +339,7 @@ GX::TraceResult GX::RecursiveTraceColor(const IR& ir, Diagnostics& diag, const I TEVStage* b = bTrace.tevStage; if (b->m_color[1] != CC_ZERO) { - if (b->m_regOut != TEVPREV) + if (b->m_cRegOut != TEVPREV) diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for multiply combine"); TEVStage& stage = addTEVStage(diag, inst.m_loc); stage.m_color[1] = aTrace.tevColorArg; @@ -360,8 +363,8 @@ GX::TraceResult GX::RecursiveTraceColor(const IR& ir, Diagnostics& diag, const I } case IR::OpSwizzle: { - if (inst.m_swizzle.m_idxs[0] == 3 && inst.m_swizzle.m_idxs[1] == -1 && - inst.m_swizzle.m_idxs[2] == -1 && inst.m_swizzle.m_idxs[3] == -1) + if (inst.m_swizzle.m_idxs[0] == 3 && inst.m_swizzle.m_idxs[1] == 3 && + inst.m_swizzle.m_idxs[2] == 3 && inst.m_swizzle.m_idxs[3] == -1) { const IR::Instruction& cInst = inst.getChildInst(ir, 0); if (cInst.m_op != IR::OpCall) @@ -428,7 +431,7 @@ GX::TraceResult GX::RecursiveTraceAlpha(const IR& ir, Diagnostics& diag, const I { const IR::Instruction& idxInst = inst.getChildInst(ir, 0); unsigned idx = unsigned(idxInst.getImmVec().vec[0]); - m_cRegMask |= 1 << idx; + m_aRegMask |= 1 << idx; return TraceResult(TevAlphaArg(CA_A0 + idx)); } else if (!name.compare("Lighting")) @@ -493,14 +496,14 @@ GX::TraceResult GX::RecursiveTraceAlpha(const IR& ir, Diagnostics& diag, const I TEVStage* b = bTrace.tevStage; if (b->m_prev != a) { - a->m_regOut = TEVLAZY; + a->m_aRegOut = TEVLAZY; b->m_alpha[3] = CA_LAZY; - if (a->m_lazyOutIdx != -1) - b->m_lazyAInIdx = a->m_lazyOutIdx; + if (a->m_lazyAOutIdx != -1) + b->m_lazyAInIdx = a->m_lazyAOutIdx; else { - b->m_lazyAInIdx = m_cRegLazy; - a->m_lazyOutIdx = m_cRegLazy++; + b->m_lazyAInIdx = m_aRegLazy; + a->m_lazyAOutIdx = m_aRegLazy++; } } else @@ -536,18 +539,18 @@ GX::TraceResult GX::RecursiveTraceAlpha(const IR& ir, Diagnostics& diag, const I { TEVStage* a = aTrace.tevStage; TEVStage* b = bTrace.tevStage; - if (b->m_op != TEV_SUB) + if (b->m_aop != TEV_SUB) diag.reportBackendErr(inst.m_loc, "unable to integrate alpha subtraction into stage chain"); if (b->m_prev != a) { - a->m_regOut = TEVLAZY; + a->m_aRegOut = TEVLAZY; b->m_alpha[3] = CA_LAZY; - if (a->m_lazyOutIdx != -1) - b->m_lazyAInIdx = a->m_lazyOutIdx; + if (a->m_lazyAOutIdx != -1) + b->m_lazyAInIdx = a->m_lazyAOutIdx; else { - b->m_lazyAInIdx = m_cRegLazy; - a->m_lazyOutIdx = m_cRegLazy++; + b->m_lazyAInIdx = m_aRegLazy; + a->m_lazyAOutIdx = m_aRegLazy++; } } else @@ -558,7 +561,7 @@ GX::TraceResult GX::RecursiveTraceAlpha(const IR& ir, Diagnostics& diag, const I bTrace.type == TraceResult::TraceTEVAlphaArg) { TEVStage* a = aTrace.tevStage; - if (a->m_op != TEV_SUB) + if (a->m_aop != TEV_SUB) diag.reportBackendErr(inst.m_loc, "unable to integrate alpha subtraction into stage chain"); if (a->m_alpha[3] != CA_ZERO) diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for add combine"); @@ -579,10 +582,10 @@ GX::TraceResult GX::RecursiveTraceAlpha(const IR& ir, Diagnostics& diag, const I diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for multiply combine"); if (b->m_prev != a) { - a->m_regOut = TEVLAZY; + a->m_aRegOut = TEVLAZY; b->m_alpha[2] = CA_LAZY; - b->m_lazyAInIdx = m_cRegLazy; - a->m_lazyOutIdx = m_cRegLazy++; + b->m_lazyAInIdx = m_aRegLazy; + a->m_lazyAOutIdx = m_aRegLazy++; } else b->m_alpha[2] = CA_APREV; @@ -607,7 +610,7 @@ GX::TraceResult GX::RecursiveTraceAlpha(const IR& ir, Diagnostics& diag, const I TEVStage* a = aTrace.tevStage; if (a->m_alpha[1] != CA_ZERO) { - if (a->m_regOut != TEVPREV) + if (a->m_aRegOut != TEVPREV) diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for multiply combine"); TEVStage& stage = addTEVStage(diag, inst.m_loc); stage.m_alpha[1] = CA_APREV; @@ -627,7 +630,7 @@ GX::TraceResult GX::RecursiveTraceAlpha(const IR& ir, Diagnostics& diag, const I TEVStage* b = bTrace.tevStage; if (b->m_alpha[1] != CA_ZERO) { - if (b->m_regOut != TEVPREV) + if (b->m_aRegOut != TEVPREV) diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for multiply combine"); TEVStage& stage = addTEVStage(diag, inst.m_loc); stage.m_alpha[1] = aTrace.tevAlphaArg; @@ -651,8 +654,8 @@ GX::TraceResult GX::RecursiveTraceAlpha(const IR& ir, Diagnostics& diag, const I } case IR::OpSwizzle: { - if (inst.m_swizzle.m_idxs[0] == 3 && inst.m_swizzle.m_idxs[1] == -1 && - inst.m_swizzle.m_idxs[2] == -1 && inst.m_swizzle.m_idxs[3] == -1) + if (inst.m_swizzle.m_idxs[0] == 3 && inst.m_swizzle.m_idxs[1] == 3 && + inst.m_swizzle.m_idxs[2] == 3 && inst.m_swizzle.m_idxs[3] == -1) { const IR::Instruction& cInst = inst.getChildInst(ir, 0); if (cInst.m_op != IR::OpCall) @@ -671,12 +674,16 @@ GX::TraceResult GX::RecursiveTraceAlpha(const IR& ir, Diagnostics& diag, const I void GX::reset(const IR& ir, Diagnostics& diag) { + diag.setBackend("GX"); + m_tevCount = 0; m_tcgCount = 0; m_texMtxCount = 0; m_kcolorCount = 0; m_cRegMask = 0; m_cRegLazy = 0; + m_aRegMask = 0; + m_aRegLazy = 0; m_alphaTraceStage = -1; /* Final instruction is the root call by hecl convention */ @@ -730,18 +737,28 @@ void GX::reset(const IR& ir, Diagnostics& diag) for (int i=0 ; i