Platformer in OpenGL
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

194 lines
34 KiB

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.11"/>
<title>GLFW: Getting started</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<script type="text/javascript">
$(document).ready(function() { init_search(); });
</script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
<link href="extra.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<div class="glfwheader">
<a href="http://www.glfw.org/" id="glfwhome">GLFW</a>
<ul class="glfwnavbar">
<li><a href="http://www.glfw.org/documentation.html">Documentation</a></li>
<li><a href="http://www.glfw.org/download.html">Download</a></li>
<li><a href="http://www.glfw.org/media.html">Media</a></li>
<li><a href="http://www.glfw.org/community.html">Community</a></li>
</ul>
</div>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.11 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search",false,'Search');
</script>
<div id="navrow1" class="tabs">
<ul class="tablist">
<li><a href="index.html"><span>Main&#160;Page</span></a></li>
<li class="current"><a href="pages.html"><span>Related&#160;Pages</span></a></li>
<li><a href="modules.html"><span>Modules</span></a></li>
<li><a href="annotated.html"><span>Data&#160;Structures</span></a></li>
<li><a href="files.html"><span>Files</span></a></li>
<li>
<div id="MSearchBox" class="MSearchBoxInactive">
<span class="left">
<img id="MSearchSelect" src="search/mag_sel.png"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
alt=""/>
<input type="text" id="MSearchField" value="Search" accesskey="S"
onfocus="searchBox.OnSearchFieldFocus(true)"
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
</span><span class="right">
<a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
</span>
</div>
</li>
</ul>
</div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0"
name="MSearchResults" id="MSearchResults">
</iframe>
</div>
</div><!-- top -->
<div class="header">
<div class="headertitle">
<div class="title">Getting started </div> </div>
</div><!--header-->
<div class="contents">
<div class="toc"><h3>Table of Contents</h3>
<ul><li class="level1"><a href="#quick_steps">Step by step</a><ul><li class="level2"><a href="#quick_include">Including the GLFW header</a></li>
<li class="level2"><a href="#quick_init_term">Initializing and terminating GLFW</a></li>
<li class="level2"><a href="#quick_capture_error">Setting an error callback</a></li>
<li class="level2"><a href="#quick_create_window">Creating a window and context</a></li>
<li class="level2"><a href="#quick_context_current">Making the OpenGL context current</a></li>
<li class="level2"><a href="#quick_window_close">Checking the window close flag</a></li>
<li class="level2"><a href="#quick_key_input">Receiving input events</a></li>
<li class="level2"><a href="#quick_render">Rendering with OpenGL</a></li>
<li class="level2"><a href="#quick_timer">Reading the timer</a></li>
<li class="level2"><a href="#quick_swap_buffers">Swapping buffers</a></li>
<li class="level2"><a href="#quick_process_events">Processing events</a></li>
</ul>
</li>
<li class="level1"><a href="#quick_example">Putting it together</a></li>
</ul>
</div>
<div class="textblock"><p>This guide takes you through writing a simple 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 <em>Escape</em>. This guide will introduce a few of the most commonly used functions, but there are many more.</p>
<p>This guide assumes no experience with earlier versions of GLFW. If you have used GLFW 2 in the past, read <a class="el" href="moving_guide.html">Moving from GLFW 2 to 3</a>, as some functions behave differently in GLFW 3.</p>
<h1><a class="anchor" id="quick_steps"></a>
Step by step</h1>
<h2><a class="anchor" id="quick_include"></a>
Including the GLFW header</h2>
<p>In the source files of your application where you use OpenGL or GLFW, you need to include the GLFW 3 header file.</p>
<div class="fragment"><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="glfw3_8h.html">GLFW/glfw3.h</a>&gt;</span></div></div><!-- fragment --><p>This defines all the constants, types and function prototypes of the GLFW API. It also includes the OpenGL header from your development environment and defines all the constants and types necessary for it to work on your platform without including any platform-specific headers.</p>
<p>In other words:</p>
<ul>
<li>Do <em>not</em> include the OpenGL header yourself, as GLFW does this for you in a platform-independent way</li>
<li>Do <em>not</em> include <code>windows.h</code> or other platform-specific headers unless you plan on using those APIs yourself</li>
<li>If you <em>do</em> need to include such headers, include them <em>before</em> the GLFW header and it will detect this</li>
</ul>
<p>On some platforms supported by GLFW the OpenGL header and link library only expose older versions of OpenGL. The most extreme case is Windows, which only exposes OpenGL 1.2. The easiest way to work around this is to use an <a class="el" href="context_guide.html#context_glext_auto">extension loader library</a>.</p>
<p>If you are using such a library then you should include its header <em>before</em> the GLFW header. This lets it replace the OpenGL header included by GLFW without conflicts. This example uses <a href="https://github.com/Dav1dde/glad">glad</a>, but the same rule applies to all such libraries.</p>
<div class="fragment"><div class="line"><span class="preprocessor">#include &lt;glad/glad.h&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="glfw3_8h.html">GLFW/glfw3.h</a>&gt;</span></div></div><!-- fragment --><h2><a class="anchor" id="quick_init_term"></a>
Initializing and terminating GLFW</h2>
<p>Before you can use most GLFW functions, the library must be initialized. On successful initialization, <code>GLFW_TRUE</code> is returned. If an error occurred, <code>GLFW_FALSE</code> is returned.</p>
<div class="fragment"><div class="line"><span class="keywordflow">if</span> (!<a class="code" href="group__init.html#ga317aac130a235ab08c6db0834907d85e">glfwInit</a>())</div><div class="line">{</div><div class="line"> <span class="comment">// Initialization failed</span></div><div class="line">}</div></div><!-- fragment --><p>Note that <code>GLFW_TRUE</code> and <code>GLFW_FALSE</code> are and will always be just one and zero.</p>
<p>When you are done using GLFW, typically just before the application exits, you need to terminate GLFW.</p>
<div class="fragment"><div class="line"><a class="code" href="group__init.html#gaaae48c0a18607ea4a4ba951d939f0901">glfwTerminate</a>();</div></div><!-- fragment --><p>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.</p>
<h2><a class="anchor" id="quick_capture_error"></a>
Setting an error callback</h2>
<p>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.</p>
<p>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. This simple error callback just prints the error description to <code>stderr</code>.</p>
<div class="fragment"><div class="line"><span class="keywordtype">void</span> error_callback(<span class="keywordtype">int</span> error, <span class="keyword">const</span> <span class="keywordtype">char</span>* description)</div><div class="line">{</div><div class="line"> fprintf(stderr, <span class="stringliteral">&quot;Error: %s\n&quot;</span>, description);</div><div class="line">}</div></div><!-- fragment --><p>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.</p>
<div class="fragment"><div class="line"><a class="code" href="group__init.html#gaa5d796c3cf7c1a7f02f845486333fb5f">glfwSetErrorCallback</a>(error_callback);</div></div><!-- fragment --><h2><a class="anchor" id="quick_create_window"></a>
Creating a window and context</h2>
<p>The window and its OpenGL context are created with a single call to <a class="el" href="group__window.html#ga5c336fddf2cbb5b92f65f10fb6043344">glfwCreateWindow</a>, which returns a handle to the created combined window and context object</p>
<div class="fragment"><div class="line"><a class="code" href="group__window.html#ga3c96d80d363e67d13a41b5d1821f3242">GLFWwindow</a>* window = <a class="code" href="group__window.html#ga5c336fddf2cbb5b92f65f10fb6043344">glfwCreateWindow</a>(640, 480, <span class="stringliteral">&quot;My Title&quot;</span>, NULL, NULL);</div><div class="line"><span class="keywordflow">if</span> (!window)</div><div class="line">{</div><div class="line"> <span class="comment">// Window or OpenGL context creation failed</span></div><div class="line">}</div></div><!-- fragment --><p>This creates a 640 by 480 windowed mode window with an OpenGL context. If window or OpenGL context creation fails, <code>NULL</code> 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.</p>
<p>By default, the OpenGL context GLFW creates may have any version. You can require a minimum OpenGL version by setting the <code>GLFW_CONTEXT_VERSION_MAJOR</code> and <code>GLFW_CONTEXT_VERSION_MINOR</code> hints <em>before</em> creation. If the required minimum version is not supported on the machine, context (and window) creation fails.</p>
<div class="fragment"><div class="line"><a class="code" href="group__window.html#ga7d9c8c62384b1e2821c4dc48952d2033">glfwWindowHint</a>(<a class="code" href="glfw3_8h.html#afe5e4922de1f9932d7e9849bb053b0c0">GLFW_CONTEXT_VERSION_MAJOR</a>, 2);</div><div class="line"><a class="code" href="group__window.html#ga7d9c8c62384b1e2821c4dc48952d2033">glfwWindowHint</a>(<a class="code" href="glfw3_8h.html#a31aca791e4b538c4e4a771eb95cc2d07">GLFW_CONTEXT_VERSION_MINOR</a>, 0);</div><div class="line"><a class="code" href="group__window.html#ga3c96d80d363e67d13a41b5d1821f3242">GLFWwindow</a>* window = <a class="code" href="group__window.html#ga5c336fddf2cbb5b92f65f10fb6043344">glfwCreateWindow</a>(640, 480, <span class="stringliteral">&quot;My Title&quot;</span>, NULL, NULL);</div><div class="line"><span class="keywordflow">if</span> (!window)</div><div class="line">{</div><div class="line"> <span class="comment">// Window or context creation failed</span></div><div class="line">}</div></div><!-- fragment --><p>The window handle is passed to all window related functions and is provided to along to all window related callbacks, so they can tell which window received the event.</p>
<p>When a window and context is no longer needed, destroy it.</p>
<div class="fragment"><div class="line"><a class="code" href="group__window.html#gacdf43e51376051d2c091662e9fe3d7b2">glfwDestroyWindow</a>(window);</div></div><!-- fragment --><p>Once this function is called, no more events will be delivered for that window and its handle becomes invalid.</p>
<h2><a class="anchor" id="quick_context_current"></a>
Making the OpenGL context current</h2>
<p>Before you can use the OpenGL API, you must have a current OpenGL context.</p>
<div class="fragment"><div class="line"><a class="code" href="group__context.html#ga1c04dc242268f827290fe40aa1c91157">glfwMakeContextCurrent</a>(window);</div></div><!-- fragment --><p>The context will remain current until you make another context current or until the window owning the current context is destroyed.</p>
<p>If you are using an <a class="el" href="context_guide.html#context_glext_auto">extension loader library</a> to access modern OpenGL then this is when to initialize it, as the loader needs a current context to load from. This example uses <a href="https://github.com/Dav1dde/glad">glad</a>, but the same rule applies to all such libraries.</p>
<div class="fragment"><div class="line">gladLoadGLLoader((GLADloadproc) <a class="code" href="group__context.html#ga35f1837e6f666781842483937612f163">glfwGetProcAddress</a>);</div></div><!-- fragment --><h2><a class="anchor" id="quick_window_close"></a>
Checking the window close flag</h2>
<p>Each window has a flag indicating whether the window should be closed.</p>
<p>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 <b>the window isn't actually closed</b>, so you are expected to monitor this flag and either destroy the window or give some kind of feedback to the user.</p>
<div class="fragment"><div class="line"><span class="keywordflow">while</span> (!<a class="code" href="group__window.html#ga24e02fbfefbb81fc45320989f8140ab5">glfwWindowShouldClose</a>(window))</div><div class="line">{</div><div class="line"> <span class="comment">// Keep running</span></div><div class="line">}</div></div><!-- fragment --><p>You can be notified when the user is attempting to close the window by setting a close callback with <a class="el" href="group__window.html#gaade9264e79fae52bdb78e2df11ee8d6a">glfwSetWindowCloseCallback</a>. The callback will be called immediately after the close flag has been set.</p>
<p>You can also set it yourself with <a class="el" href="group__window.html#ga49c449dde2a6f87d996f4daaa09d6708">glfwSetWindowShouldClose</a>. This can be useful if you want to interpret other kinds of input as closing the window, like for example pressing the <em>Escape</em> key.</p>
<h2><a class="anchor" id="quick_key_input"></a>
Receiving input events</h2>
<p>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.</p>
<div class="fragment"><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> key_callback(<a class="code" href="group__window.html#ga3c96d80d363e67d13a41b5d1821f3242">GLFWwindow</a>* window, <span class="keywordtype">int</span> key, <span class="keywordtype">int</span> scancode, <span class="keywordtype">int</span> action, <span class="keywordtype">int</span> mods)</div><div class="line">{</div><div class="line"> <span class="keywordflow">if</span> (key == <a class="code" href="group__keys.html#gaac6596c350b635c245113b81c2123b93">GLFW_KEY_ESCAPE</a> &amp;&amp; action == <a class="code" href="group__input.html#ga2485743d0b59df3791c45951c4195265">GLFW_PRESS</a>)</div><div class="line"> <a class="code" href="group__window.html#ga49c449dde2a6f87d996f4daaa09d6708">glfwSetWindowShouldClose</a>(window, <a class="code" href="glfw3_8h.html#a2744fbb29b5631bb28802dbe0cf36eba">GLFW_TRUE</a>);</div><div class="line">}</div></div><!-- fragment --><p>The key callback, like other window related callbacks, are set per-window.</p>
<div class="fragment"><div class="line"><a class="code" href="group__input.html#ga7e496507126f35ea72f01b2e6ef6d155">glfwSetKeyCallback</a>(window, key_callback);</div></div><!-- fragment --><p>In order for event callbacks to be called when events occur, you need to process events as described below.</p>
<h2><a class="anchor" id="quick_render"></a>
Rendering with OpenGL</h2>
<p>Once you have a current OpenGL context, you can use OpenGL normally. In this tutorial, a multi-colored rotating triangle will be rendered. The framebuffer size needs to be retrieved for <code>glViewport</code>.</p>
<div class="fragment"><div class="line"><span class="keywordtype">int</span> width, height;</div><div class="line"><a class="code" href="group__window.html#ga0e2637a4161afb283f5300c7f94785c9">glfwGetFramebufferSize</a>(window, &amp;width, &amp;height);</div><div class="line">glViewport(0, 0, width, height);</div></div><!-- fragment --><p>You can also set a framebuffer size callback using <a class="el" href="group__window.html#ga3203461a5303bf289f2e05f854b2f7cf">glfwSetFramebufferSizeCallback</a> and be notified when the size changes.</p>
<p>Actual rendering with OpenGL is outside the scope of this tutorial, but there are <a href="https://open.gl/">many</a> <a href="http://learnopengl.com/">excellent</a> <a href="http://openglbook.com/">tutorial</a> <a href="http://ogldev.atspace.co.uk/">sites</a> that teach modern OpenGL. Some of them use GLFW to create the context and window while others use GLUT or SDL, but remember that OpenGL itself always works the same.</p>
<h2><a class="anchor" id="quick_timer"></a>
Reading the timer</h2>
<p>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.</p>
<div class="fragment"><div class="line"><span class="keywordtype">double</span> time = <a class="code" href="group__input.html#gaa6cf4e7a77158a3b8fd00328b1720a4a">glfwGetTime</a>();</div></div><!-- fragment --><h2><a class="anchor" id="quick_swap_buffers"></a>
Swapping buffers</h2>
<p>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.</p>
<p>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.</p>
<div class="fragment"><div class="line"><a class="code" href="group__window.html#ga15a5a1ee5b3c2ca6b15ca209a12efd14">glfwSwapBuffers</a>(window);</div></div><!-- fragment --><p>The swap interval indicates how many frames to wait until swapping the buffers, commonly known as <em>vsync</em>. 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.</p>
<p>Also, because the buffers will be swapped in the middle the screen update, leading to <a href="https://en.wikipedia.org/wiki/Screen_tearing">screen tearing</a>.</p>
<p>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.</p>
<div class="fragment"><div class="line"><a class="code" href="group__context.html#ga6d4e0cdf151b5e579bd67f13202994ed">glfwSwapInterval</a>(1);</div></div><!-- fragment --><p>This function acts on the current context and will fail unless a context is current.</p>
<h2><a class="anchor" id="quick_process_events"></a>
Processing events</h2>
<p>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.</p>
<p>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.</p>
<div class="fragment"><div class="line"><a class="code" href="group__window.html#ga37bd57223967b4211d60ca1a0bf3c832">glfwPollEvents</a>();</div></div><!-- fragment --><p>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, <a class="el" href="group__window.html#ga554e37d781f0a997656c26b2c56c835e">glfwWaitEvents</a> 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.</p>
<h1><a class="anchor" id="quick_example"></a>
Putting it together</h1>
<p>Now that you know how to initialize GLFW, create a window and poll for keyboard input, it's possible to create a simple program.</p>
<p>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 <em>Escape</em> or closes the window.</p>
<div class="fragment"><div class="line"></div><div class="line"><span class="preprocessor">#include &lt;glad/glad.h&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="glfw3_8h.html">GLFW/glfw3.h</a>&gt;</span></div><div class="line"></div><div class="line"><span class="preprocessor">#include &quot;linmath.h&quot;</span></div><div class="line"></div><div class="line"><span class="preprocessor">#include &lt;stdlib.h&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;stdio.h&gt;</span></div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keyword">const</span> <span class="keyword">struct</span></div><div class="line">{</div><div class="line"> <span class="keywordtype">float</span> x, y;</div><div class="line"> <span class="keywordtype">float</span> r, g, b;</div><div class="line">} vertices[3] =</div><div class="line">{</div><div class="line"> { -0.6f, -0.4f, 1.f, 0.f, 0.f },</div><div class="line"> { 0.6f, -0.4f, 0.f, 1.f, 0.f },</div><div class="line"> { 0.f, 0.6f, 0.f, 0.f, 1.f }</div><div class="line">};</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">char</span>* vertex_shader_text =</div><div class="line"><span class="stringliteral">&quot;uniform mat4 MVP;\n&quot;</span></div><div class="line"><span class="stringliteral">&quot;attribute vec3 vCol;\n&quot;</span></div><div class="line"><span class="stringliteral">&quot;attribute vec2 vPos;\n&quot;</span></div><div class="line"><span class="stringliteral">&quot;varying vec3 color;\n&quot;</span></div><div class="line"><span class="stringliteral">&quot;void main()\n&quot;</span></div><div class="line"><span class="stringliteral">&quot;{\n&quot;</span></div><div class="line"><span class="stringliteral">&quot; gl_Position = MVP * vec4(vPos, 0.0, 1.0);\n&quot;</span></div><div class="line"><span class="stringliteral">&quot; color = vCol;\n&quot;</span></div><div class="line"><span class="stringliteral">&quot;}\n&quot;</span>;</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">char</span>* fragment_shader_text =</div><div class="line"><span class="stringliteral">&quot;varying vec3 color;\n&quot;</span></div><div class="line"><span class="stringliteral">&quot;void main()\n&quot;</span></div><div class="line"><span class="stringliteral">&quot;{\n&quot;</span></div><div class="line"><span class="stringliteral">&quot; gl_FragColor = vec4(color, 1.0);\n&quot;</span></div><div class="line"><span class="stringliteral">&quot;}\n&quot;</span>;</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> error_callback(<span class="keywordtype">int</span> error, <span class="keyword">const</span> <span class="keywordtype">char</span>* description)</div><div class="line">{</div><div class="line"> fprintf(stderr, <span class="stringliteral">&quot;Error: %s\n&quot;</span>, description);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> key_callback(<a class="code" href="group__window.html#ga3c96d80d363e67d13a41b5d1821f3242">GLFWwindow</a>* window, <span class="keywordtype">int</span> key, <span class="keywordtype">int</span> scancode, <span class="keywordtype">int</span> action, <span class="keywordtype">int</span> mods)</div><div class="line">{</div><div class="line"> <span class="keywordflow">if</span> (key == <a class="code" href="group__keys.html#gaac6596c350b635c245113b81c2123b93">GLFW_KEY_ESCAPE</a> &amp;&amp; action == <a class="code" href="group__input.html#ga2485743d0b59df3791c45951c4195265">GLFW_PRESS</a>)</div><div class="line"> <a class="code" href="group__window.html#ga49c449dde2a6f87d996f4daaa09d6708">glfwSetWindowShouldClose</a>(window, <a class="code" href="glfw3_8h.html#a2744fbb29b5631bb28802dbe0cf36eba">GLFW_TRUE</a>);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">int</span> main(<span class="keywordtype">void</span>)</div><div class="line">{</div><div class="line"> <a class="code" href="group__window.html#ga3c96d80d363e67d13a41b5d1821f3242">GLFWwindow</a>* window;</div><div class="line"> GLuint vertex_buffer, vertex_shader, fragment_shader, program;</div><div class="line"> GLint mvp_location, vpos_location, vcol_location;</div><div class="line"></div><div class="line"> <a class="code" href="group__init.html#gaa5d796c3cf7c1a7f02f845486333fb5f">glfwSetErrorCallback</a>(error_callback);</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (!<a class="code" href="group__init.html#ga317aac130a235ab08c6db0834907d85e">glfwInit</a>())</div><div class="line"> exit(EXIT_FAILURE);</div><div class="line"></div><div class="line"> <a class="code" href="group__window.html#ga7d9c8c62384b1e2821c4dc48952d2033">glfwWindowHint</a>(<a class="code" href="glfw3_8h.html#afe5e4922de1f9932d7e9849bb053b0c0">GLFW_CONTEXT_VERSION_MAJOR</a>, 2);</div><div class="line"> <a class="code" href="group__window.html#ga7d9c8c62384b1e2821c4dc48952d2033">glfwWindowHint</a>(<a class="code" href="glfw3_8h.html#a31aca791e4b538c4e4a771eb95cc2d07">GLFW_CONTEXT_VERSION_MINOR</a>, 0);</div><div class="line"></div><div class="line"> window = <a class="code" href="group__window.html#ga5c336fddf2cbb5b92f65f10fb6043344">glfwCreateWindow</a>(640, 480, <span class="stringliteral">&quot;Simple example&quot;</span>, NULL, NULL);</div><div class="line"> <span class="keywordflow">if</span> (!window)</div><div class="line"> {</div><div class="line"> <a class="code" href="group__init.html#gaaae48c0a18607ea4a4ba951d939f0901">glfwTerminate</a>();</div><div class="line"> exit(EXIT_FAILURE);</div><div class="line"> }</div><div class="line"></div><div class="line"> <a class="code" href="group__input.html#ga7e496507126f35ea72f01b2e6ef6d155">glfwSetKeyCallback</a>(window, key_callback);</div><div class="line"></div><div class="line"> <a class="code" href="group__context.html#ga1c04dc242268f827290fe40aa1c91157">glfwMakeContextCurrent</a>(window);</div><div class="line"> gladLoadGLLoader((GLADloadproc) <a class="code" href="group__context.html#ga35f1837e6f666781842483937612f163">glfwGetProcAddress</a>);</div><div class="line"> <a class="code" href="group__context.html#ga6d4e0cdf151b5e579bd67f13202994ed">glfwSwapInterval</a>(1);</div><div class="line"></div><div class="line"> <span class="comment">// NOTE: OpenGL error checks have been omitted for brevity</span></div><div class="line"></div><div class="line"> glGenBuffers(1, &amp;vertex_buffer);</div><div class="line"> glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);</div><div class="line"> glBufferData(GL_ARRAY_BUFFER, <span class="keyword">sizeof</span>(vertices), vertices, GL_STATIC_DRAW);</div><div class="line"></div><div class="line"> vertex_shader = glCreateShader(GL_VERTEX_SHADER);</div><div class="line"> glShaderSource(vertex_shader, 1, &amp;vertex_shader_text, NULL);</div><div class="line"> glCompileShader(vertex_shader);</div><div class="line"></div><div class="line"> fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);</div><div class="line"> glShaderSource(fragment_shader, 1, &amp;fragment_shader_text, NULL);</div><div class="line"> glCompileShader(fragment_shader);</div><div class="line"></div><div class="line"> program = glCreateProgram();</div><div class="line"> glAttachShader(program, vertex_shader);</div><div class="line"> glAttachShader(program, fragment_shader);</div><div class="line"> glLinkProgram(program);</div><div class="line"></div><div class="line"> mvp_location = glGetUniformLocation(program, <span class="stringliteral">&quot;MVP&quot;</span>);</div><div class="line"> vpos_location = glGetAttribLocation(program, <span class="stringliteral">&quot;vPos&quot;</span>);</div><div class="line"> vcol_location = glGetAttribLocation(program, <span class="stringliteral">&quot;vCol&quot;</span>);</div><div class="line"></div><div class="line"> glEnableVertexAttribArray(vpos_location);</div><div class="line"> glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE,</div><div class="line"> <span class="keyword">sizeof</span>(<span class="keywordtype">float</span>) * 5, (<span class="keywordtype">void</span>*) 0);</div><div class="line"> glEnableVertexAttribArray(vcol_location);</div><div class="line"> glVertexAttribPointer(vcol_location, 3, GL_FLOAT, GL_FALSE,</div><div class="line"> <span class="keyword">sizeof</span>(<span class="keywordtype">float</span>) * 5, (<span class="keywordtype">void</span>*) (<span class="keyword">sizeof</span>(<span class="keywordtype">float</span>) * 2));</div><div class="line"></div><div class="line"> <span class="keywordflow">while</span> (!<a class="code" href="group__window.html#ga24e02fbfefbb81fc45320989f8140ab5">glfwWindowShouldClose</a>(window))</div><div class="line"> {</div><div class="line"> <span class="keywordtype">float</span> ratio;</div><div class="line"> <span class="keywordtype">int</span> width, height;</div><div class="line"> mat4x4 m, p, mvp;</div><div class="line"></div><div class="line"> <a class="code" href="group__window.html#ga0e2637a4161afb283f5300c7f94785c9">glfwGetFramebufferSize</a>(window, &amp;width, &amp;height);</div><div class="line"> ratio = width / (float) height;</div><div class="line"></div><div class="line"> glViewport(0, 0, width, height);</div><div class="line"> glClear(GL_COLOR_BUFFER_BIT);</div><div class="line"></div><div class="line"> mat4x4_identity(m);</div><div class="line"> mat4x4_rotate_Z(m, m, (<span class="keywordtype">float</span>) <a class="code" href="group__input.html#gaa6cf4e7a77158a3b8fd00328b1720a4a">glfwGetTime</a>());</div><div class="line"> mat4x4_ortho(p, -ratio, ratio, -1.f, 1.f, 1.f, -1.f);</div><div class="line"> mat4x4_mul(mvp, p, m);</div><div class="line"></div><div class="line"> glUseProgram(program);</div><div class="line"> glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (<span class="keyword">const</span> GLfloat*) mvp);</div><div class="line"> glDrawArrays(GL_TRIANGLES, 0, 3);</div><div class="line"></div><div class="line"> <a class="code" href="group__window.html#ga15a5a1ee5b3c2ca6b15ca209a12efd14">glfwSwapBuffers</a>(window);</div><div class="line"> <a class="code" href="group__window.html#ga37bd57223967b4211d60ca1a0bf3c832">glfwPollEvents</a>();</div><div class="line"> }</div><div class="line"></div><div class="line"> <a class="code" href="group__window.html#gacdf43e51376051d2c091662e9fe3d7b2">glfwDestroyWindow</a>(window);</div><div class="line"></div><div class="line"> <a class="code" href="group__init.html#gaaae48c0a18607ea4a4ba951d939f0901">glfwTerminate</a>();</div><div class="line"> exit(EXIT_SUCCESS);</div><div class="line">}</div><div class="line"></div></div><!-- fragment --><p> The program above can be found in the <a href="http://www.glfw.org/download.html">source package</a> as <code>examples/simple.c</code> and is compiled along with all other examples when you build GLFW. If you built GLFW from the source package then already have this as <code>simple.exe</code> on Windows, <code>simple</code> on Linux or <code>simple.app</code> on OS X.</p>
<p>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.</p>
<ul>
<li><a class="el" href="intro_guide.html">Introduction to the API</a></li>
<li><a class="el" href="window_guide.html">Window guide</a></li>
<li><a class="el" href="context_guide.html">Context guide</a></li>
<li><a class="el" href="monitor_guide.html">Monitor guide</a></li>
<li><a class="el" href="input_guide.html">Input guide</a></li>
</ul>
<p>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.</p>
<p>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 <a class="el" href="build_guide.html">Building applications</a>. </p>
</div></div><!-- contents -->
<address class="footer">
<p>
Last update on Thu Aug 18 2016 for GLFW 3.2.1
</p>
</address>
</body>
</html>