Skip to content
Lars Buitinck edited this page Nov 16, 2013 · 8 revisions

This article will detail the steps of building the library and using it to draw a simple primitive on the screen. It is assumed that the reader is already mostly familiar with the normal OpenGL API and the concepts behind it.

Building OOGL

You first need to make sure your environment is ready for using OOGL. The following things are required:

  • Windows or Linux operating system
  • Graphics card with driver supporting OpenGL 3.2
  • OpenGL/X11 development files (libgl1-mesa-dev and libx11-dev, Windows Platform SDK)

OOGL can be built on most Linux distros without much need for configuration. It usually comes down to

git clone git://github.com/Overv/OOGL.git
cd OOGL
make

Building on Windows is equally easy, you just need Visual C++ Express. A project is included for VS2010 and you should have no trouble building by simply pressing F7. You should now have a static library called OOGL.a or OOGL.lib in the bin directory.

Building your first project

No less important of course is to be able to build a project that uses the library. On Windows it's as easy as linking with OOGL-d.lib or OOGL.lib depending on your configuration and adding the include folder to your include path.

Linking on Linux works a bit differently. You need to link with GL, X11 and _Xrandr _and include the OOGL.a archive.

g++ main.cpp -o main -I /path/to/OOGL/include /path/to/OOGL/lib/OOGL.a -lX11 -lXrandr -lGL

Your build command should resemble the one above.

Basic setup

To put something on the screen, you first need a window. It is easy to create one in a platform agnostic way with the Window class:

#include <GL/OOGL.hpp>
	 
int main()
{
	GL::Window window( 800, 600, "OpenGL Window", GL::WindowStyle::Close );

	return 0;
}

The window can be configured with a width, height, title and style. This application could be made fullscreen by simply passing WindowStyle::Fullscreen as the fourth parameter or WindowStyle::Resize could be added to make the window resizable.

As soon as you've created a window, an OpenGL context can be created. Since the context is inevitably tied to the window, it can be constructed by calling Window::GetContext where the window will function as the default framebuffer.

GL::Context& gl = window.GetContext();

The OpenGL context can be customized, just like the window. The default parameters are suitable for most projects, so we'll leave them be for now.

OOGL wraps OpenGL objects into classes and makes use of C++ language features to make the API more convenient to use. While this allows it to automate and hide a lot of details, the raw API is still exposed as much as possible. To learn how this works, let's look at two ways to create a vertex shader.

GL::Shader vert( GL::ShaderType::Vertex );
vert.Source( "#version 150\nin vec2 position; void main() { gl_Position = vec4( position, 0.0, 1.0 ); }" );
vert.Compile();

The first method greatly resembles the C API. The constructor mimics glCreateShader and the Source and Compile member functions mimic the glShaderSource and glCompileShader functions respectively.

OOGL exposes an alternate constructor which automates these steps:

GL::Shader vert( GL::ShaderType::Vertex, GLSL(
	in vec2 position;
	void main() {
		gl_Position = vec4( position, 0.0, 1.0 );
	}
) );

This constructor takes a source directly and immediately compiles the shader. Also shown here is an alternate way to include shader code in your source files. The Shader::Compile member function and this constructor can throw a CompileException. This exception can be caught and what can be called to retrieve the compile info log.

GL::Shader frag( GL::ShaderType::Fragment, GLSL(
	out vec4 outColor;
	void main() {
		outColor = vec4( 1.0, 0.0, 0.0, 1.0 );
	}
) );

The fragment shader is compiled in exactly the same way. Remember to omit the #version preprocessor directive when using the GLSL macro, because newlines will not be included in the final source and your shader will fail to compile!

GL::Program program( vert, frag );

To link the vertex and fragment shaders into a program, the Program object also offers a rather convenient constructor that takes two shaders and links them instantly. Instead of this, you could also use the AttachShader and Link member functions, just like the regular API. The link process can throw a LinkException if the program fails to link, which will also include an info log - if available.

float vertices[] = {
	-0.5f,  0.5f,
	 0.5f,  0.5f,
	 0.5f, -0.5f
};
GL::VertexBuffer vbo( vertices, sizeof( vertices ), GL::BufferUsage::StaticDraw );

Creating a vertex buffer is not very different from the regular API, but the VertexBuffer class nicely hides the underlying state-machine. The member functions Data and SubData can be used to update the buffer. Note that this class is also intended for index buffers.

Now, just one last thing is missing: the link between the shader and the vertex data. This is exactly what the VertexArray class is intended for. This is one class where OOGL differs more wildly from the underlying API, but the same principles apply.

GL::VertexArray vao;
vao.BindAttribute( program.GetAttribute( "position" ), vbo, GL::Type::Float, 2, 0, 0 );

The BindAttribute function implicitly calls glBindVertexArray, glBindBuffer and glVertexAttribPointer to set up the state.

GL::Event ev;
while ( window.IsOpen() )
{
	while ( window.GetEvent( ev ) );

	gl.Clear();

	gl.DrawArrays( vao, GL::Primitive::Triangles, 0, 3 );

	window.Present();
}

Finally, the main loop of the program. Standard window events must be retrieved from the message loop, but do not have to be handled, as shown here.

It may be a surprise that there is no VertexArray::Bind function, this is because it is so inherently tied to actual drawing that the drawing functions themselves take it as a parameter and bind it automatically.

Hopefully you've gotten a good understanding of how OOGL abstracts the API. You can now read some of the other articles in this wiki to learn about uniforms, element buffers and textures.

Clone this wiki locally