OpenGL: Save framebuffer to image, file - c

I wrote some lines of code to draw a spinning rectangle:
#include "glut.h"
static GLfloat spin = 0.0; /* current angle */
void init(void)
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel (GL_FLAT);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glRotatef(spin, 0.0, 0.0, 1.0); /* rotate Oxyz (OZ) */
glColor3f(1.0, 1.0, 1.0); /* bgr-color: white; */
glRectf(-25.0, -25.0, 25.0, 25.0); /* Rectangle */
glPopMatrix();
glutSwapBuffers(); /* Swap 2 buffer */
}
void spinDisplay(void)
{
spin = spin + 2.0; /* Add 2 degrees for every loop action */
if (spin > 360.0)
spin = spin - 360.0;
glutPostRedisplay(); /* Alert: Redraw */
}
/* Change window mode */
void reshape(int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h); /* change viewport */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-50.0, 50.0, -50.0, 50.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
/* Mouse interaction */
void mouse(int button, int state, int x, int y)
{
switch (button) {
case GLUT_LEFT_BUTTON: /* left mouse */
if (state == GLUT_DOWN)
glutIdleFunc(spinDisplay); /* idle mode switch to spinDisplay */
break;
//case GLUT_MIDDLE_BUTTON: /* middle mouse button */
//if (state == GLUT_DOWN)
//glutIdleFunc(NULL);
//break;
default:
break;
}
}
/* main */
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB); /* double buffer */
glutInitWindowSize (500, 500);
glutInitWindowPosition (100, 100);
glutCreateWindow ("spinning rectangle");
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape); /* reshape func (redraw) when window size changed */
glutMouseFunc(mouse); /* mouse func */
glutMainLoop();
return 0;
}
And I wanna save framebuffer to image (JPEG, BMP, TIFF) or file. Could you tell me how? Do I need to use some lib like jpeglib, libtiff?

Related

Can't change background color in OpenGL

