NAME
FLTK::GlWindow - ...exactly what you think it is
Description
Provides an area in which the draw()
method can use OpenGL to draw. This widget sets things up so OpenGL works, and also keeps an OpenGL "context" for that window, so that changes to the lighting and projection may be reused between redraws. GlWindow also flushes the OpenGL streams and swaps buffers after draw()
returns.
You must provide an implementation for draw()
. You can avoid reinitializing the viewport and lights and other things by checking valid()
at the start of draw()
and only doing the initialization if it is false.
draw()
can only use OpenGL calls. Do not attempt to call any of the functions in FLTK::draw, or X or GDI32 or any other drawing api. Do not call glstart()
or glfinish()
.
Double Buffering
Normally double-buffering is enabled. You can disable it by chaning the mode()
to turn off the DOUBLE_BUFFER
bit.
If double-buffering is enabled, the back buffer is made current before draw()
is called, and the back and front buffers are automatically swapped after draw()
is completed.
Some tricks using the front buffer require you to control the swapping. You can call swap_buffers()
to swap them (OpenGL does not provide a portable function for this, so we provide it). But you will need to turn off the auto-swap, you do this by adding the NO_AUTO_SWAP
bit to the mode()
.
Overlays
The method draw_overlay()
is a second drawing operation that is put atop the main image. You can implement this, and call redraw_overlay()
to indicate that the image in this overlay has changed and that draw_overlay()
must be called.
Originally this was written to support hardware overlays, but FLTK emulated it if the hardware was missing so programs were portable. FLTK 2.0 is not normally compiled to support hardware overlays, but the emulation still remains, so you can use these functions. Modern hardware typically has no overlays, and besides it is fast enough that the original purpose of them is moot.
By default the emulation is to call draw_overlay()
after draw()
and before swapping the buffers, so the overlay is just part of the normal image and does not blink. You can get some of the advantages of overlay hardware by setting the GL_SWAP_TYPE
environment variable, which will cause the front buffer to be used for the draw_overlay()
method, and not call draw()
each time the overlay changes. This will be faster if draw()
is very complex, but the overlay will blink. GL_SWAP_TYPE
can be set to:
USE_COPY
uses glCopyPixels to copy the back buffer to the front.-
This should always work.
COPY
indicates that theswap_buffers()
function actually copies the back to the front buffer, rather than swapping them. If your card does this (most do) then this is best.NODAMAGE
indicates that behavior is likeCOPY
but nothing changes the back buffer, including overlapping it with another OpenGL window. This is true of software OpenGL emulation, and may be true of some modern cards with lots of memory.
Functions
can_do
my $can = $glwindow->can_do( );
-
Returns true if the hardware supports the current value of
mode()
. If false, attempts to show or draw this window will cause anerror()
. my $can = $glwindow->can_do( $mode );
-
Returns true if the hardware supports
mode
, seemode()
for the meaning of the bits.
can_do_overlay
my $overlay = $glwindow->can_do_overlay( );
-
Return true if the hardware supports OpenGL overlay planes, and the fltk2 libs have been compiled to use them. If true,
draw_overlay()
will be called with OpenGL setup to draw these overlay planes, andredraw_overlay()
will not cause the maindraw()
to be called.
context
my $glc = $glwindow->context( );
-
Return the current OpenGL context object being used by this window, or
0
if there is none. $glwindow->context( $glc, $destroy_flag );
-
Set the OpenGL context object to use to draw this window.
This is a system-dependent structure (HGLRC on Windows, GLXContext on X, and AGLContext (may change) on OS/X), but it is portable to copy the context from one window to another. You can also set it to
undef
, which will force FLTK to recreate the context the next timemake_current()
is called, this is useful for getting around bugs in OpenGL implementations.destroy_flag
indicates that the context belongs to this window and should be destroyed by it when no longer needed. It will be destroyed when the window is destroyed, or when themode()
is changed, or if the context is changed to a new value with this call.
destroy
$glwindow->destroy( );
-
Besides getting rid of the window, this will destroy the context if it belongs to the window.
hide_overlay
invalidate
$glwindow->invalidate( );
-
Turn off
valid()
.
make_current
$glwindow->make_current( );
-
Selects the OpenGL context for the widget, creating it if necessary. It is called automatically prior to the
draw()
method being called. You can call it inhandle()
to set things up to do OpenGL hit detection, or call it other times to do incremental update of the window.
make_overlay_current
$glwindow->make_overlay_current( );
-
Selects the OpenGL context for the widget's overlay. This can be used to do incremental OpenGL drawing into the overlay. If hardware overlay is not supported, this sets things to draw into the front buffer, which is probably not good enough emulation to be usable.
mode
my $caps = $glwindow->mode( );
my $can = $glwindow->mode( $newmode );
-
Set or change the OpenGL capabilites of the window. The value can be any of the symbols from FLTK::visual OR'd together:
INDEXED_COLOR
indicates that a colormapped visual is ok. This call will normally fail if a TrueColor visual cannot be found.RGB_COLOR
this value is zero and may be passed to indicate thatINDEXED_COLOR
is not wanted.RGB24_COLOR
indicates that the visual must have at least 8 bits of red, green, and blue (Windows calls this "millions of colors").DOUBLE_BUFFER
indicates that double buffering is wanted.SINGLE_BUFFER
is zero and can be used to indicate that double buffering is \a not wanted.ACCUM_BUFFER
makes the accumulation buffer workALPHA_BUFFER
makes an alpha bufferDEPTH_BUFFER
makes a depth/Z bufferSTENCIL_BUFFER
makes a stencil bufferMULTISAMPLE
makes it multi-sample antialias if possible (X only)STEREO
stereo if possibleNO_AUTO_SWAP
disables the automatic call toswap_buffers()
afterdraw()
.NO_ERASE_OVERLAY
if overlay hardware is used, don't call glClear before callingdraw_overlay()
.
If the desired combination cannot be done, FLTK will try turning off
MULTISAMPLE
andSTERERO
. If this also fails then attempts to create the context will causeerror()
to be called, aborting the program. Usecan_do()
to check for this and try other combinations.You can change the mode while the window is displayed. This is most useful for turning double-buffering on and off. Under X this will cause the old X window to be destroyed and a new one to be created. If this is a top-level window this will unfortunately also cause the window to blink, raise to the top, and be de-iconized, and the ID will change, possibly breaking other code. It is best to make the GL window a child of another window if you wish to do this!
new
my $win = $glwindow->new( $x, $y, $w, $h, $label );
-
The constructor sets the
mode()
toRGB_COLOR | DEPTH_BUFFER | DOUBLE_BUFFER
which is probably all that is needed for most 3D OpenGL graphics. my $win = $glwindow->new( $w, $h, $label );
-
Same but placed by the OS.
ortho
$glwindow->ortho( );
-
Set the projection so
0, 0
is in the lower left of the window and each pixel is 1 unit wide/tall. If you are drawing 2D images, yourdraw()
method may want to call this whenvalid()
is false.
redraw_overlay
$glwindow->redraw_overlay( );
-
Causes
draw_overlay()
to be called at a later time. Initially the overlay is clear, if you want the window to display something in the overlay when it first appears, you must call this immediately after youshow()
your window.
swap_buffers
$glwindow->swap_buffers( );
-
Swap the front and back buffers of this window (or copy the back buffer to the front, possibly clearing or garbaging the back one, depending on your OpenGL implementation.
This is called automatically after
draw()
unless theNO_AUTO_SWAP
flag is set in themode()
.
valid
my $okay = $glwindow->valid( );
-
This flag is turned off on a new window or if the window is ever resized or the context is changed. It is turned on after
draw()
is called.draw()
can use this to skip initializing the viewport, lights, or other pieces of the context.package My_GlWindow_Subclass; sub draw { my ($self) = @_; if (!$self->valid()) { glViewport( 0, 0, $self->w(), $self->h() ); glFrustum(...); glLight(...); glEnable(...); # ...other initialization... } #... draw your geometry here ... }
$glwindow->valid( $is_it );
Subclassing FLTK::GlWindow
TODO
Author
Sanko Robinson <sanko@cpan.org> - http://sankorobinson.com/
License and Legal
Copyright (C) 2008-2010 by Sanko Robinson <sanko@cpan.org>
This program is free software; you can redistribute it and/or modify it under the terms of The Artistic License 2.0. See the LICENSE file included with this distribution or notes on the Artistic License 2.0 for clarification.
When separated from the distribution, all original POD documentation is covered by the Creative Commons Attribution-Share Alike 3.0 License. See the clarification of the CCA-SA3.0.