Texture do not rotate with OpenGL (C) - c

I am trying to rotate a texture extracted from a video frame (provided by ffmpeg), I have tried the following code :
glTexSubImage2D(GL_TEXTURE_2D,
0,
0,
0,
textureWidth,
textureHeight,
GL_RGBA,
GL_UNSIGNED_BYTE,
//s_pixels);
pFrameConverted->data[0]);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glTranslatef(0.5,0.5,0.0);
glRotatef(90,0.0,0.0,1.0);
glTranslatef(-0.5,-0.5,0.0);
glMatrixMode(GL_MODELVIEW);
//glDrawTexiOES(-dPaddingX, -dPaddingY, 0, drawWidth + 2 * dPaddingX, drawHeight + 2 * dPaddingY);
glDrawTexiOES(0, 0, 0, drawWidth, drawHeight);
The image is not rotated, do you see the problem ?

From the GL_OES_draw_texture extension specification:
Note also that s, t, r, and q are computed for each fragment as part of DrawTex rendering. This implies that the texture matrix is ignored and has no effect on the rendered result.
You are trying to transform the texture coordinates using the fixed-function texture matrix, but like point sprites, those coordinates are generated per-fragment rather than per-vertex. Thus, that means that nothing you do to the texture matrix is ever going to affect the output of glDrawTexiOES (...).
Consider using a textured quad instead, those will pass through the traditional vertex processing pipeline.

Related

GLFW3/GLU 3D world space using static pipeline

In previous projects, I enabled depth testing used gluPerspective called once on startup to set up a 3D space. Currently, I am rendering a square between -0.5 and 0.5 with 0.0 as its origin after the 3D world has initialised with code below will cause a square to cover the entire screen:
glBegin(GL_QUADS);
{
glVertex3f(-0.5, -0.5, 0);
glVertex3f(-0.5, 0.5, 0);
glVertex3f(0.5, 0.5, 0);
glVertex3f(0.5, -0.5, 0);
}
glEnd();
What I am looking is a way to set the perspective so that shapes are rendered in world space. For example, the snippet below should cause a square of 200x200 to be rendered:
glBegin(GL_QUADS);
{
glVertex3f(-100, -100, 0);
glVertex3f(-100, 100, 0);
glVertex3f(100, 100, 0);
glVertex3f(100, -100, 0);
}
glEnd();
The code below is what I am currently using to initialise a 3D world.
// WINDOW_WIDTH = 1600, WINDOW_HEIGHT = 900
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(47, WINDOW_WIDTH / WINDOW_HEIGHT, 0.01, 1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_DEPTH_TEST);
Have I missed any steps in setting up a 3D space and if gluPerspective is used to do this any suggestions why it is not working?
I am able to achieve this in 2D using ortho, it is important that the world is 3D.
Everything is being written in C using OpenGL and GLU up to 1.3 with my GLFW set up identical to this. Due to technical restraints, I am unable to use the modern pipeline.
First of all, the result of WINDOW_WIDTH / WINDOW_HEIGHT is 1, because WINDOW_WIDTH and WINDOW_HEIGHT are integral values. You have to perform a floating point division ((float)WINDOW_WIDTH / WINDOW_HEIGHT) to compute the correct aspect ratio.
At Perspective Projection the projection matrix describes the mapping from 3D points in the world as they are seen from of a pinhole camera, to 2D points of the viewport.
The projected size of an object on the viewport depends on its distance to the camera. The different size at different distances (depths) causes the perspective effect. The perspective projection matrix defines a Viewing frustum
The ratio of projected size and the distance to the camera depends on the field of view angle:
maxDim / cameraZ = tan(FOV / 2) * 2
So there is exactly 1 distance where an object with a length of 200 covers 200 pixel. For instance, If you have a filed of view angle of 90° then an object with a z distance of half the window height (height /2) and a vertical size of 200 covers 200 pixel (vertical) because tan(90° / 2) * 2 = 2.
When you use gluPerspective, then you define the field of view angle along the y axis. The field of view along the x axis depends on the aspect ratio. If the aspect ratio is set correctly, then the projection of a square which is parallel to the xy plane of the view is still a square.
Note, if you would use orthographic projection, then the size of the object is independent on the distance.

glTexImage2D, in random and occasional ways, expends 800 times more in executing

