improve Shader export

This commit is contained in:
Perfare 2018-11-14 12:20:11 +08:00
parent e7c5976f7c
commit a89fd049f1
9 changed files with 963 additions and 30 deletions

View File

@ -85,6 +85,14 @@
<HintPath>Libraries\OpenTK.GLControl.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SharpDX">
<HintPath>Libraries\SharpDX.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SharpDX.D3DCompiler">
<HintPath>Libraries\SharpDX.D3DCompiler.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SharpDX.Mathematics">
<HintPath>Libraries\SharpDX.Mathematics.dll</HintPath>
<Private>False</Private>
@ -198,6 +206,7 @@
<Compile Include="StudioClasses\BinaryWriterExtensions.cs" />
<Compile Include="StudioClasses\BuildTarget.cs" />
<Compile Include="StudioClasses\ClassIDType.cs" />
<Compile Include="StudioClasses\ShaderConverter.cs" />
<Compile Include="StudioClasses\TypeTreeNode.cs" />
<Compile Include="StudioClasses\TypeTreeHelper.cs" />
<Compile Include="StudioClasses\ResourcesHelper.cs" />

View File

@ -816,11 +816,9 @@ namespace AssetStudio
}
case ClassIDType.Shader:
{
Shader m_TextAsset = new Shader(reader);
string m_Script_Text = Encoding.UTF8.GetString(m_TextAsset.m_Script);
m_Script_Text = Regex.Replace(m_Script_Text, "(?<!\r)\n", "\r\n");
m_Script_Text = m_Script_Text.Replace("\0", "\\0");
textPreviewBox.Text = m_Script_Text;
var m_Shader = new Shader(reader);
var str = ShaderConverter.Convert(m_Shader);
textPreviewBox.Text = str == null ? "Serialized Shader can't be read" : str.Replace("\n", "\r\n");
textPreviewBox.Visible = true;
break;
}

View File

