24 Setting up a Test Framework
这次我们要对代码进行一些整理,为之后做好铺垫。
因为如果我们想让系统变得更复杂的话,像这样做是不行的。
首先清理下代码的结构
1 | int main(void) |
然后添加test
1 | test::TestClearColor test; |
就可以看到如下结果

test的部分结构如下
Test.h
作为Test的父类
1 |
|
1 | //TestClearColor.h |
这样就建立好了test的架构。
其实基于这个架构,我们可以做很多事了,例如在imgui上用菜单控制各种变量、贴图。。。
接下来我们要建立一个test的菜单,而不是直接打开test
25 Creating Tests
Test.h
1 |
|
Test.cpp
1 |
|
Application.cpp
1 | test::Test* currentTest = nullptr; |
我们运行后,啥都没有

但是点击Clear Color的button以后,就获得了前面的Clear Color的功能,并且包含一个回退按钮,再点击这个回退按钮

再点击这个回退按钮,这个Test实例就被注销了,并且UI也回到原来的界面,但由于Opengl是状态机修改,所以背景色的状态没有变回去

作者在循环开始时加上
1 | GLCall(glClearColor(0.0, 0.0f, 0.0f, 1.0f)); |
这样就能保证不存在TestClearColor实例时,有一个固定的背景色。(即注销实例后,背景色会清空)
为了防止内存溢出,在循环结束后,我们还要把new出来的test删掉
1 | delete currentTest; |
26 Creating a Texture Test
以上搭建的框架,其实就是建立了一个类似于沙盒,我们可以在里面设置各种测试Test
在之后的工作会进行Batch Rendering
1 |
|
TestTexture2D.cpp
1 | // |
在这里完成后,只需在main中注册。
Batch Rendering
在处理Texture的时候要注意,由于最大的Texture slot数量的限制(比如上一章节讲texture里提过当前windows最大的数量32),同一个batch往往不能容纳足够的Texture,那么只能把多余的texture对应的网格渲染放到下一个batch,以此类推。
假如100个submesh,对应100个texture,每32个texture对应的mesh合批,这样也只需要4个drawcall
静态合批大抵就是如此(把不同mesh的vertex组合起来)
Dynamic Geometry
这一段就是讲动态合批。
静态合批是我们一开始就设定好了合批的数据,每一帧只需要渲染这些已经传递到GPU的数据。
而我们希望对于动态的物体也能进行合批。
重要的依然是这两部分:vertex buffer和index buffer
除了提前准备了这一部分数据,我们还使用
1 | glBufferData(GL_ARRAY_BUFER,sizeof(vertices),vertices,GL_STATIC_DRAW) |
在update前将数据储存到GPU。
而为了动态改变数据,我们可以只创建buffer,但是先不传递数据,即传递一个空指针。
我们也可以根据我们的顶点结构和需要的顶点数量来决定buffer的大小。
1 | struct Vertex{ |
最后就是绘制方式,不再是Static,我们要换成dynamic
1 | glBufferData(GL_ARRAY_BUFER,1000*sizeof(Vertex),nullptr,GL_DYNAMIC_DRAW) |
其他关于顶点属性绑定之类都是一样的,只不过可以利用Vertex的结构来让它变得更通用
1 | glEnableVertexArrayAttrib(m_QuadVB,0); |
IB在合批中也不应该被改变。虽然我们动态地改变了顶点的属性,但是这些跟IB有什么关系。
在数量庞大的vertices当中,往往也需要用for loop来构建indices。(去年可视化的性能优化工作就是手动做了静态合批这件事……虽然当时并不知道合批这个概念)
Update
1 | //Set dynamic buffer |
然后我们就可以通过各种方式来改变绘制的顶点数据
比如通过gui来控制
1 | //OnImGuiRender |
这样就完成了动态的vertex buffer绘制,以及动态合批,我们只创建了一个vertex buffer,调用了一次drawcall。
Indices
对于两个quad,我们很简单地就可以直接写出合批的indices
1 | uint32_t indices[] = { |
但是对于数量更多的mesh,我们也可以有一定的规律来写出。
首先依然要决定我们要绘制多少个四边形,以1000个为例
1 | const size_t MaxQuadCount = 1000; |