在GLSL着色器中创建视图矩阵

3
我在GPU上存储了许多1D纹理中的位置和方向。我想将它们用作GLSL几何着色器中的渲染资源。为此,我需要从这些纹理创建相应的视图矩阵。
我的第一个想法是绕过CPU,将纹理读入内存并从那里创建一堆视图矩阵,例如使用glm::lookat()。然后将矩阵作为统一变量发送到着色器中。
我的问题是,是否可以跳过这个绕路,直接在GLSL几何着色器中创建视图矩阵?而且,从性能上来说,这可行吗?
3个回答

2
没人说(或者说不应该说)你的视图矩阵必须通过一个uniform从CPU传递过来。你可以在着色器内部直接从纹理向量生成视图矩阵。也许旧版的gluLookAt的实现对你有帮助。
这种方法在性能上是否可行,另外一个问题,但如果这个纹理相当大或经常变化,这种方法可能比将其读回到CPU更好。
但是,也许你可以使用一个简单的类GPGPU的着色器将矩阵预先生成到另一个纹理/缓冲区中,每个位置/向量在纹理中生成一个矩阵,并将其存储在另一个纹理(使用FBOs)或缓冲区(使用transform feedback)。这样你就不需要往返于CPU,也不需要为每个顶点/基元/任何东西重新生成矩阵。另一方面,这会增加所需的内存,因为一个4x4的矩阵比一个位置和一个方向要重。

1
当然。阅读纹理,并从值构建矩阵...
vec4 x = texture(YourSampler, WhateverCoords1);
vec4 y = texture(YourSampler, WhateverCoords2);
vec4 z = texture(YourSampler, WhateverCoords3);
vec4 w = texture(YourSampler, WhateverCoords4);
mat4 matrix = mat4(x,y,z,w);

有什么问题吗?还是我漏掉了什么?


-2

视图矩阵是一个uniform,而uniform在渲染批次中间不会改变,也不能直接从着色器中写入。因此,我不认为直接生成它是可能的。

另外请注意,几何着色器在顶点使用模型视图矩阵进行变换后运行,因此重新生成该矩阵或其部分(至少在同一次渲染中)并没有太多意义。

当然,您可以通过变换反馈来进行一些黑客操作,将一些值写入缓冲区,并稍后将其作为uniform缓冲区复制/绑定,或者仅从着色器内部读取这些值并将其作为矩阵相乘。这至少避免了与CPU之间的往返 - 问题是这种方法是否有意义,以及您是否真的想做这样一个晦涩的事情。如果不知道您想要实现什么,很难说哪种方法最好,但很可能只需在顶点着色器中进行转换(读取那些纹理,构建矩阵,相乘)就可以更好地完成任务并更容易。


也许我应该指定我倾向于在分层渲染中使用视图矩阵。我在几何着色器中指定要呈现到哪个层(gl_Layer)。因此,在同一次通行中呈现多个纹理层。渲染目标是 TEXTURE_2D_ARRAY - Morgan Bengtsson
在这种情况下,您可能希望使用一个空的顶点着色器(假设它们不都具有完全相同、方向完全相同的几何形状,您需要为每个图层分别进行变换)。您只需要从VS转发模型矩阵(如果它在任何地方都相同,则可能还要投影矩阵),从这些纹理中生成各自的视图矩阵,并将MVP相乘,然后将每个已生成原始图元中的每个顶点与正确的顶点(属于其所属的图层)相乘。 - Damon
@Damon 你是否意识到,你的评论使你的答案完全无效了? - Christian Rau
@ChristianRau:是的,那又怎样?这个评论基于之前不可得的关于分层渲染的重要信息。仅给出“几何着色器”和“模型视图矩阵”,回答中并没有任何无效之处。在顶点着色器中进行变换是很正常的事情,为矩阵设置一个统一变量也是很正常的事情。事后诸葛亮很容易做到,你知道的... - Damon
@Damon 之后不要再有聪明的话了。即使没有来自OP的任何进一步信息,前两段也过于死板以至于不正确。 - Christian Rau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接