Metal原生开发·与OGRE对比

2023-05-26 0 526

最近想再深入的研究呵呵Metal图形命令,所以找到了两本raywenderlich出版的书:

假如熟悉IOS合作开发,raywenderlich的名字肯定不孤单,市售有关Metal的书特别少,就行了一搜还都是机械加工各方面的 ,这两本书厚达800页,Cubzac一点一点教你怎么构筑两个格斗游戏发动机的构架,难能可贵的开卷,是价格有点儿贵,60刀,执意购得了。看了第三部份,最大的觉得是,这构架不是和OGRE的傻哥那样吗?但是比间接看OGRE标识符完蛋的容易的太多,几乎每一节结尾都是先解构上一节的标识符,接着增加捷伊内容,不断的插值。第三个觉得是间接用Xcode合作开发格斗游戏原来那么简单,原本我还以为会搞一大堆数学类,接着类似于OGRE那样弄两个巨大的分层写入方法,结论这些东西MetalKit和Model I/O全给搞掂了,假如用SceneKit去合作开发,估算会弄得更快。同时,将资源写入到Xcode,还能设置图形的MipMap和动画电影本篇,过去始终试著用“虚拟化”的发动机始终享受不到这种社会福利,想到这无可奈何的开始怀疑虚拟化的意义。(这一点我最后再说)这两本书的另外两个益处是Swift,苹果公司非官方非常残花,一各方面力推Swift,结论Metal各方面的实例全被是OBJC写的,而且我发现,MetalDirect3D由于仿效了C++的句法,结论导致只能include Objc的子程序,swift还需要架两个bridge。

我之所以想写那么一则文章,其实是想向大家展现呵呵OGRE“原本的模样”,当然这个样子也不一定是OGRE最原始的模样,最简单的模样,但确实是两个能生长成OGRE的转捩点,有了这两个基础,OGRE的一脉相承也就基本上把握了,先期也全然没有必要全然学OGRE合作开发。目前我展现的是书中第三部份结束后的模样,大致就能有两个类似于宋军兵这样的F1格斗游戏构架,附送圣夫龙的构架,等看完了我有点儿想把Bullet的OpenCL标识符移殖到Metal上面来,把物理演示的部份Bazelle了。该构架不高文瑞先期会做的更加复杂,但基本上内部结构估算也不会改变太多了。

OK,话不多说,进入自问自答,先上一张情景图的内部结构:

Metal原生开发·与OGRE对比
Scene
Metal原生开发·与OGRE对比
MainLogic

因为是教程,不会太复杂,这两张图基本上上已经说完了所有的逻辑。熟悉Apple平台合作开发的童鞋应该知道StoryBoard,大致是描述了应用程序的外观,接着将窗口控件连接到对应的标识符类型就能够显示图像了。首先是两个GameView,作为MTKView的子类,负责的主要是窗口范围内的事件处理,而NSViewController则是窗口图形的主力。其中Render作为MTKViewDelegate会监听视图,并且每一帧都会调用draw来绘制图像。Metal的主要逻辑大致如下:

Metal原生开发·与OGRE对比
创建devicemakeCommandQueuemakeCommandBuffermakeRenderCommandEncodersetRenderPipelineStatepresentcommit

其中每一帧都需要makeRenderCommandEncoder,并且将对应的Direct3D配置在PSO当中,接着调用setRenderPipelineState设置,这部份之前的OGRE解析里面都介绍过。书中一开始所有这一切都在Render中完成,后来逐渐的将图形命令的大部份转移到Renderable当中(是不是开始觉得很像了)

我们看到最重要的是Scene,每一帧都会先update情景图,接着调用scene.renderable.render将图形资源和命令放置到commandEncoder当中,情景图主要由Node组成,其实能理解成两个链表数组,swift实现数据内部结构能参考raywenderlich的另外一两本书:

后者也是raywenderlich的开源库,算是swift语言在GitHub上star数排前列的库,甚至还有中文翻译。

回到自问自答来看Scene的update,大致做了几件事:

根据用户的输入更新相机,并且处理碰撞将相机的矩阵保存在uniform当中,等下送到Direct3D调用虚函数updateScene,子类能复写这个函数(暂时没用)按照顺序进行node.update

