教你如何使用GPA导出模型,另送一个 GPA CSV2MESH Tool in unity


以前写过一篇:Unity - RenderDoc 抓帧导出 FBX(带UV)


吐槽

我估计GPA是怕收律师函,因为如果 GPA 将所有资源一键提取,一键导出,那么可能很多开发商会告他


GPA Geometry Output 没有 UV

可以看到也好几个帖子问 GPA 官方,都是被官方忽悠回答了:

(除了这个,我自己还搜索过还几个类似有人问这个问题,结果同样被官方忽悠)



既然GPA不整模型导出带UV,那么今天我们实现一个 GPA 中的模型导出 UV 的工具


问题实例

如果直接将 input gemoetry 导出
会得到一个除了 position 之外,没有其他数据的网格,如下:
在这里插入图片描述

然后,对应的 shader vs input 有6个 register
在这里插入图片描述

如果我们要向将这些顶点数据都导出来,直接使用 GPA 功能默认的Geometry output是导不出来的


开始实现


提取 VBV, IBV

上面的 VS_INPUT 可以看到 input attribute 的定义

但是这些数据是从哪些 VBV(vertex buffer viewer) 输入的呢?

我们可以点击 Resource 中的 Shader,选择:Vertex shader 后

然后查看使用到的数据有哪些,如下图:
在这里插入图片描述

OK,留意:
在这里插入图片描述

然后我们可以将每个 VBV 个、单个 IBV 设置导出 CSV Titles 格式,下面以导出 position.csv 为例

  • 根据shader input attribute 定义,定位使用的 vbv序号
  • 在 resource 中,找到对应的 vbv
  • 给 vbv 的 titles 设置好格式
  • 最后 导出 csv

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

其他的 tangent, normal, uv0, uv1, color0 都可以使用类似的方式导出,如上图,这个模型的数据我是使用下面的格式导出的
因为我们使用的是 unity mesh,那么TEXCOORD0 的 position 我们需要将其 semantic 修改为 POSITION,同理,normal 和 uv0 都使用对应的:NORMAL, TEXCOORD0 来替代

参考如下(注意每个 shader 的 VBV 是干嘛用的,需要自行去查看 shader 怎么使用,以此分析他们的所属的 semantic,因为每个 shader 都有可能不一样):

VBV, IBV 导出的 csv format:

  • position : VBV1 - float POSITION.x;float POSITION.y;float POSITION.z;

  • tangent : VBV2 - float TANGENT.x;float TANGENT.y;float TANGENT.z;float TANGENT.w;

  • normal : VBV3 - float NORMAL.x;float NORMAL.y;float NORMAL.z;

  • uv0 : VBV0 - half TEXCOORD0.x;half TEXCOORD0.y;byte4p

  • uv1 : VBV0 - byte4p; half TEXCOORD4.x;half TEXCOORD4.y;

  • color0 : VBV1

    • float TEXCOORD5.x;float TEXCOORD5.y;float TEXCOORD5.z;float TEXCOORD5.w; byte4p
    • ubyte COLOR0.x;ubyte COLOR0.y;ubyte COLOR0.z;ubyte COLOR0.w; byte4p
    • ubyte TEXCOORD5.x;ubyte TEXCOORD5.y;ubyte TEXCOORD5.z;ubyte TEXCOORD5.w; byte4p - 这个会使用比较多,但是这个有些问题:没有 normalized
    • nubyte TEXCOORD5.x;nubyte TEXCOORD5.y;nubyte TEXCOORD5.z;nubyte TEXCOORD5.w; byte4p - 然后添加了前缀 n 后,还是不能 normalized,所以这个我在工具中特殊弄了一些开关,可是设置 VBV 是否需要 normalized
  • index : IBV - 不需要格式,直接导出,只要确保第二列是 index 的值即可


工具演示导出

请添加图片描述


GPA 的 VBV,IBV的 BUG

我之前就怀疑还原模型的话,如果这些 IBV, VBV 长度都不对的话,除了浪费数据,还可能出问题

因为很多 VBV 和 IBV 的元素数量是对不上的

今天在抓帧某个角色的 卧蚕(眼部底下部分) 模型时候就出现这个问题

从下面的 IBV 可以看到1091,1092 之间的索引跨度很大,是有问题的

23901 的索引直接就超出了 VBV 顶点总数的数量
在这里插入图片描述

从下面的数据分析, Primitive 总数才 364 个三角形
在这里插入图片描述

VBV position 数量才 10313,但是 IBV 的索引已经远超这个范围了,这个很明显是 GPA 的数据显示上的 BUG
在这里插入图片描述

所以部分模型的导出可能遇到:

  • Fail setting triangles. Some indices are referencing out of bounds vertices. IndexCount: 2046, VertexCount: 10314
  • Fail setting triangles. The number of supplied triangle indices must be a multiple of 3.

在这里插入图片描述
在这里插入图片描述


must be a multiple of 3 的解决办法

在我的工具中,是这么来处理的:

因为是在 set triangles 的时候发生的错误

那么我们只要将 indices 的长度保持在 缓存元素数量可以整除3即可:indices.Count % 3 == 0

        // jave.lin : push padding or remove padding
        // jave.lin : 这么处理可以避免 https://blog.csdn.net/linjf520/article/details/127066726 文章中提及的 BUG:
        //  - Fail setting triangles. Some indices are referencing out of bounds vertices. IndexCount: xxx, VertexCount: xxx
        //  - Fail setting triangles. The number of supplied triangle indices must be a multiple of 3.
        if (indices.Count > 0 && indices.Count % 3 != 0)
        {
    
    
            var loopCount = 0;
            var lastOneVal = indices[indices.Count - 1];
            var lastOneIsZeroVal = lastOneVal == 0;
            while (indices.Count > 0 && indices.Count % 3 != 0)
            {
    
    
                if (loopCount > 10)
                    break;
                loopCount++;
                if (lastOneIsZeroVal)
                {
    
    
                    // jave.lin : remove padding 如果尾部是 0 索引,我们可以用删除 padding 的方式
                    indices.RemoveAt(indices.Count - 1);
                }
                else
                {
    
    
                    // jave.lin : push padding, 否则我们使用 push 最后一个顶点作为 padding 的方式
                    indices.Add(lastOneVal);
                }
            }
        }

indices out of bounds vertices - 暂无解决方法

这个问题是 GPA 的 BUG
暂时无解,连 index 的数值都错了,我们是不可能知道正确的数值的,只能猜:比如,可能是 数据类型溢出?
就是新版本的 fbx 模型,可能使用了 index buffer 的索引值的压缩技术,可能在 GPA 中没有对应实现解析,那么肯定会有报错的

这个 index 索引值的压缩技术大概是这么个思路:

  • 如果 index < byte.MaxValue,那么 index 使用 byte 类型解析
  • 如果 index < ushort.MaxValue,那么 使用 ushort 类型解析
  • 如果 index < uint.MaxValue,那么 使用 uint 类型解析

Project

  • github 工程后续上传
  • 百度盘工程后续上传

References

猜你喜欢

转载自blog.csdn.net/linjf520/article/details/127066726
GPA