diff --git a/docs/Doxyfile.in b/docs/Doxyfile.in index 20c6b816..e61a4239 100644 --- a/docs/Doxyfile.in +++ b/docs/Doxyfile.in @@ -715,7 +715,7 @@ EXCLUDE_SYMBOLS = APIENTRY GLFWAPI # directories that contain example code fragments that are included (see # the \include command). -EXAMPLE_PATH = +EXAMPLE_PATH = @GLFW_SOURCE_DIR@/examples # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp diff --git a/docs/quick.dox b/docs/quick.dox index 881d59ad..41ccb32e 100644 --- a/docs/quick.dox +++ b/docs/quick.dox @@ -5,27 +5,50 @@ @section quick_start Introduction In this guide you will learn how to write simple OpenGL applications using -GLFW 3. We start by initializing GLFW, then we create a window and read some -user keyboard input. +GLFW 3. It will introduce you to a few of the most commonly used functions, but +there are many others. To see detailed documentation on any GLFW function, just +click on its name. @section quick_include Including the GLFW header -The first thing you have to do when using GLFW is including the GLFW header. +In the files of your program where you use OpenGL or GLFW, you need to include +the GLFW 3 header file. @code #include @endcode -This header defines all the constants, types and function prototypes of the -GLFW API. It also includes the OpenGL header provided by your development -environment and defines all the necessary constants and types for it to work on -that particular platform. +This defines all the constants, types and function prototypes of the GLFW API. +It also includes the OpenGL header, and defines all the constants and types +necessary for it to work on your platform. + +For example, under Windows you are normally required to include @c windows.h +before including @c GL/gl.h. This would make your source file tied to Windows +and pollute your code's namespace with the whole Win32 API. + +Instead, the GLFW header takes care of this for you, not by including @c +windows.h, but rather by itself duplicating only the necessary parts of it. It +does this only where needed, so if @c windows.h @em is included, the GLFW header +does not try to redefine those symbols. + +In other words: + +@arg Do @em not include the OpenGL headers yourself, as GLFW does this for you +@arg Do @em not include @c windows.h or other platform-specific headers unless + you plan on using those APIs directly +@arg If you @em do need to include such headers, do it @em before including the + GLFW and it will detect this Starting with version 3.0, the GLU header @c glu.h is no longer included by default. If you wish to include it, define @c GLFW_INCLUDE_GLU before the inclusion of the GLFW header. +@code +#define GLFW_INCLUDE_GLU +#include +@endcode + @section quick_init_term Initializing and terminating GLFW @@ -35,9 +58,7 @@ error occurred. @code if (!glfwInit()) -{ exit(EXIT_FAILURE); -} @endcode When you are done using GLFW, typically at the very end of the program, you need @@ -52,6 +73,36 @@ GLFW. After this call, you must call @ref glfwInit again before using any GLFW functions that require it. +@section quick_capture_error Setting an error callback + +Most events are reported through callbacks, whether it's a key being pressed, +a GLFW window being moved, or an error occurring. Callbacks are simply +C functions (or C++ static methods) that are called by GLFW with arguments +describing the event. + +In case @ref glfwInit or any other GLFW function fails, an error is reported to +the GLFW error callback. You can receive these reports by setting the error +callback. The callback function itself should match the signature of @ref +GLFWerrorfun. Here is a simple error callback that just prints the error +description to @c stderr. + +@code +void error_callback(int error, const char* description) +{ + fputs(description, stderr); +} +@endcode + +Setting the callback, so GLFW knows to call it, is done with @ref +glfwSetErrorCallback. This is one of the few GLFW functions that may be called +before @ref glfwInit, which lets you be notified of errors during +initialization, so you should set it before you do anything else with GLFW. + +@code +glfwSetErrorCallback(error_callback); +@endcode + + @section quick_create_window Creating a window and context The window (and its context) is created with @ref glfwCreateWindow, which @@ -112,13 +163,13 @@ glfwMakeContextCurrent(window); @endcode -@section quick_window_attribs Retrieving window attributes +@section quick_window_params Retrieving window parameters -Each window provides a number of attributes that can be queried with @ref +Each window provides a number of parameters that can be queried with @ref glfwGetWindowParam. Some are related to the window itself and others to the OpenGL context. For example, to find out if the user is attempting to close the window, either by pressing the close widget in the title bar or using a key -combination like Alt+F4, check the @c GLFW_SHOULD_CLOSE attribute. +combination like Alt+F4, check the @c GLFW_SHOULD_CLOSE parameter. @code while (!glfwGetWindowParam(window, GLFW_SHOULD_CLOSE)) @@ -128,6 +179,35 @@ while (!glfwGetWindowParam(window, GLFW_SHOULD_CLOSE)) @endcode +@section quick_render Rendering with OpenGL + +Once you have a current OpenGL context, you can use OpenGL normally. In this +tutorial, a multi-colored rotating triangle will be rendered. The window size, +needed here by @c glViewport and @c glOrtho, is retrieved using @ref +glfwGetWindowSize. However, if you only need it for updating the viewport when +the window size changes, you can set a window size callback using @ref +glfwSetWindowSizeCallback and call @c glViewport from there. + +@code +void window_size_callback(GLFWwindow* window, int width, int height) +{ + glViewport(0, 0, width, height); +} +@endcode + + +@section quick_timer Reading the timer + +For the triangle to rotate properly, a time source is needed. GLFW provides +@ref glfwGetTime, which returns the number of seconds since @ref glfwInit as +a @c double. The time source used is the most accurate on each platform and +generally has micro- or nanosecond resolution. + +@code +double time = glfwGetTime(); +@endcode + + @section quick_swap_buffers Swapping buffers GLFW windows always use double-buffering. That means that you have two @@ -145,70 +225,40 @@ glfwSwapBuffers(window); @section quick_process_events Processing events -GLFW needs to communicate regularly with the window system in order to receive -events, like the ones controlling the attribute @c GLFW_SHOULD_CLOSE mentioned -above. Event processing must be done regularly and is normally done each frame -before rendering but after buffer swap. +GLFW needs to communicate regularly with the window system both in order to +receive events and to show that it hasn't locked up. Event processing must be +done regularly and is normally done each frame before rendering but after buffer +swap. -There are two ways to process events. @ref glfwPollEvents processes only those -events that have already been received and then returns immediately. This is -the best choice when rendering continually, like most games do. +There are two ways to process pending events. @ref glfwPollEvents processes +only those events that have already been received and then returns immediately. +This is the best choice when rendering continually, like most games do. @code glfwPollEvents(); @endcode If instead you only need to update your rendering once you have received new -input, @ref glfwWaitEvents is a better choice. It will wait until at least one -event has been received and then process all received events before returning. +input, @ref glfwWaitEvents is a better choice. It waits until at least one +event has been received, putting the thread to sleep in the meantime, and then +processes all received events just like @ref glfwPollEvents does. This saves +a great deal of CPU cycles and is useful for, for example, many kinds of editing +tools. @code glfwWaitEvents(); @endcode -@section quick_example Putting it together: A minimal GLFW application +@section quick_example Putting it together: A small GLFW application Now that you know how to initialize GLFW, create a window and poll for keyboard input, it's possible to create a simple program. -@code -#include -#include - -int main(void) -{ - GLFWwindow* window; - - if (!glfwInit()) - { - exit(EXIT_FAILURE); - } - - window = glfwCreateWindow(640, 480, "My Window", NULL, NULL); - if (!window) - { - glfwTerminate(); - exit(EXIT_FAILURE); - } - - glfwMakeContextCurrent(window); - - while (!glfwGetWindowParam(window, GLFW_SHOULD_CLOSE)) - { - glClear(GL_COLOR_BUFFER_BIT); - glfwSwapBuffers(window); - glfwPollEvents(); - } - - glfwDestroyWindow(window); - - glfwTerminate(); - exit(EXIT_SUCCESS); -} -@endcode +@snippet simple.c code This program creates a 640 by 480 pixels window and runs a loop clearing the -screen and processing events until the user closes the window. +screen, rendering a triangle and processing events until the user closes the +window. */ diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 42aede9e..68b7ec9b 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -27,27 +27,27 @@ if (APPLE) # Set fancy names for bundles add_executable(Boing MACOSX_BUNDLE boing.c) add_executable(Gears MACOSX_BUNDLE gears.c) + add_executable(Simple MACOSX_BUNDLE simple.c) add_executable("Split View" MACOSX_BUNDLE splitview.c) - add_executable(Triangle MACOSX_BUNDLE triangle.c) add_executable(Wave MACOSX_BUNDLE wave.c) set_target_properties(Boing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Boing") set_target_properties(Gears PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Gears") + set_target_properties(Simple PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Simple") set_target_properties("Split View" PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Split View") - set_target_properties(Triangle PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Triangle") set_target_properties(Wave PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Wave") else() # Set boring names for executables add_executable(boing WIN32 boing.c) add_executable(gears WIN32 gears.c) add_executable(heightmap WIN32 heightmap.c ${GETOPT}) + add_executable(simple WIN32 simple.c) add_executable(splitview WIN32 splitview.c) - add_executable(triangle WIN32 triangle.c) add_executable(wave WIN32 wave.c) endif() if (MSVC) - set(WINDOWS_BINARIES boing gears heightmap splitview triangle wave) + set(WINDOWS_BINARIES boing gears heightmap simple splitview wave) # Tell MSVC to use main instead of WinMain for Windows subsystem executables set_target_properties(${WINDOWS_BINARIES} PROPERTIES @@ -55,7 +55,7 @@ if (MSVC) endif() if (APPLE) - set(BUNDLE_BINARIES Boing Gears "Split View" Triangle Wave) + set(BUNDLE_BINARIES Boing Gears Simple "Split View" Wave) set_target_properties(${BUNDLE_BINARIES} PROPERTIES MACOSX_BUNDLE_SHORT_VERSION_STRING ${GLFW_VERSION} diff --git a/examples/simple.c b/examples/simple.c new file mode 100644 index 00000000..a8a105e0 --- /dev/null +++ b/examples/simple.c @@ -0,0 +1,93 @@ +//======================================================================== +// Simple GLFW example +// Copyright (c) Camilla Berglund +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== +//! [code] + +#include + +#include +#include + +static void error_callback(int error, const char* description) +{ + fputs(description, stderr); +} + +int main(void) +{ + GLFWwindow* window; + + glfwSetErrorCallback(error_callback); + + if (!glfwInit()) + exit(EXIT_FAILURE); + + window = glfwCreateWindow(640, 480, "Simple example", NULL, NULL); + if (!window) + { + glfwTerminate(); + exit(EXIT_FAILURE); + } + + glfwMakeContextCurrent(window); + + while (!glfwGetWindowParam(window, GLFW_SHOULD_CLOSE)) + { + float ratio; + int width, height; + + glfwGetWindowSize(window, &width, &height); + ratio = width / (float) height; + + glViewport(0, 0, width, height); + glClear(GL_COLOR_BUFFER_BIT); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(-ratio, ratio, -1.f, 1.f, 1.f, -1.f); + glMatrixMode(GL_MODELVIEW); + + glLoadIdentity(); + glRotatef(glfwGetTime() * 50.f, 0.f, 0.f, 1.f); + + glBegin(GL_TRIANGLES); + glColor3f(1.f, 0.f, 0.f); + glVertex3f(-0.6f, -0.4f, 0.f); + glColor3f(0.f, 1.f, 0.f); + glVertex3f(0.6f, -0.4f, 0.f); + glColor3f(0.f, 0.f, 1.f); + glVertex3f(0.f, 0.6f, 0.f); + glEnd(); + + glfwSwapBuffers(window); + glfwPollEvents(); + } + + glfwDestroyWindow(window); + + glfwTerminate(); + exit(EXIT_SUCCESS); +} + +//! [code] diff --git a/examples/triangle.c b/examples/triangle.c deleted file mode 100644 index 60042b6b..00000000 --- a/examples/triangle.c +++ /dev/null @@ -1,102 +0,0 @@ -//======================================================================== -// This is a small test application for GLFW. -// The program opens a window (640x480), and renders a spinning colored -// triangle (it is controlled with both the GLFW timer and the mouse). -//======================================================================== - -#include -#include - -#define GLFW_INCLUDE_GLU -#include - -static void error_callback(int error, const char* description) -{ - fprintf(stderr, "Error: %s\n", description); -} - -int main(void) -{ - int width, height, x; - GLFWwindow* window; - - glfwSetErrorCallback(error_callback); - - // Initialise GLFW - if (!glfwInit()) - exit(EXIT_FAILURE); - - // Open a window and create its OpenGL context - window = glfwCreateWindow(640, 480, "Spinning Triangle", NULL, NULL); - if (!window) - { - glfwTerminate(); - exit(EXIT_FAILURE); - } - - // Enable vertical sync (on cards that support it) - glfwMakeContextCurrent(window); - glfwSwapInterval(1); - - // Ensure we can capture the escape key being pressed below - glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE); - - for (;;) - { - double t = glfwGetTime(); - glfwGetCursorPos(window, &x, NULL); - - // Get window size (may be different than the requested size) - glfwGetWindowSize(window, &width, &height); - - // Special case: avoid division by zero below - height = height > 0 ? height : 1; - - glViewport(0, 0, width, height); - - // Clear color buffer to black - glClearColor(0.f, 0.f, 0.f, 0.f); - glClear(GL_COLOR_BUFFER_BIT); - - // Select and setup the projection matrix - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluPerspective(65.f, (GLfloat) width / (GLfloat) height, 1.f, 100.f); - - // Select and setup the modelview matrix - glMatrixMode( GL_MODELVIEW ); - glLoadIdentity(); - gluLookAt(0.f, 1.f, 0.f, // Eye-position - 0.f, 20.f, 0.f, // View-point - 0.f, 0.f, 1.f); // Up-vector - - // Draw a rotating colorful triangle - glTranslatef(0.f, 14.f, 0.f); - glRotatef(0.3f * (GLfloat) x + (GLfloat) t * 100.f, 0.f, 0.f, 1.f); - - glBegin(GL_TRIANGLES); - glColor3f(1.f, 0.f, 0.f); - glVertex3f(-5.f, 0.f, -4.f); - glColor3f(0.f, 1.f, 0.f); - glVertex3f(5.f, 0.f, -4.f); - glColor3f(0.f, 0.f, 1.f); - glVertex3f(0.f, 0.f, 6.f); - glEnd(); - - // Swap buffers - glfwSwapBuffers(window); - glfwPollEvents(); - - // Check if the ESC key was pressed or the window should be closed - if (glfwGetKey(window, GLFW_KEY_ESCAPE)) - break; - if (glfwGetWindowParam(window, GLFW_SHOULD_CLOSE)) - break; - } - - // Close OpenGL window and terminate GLFW - glfwTerminate(); - - exit(EXIT_SUCCESS); -} - diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h index 2364d5df..c04d99f7 100644 --- a/include/GL/glfw3.h +++ b/include/GL/glfw3.h @@ -592,10 +592,12 @@ typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int); /*! @brief The function signature for window close callbacks. * @param[in] window The window that the user attempted to close. - * @return @c GL_TRUE to allow the window to be closed, or @c GL_FALSE to - * ignore the attempt. + * @return One of @c GL_TRUE or @c GL_FALSE. * @ingroup window * + * The return value of the close callback becomes the new value of the @c + * GLFW_SHOULD_CLOSE window parameter. + * * @sa glfwSetWindowCloseCallback */ typedef int (* GLFWwindowclosefun)(GLFWwindow*); @@ -958,7 +960,7 @@ GLFWAPI void glfwDefaultWindowHints(void); * capabilities @em exactly for window and context creation to succeed. Hints * that are not hard constraints are matched as closely as possible, but the * resulting window and context may differ from what these hints requested. To - * find out the actual properties of the created window and context, use the + * find out the actual parameters of the created window and context, use the * @ref glfwGetWindowParam function. * * The following hints are hard constraints: @@ -1079,7 +1081,7 @@ GLFWAPI void glfwWindowHint(int target, int hint); * regular windows the initial cursor mode is @c GLFW_CURSOR_NORMAL and the * screensaver is allowed to start. * - * @remarks In order to determine the actual properties of an opened window, + * @remarks In order to determine the actual parameters of an opened window, * use @ref glfwGetWindowParam and @ref glfwGetWindowSize. * * @remarks Windows: If the executable has an icon resource named @c @@ -1262,48 +1264,48 @@ GLFWAPI void glfwHideWindow(GLFWwindow* window); */ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window); -/*! @brief Returns a property of the specified window. +/*! @brief Returns a parameter of the specified window. * @param[in] window The window to query. - * @param[in] param The property whose value to return. - * @return The value of the property, or zero if an error occurred. + * @param[in] param The parameter whose value to return. + * @return The value of the parameter, or zero if an error occurred. * @ingroup window * - * @par Window properties + * @par Window parameters * - * The @c GLFW_FOCUSED property indicates whether the window is focused. + * The @c GLFW_FOCUSED parameter indicates whether the window is focused. * - * The @c GLFW_ICONIFIED property indicates whether the window is iconified. + * The @c GLFW_ICONIFIED parameter indicates whether the window is iconified. * - * The @c GLFW_VISIBLE property indicates whether the window is visible. + * The @c GLFW_VISIBLE parameter indicates whether the window is visible. * - * The @c GLFW_RESIZABLE property indicates whether the window is resizable + * The @c GLFW_RESIZABLE parameter indicates whether the window is resizable * by the user. * - * The @c GLFW_SHOULD_CLOSE property indicates whether the window has been + * The @c GLFW_SHOULD_CLOSE parameter indicates whether the window has been * requested by the user to close. * - * @par Context properties + * @par Context parameters * - * The @c GLFW_CLIENT_API property indicates the client API provided by the + * The @c GLFW_CLIENT_API parameter indicates the client API provided by the * window's context; either @c GLFW_OPENGL_API or @c GLFW_OPENGL_ES_API. * * The @c GLFW_CONTEXT_VERSION_MAJOR, @c GLFW_CONTEXT_VERSION_MINOR and @c - * GLFW_CONTEXT_REVISION properties indicate the client API version of the + * GLFW_CONTEXT_REVISION parameters indicate the client API version of the * window's context. * - * The @c GLFW_OPENGL_FORWARD_COMPAT property is @c GL_TRUE if the window's + * The @c GLFW_OPENGL_FORWARD_COMPAT parameter is @c GL_TRUE if the window's * context is an OpenGL forward-compatible one, or @c GL_FALSE otherwise. * - * The @c GLFW_OPENGL_DEBUG_CONTEXT property is @c GL_TRUE if the window's + * The @c GLFW_OPENGL_DEBUG_CONTEXT parameter is @c GL_TRUE if the window's * context is an OpenGL debug context, or @c GL_FALSE otherwise. * - * The @c GLFW_OPENGL_PROFILE property indicates the OpenGL profile used by the + * The @c GLFW_OPENGL_PROFILE parameter indicates the OpenGL profile used by the * context. This is @c GLFW_OPENGL_CORE_PROFILE or @c * GLFW_OPENGL_COMPAT_PROFILE if the context uses a known profile, or @c * GLFW_OPENGL_NO_PROFILE if the OpenGL profile is unknown or the context is * for another client API. * - * The @c GLFW_CONTEXT_ROBUSTNESS property indicates the robustness strategy + * The @c GLFW_CONTEXT_ROBUSTNESS parameter indicates the robustness strategy * used by the context. This is @c GLFW_LOSE_CONTEXT_ON_RESET or @c * GLFW_NO_RESET_NOTIFICATION if the window's context supports robustness, or * @c GLFW_NO_ROBUSTNESS otherwise. @@ -1356,7 +1358,8 @@ GLFWAPI void glfwSetWindowSizeCallback(GLFWwindow* window, GLFWwindowsizefun cbf * cause this callback to be called. * * The return value of the close callback becomes the new value of the @c - * GLFW_SHOULD_CLOSE window parameter. + * GLFW_SHOULD_CLOSE window parameter, which you can query with @ref + * glfwGetWindowParam. * * @remarks Mac OS X: Selecting Quit from the application menu will * trigger the close callback for all windows. @@ -1558,9 +1561,9 @@ GLFWAPI void glfwSetCursorEnterCallback(GLFWwindow* window, GLFWcursorenterfun c */ GLFWAPI void glfwSetScrollCallback(GLFWwindow* window, GLFWscrollfun cbfun); -/*! @brief Returns a property of the specified joystick. +/*! @brief Returns a parameter of the specified joystick. * @param[in] joy The joystick to query. - * @param[in] param The property whose value to return. + * @param[in] param The parameter whose value to return. * @return The specified joystick's current value, or zero if the joystick is * not present. * @ingroup input