Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenGL: fastest way to draw 2d image

Tags:

opengl

I am writing an interactive path tracer and I was wondering what is the best way to draw the result on screen in modern GL. I have the result of the rendering stored in a pixel buffer that is updated on each pass (+1 ssp). And I would like to draw it on screen after each pass. I did some searching and people have suggested drawing a textured quad for displaying 2d images. Does that mean I would create a new texture each time I update? And given that my pixels are updated very frequently, is this still a good idea?

like image 631
march Avatar asked Dec 08 '22 03:12

march


1 Answers

You don't need to create an entirely new texture every time you want to update the content. If the size stays the same, you can reserve the storage once, using glTexImage2D() with NULL as the last argument. E.g. for a 512x512 RGBA texture with 8-bit component precision:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 512, 512, 0,
             GL_RGBA, GL_UNSIGNED_BYTE, NULL);

In OpenGL 4.2 and later, you can also use:

glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 512, 512);

You can then update all or parts of the texture with glTexSubImage2D(). For example, to update the whole texture following the example above:

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 512, 512,
                GL_RGBA, GL_UNSIGNED_BYTE, data);

Of course, if only rectangular part(s) of the texture change each time, you can make the updates more selective by choosing the 2nd to 5th parameter accordingly.

Once your current data is in a texture, you can either draw a textured screen size quad, or copy the texture to the default framebuffer using glBlitFramebuffer(). You should be able to find plenty of sample code for the first option. The code for the second option would look something like this:

// One time during setup.
GLuint readFboId = 0;
glGenFramebuffers(1, &readFboId);
glBindFramebuffer(GL_READ_FRAMEBUFFER, readFboId);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                       GL_TEXTURE_2D, tex, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);

// Every time you want to copy the texture to the default framebuffer.
glBindFramebuffer(GL_READ_FRAMEBUFFER, readFboId);
glBlitFramebuffer(0, 0, texWidth, texHeight,
                  0, 0, winWidth, winHeight,
                  GL_COLOR_BUFFER_BIT, GL_LINEAR);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
like image 181
Reto Koradi Avatar answered Dec 10 '22 17:12

Reto Koradi