首页 > 解决方案 > 如何将纹理应用于 OpenGL 中的子网格?

问题描述

我有一个网格,我将其划分为子网格并使用顶点的索引单独绘制。但是,我想知道将不同图像应用于每个子网格的最有效方法是什么。这些子网格是单独绘制的。例如,这是一个子网格。

mat4 view = identity_mat4();
mat4 persp_proj = perspective(100.0f, (float)width / (float)height, 0.1f, 100.0f);
mat4 model = identity_mat4();
model = rotate_y_deg(model, turn);
model = translate(model, vec3(ahead_x, 0.0f, ahead_z));
view = translate(view, vec3(0.0, 0.0, -5.0f));

// update uniforms & draw
glUniformMatrix4fv(proj_mat_location, 1, GL_FALSE, persp_proj.m);
glUniformMatrix4fv(view_mat_location, 1, GL_FALSE, view.m);
glUniformMatrix4fv(matrix_location, 1, GL_FALSE, model.m);
//glDrawElements(GL_TRIANGLES, mesh_data.mPointCount, GL_UNSIGNED_INT, 0);
glDrawArrays(GL_TRIANGLES, wheels[0], wheels[1] - wheels[0]);

有没有一种简单的方法可以实现这一目标?我正在考虑为每个正在绘制的网格绑定适当的图像,但是看到我所有的 VBO 管理都是在不同的函数中完成的,我认为它可能过于复杂。谢谢。

标签: c++openglgraphicstexture-mapping

解决方案


通常,所有子/网格将具有不同的材质和图像贴图。通常它们还需要不同的着色器,因为表面需要不同的 BRDF(双向反射分布函数)来传达对象的外观。

所以你不应该认为拥有单独的纹理本质上是不好的。如果没有太多的对象或子网格,您可以在每次绘制时设置纹理,然后保持原样。

由于您的绘制计数将接近每帧数百次调用,您可能会看到 CPU 负载越来越高,并且 fps 下降。这是您需要重新考虑方法的时候,而且没有灵丹妙药。“最有效”是每次都会有所不同,具体取决于您需要绘制的内容。

为了最简单的优化,您需要重新排序对象绘制,因此将首先绘制具有相同着色器/纹理的对象,并且您不必在绘制多个子网格之间更改纹理。

更复杂的优化将需要您将具有相同材质的多个子网格合并到一个更大的网格中,因此它将在一次绘制调用中绘制。在这一点上,您甚至可以动态创建更大的纹理(称为“纹理图集”),将多个图像组合成一个纹理,并重新定位子网格的纹理坐标以指向这个新的更大图像的正确部分。当有许多具有小纹理的对象(如精灵)时,这尤其适用。

简而言之,当您知道每帧必须绘制数百个对象时,就开始进行复杂的设计。对于更简单的场景,可以在每次绘制调用时绑定子网格的纹理。


推荐阅读