渲染

1、功能简介

PeriDyno通过渲染模块提供对场景图中各类节点的基础可视化功能。

class VisualModule : public Module

目前PeriDyno实现了一套基础OpenGL的渲染引擎和对应的各类节点(Nodes)的渲染模块,以支持用户图像界面(Qt/GLFW)的可视化与交互支功能。

2、使用渲染模块

在PeriDyno用户图形界面框架(Qt/GLFW)下,通过设置渲染模块的属性,并将其加入到目标节点的图形管线(graphicsPipeline)中,以实现节点的可视化功能。

2.1、表面三角网格可视化(GLSurfaceVisualModule)

参考样例GL_Bricks

PeriDyno提供GLSurfaceVisualModule节点来实现物体表面的渲染。以刚体系统为例,为了渲染物体,首先需要通过拓扑映射(TopologyMapping)将数据映射成为可渲染的三角片网格。

auto mapper = std::make_shared<DiscreteElementsToTriangleSet<DataType3f>>();
rigid->stateTopology()->connect(mapper->inDiscreteElements());
rigid->graphicsPipeline()->pushModule(mapper);

如上所示,首先构造DiscreteElementsToTriangleSet对象,并将刚体系统(rigid)的对应数据连接至mapper的输入;再将mapper对象加入到rigid对象的图形管线中,以便在调用图形管线时对内容进行更新。在构造好映射对象mapper后,我们就可以使用GLSurfaceVisualModule,通过将mapper输出到渲染模块来实现当前节点的可视化:

auto renderModule = std::make_shared<GLSurfaceVisualModule>();
renderModule->setColor(Vec3f(1, 1, 0));
// 配置可视化数据来源
mapper->outTriangleSet()->connect(renderModule->inTriangleSet());
// 将渲染模块加入到对应节点的图形管线中
rigid->graphicsPipeline()->pushModule(renderModule);

2.1、粒子(点)可视化(GLPointVisualModule)

参考代码GL_ParticleFluid

与GLSurfaceVisualModule相同,我们首先需要构造对应的映射(mapper)。例如我们首先根据流体粒子的速度计算出法向量,通过法向量来计算粒子的颜色:

auto calculateNorm = std::make_shared<CalculateNorm<DataType3f>>();
fluid->stateVelocity()->connect(calculateNorm->inVec());
fluid->graphicsPipeline()->pushModule(calculateNorm);

auto colorMapper = std::make_shared<ColorMapping<DataType3f>>();
colorMapper->varMax()->setValue(5.0f);
calculateNorm->outNorm()->connect(colorMapper->inScalar());
fluid->graphicsPipeline()->pushModule(colorMapper);

接着,我们构造GLPointVisualModule,并将流体系统的点与刚才构造的颜色映射进行连接:

auto ptRender = std::make_shared<GLPointVisualModule>();
ptRender->setColorMapMode(GLPointVisualModule::PER_VERTEX_SHADER);
fluid->stateTopology()->connect(ptRender->inPointSet());
colorMapper->outColor()->connect(ptRender->inColor());

2.1、线框可视化(GLWireframeVisualModule)

参考代码GL_Wireframe

使用GLWireframeVisualModule对三角形网格的线框进行可视化,使用方法与GLSurfaceVisualModule类似。先进行数据映射,将三角形网格数据连接到可视化模块上即可:

auto mapper = std::make_shared<DiscreteElementsToTriangleSet<DataType3f>>();
rigid->stateTopology()->connect(mapper->inDiscreteElements());
rigid->graphicsPipeline()->pushModule(mapper);

auto wireframe = std::make_shared<GLWireframeVisualModule>();
wireframe->setColor(Vec3f(1, 1, 0));
mapper->outTriangleSet()->connect(wireframe->inEdgeSet());
rigid->graphicsPipeline()->pushModule(wireframe);

2.1、实例可视化(GLInstanceVisualModule)

参考代码GL_InstanceVisualizer

在PeriDyno中,可以通过额外的变换矩阵数组来表示实例化的节点。与其他可视化模块类似,只需要将对应的变换矩阵传给GLInstanceVisualModule:

auto instanceRender = std::make_shared<GLInstanceVisualModule>();
instanceRender->setColor(Vec3f(0, 1, 0));
instanceNode->stateTopology()->connect(instanceRender->inTriangleSet());
instanceNode->stateTransforms()->connect(instanceRender->inTransform());
instanceNode->graphicsPipeline()->pushModule(instanceRender);

3、扩展渲染模块

PeriDyno对节点的可视化提供统一父类(GLVisualModule),实现新的可视化效果需继承该类并重载相应的方法。

参考代码GLVisualModule.h

virtual bool initializeGL() = 0;
virtual void updateGL() = 0;
virtual void paintGL(RenderPass pass) = 0;

其中,initializeGL()方法在对象初始化时仅被调用一次。通常用于加载对应的Shader,创建所需的Buffer等对象。当仿真更新时,updateGL()方法将被调用,用于同步仿真数据与渲染数据(例如将当前帧修改后的三角形网格更新到OpenGL的VertexBuffer中、更新当前粒子颜色等)。paintGL()在具体执行渲染时被调用。目前PeriDyno提供的基础OpenGL渲染引擎包含两个简单的RenderPass:ShadowPass和ColorPass,其中ShadowPass用于更新ShadowMap来得到阴影效果,ColorPass用于得到最终窗口中所展示的彩色图像。