PDA

View Full Version : 2D Drawing using GL_POINTS



Brlja
12-31-2009, 10:31 AM
Hi Guys,

I'm currently doing some line rasterization project using 6 different algorithms in OpenGl (CsGL).

First of all I'm new to OpenGl.

My project is mostly done but now when I have started to analyze what I have done it seems to me that something is very wrong.

I have written application that looks like paint. You can click on screen and draw lines (paint style) in different colors using selected algorithm.

Everything works fine when there are not much lines on the screen. If there are many lines, my cpu core goes to 100% and it is all you know.. crappy.

I did not know how to keep drawn lines on the screen when i draw new ones and especially when window is minimized or size changed so I have created list of objects. Each line is a separate object which consists of color and list of pixels.

So each time glDraw() is called I redraw all of the objects using GL_POINTS.

Is this the right way?? Can I keep my pixels without list, something like global screen matrix that i don't need to redraw all the time?

Thanx for your answer.

Dark Photon
12-31-2009, 03:54 PM
You can click on screen and draw lines (paint style) in different colors using selected algorithm. ... If there are many lines, my cpu core goes to 100% ...

I did not know how to keep drawn lines on the screen when i draw new ones and especially when window is minimized or size changed so I have created list of objects. Each line is a separate object which consists of color and list of pixels.

So each time glDraw() is called I redraw all of the objects using GL_POINTS.

Is this the right way?? Can I keep my pixels without list, something like global screen matrix that i don't need to redraw all the time?

Well, drawing lines using individual points is expensive. Why aren't you letting OpenGL draw the lines using GL_LINES primitives?

Also, I'll bet you're using immediate mode to draw your points. Let's see your code to draw your points. You at least should use vertex arrays, either client arrays or VBOs (server arrays). That'll speed things up a lot.

And yes, you can cache the results of your rendering to a texture (pixel grid), and from then on just draw the texture first before you draw the next new line, then save it off. That's one way to do it. The operative question with doing this is whether your paint program needs to support "undo". If so, then you'll still need to keep your list of lines so you can regenerate on an undo.

Alfonse Reinheart
12-31-2009, 04:25 PM
And yes, you can cache the results of your rendering to a texture (pixel grid), and from then on just draw the texture first before you draw the next new line, then save it off. That's one way to do it.

Actually, I'd suggest using a Renderbuffer and just doing a blit to the framebuffer. It's much more explicit to OpenGL what you're doing, and probably faster too.

Brlja
01-01-2010, 04:21 AM
Well, drawing lines using individual points is expensive. Why aren't you letting OpenGL draw the lines using GL_LINES primitives?


Thats not what my project is about.
I need to make my own line drawing algorithm in OpenGL (incremental, incremental symmetrical, midpoint, two step etc..).



Also, I'll bet you're using immediate mode to draw your points. Let's see your code to draw your points. You at least should use vertex arrays, either client arrays or VBOs (server arrays). That'll speed things up a lot.


