我的OpenGL窗口如下所示:
glClearColor(0.3f, 0.4f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
我想使用纹理来填充窗口。
是否有更简单的方法,而不是创建另一个VBO,EBO,除了我已用于我的三角形的那个?
因为glClearColor填充了背景..
答案 0 :(得分:5)
使用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);
请注意,上面的代码绑定了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);
这适用于纹理和窗口具有相同大小的情况。否则,您可以在前8个参数中指定不同的大小,并且可能希望将GL_LINEAR
用于最后一个参数。
使用glBlitFramebuffer()
比绘制窗口大小的纹理四边形有一些优势:
答案 1 :(得分:4)
用一句话说:不。
在传统的OpenGL中,glDrawPixels
就好了,但是这个功能从来没有得到很好的支持,并且在大多数实现中都很慢。你最好忘记我告诉你的事情。它也已从现代OpenGL中删除,并且从未存在于OpenGL-ES中。
答案 2 :(得分:3)
这个问题已经有了一些答案,但为了完整性,我想补充一些替代方案:
<强> 1。无属性渲染
使用现代GL,您可以完全渲染而不使用顶点属性。您可以将全屏rect的4个2d coordiantes直接作为const数组放入顶点着色器,并通过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);
}
如果您的纹理与视口的分辨率完全匹配(因此您根本没有缩放纹理),则可以完全删除v_tex
变化并使用FS中的color=texelFetch(texSampler, ivec2(gl_FragCoord.xy))
,如@datenwolf在他的评论中提出。
在任何情况下,即使没有启用任何属性,您仍然需要一些VAO绑定。因此,此方法要求您在初始化期间执行以下一次:
glGenVertexArrays()
电话对于绘图,你必须:
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)
您也可以简单地重复使用当前绑定的VAO。由于着色器不访问任何属性,因此VBO提供的数据以及当前启用的属性无关紧要。
此方法要求您切换着色器,这也不是很便宜,因此最好只需切换缓冲区bindigs并保留当前着色器。但您可能还需要切换着色器。
<强> 2。 nvidia-specificc扩展
NVidia为在屏幕上绘制纹理的任务提供了特定的扩展:NV_draw_texture。这引入了glDrawTextureNV()
函数,该函数允许绘制纹理而不用设置更改GL状态的任何内容。引自扩展规范的概述部分:
虽然可以通过绘制a在未扩展的OpenGL中获得此功能 矩形并使用片段着色器进行纹理查找,
DrawTextureNV()
可能会提高电源效率 支持此扩展的实现。另外,使用此功能 扩展使应用程序开发人员不必设置 专用着色器,变换矩阵,顶点属性和 各种其他状态,以呈现矩形。
这种方法的缺点当然是它是特定于nvidia的,所以它在一般的GL应用中可能不太实际使用。
答案 3 :(得分:1)
您可以使用ortographic投影将纹理渲染到全屏四边形:
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
glDisable(GL_LIGHTING);
// Set up ortographic projection
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0, width, 0, height, -1, 1);
// Render a quad
glBegin(GL_QUADS);
glTexCoord2f(0,0); glVertex2f(0,0);
glTexCoord2f(0,1); glVertex2f(0,width);
glTexCoord2f(1,1); glVertex2f(height, width);
glTexCoord2f(1,0); glVertex2f(height,0);
glEnd();
// Reset Projection Matrix
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
将其渲染到帧缓冲区而不是glClearColor。