类关系:
SceneDesktop 包含 struct SceneDesktopPrivate 变量,SceneDesktopPrivate 中包含 RenderScreen 和 RenderClearImage
RenderWindowBlur 和 RenderWindowShadow 是effect的具体实现类。
上面是集成和类的组合关系,使用的关系为:
- screen
代表的是屏幕,即默认的窗口framebuffer
screen在SceneDesktopPrivate的初始化的时候用的是canvas,和其他scene一样,底层用的普通的窗口系统egl/glx。这些通过fbo来进行控制:
class RenderScreen : public RenderObject
{
public:
RenderScreen(Canvas &canvas) { fbo_ = canvas.fbo(); }
virtual void init() {}
virtual void release() {}
};
- desktop
代表的背景纹理图像
创建一个framebuffer来实现,绘制一个全屏的正方行,将纹理贴到上面,desktop上有一层纹理,然后在纹理上再画其他小窗口。 - windows
是具体的小窗口
小窗口根据 effect 参数的类型,用RenderWindowBlur 或 RenderWindowShadow
上面这四个类的基类都是窗口绘制类 RenderObject
SceneDesktop 类
和其他的scene类的方法一样,包含:load、unload、setup、teardown、update、draw、validate。重点介绍setup、构造函数
构造函数
创建 SceneDesktopPrivate 对象,设置输入参数默认值。
setup
- 获取输入参数值
- 查找纹理,放到textureMap中
- 初始化clearcolor等
- 调用screen.init初始化canvas
- 调用desktop.init到RenderObject的init中,初始化FBO、texture对象、program对象
- 设置screen和desktop的size
- 计算子窗口的大小和位置,根据effect参数创建子窗口,然后初始化,并绘制到背景大窗口中,其实是绘制到fbo上。
for (unsigned int i = 0; i < windows; i++) {
RenderObject* win;
if (options_["effect"].value == "shadow")
win = new RenderWindowShadow(shadow_size);
else
win = new RenderWindowBlur(passes, blur_radius, separable);
win->init();
win->render_to(priv_->desktop);
priv_->windows.push_back(win);
}
- 再将fbo切换回来,计算帧率和时间参数
teardown
中件的关系:
screen是最大的
desktop.render_to(priv_->screen)
四个win->render_to(priv_->desktop);
- 修改去掉背景:让四个win直接render到screen上,去掉desktop,将fbo改成0,去掉fbo的创建
- 减少CPU的运算量,让四个win的位置固定----------update中的内容注释掉
- 在effect2d中添加四个窗口
update
计算新的win->position,计算方法:在分别x、y两个方向上,在旧的位置上加上偏移量(偏移量=speed*delta_time),计算的结果如果小于0,或加上边框超出canvas的范围,给速度取个反向。
draw
进行绘制,如上面的关系,先clear desktop,然后将四个window渲染到desktop上,然后将desktop渲染到screen上。
validate
和其他的scene相同,读一个点的像素进行比较
RenderClearImage 类
构造函数用RenderObject的构造函数,制定一个纹理名,作为背景照片。
init
- 调用 RenderObject::init();
- 用 Texture::load 加载创建背景的纹理对象 background_texture_
release
- 删除纹理对象 background_texture_
- 释放 RenderObject 中申请的纹理对象和fbo
clear
用纹理进行清屏绘制,绘制一个全屏的正方形贴上 background_texture_
RenderWindowBlur 类
init
调用的是 RenderObject 的 init
这里会有一个静态的变量成员 use_count ,记录new的个数。init中++,对应在release中–。window_contents_ 是一个 RenderClearImage 的对象,
draw_contents_ 控制是否绘制内容,设置位false后四个小窗口不渲染。
size
设置window的size
render_to
将rendertarget渲染到window_contents_(RenderClearImage类型,用来指向窗口界面)上,draw_contents_这个参数可以控制是否直接绘制屏幕上。好处在于统一了render的关系。
用的shader是通过create_blur_shader创建出来的,通过kernel来控制blur,提取texture中的像素,根据kernel来取偏移。
separable_ 参数是用来控制H和V两个方向的,主要实现方式是通过取kernel的参数的方法。
RenderWindowShadow 类
阴影是由5部分组成,拼接到一起的,这里shadow分成几个方向的:
shadow_h_ :下边的阴影竖条
shadow_v_ : 右边的阴影竖条
shadow_corner_ : 三个角的阴影
阴影的绘制也是用RenderObject类的render_to方法,program用的是普通的纹理贴图,没有拼接。
RenderScreen类
将fbo设置成canvas的fbo,其他的继承RenderObject类
RenderObject类
做真正的绘制
init
创建texture和fbo对象,把texture绑定到fbo的GL_COLOR_ATTACHMENT0上。
创建main_program
make_current
把fbo切换成当前的fbo
size
重新设置纹理的大小,并告诉fbo
render_to
通过中心点计算方向,计算四个角度的旋转,加上便宜,就是四个点的位置坐标,然受根据位置计算normalized,设置纹理坐标,绑定纹理,绘制正方形。
render_from
position位置固定,texcoord的位置通过ll和ur计算出来,然后绑定纹理绘制。
draw_quad_with_program
OpenGL用VertextAttribPointer绘制四边形。
算法点
- 顶点计算方式
- seperate中h和v的shader计算方式