PDA

View Full Version : Drawing pixel per pixel



03-29-2000, 04:37 AM
I have to write a C fractal drawing program ; it must run on Macintosh and Windows, so compatibily problems for the graphic interface (and i won't write 2 codes !!).
I've just discovered OpenGL, its portabiliy and its huge power ; only the portability aspect interest me (i just need to draw simple fractals as Mandelbrot group). I have to draw pixels in function of an algorithm result.

How is it possible to draw precisely pixels in an OpenGL window (i mean : an OpenGL window 640x480 -> i'd like to write something like pixel(12,50)="a color" where (12,50) is the real coordinate of the pixel in the window) (like the BGI API of Borland C, but really more powerfull) ; I know that it's not using OpenGL as it's proper use, but i only found this API for a portable program. If another API does it, it's OK too.

Thank you

Thibault
thibault.groisil@free.fr

Bob
03-29-2000, 04:49 AM
Hello

A nice way of doing this, is to render the image (fractal in your case) to a buffer allocated in the computer memory. Then you use a gl-function called glDrawPixels() to copy the image to the screen.
This should work on both Mac and Windows.

Bob

03-29-2000, 05:21 AM
Originally posted by Bob:
Hello

A nice way of doing this, is to render the image (fractal in your case) to a buffer allocated in the computer memory. Then you use a gl-function called glDrawPixels() to copy the image to the screen.
This should work on both Mac and Windows.

Bob

Hello

>A nice way of doing this, is to render the >image (fractal in your case) to a buffer >allocated in the computer memory.

As a beginner (I've learned OpenGL for 1 day)
I dont't know how to do this... Could you bring me a little more help ?

Thibault

Bob
03-29-2000, 06:13 AM
Hello again

Haven't been using glDrawPixels() much myself, but I will try to explain how it works.

void glDrawPixels(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);

width, and height is the size of your buffer you want to copy.
format is is the format (how color components ate stored) you want to store the data in the video memory. It depends on how you initialized you application, if you set it to GL_RGBA, then format is GL_RGBA.
type is what kind of data you want openGL to read. GL_UNSIGNED_CHAR if your image contains unsigned byte values to represent red, green and blue (maybe alpha too) values float 0 to 255, or GL_FLOAT if it's floats from 0 to 1.
*pixels is a pointer to where you store your data to be copied.

You have to be carefull with how you store your image. If you want to draw it as GL_RGBA, you need to store the image in red, green, blue and alpha components as well.

Well, that was a ****ty attemt to explain. Sure there's someone else out there who's willing to write a better note than me http://www.opengl.org/discussion_boards/ubb/biggrin.gif

Have a look in the red book instead, every OpenGL programmer should have one. Here's an online version: http://heron.cc.ukans.edu/ebt-bin/nph-dw...ullhtml;lang=sv (http://heron.cc.ukans.edu/ebt-bin/nph-dweb/dynaweb/SGI_Developer/OpenGL_PG/@Generic__BookView;cs=fullhtml;lang=sv)

Bob

Cool, didn't know this board changed some words to *, hehe

[This message has been edited by Bob (edited 03-29-2000).]

fenris
03-29-2000, 04:56 PM
You could also allocate a huge buffer
(height * width * 3) for RGB.
Draw into the buffer like you would the window by writing a function that plots for you.

void put_pixel(int x, int y, int r, int g, int b)
{
buffer[(y*(width*3))+x ]=r;
buffer[(y*(width*3))+x+1]=g;
buffer[(y*(width*3))+x+2]=b;
}

After you are done generating the image and drawing to the buffer, upload it as a 2D texture to OpenGL using glTexImage2d() with the quality as GL_LINEAR. Then just draw a quad polygon and texture map it with the image. This is better than glDrawPixels() i think, because:

A) it's faster for screen updates
B) can be scaled fast and easy by translating the modelview matrix

Bob
03-30-2000, 01:58 AM
Problem with your method:

A) Fast to update screen, yes. BUT! When you want to redraw the screen, you have to destroy the old texture and build a new one (if the image has changed that is).
B) Can be scaled fast and easily. Yes, but why you need to scale? It's a just an image to be shown, nothing more.

Further: A texture can only be of size 2^x, where x is an integer. In the post Thibault first wrote, he mentioned a screen with size 640x480. That means you have to create a texture with size 512x512 to represent the image, and then scale it (loosing image quality when scaling upwards), or with size 1024x1024 (wasting huge amounts of memory).

As I see it, it's easier to just copy the pixels to the framebuffer. When drawing a polygon/quad, you have to set correct coordinates to get it to cover the entire screen.

The easiest way is to get another API to do the work, OpenGL is not (directly) made for these kind of applications.

If you want the portapility you said: "and i won't write 2 codes!!", you should take a look at GLUT (GL Utility Toolkit) which can handle windows and input (mouse and keyboard), and is compilable on all platforms supporting OpenGL/GLUT with no modifications at all. That is, if you decide to use OpenGL and no other API.

Bob

03-30-2000, 02:43 AM
About one year ago I found under "http://www.westga.edu/*dsharpe/courses/cs4250/OpenGL/install.html" (which, unfortunately, seems not to be available any more) the following simple programm (C code follows):

