Gamedev Framework (gf)
0.3.0
A C++11 framework for 2D games
|
This is a quick and dirty introduction to modern OpenGL rendering pipeline. If you already know everything then you can go to the next section.
In modern OpenGL, the rendering pipeline is programmable. Not everything is programmable but the most important parts. You have to use a special language called GLSL (OpenGL Shading Language) and make programs called shaders.
The data you send to shaders is prepared in the main program and is called vertices. Vertices represent the geometry of what you have to draw. A vertex is a kind of super point: it contains the coordinates of the object but also the texture coordinates of the point, sometimes (in 3D) the normal of the surface at that point, and many more possible things.
All the vertices are sent to the graphics card that passes them to the vertex shader which is responsible of transforming the coordinates of the vertex from the game world (2D or 3D) to the screen. After this first pass, the vertices go in the rasterizer which computes the color of each pixel. Then, the pixels go through a fragment shader which can compute the final color of the pixel and sometimes other attributes.
And that's it, basically!
In gf, every draw command ends in a shader. If no shader is specified, then a default shader is used.
Here is the default vertex shader:
gf::Vertex contains the data that is passed to this vertex shader. When you call gf::RenderTarget::draw(), you have to provide an array of gf::Vertex which is then handled by the shader:
position
attribute becomes a_position
in the shadercolor
attribute becomes a_color
in the shadertexCoords
attribute becomes a_texCoords
in the shaderThe u_transform
constant is set by the library automatically. It is computed from the global transform matrix put in gf::RenderStates and from the object transform matrix (see gf::Transformable::getTransform()).
Here is the default fragment shader:
The u_texture
constant is set by the library automatically. If no texture is provided, a default opaque white infinite texture is set.
Quite easy. We are in 2D!
If you want to write your own shader, you will have to use the same variables (with the same names) so that you can receive the data from the vertices. The easiest way to do it is to start from the default shaders and modify them. This means you can not add attribute
variables, but you can do whatever you want with varying
variables and you can add uniform
variables as long as you keep the two already present variables u_transform
and u_texture
.
Then, you can load your shader with gf::Shader::loadFromFile() (or any other loading method of gf::Shader).
If you have additional constants (uniforms), you can set them with one of the gf::Shader::setUniform() functions.
Finally, you can use the gf::RenderStates to specify your shader when rendering your objects.
Post-processing is an application of global graphic effects after the frame has been computed. It can be used for a wide range of usage. Technically, the frame is rendered in a texture and the texture is then sent into the graphics pipeline again i.e. in the shaders where you can apply the desired effect.
In gf, there are some already predefined post-processing shaders, called effects:
You can write your own post-processing effects. Generally, you only use a special fragment shader.