diff --git a/src/Shaders/CMakeLists.txt b/src/Shaders/CMakeLists.txt index 35939575c..f576e5e86 100644 --- a/src/Shaders/CMakeLists.txt +++ b/src/Shaders/CMakeLists.txt @@ -25,6 +25,7 @@ corrade_add_resource(MagnumShaders_RCS MagnumShaders AbstractVector2D.vert AbstractVector3D.vert Flat2D.vert Flat3D.vert Flat.frag + MeshVisualizer.vert MeshVisualizer.geom MeshVisualizer.frag Phong.vert Phong.frag Vector.frag DistanceFieldVector.frag VertexColor2D.vert VertexColor3D.vert VertexColor.frag @@ -33,6 +34,7 @@ corrade_add_resource(MagnumShaders_RCS MagnumShaders set(MagnumShaders_SRCS DistanceFieldVector.cpp Flat.cpp + MeshVisualizer.cpp Phong.cpp Vector.cpp VertexColor.cpp @@ -42,6 +44,7 @@ set(MagnumShaders_HEADERS DistanceFieldVector.h AbstractVector.h Flat.h + MeshVisualizer.h Phong.h Shaders.h Vector.h diff --git a/src/Shaders/MeshVisualizer.cpp b/src/Shaders/MeshVisualizer.cpp new file mode 100644 index 000000000..0e44ee489 --- /dev/null +++ b/src/Shaders/MeshVisualizer.cpp @@ -0,0 +1,59 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "MeshVisualizer.h" + +#include + +#include "Context.h" +#include "Extensions.h" +#include "Shader.h" + +namespace Magnum { namespace Shaders { + +MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationProjectionMatrixUniform(0), viewportSizeUniform(1), colorUniform(2), wireframeColorUniform(3), wireframeWidthUniform(4), smoothnessUniform(5) { + if(flags & Flag::Wireframe) MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::geometry_shader4); + MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::explicit_attrib_location); + MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::explicit_uniform_location); + + Corrade::Utility::Resource rs("MagnumShaders"); + + attachShader(Shader(Version::GL330, Shader::Type::Vertex) + .addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "") + .addSource(rs.get("compatibility.glsl")) + .addSource(rs.get("MeshVisualizer.vert"))); + + if(flags & Flag::Wireframe) attachShader(Shader(Version::GL330, Shader::Type::Geometry) + .addSource(rs.get("compatibility.glsl")) + .addSource(rs.get("MeshVisualizer.geom"))); + + attachShader(Shader(Version::GL330, Shader::Type::Fragment) + .addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "") + .addSource(rs.get("compatibility.glsl")) + .addSource(rs.get("MeshVisualizer.frag"))); + + link(); +} + +}} diff --git a/src/Shaders/MeshVisualizer.frag b/src/Shaders/MeshVisualizer.frag new file mode 100644 index 000000000..467d82ce2 --- /dev/null +++ b/src/Shaders/MeshVisualizer.frag @@ -0,0 +1,46 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +layout(location = 2) uniform vec4 color = vec4(1.0, 1.0, 1.0, 1.0); + +#ifdef WIREFRAME_RENDERING +layout(location = 3) uniform vec4 wireframeColor = vec4(0.0, 0.0, 0.0, 1.0); +layout(location = 4) uniform float wireframeWidth = 1.0; +layout(location = 5) uniform float smoothness = 2.0; +noperspective in vec3 dist; +#endif + +out vec4 fragmentColor; + +void main() { + #ifdef WIREFRAME_RENDERING + /* Distance to nearest side */ + const float nearest = min(min(dist.x, dist.y), dist.z); + + /* Smooth step between face color and wireframe color based on distance */ + fragmentColor = mix(wireframeColor, color, smoothstep(wireframeWidth-smoothness, wireframeWidth+smoothness, nearest)); + #else + fragmentColor = color; + #endif +} diff --git a/src/Shaders/MeshVisualizer.geom b/src/Shaders/MeshVisualizer.geom new file mode 100644 index 000000000..3043f38cf --- /dev/null +++ b/src/Shaders/MeshVisualizer.geom @@ -0,0 +1,59 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +layout(location = 1) uniform vec2 viewportSize; + +layout(triangles) in; + +layout(triangle_strip, max_vertices = 3) out; + +/* Interpolate in screen space */ +noperspective out vec3 dist; + +void main() { + /* Screen position of each vertex */ + vec2 p[3]; + for(int i = 0; i != 3; ++i) + p[i] = viewportSize*gl_in[i].gl_Position.xy/gl_in[i].gl_Position.w; + + /* Vector of each triangle side */ + const vec2 v[3] = { + p[2]-p[1], + p[2]-p[0], + p[1]-p[0] + }; + + /* Compute area using perp-dot product */ + const float area = abs(dot(vec2(-v[1].y, v[1].x), v[2])); + + /* Add distance to opposite side to each vertex */ + for(int i = 0; i != 3; ++i) { + dist = vec3(0.0, 0.0, 0.0); + dist[i] = area/length(v[i]); + gl_Position = gl_in[i].gl_Position; + EmitVertex(); + } + + EndPrimitive(); +} diff --git a/src/Shaders/MeshVisualizer.h b/src/Shaders/MeshVisualizer.h new file mode 100644 index 000000000..b8f4fac9f --- /dev/null +++ b/src/Shaders/MeshVisualizer.h @@ -0,0 +1,154 @@ +#ifndef Magnum_Shaders_MeshVisualizer_h +#define Magnum_Shaders_MeshVisualizer_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Class Magnum::Shaders::MeshVisualizer + */ + +#include "Math/Matrix4.h" +#include "AbstractShaderProgram.h" +#include "Color.h" + +#include "Shaders/magnumShadersVisibility.h" + +namespace Magnum { namespace Shaders { + +/** +@brief %Mesh visualization shader + +Uses geometry shader to visualize wireframe. You need to call at least +setTransformationProjectionMatrix() (and setViewportSize(), if +@ref Flag "Flag::Wireframe" is enabled) to be able to render. +@requires_gl32 %Extension @extension{ARB,geometry_shader4} if + @ref Magnum::Shaders::MeshVisualizer::Flag "Flag::Wireframe" is enabled. +*/ +class MAGNUM_SHADERS_EXPORT MeshVisualizer: public AbstractShaderProgram { + public: + typedef Attribute<0, Vector3> Position; /**< @brief Vertex position */ + + /** + * @brief %Flag + * + * @see Flags, MeshVisualizer() + */ + enum class Flag: UnsignedByte { + Wireframe = 1 << 0 /**< Visualize wireframe */ + }; + + /** @brief %Flags */ + typedef Corrade::Containers::EnumSet Flags; + + /** + * @brief Constructor + * @param flags %Flags + */ + explicit MeshVisualizer(Flags flags); + + /** + * @brief Set transformation and projection matrix + * @return Pointer to self (for method chaining) + */ + inline MeshVisualizer* setTransformationProjectionMatrix(const Matrix4& matrix) { + setUniform(transformationProjectionMatrixUniform, matrix); + return this; + } + + /** + * @brief Set viewport size + * @return Pointer to self (for method chaining) + * + * Has effect only if @ref Flag "Flag::Wireframe" is enabled. + */ + inline MeshVisualizer* setViewportSize(const Vector2& size) { + setUniform(viewportSizeUniform, size); + return this; + } + + /** + * @brief Set base object color + * @return Pointer to self (for method chaining) + * + * Initial value is fully opaque white. + */ + inline MeshVisualizer* setColor(const Color4<>& color) { + setUniform(colorUniform, color); + return this; + } + + /** + * @brief Set wireframe color + * @return Pointer to self (for method chaining) + * + * Initial value is fully opaque black. Has effect only if + * @ref Flag "Flag::Wireframe" is enabled. + */ + inline MeshVisualizer* setWireframeColor(const Color4<>& color) { + if(flags & Flag::Wireframe) setUniform(wireframeColorUniform, color); + return this; + } + + /** + * @brief Set wireframe width + * @return Pointer to self (for method chaining) + * + * Initial value is `1.0f`. Has effect only if + * @ref Flag "Flag::Wireframe" is enabled. + */ + inline MeshVisualizer* setWireframeWidth(Float width) { + if(flags & Flag::Wireframe) setUniform(wireframeWidthUniform, width); + return this; + } + + /** + * @brief Set line smoothness + * @return Pointer to self (for method chaining) + * + * Initial value is `2.0f`. Has effect only if + * @ref Flag "Flag::Wireframe" is enabled. + */ + MeshVisualizer* setSmoothness(Float smoothness); + + private: + Flags flags; + Int transformationProjectionMatrixUniform, + viewportSizeUniform, + colorUniform, + wireframeColorUniform, + wireframeWidthUniform, + smoothnessUniform; +}; + +CORRADE_ENUMSET_OPERATORS(MeshVisualizer::Flags) + +inline MeshVisualizer* MeshVisualizer::setSmoothness(Float smoothness) { + if(flags & Flag::Wireframe) + setUniform(smoothnessUniform, smoothness); + return this; +} + +}} + +#endif diff --git a/src/Shaders/MeshVisualizer.vert b/src/Shaders/MeshVisualizer.vert new file mode 100644 index 000000000..784193ece --- /dev/null +++ b/src/Shaders/MeshVisualizer.vert @@ -0,0 +1,31 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +layout(location = 0) uniform mat4 transformationProjectionMatrix; + +layout(location = 0) in vec4 position; + +void main() { + gl_Position = transformationProjectionMatrix*position; +} diff --git a/src/Shaders/Shaders.h b/src/Shaders/Shaders.h index ae344e30c..0a6591e91 100644 --- a/src/Shaders/Shaders.h +++ b/src/Shaders/Shaders.h @@ -47,6 +47,7 @@ template class Flat; typedef Flat<2> Flat2D; typedef Flat<3> Flat3D; +class MeshVisualizer; class Phong; template class Vector;