@ -1,40 +1,725 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web.Script.Serialization;
using Lz4;
namespace AssetStudio
{
public sealed class Shader : NamedObject
public class StructParameter
{
public List<MatrixParameter> m_MatrixParams { get; set; }
public List<VectorParameter> m_VectorParams { get; set; }
public StructParameter(BinaryReader reader)
{
var m_NameIndex = reader.ReadInt32();
var m_Index = reader.ReadInt32();
var m_ArraySize = reader.ReadInt32();
var m_StructSize = reader.ReadInt32();
int numVectorParams = reader.ReadInt32();
m_VectorParams = new List<VectorParameter>(numVectorParams);
for (int i = 0; i < numVectorParams; i++)
{
m_VectorParams.Add(new VectorParameter(reader));
}
int numMatrixParams = reader.ReadInt32();
m_MatrixParams = new List<MatrixParameter>(numMatrixParams);
for (int i = 0; i < numMatrixParams; i++)
{
m_MatrixParams.Add(new MatrixParameter(reader));
}
}
}
public class SamplerParameter
{
public uint sampler { get; set; }
public int bindPoint { get; set; }
public SamplerParameter(BinaryReader reader)
{
sampler = reader.ReadUInt32();
bindPoint = reader.ReadInt32();
}
}
public class SerializedTextureProperty
{
public string m_DefaultName { get; set; }
public int m_TexDim { get; set; }
public SerializedTextureProperty(BinaryReader reader)
{
m_DefaultName = reader.ReadAlignedString();
m_TexDim = reader.ReadInt32();
}
}
public class SerializedProperty
{
public string m_Name { get; set; }
public string m_Description { get; set; }
public List<string> m_Attributes { get; set; }
public int m_Type { get; set; }
public uint m_Flags { get; set; }
public List<float> m_DefValue { get; set; }
public SerializedTextureProperty m_DefTexture { get; set; }
public SerializedProperty(BinaryReader reader)
{
m_Name = reader.ReadAlignedString();
m_Description = reader.ReadAlignedString();
int numAttributes = reader.ReadInt32();
m_Attributes = new List<string>(numAttributes);
for (int i = 0; i < numAttributes; i++)
{
m_Attributes.Add(reader.ReadAlignedString());
}
m_Type = reader.ReadInt32();
m_Flags = reader.ReadUInt32();
int numValues = 4;
m_DefValue = new List<float>(numValues);
for (int i = 0; i < numValues; i++)
{
m_DefValue.Add(reader.ReadSingle());
}
m_DefTexture = new SerializedTextureProperty(reader);
}
}
public class SerializedProperties
{
public List<SerializedProperty> m_Props { get; set; }
public SerializedProperties(BinaryReader reader)
{
int numProps = reader.ReadInt32();
m_Props = new List<SerializedProperty>(numProps);
for (int i = 0; i < numProps; i++)
{
m_Props.Add(new SerializedProperty(reader));
}
}
}
public class SerializedShaderFloatValue
{
public float val { get; set; }
public string name { get; set; }
public SerializedShaderFloatValue(BinaryReader reader)
{
val = reader.ReadSingle();
name = reader.ReadAlignedString();
}
}
public class SerializedShaderRTBlendState
{
public SerializedShaderFloatValue srcBlend { get; set; }
public SerializedShaderFloatValue destBlend { get; set; }
public SerializedShaderFloatValue srcBlendAlpha { get; set; }
public SerializedShaderFloatValue destBlendAlpha { get; set; }
public SerializedShaderFloatValue blendOp { get; set; }
public SerializedShaderFloatValue blendOpAlpha { get; set; }
public SerializedShaderFloatValue colMask { get; set; }
public SerializedShaderRTBlendState(BinaryReader reader)
{
srcBlend = new SerializedShaderFloatValue(reader);
destBlend = new SerializedShaderFloatValue(reader);
srcBlendAlpha = new SerializedShaderFloatValue(reader);
destBlendAlpha = new SerializedShaderFloatValue(reader);
blendOp = new SerializedShaderFloatValue(reader);
blendOpAlpha = new SerializedShaderFloatValue(reader);
colMask = new SerializedShaderFloatValue(reader);
}
}
public class SerializedStencilOp
{
public SerializedShaderFloatValue pass { get; set; }
public SerializedShaderFloatValue fail { get; set; }
public SerializedShaderFloatValue zFail { get; set; }
public SerializedShaderFloatValue comp { get; set; }
public SerializedStencilOp(BinaryReader reader)
{
pass = new SerializedShaderFloatValue(reader);
fail = new SerializedShaderFloatValue(reader);
zFail = new SerializedShaderFloatValue(reader);
comp = new SerializedShaderFloatValue(reader);
}
}
public class SerializedShaderVectorValue
{
public SerializedShaderFloatValue x { get; set; }
public SerializedShaderFloatValue y { get; set; }
public SerializedShaderFloatValue z { get; set; }
public SerializedShaderFloatValue w { get; set; }
public string name { get; set; }
public SerializedShaderVectorValue(BinaryReader reader)
{
x = new SerializedShaderFloatValue(reader);
y = new SerializedShaderFloatValue(reader);
z = new SerializedShaderFloatValue(reader);
w = new SerializedShaderFloatValue(reader);
name = reader.ReadAlignedString();
}
}
public class SerializedShaderState
{
public string m_Name { get; set; }
public SerializedShaderRTBlendState rtBlend0 { get; set; }
public SerializedShaderRTBlendState rtBlend1 { get; set; }
public SerializedShaderRTBlendState rtBlend2 { get; set; }
public SerializedShaderRTBlendState rtBlend3 { get; set; }
public SerializedShaderRTBlendState rtBlend4 { get; set; }
public SerializedShaderRTBlendState rtBlend5 { get; set; }
public SerializedShaderRTBlendState rtBlend6 { get; set; }
public SerializedShaderRTBlendState rtBlend7 { get; set; }
public bool rtSeparateBlend { get; set; }
public SerializedShaderFloatValue zClip { get; set; }
public SerializedShaderFloatValue zTest { get; set; }
public SerializedShaderFloatValue zWrite { get; set; }
public SerializedShaderFloatValue culling { get; set; }
public SerializedShaderFloatValue offsetFactor { get; set; }
public SerializedShaderFloatValue offsetUnits { get; set; }
public SerializedShaderFloatValue alphaToMask { get; set; }
public SerializedStencilOp stencilOp { get; set; }
public SerializedStencilOp stencilOpFront { get; set; }
public SerializedStencilOp stencilOpBack { get; set; }
public SerializedShaderFloatValue stencilReadMask { get; set; }
public SerializedShaderFloatValue stencilWriteMask { get; set; }
public SerializedShaderFloatValue stencilRef { get; set; }
public SerializedShaderFloatValue fogStart { get; set; }
public SerializedShaderFloatValue fogEnd { get; set; }
public SerializedShaderFloatValue fogDensity { get; set; }
public SerializedShaderVectorValue fogColor { get; set; }
public int fogMode { get; set; }
public int gpuProgramID { get; set; }
public SerializedTagMap m_Tags { get; set; }
public int m_LOD { get; set; }
public bool lighting { get; set; }
public SerializedShaderState(ObjectReader reader)
{
var version = reader.version;
m_Name = reader.ReadAlignedString();
rtBlend0 = new SerializedShaderRTBlendState(reader);
rtBlend1 = new SerializedShaderRTBlendState(reader);
rtBlend2 = new SerializedShaderRTBlendState(reader);
rtBlend3 = new SerializedShaderRTBlendState(reader);
rtBlend4 = new SerializedShaderRTBlendState(reader);
rtBlend5 = new SerializedShaderRTBlendState(reader);
rtBlend6 = new SerializedShaderRTBlendState(reader);
rtBlend7 = new SerializedShaderRTBlendState(reader);
rtSeparateBlend = reader.ReadBoolean();
reader.AlignStream(4);
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
{
zClip = new SerializedShaderFloatValue(reader);
}
zTest = new SerializedShaderFloatValue(reader);
zWrite = new SerializedShaderFloatValue(reader);
culling = new SerializedShaderFloatValue(reader);
offsetFactor = new SerializedShaderFloatValue(reader);
offsetUnits = new SerializedShaderFloatValue(reader);
alphaToMask = new SerializedShaderFloatValue(reader);
stencilOp = new SerializedStencilOp(reader);
stencilOpFront = new SerializedStencilOp(reader);
stencilOpBack = new SerializedStencilOp(reader);
stencilReadMask = new SerializedShaderFloatValue(reader);
stencilWriteMask = new SerializedShaderFloatValue(reader);
stencilRef = new SerializedShaderFloatValue(reader);
fogStart = new SerializedShaderFloatValue(reader);
fogEnd = new SerializedShaderFloatValue(reader);
fogDensity = new SerializedShaderFloatValue(reader);
fogColor = new SerializedShaderVectorValue(reader);
fogMode = reader.ReadInt32();
gpuProgramID = reader.ReadInt32();
m_Tags = new SerializedTagMap(reader);
m_LOD = reader.ReadInt32();
lighting = reader.ReadBoolean();
reader.AlignStream(4);
}
}
public class ShaderBindChannel
{
public sbyte source { get; set; }
public sbyte target { get; set; }
public ShaderBindChannel(BinaryReader reader)
{
source = reader.ReadSByte();
target = reader.ReadSByte();
}
}
public class ParserBindChannels
{
public List<ShaderBindChannel> m_Channels { get; set; }
public uint m_SourceMap { get; set; }
public ParserBindChannels(BinaryReader reader)
{
int numChannels = reader.ReadInt32();
m_Channels = new List<ShaderBindChannel>(numChannels);
for (int i = 0; i < numChannels; i++)
{
m_Channels.Add(new ShaderBindChannel(reader));
}
reader.AlignStream(4);
m_SourceMap = reader.ReadUInt32();
}
}
public class VectorParameter
{
public int m_NameIndex { get; set; }
public int m_Index { get; set; }
public int m_ArraySize { get; set; }
public sbyte m_Type { get; set; }
public sbyte m_Dim { get; set; }
public VectorParameter(BinaryReader reader)
{
m_NameIndex = reader.ReadInt32();
m_Index = reader.ReadInt32();
m_ArraySize = reader.ReadInt32();
m_Type = reader.ReadSByte();
m_Dim = reader.ReadSByte();
reader.AlignStream(4);
}
}
public class MatrixParameter
{
public int m_NameIndex { get; set; }
public int m_Index { get; set; }
public int m_ArraySize { get; set; }
public sbyte m_Type { get; set; }
public sbyte m_RowCount { get; set; }
public MatrixParameter(BinaryReader reader)
{
m_NameIndex = reader.ReadInt32();
m_Index = reader.ReadInt32();
m_ArraySize = reader.ReadInt32();
m_Type = reader.ReadSByte();
m_RowCount = reader.ReadSByte();
reader.AlignStream(4);
}
}
public class TextureParameter
{
public int m_NameIndex { get; set; }
public int m_Index { get; set; }
public int m_SamplerIndex { get; set; }
public sbyte m_Dim { get; set; }
public TextureParameter(ObjectReader reader)
{
var version = reader.version;
m_NameIndex = reader.ReadInt32();
m_Index = reader.ReadInt32();
m_SamplerIndex = reader.ReadInt32();
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)) //2017.3 and up
{
var m_MultiSampled = reader.ReadBoolean();
}
m_Dim = reader.ReadSByte();
reader.AlignStream(4);
}
}
public class BufferBinding
{
public int m_NameIndex { get; set; }
public int m_Index { get; set; }
public BufferBinding(BinaryReader reader)
{
m_NameIndex = reader.ReadInt32();
m_Index = reader.ReadInt32();
}
}
public class ConstantBuffer
{
public int m_NameIndex { get; set; }
public List<MatrixParameter> m_MatrixParams { get; set; }
public List<VectorParameter> m_VectorParams { get; set; }
public List<StructParameter> m_StructParams { get; set; }
public int m_Size { get; set; }
public ConstantBuffer(ObjectReader reader)
{
var version = reader.version;
m_NameIndex = reader.ReadInt32();
int numMatrixParams = reader.ReadInt32();
m_MatrixParams = new List<MatrixParameter>(numMatrixParams);
for (int i = 0; i < numMatrixParams; i++)
{
m_MatrixParams.Add(new MatrixParameter(reader));
}
int numVectorParams = reader.ReadInt32();
m_VectorParams = new List<VectorParameter>(numVectorParams);
for (int i = 0; i < numVectorParams; i++)
{
m_VectorParams.Add(new VectorParameter(reader));
}
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)) //2017.3 and up
{
int numStructParams = reader.ReadInt32();
m_StructParams = new List<StructParameter>(numStructParams);
for (int i = 0; i < numStructParams; i++)
{
m_StructParams.Add(new StructParameter(reader));
}
}
m_Size = reader.ReadInt32();
}
}
public class UAVParameter
{
public int m_NameIndex { get; set; }
public int m_Index { get; set; }
public int m_OriginalIndex { get; set; }
public UAVParameter(BinaryReader reader)
{
m_NameIndex = reader.ReadInt32();
m_Index = reader.ReadInt32();
m_OriginalIndex = reader.ReadInt32();
}
}
public class SerializedSubProgram
{
public uint m_BlobIndex { get; set; }
public ParserBindChannels m_Channels { get; set; }
public List<ushort> m_KeywordIndices { get; set; }
public sbyte m_ShaderHardwareTier { get; set; }
public sbyte m_GpuProgramType { get; set; }
public List<VectorParameter> m_VectorParams { get; set; }
public List<MatrixParameter> m_MatrixParams { get; set; }
public List<TextureParameter> m_TextureParams { get; set; }
public List<BufferBinding> m_BufferParams { get; set; }
public List<ConstantBuffer> m_ConstantBuffers { get; set; }
public List<BufferBinding> m_ConstantBufferBindings { get; set; }
public List<UAVParameter> m_UAVParams { get; set; }
public List<SamplerParameter> m_Samplers { get; set; }
public SerializedSubProgram(ObjectReader reader)
{
var version = reader.version;
m_BlobIndex = reader.ReadUInt32();
m_Channels = new ParserBindChannels(reader);
int numIndices = reader.ReadInt32();
m_KeywordIndices = new List<ushort>(numIndices);
for (int i = 0; i < numIndices; i++)
{
m_KeywordIndices.Add(reader.ReadUInt16());
}
if (version[0] >= 2017) //2017 and up
{
reader.AlignStream(4);
}
m_ShaderHardwareTier = reader.ReadSByte();
m_GpuProgramType = reader.ReadSByte();
reader.AlignStream(4);
int numVectorParams = reader.ReadInt32();
m_VectorParams = new List<VectorParameter>(numVectorParams);
for (int i = 0; i < numVectorParams; i++)
{
m_VectorParams.Add(new VectorParameter(reader));
}
int numMatrixParams = reader.ReadInt32();
m_MatrixParams = new List<MatrixParameter>(numMatrixParams);
for (int i = 0; i < numMatrixParams; i++)
{
m_MatrixParams.Add(new MatrixParameter(reader));
}
int numTextureParams = reader.ReadInt32();
m_TextureParams = new List<TextureParameter>(numTextureParams);
for (int i = 0; i < numTextureParams; i++)
{
m_TextureParams.Add(new TextureParameter(reader));
}
int numBufferParams = reader.ReadInt32();
m_BufferParams = new List<BufferBinding>(numBufferParams);
for (int i = 0; i < numBufferParams; i++)
{
m_BufferParams.Add(new BufferBinding(reader));
}
int numConstantBuffers = reader.ReadInt32();
m_ConstantBuffers = new List<ConstantBuffer>(numConstantBuffers);
for (int i = 0; i < numConstantBuffers; i++)
{
m_ConstantBuffers.Add(new ConstantBuffer(reader));
}
int numConstantBufferBindings = reader.ReadInt32();
m_ConstantBufferBindings = new List<BufferBinding>(numConstantBufferBindings);
for (int i = 0; i < numConstantBufferBindings; i++)
{
m_ConstantBufferBindings.Add(new BufferBinding(reader));
}
int numUAVParams = reader.ReadInt32();
m_UAVParams = new List<UAVParameter>(numUAVParams);
for (int i = 0; i < numUAVParams; i++)
{
m_UAVParams.Add(new UAVParameter(reader));
}
if (version[0] >= 2017) //2017 and up
{
int numSamplers = reader.ReadInt32();
m_Samplers = new List<SamplerParameter>(numSamplers);
for (int i = 0; i < numSamplers; i++)
{
m_Samplers.Add(new SamplerParameter(reader));
}
}
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
{
var m_ShaderRequirements = reader.ReadInt32();
}
}
}
public class SerializedProgram
{
public List<SerializedSubProgram> m_SubPrograms { get; set; }
public SerializedProgram(ObjectReader reader)
{
int numSubPrograms = reader.ReadInt32();
m_SubPrograms = new List<SerializedSubProgram>(numSubPrograms);
for (int i = 0; i < numSubPrograms; i++)
{
m_SubPrograms.Add(new SerializedSubProgram(reader));
}
}
}
public class SerializedPass
{
public List<KeyValuePair<string, int>> m_NameIndices { get; set; }
public int m_Type { get; set; }
public SerializedShaderState m_State { get; set; }
public uint m_ProgramMask { get; set; }
public SerializedProgram progVertex { get; set; }
public SerializedProgram progFragment { get; set; }
public SerializedProgram progGeometry { get; set; }
public SerializedProgram progHull { get; set; }
public SerializedProgram progDomain { get; set; }
public bool m_HasInstancingVariant { get; set; }
public string m_UseName { get; set; }
public string m_Name { get; set; }
public string m_TextureName { get; set; }
public SerializedTagMap m_Tags { get; set; }
public SerializedPass(ObjectReader reader)
{
var version = reader.version;
int numIndices = reader.ReadInt32();
m_NameIndices = new List<KeyValuePair<string, int>>(numIndices);
for (int i = 0; i < numIndices; i++)
{
m_NameIndices.Add(new KeyValuePair<string, int>(reader.ReadAlignedString(), reader.ReadInt32()));
}
m_Type = reader.ReadInt32();
m_State = new SerializedShaderState(reader);
m_ProgramMask = reader.ReadUInt32();
progVertex = new SerializedProgram(reader);
progFragment = new SerializedProgram(reader);
progGeometry = new SerializedProgram(reader);
progHull = new SerializedProgram(reader);
progDomain = new SerializedProgram(reader);
m_HasInstancingVariant = reader.ReadBoolean();
if (version[0] >= 2018) //2018 and up
{
var m_HasProceduralInstancingVariant = reader.ReadBoolean();
}
reader.AlignStream(4);
m_UseName = reader.ReadAlignedString();
m_Name = reader.ReadAlignedString();
m_TextureName = reader.ReadAlignedString();
m_Tags = new SerializedTagMap(reader);
}
}
public class SerializedTagMap
{
public List<KeyValuePair<string, string>> tags { get; set; }
public SerializedTagMap(BinaryReader reader)
{
int numTags = reader.ReadInt32();
tags = new List<KeyValuePair<string, string>>(numTags);
for (int i = 0; i < numTags; i++)
{
tags.Add(new KeyValuePair<string, string>(reader.ReadAlignedString(), reader.ReadAlignedString()));
}
}
}
public class SerializedSubShader
{
public List<SerializedPass> m_Passes { get; set; }
public SerializedTagMap m_Tags { get; set; }
public int m_LOD { get; set; }
public SerializedSubShader(ObjectReader reader)
{
int numPasses = reader.ReadInt32();
m_Passes = new List<SerializedPass>(numPasses);
for (int i = 0; i < numPasses; i++)
{
m_Passes.Add(new SerializedPass(reader));
}
m_Tags = new SerializedTagMap(reader);
m_LOD = reader.ReadInt32();
}
}
public class SerializedShaderDependency
{
public string from { get; set; }
public string to { get; set; }
public SerializedShaderDependency(BinaryReader reader)
{
from = reader.ReadAlignedString();
to = reader.ReadAlignedString();
}
}
public class SerializedShader
{
public SerializedProperties m_PropInfo { get; set; }
public List<SerializedSubShader> m_SubShaders { get; set; }
public string m_Name { get; set; }
public string m_CustomEditorName { get; set; }
public string m_FallbackName { get; set; }
public List<SerializedShaderDependency> m_Dependencies { get; set; }
public bool m_DisableNoSubshadersMessage { get; set; }
public SerializedShader(ObjectReader reader)
{
m_PropInfo = new SerializedProperties(reader);
int numSubShaders = reader.ReadInt32();
m_SubShaders = new List<SerializedSubShader>(numSubShaders);
for (int i = 0; i < numSubShaders; i++)
{
m_SubShaders.Add(new SerializedSubShader(reader));
}
m_Name = reader.ReadAlignedString();
m_CustomEditorName = reader.ReadAlignedString();
m_FallbackName = reader.ReadAlignedString();
int numDependencies = reader.ReadInt32();
m_Dependencies = new List<SerializedShaderDependency>(numDependencies);
for (int i = 0; i < numDependencies; i++)
{
m_Dependencies.Add(new SerializedShaderDependency(reader));
}
m_DisableNoSubshadersMessage = reader.ReadBoolean();
reader.AlignStream(4);
}
}
public class Shader : NamedObject
{
public byte[] m_Script;
//5.3 - 5.4
public uint decompressedSize;
public byte[] m_SubProgramBlob;
//5.5 and up
public SerializedShader m_ParsedForm;
public List<uint> platforms;
public List<uint> offsets;
public List<uint> compressedLengths;
public List<uint> decompressedLengths;
public byte[] compressedBlob;
public Shader(ObjectReader reader) : base(reader)
{
if (version[0] == 5 && version[1] >= 5 || version[0] > 5) //5.5.0 and up
if (version[0] == 5 && version[1] >= 5 || version[0] > 5) //5.5 and up
{
var str = reader.Dump();
m_Script = Encoding.UTF8.GetBytes(str ?? "Serialized Shader can't be read");
m_ParsedForm = new SerializedShader(reader);
int numPlatforms = reader.ReadInt32();
platforms = new List<uint>(numPlatforms);
for (int i = 0; i < numPlatforms; i++)
{
platforms.Add(reader.ReadUInt32());
}
int numOffsets = reader.ReadInt32();
offsets = new List<uint>(numOffsets);
for (int i = 0; i < numOffsets; i++)
{
offsets.Add(reader.ReadUInt32());
}
int numCompressedLengths = reader.ReadInt32();
compressedLengths = new List<uint>(numCompressedLengths);
for (int i = 0; i < numCompressedLengths; i++)
{
compressedLengths.Add(reader.ReadUInt32());
}
int numDecompressedLengths = reader.ReadInt32();
decompressedLengths = new List<uint>(numDecompressedLengths);
for (int i = 0; i < numDecompressedLengths; i++)
{
decompressedLengths.Add(reader.ReadUInt32());
}
compressedBlob = reader.ReadBytes(reader.ReadInt32());
}
else
{
m_Script = reader.ReadBytes(reader.ReadInt32());
reader.AlignStream(4);
var m_PathName = reader.ReadAlignedString();
if (version[0] == 5 && version[1] >= 3) //5.3 - 5.4
{
reader.AlignStream(4);
var m_PathName = reader.ReadAlignedString();
var decompressedSize = reader.ReadUInt32();
var m_SubProgramBlob = reader.ReadBytes(reader.ReadInt32());
var decompressedBytes = new byte[decompressedSize];
using (var decoder = new Lz4DecoderStream(new MemoryStream(m_SubProgramBlob)))
{
decoder.Read(decompressedBytes, 0, (int)decompressedSize);
}
m_Script = m_Script.Concat(decompressedBytes.ToArray()).ToArray();
decompressedSize = reader.ReadUInt32();
m_SubProgramBlob = reader.ReadBytes(reader.ReadInt32());
}
}
}

Binary file not shown.

Binary file not shown.

View File

@ -86,7 +86,8 @@ namespace AssetStudio
var exportFullName = exportPath + reader.exportName + ".shader";
if (ExportFileExists(exportFullName))
return false;
File.WriteAllBytes(exportFullName, m_Shader.m_Script);
var str = ShaderConverter.Convert(m_Shader);
File.WriteAllText(exportFullName, str ?? "Serialized Shader can't be read");
return true;
}