I've just started to experiment with OpenGL (using freeglut and GLEW). I can get a window to pop up, but nothing gets drawn to it, I can't even get it to change background color.
Here's what the main function looks like:
int
main(int argc, char **argv)
{
GLenum err;
/* Initialize GLUT library */
glutInit(&argc, argv);
/* Set window mode */
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
/* Choose OpenGL version */
glutInitContextVersion(3, 3);
/* Choose OpenGL profile */
glutInitContextFlags(GLUT_CORE_PROFILE);
/* Create a GLUT window */
glutCreateWindow("OpenGL 2D");
/* Initialize GLEW library */
glewExperimental = GL_TRUE;
err = glewInit();
if(err != GLEW_OK) {
printf("Cannot initialize GLEW: %s\n",
glewGetErrorString(err));
return 1;
}
/* WORKAROUND: Ignore all GLEW errors */
while(glGetError() != GL_NO_ERROR)
;
(void) printf("OpenGL vendor: \"%s\"\n"
" renderer: \"%s\"\n"
" version: \"%s\"\n"
" SL version: \"%s\"\n",
glGetString(GL_VENDOR),
glGetString(GL_RENDERER),
glGetString(GL_VERSION),
glGetString(GL_SHADING_LANGUAGE_VERSION));
/* Set up callback function for "reshape" event */
printf("Setting callback functions\n");
glutReshapeFunc(canvas_reshape);
/* Set up callback function for "display" event */
glutDisplayFunc(canvas_display);
/* Set up callback function for "keyboard" event */
glutKeyboardFunc(canvas_keyboard);
/* Set up callback function for "timer" event */
glutTimerFunc(30, canvas_timer, 0);
/* Initialize OpenGL */
init();
/* Choose the window's position */
glutPositionWindow(100, 100);
/* Choose the window's size */
glutReshapeWindow(800, 600);
/* Start main loop */
printf("Entering main loop\n");
glutMainLoop();
return 0;
}
Here's what init looks like:
init()
{
const GLchar *vertex_shader_source[] = {
"#version 330 core\n",
"\n",
"layout(location=0) in vec4 position;\n",
"out vec4 color;\n",
"uniform mat4 viewtrans;\n",
"\n",
"void\n",
"main()\n",
"{\n",
" gl_Position = viewtrans * position;\n"
" color = vec4(1.0, 1.0, 1.0, 1.0);\n"
"}\n" };
const GLchar *fragment_shader_source[] = {
"#version 330 core\n",
"in vec4 color;\n",
"layout(location=0) out vec4 fcolor;\n",
"void\n",
"main()\n",
"{\n",
" fcolor = color;\n",
"}\n" };
char compiler_log[LOGSIZE];
/* Obtain an unused name for our vertex array */
printf("Creating vertex array\n");
glGenVertexArrays(1, &vertex_array);
check_error("glGenVertexArrays");
/* Tell OpenGL to use the new vertex array */
glBindVertexArray(vertex_array);
check_error("glBindVertexArray");
/* Obtain an unused name for our vertex buffer */
printf("Creating vertex buffer\n");
glGenBuffers(1, &vertex_buffer);
check_error("glGenBuffers");
/* Tell OpenGL to use the new vertex buffer as the
* vertex array */
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
check_error("glBindBuffer");
/* We want to get two coordinates from the vertex buffer and
* feed them as the first parameter to the vertex shader */
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 2, 0);
/* Create vertex shader */
printf("Creating vertex shader\n");
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
check_error("glCreateShader");
/* Assign vertex shader source code */
glShaderSource(vertex_shader, sizeof(vertex_shader_source) / sizeof(GLchar *),
vertex_shader_source, 0);
check_error("glShaderSource");
/* Compile vertex shader */
glCompileShader(vertex_shader);
check_error("glCompileShader");
/* Get compiler log *//* Set up callback function for "timer" event */
glGetShaderInfoLog(vertex_shader, LOGSIZE, 0, compiler_log);
printf(" Compiler log: \"%s\"\n", compiler_log);
/* Create fragment shader */
printf("Creating fragment shader\n");
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
check_error("glCreateShader");
/* Assign fragment shader source code */
glShaderSource(fragment_shader, sizeof(fragment_shader_source) / sizeof(GLchar *),
fragment_shader_source, 0);
check_error("glShaderSource");
/* Compile fragment shader */
glCompileShader(fragment_shader);
check_error("glCompileShader");
/* Get compiler log */
glGetShaderInfoLog(fragment_shader, LOGSIZE, 0, compiler_log);
printf(" Compiler log: \"%s\"\n", compiler_log);
/* Create shader program */
printf("Creating shader program\n");
shader_program = glCreateProgram();
check_error("glCreateProgram");
/* Attach vertex shader */
glAttachShader(shader_program, vertex_shader);
check_error("glAttachShader");
/* Attach fragment shader */
glAttachShader(shader_program, fragment_shader);
check_error("glAttachShader");
/* Link shader program */
glLinkProgram(shader_program);
check_error("glLinkProgram");
/* Get linker log */
glGetProgramInfoLog(shader_program, LOGSIZE, 0, compiler_log);
printf(" Linker log: \"%s\"\n", compiler_log);
/* Get location of "viewtrans" matrix */
viewtrans = glGetUniformLocation(shader_program, "viewtrans");
check_error("glGetUniformLocation");
/* Tell OpenGL to use the new shader program */
glUseProgram(shader_program);
/* Choose background color */
glClearColor(1.0, 0.0, 1.0, 0.0);
}
Here's what I use to draw:
static void
canvas_display()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
This is all based off of a tutorial. What actually happens is something like a 300 x 300 white window shows up, gets reshaped into a 800 x 600 black window, BUT with still a 300 x 300 white square in the middle or in a corner, whose pixels (partially) turn black when resizing the window such that (part of) the square disappears (either manually or through code). I've also written code to draw triangles, but that doesn't work either, as one might expect. But here's the code for that anyway:
static void
canvas_display()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLfloat vertices[] =
{ 0.0, 0.0,
0.5, 0.5,
0.5, 0.0 };
glGenVertexArrays(1, &vertex_array);
glBindVertexArray(vertex_array);
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GL_FLOAT) * 2, vertices);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
Do not continuously specify the new vertex array objects. Create 1 Vertex Array Object at initialization. The vertex array is contained in the Vertex Buffer Object. When a named buffer object is bound to the ARRAY_BUFFER target, then the last parameter of glVertexAttribPointer is treated as a byte offset into the buffer object's data store. Thus the offset has to be NULL:
void init()
{
// [...]
GLfloat vertices[] =
{ 0.0, 0.0,
0.5, 0.5,
0.5, 0.0 };
glGenVertexArrays(1, &vertex_array);
glBindVertexArray(vertex_array);
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GL_FLOAT) * 2, NULL);
}
Ensure that the program is installed and the VAO is bound when the geometry is drawn. By default the values of uniforms are initialized by zero. At least you have to set the Identity matrix then matrix uniform viewtrans.
Since you use double buffering (GLUT_DOUBLE), you have to swaps the buffers of the current window after drawing all the geometry by glutSwapBuffers
void canvas_display()
{
glClearColor(1.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shader_program);
GLfloat identity_mat[] = { 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 };
glUniformMatrix4fv(viewtrans, 1, GL_FALSE, identity_mat);
glBindVertexArray(vertex_array);
glDrawArrays(GL_TRIANGLES, 0, 3);
glutSwapBuffers();
glutPostRedisplay();
}

