OGLplus  (0.59.0) a C++ wrapper for rendering APIs

oglplus/020_glfw3_glew_recursive_cube.cpp

Copyright Matus Chochlik. Distributed under the Boost Software License, Version 1.0. See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt

#include <GL/glew.h>
#include <oglplus/constant_defs.hpp>
#include <oglplus/constants.hpp>
#include <oglplus/error/format.hpp>
#include <oglplus/operations.hpp>
#include <GLFW/glfw3.h>
#include <cmath>
#include <iostream>
#include <stdexcept>
static oglplus::constants GL;
static oglplus::operations gl;
static void run_loop(GLFWwindow* window, int width, int height) {
using namespace oglplus;
shader vs(GL.vertex_shader);
vs.source(
glsl_literal("#version 140\n"
"uniform mat4 Projection;"
"uniform mat4 Modelview;"
"uniform vec3 LightPos;"
"in vec4 Position;\n"
"in vec3 Normal;\n"
"in vec2 TexCoord;\n"
"out vec3 vertNormal;\n"
"out vec3 vertLightDir;\n"
"out vec2 vertTexCoord;\n"
"void main()\n"
"{\n"
" gl_Position = Modelview*Position;\n"
" vertNormal = mat3(Modelview)*Normal;\n"
" vertLightDir = LightPos - gl_Position.xyz;\n"
" vertTexCoord = TexCoord;\n"
" gl_Position = Projection*gl_Position;\n"
"}\n"));
vs.compile();
shader fs(GL.fragment_shader);
fs.source(glsl_literal(
"#version 140\n"
"uniform sampler2D CubeTex;"
"in vec3 vertNormal;\n"
"in vec3 vertLightDir;\n"
"in vec2 vertTexCoord;\n"
"out vec4 fragColor;\n"
"void main()\n"
"{\n"
" float d = 0.3*dot(vertNormal, normalize(vertLightDir));\n"
" float i = 0.6 + max(d, 0.0);\n"
" fragColor = texture(CubeTex, vertTexCoord)*i;\n"
"}\n"));
fs.compile();
program prog;
prog.attach(vs);
prog.attach(fs);
prog.link();
gl.use_program(prog);
uniform_location projection, modelview, light_pos, cube_tex;
gl.query_location(projection, prog, "Projection");
gl.query_location(modelview, prog, "Modelview");
gl.query_location(light_pos, prog, "LightPos");
gl.query_location(cube_tex, prog, "CubeTex");
vertex_array vao;
gl.bind(vao);
// positions
const GLfloat v[8][3] = {
{-0.5F, -0.5F, -0.5F},
{+0.5F, -0.5F, -0.5F},
{-0.5F, +0.5F, -0.5F},
{+0.5F, +0.5F, -0.5F},
{-0.5F, -0.5F, +0.5F},
{+0.5F, -0.5F, +0.5F},
{-0.5F, +0.5F, +0.5F},
{+0.5F, +0.5F, +0.5F}};
const GLint f[6][2][3] = {
{{0, 4, 2}, {2, 4, 6}},
{{5, 1, 7}, {7, 1, 3}},
{{0, 1, 4}, {4, 1, 5}},
{{6, 7, 2}, {2, 7, 3}},
{{1, 0, 3}, {3, 0, 2}},
{{4, 5, 6}, {6, 5, 7}}};
const GLuint vertex_count = 6 * 2 * 3;
GLfloat cube_vertices[vertex_count * 3];
for(GLuint fi = 0; fi != 6; ++fi) {
for(GLuint ti = 0; ti != 2; ++ti) {
for(GLuint vi = 0; vi != 3; ++vi) {
for(GLuint ci = 0; ci != 3; ++ci) {
cube_vertices[fi * 2 * 3 * 3 + ti * 3 * 3 + vi * 3 + ci] =
v[f[fi][ti][vi]][ci];
}
}
}
}
buffer pos;
gl.bind(GL.array_buffer, pos);
gl.buffer_data(GL.array_buffer, cube_vertices, GL.static_draw);
gl.vertex_array_attrib_pointer(
vertex_attrib_location(0), 3, GL.float_, false, 0, nullptr);
gl.enable_vertex_array_attrib(vertex_attrib_location(0));
gl.query_location(va_p, prog, "Position");
gl.vertex_array_attrib_pointer(va_p, 3, GL.float_, false, 0, nullptr);
gl.enable_vertex_array_attrib(va_p);
// normals
const GLfloat n[6][3] = {
{-1.0F, 0.0F, 0.0F},
{1.0F, 0.0F, 0.0F},
{0.0F, -1.0F, 0.0F},
{0.0F, 1.0F, 0.0F},
{0.0F, 0.0F, -1.0F},
{0.0F, 0.0F, 1.0F}};
GLfloat cube_normals[vertex_count * 3];
for(GLuint fi = 0; fi != 6; ++fi) {
for(GLuint vi = 0; vi != 6; ++vi) {
for(GLuint ci = 0; ci != 3; ++ci) {
cube_normals[(fi * 6 + vi) * 3 + ci] = n[fi][ci];
}
}
}
buffer nml;
gl.bind(GL.array_buffer, nml);
gl.buffer_data(GL.array_buffer, cube_normals, GL.static_draw);
gl.query_location(va_n, prog, "Normal");
gl.vertex_array_attrib_pointer(va_n, 3, GL.float_, false, 0, nullptr);
gl.enable_vertex_array_attrib(va_n);
// face-coords
const GLfloat c[6][2] = {
{0.0F, 0.0F},
{1.0F, 0.0F},
{0.0F, 1.0F},
{0.0F, 1.0F},
{1.0F, 0.0F},
{1.0F, 1.0F}};
GLfloat cube_coords[vertex_count * 2];
for(GLuint fi = 0; fi != 6; ++fi) {
for(GLuint vi = 0; vi != 6; ++vi) {
for(GLuint ci = 0; ci != 2; ++ci) {
cube_coords[(fi * 6 + vi) * 2 + ci] = c[vi][ci];
}
}
}
buffer crd;
gl.bind(GL.array_buffer, crd);
gl.buffer_data(GL.array_buffer, cube_coords, GL.static_draw);
gl.query_location(va_c, prog, "TexCoord");
gl.vertex_array_attrib_pointer(va_c, 2, GL.float_, false, 0, nullptr);
gl.enable_vertex_array_attrib(va_c);
gl.clear_color(0.8F, 0.8F, 0.8F, 0.0F);
gl.clear_depth(1);
GLsizei tex_side = 512;
texture_array<2> texs;
renderbuffer_array<2> rbos;
framebuffer_array<2> fbos;
for(GLuint i = 0; i < 2u; ++i) {
texture_name tex = texs[i];
gl.active_texture(GL.texture0 + i);
gl.bind(GL.texture_2d, tex);
gl.texture_min_filter(GL.texture_2d, GL.linear);
gl.texture_mag_filter(GL.texture_2d, GL.linear);
gl.texture_image_2d(
GL.texture_2d,
0,
GL.rgb,
tex_side,
tex_side,
0,
GL.rgb,
GL.unsigned_byte,
const_memory_block());
renderbuffer_name rbo = rbos[i];
gl.bind(GL.renderbuffer, rbo);
gl.renderbuffer_storage(
GL.renderbuffer, GL.depth_component, tex_side, tex_side);
framebuffer_name fbo = fbos[i];
gl.bind(GL.draw_framebuffer, fbo);
gl.framebuffer_texture_2d(
GL.draw_framebuffer, GL.color_attachment0, GL.texture_2d, tex, 0);
gl.framebuffer_renderbuffer(
GL.draw_framebuffer, GL.depth_attachment, GL.renderbuffer, rbo);
gl.viewport(tex_side, tex_side);
gl.clear(GL.color_buffer_bit);
}
gl.bind(GL.draw_framebuffer, default_framebuffer);
gl.bind(GL.renderbuffer, no_renderbuffer);
gl.enable(GL.depth_test);
gl.enable(GL.cull_face);
gl.cull_face(GL.back);
gl.front_face(GL.ccw);
unsigned current_buf = 0;
float rad = 0.0F;
while(true) {
glfwPollEvents();
if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
glfwSetWindowShouldClose(window, 1);
break;
}
if(glfwWindowShouldClose(window)) {
break;
}
int new_width, new_height;
glfwGetWindowSize(window, &new_width, &new_height);
if((width != new_width) || (height != new_height)) {
width = new_width;
height = new_height;
}
current_buf = (current_buf + 1) % 2;
gl.uniform(light_pos, vec3(std::cos(rad) * 4, std::sin(rad) * 4, 8));
gl.uniform(
modelview,
rad += 0.01F;
// draw into the texture
gl.bind(GL.draw_framebuffer, fbos[current_buf]);
gl.viewport(tex_side, tex_side);
GLfloat s = 0.5F;
gl.uniform(
projection,
oglplus::matrix_perspective(-s, +s, -s, +s, 1.0F, 5) *
gl.clear(GL.color_buffer_bit | GL.depth_buffer_bit);
gl.draw_arrays(GL.triangles, 0, 6 * 2 * 3);
// draw on screen
gl.bind(GL.draw_framebuffer, default_framebuffer);
gl.viewport(width, height);
gl.uniform(cube_tex, GLint(current_buf));
GLfloat asp = GLfloat(width) / height;
GLfloat h = 0.55F;
GLfloat w = h * asp;
gl.uniform(
projection,
oglplus::matrix_perspective(-w, +w, -h, +h, 1, 3) *
gl.clear(GL.color_buffer_bit | GL.depth_buffer_bit);
gl.draw_arrays(GL.triangles, 0, 6 * 2 * 3);
glfwSwapBuffers(window);
}
}
static void init_and_run() {
if(!glfwInit()) {
throw std::runtime_error("GLFW initialization error");
} else {
auto ensure_glfw_cleanup = eagine::finally(glfwTerminate);
glfwWindowHint(GLFW_DOUBLEBUFFER, GL_TRUE);
glfwWindowHint(GLFW_RED_BITS, 8);
glfwWindowHint(GLFW_BLUE_BITS, 8);
glfwWindowHint(GLFW_GREEN_BITS, 8);
glfwWindowHint(GLFW_ALPHA_BITS, 0);
glfwWindowHint(GLFW_DEPTH_BITS, 24);
glfwWindowHint(GLFW_STENCIL_BITS, 0);
glfwWindowHint(GLFW_SAMPLES, GLFW_DONT_CARE);
int width = 800, height = 600;
GLFWwindow* window =
glfwCreateWindow(width, height, "OGLplus example", nullptr, nullptr);
if(!window) {
throw std::runtime_error("Error creating GLFW window");
} else {
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
GLenum init_result = glewInit();
glGetError();
if(init_result != GLEW_OK) {
throw std::runtime_error("OpenGL/GLEW initialization error.");
} else {
run_loop(window, width, height);
}
}
}
}
auto main() -> int {
try {
init_and_run();
return 0;
} catch(oglplus::error& gle) {
oglplus::format_error(
gle,
"OpenGL error\n"
"in GL function: %(gl_function_name)\n"
"with object: %(gl_object)\n"
"with enum parameter: %(gl_enum_value)\n"
"with index: %(gl_index)\n"
"from source file: %(source_file)\n"
"%(message)\n",
std::cerr)
<< std::endl;
} catch(std::runtime_error& sre) {
std::cerr << "Runtime error: " << sre.what() << std::endl;
} catch(std::exception& se) {
std::cerr << "Unknown error: " << se.what() << std::endl;
}
return 1;
}
prog_var_location< EAGINE_ID_V(Uniform)> uniform_location
Alias for shader program uniform location wrapper.
Definition: prog_var_loc.hpp:115
gl_object_name< renderbuffer_tag > renderbuffer_name
Alias for GL renderbuffer object handle.
Definition: object_name.hpp:138
convertible_matrix_constructor< rotation_x< matrix< T, 4, 4, true, V > >> matrix_rotation_x
Alias for constructor of rotation along x-axis transformation matrix.
Definition: matrix_rotation.hpp:124
Definition: 005_path_nv_text.cpp:19
gl_object_name< texture_tag > texture_name
Alias for GL texture object handle.
Definition: object_name.hpp:153
convertible_matrix_constructor< perspective< matrix< T, 4, 4, true, V > >> matrix_perspective
Alias for constructor of perspective projection matrix.
Definition: matrix_perspective.hpp:177
convertible_matrix_constructor< translation< matrix< T, 4, 4, true, V > >> matrix_translation
Alias for constructor of uniform translation transformation matrix.
Definition: matrix_translation.hpp:95
gl_object_name< framebuffer_tag > framebuffer_name
Alias for GL framebuffer object handle.
Definition: object_name.hpp:118
static constexpr auto radians_(T value) noexcept -> radians_t< T >
Creates a tagged quantity storing value in radians.
Definition: quantities.hpp:50
prog_var_location< EAGINE_ID_V(VertexAttr)> vertex_attrib_location
Alias for program vertex attribute location wrapper.
Definition: prog_var_loc.hpp:104
static auto finally(Func func) -> func_on_scope_exit< Func >
Function constructing on-scope-exit actions.
Definition: scope_exit.hpp:144
convertible_matrix_constructor< rotation_z< matrix< T, 4, 4, true, V > >> matrix_rotation_z
Alias for constructor of rotation along z-axis transformation matrix.
Definition: matrix_rotation.hpp:152
tvec< gl_types::float_type, 3 > vec3
Alias for a 3D vector type.
Definition: vector.hpp:32
convertible_matrix_constructor< rotation_y< matrix< T, 4, 4, true, V > >> matrix_rotation_y
Alias for constructor of rotation along y-axis transformation matrix.
Definition: matrix_rotation.hpp:138

Copyright © 2015-2021 Matúš Chochlík.
<chochlik -at -gmail.com>
Documentation generated on Tue Apr 13 2021 by Doxygen (version 1.8.17).