使用 OpenGL 和纹理在同一窗口中查看 2x2 网格中的多个图像
Posted
技术标签:
【中文标题】使用 OpenGL 和纹理在同一窗口中查看 2x2 网格中的多个图像【英文标题】:Viewing multiple images in a 2x2 grid in the same window using OpenGL and textures 【发布时间】:2020-12-21 16:57:17 【问题描述】:我正在学习 OpenGL 以尝试创建一些基本的可视化工具。我要做的第一件事是从 4 个摄像头渲染保存的图像。想要获得 2x2 图像的布局
我正在关注有关使用纹理的本教程(https://learnopengl.com/Getting-started/Textures 和完整源代码https://learnopengl.com/code_viewer_gh.php?code=src/1.getting_started/4.1.textures/textures.cpp)。我可以成功加载其中一张图像并将其显示到全尺寸窗口。我将示例中的vertices[]
数组更改为最大值(在所有方向上为-1 到1)以获得全屏显示。我的问题是,对 OpenGL 不熟悉
这是使用顶点着色器和片段着色器的最佳/现代方法吗?大约 5 到 10 年前有很多图像示例做了不同的事情。
如果我加载了四张图片,我可以为每张图片重复使用相同的顶点和片段着色器吗?
我目前对在 2x2 网格中渲染图像的想法是为每个象限创建 4 个vertices[]
(-1 到 0、0 到 1 等)。这意味着我需要 4 个顶点 VAO 对象。这是最好的方法,还是可以做一些更简单的方法?
一旦我得到它的工作,我会为未来的读者分享/发布代码。
【问题讨论】:
您可以使用多重纹理,因此将每个图像绑定到不同的纹理单元,并且只有单个 VBO/VAO 和渲染调用。您也可以只传递单个 Quad-1,+1
并从中计算纹理坐标和顶点着色器中的源纹理,无需渲染 4 个四边形但是将每帧上的 4 个纹理加载到 GL 中可能会很慢......不是这方面的专家但是我认为在新的 GL api 中的 IIRC 有一些使用 PBO 或 FBO 进行更快传输的机制。如果您有大量 GPU 内存,您可以使用纹理数组并将整个或部分视频加载到 GPU 中,然后“延迟”加载每 n 帧
你也可以对 3D 纹理做同样的事情......这里是同时使用多个纹理的例子Normal mapping gone horribly wrong 这里是 3D 纹理的例子 3D voxel back raytracing 纹理数组几乎是一样的,这里是 GLSL debug prints是从片段着色器打印文本的示例(您可以使用它进行调试,或打印帧信息或其他)它还显示了如何从位置计算纹理坐标..
【参考方案1】:
如果没有任何代码提供您正在尝试做的事情的进一步上下文,很难提供“最佳方法”。
这是使用顶点着色器和片段着色器的最佳/现代方法吗?大约 5 到 10 年前有很多图像示例做了不同的事情。
没有看教程,很难给出答案。但是,我假设您指的是使用固定功能管道的示例。如果是这样,那么是的,坚持使用着色器。
如果我加载了四张图片,我可以为每张图片重复使用相同的顶点和片段着色器吗?
假设您的片段着色器在某种程度上与您链接的那个 (4.1.texture.fs) 相匹配,即归结为如下内容:
#version 330 core
out vec4 fragColor;
in vec2 vTexCoord;
uniform sampler2D tex;
void main()
fragColor = texture(tex, vTexCoord);
那么是的,您可以重用着色器。假设您当前的方法涉及 4 个绘制调用,那么在绘制调用之前只需 bind 所需的纹理。
我目前对在 2x2 网格中渲染图像的想法是为每个象限(-1 到 0、0 到 1 等)创建 4 个顶点[]。这意味着我需要 4 个顶点 VAO 对象。这是最好的方法,还是可以做一些更简单的方法?
据我了解,您的顶点数据不会因每个图像而改变。只有位置和实际图像。因此,您可以在顶点着色器中使用矩阵来转换顶点,而不是复制顶点数组和顶点数据。
您将在后续的 LearnOpenGL "Transformations" 教程中了解这一点。
简而言之,您需要将uniform mat4 mvp
添加到顶点着色器中,并将其与顶点位置相乘,如下所示:
#version 330 core
layout (location = 0) in vec3 pos;
uniform mat4 mvp;
void main()
gl_Position = mvp * vec4(pos, 1.0);
还有其他方法,您可以通过一次绘图调用来完成您想要做的事情。
您可以使用“texture atlas” 如果所有图片尺寸相同,您可以使用“array texture” 您还可以使用uniform
array 的纹理
要使用数组纹理,您的着色器需要指定sampler2DArray
而不是sampler2D
。随着您的vTexCoord
需要提供第三个坐标,代表图层。
#version 330 core
out vec4 fragColor;
in vec3 vTexCoord;
uniform sampler2DArray tex;
void main()
fragColor = texture(tex, vTexCoord);
与 uniform
纹理数组相比。您需要将layer
属性添加到您的顶点数据和着色器中。
顶点着色器:
#version 330 core
layout (location = 0) in vec3 pos;
layout (location = 1) in vec2 texCoord;
layout (location = 2) in uint layer;
flat out uint vLayer;
uniform mat4 mvp;
void main()
vTexCoord = texCoord;
vLayer = index;
gl_Position = mvp * vec4(position, 0.0, 1.0);
片段着色器:
#version 330 core
out vec4 fragColor;
in vec2 vTexCoord;
flat in uint vLayer;
uniform sampler2D tex[4];
void main()
fragColor = texture(tex[vLayer], vTexCoord);
【讨论】:
以上是关于使用 OpenGL 和纹理在同一窗口中查看 2x2 网格中的多个图像的主要内容,如果未能解决你的问题,请参考以下文章