基本功能在51前已经做好,因为放假出去,所以没来得及更新.
底层支持
1.多视口功能的底层支持, 添加了2种方案,
A) Present到另外一个窗口
B) 多Swapchain
C) 为什么不使用D3D的viewport?感觉那个功能太简单,不满足复杂的需求(除非自己补充功能),感觉swap chain比较满足当前的情况.
当然,google了一下发现了等价的OGL(扩展)实现,所以可以封装.
第一种方法使用一个桌面(全屏)大小的共享backbuffer,present到不同的窗口, 要计算源矩形区域
第二种因为使用D3D的swap chain,相对简单,但是根据d3d sdk每个swapchain都有自己的backbuffer,但因为默认的backbuffer目前就是全屏的,改起来有点麻烦,不改的话,这个buffer又不用,资源稍微有点耗.
两种方法都试了一下,视觉上没什么大的差别,现在选用第一种方案.
2.由于viewport可以不实时更新,所以添加了同步单帧绘制的功能(之前只有基于任务的异步持续性绘制功能).
在MFC的OnPaint的时候更新非活动视图,
非实时的视图只有在鼠标移动/键盘按下时才会绘制.
设计
视口抽象:
1 enum EViewportType 2 { 3 VT_TOP = 0, 4 VT_FONT, 5 VT_LEFT, 6 VT_PERSPECTIVE, 7 8 // 9 VT_COUNT, 10 }; 11 12 typedef struct SViewportDesc 13 { 14 scalar mCameraSpeed; 15 EViewportType mType; 16 FILL_MODE mFillMode; 17 //size in percent of parent dimension 18 scalar mLeft; 19 scalar mRight; 20 scalar mTop; 21 scalar mBottom; 22 23 //real time update 24 //one view port will auto-update at real time when it is active AND this real-time switch is on. 25 bool mRealtime; 26 //active (focused) 27 bool mActive; 28 }VIEWPORT_DESC;
有了视口的描述信息,后面就方便多了,比如做视口布局信息,只要填充好结构,就可以根据这些信息切换.
1 static const int MAX_VIEWPORT_COUNT = 4; 2 typedef struct SViewportLayout 3 { 4 //view port count 5 size_t count; 6 VIEWPORT_DESC layouts[MAX_VIEWPORT_COUNT]; 7 }VIEWPORT_LAYOUT;
目前的设计是一个窗口对应一个viewportset, 一个viewportset对应1-4个viewport
由于设计比较简单,就不多说了,贴几张图吧
经典的4视图布局,每个视图都有自己的工具栏和菜单(仿UE3的那种):
4视图下透视最大化:
菜单:
布局设置:
另外,编辑器的图标全部换掉了,还是在网上下的,改用了32x32的尺寸绘制(内置了8,16,24,32几种大小,切换比较方便). 视图的图标使用16x16的.
现在视图有每种类型的渲染开关,准备加上每个buffer的选择开关(调试的时候用)
虽然现在是foward shading而且没有预深度,但是输出buffer这个功能对调试很有用处,比如调试延迟渲染的时候GBuffer的输出等等.
遇到的问题是:目前菜单项的数量不能动态更新(所有菜单只能是一次性的动态添加好),但是如果渲染方式实时切换的话,输出的buffer的类型和个数就会实时改变,当前菜单功能不满足需求.
因为菜单的功能是几年前写的,不太想改动了(运行时添加删除菜单项要修改菜单ID线性增长等等一些机制),所以目前计划是预留一定数量的菜单项,运行时修改菜单文字,以及enable/disable...这样感觉也勉强可以.
下一步可能先把Gizmo和基本工具(Rotate+Scale+Translate)完善一下,再继续搞动画.