如何将每个模型的模型矩阵仅发送到着色器一次 [英] How to send my model matrix only once per model to shaders

查看:88
本文介绍了如何将每个模型的模型矩阵仅发送到着色器一次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为参考,我正在关注教程.现在假设我有一个具有多种模型类型的小应用程序,如果我理解正确,我必须将每个模型的MPV矩阵从CPU发送到GPU(换句话说,将其发送到我的顶点着色器),因为每个模型可能具有彼此不同的模型矩阵.

For reference, I'm following this tutorial. Now suppose I have a little application with multiple types of model, if I understand correctly I have to send my MPV matrix from the CPU to the GPU (in other words to my vertex shader) for each model, because each model might have a different model matrix from one to another.

现在查看教程和

Now looking at the tutorial and this post, I understand that the call to send the matrix to my shader (glUniformMatrix4fv(myMatrixID, 1, GL_FALSE, &myModelMVP[0][0])) should be done for each frame and for each model since each time it overwrites the previous value of my MVP (the one for my last model). But, being concerned about the performance of my app, I don't want to send useless data through the bus and if I understand correctly, my model matrix is constant for each model.

我正在考虑为每个模型的MVP矩阵提供统一的方法,但是我认为它是不可扩展的,并且如果我的视图或投影矩阵发生更改,我还必须更新所有模型...是否有避免的方法多次发送我的模型矩阵,仅在更改后发送我的视图和投影矩阵?

I'm thinking about having an uniform for each model's MVP matrix, but I think it is not scalable and I would also have to update all of them if my view or projection matrices changed... Is there a way to avoid sending multiple times my model matrices and only send my view and projection matrices upon change?

推荐答案

本质上,这是两个问题:如何在仅变换顺序的一部分发生变化时如何避免发送数据,以及如何有效地提供可能或可能的按模型数据自上一帧以来没有改变.

These are essentially two questions: how to avoid sending data when only part of a transformation sequence changes, and how to efficiently supply per-model data which may or may not have changed since the last frame.

首先,您有一个转换序列.您的位置在模型空间中.然后,从概念上将它们转换为世界空间,然后转换为摄影机/视图空间,最后转换为剪辑空间,然后将位置写入gl_Position.

For the first, you have a transformation sequence. Your positions are in model space. You then conceptually transform them into world space, then to camera/view space, then finally to clip space, where you write the position to gl_Position.

大多数这些转换在整个帧中都是恒定的,但可能会在逐帧的基础上发生变化.因此,您要避免更改不需要严格更改的数据.

Most of these transformations are constant throughout a frame, but may change on a frame-to-frame basis. So you want to avoid changing data that doesn't strictly need to be changed.

如果要执行此操作,则显然不能提供"MVP"矩阵.也就是说,您不应有一个包含整个转换的矩阵.相反,您应该有一个代表转换的特定部分的矩阵.

If you want to do this, then clearly you cannot provide an "MVP" matrix. That is, you should not have a single matrix that contains the whole transformation. You should instead have a matrix that represents particular parts of the transformation.

但是,出于性能以外的原因,您将需要执行此分解.您不能在剪辑空间中执行许多照明操作;作为一个非线性空间,它搞砸了很多照明操作.因此,如果要进行照明,则需要在剪辑空间之前停止转换.

However, you will need to do this decomposition for reasons other than performance. You cannot do many lighting operations in clip-space; as a non-linear space, it messes up lots of lighting operations. Therefore, if you're going to do lighting at all, you need a transformation that stops before clip space.

相机/视图空间是照明计算最常见的停止点.

现在,如果您使用模型到摄像机"和摄像机到剪辑",那么即使摄像机本身未移动,当摄像机更改时,每个模型的模型到摄像机矩阵也会发生变化.因此,您可能需要上传一堆严格不需要更改的矩阵.

Now, if you use model-to-camera and camera-to-clip, then the model-to-camera matrix for every model will change when the camera changes, even if the model itself has not moved. And therefore, you may need to upload a bunch of matrices that don't strictly need to be changed.

为避免这种情况,您需要使用模型到世界"和世界到剪辑"(在这种情况下,您要在世界空间中进行照明).这里的问题是您可能会遇到世界空间的危险数值精度可能会成为问题.

To avoid that, you would need to use model-to-world and world-to-clip (in this case, you do your lighting in world space). The issue here is that you are exposed to the perils of world space Numerical precision may become problematic.

但是这里是否存在真正的性能问题?显然,这在某种程度上取决于硬件.但是,请考虑许多应用程序具有数百个(甚至不是数千个)对象,每个对象的矩阵每帧都会更改.一个动画角色通常为自己改变一百多个矩阵.

But is there a genuine performance issue here? Obviously it somewhat depends on the hardware. However, consider that many applications have hundreds if not thousands of objects, each with matrices that change every frame. An animated character usually has over a hundred matrices just for themselves that change every frame.

因此,上载可能一直不变的几个矩阵的性能开销似乎不太可能是现实问题.

So it seems unlikely that the performance cost of uploading a few matrices that could have been constant is a real-world problem.

您真正想要的是将按对象数据的存储与程序对象本身分开.可以通过UBO或SSBO来完成;在这两种情况下,您都将统一数据存储在缓冲区对象中.

What you really want is to separate your storage of per-object data from the program object itself. This can be done with UBOs or SSBOs; in both cases, you're storing uniform data in buffer objects.

前者通常较小(64KB左右),而后者在其存储中基本上不受限制(最小16MB).显然,前者通常访问速度较快,但不应认为SSBO速度较慢.

The former are typically smaller in size (64KB or so), while the latter are essentially unbounded in their storage (16MB minimum). Obviously, the former are typically faster to access, but SSBOs shouldn't be considered to be slow.

每个对象都有一部分用于每个对象数据的缓冲区.因此,您可以根据自己的喜好选择是否更改.

Each object would have a section of the buffer that gets used for per-object data. And thus, you could choose to change it or not as you see fit.

即使如此,这样的系统也不能保证更快的性能.例如,如果在尝试更改该帧时该实现仍从最后一帧的缓冲区中读取,则该实现将不得不分配新的内存或仅等到GPU完成时再进行操作.这不是一种假设的可能性;复杂场景的GPU渲染经常落后于CPU一帧.

Even so, such a system does not guarantee faster performance. For example, if the implementation is still reading from that buffer from last frame when you try to change it this frame, the implementation will have to either allocate new memory or just wait until the GPU is finished. This is not a hypothetical possibility; GPU rendering for complex scenes frequently lags a frame behind the CPU.

因此,为了避免这种情况,您需要对每个对象的数据进行双重缓冲.但是,这样做时,即使数据没有变化,也必须始终上传其数据.为什么?因为它可能在两帧之前已更改,并且您的双缓冲区中有旧数据.

So to avoid that, you would need to double-buffer your per-object data. But when you do that, you will have to always upload their data, even if it doesn't change. Why? Because it might have changed two frames ago, and your double buffer has old data in it.

基本上,您试图避免上传有时静态的基于模型的数据的目标可能会损害性能,而有助改善性能的可能性.

Basically, your goal of trying to avoid uploading of sometimes-static per-model data is just as likely to harm performance as to help it.

这篇关于如何将每个模型的模型矩阵仅发送到着色器一次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