Closed HBigger closed 5 months ago
You forgot to attach the index buffer, or for that matter the rest of the frame analysis dump. The only valid data in the vertex buffer you did attach is POSITION and NORMAL. TEXCOORD is in vb1, which you forgot to attach, and it's AlignedByteOffset is not 0, which is unusual given the header declares that nothing else is in vb1. Everything else reuses InputSlot:0 and AlignedByteOffset: 0 making them invalid.
Curiously the vertex buffer stride (40 bytes) is larger than the data inside it (sizeof(R32G32B32_FLOAT) + sizeof(R32G32B32_FLOAT) = 24 bytes), leaving room for an additional 16 bytes per vertex. Since you forgot to attach the buf files I cannot examine them to determine if there is any actual data here, or if it was just padding (which would be unusual).
Is this buffer straight out of 3DMigoto or have you used another script to pre-process it?
Google tells me this game engine is Unity, so it is likely that the missing blendindices data is in an earlier draw call - the vanilla version of my blender script does not fully support combining these together for import yet, though there is some work in progress towards this goal - refer to this bug: https://github.com/DarkStarSword/3d-fixes/issues/19
There are forks of the script created for specific games (e.g. Genshin Impact) that do support the pre-skinning pass that Unity uses, but my understanding is that they used hard coded offsets so may require some modification to work in other games.
Thanks for your reply!
Curiously the vertex buffer stride (40 bytes) is larger than the data inside it (sizeof(R32G32B32_FLOAT) + sizeof(R32G32B32_FLOAT) = 24 bytes), leaving room for an additional 16 bytes per vertex. Since you forgot to attach the buf files I cannot examine them to determine if there is any actual data here, or if it was just padding (which would be unusual).
In a drawcall which shares the same vb0_vertexcount(of course also the same vb0 hash) and ib_first index, I found a vb0 file that solve this problem. 000019-vb0=474ec2d2-vs=b1701006f73554da-ps=7fb77c7166d44fb1.txt I put part of the vb0 content here for convenience
stride: 40
element[2]: SemanticName: TANGENT SemanticIndex: 0 Format: R32G32B32A32_FLOAT InputSlot: 0 AlignedByteOffset: 24 InputSlotClass: per-vertex InstanceDataStepRate: 0 vertex-data: vb0[0]+000 POSITION: -0.0827184916, -0.0571886711, 0.0920202881 vb0[0]+012 NORMAL: 0.88827616, 0.00512076262, -0.450060397 vb0[0]+024 TANGENT: 0.103927225, -0.975161254, 0.195394143, -1 vb0[0]+000 TEXCOORD1: 0.313725501, 0.407843143, 0.662745118, 0.741176486 vb0[0]+000 TEXCOORD2: 0.313725501, 0.407843143, 0.662745118, 0.741176486 vb0[0]+000 TEXCOORD3: 0.313725501, 0.407843143, 0.662745118, 0.741176486 vb0[0]+000 TEXCOORD5: 0.313725501, 0.407843143, 0.662745118, 0.741176486 vb0[0]+000 TEXCOORD6: 0.313725501, 0.407843143, 0.662745118, 0.741176486 vb0[0]+000 TEXCOORD7: 0.313725501, 0.407843143, 0.662745118, 0.741176486 vb0[0]+000 BLENDWEIGHTS: 0.313725501, 0.407843143, 0.662745118, 0.741176486 vb0[0]+000 BLENDINDICES: 0.313725501, 0.407843143, 0.662745118, 0.741176486
I guess the TANGENT data is also valid in this vb0 file. And its size is 16(R32G32B32A32_FLOAT). The size add up to 40(12+12+16), which matches the stride.
Is this buffer straight out of 3DMigoto or have you used another script to pre-process it?
It's straight out of 3DMigoto.
so it is likely that the missing blendindices data is in an earlier draw call
I write a script to search all vb files in the same folder that contain the same vertex count. vbfile-vb0=474ec2d2-vertexcount=3813-id=7_19_34_txt.zip And I check them manually. All of them contain no data that looks like the actual BLENDINDICIES
I also check all the files that share the same vertex buffer hash with it (but with different first index & vertex count), but to no avail. vbfile-vb0=474ec2d2-vertexcount=5211-id=14_23_38_txt.zip vbfile-vb0=474ec2d2-vertexcount=5357-id=1_55_56_txt.zip
Emmm, GF2 already fix the problem for can use 3dmigoto to make model modify mod, this game sell skins and change their GPU bone animation calculation into CPU, so now you can't dump any topology = pointlist 's file to get it's BLENDINDICES and BLENDWEIGHTS.
And the value you dumped from trianglelist file is all same because it's a fake value generated by 3dmigoto if 3dmigoto find it's slot is empty but element desc is there, actually you can see the file's stride is 40 which means there is only POSITION 12, NORMAL 12, TANGENT 16, add them together is 40, so other value is fake and useless.
Base on the the script for Genshin Impact https://github.com/SilentNightSound/GI-Model-Importer/blob/main/Tools/genshin_3dmigoto_collect.py I guess the blend indices data is in a certain root draw call's vb file.
So I try to search BLENDINDICES data that's over 1 through the whole dump folder. And the result is there's no BLENDINDICES data that's over 1.
invalidcount = 0
validcount = 0
for filename in frame_dump_files:
if "vb" in filename and ".txt" in filename:
with open(os.path.join(frame_dump_folder, filename), "r") as f:
for x in f.readlines():
if "BLENDINDICES:" in x:
indices = x.split(":")[1]
for y in indices.split(","):
indi = float(y)
if indi>1:
validcount += 1
else:
invalidcount += 1
print(validcount,invalidcount)
return
So I try to search BLENDINDICES data that's over 1 through the whole dump folder. And the result is there's no BLENDINDICES data that's over 1.
It could be that frame analysis wasn't active when the pre-skinning pass ran - how have you set up FA in this game?
Another possibility is that the game might be applying pre-skinning on the CPU, which 3DMigoto can't do much about (Edit: StarBobis post above confirms this is the case). Apparently Unity does this if the developer didn't have a pro license (which is evident when launching the game as the Unity splash screen will display - a pro license is required to remove that).
If you attach the frame analysis log file I can take a look to find out which shaders were responsible for the pre-skinning pass or if it came from the CPU, or if you would like to learn how to do this yourself, the process is:
000007 IASetVertexBuffers(StartSlot:0, NumBuffers:1, ppVertexBuffers:0x0000001DEC0DFB08, pStrides:0x0000001DEC0DFAD0, pOffsets:0x0000001DEC0DFAD4)
0: resource=0x0000018AD5DA2230 hash=474ec2d2
000001 SOSetTargets(NumBuffers:1, ppSOTargets:0x0000001DEC0DFC60, pOffsets:0x0000001DEC0DFCB0)
0: resource=0x0000018AD5DA2230 hash=65fd0d73
000001 IASetVertexBuffers(StartSlot:0, NumBuffers:1, ppVertexBuffers:0x0000001DEC0DFB48, pStrides:0x0000001DEC0DFB10, pOffsets:0x0000001DEC0DFB14)
0: resource=0x0000018ACAFC84B0 hash=8f4bc08a
000001 IASetVertexBuffers(StartSlot:1, NumBuffers:1, ppVertexBuffers:0x0000001DEC0DFB48, pStrides:0x0000001DEC0DFB10, pOffsets:0x0000001DEC0DFB14)
1: resource=0x0000018ACAFC87B0 hash=0bb8989a
The shaders used for pre-skinning (note no pixel shader is assigned, this pass operates with vertex + geometry shaders only, and the current 3DMigoto won't hash the geometry shader for these stream out passes (which is on my TODO list to fix), so only the vertex shader hash can be used to match this in a ShaderOverride):
000001 VSSetShader(pVertexShader:0x00000189E39149C8, ppClassInstances:0x0000000000000000, NumClassInstances:0) hash=e58e7a5d769437dd
000001 PSSetShader(pPixelShader:0x0000000000000000, ppClassInstances:0x0000000000000000, NumClassInstances:0)
000001 GSSetShader(pShader:0x00000189E3914108, ppClassInstances:0x0000000000000000, NumClassInstances:0)
Emmm, GF2 already fix the problem for can use 3dmigoto to make model modify mod, this game sell skins and change their GPU bone animation calculation into CPU, so now you can't dump any topology = pointlist 's file to get it's BLENDINDICES and BLENDWEIGHTS.
Yeah, that will be a show stopper for 3DMigoto, since it can't intervene with anything the game does on the CPU. I don't know anything about this game - does it use any anti-tamper/anti-mod/anti-cheat detection?
And the value you dumped from trianglelist file is all same because it's a fake value generated by 3dmigoto if 3dmigoto find it's slot is empty but element desc is there, actually you can see the file's stride is 40 which means there is only POSITION 12, NORMAL 12, TANGENT 16, add them together is 40, so other value is fake and useless.
They're not generated by 3DMigoto - it simply follows whatever the game specified in the input layout that it passed to DirectX, but since they all reuse the same offset as POSITION it will try to reinterpret the POSITION data as a different type (e.g. here POSITION is a R32G32B32_FLOAT, but the invalid semantics are declared as e.g. R8G8B8A8_UNORM, so it will attempt to interpret the data as such - and you can verify that if the shader were to access those semantics it would get the same values that 3DMigoto wrote in the .txt file). 3DMigoto doesn't try to be smart here - it just logs whatever the game told it. It's the Blender addon that recognises they are invalid and ignores them.
If you attach the frame analysis log file I can take a look to find out which shaders were responsible for the pre-skinning pass or if it came from the CPU, or if you would like to learn how to do this yourself, the process is:
Thanks for your elucidation. I followed the process and examine the log file. log.txt Unfortunately, there's no SOSetTargets call. So no geometry shaders is utilized here. Guess the game use cpu for pre-skinning.
I tried to dump vertex buffers from Girl's Frontline2 Elixium. The value of texcoords, blendindices and blendweights are all the same. 000007-vb0=474ec2d2-vs=f58b6b788ceaba1a-ps=04d13489e228a5ef.txt
It's obvious that blendindices should be integers. I try to import the vb&ib files into blender, and the model is displayed normally, so i guess the position data is correct.