This repository contains proof-of-concept implementations of various rendering / simulation techniques in OpenGL that I wrote over the past few years.
- Implemented Examples
- pointcloud rendering (geometry shader constructed billboards)
- volume raycasting (MIP / ISO-Surface)
- temporal anti aliasing (AABB clamping rectification)
- shadow-mapping
- cel-shading (post-process edge detection)
- physically based rendering (+ image based lighting)
- deferred rendering (light volumes)
- reflection probes (AABB parallax correction)
- screen space reflections
- screen space ambient occlusion
- transclucent shadow map
- texture space subsurface scattering
- voxelizer (compute shader)
- single-pass voxelizer
- cloth physics (position based dynamics in compute shader)
"Wanderers by Bastien Genbrugge licensed under CC BY 4.0.
"Skull" from volvis.org and Siemens Medical Solutions, Forchheim, Germany
"1982 Porsche 911 - SiteScape 3D Scan" by SiteScape licensed under CC BY 4.
The viewer class handles window (context) creation, input events, and callback registration (rendering, input, window events, and ImGui / ImPlot draw calls) - have a look at the viewer_demos for a more detailed overview.
viewer::window_settings settings;
settings.title = "Colored Cube";
settings.width = 720;
settings.heigth = 720;
/* construct viewer (creates window and context) */
viewer view(settings);
The OpenGL context is created on viewer construction and is destroyed on destruction - OpenGL calls are only allowed in between. For ease of use I wrapped some of the most commonly used OpenGL functionalities (not feature complete), which is accessed through an opengl::context instance. For example, to create a shader program the context provides a handle to which the source code can be attached, linked and compiled.
const char *vertex_shader = "
#version 330\n
layout(location = 0) in vec3 aPosition;
layout(location = 1) in vec4 aColor;
uniform mat4 uModel;
uniform mat4 uView;
uniform mat4 uProj;
out vec4 tColor;
void main(void)
{
gl_Position = uProj * uView * uModel * vec4(aPosition, 1.0);
tColor = aColor;
});"
const char *frag_shader = "
#version 330\n
in vec4 tColor;
out vec4 fragColor;
void main(void)
{
fragColor = tColor;
});"
/* create shader and compile */
auto shader = context.make_shader();
shader->attach(vertex_shader, opengl::shader_type::vertex);
shader->attach(frag_shader, opengl::shader_type::fragment);
shader->link();
To create vertexbuffers with generic vertex types, a static layout description is required (I am not really happy with this; may change in the future).
/*============= Vertex Defition =============*/
struct vertex
{
glm::vec3 position;
glm::vec4 color;
};
/* vertexbuffer layout definition for OpenGL */
template <>
struct opengl::layout<vertex>
{
static constexpr attr_info value[] = {
{opengl::type::float_, 3, opengl::buffer_mapping::cast, offsetof(vertex, position)},
{opengl::type::float_, 4, opengl::buffer_mapping::cast, offsetof(vertex, color)}};
};
With access to the layout description, a vertexbuffer (here a colored cube + indexbuffer) can be created and attached to a vertexarray object.
/* create vertexarray, and attach vertexbuffer and indexbuffer to it */
auto vao = context.make_vertexarray();
auto vertexbuffer = context.make_vertexbuffer<vertex>(
std::initializer_list<vertex>
{{{-1.0, -1.0, 1.0}, {1.0, 0.0, 0.0, 1.0}}, {{-1.0, 1.0, 1.0}, {0.0, 1.0, 0.0, 1.0}},
{{ 1.0, 1.0, 1.0}, {0.0, 0.0, 1.0, 1.0}}, {{ 1.0, -1.0, 1.0}, {1.0, 0.0, 1.0, 1.0}},
{{-1.0, -1.0, -1.0}, {1.0, 0.0, 0.0, 1.0}}, {{-1.0, 1.0, -1.0}, {0.0, 1.0, 0.0, 1.0}},
{{ 1.0, 1.0, -1.0}, {0.0, 0.0, 1.0, 1.0}}, {{ 1.0, -1.0, -1.0}, {1.0, 0.0, 1.0, 1.0}}});
auto indexbuffer = context.make_indexbuffer<unsigned int>(
std::initializer_list<unsigned int>
{0, 2, 1, 2, 0, 3,
4, 5, 6, 6, 7, 4,
0, 1, 5, 5, 4, 0,
3, 6, 2, 6, 3, 7,
1, 6, 5, 6, 1, 2,
0, 4, 7, 7, 3, 0});
vao->attach(vertexbuffer);
vao->attach(indexbuffer);
In the render callback of the viewer we use the previously defined shader program to draw the content of the vertexarray.
/* access viewer camera */
auto& cam = view.camera();
/* set render callback*/
view.on_render([&](auto& window, float dt)
{
static float s_time = 0.0f;
s_time += dt;
/* set shader uniforms */
shader->bind();
shader->uniform("uModel", glm::rotate(s_time*glm::pi<float>(),
glm::vec3{0.0f, 1.0f, 0.0f}));
shader->uniform("uView", cam.view());
shader->uniform("uProj", cam.projection());
/* draw elements */
vao->draw(opengl::primitives::triangles);
});
/* execute main loop */
view.run();