I'm using glsl 2.0 for some GPGPU purposes (I know, not the best for GPGPU).
I have a reduction phase for matrix multiplication in which I have to constantly reduce the texture size (I'm using glTexImage2D). The pseudocode is something like this:
// Start reduction
for (int i = 1; i <= it; i++)
{
glViewport(0, 0, x, y);
glDrawArrays(GL_TRIANGLES, 0, 6);
x = resize(it);
if (i % 2 != 0)
{
glUniform1i(tex2_multiply_initialstep, 4);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer3);
// Resize output texture
glActiveTexture(GL_TEXTURE5);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, x, y, 0, GL_RGBA, GL_FLOAT, NULL);
}
else
{
glUniform1i(tex2_multiply_initialstep, 5);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
// Resize output texture
glActiveTexture(GL_TEXTURE4);
// A LOT OF TIME!!!!!!!
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, x, y, 0, GL_RGBA, GL_FLOAT, NULL);
// A LOT OF TIME!!!!!!!
}
}
In some iterations the glTexImage2D of the else branch takes 800 times more time that in other ones. I make a test hardcoding x and y but surprisingly takes similar high times in the same iterations, so have nothing to do with x value.
What's wrong here? Alternatives to resizing without glTexImage2D?
Thanks.
EDIT:
I know that glsl 2.0 is a bad choice for GPGPU but its mandatory for my project. So that I'm not able to use functions like glTexStorage2D because they are not included in 2.0 subset.
I'm not sure if I understand exactly what you're trying to achieve, but glTexImage2D is reallocating memory each time you call it. You may want to call glTexStorage2D, and then call glTexSubImage2D.
You can check Khronos's Common Mistakes page about that. Relevant part is :
Better code would be to use texture storage functions (if you have
OpenGL 4.2 or ARB_texture_storage) to allocate the texture's storage,
then upload with glTexSubImage2D:
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
glTexSubImage2D(GL_TEXTURE_2D, 0​, 0, 0, width​, height​, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
This creates a texture with a single mipmap level, and sets all of the parameters appropriately. If you wanted to have multiple mipmaps, then you should change the 1 to the number of mipmaps you want. You will also need separate glTexSubImage2D calls to upload each mipmap.
If that is unavailable, you can get a similar effect from this code:
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
Again, if you use more than one mipmaps, you should change the GL_TEXTURE_MAX_LEVEL to state how many you will use (minus 1. The base/max level is a closed range), then perform a glTexImage2D (note the lack of "Sub") for each mipmap.

How to use unsigned short in an opengl shader?

I'm trying to upload a texture with unsigned shorts in a shader but it's not working.
I have tried the following:
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, vbt[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 640, 480, 0, GL_RED, GL_UNSIGNED_SHORT, kinect_depth);
glUniform1i(ptexture1, 1);
GLenum ErrorCheckValue = glGetError();
I know I'm binding correctly the texture because I get some results by using
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, vbt[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 640, 480, 0,
GL_RG, GL_UNSIGNED_BYTE, kinect_depth);
glUniform1i(ptexture1, 1);
GLenum ErrorCheckValue = glGetError();
In particular, I get part of my values in the red channel. I would like to upload the texture as a unsigned byte or as a float. However I don't manage to get the glTexImage2D call correctly. Also, is it possible to something similar using a depth texture? I would like to do some operations on the depth information I get from a kinect and display it.
Your arguments to glTexImage2D are inconsistent. The 3rd argument (GL_RGB) suggests that you want a 3 component texture, the 7th (GL_RED) suggests a one-component texture. Then your other attempt uses GL_RG, which suggests 2 components.
You need to use an internal texture format that stores unsigned shorts, like GL_RGB16UI.
If you want one component, your call would look like this:
glTexImage2D(GL_TEXTURE_2D, 0, GL_R16UI, 640, 480, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, kinect_depth);
If you want three components:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16UI, 640, 480, 0, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, kinect_depth);
You also need to make sure that the types used in your shader for sampling the texture match the type of the data stored in the texture. In this example, since you use a 2D texture containing unsigned integer values, your sampler type should be usampler2D, and you want to store the result of the sampling operation (result of texture() call in the shader) in a variable of type uvec4. (paragraph added based on suggestion by Andon)
Some more background on the format/type arguments of glTexImage2D, since this is a source of fairly frequent misunderstandings:
The 3rd argument (internalFormat) is the format of the data that your OpenGL implementation will store in the texture (or at least the closest possible if the hardware does not support the exact format), and that will be used when you sample from the texture.
The last 3 arguments (format, type, data) belong together. format and type describe what is in data, i.e. they describe the data you pass into the glTexImage2D call.
It is mostly a good idea to keep the two formats matched. Like in this case, the data you pass in is GL_UNSIGNED_SHORT, and the internal format GL_R16UI contains unsigned short values. In OpenGL ES it is required for the internal format to match format/type. Full OpenGL does conversion if necessary, which is undesirable for performance reasons, and also frequently not what you want because the precision of the data in the texture won't be the same as the precision of your original data.

How to write out a greyscale cairo surface to PNG

I have a cairo_surface_t of format CAIRO_FORMAT_A8. I want to write out the surfe as a greyscale image, so every pixel has a single byte value of type uchar.
If I use cairo_surface_write_to_png directly on the CAIRO_FORMAT_A8 surface, all I get is an all-black image. I think this is how cairo internally treats the A8 surface - as alpha values, not as greyscale data. I want a single greyscale image, however.
I'd be enough if somebody count point out how to copy the A8 format to all 3 layers of an RGB24 image.
Any help appreciated!
Untested code below. The idea is to create an ARGB-surface and "copy" the A8 surface there via cairo_mask_surface(). If the colors are "swapped", swap the two cairo_set_source_rgb() calls.
cairo_surface_t *s = YOUR_A8_SURFACE;
cairo_t *cr = cairo_create(s);
cairo_push_group_with_content(cr, CAIRO_CONTENT_COLOR_ALPHA);
cairo_set_source_rgb(cr, 1, 1, 1);
cairo_paint(cr);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_mask_surface(cr, cairo_get_target(cr), 0, 0);
cairo_surface_write_to_png(cairo_get_group_target(cr), "/tmp/foo.png");
/* If you want to continue using the context:
cairo_pattern_destroy(cairo_pop_group(cr)); */
cairo_destroy(cr);

How do I fill the screen with a rectangle in OpenGL ortho mode?

I have a single 640x480 texture that needs to fill the screen. So far, I can make it work with a square texture, but not a rectangular one.
glViewport(0, 0, display->w, display->h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double aspectRatio = (double)display->w / (double)display->h;
if (display->w <= display->h)
glOrtho(-1, 1, -1 / aspectRatio, 1 / aspectRatio, -1, 1);
else
glOrtho(-1 * aspectRatio, 1 * aspectRatio, -1, 1, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
What modifications do I need to make so that it will fit any texture to the screen, regardless of its aspect ratio?
This may have some relevance.
Tiling texture bmp file as texture onto a rectangle in OpenGL?
You may wish to consider ARB extension texture rectangle as an alternative approach to (assuming glTexImage2D?) http://glprogramming.com/red/chapter09.html

Resources