OpenGL Framebuffer size limit is 0 - opengl

I use OpenGL FrameBuffer Objects (FBO) to render to textures using either GL_ARB_FRAMEBUFFER_OBJECT or GL_EXT_FRAMEBUFFER_OBJECT extentions.
However, there are significant number of videocards (mostly Intel, with OGL 2.0 and even 3.0) supporting GL_ARB_FRAMEBUFFER_OBJECT but having GL_MAX_FRAMEBUFFER_WIDTH=0 and GL_MAX_FRAMEBUFFER_HEIGHT=0, so it fails when I try to attach a texture to FBO.
Does it really mean that FBO can't be used for rendering to textures on these videocards? Is there a workaround?
Render to texture is a very important rendering technique, and it works well with Direct3D everywhere, so there should be a way to use it using OpenGL too.

However, there are significant number of videocards (mostly Intel, with OGL 2.0 and even 3.0) supporting GL_ARB_FRAMEBUFFER_OBJECT but having GL_MAX_FRAMEBUFFER_WIDTH=0 and GL_MAX_FRAMEBUFFER_HEIGHT=0, so it fails when I try to attach a texture to FBO.
Neither GL_ARB_framebuffer_object nor GL_EXT_framebuffer_object do define GL_MAX_FRAMEBUFFER_WIDTH or GL_MAX_FRAMEBUFFER_HEIGHT.
These enums were actually added in GL_ARB_framebuffer_no_attachments (core since OpenGL 4.3), so it is no wonder that some Intel GPUs don't support these. (If you'd check for errors, you would have noticed some GL_INVALID_ENUM from your glGets - so it is not returning zero, it is erroring out on the get, leaving the contents of your variable as it was before). However, the main point is that these limits are only relevant for a framebuffer without any attachment, so you are querying the wrong property here.
There is no explicit size limit for the framebuffer, but there are size limits for each attachment type. Renderbuffers can be at most GL_MAX_RENDERBUFFER_SIZE in any dimension, and 2D tetxures at most GL_TEXTURE_SIZE. If you want to render to the target in a single pass, you might also want to care about the GL_MAX_VIEWPORT_DIMS.

Related

How to set all pixels of a texture to one value?

I'm using texture in grids: firstly a large texture (such as 1024x1024 or 2048x2048) is created without data, then areas being used are set with glTexSubImage2d calls. However, I want to have all pixels to have initial value of 0xffff, not zero. And I feel it's stupid to allocate megabytes of all-0xffff host memory only for initialize texture value. So is it possible to set all pixels of a texture to a specific value, with just a few calls?
Specifically, is it possible in OpenGL 2.1?
There is glClearTexImage, but it was introduced in OpenGL 4.4; see if it's available to you with the ARB_clear_texture extension.
If you're absolutely restricted to the core OpenGL 2.1, allocating client memory and issuing a glTexImage2D call is the only way of doing that. In particular you cannot even render to a texture with unextended OpenGL 2.1, so tricks like binding the texture to a framebuffer (OpenGL 3.0+) and calling glClearColor aren't applicable. However, a one-time allocation and initialization of a 1-16MB texture isn't that big of a problem, even if it feels 'stupid'.
Also note that a newly created texture image is undetermined; you cannot rely on it being all zeros, thus you have to initialize it one way or another.

OpenGL: Post-Processing + Multisampling =?

