summaryrefslogtreecommitdiff
path: root/documentation/src/opengl.dox
diff options
context:
space:
mode:
authorFabien Costantini <fabien@onepost.net>2008-10-14 22:12:25 +0000
committerFabien Costantini <fabien@onepost.net>2008-10-14 22:12:25 +0000
commit497afccb07164373e0de6639e754d7d691f1926f (patch)
tree449d0b92ceb05f39617fe8fc2876d16eecde7460 /documentation/src/opengl.dox
parente08fffdfe08bbc9320e39a15d162b6501abd4925 (diff)
Doxygen pdf man: First version added in documentation/fltk.pdf, old doc removed, images, dox files moved to a new src directory.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@6431 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'documentation/src/opengl.dox')
-rw-r--r--documentation/src/opengl.dox459
1 files changed, 459 insertions, 0 deletions
diff --git a/documentation/src/opengl.dox b/documentation/src/opengl.dox
new file mode 100644
index 000000000..bed6b5d5c
--- /dev/null
+++ b/documentation/src/opengl.dox
@@ -0,0 +1,459 @@
+/**
+
+ \page opengl 8 - Using OpenGL
+
+This chapter discusses using FLTK for your OpenGL applications.
+
+\section opengl_using Using OpenGL in FLTK
+
+The easiest way to make an OpenGL display is to subclass
+<A href="Fl_Gl_Window.html#Fl_Gl_Window"><tt>Fl_Gl_Window</tt></A>.
+Your subclass must implement a <tt>draw()</tt> method which uses
+OpenGL calls to draw the display. Your main program should call
+<tt>redraw()</tt> when the display needs to change, and
+(somewhat later) FLTK will call <tt>draw()</tt>.
+
+With a bit of care you can also use OpenGL to draw into
+normal FLTK windows. This allows you to use Gouraud shading for
+drawing your widgets. To do this you use the
+<A href="#gl_start"><tt>gl_start()</tt></A>
+and
+<A href=#gl_finish><tt>gl_finish()</tt></A>
+functions around your OpenGL code.
+
+You must include FLTK's <tt><FL/gl.h></tt> header
+file. It will include the file <tt><GL/gl.h></tt>, define
+some extra drawing functions provided by FLTK, and include the
+<tt><windows.h></tt> header file needed by WIN32
+applications.
+
+\section opengl_subclass Making a Subclass of Fl_Gl_Window
+
+To make a subclass of Fl_Gl_Window, you must provide:
+
+\li A class definition.
+
+\li A <tt>draw()</tt> method.
+
+\li A <tt>handle()</tt> method if you need to receive input from the user.
+
+If your subclass provides static controls in the window, they
+must be redrawn whenever the <tt>FL_DAMAGE_ALL</tt> bit is set
+in the value returned by <tt>damage()</tt>. For double-buffered
+windows you will need to surround the drawing code with the
+following code to make sure that both buffers are redrawn:
+
+\code
+#ifndef MESA
+glDrawBuffer(GL_FRONT_AND_BACK);
+#endif // !MESA
+... draw stuff here ...
+#ifndef MESA
+glDrawBuffer(GL_BACK);
+#endif // !MESA
+\endcode
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" CELLSPACING="0" BGCOLOR="#cccccc">
+<TR>
+ <TD><B>Note:</B>
+
+ <P>If you are using the Mesa graphics library, the call
+ to <tt>glDrawBuffer()</tt> is not required and will slow
+ down drawing considerably. The preprocessor instructions
+ shown above will optimize your code based upon the
+ graphics library used.
+
+ </TD>
+
+</TR>
+</TABLE></CENTER>
+
+\subsection opengl_defining Defining the Subclass
+
+To define the subclass you just subclass the <tt>Fl_Gl_Window</tt> class:
+
+\code
+class MyWindow : public Fl_Gl_Window {
+ void draw();
+ int handle(int);
+
+public:
+ MyWindow(int X, int Y, int W, int H, const char *L)
+ : Fl_Gl_Window(X, Y, W, H, L) {}
+};
+\endcode
+
+The <tt>draw()</tt> and <tt>handle()</tt> methods are
+described below. Like any widget, you can include additional
+private and public data in your class (such as scene graph
+information, etc.)
+
+\subsection opengl_draw The draw() Method
+
+The <tt>draw()</tt> method is where you actually do your OpenGL drawing:
+
+\code
+void MyWindow::draw() {
+ if (!valid()) {
+ ... set up projection, viewport, etc ...
+ ... window size is in w() and h().
+ ... valid() is turned on by FLTK after draw() returns
+ }
+ ... draw ...
+}
+\endcode
+
+\subsection opengl_handle The handle() Method
+
+The <tt>handle()</tt> method handles mouse and keyboard
+events for the window:
+
+\code
+int MyWindow::handle(int event) {
+ switch(event) {
+ case FL_PUSH:
+ ... mouse down event ...
+ ... position in Fl::event_x() and Fl::event_y()
+ return 1;
+ case FL_DRAG:
+ ... mouse moved while down event ...
+ return 1;
+ case FL_RELEASE:
+ ... mouse up event ...
+ return 1;
+ case FL_FOCUS :
+ case FL_UNFOCUS :
+ ... Return 1 if you want keyboard events, 0 otherwise
+ return 1;
+ case FL_KEYBOARD:
+ ... keypress, key is in Fl::event_key(), ascii in Fl::event_text()
+ ... Return 1 if you understand/use the keyboard event, 0 otherwise...
+ return 1;
+ case FL_SHORTCUT:
+ ... shortcut, key is in Fl::event_key(), ascii in Fl::event_text()
+ ... Return 1 if you understand/use the shortcut event, 0 otherwise...
+ return 1;
+ default:
+ // pass other events to the base class...
+ return Fl_Gl_Window::handle(event);
+ }
+}
+\endcode
+
+When <tt>handle()</tt> is called, the OpenGL context is not
+set up! If your display changes, you should call
+<tt>redraw()</tt> and let <tt>draw()</tt> do the work. Don't
+call any OpenGL drawing functions from inside <tt>handle()</tt>!
+
+You can call <I>some</I> OpenGL stuff like hit detection and texture
+loading functions by doing:
+
+\code
+ case FL_PUSH:
+ make_current(); // make OpenGL context current
+ if (!valid()) {
+
+ ... set up projection exactly the same as draw ...
+
+ valid(1); // stop it from doing this next time
+ }
+ ... ok to call NON-DRAWING OpenGL code here, such as hit
+ detection, loading textures, etc...
+\endcode
+
+Your main program can now create one of your windows by doing
+<tt>new MyWindow(...)</tt>. You can also use
+<A href="fluid.html#FLUID">FLUID</A>
+by:
+
+-# Putting your class definition in a <tt>MyWindow.H</tt> file.
+ <br>
+-# Creating a <tt>Fl_Box</tt> widget in FLUID.
+ <br>
+-# In the widget panel fill in the "class" field with <tt>MyWindow</tt>.
+ This will make FLUID produce constructors for your new class.
+ <br>
+-# In the "Extra Code" field put <tt>\#include "MyWindow.H"</tt>,
+ so that the FLUID output file will compile.
+
+You must put <tt>glwindow->show()</tt> in your main code
+after calling <tt>show()</tt> on the window containing the
+OpenGL window.
+
+\section opengl_normal Using OpenGL in Normal FLTK Windows
+
+You can put OpenGL code into an
+<A href="subclassing.html#draw"><tt>Fl_Widget::draw()</tt></A>
+method or into the code for a
+<A href="common.html#boxtypes">boxtype</A>
+or other places with some care.
+
+Most importantly, before you show <I>any</I> windows,
+including those that don't have OpenGL drawing, you <B>must</B>
+initialize FLTK so that it knows it is going to use OpenGL. You
+may use any of the symbols described for Fl_Gl_Window::mode()
+to describe how you intend to use OpenGL:
+
+\code
+Fl::gl_visual(FL_RGB);
+\endcode
+
+You can then put OpenGL drawing code anywhere you can draw
+normally by surrounding it with:
+
+\code
+gl_start();
+... put your OpenGL code here ...
+gl_finish();
+\endcode
+
+<A name="gl_start"><tt>gl_start()</tt></A>
+and
+<A name="gl_finish"><tt>gl_finish()</tt></A>
+set up an OpenGL
+context with an orthographic projection so that 0,0 is the
+lower-left corner of the window and each pixel is one unit. The
+current clipping is reproduced with OpenGL <tt>glScissor()</tt>
+commands. These functions also synchronize the OpenGL graphics stream
+with the drawing done by other X, WIN32, or FLTK functions.
+
+The same context is reused each time. If your code changes
+the projection transformation or anything else you should use
+<tt>glPushMatrix()</tt> and <tt>glPopMatrix()</tt> functions to
+put the state back before calling <tt>gl_finish()</tt>.
+
+You may want to use Fl_Window::current()->h() to
+get the drawable height so that you can flip the Y
+coordinates.
+
+Unfortunately, there are a bunch of limitations you must
+adhere to for maximum portability:
+
+\li You must choose a default visual with Fl::gl_visual().
+
+\li You cannot pass <tt>FL_DOUBLE</tt> to Fl::gl_visual().
+
+\li You cannot use Fl_Double_Window or Fl_Overlay_Window.
+
+Do <I>not</I> call <tt>gl_start()</tt> or
+<tt>gl_finish()</tt> when drawing into an Fl_Gl_Window !
+
+\section opengl_drawing OpenGL Drawing Functions
+
+FLTK provides some useful OpenGL drawing functions. They can
+be freely mixed with any OpenGL calls, and are defined by
+including <FL/gl.H> which you should include
+instead of the OpenGL header <tt><GL/gl.h></tt>.
+
+void gl_color(Fl_Color)
+
+\par
+Sets the current OpenGL color to a FLTK color. <I>For
+color-index modes it will use <tt>fl_xpixel(c)</tt>, which is
+only right if this window uses the default colormap!</I>
+
+void gl_rect(int x, int y, int w, int h) <br>
+void gl_rectf(int x, int y, int w, int h)
+
+\par
+Outlines or fills a rectangle with the current color. If
+Fl_Gl_Window::ortho() has been called, then the rectangle will exactly
+fill the pixel rectangle passed.
+
+void gl_font(Fl_Font fontid, int size)
+
+\par
+Sets the current OpenGL font to the same font you get by calling
+<A href="drawing.html#fl_font"><tt>fl_font()</tt></A>.
+
+int gl_height() <br>
+int gl_descent() <br>
+float gl_width(const char *) <br>
+float gl_width(const char *, int n) <br>
+float gl_width(uchar)
+
+\par
+Returns information about the current OpenGL font.
+
+void gl_draw(const char *) <br>
+void gl_draw(const char *, int n)
+
+\par
+Draws a nul-terminated string or an array of <tt>n</tt>
+characters in the current OpenGL font at the current raster
+position.
+
+void gl_draw(const char *, int x, int y) <br>
+void gl_draw(const char *, int n, int x, int y) <br>
+void gl_draw(const char *, float x, float y) <br>
+void gl_draw(const char *, int n, float x, float y)
+
+\par
+Draws a nul-terminated string or an array of <tt>n</tt>
+characters in the current OpenGL font at the given position.
+
+void gl_draw(const char *, int x, int y, int w, int h, Fl_Align)
+
+\par
+Draws a string formatted into a box, with newlines and tabs
+expanded, other control characters changed to ^X, and aligned
+with the edges or center. Exactly the same output as
+<A href="drawing.html#text"><tt>fl_draw()</tt></A>.
+
+\section opengl_speed Speeding up OpenGL
+
+Performance of Fl_Gl_Window may be improved on some types of
+OpenGL implementations, in particular MESA and other software
+emulators, by setting the <tt>GL_SWAP_TYPE</tt> environment
+variable. This variable declares what is in the backbuffer after
+you do a swapbuffers.
+
+\li <tt>setenv GL_SWAP_TYPE COPY</tt> <br>
+ <br>
+ This indicates that the back buffer is copied to the
+ front buffer, and still contains it's old data. This is
+ true of many hardware implementations. Setting this
+ will speed up emulation of overlays, and widgets that
+ can do partial update can take advantage of this as
+ damage() will not be cleared to -1. <p>
+
+\li <tt>setenv GL_SWAP_TYPE NODAMAGE</tt> <br>
+ <br>
+ This indicates that nothing changes the back buffer
+ except drawing into it. This is true of MESA and Win32
+ software emulation and perhaps some hardware emulation
+ on systems with lots of memory. <p>
+
+\li All other values for <tt>GL_SWAP_TYPE</tt>, and not
+ setting the variable, cause FLTK to assume that the
+ back buffer must be completely redrawn after a swap.
+
+This is easily tested by running the <tt>gl_overlay</tt> demo
+program and seeing if the display is correct when you drag
+another window over it or if you drag the window off the screen
+and back on. You have to exit and run the program again for it
+to see any changes to the environment variable.
+
+\section opengl_optimizer Using OpenGL Optimizer with FLTK
+
+<A href="http://www.sgi.com/software/optimizer">OpenGL Optimizer</A>
+is a scene graph toolkit for OpenGL available from
+Silicon Graphics for IRIX and Microsoft Windows. It allows you
+to view large scenes without writing a lot of OpenGL code.
+
+\par OptimizerWindow Class Definition
+
+\par
+To use OpenGL Optimizer with FLTK you'll need to create a
+subclass of <tt>Fl_Gl_Widget</tt> that includes several state
+variables:
+
+\code
+class OptimizerWindow : public Fl_Gl_Window {
+ csContext *context_; // Initialized to 0 and set by draw()...
+ csDrawAction *draw_action_; // Draw action...
+ csGroup *scene_; // Scene to draw...
+ csCamara *camera_; // Viewport for scene...
+
+ void draw();
+
+public:
+ OptimizerWindow(int X, int Y, int W, int H, const char *L)
+ : Fl_Gl_Window(X, Y, W, H, L) {
+ context_ = (csContext *)0;
+ draw_action_ = (csDrawAction *)0;
+ scene_ = (csGroup *)0;
+ camera_ = (csCamera *)0;
+ }
+
+ void scene(csGroup *g) { scene_ = g; redraw(); }
+
+ void camera(csCamera *c) {
+ camera_ = c;
+ if (context_) {
+ draw_action_->setCamera(camera_);
+ camera_->draw(draw_action_);
+ redraw();
+ }
+ }
+};
+\endcode
+
+\par The camera() Method
+
+\par
+The <tt>camera()</tt> method sets the camera (projection and
+viewpoint) to use when drawing the scene. The scene is redrawn after
+this call.
+
+\par The draw() Method
+
+\par
+The <tt>draw()</tt> method performs the needed initialization and does
+the actual drawing:
+
+\code
+void OptimizerWindow::draw() {
+ if (!context_) {
+ // This is the first time we've been asked to draw; create the
+ // Optimizer context for the scene...
+
+#ifdef WIN32
+ context_ = new csContext((HDC)fl_getHDC());
+ context_->ref();
+ context_->makeCurrent((HDC)fl_getHDC());
+#else
+ context_ = new csContext(fl_display, fl_visual);
+ context_->ref();
+ context_->makeCurrent(fl_display, fl_window);
+#endif // WIN32
+
+ ... perform other context setup as desired ...
+
+ // Then create the draw action to handle drawing things...
+
+ draw_action_ = new csDrawAction;
+ if (camera_) {
+ draw_action_->setCamera(camera_);
+ camera_->draw(draw_action_);
+ }
+ } else {
+#ifdef WIN32
+ context_->makeCurrent((HDC)fl_getHDC());
+#else
+ context_->makeCurrent(fl_display, fl_window);
+#endif // WIN32
+ }
+
+ if (!valid()) {
+ // Update the viewport for this context...
+ context_->setViewport(0, 0, w(), h());
+ }
+
+ // Clear the window...
+ context_->clear(csContext::COLOR_CLEAR | csContext::DEPTH_CLEAR,
+ 0.0f, // Red
+ 0.0f, // Green
+ 0.0f, // Blue
+ 1.0f); // Alpha
+
+ // Then draw the scene (if any)...
+ if (scene_)
+ draw_action_->apply(scene_);
+}
+\endcode
+
+\par The scene() Method
+
+\par
+The <tt>scene()</tt> method sets the scene to be drawn. The scene is
+a collection of 3D objects in a <tt>csGroup</tt>. The scene is redrawn
+after this call.
+
+\htmlonly
+<hr>
+<a class="el" href="index.html">[Index]</a> &nbsp;&nbsp;
+<a class="el" href="subclassing.html">[Previous]&nbsp; 7 - Adding and Extending Widgets</a>&nbsp;
+<a class="el" href="fluid.html">[Next]&nbsp; 9 - Programming with FLUID</a>&nbsp;
+\endhtmlonly
+*/