PDA

View Full Version : Render offscreen / to texture - basic questions



art-ganseforth
04-01-2016, 06:19 PM
Hi there,

i'm working on a c++ application under windows 10 for live-animation-arts, using OpenGL for rendering and wxWidgets for controlling. The program is just in a basic state, which means that wxWidgets-part (the window-management, and most of the module-linking and unlinking) is working fine. But with OpenGL i'm just doing the first steps - not only in this program, also concerning my own skills.

The concept is simelar to a moduar synthesizer. So modules like eg. a small window (however) definig a texture or one, defining a position and a rotation can be added / renmoved and linked to other modules defining eg. a 3d-object or a light-souce while the program is running.

I also want modules with "2d-functions".
The idea is to manipulate textures inside of the graphic-memory by eg. merging them using the blending-functions. So my project needs a lot of offscreen-rendering. In fact i want to render everyting in memory, which means that every 2d-module (even those who render 3d-objects have a 2d output, while my display has two dimensions;)) is generating a texture first and one of them can be drawn to the output in a second step, while othes are used as sorces for the module-chain. So requirements for 2d-modules are:
a) a 2d-module is associated with exact one output-texture (but may have 0 to x source-textures)
b) it can be added or deleted, which should generate or delete the associated texture-pointer (glGenTextures(1, &texptr) / glDeleteTextures(1, &texptr))
c) associated textures may change size without removing the module.
d) not every 2d-module (texture) will be updated per frame. Some may be updated only on a trigger-signal.

Now i have some basic questions concerning offscreen-rendering. because something is going wrong like eg. flickering since i konsequently implemneted it (- used some slow workarounds for testing in before).

Are the following points correct:

1. A framebufferobject just "redirects" the rendering-target to another address. It does not allocate memory itself?

2. Deleteng a framebufferobject will not free the texure-memory?

3. If there is no depth or (at least) no object will be hidden by another one, a depthbuffer is not needed?

4. A renderbufferobject is an object which links eg. a depth- or a stencilbuffer to the process, so if i don't need them, i also don't need to create a renderbuffer. In this case it will be sufficient to create a framebuffer, to render to a texture?

5. As already said, currently i'm creating a texture-pointer (glGenTextures(1, texptr)) when i create the module. The texture itself i generated just before drawing to it (wich is not in every case per frame) by:
glBindTexture (GL_TEXTURE_2D, texptr);
glTexImage2D(GL_TEXTURE_2D, 0, [internalFormat], w, h, ...);
Is this also correct?

6. If a module is deleted, i call glDeleteTextures(1, &texptr);. There is no call needed to free the memry?

7. If a texture-memory should have anoter size in a later frame (not the textue-image, which will be replaced completely afterwards - so it may be discarted) i just need to call another glBindTexture-glTexImage2D-combination with the new size. The previously used memory is given free automaticly?

8. As long as i don't do delete (=> point 5) or "recreate" (=> point 6), the texture will be kept in memory?

9. Concerning parameters of:
void glTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid * data);
Is it right that "internalFormat" means, how the data is stored in the graphich-memory, while "format" and "type" are only used to interpret *data, so for *data = NULL they are indifferent?

10. What means the index in GL_COLOR_ATTACHMENT[x]?

11. What i basicly do per calulation-step of a module is:
- bind target-texture
- create fbo
- create depthbuffer etc. and renderbuffer if depht etc. are needed
- bind source-texture
- process rendering
- delete backwards: renderbuffer, depth- & stencil-textue etc.
- delete fbo
- call glActiveTexture (GL_TEXTURE0);
Is this correct?
11b. glBindFramebuffer (GL_FRAMEBUFFER, 0); is just needed when i want to render to an output?



Thanks a lot for reading all this :)


Regards,
Frank

GClements
04-01-2016, 09:40 PM
Are the following points correct:

1. A framebufferobject just "redirects" the rendering-target to another address. It does not allocate memory itself?

2. Deleteng a framebufferobject will not free the texure-memory?

A framebuffer object (FBO) is "state", not "data". It requires some memory to hold that state, but it's a small amount of memory. It doesn't "own" the textures or renderbuffers which are attached to it, it just keeps references to them. Deleting a FBO will not delete the textures or renderbuffers.

The existence of FBOs allows you to change all of the rendering buffers with a single glBindFramebuffer() call rather than needing to make multiple glFramebufferTexure2D() or glFramebufferRenderbuffer() calls. In that regard, they're much like VAOs, but with less state.



3. If there is no depth or (at least) no object will be hidden by another one, a depthbuffer is not needed?

If you don't use depth testing (glEnable(GL_DEPTH_TEST)) or otherwise need depth values, there's no need for a depth buffer.



4. A renderbufferobject is an object which links eg. a depth- or a stencilbuffer to the process, so if i don't need them, i also don't need to create a renderbuffer. In this case it will be sufficient to create a framebuffer, to render to a texture?

In the context of FBOs, a renderbuffer is similar to a texture except that it can only be used as a framebuffer attachment; it can't be used as a texture. If you need to be able to take the result of a rendering operation and use it as a texture, then you need to use a texture. If you don't need to be able to access the data as a texture, you can use either a texture or a renderbuffer (you can still read the contents of a renderbuffer using glReadPixels(), but you can't e.g. sample it in a shader with texture() etc).

Stencil buffers rarely need to be accessed as textures so a renderbuffer is often used. Similarly for depth buffers (although that shadow mapping does need to be able to sample them as textures).



5. As already said, currently i'm creating a texture-pointer (glGenTextures(1, texptr)) when i create the module. The texture itself i generated just before drawing to it (wich is not in every case per frame) by:
glBindTexture (GL_TEXTURE_2D, texptr);
glTexImage2D(GL_TEXTURE_2D, 0, [internalFormat], w, h, ...);
Is this also correct?

It's valid, but unnecessary. You don't need to re-create the texture unless its internal format or dimensions change. If you want to fill the texture with a constant value prior to rendering, just use glClear() (or glClearBuffer() etc) after binding the FBO. If you want to fill a region of an existing texture with specific data, use glTexSubImage2D().

Also: textures are referenced by "names" (unsigned integers) rather than pointers. glGenTextures() takes a pointer to an unsigned integer or an array of such so that it can return the generated names (C's concept of function return values is somewhat limited, and is rarely used by OpenGL). Other functions (e.g. glBindTexture() take the texture name, not a pointer). The behaviour is similar for most other OpenGL "objects" (e.g. FBOs).



6. If a module is deleted, i call glDeleteTextures(1, &texptr);. There is no call needed to free the memry?

glDeleteTextures() will result in the memory being deleted at some point, although not necessarily immediately. Most OpenGL functions merely enqueue a command for subsequent execution, they don't wait until it has completed before returning. This is mostly transparent to the application. You can use glFinish() to wait until all queued commands have completed, but this may take a long time; there may be several frames' worth of commands in the queue, so don't do it unnecessarily.



7. If a texture-memory should have anoter size in a later frame (not the textue-image, which will be replaced completely afterwards - so it may be discarted) i just need to call another glBindTexture-glTexImage2D-combination with the new size. The previously used memory is given free automaticly?

Yes.



8. As long as i don't do delete (=> point 5) or "recreate" (=> point 6), the texture will be kept in memory?

Yes; for some definition of "memory" (it may be video memory, system memory, or even swapped to disk by the OS).



9. Concerning parameters of:
void glTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid * data);
Is it right that "internalFormat" means, how the data is stored in the graphich-memory, while "format" and "type" are only used to interpret *data, so for *data = NULL they are indifferent?

Essentually, yes.

Except ... even for data==NULL, internalformat, format and type must be minimally consistent. E.g. you can't use an internalformat of GL_DEPTH_COMPONENT (or a sized variant) with a format that isn't GL_DEPTH_COMPONENT, or vice versa. Similarly, "packed" types (GL_UNSIGNED_INT_8_8_8_8 etc) can't be used with a format with a different number of components. For colour formats, internalformat and format don't need to have the same number of components (extra components are ignored, missing components default to zero for red/green/blue and one for alpha).



10. What means the index in GL_COLOR_ATTACHMENT[x]?

A framebuffer can have multiple colour attachments. Each output variable of a fragment shader is bound to a particular attachment. If you can't see how this might be used, don't worry about it; just use GL_COLOR_ATTACHMENT0.



11. What i basicly do per calulation-step of a module is:
- bind target-texture
- create fbo
- create depthbuffer etc. and renderbuffer if depht etc. are needed
- bind source-texture
- process rendering
- delete backwards: renderbuffer, depth- & stencil-textue etc.
- delete fbo
- call glActiveTexture (GL_TEXTURE0);
Is this correct?

You should try to avoid creating and deleting objects and buffers unnecessarily. Try to re-use them where possible.



11b. glBindFramebuffer (GL_FRAMEBUFFER, 0); is just needed when i want to render to an output?

Binding framebuffer zero renders to the default framebuffer, typically a window.

art-ganseforth
04-02-2016, 03:38 AM
this is exactly what i wanted t know and in some points you obviousliy figuresd the "qustion behind the question" like

A framebuffer object (FBO) is "state", not "data".

No i know that i'm on the right way. I was not sure if i basically missunderstood something because the program is flickering currently. But now i think i will have to search for some pointer-mess in the basics of my program.
I know, that it is a quite sophisticated thing what i'm doing there. But one advantage of modular architectures is, that things can be implemented step by step. So, thanks again for this:
don't worry about it; just use GL_COLOR_ATTACHMENT0 This is my way to do it. Currently i don't even use light & materials and i also red almost nothing about. But if all this adding and removing of modules works (which is just one step ahead), it'll be easy to create other modules step by step implementing all this nice things like lights, materials, shaders etc., while i'm learning to use them...


Kind regards,
Frank