我的OpenGL窗口是这样绘制的:
glClearColor(0.3f, 0.4f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
Run Code Online (Sandbox Code Playgroud)
我想用一个纹理来填充窗口.
有没有更简单的方法,而不是创建另一个VBO,EBO除了我已经用于我的三角形的那个?
因为有glClearColor填充背景..
这个问题已经有一些答案,但为了完整性,我想添加更多替代方案:
1.无属性渲染
使用现代 GL,您可以完全渲染而无需顶点属性。您可以将全屏矩形的 4 个 2d 坐标直接作为常量数组放入顶点着色器中,并通过以下方式访问它们gl_VertexID:
// VERTEX SHADER
#version 150 core
out vec2 v_tex;
const vec2 pos[4]=vec2[4](vec2(-1.0, 1.0),
vec2(-1.0,-1.0),
vec2( 1.0, 1.0),
vec2( 1.0,-1.0));
void main()
{
v_tex=0.5*pos[gl_VertexID] + vec2(0.5);
gl_Position=vec4(pos[gl_VertexID], 0.0, 1.0)
}
// FRAGMENT SHADER
#version 150 core
in vec2 v_tex;
uniform sampler2D texSampler;
out vec4 color;
void main()"
{
color=texture(texSampler, v_tex);
}
Run Code Online (Sandbox Code Playgroud)
如果您的纹理与视口的分辨率完全匹配(因此您根本不缩放纹理),则可以完全删除FS 中的v_tex变化和使用,正如 @datenwolf 在他的评论中建议的那样。color=texelFetch(texSampler, ivec2(gl_FragCoord.xy))
无论如何,您仍然需要一些 VAO 绑定,即使其中没有启用任何属性。所以这个方法需要你在初始化的时候做一次如下操作:
glGenVertexArrays()通过调用创建新的 VAO 名称对于绘图,你必须:
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)您也许还可以简单地重新使用当前绑定的 VAO。由于着色器不访问任何属性,因此您的 VBO 提供什么数据以及当前启用哪些属性并不重要。
此方法需要您切换着色器,这也不是很便宜,因此最好只切换缓冲区绑定并保留当前着色器。但是您可能仍然需要切换着色器。
2.nvidia特定扩展
NVidia 为在屏幕上绘制纹理的任务提供了特定的扩展:NV_draw_texture。这引入了glDrawTextureNV()允许绘制纹理而无需在 GL 状态上进行任何设置更改的功能。引用扩展规范的概述部分:
虽然可以在未扩展的 OpenGL 中通过绘制矩形并使用片段着色器进行纹理查找来获得此功能,但
DrawTextureNV()在支持此扩展的实现上可能会具有更好的电源效率。此外,使用此扩展使应用程序开发人员不必设置专门的着色器、变换矩阵、顶点属性和各种其他状态来渲染矩形。
当然,这种方法的缺点是它是 nvidia 特定的,因此在一般 GL 应用中可能不太实用。
将纹理绘制到窗口的最直接且通常最有效的方法是使用glBlitFramebuffer().
要使用它,您需要创建一个FBO,并将纹理附加texId到它:
GLuint fboId = 0;
glGenFramebuffers(1, &fboId);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fboId);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, texId, 0);
Run Code Online (Sandbox Code Playgroud)
请注意上面的代码绑定GL_READ_FRAMEBUFFER,因为我们想要使用它作为blit的源.
然后,复制内容:
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); // if not already bound
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
Run Code Online (Sandbox Code Playgroud)
这适用于纹理和窗口具有相同大小的情况.否则,您可以在前8个参数中指定不同的大小,并且可能希望GL_LINEAR用于最后一个参数.
使用glBlitFramebuffer()与绘制窗口大小的纹理四边形相比具有一些优势: