-
Notifications
You must be signed in to change notification settings - Fork 45
Getting started
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.
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.
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.
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.