I'm fairly new to OpenGL and trying to figure out how to add a post-processing stage to my scene rendering. What I believe I know so far is that I create an FBO, render the scene to that, and then I can render to the back buffer using my post-processing shader with the texture from the FBO as the input.
But where this goes beyond my knowledge is when multisampling gets thrown in. The FBO must be multisampled. That leaves two possibilities: 1. the post-process shader operates 1:1 on subsamples to generate the final multisampled screen output, or 2. the shader must resolve the multiple samples and output a single screen fragment for each screen pixel. How can these be done?
Well, option 1 is supported in the GL via the features braught in via GL_ARB_texture_multisample (in core since GL 3.2). Basically, this brings new multisample texture types, and the corresponding samplers like sampler2DMS, where you explicitely can fetch from a particular sample index. If this approach can be efficiently used to implement your post-processing effect, I don't know.
Option 2 is a little bit different than what you describe. Not the shader will do the multisample resolve. You can render into a multisample FBO (don't need a texture for that, a renderbuffer will do as well) and do the resolve explicitely using glBlitFramebuffer, into another, non-multisampled FBO (this time, with a texture). This non-multisamples texture can then be used as input for the post-processing. And neither the post-processing nor the default framebuffer need to be aware of multisampling at all.

How to render/draw buffer object to framebuffer without glDrawPixels

According to opengl spec 4.0 glDrawPixels is deprecated.
For cuda interoperability it seems best to use "opengl buffer objects". (An alternative could be textures or surfaces but these have caching/concurrency issues and are therefore unusable for my cuda kernel).
I simply want to create a cuda kernel which uses this mapped opengl buffer object and uses it as a "pixel array" or a piece of memory holding pixels, later the buffer is unmapped.
I then want the opengl program to draw the buffer object to the framebuffer. I would like to use an opengl api which is not deprecated.
What other ways/apis are there to draw a buffer object to the frame buffer ? (Also render buffers cannot be used since they probably have same issue as cuda arrays/caching issues, so this rules out framebuffer object/extension ?!?).
Is there a gap/missing functionality in opengl 4.0 now that glDrawPixels is deprecated ? Or is there an alternative ?
glDrawPixels has been removed from GL 3.2 and above (it is not deprecated. Deprecated means "available but to be removed in the future"). It was removed because it's generally not a fast way to draw pixel data to the screen.
Your best bet is to use glTexSubImage2D to upload it to a texture, then draw that to the screen. Or blit it from the texture with glBlitFramebuffer.

OpenGL FBO renderbuffer or texture attatchment

In what cases would I want to have a renderbuffer attachment in an OpenGL FBO, instead of a texture attachment, besides for the default framebuffer? As, a texture attachment seems far more versatile.
Textures provide more features to you (sampling!, formats variety) and hence are more likely subject to performance loss.
The answer is simple: use Textures wherever you have to sample from the surface (no alternatives).
Use Render buffers wherever you don't need to sample. The driver may or may not decide to store your pixel data more effectively based on your expressed intention of not doing sampling.
You can use GL blitting afterwards to do something with the result.
Extending the question to OpenGL|ES, another reason to use RenderBuffers instead of textures is also that textures may not be supported in some configurations and prevent you from building a valid FBO. I specifically think about depth textures, which are not natively supported on some hardware, for instance nVidia Tegra 2/3.

How to create textures within GPU

Can anyone pls tell me how to use hardware memory to create textures in OpenGL ? Currently I'm running my game in window mode, do I need to switch to fullscreen to get the use of hardware ?
If I can create textures in hardware, is there a limit for no of textures (other than the hardware memory) ? and then how can I cache my textures into hardware ? Thanks.
This should be covered by almost all texture tutorials for OpenGL. For example here, here and here.
For every texture you first need a texture name. A texture name is like a unique index for a single texture. Every name points to a texture object that can have its own parameters, data, etc. glGenTextures is used to get new names. I don't know if there is any limit besides the uint range (2^32). If there is then you will probably get 0 for all new texture names (and a gl error).
The next step is to bind your texture (see glBindTexture). After that all operations that use or affect textures will use the texture specified by the texture name you used as parameter for glBindTexture. You can now set parameters for the texture (glTexParameter) and upload the texture data with glTexImage2D (for 2D textures). After calling glTexImage you can also free the system memory with your texture data.
For static textures all this has to be done only once. If you want to use the texture you just need to bind it again and enable texturing (glEnable(GL_TEXTURE_2D)).
The size (width/height) for a single texture is limited by GL_MAX_TEXTURE_SIZE. This is normally 4096, 8192 or 16384. It is also limited by the available graphics memory because it has to fit into it together with some other resources like the framebuffer or vertex buffers. All textures together can be bigger then the available memory but then they will be swapped.
In most cases the graphics driver should decide which textures are stored in system memory and which in graphics memory. You can however give certain textures a higher priority with either glPrioritizeTextures or with glTexParameter.
Edit:
I wouldn't worry too much about where textures are stored because the driver normally does a very good job with that. Textures that are used often are also more likely to be stored in graphics memory. If you set a priority that's just a "hint" for the driver on how important it is for the texture to stay on the graphics card. It's also possible the the priority is completely ignored. You can also check where textures currently are with glAreTexturesResident.
Usually when you talk about generating a texture on the GPU, you're not actually creating texture images and applying them like normal textures. The simpler and more common approach is to use Fragment shaders to procedurally calculate the colors of for each pixel in real time from scratch for every single frame.
The canonical example for this is to generate a Mandelbrot pattern on the surface of an object, say a teapot. The teapot is rendered with its polygons and texture coordinates by the application. At some stage of the rendering pipeline every pixel of the teapot passes through the fragment shader which is a small program sent to the GPU by the application. The fragment shader reads the 2D texture coordinates and calculates the Mandelbrot set color of the 2D coordinates and applies it to the pixel.
Fullscreen mode has nothing to do with it. You can use shaders and generate textures even if you're in window mode. As I mentioned, the textures you create never actually occupy space in the texture memory, they are created on the fly. One could probably think of a way to capture and cache the generated texture but this can be somewhat complex and require multiple rendering passes.
You can learn more about it if you look up "GLSL" in google - the OpenGL shading language.
This somewhat dated tutorial shows how to create a simple fragment shader which draws the Mandelbrot set (page 4).
If you can get your hands on the book "OpenGL Shading Language, 2nd Edition", you'll find it contains a number of simple examples on generating sky, fire and wood textures with the help of an external 3D Perlin noise texture from the application.
To create a texture on GPU look into "render to texture" tutorials. There are two common methods: Binding a PBuffer context as texture, or using Frame Buffer Objects. PBuffer render to textures are the older method, and have the wider support. Frame Buffer Objects are easier to use.
Also you don't have to switch to "fullscreen" mode for OpenGL to be HW accelerated. In fact OpenGL doesn't know about windows at all. A fullscreen OpenGL window is just that: A toplvel window on top of all other windows with no decorations and the input focus grabed. Some drivers bypass window masking and clipping code, and employ a simpler, faster buffer swap method if the window with the active OpenGL context covers the whole screen, thus gaining a little performance, but with current hard- and software the effect is very small compared to other influences.