- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 OpenGL 和 GLSL 开发一个小型 3D 引擎。我目前使用纹理缓冲区对象 (TBO) 来存储我的所有矩阵(项目、 View 、模型和阴影矩阵)。但我对图形引擎中处理矩阵的最佳方法(我的意思是最有效的方法)进行了一些研究,但没有成功。目标是将最多的矩阵存储到最少数量的 TBO 中,并发生最少的状态更改以及 GPU 和客户端代码 (glBufferSubData) 之间的最少交换。
我提出了两种不同的方法(各有优缺点):
这是一个场景示例:
1 个摄像头(1 个 ProjMatrix、1 个 ViewMatrix)5个盒子(5个ModelMatrix)
这是我使用的简单顶点着色器的示例:
#version 400
/*
** Vertex attributes.
*/
layout (location = 0) in vec4 VertexPosition;
layout (location = 1) in vec2 VertexTexture;
/*
** Uniform matrix buffer.
*/
uniform samplerBuffer matrixBuffer;
/*
** Matrix buffer offset.
*/
uniform int MatrixBufferOffset;
/*
** Output variables.
*/
out vec2 TexCoords;
/*
** Returns matrix4x4 from texture cache.
*/
mat4 Get_Matrix(int offset)
{
return (mat4(texelFetch(
matrixBuffer, offset), texelFetch(
matrixBuffer, offset + 1), texelFetch(matrixBuffer, offset + 2),
texelFetch(matrixBuffer, offset + 3)));
}
/*
** Vertex shader entry point.
*/
void main(void)
{
TexCoords = VertexTexture;
{
mat4 ModelViewProjMatrix = Get_Matrix(
MatrixBufferOffset);
gl_Position = ModelViewProjMatrix * VertexPosition;
}
}
1)我目前使用的方法:在我的顶点着色器中,我使用ModelViewProjMatrix(光栅化(gl_Position)所需)、ModelViewMatrix(用于照明计算)和ModelMatrix。因此,为了避免顶点着色器中无用的计算,我决定存储 ModelViewProjMatrix、ModelViewMatrix 和 TBO 中内联的每个网格节点的 ModelMatrix,如下所示:
TBO = {[ModelViewProj_Box1][ModelView_Box1][Model_Box1]|[ModelViewProj_Box2]...}
优点:我不需要为每个顶点着色器计算乘积 Proj * View * Model(例如 ModelViewProj)(矩阵是预先计算好的)。
缺点:如果移动相机,我需要更新所有 ModelViewProj 和 ModelView 矩阵。因此,有很多信息需要更新。
2)我想到了另一种方式,我认为更有效:存储一次投影矩阵,一次 View 矩阵,最后再次存储每个盒子场景节点模型矩阵:
TBO = {[ProjMatrix][ViewMatrix][ModelMatrix_Box1][ModelMatrix_Box2]...}
所以我的顶点着色器将如下所示:
#version 400
/*
** Vertex attributes.
*/
layout (location = 0) in vec4 VertexPosition;
layout (location = 1) in vec2 VertexTexture;
/*
** Uniform matrix buffer.
*/
uniform samplerBuffer matrixBuffer;
/*
** Matrix buffer offset.
*/
uniform int MatrixBufferOffset;
/*
** Output variables.
*/
out vec2 TexCoords;
/*
** Returns matrix4x4 from texture cache.
*/
mat4 Get_Matrix(int offset)
{
return (mat4(texelFetch(
matrixBuffer, offset), texelFetch(
matrixBuffer, offset + 1), texelFetch(matrixBuffer, offset + 2),
texelFetch(matrixBuffer, offset + 3)));
}
/*
** Vertex shader entry point.
*/
void main(void)
{
TexCoords = VertexTexture;
{
mat4 ProjMatrix = Get_Matrix(MatrixBufferOffset);
mat4 ViewMatrix = Get_Matrix(MatrixBufferOffset + 4);
mat4 ModelMatrix = Get_Matrix(MatrixBufferOffset + 8);
gl_Position = ProjMatrix * ViewMatrix * ModelMatrix * VertexPosition;
}
}
优点:TBO 包含所用矩阵的确切数量。更新具有很强的针对性(如果我移动相机,我只会更新 View 矩阵,如果我调整窗口大小,我只会更新投影矩阵,最后,如果对象正在移动,则只会更新其模型矩阵)。
缺点:我需要计算顶点着色器 ModelViewProjMatrix 中的每个顶点。另外,如果场景由大量对象组成,每个对象都拥有不同的模型矩阵,我可能需要创建一个新的 TBO。因此,我将丢失项目/ View 矩阵信息,因为我将无法连接到正确的 TBO,这将我们带到我的第三种方法。
3) 将投影和 View 矩阵存储在 TBO 中,并将所有其他模型矩阵存储在另一个或其他 TBO 中,如下所示:
TBO_0 = {[ProjMatrix][ViewMatrix]}TBO_1 = {[ModelMatrix_Box1][ModelMatrix_Box2]...}
您觉得我的 3 种方法怎么样?哪一个最适合您?
预先非常感谢您的帮助!
最佳答案
解决方案 3 是大多数引擎所做的,只不过它们使用统一缓冲区(常量缓冲区)而不是纹理缓冲区。此外,它们通常不会将所有模型矩阵分组在同一个缓冲区中,它们通常按对象类型分组(因为相同的对象通过实例化一次绘制),有时按更新频率分组(对象从不移动的都在同一个缓冲区中,因此永远不需要更新)。
glBufferSubData 也可能非常慢;更新缓冲区通常比绑定(bind)不同的缓冲区慢,因为所有同步都发生在驱动程序内部。关于这一点,有一个很好的书籍章节,可以在 Internet 上免费获得,名为“OpenGL Insights:异步缓冲区传输”(Google 即可找到它)。
编辑:nvidia article您在评论中链接的内容非常有趣。他们建议使用 glMultiDrawElements 一次进行多次绘制调用(这是主要技巧,其他一切都是因为这个决定)。这可以大大减少驱动程序中的 CPU 工作,但这也意味着提供绘制对象所需的所有数据要复杂得多:您必须为矩阵/ Material 值构建/更新更大的缓冲区,并且,您还需要使用诸如无绑定(bind)纹理之类的东西才能为每个对象提供不同的纹理。所以,有趣,但更复杂。
只有当您想要绘制许多不同对象时,glMultiDrawElements才重要。他们的示例有 68000-98000 个不同的网格,这确实很多。例如,在游戏中,通常有许多相同对象的实例,但只有几百个不同的对象(最多)。最终,这取决于您的 3D 引擎需要渲染什么。
关于opengl - 使用纹理缓冲区对象 (OpenGL) 在图形应用程序中管理矩阵的有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29672810/
我的一位教授给了我们一些考试练习题,其中一个问题类似于下面(伪代码): a.setColor(blue); b.setColor(red); a = b; b.setColor(purple); b
我似乎经常使用这个测试 if( object && object !== "null" && object !== "undefined" ){ doSomething(); } 在对象上,我
C# Object/object 是值类型还是引用类型? 我检查过它们可以保留引用,但是这个引用不能用于更改对象。 using System; class MyClass { public s
我在通过 AJAX 发送 json 时遇到问题。 var data = [{"name": "Will", "surname": "Smith", "age": "40"},{"name": "Wil
当我尝试访问我的 View 中的对象 {{result}} 时(我从 Express js 服务器发送该对象),它只显示 [object][object]有谁知道如何获取 JSON 格式的值吗? 这是
我有不同类型的数据(可能是字符串、整数......)。这是一个简单的例子: public static void main(String[] args) { before("one"); }
嗨,我是 json 和 javascript 的新手。 我在这个网站找到了使用json数据作为表格的方法。 我很好奇为什么当我尝试使用 json 数据作为表时,我得到 [Object,Object]
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
我听别人说 null == object 比 object == null check 例如: void m1(Object obj ) { if(null == obj) // Is thi
Match 对象 提供了对正则表达式匹配的只读属性的访问。 说明 Match 对象只能通过 RegExp 对象的 Execute 方法来创建,该方法实际上返回了 Match 对象的集合。所有的
Class 对象 使用 Class 语句创建的对象。提供了对类的各种事件的访问。 说明 不允许显式地将一个变量声明为 Class 类型。在 VBScript 的上下文中,“类对象”一词指的是用
Folder 对象 提供对文件夹所有属性的访问。 说明 以下代码举例说明如何获得 Folder 对象并查看它的属性: Function ShowDateCreated(f
File 对象 提供对文件的所有属性的访问。 说明 以下代码举例说明如何获得一个 File 对象并查看它的属性: Function ShowDateCreated(fil
Drive 对象 提供对磁盘驱动器或网络共享的属性的访问。 说明 以下代码举例说明如何使用 Drive 对象访问驱动器的属性: Function ShowFreeSpac
FileSystemObject 对象 提供对计算机文件系统的访问。 说明 以下代码举例说明如何使用 FileSystemObject 对象返回一个 TextStream 对象,此对象可以被读
我是 javascript OOP 的新手,我认为这是一个相对基本的问题,但我无法通过搜索网络找到任何帮助。我是否遗漏了什么,或者我只是以错误的方式解决了这个问题? 这是我的示例代码: functio
我可以很容易地创造出很多不同的对象。例如像这样: var myObject = { myFunction: function () { return ""; } };
function Person(fname, lname) { this.fname = fname, this.lname = lname, this.getName = function()
任何人都可以向我解释为什么下面的代码给出 (object, Object) 吗? (console.log(dope) 给出了它应该的内容,但在 JSON.stringify 和 JSON.parse
我正在尝试完成散点图 exercise来自免费代码营。然而,我现在只自己学习了 d3 几个小时,在遵循 lynda.com 的教程后,我一直在尝试确定如何在工具提示中显示特定数据。 This code
我是一名优秀的程序员,十分优秀!