Commit 03dda6ed authored by Tim Übelhör's avatar Tim Übelhör

Read subimage from framebuffer.

Get uniform variables from shaders.
parent bbdd6d5c
......@@ -2,3 +2,4 @@
*.3ds filter=lfs diff=lfs merge=lfs -text
*.stl filter=lfs diff=lfs merge=lfs -text
*.dae filter=lfs diff=lfs merge=lfs -text
*.ply filter=lfs diff=lfs merge=lfs -text
......@@ -2,4 +2,5 @@ install
build
log
*.blend1
dna.txt
\ No newline at end of file
dna.txt
.vscode/ipch
\ No newline at end of file
......@@ -3,7 +3,7 @@ from conans import ConanFile, CMake
class SciglRenderConan(ConanFile):
name = "scigl_render"
version = "0.5"
version = "0.6"
license = "MIT"
url = "https://git.rwth-aachen.de/robo_guide/scigl_render"
description = ("Library to simplify rendering objects via OpenGL."
......
......@@ -3,19 +3,17 @@
#include <memory>
#include <scigl_render/buffer/texture2d.hpp>
namespace scigl_render
{
namespace scigl_render {
/*!
Wraps a texture frame buffer that can be rendered to offscreen.
Has a color and depth-stencil attachement.
has a color and depth-stencil attachement.
The resources are managed RAII style so the copy constructor is disables; use
a shared_ptr to share the isntance.
*/
class FrameBuffer
{
public:
class FrameBuffer {
public:
/*!
Creates the framebuffer with a rednerbuffer attachment to render to.
Creates the framebuffer with a texture attachment to render to.
\throws a runtime_error on failure
\param texture the texture to render to
*/
......@@ -47,7 +45,18 @@ public:
/** gets the maximum rbo size */
static int get_max_size();
private:
/**
* Reads the image from the underlying texture
* \param pixels stores the values in this adress
* \param x window x coordinates of the first pixel
* \param y window y coordinates of the first pixel
* \param width horizontal dimension of the image
* \param height vertical dimension of the image
*/
void read_image(GLvoid *pixels, GLint x, GLint y, GLsizei width,
GLsizei height) const;
private:
// framebuffer object to render the texture into
GLuint fbo;
// texture for renderng colors, can be sampled from
......@@ -55,4 +64,4 @@ private:
// renderbuffer object for the depth testing, does not allow sampling
GLuint depth_stencil_rbo;
};
} // namespace scigl_render
\ No newline at end of file
} // namespace scigl_render
\ No newline at end of file
#pragma once
#include <GL/gl3w.h>
namespace scigl_render
{
namespace scigl_render {
/** RAII style creation of a 2D texture */
class Texture2D
{
public:
Texture2D(GLsizei width, GLsizei height,
GLenum format, GLenum internal_format, GLenum type);
class Texture2D {
public:
Texture2D(GLsizei width, GLsizei height, GLenum format,
GLenum internal_format, GLenum type);
Texture2D(const Texture2D &) = delete;
~Texture2D();
/** activates texture_n for use in shaders */
static void activate(GLenum texture_n);
/**
* bind this texture to an image unit for imageLoad
/**
* bind this texture to an image unit for imageLoad
* \param unit the binding unit
* \param access GL_READ_ONLY, GL_WRITE_ONLY, or GL_READ_WRITE
*/
......@@ -28,14 +26,14 @@ public:
/** unbinds this texture */
void unbind() const;
/**
/**
* Reads the texture in the pixels pointer.
* Note: If a non-zero named buffer object is bound to the
* GL_PIXEL_PACK_BUFFER target (see glBindBuffer) while a texture image is
* Note: If a non-zero named buffer object is bound to the
* GL_PIXEL_PACK_BUFFER target (see glBindBuffer) while a texture image is
* specified, pixels is treated as a byte offset into the buffer object's
* data store.
*/
void read_image(GLvoid *pixels);
void read_image(GLvoid *pixels) const;
/** upload an image to the texture. */
void store_image(const GLvoid *image) const;
......@@ -47,9 +45,9 @@ public:
GLenum get_internal_format() const;
GLenum get_type() const;
private:
private:
const GLsizei width, height;
const GLenum format, internal_format, type;
GLuint texture;
};
} // namespace scigl_render
\ No newline at end of file
} // namespace scigl_render
\ No newline at end of file
......@@ -2,21 +2,18 @@
#include <cstddef>
#include <utility>
namespace scigl_render
{
/**
namespace scigl_render {
/**
* Render different views to a rasterized texture. This class is double buffer
* enabled.
*/
class Rasterizer
{
public:
class Rasterizer {
public:
/**
* Defines a header that is compatible to the OpenCV Mat_<T> constructor.
*/
template <typename T>
struct ImageHeader
{
struct ImageHeader {
/** height of the image */
size_t rows;
/** width of the image */
......@@ -50,7 +47,7 @@ public:
/** activate the whole texture view, for example when clearing it */
void activate_all() const;
/**
/**
* 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
......@@ -59,8 +56,9 @@ public:
* \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);
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.
......@@ -71,8 +69,7 @@ public:
*/
template <typename T>
ImageHeader<T> get_image(size_t row, size_t column, void *data,
size_t channels) const
{
size_t channels) const {
auto xy = view_xy(row, column);
// all the rows above and the columns in front
ImageHeader<T> header;
......@@ -91,10 +88,8 @@ public:
* \param channels number of channels in the image
*/
template <typename T>
ImageHeader<T> get_image(size_t view, void *data,
size_t channels) const
{
auto pos = view_position(view);
ImageHeader<T> get_image(size_t view, void *data, size_t channels) const {
auto pos = view_row_column(view);
return get_image<T>(pos.first, pos.second, data, channels);
}
......@@ -102,14 +97,19 @@ public:
size_t get_views_per_column() const;
size_t get_view_width() const;
size_t get_view_height() const;
/** view width * view height */
size_t get_view_size() const;
size_t get_texture_width() const;
size_t get_texture_height() const;
/** position of the first pixel of the image in the texture */
std::pair<size_t, size_t> get_view_xy(size_t view) const;
void set_views_per_row(size_t views_per_row);
void set_views_per_column(size_t views_per_column);
void set_view_width(size_t width);
void set_view_height(size_t height);
private:
private:
// dimensions of the observation
size_t width, height;
// for the whole texture precalculated
......@@ -119,7 +119,7 @@ private:
/**
* Calculates row and column of the view
*/
std::pair<size_t, size_t> view_position(size_t view) const;
std::pair<size_t, size_t> view_row_column(size_t view) const;
/**
* Calculates x and y coordinates of the row and column
......@@ -127,4 +127,4 @@ private:
*/
std::pair<size_t, size_t> view_xy(size_t row, size_t column) const;
};
} // namespace scigl_render
} // namespace scigl_render
......@@ -26,6 +26,18 @@ public:
/*! Set the id of the underlying shader program */
void set_program_id(GLuint id);
/*! Get the uniform variable value from the shader program. */
bool getBool(const std::string &name) const;
/*! Get the uniform variable value from the shader program. */
int getInt(const std::string &name) const;
/*! Get the uniform variable value from the shader program. */
uint32_t getUInt(const std::string &name) const;
/*! Get the uniform variable value from the shader program. */
float getFloat(const std::string &name) const;
/*! Set the uniform variable value in the shader program. */
void setBool(const std::string &name, bool value) const;
......
No preview for this file type
File added
File added
......@@ -2,7 +2,7 @@
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="2">
<name>scigl_render</name>
<version>0.5</version>
<version>0.6</version>
<description>
Library to simplify rendering objects via OpenGL. The intendet use case
is scientific (e.g. probabalistic filtering). It is not supposed to be a
......
#include <scigl_render/buffer/frame_buffer.hpp>
#include <stdexcept>
namespace scigl_render
{
namespace scigl_render {
FrameBuffer::FrameBuffer(std::shared_ptr<Texture2D> texture)
: color_tex(texture)
{
: color_tex(texture) {
// Create framebuffer with renderbuffer attachements
glGenFramebuffers(1, &fbo);
activate();
color_tex->bind();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, color_tex->get_raw(), 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
color_tex->get_raw(), 0);
color_tex->unbind();
glGenRenderbuffers(1, &depth_stencil_rbo);
glBindRenderbuffer(GL_RENDERBUFFER, depth_stencil_rbo);
glRenderbufferStorage(
GL_RENDERBUFFER, GL_DEPTH24_STENCIL8,
color_tex->get_width(), color_tex->get_height());
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8,
color_tex->get_width(), color_tex->get_height());
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, depth_stencil_rbo);
// Check framebuffer, will check rbo, too, since it is attached
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
throw std::runtime_error("Framebuffer is not completed");
}
deactivate();
}
FrameBuffer::~FrameBuffer()
{
FrameBuffer::~FrameBuffer() {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteRenderbuffers(1, &depth_stencil_rbo);
}
void FrameBuffer::activate() const
{
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
}
void FrameBuffer::activate() const { glBindFramebuffer(GL_FRAMEBUFFER, fbo); }
void FrameBuffer::deactivate() const
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void FrameBuffer::deactivate() const { glBindFramebuffer(GL_FRAMEBUFFER, 0); }
void FrameBuffer::clear(float color, float depth, int stencil) const
{
void FrameBuffer::clear(float color, float depth, int stencil) const {
activate();
glClearColor(color, color, color, 1);
glClearDepth(depth);
......@@ -55,15 +43,21 @@ void FrameBuffer::clear(float color, float depth, int stencil) const
deactivate();
}
std::shared_ptr<Texture2D> FrameBuffer::get_texture() const
{
std::shared_ptr<Texture2D> FrameBuffer::get_texture() const {
return color_tex;
}
int FrameBuffer::get_max_size()
{
int FrameBuffer::get_max_size() {
int max_rbo_size;
glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &max_rbo_size);
return max_rbo_size;
}
} // namespace scigl_render
\ No newline at end of file
void FrameBuffer::read_image(GLvoid *pixels, GLint x, GLint y, GLsizei width,
GLsizei height) const {
activate();
glReadPixels(x, y, width, height, color_tex->get_format(),
color_tex->get_type(), pixels);
deactivate();
}
} // namespace scigl_render
\ No newline at end of file
#include <scigl_render/buffer/texture2d.hpp>
namespace scigl_render
{
Texture2D::Texture2D(GLsizei width, GLsizei height,
GLenum format, GLenum internal_format, GLenum type)
: width(width), height(height),
format(format), internal_format(internal_format),
type(type)
{
namespace scigl_render {
Texture2D::Texture2D(GLsizei width, GLsizei height, GLenum format,
GLenum internal_format, GLenum type)
: width(width),
height(height),
format(format),
internal_format(internal_format),
type(type) {
glGenTextures(1, &texture);
bind();
glTexStorage2D(GL_TEXTURE_2D, 1, internal_format, width, height);
unbind();
}
Texture2D::~Texture2D()
{
glDeleteTextures(1, &texture);
}
Texture2D::~Texture2D() { glDeleteTextures(1, &texture); }
GLuint Texture2D::get_raw() const
{
return texture;
}
GLuint Texture2D::get_raw() const { return texture; }
GLsizei Texture2D::get_width() const
{
return width;
}
GLsizei Texture2D::get_height() const
{
return height;
}
GLenum Texture2D::get_format() const
{
return format;
}
GLenum Texture2D::get_internal_format() const
{
return internal_format;
}
GLenum Texture2D::get_type() const
{
return type;
}
GLsizei Texture2D::get_width() const { return width; }
GLsizei Texture2D::get_height() const { return height; }
GLenum Texture2D::get_format() const { return format; }
GLenum Texture2D::get_internal_format() const { return internal_format; }
GLenum Texture2D::get_type() const { return type; }
void Texture2D::activate(GLenum texture_n)
{
glActiveTexture(texture_n);
}
void Texture2D::activate(GLenum texture_n) { glActiveTexture(texture_n); }
void Texture2D::bind() const
{
glBindTexture(GL_TEXTURE_2D, texture);
}
void Texture2D::bind() const { glBindTexture(GL_TEXTURE_2D, texture); }
void Texture2D::bind_image_unit(GLuint unit, GLenum access) const
{
void Texture2D::bind_image_unit(GLuint unit, GLenum access) const {
glBindImageTexture(unit, texture, 0, GL_FALSE, 0, access, internal_format);
}
void Texture2D::unbind() const
{
glBindTexture(GL_TEXTURE_2D, 0);
}
void Texture2D::unbind() const { glBindTexture(GL_TEXTURE_2D, 0); }
void Texture2D::read_image(GLvoid *pixels)
{
void Texture2D::read_image(GLvoid *pixels) const {
bind();
glGetTexImage(GL_TEXTURE_2D, 0, format, type, pixels);
unbind();
}
void Texture2D::store_image(const GLvoid *image) const
{
void Texture2D::store_image(const GLvoid *image) const {
bind();
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, image);
unbind();
}
} // namespace scigl_render
} // namespace scigl_render
......@@ -2,50 +2,43 @@
#include <scigl_render/render/rasterizer.hpp>
#include <sstream>
namespace scigl_render
{
Rasterizer::Rasterizer()
{
}
namespace scigl_render {
Rasterizer::Rasterizer() {}
Rasterizer::Rasterizer(size_t width, size_t height, size_t views_per_row,
size_t views_per_column)
{
size_t views_per_column) {
set_view_width(width);
set_view_height(height);
set_views_per_row(views_per_row);
set_views_per_column(views_per_column);
}
void Rasterizer::activate_view(size_t row, size_t column) const
{
void Rasterizer::activate_view(size_t row, size_t column) const {
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) const
{
auto position = view_position(view);
void Rasterizer::activate_view(size_t view) const {
auto position = view_row_column(view);
size_t row = position.first;
size_t column = position.second;
activate_view(position.first, position.second);
}
void Rasterizer::activate_all() const
{
void Rasterizer::activate_all() const {
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)
{
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)
{
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)
......@@ -55,58 +48,40 @@ std::pair<size_t, size_t> Rasterizer::calc_min_raster(
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;
}
size_t Rasterizer::get_view_width() const
{
return width;
}
size_t Rasterizer::get_view_height() const
{
return height;
}
size_t Rasterizer::get_texture_width() const
{
return texture_width;
}
size_t Rasterizer::get_texture_height() const
{
return texture_height;
}
void Rasterizer::set_views_per_row(size_t views_per_row)
{
size_t Rasterizer::get_views_per_row() const { return views_per_row; }
size_t Rasterizer::get_views_per_column() const { return views_per_column; }
size_t Rasterizer::get_view_width() const { return width; }
size_t Rasterizer::get_view_height() const { return height; }
size_t Rasterizer::get_texture_width() const { return texture_width; }
size_t Rasterizer::get_texture_height() const { return texture_height; }
std::pair<size_t, size_t> Rasterizer::get_view_xy(size_t view) const {
auto row_column = view_row_column(view);
return view_xy(row_column.first, row_column.second);
}
size_t Rasterizer::get_view_size() const {
return get_view_width() * get_view_height();
}
void Rasterizer::set_views_per_row(size_t views_per_row) {
this->views_per_row = views_per_row;
texture_width = views_per_row * width;
}
void Rasterizer::set_views_per_column(size_t views_per_column)
{
void Rasterizer::set_views_per_column(size_t views_per_column) {
this->views_per_column = views_per_column;
texture_height = views_per_column * height;
}
void Rasterizer::set_view_width(size_t width)
{
void Rasterizer::set_view_width(size_t width) {
this->width = width;
texture_width = views_per_row * width;
}
void Rasterizer::set_view_height(size_t height)
{
void Rasterizer::set_view_height(size_t height) {
this->height = height;
texture_height = views_per_column * height;
}
std::pair<size_t, size_t> Rasterizer::view_position(size_t view) const
{
if (view > views_per_row * views_per_column)
{
std::pair<size_t, size_t> Rasterizer::view_row_column(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 << " > "
error_stream << "view number exceeds the raster size " << view << " > "
<< views_per_row * views_per_column;
throw std::invalid_argument(error_stream.str());
}
......@@ -115,8 +90,7 @@ std::pair<size_t, size_t> Rasterizer::view_position(size_t view) const
return std::pair<size_t, size_t>(row, column);
}
std::pair<size_t, size_t> Rasterizer::view_xy(size_t row, size_t column) const
{
std::pair<size_t, size_t> Rasterizer::view_xy(size_t row, size_t column) const {
return std::pair<size_t, size_t>(column * width, row * height);
}
} // namespace scigl_render
\ No newline at end of file
} // namespace scigl_render
\ No newline at end of file
#include <scigl_render/shader/shader.hpp>
#include <stdexcept>
namespace scigl_render
{
Shader::Shader()
{
set_program_id(0);
}
namespace scigl_render {
Shader::Shader() { set_program_id(0); }
Shader::Shader(GLuint program_id) { set_program_id(program_id); }
void Shader::activate() const { glUseProgram(program_id); }
Shader::Shader(GLuint program_id)
{
set_program_id(program_id);
void Shader::deactivate() const { glUseProgram(GL_ZERO); }