PDA

View Full Version : Creating 2 LazyOpenGL boxes



IlovePascal
20-07-2007, 08:26 PM
System: Windows XP
Compiler/IDE: Lazarus 1.0 for Win32
API: OpenGL

Hey all!

I've been writing a program which basically draws stuff on a LazyOpenGL box. Simple.
Now, however, I would like to improve it and either
- add another form with another LazyOpenGL box
- or simply add another LazyOpenGL box on the same form
which would run simultaneously with the main form but would show other pieces of information.

At the moment, my drawing procedure looks like this:
{code}
procedure TForm1.Timer1Timer(Sender: TObject);
begin
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

...

// Draw everything
DrawBackground(...);
DrawAxes(...);
DrawDots(...);

// Displaya
OpenGLBox1.SwapBuffers;
end;
{/code}

My problem is that I don't know how to tell which OpenGLBox to draw on when I create a second OpenGLBox on the same form; or how to open a second form at the same time as the first one.

I tried creating a second OpenGLBox and adding OpenGLBox2.SwapBuffers on the last line, but I get a SIGSEV error.
I also tried designing another form, which automatically adds the line
Application.CreateForm(TForm2, Form2);
in the main program
{code}
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.CreateForm(TForm2, Form2);
Application.Run;
end.
{/code}
but the second form never runs.
I also tried
{code}
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
Application.CreateForm(TForm2, Form2);
Application.Run;
end.
{/code}
to see if the second form would run after the first one closes, but it doesnt.

I tried moving the lines
Application.CreateForm(TForm2, Form2);
Application.Run;
to the procedure which runs when the first form is created, but it bugs.

Could anyone please help?
Cheers ;)

AthenaOfDelphi
21-07-2007, 09:11 AM
Hi IlovePascal,

I'm no expert, but if my understanding is correct, its all about the rendering context.

I don't know anything about LazyOpenGL, but with normal OpenGL (dglOpenGL headers) you'd have something like this to create and activate a rendering context.


fDC:=getDC(pnlGL.handle);
fGLRC:=createRenderingContext(fDC,[opDoubleBuffered],32,24,0,0,0,0);
activateRenderingContext(fDC,fGLRC);


Assuming you want to draw on two (in this case) panels, you'd probably do something like this.


fPanel1DC:=getDC(pnl1.handle);
fPanel2DC:=getDC(pnl2.handle);
fPanel1GLRC:=createRenderingContext(fPanel1DC,[opDoubleBuffered],32,24,0,0,0,0);
fPanel2GLRC:=createRenderingContext(fPanel2DC,[opDoubleBuffered],32,24,0,0,0,0);


Then, when you want to draw on panel 1....


activateRenderingContext(fPanel1GLRC);
...
(* DO YOUR PANEL 1 DRAWING HERE *)
...
deactivateRenderingContext;


And likewise for panel 2...


activateRenderingContext(fPanel2GLRC);
...
(* DO YOUR PANEL 2 DRAWING HERE *)
...
deactivateRenderingContext;


As I say, this should work if my understanding of OpenGL is correct. As for how to handle this when its spread across multiple forms... I'm afraid you're on your own with that one, just be aware that you can only have one rendering context active at once.

IlovePascal
22-07-2007, 08:00 PM
Ok, I get the idea; but I couldnt get it to work...
My main problem is that the compiler cant find the function createRenderingContext. In which unit can I find it?

And because the LazyOpenGL box is automatically created, is it still ok to use the functions and procedures you tell me to use?

Thanks again!

User137
22-07-2007, 11:14 PM
This depends on OpenGL headers you are using. For example dglOpenGL has function wglMakeCurrent(h_Dc, h_Rc)
that alone is needed for swapping rendering display.
This makes screen come visible (call at end of each frame):
SwapBuffers(h_Dc);

.. which was created with
h_Rc:=wglCreateContext(h_Dc);

IlovePascal
29-07-2007, 07:19 AM
Ok, I got the procedures working, but I get a sigsegv error on the line
Windows.Swapbuffers(pnl2DC);
the message box says the problem is in the procedure
OGLDRV!DrvSwapLayerBuffers;

My code looks like this:

procedure TForm1.Form1Create(Sender: TObject);
begin
...
with PanelHandles do
begin
p1DC := getDC(OpenGLBox1.handle); // Get Device Context
p2DC := getDC(OpenGLBox2.handle);
p1RC := wglCreateContext(p1DC);
p2RC := wglCreateContext(p2DC);
end;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
with panelHandles do wglMakeCurrent(p2Dc, p2Rc);
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

Background.Render;
Windows.SwapBuffers(panelHandles.p2DC);
//OpenGLBox2.SwapBuffers;

with panelHandles do wglMakeCurrent(p1Dc, p1Rc);
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

...

BAction.Draw;

...

OpenGLBox1.SwapBuffers;
end;

I guess what that means is that I do not properly initialise the second OpenGL box, but if that's the case, how am I supposed to initialise it?
Or is it something else I'm doing wrong?