How to setup gluLookat() and glOrtho() in openGL?

I am new to openGL and have a hard time to understand how to actually parametrize the function gluLookat. I what it does but don't know how to know which parameters I should pass to that function and what consequences it will have.
This is my current code and strangely enough I don't even see the axis I drew... I think it is due to the parameters I pass to the function gluLookAt();
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <GL/glut.h>
void init(void)
{
glClearColor(0.8, 0.8, 0.8, 0.0); /* window color white */
glEnable(GL_DEPTH_TEST);
}
void drawScene(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(3.0,3.0,3.0, 0.0,0.0,0.0, 0.0,1.0,0.0);
//used some random parameters...
gluLookAt(0.0, 0.0, 0.0, 5.0, 5.0, 5.0, 0, 1, 0);
//axis
//x
glColor3f(1.0,0.0,0.0);
glLineWidth(1.0);
glBegin(GL_LINES);
glVertex3d(0.0,0.0,0.0);
glVertex3d(1.0,0.0,0.0);
glEnd();
//y
glColor3f(0.0,1.0,0.0);
glLineWidth(1.0);
glBegin(GL_LINES);
glVertex3d(0.0,0.0,0.0);
glVertex3d(1.0,0.0,0.0);
glEnd();
//z
glColor3f(0.0,0.0,1.0);
glLineWidth(1.0);
glBegin(GL_LINES);
glVertex3d(0.0,0.0,0.0);
glVertex3d(1.0,0.0,0.0);
glEnd();
glFlush();
}
void herschaal(){
glViewport(0,0,500,500);
glMatrixMode(GL_PROJECTION);
glOrtho(-10, 10, 10, -10, 10, -10);
glLoadIdentity();
}
int main( int argc, char * argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH );
glutInitWindowPosition(50, 100);
glutInitWindowSize(500, 500);
glutCreateWindow("mijn test");
glutReshapeFunc(herschaal);
init();
glutDisplayFunc(drawScene);
glutMainLoop();
return 0;
}

Blank screen while using glGenBuffers in openGL

#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GL/glut.h>
void changeSize(int w, int h)
{
if(h == 0)
h = 1;
float ratio = w / h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, w, h);
gluPerspective(40,ratio,1.5,20);
glMatrixMode(GL_MODELVIEW);
}
void renderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT );
glLoadIdentity();
glTranslatef(0.0,0.0,-5.0);
glDrawArrays(GL_TRIANGLES,0,3);
glutSwapBuffers();
}
void init()
{
GLfloat verts[] = {
0.0, 1.0,
-1.0, -1.0,
1.0, -1.0
};
GLuint bufferid;
glGenBuffers(1,&bufferid);
glBindBuffer(GL_ARRAY_BUFFER,bufferid);
glBufferData(GL_ARRAY_BUFFER,sizeof(verts),verts,GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0,2,GL_FLOAT,GL_FALSE,0,0);
if(glGetError()==GL_NO_ERROR)
printf("no error");
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(500,500);
glutCreateWindow("MM 2004-05");
glewInit();
init();
glutDisplayFunc(renderScene);
glutReshapeFunc(changeSize);
if (GLEW_ARB_vertex_program && GLEW_ARB_fragment_program)
printf("Ready for GLSL\n");
else {
printf("No GLSL support\n");
//exit(1);
}
glutMainLoop();
return 0;
}
When using glGenBuffers my screen turns out black and shows no error. If i draw some other shape without using buffers they are displayed but not with buffer objects.
openGL version:3.0
operating system:ubuntu
IDE:eclipse
When using glGenBuffers you're using the OpenGL-3.0 specification. To draw anything in OpenGL-3.0+ you need to use shaders, hence why the screen is black; your triangle isn't being shaded.
You are using calls for generic vertex attributes here:
glEnableVertexAttribArray(0);
glVertexAttribPointer(0,2,GL_FLOAT,GL_FALSE,0,0);
Generic vertex attributes can only be used in combination with shaders. As long as you're using the fixed function pipeline, you also have to use fixed function vertex attributes.
The corresponding calls using fixed function attributes are:
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, 0);

