diff options
Diffstat (limited to 'ext/glfw/docs/quick.md')
-rw-r--r-- | ext/glfw/docs/quick.md | 365 |
1 files changed, 365 insertions, 0 deletions
diff --git a/ext/glfw/docs/quick.md b/ext/glfw/docs/quick.md new file mode 100644 index 0000000..6f487fc --- /dev/null +++ b/ext/glfw/docs/quick.md @@ -0,0 +1,365 @@ +# Getting started {#quick_guide} + +[TOC] + +This guide takes you through writing a small application using GLFW 3. The +application will create a window and OpenGL context, render a rotating triangle +and exit when the user closes the window or presses _Escape_. This guide will +introduce a few of the most commonly used functions, but there are many more. + +This guide assumes no experience with earlier versions of GLFW. If you +have used GLFW 2 in the past, read @ref moving_guide, as some functions +behave differently in GLFW 3. + + +## Step by step {#quick_steps} + +### Including the GLFW header {#quick_include} + +In the source files of your application where you use GLFW, you need to include +its header file. + +```c +#include <GLFW/glfw3.h> +``` + +This header provides all the constants, types and function prototypes of the +GLFW API. + +By default it also includes the OpenGL header from your development environment. +On some platforms this header only supports older versions of OpenGL. The most +extreme case is Windows, where it typically only supports OpenGL 1.2. + +Most programs will instead use an +[extension loader library](@ref context_glext_auto) and include its header. +This example uses files generated by [glad](https://gen.glad.sh/). The GLFW +header can detect most such headers if they are included first and will then not +include the one from your development environment. + +```c +#include <glad/gl.h> +#include <GLFW/glfw3.h> +``` + +To make sure there will be no header conflicts, you can define @ref +GLFW_INCLUDE_NONE before the GLFW header to explicitly disable inclusion of the +development environment header. This also allows the two headers to be included +in any order. + +```c +#define GLFW_INCLUDE_NONE +#include <GLFW/glfw3.h> +#include <glad/gl.h> +``` + + +### Initializing and terminating GLFW {#quick_init_term} + +Before you can use most GLFW functions, the library must be initialized. On +successful initialization, `GLFW_TRUE` is returned. If an error occurred, +`GLFW_FALSE` is returned. + +```c +if (!glfwInit()) +{ + // Initialization failed +} +``` + +Note that `GLFW_TRUE` and `GLFW_FALSE` are and will always be one and zero. + +When you are done using GLFW, typically just before the application exits, you +need to terminate GLFW. + +```c +glfwTerminate(); +``` + +This destroys any remaining windows and releases any other resources allocated by +GLFW. After this call, you must initialize GLFW again before using any GLFW +functions that require it. + + +### Setting an error callback {#quick_capture_error} + +Most events are reported through callbacks, whether it's a key being pressed, +a GLFW window being moved, or an error occurring. Callbacks are C functions (or +C++ static methods) that are called by GLFW with arguments describing the event. + +In case a GLFW function fails, an error is reported to the GLFW error callback. +You can receive these reports with an error callback. This function must have +the signature below but may do anything permitted in other callbacks. + +```c +void error_callback(int error, const char* description) +{ + fprintf(stderr, "Error: %s\n", description); +} +``` + +Callback functions must be set, so GLFW knows to call them. The function to set +the error callback is one of the few GLFW functions that may be called before +initialization, which lets you be notified of errors both during and after +initialization. + +```c +glfwSetErrorCallback(error_callback); +``` + + +### Creating a window and context {#quick_create_window} + +The window and its OpenGL context are created with a single call to @ref +glfwCreateWindow, which returns a handle to the created combined window and +context object + +```c +GLFWwindow* window = glfwCreateWindow(640, 480, "My Title", NULL, NULL); +if (!window) +{ + // Window or OpenGL context creation failed +} +``` + +This creates a 640 by 480 windowed mode window with an OpenGL context. If +window or OpenGL context creation fails, `NULL` will be returned. You should +always check the return value. While window creation rarely fails, context +creation depends on properly installed drivers and may fail even on machines +with the necessary hardware. + +By default, the OpenGL context GLFW creates may have any version. You can +require a minimum OpenGL version by setting the `GLFW_CONTEXT_VERSION_MAJOR` and +`GLFW_CONTEXT_VERSION_MINOR` hints _before_ creation. If the required minimum +version is not supported on the machine, context (and window) creation fails. + +You can select the OpenGL profile by setting the `GLFW_OPENGL_PROFILE` hint. +This program uses the core profile as that is the only profile macOS supports +for OpenGL 3.x and 4.x. + +```c +glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); +glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); +glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); +GLFWwindow* window = glfwCreateWindow(640, 480, "My Title", NULL, NULL); +if (!window) +{ + // Window or context creation failed +} +``` + +When a window and context is no longer needed, destroy it. + +```c +glfwDestroyWindow(window); +``` + +Once this function is called, no more events will be delivered for that window +and its handle becomes invalid. + + +### Making the OpenGL context current {#quick_context_current} + +Before you can use the OpenGL API, you must have a current OpenGL context. + +```c +glfwMakeContextCurrent(window); +``` + +The context will remain current until you make another context current or until +the window owning the current context is destroyed. + +If you are using an [extension loader library](@ref context_glext_auto) to +access modern OpenGL then this is when to initialize it, as the loader needs +a current context to load from. This example uses +[glad](https://github.com/Dav1dde/glad), but the same rule applies to all such +libraries. + +```c +gladLoadGL(glfwGetProcAddress); +``` + + +### Checking the window close flag {#quick_window_close} + +Each window has a flag indicating whether the window should be closed. + +When the user attempts to close the window, either by pressing the close widget +in the title bar or using a key combination like Alt+F4, this flag is set to 1. +Note that __the window isn't actually closed__, so you are expected to monitor +this flag and either destroy the window or give some kind of feedback to the +user. + +```c +while (!glfwWindowShouldClose(window)) +{ + // Keep running +} +``` + +You can be notified when the user is attempting to close the window by setting +a close callback with @ref glfwSetWindowCloseCallback. The callback will be +called immediately after the close flag has been set. + +You can also set it yourself with @ref glfwSetWindowShouldClose. This can be +useful if you want to interpret other kinds of input as closing the window, like +for example pressing the _Escape_ key. + + +### Receiving input events {#quick_key_input} + +Each window has a large number of callbacks that can be set to receive all the +various kinds of events. To receive key press and release events, create a key +callback function. + +```c +static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) +{ + if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) + glfwSetWindowShouldClose(window, GLFW_TRUE); +} +``` + +The key callback, like other window related callbacks, are set per-window. + +```c +glfwSetKeyCallback(window, key_callback); +``` + +In order for event callbacks to be called when events occur, you need to process +events as described below. + + +### Rendering with OpenGL {#quick_render} + +Once you have a current OpenGL context, you can use OpenGL normally. In this +tutorial, a multicolored rotating triangle will be rendered. The framebuffer +size needs to be retrieved for `glViewport`. + +```c +int width, height; +glfwGetFramebufferSize(window, &width, &height); +glViewport(0, 0, width, height); +``` + +You can also set a framebuffer size callback using @ref +glfwSetFramebufferSizeCallback and be notified when the size changes. + +The details of how to render with OpenGL is outside the scope of this tutorial, +but there are many excellent resources for learning modern OpenGL. Here are +a few of them: + + - [Anton's OpenGL 4 Tutorials](https://antongerdelan.net/opengl/) + - [Learn OpenGL](https://learnopengl.com/) + - [Open.GL](https://open.gl/) + +These all happen to use GLFW, but OpenGL itself works the same whatever API you +use to create the window and context. + + +### Reading the timer {#quick_timer} + +To create smooth animation, a time source is needed. GLFW provides a timer that +returns the number of seconds since initialization. The time source used is the +most accurate on each platform and generally has micro- or nanosecond +resolution. + +```c +double time = glfwGetTime(); +``` + + +### Swapping buffers {#quick_swap_buffers} + +GLFW windows by default use double buffering. That means that each window has +two rendering buffers; a front buffer and a back buffer. The front buffer is +the one being displayed and the back buffer the one you render to. + +When the entire frame has been rendered, the buffers need to be swapped with one +another, so the back buffer becomes the front buffer and vice versa. + +```c +glfwSwapBuffers(window); +``` + +The swap interval indicates how many frames to wait until swapping the buffers, +commonly known as _vsync_. By default, the swap interval is zero, meaning +buffer swapping will occur immediately. On fast machines, many of those frames +will never be seen, as the screen is still only updated typically 60-75 times +per second, so this wastes a lot of CPU and GPU cycles. + +Also, because the buffers will be swapped in the middle the screen update, +leading to [screen tearing](https://en.wikipedia.org/wiki/Screen_tearing). + +For these reasons, applications will typically want to set the swap interval to +one. It can be set to higher values, but this is usually not recommended, +because of the input latency it leads to. + +```c +glfwSwapInterval(1); +``` + +This function acts on the current context and will fail unless a context is +current. + + +### Processing events {#quick_process_events} + +GLFW needs to communicate regularly with the window system both in order to +receive events and to show that the application hasn't locked up. Event +processing must be done regularly while you have visible windows and is normally +done each frame after buffer swapping. + +There are two methods for processing pending events; polling and waiting. This +example will use event polling, which processes only those events that have +already been received and then returns immediately. + +```c +glfwPollEvents(); +``` + +This is the best choice when rendering continually, like most games do. If +instead you only need to update your rendering once you have received new 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. This saves a great deal of CPU cycles and is useful for, +for example, many kinds of editing tools. + + +## Putting it together {#quick_example} + +Now that you know how to initialize GLFW, create a window and poll for +keyboard input, it's possible to create a small program. + +This program creates a 640 by 480 windowed mode window and starts a loop that +clears the screen, renders a triangle and processes events until the user either +presses _Escape_ or closes the window. + +@snippet triangle-opengl.c code + +The program above can be found in the [source package][download] as +`examples/triangle-opengl.c` and is compiled along with all other examples when +you build GLFW. If you built GLFW from the source package then you already have +this as `triangle-opengl.exe` on Windows, `triangle-opengl` on Linux or +`triangle-opengl.app` on macOS. + +[download]: https://www.glfw.org/download.html + +This tutorial used only a few of the many functions GLFW provides. There are +guides for each of the areas covered by GLFW. Each guide will introduce all the +functions for that category. + + - @ref intro_guide + - @ref window_guide + - @ref context_guide + - @ref monitor_guide + - @ref input_guide + +You can access reference documentation for any GLFW function by clicking it and +the reference for each function links to related functions and guide sections. + +The tutorial ends here. Once you have written a program that uses GLFW, you +will need to compile and link it. How to do that depends on the development +environment you are using and is best explained by the documentation for that +environment. To learn about the details that are specific to GLFW, see +@ref build_guide. + |