View File

@ -0,0 +1,229 @@
using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using Lz4;
using SharpDX.D3DCompiler;
namespace AssetStudio
{
public static class ShaderConverter
{
public static string Convert(Shader shader)
{
if (shader.m_SubProgramBlob != null) //5.3 - 5.4
{
var decompressedBytes = new byte[shader.decompressedSize];
using (var decoder = new Lz4DecoderStream(new MemoryStream(shader.m_SubProgramBlob)))
{
decoder.Read(decompressedBytes, 0, (int)shader.decompressedSize);
}
using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes)))
{
var program = new ShaderProgram(blobReader);
return program.Export(Encoding.UTF8.GetString(shader.m_Script));
}
}
if (shader.compressedBlob != null) //5.5 and up
{
//TODO
/*for (var i = 0; i < shader.platforms.Count; i++)
{
var compressedBytes = new byte[shader.compressedLengths[i]];
Array.Copy(shader.compressedBlob, shader.offsets[i], compressedBytes, 0, shader.compressedLengths[i]);
var decompressedBytes = new byte[shader.decompressedLengths[i]];
using (var decoder = new Lz4DecoderStream(new MemoryStream(compressedBytes)))
{
decoder.Read(decompressedBytes, 0, (int)shader.decompressedLengths[i]);
}
using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes)))
{
new ShaderProgram(blobReader);
}
}*/
return shader.reader.Dump();
}
return Encoding.UTF8.GetString(shader.m_Script);
}
}
public class ShaderProgram
{
public ShaderSubProgram[] m_SubPrograms;
public ShaderProgram(BinaryReader reader)
{
var subProgramsCapacity = reader.ReadInt32();
m_SubPrograms = new ShaderSubProgram[subProgramsCapacity];
for (int i = 0; i < subProgramsCapacity; i++)
{
reader.BaseStream.Position = 4 + i * 8;
var offset = reader.ReadInt32();
reader.BaseStream.Position = offset;
m_SubPrograms[i] = new ShaderSubProgram(reader);
}
}
public string Export(string shader)
{
var evaluator = new MatchEvaluator(match =>
{
var index = int.Parse(match.Groups[1].Value);
return m_SubPrograms[index].Export();
});
shader = Regex.Replace(shader, "GpuProgramIndex (.+)", evaluator);
return shader;
}
}
public class ShaderSubProgram
{
private int magic;
public ShaderGpuProgramType m_ProgramType;
public string[] m_Keywords;
public byte[] m_ProgramCode;
public ShaderSubProgram(BinaryReader reader)
{
//LoadGpuProgramFromData
// 201509030 - Unity 5.3
// 201510240 - Unity 5.4
// 201608170 - Unity 5.5
// 201609010 - Unity 5.6, 2017.1 & 2017.2
// 201708220 - Unity 2017.3, Unity 2017.4 & Unity 2018.1
// 201802150 - Unity 2018.2
magic = reader.ReadInt32();
m_ProgramType = (ShaderGpuProgramType)reader.ReadInt32();
reader.BaseStream.Position += 12;
if (magic >= 201608170) //5.5.0 and up
{
reader.BaseStream.Position += 4;
}
var keywordCount = reader.ReadInt32();
m_Keywords = new string[keywordCount];
for (int i = 0; i < keywordCount; i++)
{
m_Keywords[i] = reader.ReadAlignedString();
}
m_ProgramCode = reader.ReadBytes(reader.ReadInt32());
reader.AlignStream(4);
//TODO
}
public string Export()
{
var sb = new StringBuilder();
if (m_Keywords.Length > 0)
{
sb.Append("Keywords { ");
foreach (string keyword in m_Keywords)
{
sb.Append($"\"{keyword}\" ");
}
sb.Append("}\n");
}
sb.Append("\"\n");
if (m_ProgramCode.Length > 0)
{
switch (m_ProgramType)
{
case ShaderGpuProgramType.kShaderGpuProgramGLLegacy:
case ShaderGpuProgramType.kShaderGpuProgramGLES31AEP:
case ShaderGpuProgramType.kShaderGpuProgramGLES31:
case ShaderGpuProgramType.kShaderGpuProgramGLES3:
case ShaderGpuProgramType.kShaderGpuProgramGLES:
case ShaderGpuProgramType.kShaderGpuProgramGLCore32:
case ShaderGpuProgramType.kShaderGpuProgramGLCore41:
case ShaderGpuProgramType.kShaderGpuProgramGLCore43:
sb.Append(Encoding.UTF8.GetString(m_ProgramCode));
break;
case ShaderGpuProgramType.kShaderGpuProgramDX9VertexSM20:
case ShaderGpuProgramType.kShaderGpuProgramDX9VertexSM30:
case ShaderGpuProgramType.kShaderGpuProgramDX9PixelSM20:
case ShaderGpuProgramType.kShaderGpuProgramDX9PixelSM30:
{
var shaderBytecode = new ShaderBytecode(m_ProgramCode);
sb.Append(shaderBytecode.Disassemble());
break;
}
case ShaderGpuProgramType.kShaderGpuProgramDX10Level9Vertex:
case ShaderGpuProgramType.kShaderGpuProgramDX10Level9Pixel:
case ShaderGpuProgramType.kShaderGpuProgramDX11VertexSM40:
case ShaderGpuProgramType.kShaderGpuProgramDX11VertexSM50:
case ShaderGpuProgramType.kShaderGpuProgramDX11PixelSM40:
case ShaderGpuProgramType.kShaderGpuProgramDX11PixelSM50:
case ShaderGpuProgramType.kShaderGpuProgramDX11GeometrySM40:
case ShaderGpuProgramType.kShaderGpuProgramDX11GeometrySM50:
case ShaderGpuProgramType.kShaderGpuProgramDX11HullSM50:
case ShaderGpuProgramType.kShaderGpuProgramDX11DomainSM50:
{
int start = 6;
if (magic == 201509030) // 5.3
{
start = 5;
}
var buff = new byte[m_ProgramCode.Length - start];
Buffer.BlockCopy(m_ProgramCode, start, buff, 0, buff.Length);
var shaderBytecode = new ShaderBytecode(buff);
sb.Append(shaderBytecode.Disassemble());
break;
}
case ShaderGpuProgramType.kShaderGpuProgramMetalVS:
case ShaderGpuProgramType.kShaderGpuProgramMetalFS:
using (var reader = new BinaryReader(new MemoryStream(m_ProgramCode)))
{
var fourCC = reader.ReadUInt32();
if (fourCC == 0xf00dcafe)
{
int offset = reader.ReadInt32();
reader.BaseStream.Position = offset;
}
var entryName = reader.ReadStringToNull();
var buff = reader.ReadBytes((int)(reader.BaseStream.Length - reader.BaseStream.Position));
sb.Append(Encoding.UTF8.GetString(buff));
}
break;
default:
sb.Append($"/*Unsupported program data {m_ProgramType}*/");
break;
}
}
sb.Append('"');
return sb.ToString();
}
}
public enum ShaderGpuProgramType
{
kShaderGpuProgramUnknown = 0,
kShaderGpuProgramGLLegacy = 1,
kShaderGpuProgramGLES31AEP = 2,
kShaderGpuProgramGLES31 = 3,
kShaderGpuProgramGLES3 = 4,
kShaderGpuProgramGLES = 5,
kShaderGpuProgramGLCore32 = 6,
kShaderGpuProgramGLCore41 = 7,
kShaderGpuProgramGLCore43 = 8,
kShaderGpuProgramDX9VertexSM20 = 9,
kShaderGpuProgramDX9VertexSM30 = 10,
kShaderGpuProgramDX9PixelSM20 = 11,
kShaderGpuProgramDX9PixelSM30 = 12,
kShaderGpuProgramDX10Level9Vertex = 13,
kShaderGpuProgramDX10Level9Pixel = 14,
kShaderGpuProgramDX11VertexSM40 = 15,
kShaderGpuProgramDX11VertexSM50 = 16,
kShaderGpuProgramDX11PixelSM40 = 17,
kShaderGpuProgramDX11PixelSM50 = 18,
kShaderGpuProgramDX11GeometrySM40 = 19,
kShaderGpuProgramDX11GeometrySM50 = 20,
kShaderGpuProgramDX11HullSM50 = 21,
kShaderGpuProgramDX11DomainSM50 = 22,
kShaderGpuProgramMetalVS = 23,
kShaderGpuProgramMetalFS = 24,
kShaderGpuProgramSPIRV = 25,
kShaderGpuProgramConsole = 26,
};
}