// From Angel, p. 436

#include <GL/glut.h>
#include <stdlib.h>

void myinit(void) {
glClearColor(1.0, 1.0, 1.0, 1.0);
glColor3f(1.0, 0.0, 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 500.0, 0.0, 500.0);
glMatrixMode(GL_MODELVIEW);
}

void display(void) {
typedef GLfloat point2[2];
point2 vertices[3] = {{0.0, 0.0}, {249.0, 499.0}, {499.0, 0.0}};
int j, k;
point2 p = {0.0, 0.0};
glClear(GL_COLOR_BUFFER_BIT);
for (k = 0; k < 50000; k++) {
j = rand() % 3;
p[0] = (p[0] + vertices[j][0]) / 2.0;
p[1] = (p[1] + vertices[j][1]) / 2.0;
glBegin(GL_POINTS);
glVertex2fv(p);
glEnd();
}
glFlush();
}

void main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (500, 500);
glutInitWindowPosition (0, 0);
glutCreateWindow ("Sierpinski Gasket");
glutDisplayFunc (display);
myinit();
glutMainLoop();
}

The tutorial text to it was (html source code follows):

<HTML>

<HEAD>
<TITLE>Installing OpenGL and Utilities</TITLE>
</HEAD>

<H1>Installing OpenGL and Utilities</H1>



These instructions tell how to install OpenGL, along with the glu, glut,
and aux libraries, under Microsoft Windows 95 and NT. They assume you have
Microsoft Developer's Studio with Visual C++ installed; if not, then change
the folder name,


<UL>
C:\Program Files\DevStudio\VC\
[/LIST]



to whatever is appropriate for your C/C++ installation.

<TABLE BORDER>
<TR>
<TD><UL>Windows 95[/LIST]</TD>
<TD><UL>Windows NT[/LIST]</TD>
</TR>
<TR VALIGN=TOP>
<TD>

<LI>

Install OpenGL:

<LI>

Save glaux.h (gl.h>gl.h</A>,
), and
<A HREF=glu.h>glu.h</A> in
C:\Program Files\DevStudio\VC\include\gl\</LI>

<LI>

Right-click to save
glu32.lib (ftp://ftp.westga.edu/pub/class/dsharpe/glaux.lib>glaux.lib</A>,
), and
<A HREF=ftp://ftp.westga.edu/pub/class/dsharpe/opengl32.lib>opengl32.lib</A> in
C:\Program Files\DevStudio\VC\lib\</LI>

<LI>

Right-click to save opengl32.dll (ftp://ftp.westga.edu/pub/class/dsharpe/glu32.dll>glu32.dll</A>) in
C:\Windows\System\</LI>


<LI>

Right-click to save <A HREF=ftp://ftp.westga.edu/pub/class/dsharpe/glut.dll>glut.dll</A> to
c:\windows\system\</LI>

<LI>

Save <A HREF=glut.h>glut.h</A> to
c:\Program Files\DevStudio\Vc\include\gl\</LI>

<LI>

Right-click to save <A HREF=ftp://ftp.westga.edu/pub/class/dsharpe/glut32.lib>glut32.lib</A> to
c:\Program Files\DevStudio\Vc\lib\</LI>
</TD>
<TD>

<LI>

Windows NT comes with OpenGL already installed.</LI>

<LI>

Right-click to save <A HREF=ftp://ftp.westga.edu/pub/class/dsharpe/glut.dll>glut.dll</A> to
c:\winnt\system32\</LI>

<LI>

Save <A HREF=glut.h>glut.h</A> to
c:\Program Files\DevStudio\Vc\include\gl\</LI>

<LI>

Right-click to save <A HREF=ftp://ftp.westga.edu/pub/class/dsharpe/glut32.lib>glut32.lib</A> to
c:\Program Files\DevStudio\Vc\lib\</LI>
</TD>
</TR>
<TR>
<TD COLSPAN=2>
[list=1]
<LI>

To test the installation:
[list=a]
<LI>Create a Visual C++ project called "glSierpinski".</LI>
<LI>Save <A HREF=main.cpp>main.cpp</A> to your project
directory.</LI>
<LI>Add main.cpp to your project.</LI>
<LI>Go to the Project / Settings / Link window and add the file names
glut32.lib, glu32.lib, and opengl32.lib to the Object/library
modules box if necessary.</LI>
<LI>Compile it, link it, and run it. It should draw Sierpinski's
gasket in a window.</LI>
</LI>

</TD>
</TR>
</TABLE>


</BODY>
</HTML>

May be, it helps for a beginning!?
Good luck
Aris

(A.Christidis@de1.vdogrp.de)

falcon
03-30-2000, 07:53 AM
I know this is a OpenGL board, but wouldn't it be easier to use a 2D API for what you are trying to accomplish? Writing directly to the frame buffer with glDrawPixels is very slow on end-user hardware.

I'd suggest you take a look at SDL, a cross platform 2D toolkit
http://www.devolution.com/~slouken/projects/SDL/index.html

It works on Linux, Win32, MacOS and BeOS.