Commit 840720ec authored by Tim Übelhör's avatar Tim Übelhör

More flexibel ShaderBuilder.

parent ceda353e
install
build
log
*.blend1
\ No newline at end of file
*.blend1
dna.txt
\ No newline at end of file
......@@ -4,13 +4,6 @@
// Weitere Informationen finden Sie unter https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python: Terminal (integrated)",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal"
},
{
"name": "scigl_viewer",
"type": "cppdbg",
......@@ -29,6 +22,25 @@
"ignoreFailures": true
}
]
},
{
"name": "scigl_depth_viewer",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/bin/scigl_depth_viewer",
"args": ["${workspaceFolder}/model/monkey.blend"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": true,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}
\ No newline at end of file
......@@ -60,7 +60,8 @@
"iomanip": "cpp",
"optional": "cpp",
"string_view": "cpp",
"*.fs": "cpp"
"*.fs": "cpp",
"*.vs": "cpp"
},
"python.autoComplete.extraPaths": [
"/opt/ros/kinetic/lib/python2.7/dist-packages"
......
......@@ -33,10 +33,9 @@ target_sources(scigl_render PRIVATE
src/scene/diffuse_light.cpp
src/scene/mesh.cpp
src/scene/model.cpp
src/shader/depth_shader.cpp
src/shader/shader.cpp
src/shader/single_color_shader.cpp
src/shader/single_texture_shader.cpp)
src/shader/shader_builder.cpp
src/shader/single_color_shader.cpp)
target_include_directories(scigl_render PUBLIC include)
target_link_libraries(scigl_render ${CONAN_LIBS})
......
R""(
#version 330 core
in float depth;
out float positive_depth;
void main()
{
// since we are looking down the negative axis
positive_depth = -depth;
})""
\ No newline at end of file
#pragma once
#include <scigl_render/shader/shader.hpp>
namespace scigl_render
{
/*!
Returns the source code for shaders that render the absolute depth
of a pixel.
*/
class DepthShader
{
public:
/*!
Creates the shader program from the sources.
*/
static Shader create_shader();
private:
/*!
Returns the vertex shader source code.
*/
static std::string get_vertex_source();
/*!
Returns the geometry shader source code. Since this shader is optional,
returning an empty string is valid.
*/
static std::string get_geometry_source();
/*!
Returns the fragment shader source code.
*/
static std::string get_fragment_source();
};
} // namespace scigl_render
\ No newline at end of file
......@@ -9,9 +9,10 @@ uniform mat4 model_matrix;
uniform mat4 projection_matrix;
uniform mat4 view_matrix;
out vec3 world_position;
out float depth;
out vec3 normal;
out vec2 texture_coordinate;
out vec3 world_position;
// distort the real world vertices using the rational model
vec4 distort(vec4 view_pos)
......@@ -50,6 +51,7 @@ void main()
// distortion in view coordinates
vec4 view_pos = view_matrix * vec4(world_position, 1.0);
vec4 dist_pos = distort(view_pos);
depth = view_pos.z;
gl_Position = projection_matrix * dist_pos;
}
)""
\ No newline at end of file
R""(
#version 330 core
layout(points) in;
layout(triangle_strip, max_vertices = 4) out;
out vec2 texture_coordinate;
// Creates a fullscreen quad with z-Coordinate 1.0, so stuff can be rendered in
// front of the texture :). Memberberries: looking down z the negative axis.
void main()
{
gl_Position = vec4(1.0, 1.0, 1.0, 1.0);
texture_coordinate = vec2(1.0, 1.0);
EmitVertex();
gl_Position = vec4(-1.0, 1.0, 1.0, 1.0);
texture_coordinate = vec2(0.0, 1.0);
EmitVertex();
gl_Position = vec4(1.0, -1.0, 1.0, 1.0);
texture_coordinate = vec2(1.0, 0.0);
EmitVertex();
gl_Position = vec4(-1.0, -1.0, 1.0, 1.0);
texture_coordinate = vec2(0.0, 0.0);
EmitVertex();
EndPrimitive();
})""
\ No newline at end of file
......@@ -11,9 +11,11 @@ Wraps a shader program for simplified compilation and usage.
class Shader
{
public:
/*! Compiles the shader program from the given sources. */
Shader(const std::string &vertex_source, const std::string &geometry_source,
const std::string &fragment_source);
/*! Use set_program_id */
Shader();
/*! For convenience. Alternative: default constructor + set_program_id */
Shader(GLuint program_id);
/*! Activate this shader program. */
void activate() const;
......@@ -21,6 +23,9 @@ public:
/*! Deactivate this shader program. */
void deactivate() const;
/*! Set the id of the underlying shader program */
void set_program_id(GLuint id);
/*! Set the uniform variable value in the shader program. */
void setBool(const std::string &name, bool value) const;
......@@ -66,31 +71,5 @@ private:
Reference to this shader program.
*/
GLuint program_id;
/*!
Compiles the shader source code.
\param source the buffered source code
\param shader_type for example GL_VERTEX_SHADER & GL_FRAGMENT_SHADER
\return the reference id of the compiled shader object
*/
GLuint compile_shader(const std::string &source, GLenum shader_type);
/*!
Reads the shader source file into the string. Throws on error.
\param path the path of the shader source file
*/
std::string read_shader_file(const std::string &path);
/*!
Logs the compilation error info.
\param shader the reference id of the shader
\param source the source code of the shader
*/
void checkShaderCompileErrors(GLuint shader, const std::string &source);
/*!
Logs the compilation error info.
*/
void checkProgramCompileErrors(GLuint program);
};
} // namespace scigl_render
#pragma once
#include <GL/gl3w.h>
#include <scigl_render/shader/shader.hpp>
#include <string>
namespace scigl_render
{
/*!
Builds a shader program
*/
class ShaderBuilder
{
public:
ShaderBuilder();
/*!
Attach a vertex shader to the program.
*/
void attach_vertex_shader(const std::string &vs_source);
/*!
Attach a fragment shader to the program.
*/
void attach_fragment_shader(const std::string &fs_source);
/*!
Attach a geometry shader to the program.
*/
void attach_geometry_shader(const std::string &gs_source);
/*!
Attach tessellation control and evaluation shaders to the program
\param tcs_source the source code of the tessellation control shader
\param tes_source the source code of the tessellation evaluation shader
*/
void attach_tessellation_shader(const std::string &tcs_source,
const std::string &tes_source);
/*!
Attach a compute shader to the program.
*/
void attach_compute_shader(const std::string &cs_source);
/*!
Builds the shader program.
*/
Shader build();
private:
GLuint vertex_shader, fragment_shader, geometry_shader, tc_shader, te_shader,
compute_shader;
/*!
Compiles the shader source code.
\param source the buffered source code
\param shader_type for example GL_VERTEX_SHADER & GL_FRAGMENT_SHADER
\return the reference id of the compiled shader object
*/
GLuint compile_shader(const std::string &source, GLenum shader_type);
/*!
Logs the compilation error info.
\param shader the reference id of the shader
\param source the source code of the shader
*/
void checkShaderCompileErrors(GLuint shader, const std::string &source);
/*!
Logs the compilation error info.
*/
void checkProgramCompileErrors(GLuint program);
};
} // namespace scigl_render
\ No newline at end of file
#include <scigl_render/shader/depth_shader.hpp>
namespace scigl_render
{
Shader DepthShader::create_shader()
{
return Shader(get_vertex_source(), get_geometry_source(),
get_fragment_source());
}
std::string DepthShader::get_vertex_source()
{
return R"(#version 330 core
R""(
#version 330 core
layout (location = 0) in vec3 position;
uniform mat4 model_matrix;
uniform mat4 view_matrix;
uniform mat4 projection_matrix;
out float depth;
// simple linear transformation into projection space
void main()
{
vec4 local_pos = vec4(position, 1.0);
vec4 view_pos = view_matrix * model_matrix * local_pos;
depth = view_pos.z;
// needed for z testing
gl_Position = projection_matrix * view_pos;
})";
}
std::string DepthShader::get_geometry_source()
{
return "";
}
std::string DepthShader::get_fragment_source()
{
return R"(#version 330 core
in float depth;
out float positive_depth;
void main()
{
// since we are looking down the negative axis
positive_depth = -depth;
})";
}
} // namespace scigl_render
\ No newline at end of file
})""
\ No newline at end of file
#pragma once
#include <scigl_render/shader/shader.hpp>
namespace scigl_render
{
/*!
This shader renders a model that has a single texture.
Diffuse light reflection is applied.
*/
class SingleTextureShader
{
public:
static Shader create_shader();
};
} // namespace scigl_render
\ No newline at end of file
#include <glm/glm.hpp>
#include <stdexcept>
#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/scene/cv_camera.hpp>
#include <scigl_render/scene/diffuse_light.hpp>
#include <scigl_render/shader/depth_shader.hpp>
#include <scigl_render/shader/shader_builder.hpp>
// forward declare callbacks
// get mouse and keyboard inputs
......@@ -29,8 +30,8 @@ Provide the model as argument via command line.
int main(int argc, char *argv[])
{
// Some default parameters
const int WIDTH = 1024;
const int HEIGHT = 720;
const int WIDTH = 640;
const int HEIGHT = 480;
using namespace scigl_render;
if (argc < 2)
{
......@@ -40,7 +41,20 @@ int main(int argc, char *argv[])
// Setup renderer creates context
std::shared_ptr<GLContext> context =
std::make_shared<GLContext>(true, false, WIDTH, HEIGHT);
ExampleRender render(context, DepthShader::create_shader(),
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));
// Intrinsics of my shitty webcam
CameraIntrinsics camera_intrinsics;
......@@ -50,10 +64,6 @@ int main(int argc, char *argv[])
camera_intrinsics.c_y = 310;
camera_intrinsics.f_x = 511;
camera_intrinsics.f_y = 513;
// camera_intrinsics.f_x = 1000;
// camera_intrinsics.f_y = 500;
// camera_intrinsics.c_x = 320;
// camera_intrinsics.c_y = 240;
CvCamera camera(camera_intrinsics);
// Test if Cartesian -> Quaternion works
CartesianPose camera_pose = {glm::vec3(0, 0, 0), glm::vec3(0, 0, 0)};
......@@ -61,8 +71,6 @@ int main(int argc, char *argv[])
Model model(argv[1]);
model.pose.position = glm::vec3(0, 0, 1);
DiffuseLight light;
light.position = glm::vec3(2, 0, 0);
light.color = glm::vec3(0.36, 0.4, 0.3);
// main loop
while (!glfwWindowShouldClose(context->get_window()))
{
......
......@@ -6,8 +6,8 @@
#include <scigl_render/render/onscreen_render.hpp>
#include <scigl_render/scene/cv_camera.hpp>
#include <scigl_render/scene/diffuse_light.hpp>
#include <scigl_render/shader/shader_builder.hpp>
#include <scigl_render/shader/single_color_shader.hpp>
#include <scigl_render/shader/single_texture_shader.hpp>
#include <thread>
// forward declare callbacks
......@@ -44,9 +44,18 @@ int main(int argc, char *argv[])
// Setup renderer creates context
std::shared_ptr<GLContext> context =
std::make_shared<GLContext>(true, false, WIDTH, HEIGHT);
auto shader = SingleTextureShader::create_shader();
// build the shader program
const std::string vs_source =
#include <scigl_render/shader/distort.vs>
"";
const std::string fs_source =
#include <scigl_render/shader/texture.fs>
"";
ShaderBuilder shader_builder;
shader_builder.attach_vertex_shader(vs_source);
shader_builder.attach_fragment_shader(fs_source);
auto shader = shader_builder.build();
// auto shader = SingleColorShader::create_shader(0.75, 0, 1, 0);
// ExampleRender render(context, shader, GL_BGR, GL_UNSIGNED_BYTE, GL_RGB8, 3);
OnscreenRender render(shader);
// Intrinsics of my shitty webcam
CameraIntrinsics camera_intrinsics = {};
......
#include <algorithm>
#include <scigl_render/check_gl_error.hpp>
#include <scigl_render/render/offscreen_render.hpp>
#include <stdexcept>
......@@ -18,6 +19,7 @@ OffscreenRender::OffscreenRender(int width, int height, size_t pixel_size,
GL_DYNAMIC_READ);
}
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
check_gl_error("OffscreenRender created");
}
void OffscreenRender::activate_fbo()
......
#include <scigl_render/check_gl_error.hpp>
#include <scigl_render/render/texture_fullscreen_render.hpp>
#include <scigl_render/shader/shader_builder.hpp>
namespace scigl_render
{
/*!
The geometry shader creates the vertices. Nevertheless a vertex shader MUST be
provided so it is simply empty.
*/
const std::string vertex_source = R"(
#version 330 core
void main()
{
})";
/*!
Creates a fullscreen quad with z-Coordinate 1.0, so stuff can be rendered in
front of the texture :). Memberberries: looking down z the negative axis.
*/
const std::string geometry_source = R"(
#version 330 core
layout(points) in;
layout(triangle_strip, max_vertices = 4) out;
out vec2 texture_coordinate;
void main()
{
gl_Position = vec4(1.0, 1.0, 1.0, 1.0);
texture_coordinate = vec2(1.0, 1.0);
EmitVertex();
gl_Position = vec4(-1.0, 1.0, 1.0, 1.0);
texture_coordinate = vec2(0.0, 1.0);
EmitVertex();
gl_Position = vec4(1.0, -1.0, 1.0, 1.0);
texture_coordinate = vec2(1.0, 0.0);
EmitVertex();
gl_Position = vec4(-1.0, -1.0, 1.0, 1.0);
texture_coordinate = vec2(0.0, 0.0);
EmitVertex();
EndPrimitive();
})";
/*!
Renderesthe texture
*/
const std::string geometry_source =
#include <scigl_render/shader/fullscreen_quad.gs>
"";
const std::string fragment_source = R"(
#version 330 core
in vec2 texture_coordinate;
......@@ -56,9 +26,13 @@ void main()
TextureFullscreenRender::TextureFullscreenRender(
int width, int height, GLint internal_format)
: width(width), height(height),
shader(vertex_source, geometry_source, fragment_source)
: width(width), height(height)
{
ShaderBuilder shader_builder;
shader_builder.attach_vertex_shader(vertex_source);
shader_builder.attach_geometry_shader(geometry_source);
shader_builder.attach_fragment_shader(fragment_source);
shader = shader_builder.build();
// create the texture buffer
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
......@@ -68,6 +42,7 @@ TextureFullscreenRender::TextureFullscreenRender(
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindVertexArray(0);
check_gl_error("TextureFullscreenRender created");
}
void TextureFullscreenRender::draw(
......
......@@ -3,71 +3,14 @@
namespace scigl_render
{
Shader::Shader(const std::string &vertex_source, const std::string &geometry_source,
const std::string &fragment_source)
{
GLuint vertex_shader = compile_shader(vertex_source, GL_VERTEX_SHADER);
GLuint geometry_shader = compile_shader(geometry_source, GL_GEOMETRY_SHADER);
GLuint fragment_shader = compile_shader(fragment_source, GL_FRAGMENT_SHADER);
// shader program
program_id = glCreateProgram();
glAttachShader(program_id, vertex_shader);
if (geometry_shader != 0)
{
glAttachShader(program_id, geometry_shader);
}
glAttachShader(program_id, fragment_shader);
glLinkProgram(program_id);
checkProgramCompileErrors(program_id);
// Delete unused resources
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
}
GLuint Shader::compile_shader(const std::string &source, GLenum shader_type)
{
if (!source.empty())
{
GLuint shader_id = glCreateShader(shader_type);
// Cast string to const GLchar* since OpenGL expects const GLchar**
const GLchar *gl_source = source.c_str();
glShaderSource(shader_id, 1, &gl_source, NULL);
glCompileShader(shader_id);
checkShaderCompileErrors(shader_id, source);
return shader_id;
}
else
{
return 0;
}
}
void Shader::checkShaderCompileErrors(GLuint shader, const std::string &source)
{
GLint success;
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success)
{
GLchar infoLog[1024];
glGetShaderInfoLog(shader, 1024, NULL, infoLog);
throw std::runtime_error("Shader compilation error"
"\nShaderInfoLog: " +
std::string(infoLog) +
"\nShader source:\n" + source);
}
}
void Shader::checkProgramCompileErrors(GLuint program)
{
GLint success;
glGetProgramiv(program, GL_LINK_STATUS, &success);
if (!success)
{
GLchar infoLog[1024];
glGetProgramInfoLog(program, 1024, NULL, infoLog);
throw std::runtime_error("Program linking error\nInfoLog: " +
std::string(infoLog));
}
Shader::Shader()
{
set_program_id(0);
}
Shader::Shader(GLuint program_id)
{
set_program_id(program_id);
}
void Shader::activate() const
......@@ -80,6 +23,11 @@ void Shader::deactivate() const
glUseProgram(GL_ZERO);
}
void Shader::set_program_id(GLuint id)
{
program_id = id;
}
void Shader::setBool(const std::string &name, bool value) const
{
glUniform1i(glGetUniformLocation(program_id, name.c_str()), (int)value);
......