This is my code (most of it is taken from other people's examples as I only have 3 days of expirience in openGl):

Do I need this?


protected override void InitGLContext()
{
GL.glShadeModel(GL.GL_SMOOTH);
GL.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
GL.glClearDepth(1.0);
GL.glEnable(GL.GL_DEPTH_TEST);
GL.glDepthFunc(GL.GL_LEQUAL);
GL.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
}


This is where the things get drawn:


public override void glDraw()
{
GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

if (ObjectBeingDrawn)
{
GL.glColor3d(DrawnObjekt.Boja.Red, DrawnObjekt.Boja.Green, DrawnObjekt.Boja.Blue);
glDrawPixels(DrawnObjekt);
}
for (int Counter = 0; Counter < Objekti.Count; Counter++)
{
Objekt = Objekti[Counter];
GL.glColor3d(Objekt.Boja.Red, Objekt.Boja.Green, Objekt.Boja.Blue);
glDrawPixels(Objekt);
}
}

public void glDrawPixels(_Objekt Objekt)
{
for (int i = 0; i < Objekt.TockeObjekta.Count; i++)
{
MouseXposition = Objekt.TockeObjekta[i].X;
MouseYposition = Objekt.TockeObjekta[i].Y;
GetOGLPos();
GL.glBegin(GL.GL_POINTS);
GL.glVertex2d(OpenGlXpos, OpenGlYpos);
GL.glEnd();
}
}

Function that converts windows coordinates to vertex:


public void GetOGLPos()
{
/*
This function converts coordinates from Windows form coordinates to OpenGl vertex coordinates
*/
int[] viewport = new int[4];
double[] modelview = new double[16];
double[] projection = new double[16];

float winX, winY;
double posX, posY, posZ;

GL.glGetDoublev(GL.GL_MODELVIEW_MATRIX, modelview);
GL.glGetDoublev(GL.GL_PROJECTION_MATRIX, projection);
GL.glGetIntegerv(GL.GL_VIEWPORT, viewport);

winX = (float)MouseXposition;
winY = (float)viewport[3] - (float)MouseYposition;
GL.gluUnProject(winX, winY, 0, modelview, projection, viewport, out posX, out posY, out posZ);

OpenGlXpos = posX;
OpenGlYpos = posY;
}

This is my Object class that holds information about line:


public class _Objekt
{
public struct _Boja
{
public double Red;
public double Green;
public double Blue;
};

public List<Point> KrajnjeTocke;
public List<Point> TockeObjekta;
public _Boja Boja;
public Point Tocka;

public _Objekt()
{
KrajnjeTocke = new List<Point>();
TockeObjekta = new List<Point>();
Point Tocka = new Point();
KrajnjeTocke.Add(Tocka);
KrajnjeTocke.Add(Tocka);
}

public void SetColor(double Red, Double Green, Double Blue)
{
Boja.Red = Red;
Boja.Green = Green;
Boja.Blue = Blue;
}
}

Thanx for your help.

Brlja
01-01-2010, 12:58 PM
Hi,



public override unsafe void glDraw()
{
GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

if (ObjectBeingDrawn)
{
GL.glColor3d(DrawnObjekt.Boja.Red, DrawnObjekt.Boja.Green, DrawnObjekt.Boja.Blue);
// glDrawPixels(DrawnObjekt);
if (DrawnObjekt.Vertices != null)
{
fixed (float* TexCoordPtr = &amp;DrawnObjekt.Vertices[0])
{ GL.glVertexPointer(2, GL.GL_FLOAT, 0, TexCoordPtr); }
GL.glEnableClientState(GL.GL_VERTEX_ARRAY);
GL.glDrawArrays(GL.GL_POINTS, 0, DrawnObjekt.Vertices.GetUpperBound(0) + 1);
GL.glDisableClientState(GL.GL_VERTEX_ARRAY);
}
}

for (int Counter = 0; Counter < Objekti.Count; Counter++)
{
Objekt = Objekti[Counter];
GL.glColor3d(Objekt.Boja.Red, Objekt.Boja.Green, Objekt.Boja.Blue);
fixed (float* TexCoordPtr = &amp;Objekt.Vertices[0])
{ GL.glVertexPointer(2, GL.GL_FLOAT, 0, TexCoordPtr); }
GL.glEnableClientState(GL.GL_VERTEX_ARRAY);
GL.glDrawArrays(GL.GL_POINTS, 0,Objekt.Vertices.GetUpperBound(0) + 1);
GL.glDisableClientState(GL.GL_VERTEX_ARRAY);

// glDrawPixels(Objekt);
}
}


This is my modified code using vertex array.
It works but I get some noise on the screen.
Some dots on random places.

I have checked vertex array for bugs (wrong or unwanted entries) but everything is fine there also that array draws ok in immediate mode.

Maybe I'm not clearing memory right?

Brlja
01-02-2010, 04:39 AM
Got it!!

Problem was here:


GL.glDrawArrays(GL.GL_POINTS,0,VertLenght);


I sent the number of elements in array not the points so correct thing is:



GL.glDrawArrays(GL.GL_POINTS,0,VertLenght/2);

Because each point consists of 2 coordinates.

Now it works much better :)

I made another breakthrough in optimization.
I draw my line on mousehover event and it is waste of resources!!
Human eye can see 25 fps so I have added timer to run algorithm only 25 times per second when line is being drawn.