what is the Difference between Frame buffer object, Render buffer object and texture? In what context they will be used?
Framebuffer
A framebuffer is not actually a buffer. It's an abstraction for an object that defines parameters for a draw operation. It's a small object that holds one or more attachments, which are themselves the actual buffers. Understand the framebuffer as a C struct with many fields. Each field (each attachment in OpenGL terms) can be a pointer to a render buffer, texture, depth buffer, etc.
Texture
An array of standard pixels. This is an actual buffer and can be attached to a framebuffer as the destination of pixels being drawn. Each pixel in a texture typically contains color components and an alpha value (a pixel in the texture can be translated from and into an RGBA quad with 4 floats).
After drawing to the framebuffer that contains a texture attached, it's possible to read pixels from the texture to use in another draw operation. This allows, for instance, multi-pass drawing or drawing a scene inside another scene.
Textures can be attached to a shader program and used as samplers.
Renderbuffer
An array of native pixels. The renderbuffer is just like a texture, but stores pixels using an internal format. It's optimized for pixel transfer operations. It can be attached to a framebuffer as the destination of pixels being drawn, then quickly copied to the viewport or another framebuffer. This allows implementing of double buffer algorithms, where the next scene is drawn while the previous scene is exhibited.
A renderbuffer can also be used to store depth and stencil information that is used just for a single draw procedure. This is possible because only the implementation itself needs to read renderbuffer data, and tends to be faster than textures, because uses a native format.
Because this uses a native format, a renderbuffer cannot be attached to a shader program and used as a sampler.
A framebuffer object is more or less just a managing construct. It manages a complete framebuffer at a whole with all its sub-buffers, like the color buffers, the depth buffer and the stencil buffer.
The textures or renderbuffers comprise the actual storage for the individual sub-buffers. This way you can have multiple color buffers, a depth buffer and a stencil buffer, all stored in different textures/renderbuffers. But they all together make up a single logical framebuffer into which you render.
So a final fragment (you may call it pixel, but actually isn't one yet) written to the framebuffer has one or more color values, a depth value and a stencil value and they all end up in different sub-buffers of the framebuffer.
Related
A font rendering library (like say freetype) provides a function that will take an outline font file (like a .ttf) and a character code and produce a bitmap of the corresponding glyph in host memory.
For small text (like say up to 30x30 pixel glyphs) what's the most efficient way to render those glyphs to a Vulkan framebuffer?
Some options I've though about might be:
Render the glyphs with the font rendering library every time on demand, blit them with host code to a single host-side image holding a whole "text box", transfer the host-side image of the text box to a device local image, and then render a quad (like a normal image) using fragment shader / image sampler from the text box to be drawn.
At program startup cycle through all the glyphs host side, render them to glyph bitmaps. Do the same as 1 but blit from the cached glyph bitmaps (takes about 1 MB host memory).
Cache the glyph bitmaps individually into device local images. Rather than bitting host-side, render a quad for each glyph device-side and set the image sampler to the corresponding glyph each time. (Not sure how the draw calls would work? One draw call per glyph with a different combined image sampler every time?)
Cache all the glyph bitmaps into one large device-side image (layed out in a big grid say). Use a single device-side combined image sampler, and push params to describe the subregion that contains the glyph image. One draw call per glyph, updating push params each time.
Like 4 but use a single instanced draw call, and rather than push params use instance-varying input attributes.
Something else?
I mean like, how do common game engines like Unreal or Unity or Godot etc solve this problem? Is there a typical approach or best practice?
First, some considerations:
Rasterizing a glyph at around 30px with freetype might take on the order of 10μs. This is a very small one-time cost, but rendering e.g. 100 glyphs every frame would seriously eat into your frame budget (if we assume the math is as simple as 100 * 10μs == 1ms).
State changes (like descriptor updates) are relatively expensive. Changing the bound descriptor for each character you render has non-negligible cost. This could be limited by batching character draws (draw all the As, then the Bs, etc), but using push constants is typically the fastest.
Instanced drawing with small meshes (such as quads or single triangles) can be very slow on some GPUs, as they will not schedule multiple instances on a single wavefront/warp. If you're rendering a quad with 6 vertices, and a single execution unit can process 64 vertices, you may end up wasting 58/64 = 90.6% of available vertex shading capacity.
This suggests 4 is your best option (although 5 is likely comparable); you can further optimize that approach by caching the results of the draw calls. Imagine you have some menu text:
The first frame it is needed, render all the text to an intermediate image.
Each frame it is needed, make a single draw call textured with the intermediate image. (You could also blit the text if you don't need transparency.)
I need to draw textured quad. My texture has some alpha pixels. So I need to do glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Thats OK. But I need some other blending function on that quad (glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA);) to achieve textures masking. How can I do it? Because if I set both glBlendFunc, one of them is ignored.
Blending is a framebuffer operation and can not be set per primitive. If you need to combine several texture layers on a single primitive, do this in a shader and emit a compound color/alpha that interacts in the right way with the choosen blending function. If you need different blending functions, you must do this using separate drawing calls.
I have painting app. Mouse event coordinates are stored to VertexArray. Then vertex array is being drawn to screen. My code structure looks like this
// I get mouse event coordinates and store them to VertexArray
glPushMatrix();
//some new matrix settings
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
glClear(GL_COLOR_BUFFER_BIT);
//now I draw first full size textured quad and later I draw vertexArray
glDrawArrays(.....);
//and now I draw second full size textured quad on top of first quad ant that what have been drawn from vertex array
glPopMatrix();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
//immediately after that I draw FBO to screen:
glBindTexture(GL_TEXTURE_2D, fbTexture);
//Code for drawing textured quad
glBindTexture(GL_TEXTURE_2D, 0);
So everything is redrawn every time when new mouse event coordinate is being registered. And if there are more than 1000 coordinates, drawing becomes really slow. Where could be my problem? I thing 1000 vertices for OpenGL is not much
It's not the number of vertices; it's how you're sending them.
First, you never defined "really slow"; often times people will mistakenly think that a change from 400fps to 300fps is "slow". It's not. It only represents a render time increase from 2.5ms-per-frame to 3.3ms, a change of less than a single millisecond. Non-trivial, but probably not something to be too concerned over.
It's always important to measure performance in terms of render time, not FPS.
That being said, your main problem is that you're drawing a single quad at a time. Each one coming from a separate glDrawArrays command. That's not necessarily a good thing, especially if you change state between drawing commands (like binding a texture and so forth).
If you're doing that, then you need to find ways to avoid doing that. What you want to do is render a lot of quads all with one draw calls. This means you have to use the same texture for all of them.
The common solution to this problem is to make a larger texture that has multiple images in different locations. This is commonly called a "texture atlas" (Google that for the details). Each quad would have texture coordinates for the particular image it renders. Text is often drawn in such a way, where each letter (glyph) is stored in the same texture.
In my OpenGLES 2 application (on an SGX535 on Android 2.3, not that it matters), I've got a large texture that I need to make frequent small updates to. I set this up as a pair of FBOs, where I render updates to the back buffer, then render the entire back buffer as a texture to the front buffer to "swap" them. The front buffer is then used elsewhere in the scene as a texture.
The updates are sometimes solid color sub-rectangles, but most of the time, the updates are raw image data, in the same format as the texture, e.g., new image data is coming in as RGB565, and the framebuffer objects are backed by RGB565 textures.
Using glTexSubImage2D() is slow, as you might expect, particularly on a deferred renderer like the SGX. Not only that, using glTexSubImage2D on the back FBO eventually causes the app to crash somewhere in the SGX driver.
I tried creating new texture objects for each sub-rectangle, calling glTexImage2D to initialize them, then render them to the back buffer as textured quads. I preserved the texture objects for two FBO buffer swaps before deleting them, but apparently that wasn't long enough, because when the texture IDs were re-used, they retained the dimensions of the old texture.
Instead, I'm currently taking the entire buffer of raw image data and converting it to an array of structs of vertices and colors, like this:
struct rawPoint {
GLfloat x;
GLfloat y;
GLclampf r;
GLclampf g;
GLclampf b;
};
I can then render this array to the back buffer using GL_POINTS. For a buffer of RGB565 data, this means allocating a buffer literally 10x bigger than the original data, but it's actually faster than using glTexSubImage2D()!
I can't keep the vertices or the colors in their native unsigned short format, because OpenGL ES 2 only takes floats in vertex attributes and shader uniforms. I have to submit every pixel as a separate set of coordinates, because I don't have geometry shaders. Finally, I can't use the EGL_KHR_gl_texture_2D_image extension, since my platform doesn't support it!
There must be a better way to do this! I'm burning tons of CPU cycles just to convert image data into a wasteful floating point color format just so the GPU can convert it back into the format it started with.
Would I be better off using EGL Pbuffers? I'm not excited by that prospect, since it requires context switching, and I'm not even sure it would let me write directly to the image buffer.
I'm kind of new to graphics, so take this with a big grain of salt.
Create a native buffer (see ) the size of your texture
Use the native buffer to create an EGL image
eglCreateImageKHR(eglGetCurrentDisplay(),
eglGetCurrentContext(),
EGL_GL_TEXTURE_2D_KHR,
buffer,
attr);
I know this uses EGL_GL_TEXTURE_2D_KHR. Are you sure your platform doesn't support this? I am developing on a platform that uses SGX535 as well, and mine seems to support it.
After that, bind the texture as usual. You can memcpy into your native buffer to update sub rectangles very quickly I believe.
I realize I'm answering a month old question, but if you need to see some more code or something, let me know.
How would I draw a UIImage in Core Graphics with dimensions 16x16 filled with random pixels at random coordinates and random grayscale color? This seems slightly impossible to do at the moment...
EDIT: Perhaps I should start with a diagonal line texture? My problem is filling in each pixel one by one. Doesn't seem doable in Core Graphics.
Create a buffer as many bytes long as you want pixels (so, in this case, 16 * 16).
Fill this buffer by reading from /dev/random.
Pass this buffer to the CGImageCreate function using kCGImageAlphaNone.
Once you have created a CGImage, it is trivial to create a UIImage from it. Depending on your requirements, you can actually create up to eight “random” UIImages from the same CGImage by specifying different orientation values.
ETA: You might also try creating a two-byte-per-pixel buffer and image. Then, by using each of the endianness flags, you can create two “random” CGImages from the same buffer, for a total of 16 “random” UIImages. However, I don't know whether two-byte-per-pixel no-alpha grayscale is supported on any version of iOS; the Quartz 2D Programming Guide lists only Mac OS X version numbers.