View File

@ -203,25 +203,36 @@ namespace AssetStudio
var m_Texture2D = new Texture2D(objectReader, false);
if (!string.IsNullOrEmpty(m_Texture2D.path))
assetItem.FullSize = objectReader.byteSize + m_Texture2D.size;
goto case ClassIDType.NamedObject;
assetItem.Text = m_Texture2D.m_Name;
exportable = true;
break;
}
case ClassIDType.AudioClip:
{
var m_AudioClip = new AudioClip(objectReader, false);
if (!string.IsNullOrEmpty(m_AudioClip.m_Source))
assetItem.FullSize = objectReader.byteSize + m_AudioClip.m_Size;
goto case ClassIDType.NamedObject;
assetItem.Text = m_AudioClip.m_Name;
exportable = true;
break;
}
case ClassIDType.VideoClip:
{
var m_VideoClip = new VideoClip(objectReader, false);
if (!string.IsNullOrEmpty(m_VideoClip.m_OriginalPath))
assetItem.FullSize = objectReader.byteSize + (long)m_VideoClip.m_Size;
goto case ClassIDType.NamedObject;
assetItem.Text = m_VideoClip.m_Name;
exportable = true;
break;
}
case ClassIDType.NamedObject:
case ClassIDType.Mesh:
case ClassIDType.Shader:
{
var m_Shader = new Shader(objectReader);
assetItem.Text = m_Shader.m_ParsedForm?.m_Name ?? m_Shader.m_Name;
exportable = true;
break;
}
case ClassIDType.Mesh:
case ClassIDType.TextAsset:
case ClassIDType.AnimationClip:
case ClassIDType.Font: