OGLplus (0.52.0) a C++ wrapper for OpenGL

RGB triangle

This tutorial is an extension of the Basic usage with GLUT and GLEW tutorial, but it does not go through the code responsible for window initialization, OpenGL initialization and event handling.

For a full working code see the oglplus/002_triangle.cpp file in the example directory.

First we include a locale helper header that in turn includes GL3/gl3.h , GLEW or makes sure that the OpenGL symbols are defined. It is however not required for your applications to do it this way and if you wish you can use other means of defining the necessary OpenGL 3 functions, constants, etc.

#include <oglplus/gl.hpp>

Include everything from OGLplus, except the image loaders and generators and geometric shape data generators.

#include <oglplus/all.hpp>

The header declaring the base class for OGLplus examples.

#include "example.hpp"

Since this is an example that comes with the library it is implemented inside of the oglplus namespace.

namespace oglplus {
Real-life applications should instead do something like:

using namespace oglplus;

Doing this on the global scope may cause name clashes with other libraries especially in larger applications, so it may be a better idea to use fully qualified names or apply the using directive only in local scopes.

As before, the rendering code is encapsulated in the TriangleExample class which is derived from oglplus::Example.

class TriangleExample : public Example
{

Most of the member variables are the same as in the previous tutorial. There is an instance of the oglplus::Context class wrapping the current context functions, a oglplus::VertexShader and oglplus::FragmentShader, a oglplus::Program which define the custom functionality of the rendering pipeline and a oglplus::VertexArray object managing the vertex data for the rendered triangle.

private:
// wrapper around the current OpenGL context
Context gl;
// Vertex shader
// Fragment shader
// Program
Program prog;
// A vertex array object for the rendered triangle
VertexArray triangle;

The first difference between this and the previous tutorial is that there are two oglplus::Buffer objects, one for the vertex positions and the second for vertex colors.

// VBOs for the triangle's vertices and colors
Buffer verts;
Buffer colors;

The public interface consists of a constructor and a couple of member functions.

public:

The constructor takes no arguments and again sets the vertex shader source:

TriangleExample(void)
{
// Set the vertex shader source
vs.Source(" \

As before we specify the version of GLSL we wish to use with the version directive.

#version 330\n \

Declare the input variables of the vertex shader; Position for vertex positions and Color for vertex colors.

in vec3 Position; \
in vec3 Color; \

This time there is also an explicitly declared output variable called vertColor.

out vec4 vertColor; \

The main function again passes the value of the Position input variable to the next stages of the rendering pipeline via the implicitly declared gl_Position output variable:

void main(void) \
{ \
gl_Position = vec4(Position, 1.0); \

We also pass the color value to the fragment shader, converting the RGB value into RGBA, with the alpha component set to 1.0.

vertColor = vec4(Color, 1.0); \

That's it for the vertex shader and now it can be compiled:

} \
");
// compile it
vs.Compile();

The fragment shader is similar to the one from the previous tutorial:

// set the fragment shader source
fs.Source(" \
#version 330\n \

This time there is a input variable vertColor, matching the output variable from vertex shader in both name and type. The value of this variable will be smoothly interpolated across the surface of the rendered triangle.

in vec4 vertColor; \

The only thing the shader does is that is assigns the vertColor value to the fragColor output variable:

out vec4 fragColor; \
void main(void) \
{ \
fragColor = vertColor; \
} \
");

We can now compile the fragment shader source code, attach both shaders to the shading program and try to link and use it.

// compile it
fs.Compile();
// attach the shaders to the program
prog.AttachShader(vs);
prog.AttachShader(fs);
// link and use it
prog.Link();
prog.Use();

Now we can start to specify the data for the individual vertex attributes of the triangle we're going to render. The first step as before is to bind the vertex array object managing the vertex data.

triangle.Bind();

Since this is a simple example the vertex positions are hardcoded:

GLfloat triangle_verts[9] = {
0.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f
};

We bind the VBO for vertex positions to the ARRAY_BUFFER target.

verts.Bind(Buffer::Target::Array);

The data are uploaded from client's memory to the server's memory by using the Buffer 's Data static function.

Buffer::Data(Buffer::Target::Array, 9, triangle_verts);

Then we use a oglplus::VertexArrayAttrib object referencing the Position input variable in the prog program, to tell OpenGL about the structure of the data in the currently bound VBO and to enable this vertex attribute.

VertexArrayAttrib(prog, "Position").Setup<GLfloat>(3).Enable();

Now we repeat the steps above, for the second vertex attribute, specifying the colors of the individual vertices:

GLfloat triangle_colors[9] = {
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f
};
// bind the VBO for the triangle colors
colors.Bind(Buffer::Target::Array);
// upload the data
Buffer::Data(Buffer::Target::Array, 9, triangle_colors);
// setup the vertex attribs array
VertexArrayAttrib(prog, "Color").Setup<GLfloat>(3).Enable();

That's it for the vertex data specification. As the last step of initialization we specify the clear value for the color buffer and disable the depth test.

gl.ClearColor(1.0f, 1.0f, 1.0f, 0.0f);
gl.Disable(Capability::DepthTest);
}

The Reshape function gets called when the window is created and everytime the window's size changes. Here we tell the GL that the rendering viewport has changed.

void Reshape(GLuint width, GLuint height)
{
gl.Viewport(width, height);
}

This function redraws our scene and is basically the same as in the previous tutorial; we clear the color buffer and we tell the GL to draw triangle from the vertex data stored in the buffer objects tied to the currently bound VAO, which is still triangle, because we didn't bind any other VAO since initialization. More precisely we draw the triangle composed from 3 vertices starting at index 0 in the buffers.

void Render(double)
{
gl.Clear().ColorBuffer();
gl.DrawArrays(PrimitiveType::Triangles, 0, 3);
}

Now the TriangleExample class is complete:

};

The last thing in this example's source is the makeExample function. This function is called by shared internal piece of code (that comes with the examples) which does the initialization and event processing common to all the examples. makeExample creates an instance of our TriangleExample class. The common code then calls the event handler functions like Reshape and Render when appropriate. To see how this can be incorporated into a complete application see the standalone examples and the related tutorials.

std::unique_ptr<Example> makeExample(const ExampleParams& /*params*/)


Copyright © 2010-2014 Matúš Chochlík, University of Žilina, Žilina, Slovakia.
<matus.chochlik -at- fri.uniza.sk>
<chochlik -at -gmail.com>
Documentation generated on Mon Sep 22 2014 by Doxygen (version 1.8.6).