Closed cuixiang0130 closed 2 years ago
从Minecraft中提取出来的编译后着色器版本号是5,是2018年的时候,现在bgfx的shaderc代码已经改动了不少,大概可以参考一下这个https://github.com/bkaradzic/bgfx/commit/70c06f46c35587f8e32ffeab4954f0c9284acd23
根据bgfx的源码,反编译bgfx的着色器过程大概是这样
// 前3位是VSH/FSH/CSH表示着色器代码类型,对应Vertex、Fragment、Compute三种着色器,最后一位是版本号,Minecraft提取出来为5
byte[] magicNumber = ByteBufUtil.readBytes(buf, 4);
//根据着色器的输入输出的变量计算出hash值,不过运行时只校验Vertex与Fragment两个着色器hash值相同,确保Vertex的输出与Fragment输入相同,只要两个相同,随便填一个应该都可以
int hashIn = buf.readIntLE();
short uniformCount = buf.readShortLE();
materialUniformList = new ArrayList<>(uniformCount);
for (int i = 0; i < uniformCount; ++i) {
MaterialUniform materialUniform = new MaterialUniform();
materialUniform.readFrom(buf);
materialUniformList.add(materialUniform);
}
code = ByteBufUtil.readByteArray(buf);
// 永远为0
buf.readByte();
MaterialUniform
public void readFrom(ByteBuf buf) {
byte nameLength = buf.readByte();
name = new String(ByteBufUtil.readBytes(buf, nameLength), StandardCharsets.UTF_8);
type = buf.readByte();
count = buf.readByte();
regIndex = buf.readShortLE();
regCount = buf.readShortLE();
}
如果是DirectX的话,后面还存了attribute的信息,可以翻bgfx的shaderc_hlsl.cpp
然后SamplerDefinition这里,1.18跟在1.17的格式上加了个int
public void readFrom(ByteBuf buf) {
name = ByteBufUtil.readString(buf);
//猜测应该是索引值?
index = buf.readByte();
unknownByte1 = buf.readByte();
unknownByte2 = buf.readByte();
unknownBool0 = buf.readBoolean();
unknownByte3 = buf.readByte();
unknownStr0 = ByteBufUtil.readString(buf);
//1.18的文件这里多了个int,似乎一直是1
unknownInt = buf.readIntLE();
unknownBool1 = buf.readBoolean();
if (unknownBool1) {
unknownStr1 = ByteBufUtil.readString(buf);
}
unknownBool2 = buf.readBoolean();
if (unknownBool2) {
unknownStr2 = ByteBufUtil.readString(buf);
unknownInt0 = buf.readIntLE();
}
}
Pass类中这段代码也不太适合现在的情况,现在1.18 Windows版中的文件也是长度15的字符串bitset
if (version >= 0x16) {
v1_17_40_20_Android = buf.readIntLE() == 15;
buf.readerIndex(buf.readerIndex() - 4);
} else {
v1_17_40_20_Android = false;
}
if (v1_17_40_20_Android) {
bitSet = ByteBufUtil.readString(buf);
} else {
unknownByte0 = buf.readByte();
}
虽然Android提取出的代码没有编译成什么字节码,但估计可能还是得用bgfx的shaderc编译一下,之前尝试着修改的时候,调用一些内置函数Minecraft直接崩溃,我应该没写错语法(大概)。而且用bgfx的话,着色器可以write once,compile everywhere了
感谢反馈
Pass类中这段代码也不太适合现在的情况,现在1.18 Windows版中的文件也是长度15的字符串bitset
if (version >= 0x16) { v1_17_40_20_Android = buf.readIntLE() == 15; buf.readerIndex(buf.readerIndex() - 4); } else { v1_17_40_20_Android = false; } if (v1_17_40_20_Android) { bitSet = ByteBufUtil.readString(buf); } else { unknownByte0 = buf.readByte(); }
这个地方这么写是因为我写这个工具的那段时间win10版和安卓版的version同为0x16,同名的.material.bin文件这个位置之前的其他地方也相同,但win10版的这个位置只有一个字节,安卓版则是现在这样的字符串bitset,没法区分,为了兼容旧版本还是得留着(
今天又试了一下,发现之前调用一些内置函数导致Minecraft崩溃好像真是我的问题(没切换输入法输了个中文符号();什么的,😅笑嘻了),所以修改着色器应该没什么这些限制
Shader Code部分
对应的枚举类