场景层数据定义和能力开发是正交的,其扩展方式,可以用这个table解释:
右侧场景能力(feature sets, traits) 下侧场景数据定义(scene content, types) | webgpu rendering (某种渲染能力) | content optimization(merge, instance) 某种优化或处理能力 | import gltf(某种外部io能力) | interactive query (picking) | ... more features |
---|---|---|---|---|---|
scene-core 场景核心数据定义 | scene-webgpu-rendering | scene-optimization | scene-io-gltf | scene-geom-query | .. |
为特定领域服务的场景数据定义扩展包 | .. | .. | .. | .. | .. |
more data.. | .. | .. | .. | .. | .. |
扩展新的场景对象就是添加一行实现:添加场景对象的定义,然后针对这些定义实现所有其他的能力接口。在代码组织上,上表中除了表头每一个单元格可作为独立的实现模块(比如采用独立的crate),也可以对常见的能力可聚合成一个crate做实现。
每一种场景能力的都有其特定的扩展方式,这些方式的特征一般是要求实现某些trait,并且将这些实现以动态注册或者静态组合的方式进行组装。这些扩展方式的具体设计在工程上具备一些挑战,也是值得研究的具体问题。
设计和坚持这样的feature矩阵,核心目的是我们希望实现这样的愿景:
渲染器/图形能力 是可以根据实际需求定制组装出来, 框架建设目标的不是具体的渲染/能力实现,而是渲染/能力本身的framework。
如果我的用户不需要某些feature,也不需要某些数据,那么就可以轻松移除实现。如果某个feature对于用户特别重要,那么强化版本的实现可以被特别的开发和引入。比如有的业务场景要用运行速度换内存消耗。比如有的业务场景高度动态,就没必要支持增量更新。比如有的目标客户端内存用量特别受限,比如web上binary size比较重要。有时候要用内存换速度。比如bvh加速picking,比如场景优化。
从feature层面看,在基本抽象成熟之后,假设有充裕的开发资源,那么会迟早把所有的有不同tradeoff的实现都做一遍,然后不同用户组优雅的灵活的装出他最适合自己场景的渲染器。以至于最后不存在说我们的渲染器不适合某种类型的场景,不适合某类用户,而是我们的渲染器长期完全没有缺点。
对“充裕的开发资源”的假设是理想的,这样的基础工程框架可能只能是以开源的方式存在。因为没有任何公司有足够的动机甚至意识去做这样的工程建设。