odel,其实Model是OGRE里面的Item,它包含Mesh和AnimationClip,接着Mesh又包含了Submesh,Skeleton,TransformComponent,简直和OGRE一模那样的内部结构。之所以那么设计,是因为两个分层上的不同部份能指定不同的材质,而submesh则是保存material,texture,甚至Pso的地方。但需要指出的是,OGRE里面费力实现的这一结构,MetalKit全部现成提供,例如MTKMesh表示mesh,MTKSubmesh表示submesh,MTLTexture表示texture,当然啦,你会说OGRE是两个虚拟化的发动机,所以肯定在上层做了封装,但我折腾到现在的两个觉得是,虚拟化是一场梦,必须承认Metal并不是两个非常强大的图形API,DX12秒他几条街,最捷伊DX12 Ultimate已经试图将传统的图形光线内部结构改造成Mesh Shader,用以支持更加强大的控制,这种情况下,虚拟化封装又有什么作用?与其折腾封装,不如好好利用系统原生植物提供的资源,和系统原生植物IDE做更精密的结合,才能发挥出最大的效果,我自己并不做3A格斗游戏,但假如做3A格斗游戏,估算也不会研究Metal,出门右转DX12走起。这里再插一句,在OGRE当中我们看到过合成Direct3D,OGRE实现了两个HLMS系统,将Direct3D片段组装起来,我们知道在Direct3D当中使用分支往往会降低效率,但是Metal提供两个功能类似于:

static func makeFunctionConstants(textures: Textures) -> MTLFunctionConstantValues { let functionConstants = MTLFunctionConstantValues() var property = textures.baseColor != nil functionConstants.setConstantValue(&property, type: .bool, index: 0) property = textures.normal != nil functionConstants.setConstantValue(&property, type: .bool, index: 1) property = textures.roughness != nil functionConstants.setConstantValue(&property, type: .bool, index: 2) property = textures.metallic != nil functionConstants.setConstantValue(&property, type: .bool, index: 3) property = textures.ao != nil functionConstants.setConstantValue(&property, type: .bool, index: 4) return functionConstants } fragmentFunction = try library?.makeFunction(name: “fragment_mainPBR”, constantValues: functionConstants)

makeFunction接受两个MTLFunctionConstantValues,使得编译Direct3D标识符时能自动的根据Direct3D当中的if判断剔除掉无关的部份。也是说,我们能将所有光照的图形标识符都写在两个Direct3D里面,接着写if判断属于何种光照,且不影响效率。是不是就类似于合成Direct3D的作用?所以原生植物的API就有原生植物API的优点。

扯得有点儿远,接下里我们看到图形的主要部份是一句话:

renderable.render(renderEncoder: renderEncoder, uniforms: scene.uniforms, fragmentUniforms: scene.fragmentUniforms)

情景图当中的renderable恰好又是Model,在Swift当中不允许多重继承,却能通过协议进行扩展,Renderable就被声明为两个协议,只有两个方法,即render,图形的逻辑和Model的内部结构是类似于的:

setVertexBuffer,设置骨骼分层,变换等资源进入submesh,setFragmentTexture,设置图形,pso等资源最后调用draw命令

总结

读完书中的第三部份,我逐渐对格斗游戏构架合作开发有了一点觉得,render操作,无论在这里还是OGRE当中,都是标识符的底层,OGRE当中甚至用两个RenderSystem来包装以实现虚拟化。但事实上,真正的合作开发逻辑应该如下:

先实现两个简单的图形,构造好Render将Render当中有关资源的部份封装到Model当中,实现简单的光照实现骨骼,所以引入Animation和Skeleton实现多物体,比如开车,需要构造情景图的链表内部结构,将Model作为情景图的成员

在OGRE当中更进一步由Compositor来控制Scene,这里还没到这个程度,但到了这里基本上上用户已经不太需要碰到图形,只需要用Scene组织好GameLogic即可。所以Render从一开始的C位,逐渐成为两个接纳图形指令的底层对象。

在《格斗游戏发动机构架》当中,我们能看到图形时偏底层的,但假如从底层一点一点的合作开发,实际上做不出两个格斗游戏发动机,只有从上层合作开发,逐渐分离组件,才能边写边解构地将底层组件分离出来,实现标识符的重用。

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务