Commit 8e7a9ecf authored by Philip Trettner's avatar Philip Trettner

Added glow extras debugging library

parent 94f6d769
......@@ -26,6 +26,10 @@ target_link_libraries(glow-extras PUBLIC glow-extras-geometry)
add_subdirectory(pipeline)
target_link_libraries(glow-extras PUBLIC glow-extras-pipeline)
# Debug
add_subdirectory(debugging)
target_link_libraries(glow-extras PUBLIC glow-extras-debugging)
# Material shading library
add_subdirectory(material)
target_link_libraries(glow-extras PUBLIC glow-extras-material)
......
cmake_minimum_required(VERSION 3.0)
file(GLOB_RECURSE SOURCE_FILES "*.cc")
file(GLOB_RECURSE HEADER_FILES "*.hh")
file(GLOB_RECURSE SHADER_FILES "*.*sh")
add_library(glow-extras-debugging ${GLOW_LINK_TYPE} ${SOURCE_FILES} ${HEADER_FILES} ${SHADER_FILES})
target_include_directories(glow-extras-debugging PUBLIC ./)
target_compile_options(glow-extras-debugging PRIVATE ${GLOW_EXTRAS_DEF_OPTIONS})
target_link_libraries(glow-extras-debugging PUBLIC
glow
glow-extras-geometry
glow-extras-camera
glow-extras-pipeline
)
#include "DebugRenderer.hh"
#include <glm/ext.hpp>
#include <glow-extras/geometry/Cube.hh>
#include <glow-extras/geometry/Quad.hh>
#include <glow-extras/geometry/Line.hh>
#include <glow-extras/pipeline/RenderPass.hh>
#include <glow-extras/camera/FixedCamera.hh>
#include <glow/objects/Program.hh>
using namespace glow;
using namespace glow::debugging;
using namespace glow::pipeline;
DebugRenderer::DebugRenderer()
{
mQuad = geometry::Quad<PrimitiveVertex>().generate();
mCube = geometry::Cube<PrimitiveVertex>().generate();
mLine = geometry::Line<PrimitiveVertex>().generate();
mShaderOpaque = Program::createFromFiles({"glow-debugging/primitive.opaque.fsh", "glow-debugging/primitive.vsh"});
mShaderTransparent
= Program::createFromFiles({"glow-debugging/primitive.transparent.fsh", "glow-debugging/primitive.vsh"});
}
void DebugRenderer::clear()
{
mPrimitives.clear();
}
void DebugRenderer::renderPass(const pipeline::RenderPass& pass) const
{
switch (pass.type)
{
case RenderPassType::Opaque:
{
auto shader = mShaderOpaque->use();
shader.setUniform("uView", pass.camera->getViewMatrix());
shader.setUniform("uProj", pass.camera->getProjectionMatrix());
for (auto const& p : mPrimitives)
if (p.color.a >= 1.0)
{
shader.setUniform("uColor", p.color);
shader.setUniform("uModel", p.modelMatrix);
p.vao->bind().draw();
}
}
break;
case RenderPassType::Transparent:
{
auto shader = mShaderTransparent->use();
shader.setUniform("uView", pass.camera->getViewMatrix());
shader.setUniform("uProj", pass.camera->getProjectionMatrix());
for (auto const& p : mPrimitives)
if (p.color.a < 1.0)
{
shader.setUniform("uColor", p.color);
shader.setUniform("uModel", p.modelMatrix);
p.vao->bind().draw();
}
}
break;
default:
break;
}
}
void DebugRenderer::renderLine(glm::vec3 start, glm::vec3 end, glm::vec4 color)
{
auto m = translate(start) * glm::mat4(glm::mat3(end - start, glm::vec3(0, 1, 0), glm::vec3(0, 0, 1)));
mPrimitives.push_back({mLine, color, m});
}
void DebugRenderer::renderAABB(glm::vec3 start, glm::vec3 end, glm::vec4 color, bool wireframe)
{
if (!wireframe)
{
auto m = translate((start + end) / 2.0f) * scale((end - start) / 2.0f);
mPrimitives.push_back({mCube, color, m});
}
else
{
auto s = start;
auto e = end;
renderLine({s.x, s.y, s.z}, {e.x, s.y, s.z}, color);
renderLine({s.x, s.y, e.z}, {e.x, s.y, e.z}, color);
renderLine({s.x, e.y, s.z}, {e.x, e.y, s.z}, color);
renderLine({s.x, e.y, e.z}, {e.x, e.y, e.z}, color);
renderLine({s.x, s.y, s.z}, {s.x, e.y, s.z}, color);
renderLine({s.x, s.y, e.z}, {s.x, e.y, e.z}, color);
renderLine({e.x, s.y, s.z}, {e.x, e.y, s.z}, color);
renderLine({e.x, s.y, e.z}, {e.x, e.y, e.z}, color);
renderLine({s.x, s.y, s.z}, {s.x, s.y, e.z}, color);
renderLine({e.x, s.y, s.z}, {e.x, s.y, e.z}, color);
renderLine({s.x, e.y, s.z}, {s.x, e.y, e.z}, color);
renderLine({e.x, e.y, s.z}, {e.x, e.y, e.z}, color);
}
}
void DebugRenderer::renderAABBCentered(glm::vec3 center, glm::vec3 size, glm::vec4 color, bool wireframe)
{
renderAABB(center - size / 2.0f, center + size / 2.0f, color, wireframe);
}
#pragma once
#include <vector>
#include <glow/common/shared.hh>
#include <glow/common/property.hh>
#include <glow/objects/ArrayBufferAttribute.hh>
#include <glow/fwd.hh>
#include <glm/mat4x4.hpp>
#include <glm/vec4.hpp>
namespace glow
{
namespace pipeline
{
struct RenderPass;
GLOW_SHARED(class, RenderingPipeline);
}
namespace debugging
{
/**
* @brief The DebugRenderer is a easy-to-use (but not so performant) interface for easy debug rendering
*
* The DebugRenderer provides a set of functions for drawing primitives:
* - drawLine(...)
* - drawCube(...)
*
* In renderPass(...), call DebugRenderer::renderPass(...)
*
* The DebugRenderer accumulates all primitives, unless DebugRenderer::clear() is called
*
* Requires:
* // setup shader path
* DefaultShaderParser::addIncludePath("PATH/TO/glow-extras/debug/shader");
*/
class DebugRenderer
{
private:
struct PrimitiveVertex
{
glm::vec3 pos;
PrimitiveVertex() = default;
PrimitiveVertex(float u, float v) : pos(u, v, 0.0) {}
PrimitiveVertex(glm::vec3 pos) : pos(pos) {}
PrimitiveVertex(glm::vec3 position, glm::vec3 normal, glm::vec3 tangent, glm::vec2 texCoord) : pos(position) {}
static std::vector<ArrayBufferAttribute> attributes()
{
return {
{&PrimitiveVertex::pos, "aPosition"}, //
};
}
};
struct Primitive
{
SharedVertexArray vao;
glm::vec4 color;
glm::mat4 modelMatrix;
};
SharedVertexArray mQuad;
SharedVertexArray mCube;
SharedVertexArray mLine;
SharedProgram mShaderOpaque;
SharedProgram mShaderTransparent;
std::vector<Primitive> mPrimitives;
public:
DebugRenderer();
/// Clears all stored primitives
void clear();
/// Renders all stored primitives
void renderPass(pipeline::RenderPass const& pass) const;
// render functions
public:
void renderLine(glm::vec3 start, glm::vec3 end, glm::vec4 color = glm::vec4(1.0));
void renderAABB(glm::vec3 start, glm::vec3 end, glm::vec4 color = glm::vec4(1.0), bool wireframe = false);
void renderAABBCentered(glm::vec3 center, glm::vec3 size, glm::vec4 color = glm::vec4(1.0), bool wireframe = false);
};
GLOW_SHARED(class, DebugRenderer);
}
}
uniform vec4 uColor;
out vec3 fColor;
void main()
{
fColor = uColor.rgb;
}
\ No newline at end of file
#include <glow-pipeline/transparency.glsl>
uniform vec4 uColor;
void main()
{
outputTransparency(uColor.rgb * uColor.a, uColor.a);
}
\ No newline at end of file
in vec3 aPosition;
uniform mat4 uModel;
uniform mat4 uView;
uniform mat4 uProj;
void main()
{
gl_Position = uProj * uView * uModel * vec4(aPosition, 1.0);
}
\ No newline at end of file
#include "Line.hh"
using namespace glow::geometry;
#pragma once
#include <glm/vec3.hpp>
#include <glow/common/shared.hh>
#include <glow/objects/VertexArray.hh>
#include <glow/objects/ArrayBuffer.hh>
namespace glow
{
GLOW_SHARED(class, VertexArray);
namespace geometry
{
/// Builder for a line (GL_LINES) with 2 vertices
/// VertexT needs a c'tor that can be called with (x,y,z)
/// or supply a VertexCreator object which can be called as such
/// e.g. VertexT make_vertex(glm::vec3 p)
///
/// Supported built-in types:
/// vec3
///
/// If you use your custom vertex struct you have 2 options:
/// A: specify all attributes in Line(...) ctor
/// B: implemented the following function in your VertexT:
/// static std::vector<ArrayBufferAttribute> attributes();
///
/// Usage:
/// * auto lineVA = geometry::Line<>().generate();
/// * auto lineVA = geometry::Line<glm::vec3>().generate();
/// * auto lineVA = geometry::Line<MyVertex>().generate();
/// with struct MyVertex { ...
/// static std::vector<ArrayBufferAttribute> attributes() { return { {&MyVertex::a, "a"}, ... }; }
/// };
/// * auto lineVA = geometry::Line<MyVertex>({ {&MyVertex::a, "a"}, ... }).generate();
/// with struct MyVertex { ... };
template <typename VertexT = glm::vec3>
struct Line
{
public:
/// List of line attributes
std::vector<ArrayBufferAttribute> attributes;
/// start coordinate
glm::vec3 startPos;
/// end coordinate
glm::vec3 endPos;
public: // Predefined creators
static VertexT createVertex(glm::vec3 p) { return VertexT{p}; }
public:
Line(std::vector<ArrayBufferAttribute> const& attrs = attributesOf((VertexT*)0),
glm::vec3 start = {0, 0, 0},
glm::vec3 end = {1, 0, 0})
: attributes(attrs), startPos(start), endPos(end)
{
}
/**
* @brief generates a Vertex Array with a single Array Buffer containing line data
*
* Vertex layout:
* VertexT{0, 0}
* VertexT{0, 1}
* VertexT{1, 0}
* VertexT{1, 1}
*/
template <typename VertexCreator = decltype(createVertex)>
SharedVertexArray generate(VertexCreator&& gen = createVertex) const
{
auto ab = ArrayBuffer::create();
ab->defineAttributes(attributes);
VertexT data[] = {
gen(startPos), //
gen(endPos), //
};
ab->bind().setData(data);
return VertexArray::create(ab, nullptr, GL_LINES);
}
public: // Predefined attributes
static std::vector<ArrayBufferAttribute> attributesOf(glm::vec3*)
{
return {ArrayBufferAttribute("aPosition", GL_FLOAT, 3, 0)};
}
static std::vector<ArrayBufferAttribute> attributesOf(void*) { return VertexT::attributes(); }
};
}
}
......@@ -15,5 +15,6 @@ target_link_libraries(glow-extras-glfw PUBLIC
glow-extras-timing
glow-extras-material
glow-extras-pipeline
glow-extras-debugging
glow-extras-camera
)
......@@ -30,7 +30,7 @@
#include <glow-extras/camera/GenericCamera.hh>
#include <glow-extras/pipeline/RenderingPipeline.hh>
#include <glow-extras/debugging/DebugRenderer.hh>
using namespace glow;
using namespace glow::glfw;
......@@ -60,9 +60,12 @@ void GlfwApp::init()
// include paths (BEFORE pipeline init)
DefaultShaderParser::addIncludePath(util::pathOf(__FILE__) + "/../../../pipeline/shader");
DefaultShaderParser::addIncludePath(util::pathOf(__FILE__) + "/../../../material/shader");
DefaultShaderParser::addIncludePath(util::pathOf(__FILE__) + "/../../../debugging/shader");
mCamera = std::make_shared<camera::GenericCamera>();
mPipeline = pipeline::RenderingPipeline::create(mCamera);
mDebugRenderer = std::make_shared<debugging::DebugRenderer>();
}
mPrimitiveQuery = std::make_shared<PrimitiveQuery>();
......@@ -103,6 +106,10 @@ void GlfwApp::render(float elapsedSeconds)
void GlfwApp::renderPass(const pipeline::RenderPass &pass, float elapsedSeconds)
{
if (mUseDefaultRendering)
{
debug()->renderPass(pass);
}
}
void GlfwApp::onResize(int w, int h)
......
......@@ -25,6 +25,10 @@ namespace camera
{
GLOW_SHARED(class, GenericCamera);
}
namespace debugging
{
GLOW_SHARED(class, DebugRenderer);
}
namespace glfw
{
......@@ -46,6 +50,7 @@ enum class CursorMode
* - update(...): called with a constant rate (default 60 Hz, configurable) before rendering
* - render(...): called as fast as possible (affected by vsync)
* - renderPass(...): if rendering pipeline enabled (default), default render(...) will call this (RECOMMENDED)
* NOTE: if you use debug()->renderXYZ, do so BEFORE call to base
* - onResize(...): called when window is resized
* - onClose(...): called when app is closed
* - input: see onKey/onChar/onMouseXYZ/onFileDrop (return true if you handled the event, if base returned true, you
......@@ -118,6 +123,8 @@ private:
SharedTimerQuery mRenderStartQuery; ///< start timestamp
SharedTimerQuery mRenderEndQuery; ///< end timestamp
debugging::SharedDebugRenderer mDebugRenderer; ///< debug rendering
// Camera handling
private:
bool mMouseLeft = false;
......@@ -157,6 +164,8 @@ public:
void setTitle(std::string const& title);
debugging::SharedDebugRenderer const& debug() const { return mDebugRenderer; }
glm::vec2 getMousePosition() const { return {mMouseX, mMouseY}; }
GLFWwindow* window() const { return mWindow; }
TwBar* tweakbar() const { return mTweakbar; }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment