Commit 3a092919 authored by Tim Übelhör's avatar Tim Übelhör

Using different shader extensions.

Added rasterizer and depth simulator
parent 4c5d54d4
......@@ -4,15 +4,14 @@
"name": "Linux",
"includePath": [
"${workspaceFolder}/include",
"/home/tim/.conan/data/gl3w/0.2/tuebel/testing/package/1a651c5b4129ad794b88522bece2281a7453aee4/include",
"/home/tim/.conan/data/glm/0.9.9.1/g-truc/stable/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9/include"
],
"defines": [],
"cStandard": "c11",
"cppStandard": "c++11",
"configurationProvider": "vector-of-bool.cmake-tools",
"compileCommands": "${workspaceFolder}/build/compile_commands.json"
}
],
"version": 4
"~/.conan/data/"
],
"defines": [],
"cStandard": "c11",
"cppStandard": "c++11",
"configurationProvider": "vector-of-bool.cmake-tools",
"compileCommands": "${workspaceFolder}/build/compile_commands.json"
}
],
"version": 4
}
\ No newline at end of file
......@@ -61,7 +61,8 @@
"optional": "cpp",
"string_view": "cpp",
"*.fs": "cpp",
"*.vs": "cpp"
"*.vs": "cpp",
"*.vert": "cpp"
},
"python.autoComplete.extraPaths": [
"/opt/ros/kinetic/lib/python2.7/dist-packages"
......
......@@ -22,12 +22,13 @@ endif()
set(OpenGL_GL_PREFERENCE "GLVND")
# library
add_library(scigl_render)
target_sources(scigl_render PRIVATE
add_library(scigl_render
src/gl_context.cpp
src/render/depth_simulator.cpp
src/render/frame_buffer.cpp
src/render/offscreen_render.cpp
src/render/onscreen_render.cpp
src/render/rasterizer.cpp
src/render/texture_fullscreen_render.cpp
src/scene/cv_camera.cpp
src/scene/diffuse_light.cpp
......@@ -41,13 +42,12 @@ target_link_libraries(scigl_render ${CONAN_LIBS})
# example apps
add_executable(scigl_viewer
src/example/scigl_viewer.cpp
src/example/example_render.cpp)
src/example/scigl_viewer.cpp)
target_link_libraries(scigl_viewer
scigl_render)
add_executable(scigl_depth_viewer
src/example/scigl_depth_viewer.cpp
src/example/example_render.cpp)
src/example/depth_offscreen_render.cpp)
target_link_libraries(scigl_depth_viewer
scigl_render)
......@@ -30,12 +30,12 @@ class SciglRenderConan(ConanFile):
cmake.build()
def package(self):
self.copy("*.cs", dst="include", src="include", keep_path=True)
self.copy("*.fs", dst="include", src="include", keep_path=True)
self.copy("*.gs", dst="include", src="include", keep_path=True)
self.copy("*.tcs", dst="include", src="include", keep_path=True)
self.copy("*.tes", dst="include", src="include", keep_path=True)
self.copy("*.vs", dst="include", src="include", keep_path=True)
self.copy("*.comp", dst="include", src="include", keep_path=True)
self.copy("*.frag", dst="include", src="include", keep_path=True)
self.copy("*.geom", dst="include", src="include", keep_path=True)
self.copy("*.tesc", dst="include", src="include", keep_path=True)
self.copy("*.tese", dst="include", src="include", keep_path=True)
self.copy("*.vert", dst="include", src="include", keep_path=True)
self.copy("*.h", dst="include", src="include", keep_path=True)
self.copy("*.hpp", dst="include", src="include", keep_path=True)
self.copy("*.lib", dst="lib", keep_path=False)
......
#pragma once
#include <scigl_render/gl_context.hpp>
#include <scigl_render/render/depth_simulator.hpp>
#include <scigl_render/render/offscreen_render.hpp>
#include <scigl_render/render/texture_fullscreen_render.hpp>
#include <scigl_render/scene/cv_camera.hpp>
#include <scigl_render/scene/diffuse_light.hpp>
#include <scigl_render/scene/model.hpp>
#include <scigl_render/shader/shader.hpp>
#include <memory>
#include <vector>
......@@ -14,11 +11,11 @@ namespace scigl_render
/*!
Demonstrates how to render a scene with this library. Frankly this is quite
the unnecessary complicated case, since I test rendering offscreen to a FBO,
transfer the texture to a PBO and reading this into CPU memory.Then I push it
transfer the texture to a PBO and reading this into CPU memory. Then I push it
back to the GPU as anoter texture generated from the CPU memory and it will is
be displayed on screen.
*/
class ExampleRender
class DepthOffscreenRender
{
public:
/*!
......@@ -31,16 +28,16 @@ public:
\param pixel_size the size of one pixel. Must match the internal format:
number_of_channels * sizeof(type)
*/
ExampleRender(std::shared_ptr<GLContext> context,
Shader shader,
GLenum tex_format, GLenum tex_type, GLint tex_internal_format,
size_t pixel_size);
DepthOffscreenRender(
std::shared_ptr<GLContext> context, GLenum tex_format, GLenum tex_type,
GLint tex_internal_format, size_t pixel_size);
/*!
Continues to render the next frame.
*/
void next_frame(const CvCamera &camera, const Model &model,
const DiffuseLight &light);
void next_frame(std::shared_ptr<DepthSimulator> depth_simulator,
const CartesianPose &model_pose,
const CartesianPose &camera_pose);
/*!
Resizes the buffers to the screen size of the GLContext.
......
#pragma once
#include <scigl_render/scene/cv_camera.hpp>
#include <scigl_render/scene/model.hpp>
namespace scigl_render
{
class DepthSimulator
{
public:
/**
* Create a simulator for this camera and model.
*/
DepthSimulator(scigl_render::CvCamera camera,
scigl_render::Model model);
/**
* Renders the simulated depth image of the model.
* \param state the current pose of the object
*/
void render_pose(const QuaternionPose &object_pose,
const QuaternionPose &camera_pose);
/** width of the simulated images */
int get_width();
/** height of the simulated images */
int get_height();
// the OpenGL texture needed to render depth values
static const GLenum FORMAT = GL_RED;
static const GLenum TYPE = GL_FLOAT;
static const GLint INTERNAL_FORMAT = GL_R32F;
static const size_t PIXEL_SIZE = sizeof(GLfloat);
private:
// where and how to render
scigl_render::CvCamera camera;
scigl_render::Shader depth_shader;
scigl_render::Model model;
};
} // namespace scigl_render
\ No newline at end of file
#pragma once
#include <cstddef>
#include <utility>
namespace scigl_render
{
/**
* Render different views to a rasterized texture. This class is double buffer
* enabled.
*/
class Rasterizer
{
public:
/**
* Defines a header that is compatible to the OpenCV Mat_<float> constructor.
*/
struct ImageHeader
{
/** height of the image */
size_t rows;
/** width of the image */
size_t columns;
/** points to the first pixel of the image in the texture */
void *data;
/** size in bytes of one row in the image */
size_t step;
};
/**
* Initialize the rasterizer with 2D dimensions. Use calc_min_raster to
* determine the minimal dimensions for a given number of views.
* \param width the width of one view
* \param height the height of one view
* \param views_per_row the number of views in one row
* \param views_per_column the number of views in one column
* \param internal_format internal OpenGl texture format
*/
Rasterizer(size_t width, size_t height, size_t views_per_row,
size_t views_per_column);
/** activate a view by its 2D coordinates */
void activate_view(size_t row, size_t column);
/** as if the rows were concatenated */
void activate_view(size_t view);
/** activate the whole texture view, for example when clearing it */
void activate_all();
/**
* Minimal raster size for the given number of views
* \param n_views total number of views to render, must be greater than 0
* \param width of the observation image
* \param height of the observation image
* \param max_buffer_size the maximum dimensions of the buffer (e.g. RBO)
* \retuns views per row, views per column. Both 0 if the views do not fit
* into the buffer.
*/
static std::pair<size_t, size_t> calc_min_raster(
size_t n_views, size_t width, size_t height, size_t max_buffer_size);
/**
* Create metadata to read one view as image from the texture of all views.
* \param row of the view
* \param column of the view
* \param data pointer to the full texture
* \param pixel_size size of one pixel in bytes (sizeof(type) * n_channels)
*/
ImageHeader get_view_image(size_t row, size_t column, void *data,
size_t pixel_size) const;
/**
* Create metadata to read one view as image from the texture of all views.
* \param view get the image for this view
* \param data pointer to the full texture
* \param pixel_size size of one pixel in bytes (sizeof(type) * n_channels)
*/
ImageHeader get_view_image(size_t view, void *data,
size_t pixel_size) const;
size_t get_views_per_row() const;
size_t get_views_per_column() const;
private:
// dimensions of the observation
size_t width, height;
// for the whole texture precalculated
size_t views_per_row, views_per_column;
size_t texture_width, texture_height;
/**
* Calculates row and column of the view
*/
std::pair<size_t, size_t> view_position(size_t view) const;
/**
* Calculates x and y coordinates of the row and column
* \returns x,y
*/
std::pair<size_t, size_t> view_xy(size_t row, size_t column) const;
};
} // namespace scigl_render
#include <scigl_render/check_gl_error.hpp>
#include <scigl_render/example/example_render.hpp>
#include <scigl_render/example/depth_offscreen_render.hpp>
#include <scigl_render/render/offscreen_render.hpp>
namespace scigl_render
{
// I know there is a lot of configuration but it is intendet to be flexible
ExampleRender::ExampleRender(
DepthOffscreenRender::DepthOffscreenRender(
std::shared_ptr<GLContext> context,
Shader shader,
GLenum tex_format, GLenum tex_type, GLint tex_internal_format,
size_t pixel_size)
: texture_format(tex_format),
......@@ -23,16 +22,15 @@ ExampleRender::ExampleRender(
gl_context->get_height(),
tex_internal_format),
image_buffer(gl_context->get_width() * gl_context->get_height() *
pixel_size),
scene_shader(std::move(shader))
pixel_size)
{
// Configure the global rendering settings
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
check_gl_error("example render created");
}
void ExampleRender::next_frame(const CvCamera &camera, const Model &model,
const DiffuseLight &light)
void DepthOffscreenRender::next_frame(
std::shared_ptr<DepthSimulator> depth_simulator,
const CartesianPose &model_pose,
const CartesianPose &camera_pose)
{
using namespace std::placeholders;
check_gl_error("next frame begin");
......@@ -40,10 +38,8 @@ void ExampleRender::next_frame(const CvCamera &camera, const Model &model,
offscreen_render.clear_fbo();
offscreen_render.activate_fbo();
check_gl_error("activated fbo");
glEnable(GL_DEPTH_TEST);
camera.set_in_shader(scene_shader);
light.set_in_shader(scene_shader);
model.draw(scene_shader);
depth_simulator->render_pose(model_pose.to_quaternion_pose(),
camera_pose.to_quaternion_pose());
offscreen_render.deactivate_fbo();
// read asynchronously using the pbos
offscreen_render.start_read(texture_format, texture_type);
......@@ -56,7 +52,7 @@ void ExampleRender::next_frame(const CvCamera &camera, const Model &model,
check_gl_error("end synchronous reading");
}
void ExampleRender::display_data(const void *data)
void DepthOffscreenRender::display_data(const void *data)
{
// Test copying the data, buffer_size is in bytes
memcpy(image_buffer.data(), data, image_buffer.size());
......@@ -69,7 +65,7 @@ void ExampleRender::display_data(const void *data)
glfwSwapBuffers(gl_context->get_window());
}
void ExampleRender::resize_buffers()
void DepthOffscreenRender::resize_buffers()
{
offscreen_render = scigl_render::OffscreenRender(
gl_context->get_width(),
......
......@@ -3,15 +3,15 @@
#include <iostream>
#include <scigl_render/check_gl_error.hpp>
#include <scigl_render/gl_context.hpp>
#include <scigl_render/example/example_render.hpp>
#include <scigl_render/example/depth_offscreen_render.hpp>
#include <scigl_render/render/depth_simulator.hpp>
#include <scigl_render/scene/cv_camera.hpp>
#include <scigl_render/scene/diffuse_light.hpp>
#include <scigl_render/shader/shader_builder.hpp>
// forward declare callbacks
// get mouse and keyboard inputs
void process_input(GLFWwindow *window, scigl_render::CartesianPose &camera_pose,
const scigl_render::CvCamera &camera);
void process_input(GLFWwindow *window,
scigl_render::CartesianPose &camera_pose);
// Debug printing
std::ostream &operator<<(std::ostream &out, const glm::mat4 &mat)
......@@ -42,20 +42,8 @@ int main(int argc, char *argv[])
std::shared_ptr<GLContext> context =
std::make_shared<GLContext>(true, false, WIDTH, HEIGHT);
check_gl_error("Context created");
// build the shader program
const std::string vs_source =
#include <scigl_render/shader/simple.vs>
"";
const std::string fs_source =
#include <scigl_render/shader/depth.fs>
"";
ShaderBuilder shader_builder;
shader_builder.attach_vertex_shader(vs_source);
shader_builder.attach_fragment_shader(fs_source);
auto shader = shader_builder.build();
check_gl_error("Built depth shader");
ExampleRender render(context, shader,
GL_RED, GL_FLOAT, GL_R32F, sizeof(float));
DepthOffscreenRender render(context, GL_RED, GL_FLOAT, GL_R32F,
sizeof(float));
// Intrinsics of my shitty webcam
CameraIntrinsics camera_intrinsics;
camera_intrinsics.width = 640;
......@@ -73,19 +61,18 @@ int main(int argc, char *argv[])
0, 0, 0};
std::copy(std::begin(dist_coeffs), std::end(dist_coeffs),
std::begin(camera_intrinsics.dist_coeffs));
CvCamera camera(camera_intrinsics);
// create the depth simulator
auto depth_simulator = std::make_shared<DepthSimulator>(
CvCamera(camera_intrinsics), Model(argv[1]));
check_gl_error("Built depth shader");
// Test if Cartesian -> Quaternion works
CartesianPose camera_pose = {glm::vec3(0, 0, 0), glm::vec3(0, 0, 0)};
camera.pose = camera_pose.to_quaternion_pose();
Model model(argv[1]);
model.pose.position = glm::vec3(0, 0, 1);
DiffuseLight light;
CartesianPose camera_pose(glm::vec3(0, 0, 0), glm::vec3(0, 0, 0));
CartesianPose model_pose(glm::vec3(0, 0, 1), glm::vec3(0, 0, 0));
// main loop
while (!glfwWindowShouldClose(context->get_window()))
{
process_input(context->get_window(), camera_pose, camera);
camera.pose = camera_pose.to_quaternion_pose();
render.next_frame(camera, model, light);
process_input(context->get_window(), camera_pose);
render.next_frame(depth_simulator, model_pose, camera_pose);
glfwPollEvents();
}
// Finally release the context
......@@ -94,8 +81,7 @@ int main(int argc, char *argv[])
}
void process_input(GLFWwindow *window,
scigl_render::CartesianPose &camera_pose,
const scigl_render::CvCamera &camera)
scigl_render::CartesianPose &camera_pose)
{
// exit
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
......@@ -103,7 +89,7 @@ void process_input(GLFWwindow *window,
glfwSetWindowShouldClose(window, true);
}
// movement
float cameraSpeed = 0.01;
float cameraSpeed = 0.001;
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
{
camera_pose.position.y += cameraSpeed;
......@@ -152,10 +138,4 @@ void process_input(GLFWwindow *window,
{
camera_pose.orientation.z += cameraSpeed;
}
if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS)
{
std::cout << "camera info\n\n";
std::cout << camera.get_projection_matrix() << "\n\n";
std::cout << camera.get_view_matrix() << "\n\n";
}
}
......@@ -2,7 +2,6 @@
#include <stdexcept>
#include <iostream>
#include <scigl_render/gl_context.hpp>
#include <scigl_render/example/example_render.hpp>
#include <scigl_render/render/onscreen_render.hpp>
#include <scigl_render/scene/cv_camera.hpp>
#include <scigl_render/scene/diffuse_light.hpp>
......@@ -46,10 +45,10 @@ int main(int argc, char *argv[])
std::make_shared<GLContext>(true, false, WIDTH, HEIGHT);
// build the shader program
const std::string vs_source =
#include <scigl_render/shader/distort.vs>
#include <scigl_render/shader/distort.vert>
"";
const std::string fs_source =
#include <scigl_render/shader/texture.fs>
#include <scigl_render/shader/texture.frag>
"";
ShaderBuilder shader_builder;
shader_builder.attach_vertex_shader(vs_source);
......@@ -122,7 +121,7 @@ void process_input(std::shared_ptr<scigl_render::GLContext> context,
glfwSetWindowShouldClose(window, true);
}
// movement
float cameraSpeed = 0.01;
float cameraSpeed = 0.001;
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
{
camera_pose.position.y += cameraSpeed;
......
#include <scigl_render/render/depth_simulator.hpp>
#include <scigl_render/check_gl_error.hpp>
#include <scigl_render/shader/shader_builder.hpp>
namespace scigl_render
{
DepthSimulator::DepthSimulator(scigl_render::CvCamera camera,
scigl_render::Model model)
: camera(std::move(camera)),
model(std::move(model))
{
const std::string vs_source =
#include <scigl_render/shader/simple.vert>
"";
const std::string fs_source =
#include <scigl_render/shader/depth.frag>
"";
scigl_render::ShaderBuilder shader_builder;
shader_builder.attach_vertex_shader(vs_source);
shader_builder.attach_fragment_shader(fs_source);
depth_shader = shader_builder.build();
scigl_render::check_gl_error("depth simulator created");
}
int DepthSimulator::get_width()
{
return camera.get_intrinsics().width;
}
int DepthSimulator::get_height()
{
return camera.get_intrinsics().height;
}
void DepthSimulator::render_pose(const QuaternionPose &object_pose,
const QuaternionPose &camera_pose)
{
glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
glEnable(GL_DEPTH_TEST);
camera.pose = camera_pose;
camera.set_in_shader(depth_shader);
model.pose = object_pose;
model.draw(depth_shader);
}
} // namespace scigl_render
\ No newline at end of file
#include <GL/gl3w.h>
#include <scigl_render/render/rasterizer.hpp>
#include <sstream>
namespace scigl_render
{
Rasterizer::Rasterizer(size_t width, size_t height, size_t views_per_row,
size_t views_per_column)
: width(width), height(height),
views_per_row(views_per_row), views_per_column(views_per_column)
{
// create the offscreen render object
texture_width = width * views_per_row;
texture_height = width * views_per_column;
}
void Rasterizer::activate_view(size_t row, size_t column)
{
auto xy = view_xy(row, column);
glScissor(xy.first, xy.second, width, height);
glViewport(xy.first, xy.second, width, height);
}
void Rasterizer::activate_view(size_t view)
{
auto position = view_position(view);
size_t row = position.first;
size_t column = position.second;
activate_view(position.first, position.second);
}
void Rasterizer::activate_all()
{
glScissor(0, 0, texture_width, texture_height);
glViewport(0, 0, texture_width, texture_height);
}
std::pair<size_t, size_t> Rasterizer::calc_min_raster(
size_t n_views, size_t width, size_t height, size_t max_buffer_size)
{
// determine maximum number of views
size_t max_per_row = max_buffer_size / width;
size_t max_per_column = max_buffer_size / height;
if (n_views <= 0 || n_views > max_per_row * max_per_column)
{
return std::pair<size_t, size_t>(0, 0);
}
// minimum needed views per column and row (ceil int division)
// https://stackoverflow.com/questions/2745074/fast-ceiling-of-an-integer-division-in-c-c
size_t min_per_column = 1 + ((n_views - 1) / max_per_row);
size_t min_per_row = 1 + ((n_views - 1) / min_per_column);
return std::pair<size_t, size_t>(min_per_row, min_per_column);
}
size_t Rasterizer::get_views_per_row() const
{
return views_per_row;
}
size_t Rasterizer::get_views_per_column() const
{
return views_per_column;
}
Rasterizer::ImageHeader Rasterizer::get_view_image(
size_t row, size_t column, void *data, size_t pixel_size) const
{
auto xy = view_xy(row, column);
// all the rows above and the columns in front
ImageHeader header;
header.data = data + (xy.second * texture_width + xy.first) * pixel_size;
header.columns = width;
header.rows = height;
header.step = texture_width * pixel_size;
return header;
}
Rasterizer::ImageHeader Rasterizer::get_view_image(
size_t view, void *data, size_t pixel_size) const
{
auto pos = view_position(view);
return get_view_image(pos.first, pos.second, data, pixel_size);
}
std::pair<size_t, size_t> Rasterizer::view_position(size_t view) const
{
if (view > views_per_row * views_per_column)
{
std::stringstream error_stream;
error_stream << "view number exceeds the raster size "
<< view << " > "
<< views_per_row * views_per_column;
throw std::invalid_argument(error_stream.str());
}
size_t row = view / views_per_row;
size_t column = view % views_per_row;
return std::pair<size_t, size_t>(row, column);
}