Your first triangle
Basic rendering with builtin shaders.

The Hello World of 3D graphics, rendering a single colored triangle using OpenGL.
Continuing from the Getting Started Guide, where we used basically just the Platform::
#include <Magnum/GL/Buffer.h> #include <Magnum/GL/DefaultFramebuffer.h> #include <Magnum/GL/Mesh.h> #include <Magnum/Math/Color.h> #include <Magnum/Platform/Sdl2Application.h> #include <Magnum/Shaders/VertexColor.h>
The subclassed application looks very similar, only additionally containing the shader and a mesh instance. You can read more about platform support and various portability tricks in Platform support.
class TriangleExample: public Platform::Application { public: explicit TriangleExample(const Arguments& arguments); private: void drawEvent() override; GL::Mesh _mesh; Shaders::VertexColor2D _shader; };
In the constructor we pass arguments to the application class. The Configuration configuration is optional and allows us to set a window title and other things.
TriangleExample::TriangleExample(const Arguments& arguments): Platform::Application{arguments, Configuration{}.setTitle("Magnum Triangle Example")} {
Now we specify vertex attributes, consisting of positions and colors. For performance reasons it is common to interleave them, so data for each vertex are in one continuous place in memory. In this case, because we need just three vertices, we will interleave them manually in-place. In the next tutorial we will learn how to interleave them programatically. See Math type system for more information about scalar and vector types used in Magnum — one of the notable convenience features is an ability to use a custom literal to specify hexadecimal colors, just like you are used to from CSS and various graphics editors.
using namespace Math::Literals; struct TriangleVertex { Vector2 position; Color3 color; }; const TriangleVertex data[]{ {{-0.5f, -0.5f}, 0xff0000_rgbf}, /* Left vertex, red color */ {{ 0.5f, -0.5f}, 0x00ff00_rgbf}, /* Right vertex, green color */ {{ 0.0f, 0.5f}, 0x0000ff_rgbf} /* Top vertex, blue color */ };
We then create vertex buffer and fill it with data.
GL::Buffer buffer; buffer.setData(data);
Now we configure the mesh. The mesh is GL::
Here we use std::buffer
exists for the whole mesh lifetime. On the other hand, we lose the ability to modify that buffer afterwards.
_mesh.setCount(3) .addVertexBuffer(std::move(buffer), 0, Shaders::VertexColor2D::Position{}, Shaders::VertexColor2D::Color3{}); }
The drawEvent() function will take care of rendering the scene. We will clear color buffer of the default framebuffer (which is also the default rendering target) and then we draw the mesh using our shader. The context is double-buffered, so we need to swap the buffers after drawing.
void TriangleExample::drawEvent() { GL::defaultFramebuffer.clear(GL::FramebufferClear::Color); _mesh.draw(_shader); swapBuffers(); }
Lastly, we need a main()
function. The MAGNUM_
MAGNUM_APPLICATION_MAIN(TriangleExample)
That's all, now we can compile the whole example using CMake. Continuing from the Getting Started Guide, the only addition is finding & linking the Magnum::
find_package(Corrade REQUIRED Main) find_package(Magnum REQUIRED GL Shaders Sdl2Application) set_directory_properties(PROPERTIES CORRADE_USE_PEDANTIC_FLAGS ON) add_executable(magnum-triangle WIN32 TriangleExample.cpp) target_link_libraries(magnum-triangle PRIVATE Corrade::Main Magnum::Application Magnum::GL Magnum::Magnum Magnum::Shaders)
You can now try changing vertex count, positions or colors to see how the shader behaves. The full file content is linked below. Full source code is also available in the magnum-examples GitHub repository.
The ports branch contains additional patches for iOS, Android and Emscripten support that aren't present in master
in order to keep the example code as simple as possible.