From 3129d67fc17591b9f4fc010649ee4074e9003dbe Mon Sep 17 00:00:00 2001 From: Perfare Date: Tue, 6 Jul 2021 12:45:24 +0800 Subject: [PATCH] Improve ShaderConverter --- AssetStudioUtility/ShaderConverter.cs | 388 ++++++++++++++++++++++---- 1 file changed, 328 insertions(+), 60 deletions(-) diff --git a/AssetStudioUtility/ShaderConverter.cs b/AssetStudioUtility/ShaderConverter.cs index 6f65ecf..4849e00 100644 --- a/AssetStudioUtility/ShaderConverter.cs +++ b/AssetStudioUtility/ShaderConverter.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.IO; using System.Linq; using System.Text; @@ -229,7 +230,7 @@ namespace AssetStudio sb.Append(ConvertSerializedTagMap(m_State.m_Tags, 2)); - sb.Append(ConvertSerializedShaderRTBlendState(m_State.rtBlend)); + sb.Append(ConvertSerializedShaderRTBlendState(m_State.rtBlend, m_State.rtSeparateBlend)); if (m_State.alphaToMask.val > 0f) { @@ -300,9 +301,111 @@ namespace AssetStudio sb.Append($" Offset {m_State.offsetFactor.val}, {m_State.offsetUnits.val}\n"); } - //TODO Stencil + if (m_State.stencilRef.val != 0f || + m_State.stencilReadMask.val != 255f || + m_State.stencilWriteMask.val != 255f || + m_State.stencilOp.pass.val != 0f || + m_State.stencilOp.fail.val != 0f || + m_State.stencilOp.zFail.val != 0f || + m_State.stencilOp.comp.val != 8f || + m_State.stencilOpFront.pass.val != 0f || + m_State.stencilOpFront.fail.val != 0f || + m_State.stencilOpFront.zFail.val != 0f || + m_State.stencilOpFront.comp.val != 8f || + m_State.stencilOpBack.pass.val != 0f || + m_State.stencilOpBack.fail.val != 0f || + m_State.stencilOpBack.zFail.val != 0f || + m_State.stencilOpBack.comp.val != 8f) + { + sb.Append(" Stencil {\n"); + if (m_State.stencilRef.val != 0f) + { + sb.Append($" Ref {m_State.stencilRef.val}\n"); + } + if (m_State.stencilReadMask.val != 255f) + { + sb.Append($" ReadMask {m_State.stencilReadMask.val}\n"); + } + if (m_State.stencilWriteMask.val != 255f) + { + sb.Append($" WriteMask {m_State.stencilWriteMask.val}\n"); + } + if (m_State.stencilOp.pass.val != 0f || + m_State.stencilOp.fail.val != 0f || + m_State.stencilOp.zFail.val != 0f || + m_State.stencilOp.comp.val != 8f) + { + sb.Append(ConvertSerializedStencilOp(m_State.stencilOp, "")); + } + if (m_State.stencilOpFront.pass.val != 0f || + m_State.stencilOpFront.fail.val != 0f || + m_State.stencilOpFront.zFail.val != 0f || + m_State.stencilOpFront.comp.val != 8f) + { + sb.Append(ConvertSerializedStencilOp(m_State.stencilOpFront, "Front")); + } + if (m_State.stencilOpBack.pass.val != 0f || + m_State.stencilOpBack.fail.val != 0f || + m_State.stencilOpBack.zFail.val != 0f || + m_State.stencilOpBack.comp.val != 8f) + { + sb.Append(ConvertSerializedStencilOp(m_State.stencilOpBack, "Back")); + } + sb.Append(" }\n"); + } - //TODO Fog + if (m_State.fogMode != FogMode.kFogUnknown || + m_State.fogColor.x.val != 0f || + m_State.fogColor.y.val != 0f || + m_State.fogColor.z.val != 0f || + m_State.fogColor.w.val != 0f || + m_State.fogDensity.val != 0f || + m_State.fogStart.val != 0f || + m_State.fogEnd.val != 0f) + { + sb.Append(" Fog {\n"); + if (m_State.fogMode != FogMode.kFogUnknown) + { + sb.Append(" Mode "); + switch (m_State.fogMode) + { + case FogMode.kFogDisabled: + sb.Append("Off"); + break; + case FogMode.kFogLinear: + sb.Append("Linear"); + break; + case FogMode.kFogExp: + sb.Append("Exp"); + break; + case FogMode.kFogExp2: + sb.Append("Exp2"); + break; + } + sb.Append("\n"); + } + if (m_State.fogColor.x.val != 0f || + m_State.fogColor.y.val != 0f || + m_State.fogColor.z.val != 0f || + m_State.fogColor.w.val != 0f) + { + sb.AppendFormat(" Color ({0},{1},{2},{3})\n", + m_State.fogColor.x.val.ToString(CultureInfo.InvariantCulture), + m_State.fogColor.y.val.ToString(CultureInfo.InvariantCulture), + m_State.fogColor.z.val.ToString(CultureInfo.InvariantCulture), + m_State.fogColor.w.val.ToString(CultureInfo.InvariantCulture)); + } + if (m_State.fogDensity.val != 0f) + { + sb.Append($" Density {m_State.fogDensity.val.ToString(CultureInfo.InvariantCulture)}\n"); + } + if (m_State.fogStart.val != 0f || + m_State.fogEnd.val != 0f) + { + sb.Append($" Range {m_State.fogStart.val.ToString(CultureInfo.InvariantCulture)}, {m_State.fogEnd.val.ToString(CultureInfo.InvariantCulture)}\n"); + } + sb.Append(" }\n"); + } if (m_State.lighting) { @@ -314,27 +417,220 @@ namespace AssetStudio return sb.ToString(); } - private static string ConvertSerializedShaderRTBlendState(SerializedShaderRTBlendState[] rtBlend) + private static string ConvertSerializedStencilOp(SerializedStencilOp stencilOp, string suffix) { - //TODO Blend var sb = new StringBuilder(); - /*for (var i = 0; i < rtBlend.Length; i++) + sb.Append($" Comp{suffix} {ConvertStencilComp(stencilOp.comp)}\n"); + sb.Append($" Pass{suffix} {ConvertStencilOp(stencilOp.pass)}\n"); + sb.Append($" Fail{suffix} {ConvertStencilOp(stencilOp.fail)}\n"); + sb.Append($" ZFail{suffix} {ConvertStencilOp(stencilOp.zFail)}\n"); + return sb.ToString(); + } + + private static string ConvertStencilOp(SerializedShaderFloatValue op) + { + switch (op.val) + { + case 0f: + default: + return "Keep"; + case 1f: + return "Zero"; + case 2f: + return "Replace"; + case 3f: + return "IncrSat"; + case 4f: + return "DecrSat"; + case 5f: + return "Invert"; + case 6f: + return "IncrWrap"; + case 7f: + return "DecrWrap"; + } + } + + private static string ConvertStencilComp(SerializedShaderFloatValue comp) + { + switch (comp.val) + { + case 0f: + return "Disabled"; + case 1f: + return "Never"; + case 2f: + return "Less"; + case 3f: + return "Equal"; + case 4f: + return "LEqual"; + case 5f: + return "Greater"; + case 6f: + return "NotEqual"; + case 7f: + return "GEqual"; + case 8f: + default: + return "Always"; + } + } + + private static string ConvertSerializedShaderRTBlendState(SerializedShaderRTBlendState[] rtBlend, bool rtSeparateBlend) + { + var sb = new StringBuilder(); + for (var i = 0; i < rtBlend.Length; i++) { var blend = rtBlend[i]; - if (!blend.srcBlend.val.Equals(1f) || - !blend.destBlend.val.Equals(0f) || - !blend.srcBlendAlpha.val.Equals(1f) || - !blend.destBlendAlpha.val.Equals(0f)) + if (blend.srcBlend.val != 1f || + blend.destBlend.val != 0f || + blend.srcBlendAlpha.val != 1f || + blend.destBlendAlpha.val != 0f) { sb.Append(" Blend "); - sb.Append($"{i} "); - sb.Append('\n'); + if (i != 0 || rtSeparateBlend) + { + sb.Append($"{i} "); + } + sb.Append($"{ConvertBlendFactor(blend.srcBlend)} {ConvertBlendFactor(blend.destBlend)}"); + if (blend.srcBlendAlpha.val != 1f || + blend.destBlendAlpha.val != 0f) + { + sb.Append($", {ConvertBlendFactor(blend.srcBlendAlpha)} {ConvertBlendFactor(blend.destBlendAlpha)}"); + } + sb.Append("\n"); } - }*/ + if (blend.blendOp.val != 0f || + blend.blendOpAlpha.val != 0f) + { + sb.Append(" BlendOp "); + if (i != 0 || rtSeparateBlend) + { + sb.Append($"{i} "); + } + sb.Append(ConvertBlendOp(blend.blendOp)); + if (blend.blendOpAlpha.val != 0f) + { + sb.Append($", {ConvertBlendOp(blend.blendOpAlpha)}"); + } + sb.Append("\n"); + } + + var val = (int)blend.colMask.val; + if (val != 0xf) + { + sb.Append(" ColorMask "); + if (val == 0) + { + sb.Append(0); + } + else + { + if ((val & 0x2) != 0) + { + sb.Append("R"); + } + if ((val & 0x4) != 0) + { + sb.Append("G"); + } + if ((val & 0x8) != 0) + { + sb.Append("B"); + } + if ((val & 0x1) != 0) + { + sb.Append("A"); + } + } + sb.Append($" {i}\n"); + } + } return sb.ToString(); } + private static string ConvertBlendOp(SerializedShaderFloatValue op) + { + switch (op.val) + { + case 0f: + default: + return "Add"; + case 1f: + return "Sub"; + case 2f: + return "RevSub"; + case 3f: + return "Min"; + case 4f: + return "Max"; + case 5f: + return "LogicalClear"; + case 6f: + return "LogicalSet"; + case 7f: + return "LogicalCopy"; + case 8f: + return "LogicalCopyInverted"; + case 9f: + return "LogicalNoop"; + case 10f: + return "LogicalInvert"; + case 11f: + return "LogicalAnd"; + case 12f: + return "LogicalNand"; + case 13f: + return "LogicalOr"; + case 14f: + return "LogicalNor"; + case 15f: + return "LogicalXor"; + case 16f: + return "LogicalEquiv"; + case 17f: + return "LogicalAndReverse"; + case 18f: + return "LogicalAndInverted"; + case 19f: + return "LogicalOrReverse"; + case 20f: + return "LogicalOrInverted"; + } + } + + private static string ConvertBlendFactor(SerializedShaderFloatValue factor) + { + switch (factor.val) + { + case 0f: + return "Zero"; + case 1f: + default: + return "One"; + case 2f: + return "DstColor"; + case 3f: + return "SrcColor"; + case 4f: + return "OneMinusDstColor"; + case 5f: + return "SrcAlpha"; + case 6f: + return "OneMinusSrcColor"; + case 7f: + return "DstAlpha"; + case 8f: + return "OneMinusDstAlpha"; + case 9f: + return "SrcAlphaSaturate"; + case 10f: + return "OneMinusSrcAlpha"; + } + } + private static string ConvertSerializedTagMap(SerializedTagMap m_Tags, int intent) { var sb = new StringBuilder(); @@ -443,12 +739,18 @@ namespace AssetStudio || programType == ShaderGpuProgramType.kShaderGpuProgramDX9PixelSM20 || programType == ShaderGpuProgramType.kShaderGpuProgramDX9PixelSM30; case ShaderCompilerPlatform.kShaderCompPlatformXbox360: - return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS; case ShaderCompilerPlatform.kShaderCompPlatformPS3: + case ShaderCompilerPlatform.kShaderCompPlatformPSP2: + case ShaderCompilerPlatform.kShaderCompPlatformPS4: + case ShaderCompilerPlatform.kShaderCompPlatformXboxOne: + case ShaderCompilerPlatform.kShaderCompPlatformN3DS: + case ShaderCompilerPlatform.kShaderCompPlatformWiiU: + case ShaderCompilerPlatform.kShaderCompPlatformSwitch: + case ShaderCompilerPlatform.kShaderCompPlatformXboxOneD3D12: + case ShaderCompilerPlatform.kShaderCompPlatformGameCoreXboxOne: + case ShaderCompilerPlatform.kShaderCompPlatformGameCoreScarlett: + case ShaderCompilerPlatform.kShaderCompPlatformPS5: + case ShaderCompilerPlatform.kShaderCompPlatformPS5NGGC: return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS @@ -476,24 +778,6 @@ namespace AssetStudio return programType == ShaderGpuProgramType.kShaderGpuProgramGLES31AEP || programType == ShaderGpuProgramType.kShaderGpuProgramGLES31 || programType == ShaderGpuProgramType.kShaderGpuProgramGLES3; - case ShaderCompilerPlatform.kShaderCompPlatformPSP2: - return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS; - case ShaderCompilerPlatform.kShaderCompPlatformPS4: - return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS; - case ShaderCompilerPlatform.kShaderCompPlatformXboxOne: - return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS; case ShaderCompilerPlatform.kShaderCompPlatformPSM: //Unknown throw new NotSupportedException(); case ShaderCompilerPlatform.kShaderCompPlatformMetal: @@ -503,32 +787,8 @@ namespace AssetStudio return programType == ShaderGpuProgramType.kShaderGpuProgramGLCore32 || programType == ShaderGpuProgramType.kShaderGpuProgramGLCore41 || programType == ShaderGpuProgramType.kShaderGpuProgramGLCore43; - case ShaderCompilerPlatform.kShaderCompPlatformN3DS: - return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS; - case ShaderCompilerPlatform.kShaderCompPlatformWiiU: - return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS; case ShaderCompilerPlatform.kShaderCompPlatformVulkan: return programType == ShaderGpuProgramType.kShaderGpuProgramSPIRV; - case ShaderCompilerPlatform.kShaderCompPlatformSwitch: - return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS; - case ShaderCompilerPlatform.kShaderCompPlatformXboxOneD3D12: - return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS - || programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS; default: throw new NotSupportedException(); } @@ -580,6 +840,14 @@ namespace AssetStudio return "switch"; case ShaderCompilerPlatform.kShaderCompPlatformXboxOneD3D12: return "xboxone_d3d12"; + case ShaderCompilerPlatform.kShaderCompPlatformGameCoreXboxOne: + return "xboxone"; + case ShaderCompilerPlatform.kShaderCompPlatformGameCoreScarlett: + return "xbox_scarlett"; + case ShaderCompilerPlatform.kShaderCompPlatformPS5: + return "ps5"; + case ShaderCompilerPlatform.kShaderCompPlatformPS5NGGC: + return "ps5_nggc"; default: return "unknown"; }