- 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/
我有一个未定义数量的显示上下文,每个都将显示一个纹理。当我调用 glGenTextures 时,我会在所有显示上下文中返回相同的名称。这会起作用吗?即使它们具有相同的名称,它们仍会存储和显示不同的纹理
我在 SVG 中看到过:文本填充是图像而不是颜色;我一直想知道使用 CSS3 是否可以实现这样的事情。 我浏览了整个网络,到目前为止只找到了基本上将图像覆盖在文本上的解决方法(请参阅 this ,这对
我是 WebGL 的新手。 :)我知道顶点数据和纹理不应该经常更新,但是当它们确实发生变化时,首选哪个:- 通过调用 gl.deleteBuffer 销毁先前的缓冲区 (static_draw) 并创
我需要将 GL_RGBA32F 作为内部格式,但我在 OpenGL ES 实现中没有得到它。相反,我只得到 GL_FLOAT 作为纹理数据类型。 OES_texture_float 规范没有说明里面的
当我执行某些几何体的渲染时,我可以在控制台中看到此警告: THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter sho
我正在尝试使用阴影贴图实现阴影,因此我需要将场景渲染到单独的帧缓冲区(纹理)。我无法让它正常工作,因此在剥离我的代码库后,我留下了一组相对简单的指令,这些指令应该将场景渲染到纹理,然后简单地渲染纹理。
我在 XNA 中使用带有自定义着色器的标准 .fbx 导入器。当我使用 BasicEffect 时,.fbx 模型被 UV 正确包裹并且纹理正确。但是,当我使用我的自定义效果时,我必须将纹理作为参数加
如果我创建一个 .PNG 1024 x 1024 的纹理并在中间画一个 124 x 124 的圆,它周围是空的,它使用的 RAM 量是否与我画一个 124 x 的圆一样124 x 124 空间上的 1
我试图在 Android 中绘制一个地球仪,为此我使用了 OpenGL。然而,为了让它更容易理解,我将从制作一个简单的 3D 立方体开始。我使用 Blender 创建我的 3D 对象(立方体),并在我
文本本身的背景图像层是否有任何 JS/CSS 解决方案? 示例 最佳答案 检查这个http://lea.verou.me/2012/05/text-masking-the-standards-way/
非功能代码: if sprite.texture == "texture" { (code) } 当 Sprite 具有特定纹理时,我正在尝试访问 Sprite 的纹理以运行代码。目前纹理仅在我的
我正在尝试学习适用于 iOS 的 SceneKit 并超越基本形状。我对纹理的工作原理有点困惑。在示例项目中,平面是一个网格,并对其应用了平面 png 纹理。你如何“告诉”纹理如何包裹到物体上?在 3
基本上, 这有效: var expl1 = new THREE.ImageUtils.loadTexture( 'images/explodes/expl1.png' ); this.material
我正在尝试将各种场景渲染为一组纹理,每个场景都有自己的纹理到应该绘制的位置...... 问题: 创建 512 个 FBO,每个 FBO 绑定(bind)了 512 个纹理,这有多糟糕。只使用一个 FB
我正在使用文本 protobuf 文件进行系统配置。 我遇到的一个问题是序列化的 protobuf 格式不支持注释。 有没有办法解决? 我说的是文本序列化数据格式,而不是方案定义。 这个问题是有人在某
我想将我的 3D 纹理的初始化从 CPU 移到 GPU。作为测试,我编写了一个着色器将所有体素设置为一个常数值,但纹理根本没有修改。我如何使它工作? 计算着色器: #version 430 layou
我可以像这样用 JavFX 制作一个矩形: Rectangle node2 = RectangleBuilder.create() .x(-100) .
我在 iPhone 上遇到了 openGL 问题,我确信一定有一个简单的解决方案! 当我加载纹理并显示它时,我得到了很多我认为所谓的“色带”,其中颜色,特别是渐变上的颜色,似乎会自动“优化”。 只是为
假设我有一个域类 class Profile{ String name byte[] logo } 和一个 Controller : class ImageController {
我正在开发一款使用 SDL 的 2D 游戏。由于某些系统的 CPU 较弱而 GPU 较强,因此除了普通的 SDL/软件之外,我还有一个使用 OpenGL 的渲染器后端。 渲染器界面的简化版本如下所示:
我是一名优秀的程序员,十分优秀!