Regarding glutReshapeFunc()

I have small code drawing a square initially but when I maximize the window it changes to rectangle. I know this has do with aspect ratio and when I add glutReshapeFunc(Reshape); call it works perfectly, I mean after maximizing the window, it remains square only. ReshapFunc is called every time display is modified and before the first display as well.
I am not getting just by adding reshapefunc, how it maintains aspect ratio. Please help me understanding this. I am copying my code here:
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.5, 0.5, 1.0);
glBegin(GL_POLYGON);
glVertex2f(-0.5, -0.5);
glVertex2f(0.5, -0.5);
glVertex2f(0.5, 0.5);
glVertex2f(-0.5, 0.5);
glEnd();
glutSwapBuffers();
glFlush();
}
void Reshape(int w, int h) {
glutPostRedisplay();
}
void init()
{
glClearColor(1.0, 0.0, 1.0, 0.0);
glColor3f(1.0, 1.0, 1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-1.0, 1.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize(500, 500);
glutInitWindowPosition(200, 200);
glutCreateWindow("basics");
glutDisplayFunc(display);
// If I comment this, it will become rectangle.
glutReshapeFunc(Reshape);
init();
glutMainLoop();
}
Your problem is related to the use of gluOrtho2D (...). If you want to preserve aspect ratio, your projection matrix needs to be defined based on the dimensions of your window.
I suggest you do this in your reshape function:
GLdouble aspect = (GLdouble)w / (GLdouble)h;
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluOrtho2D (-1.0 * aspect, 1.0 * aspect, -1.0, 1.0);
glMatrixMode (GL_MODELVIEW);
glViewport (0, 0, w, h);

Problem with GLUT

When i try to run this code after compiling it, i got only a window border without content, so where is the error?
Note: i am using ubuntu and gcc for compiling
gcc -lglut Simple.c -o Simple
The output
#include <GL/glut.h> // Header File For The GLUT Library
#include <GL/gl.h> // Header File For The OpenGL Library
#include <GL/glu.h> // Header File For The GLu Library
void SetupRC(void);
void RenderScene(void);
void ChangeSize(GLsizei w, GLsizei h);
// Called to draw scene
void RenderScene(void)
{
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT);
// set the color to these values
// R G B
glColor3f(56.0f, 19.0f,68.0f);
// Draw a filled rectangle with current color
glRectf(-25.0f, 50.0f, 50.0f, -25.0f);
// Flush drawing commands
glFlush();
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA);
glutInitWindowPosition(400,200);
glutInitWindowSize(640,468);
glutCreateWindow("Simple");
glutDisplayFunc(RenderScene);
glutReshapeFunc(ChangeSize);
SetupRC();
glutMainLoop();
return 0;
}
// Setup the rendering state
void SetupRC(void)
{
glClearColor(0.0f, 2.0f, 1.0f, 0.0f);
}
// Handling window resizing
void ChangeSize(GLsizei w, GLsizei h)
{
GLfloat aspectRatio;
// Prevent divide by zero
if (h == 0)
h = 1;
// Set Viewport to window dimensions
glViewport(0, 0, w, h);
// Reset coordinate system
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Establish clipping volume (left, right, bottom, top, near, far)
aspectRatio = (GLfloat) w / (GLfloat) h;
if (w <= h) {
glOrtho(-100.0, 100.0, -100 / aspectRatio, 100.0 / aspectRatio, 1.0, -1.0);
}
else
glOrtho(-100.0 * aspectRatio, 100.0 * aspectRatio, -100.0, 100.0, 1.0, -1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
Try adding a glutSwapBuffers() to the end of RenderScene().
One thing. You have a depth buffer so you should also add GL_DEPTH_BUFFER_BIT to the clear call.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

Resources