So, I’m writing a buffer to a file as a bitmap. I want to be able to run this program without ever actually launching the winow, preferrably on a machine that isn’t even running X concurrently. Is this possible? I’m using GLUT to do it all, and it seems that no drawing to buffers occurs until glutMainLoop is entered-- and this automatically draws the window. Suggestions?
Cheers,
Michael
Originally posted by mrshirts:
So, I’m writing a buffer to a file as a bitmap. I want to be able to run this program without ever actually launching the winow, preferrably on a machine that isn’t even running X concurrently. Is this possible? I’m using GLUT to do it all, and it seems that no drawing to buffers occurs until glutMainLoop is entered-- and this automatically draws the window. Suggestions?
Cheers,
Michael
Just browsing through the Red Book revealed:
Create surfaces that support rendering (both on-screen and off-screen):
…
glXCreatePixmap …
glXCreatePbuffer …
Maybe these functions would help?
I’m going to try playing around with them right now…
I’ll post my code here if I get anywhere.
Hope this helps
Here’s my code… this draws a lit sphere to a
.bmp file.
This will not make a window, but I think it does
require that an X server be running.
CFLAGS = -I/usr/X11R6/include
all: render2bmp
render2bmp: render2bmp.o
cc -o render2bmp render2bmp.o -L/usr/X11R6/lib -lglut -lGLU -lGL -lXext -lX11
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <GL/glx.h>
#include <GL/glu.h>
void Render(int w, int h)
{
/* Draw a lit sphere /
/ Taken right out of the red book */
GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0};
GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0};
GLfloat diffuse_material[] = {0.5, 0.5, 0.5, 1.0};glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse_material);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialf(GL_FRONT, GL_SHININESS, 25.0);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);glColorMaterial(GL_FRONT, GL_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h) {
glOrtho(-1.5, 1.5, -1.5*(GLfloat)h/(GLfloat)w,
1.5*(GLfloat)h/(GLfloat)w, -10.0, 10.0);
} else {
glOrtho(-1.5*(GLfloat)w/(GLfloat)h,
1.5*(GLfloat)w/(GLfloat)h,
-1.5, 1.5, -10.0, 10.0);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glutSolidSphere(1.0, 20, 16);
glFlush();
}int MakeBMP(const char *fname, const unsigned char image, int w, int h)
{
/ See http://www.dcs.ed.ac.uk/home/mxr/gfx/2d/BMP.txt */
struct BMPHeader {
unsigned short type;
unsigned int size;
unsigned short res1;
unsigned short res2;
unsigned int offset;
} attribute((packed)) header;
struct BMPInfo {
unsigned int size;
unsigned int width;
unsigned int height;
unsigned short planes;
unsigned short bit_count;
unsigned int comp;
unsigned int sizeImage;
unsigned int x_pels_per_meter;
unsigned int y_pels_per_meter;
unsigned int clr_used;
unsigned int clr_important;
} attribute((packed)) info;
FILE *fp;
int ret = 0;/* Open file /
fp = fopen(fname, “wb”);
if (!fp) {
fprintf(stderr,
"Unable to open %s for writing
",
fname);
ret = -1;
} else {
/ Header */
header.type = ‘B’ | ‘M’ << 8;
header.size = sizeof(header) + sizeof(info) + w * h * 3;
header.res1 = header.res2 = 0;
header.offset = sizeof(header) + sizeof(info);
info.size = sizeof(info);
info.width = w;
info.height = h;
info.planes = 1;
info.bit_count = 24;
info.comp = 0;
info.sizeImage = w * h * 3;
info.x_pels_per_meter = info.y_pels_per_meter = 0;
info.clr_used = 0;
info.clr_important = 0;fwrite(&header, sizeof(header), 1, fp); fwrite(&info, sizeof(info), 1, fp); fwrite(image, sizeof(unsigned char), h*w*3, fp);
}
if (fp) {
fclose(fp);
}return ret;
}int main(int argc, char **argv)
{
Display *dpy = NULL;
XVisualInfo *vi = NULL;
GLXContext cx = NULL;
Pixmap pmap;
GLXPixmap glxpmap ;
unsigned char *image = NULL;
const int attrib_list[] = {GLX_DOUBLEBUFFER, GLX_RGBA,
GLX_DEPTH_SIZE, 16,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
None};
const int width = 300;
const int height = 300;
int ret = 0;/* Create a pixmap to render into */
dpy = XOpenDisplay(NULL);
if (dpy == NULL) {
fprintf(stderr, "Could not open display
");
ret = -1;
goto abort;
}if (!glXQueryExtension(dpy, NULL, NULL)) {
fprintf(stderr, "X server has no GLX extension
");
ret = -1;
goto abort;
}vi = glXChooseVisual(dpy, DefaultScreen(dpy), (int *)attrib_list);
if (vi == NULL) {
fprintf(stderr, "could not create visual
");
ret = -1;
goto abort;
}cx = glXCreateContext(dpy, vi, NULL, 0);
if (cx == NULL) {
fprintf(stderr, "could not create rendering context
");
ret = -1;
goto abort;
}pmap = XCreatePixmap(dpy, RootWindow(dpy, vi->screen),
width, height, vi->depth);
glxpmap = glXCreateGLXPixmap(dpy, vi, pmap);
glXMakeCurrent(dpy, glxpmap, cx);/* Now render scene */
Render(width, height);/* Save the frame buffer to a BMP */
image = (unsigned char )malloc(sizeof(unsigned char)widthheight3);
if (!image) {
fprintf(stderr, "Unable to allocate image buffer
");
ret = -1;
goto abort;
}
glReadPixels(0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, image);
MakeBMP(“render2bmp.bmp”, image, width, height);/* Clean up /
abort:
if (cx && dpy) {
glXDestroyContext(dpy, cx);
}
if (dpy) {
/ MesaGL seems to be missing this… doesn’t link so well /
/ glXDestroyPixmap(dpy, glxpmap); */
}
if (dpy) {
XFreePixmap(dpy, pmap);
}
if (dpy) {
XCloseDisplay(dpy);
}
if (image) {
free(image);
}return ret;
}
Hope this helps
If you do not need hardware rendering you could use OSMesa which renders right into a memory buffer.
Judd Tracy
This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.