diff --git a/doc/features.dox b/doc/features.dox index dd909093e..2614e21cc 100644 --- a/doc/features.dox +++ b/doc/features.dox @@ -32,6 +32,7 @@ namespace Magnum { - @subpage matrix-vector -- @copybrief matrix-vector - @subpage transformations -- @copybrief transformations - @subpage plugins -- @copybrief plugins +- @subpage shaders -- @copybrief shaders - @subpage scenegraph -- @copybrief scenegraph - @subpage shapes -- @copybrief shapes - @subpage debug-tools -- @copybrief debug-tools diff --git a/doc/generated/.gitattributes b/doc/generated/.gitattributes new file mode 100644 index 000000000..2117a73f8 --- /dev/null +++ b/doc/generated/.gitattributes @@ -0,0 +1 @@ +vector.svg -diff diff --git a/doc/generated/CMakeLists.txt b/doc/generated/CMakeLists.txt new file mode 100644 index 000000000..0c591a08d --- /dev/null +++ b/doc/generated/CMakeLists.txt @@ -0,0 +1,60 @@ +# +# This file is part of Magnum. +# +# Copyright © 2010, 2011, 2012, 2013, 2014 +# 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. +# + +cmake_minimum_required(VERSION 2.8.9) +project(MyApplication) + +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/../../modules/") + +find_package(Magnum REQUIRED + MeshTools + Primitives + Shaders) + +if(CORRADE_TARGET_APPLE) + find_package(Magnum REQUIRED WindowlessCglApplication) +elseif(CORRADE_TARGET_UNIX) + find_package(Magnum REQUIRED WindowlessGlxApplication) +elseif(CORRADE_TARGET_WINDOWS) + find_package(Magnum REQUIRED WindowlessWglApplication) +else() + message(FATAL_ERROR "No windowless application available on this platform") +endif() + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake + ${CMAKE_CURRENT_BINARY_DIR}/configure.h) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CORRADE_CXX_FLAGS}") +include_directories(${MAGNUM_INCLUDE_DIRS} + ${MAGNUM_WINDOWLESSAPPLICATION_INCLUDE_DIRS}) + +add_executable(shaders shaders.cpp) +target_link_libraries(shaders + ${MAGNUM_LIBRARIES} + ${MAGNUM_MESHTOOLS_LIBRARIES} + ${MAGNUM_PRIMITIVES_LIBRARIES} + ${MAGNUM_SHADERS_LIBRARIES} + ${MAGNUM_WINDOWLESSAPPLICATION_LIBRARIES}) diff --git a/doc/generated/README.md b/doc/generated/README.md new file mode 100644 index 000000000..23b8f5c64 --- /dev/null +++ b/doc/generated/README.md @@ -0,0 +1,32 @@ +Source files for images in Magnum documentation +----------------------------------------------- + +Compile and install Magnum with windowless application for your platform and +`magnum-distancefieldconverter` utility and any `PngImporter` and +`PngImageConverter` plugins from Magnum Plugins. + +Create build dir, point CMake to this directory and compile the executables: + + mkdir build-doc + cd build-doc + cmake ../doc/generated + cmake --build . + +### Shader images + +Generated by the `shaders` executable. Must be run in this directory, the +output is put into `doc/` directory. The executable requires two textures: + +- `vector.png`, generated as full-page PNG output at 90 DPI from `vector.svg`, + converted to pure grayscale using imagemagick: + + ```bash + mogrify -flatten -background '#ffffff' -format grayscale vector.png + ``` + +- `vector-distancefield.png`, generated as full-page PNG output at 360 DPI + (1024x1024) and then processed through `magnum-distancefieldconverter` + + ```bash + magnum-distancefieldconverter --importer PngImporter --converter PngImageConverter --output-size "64 64" --radius 16 vector-src.png vector-distancefield.png + ``` diff --git a/doc/generated/configure.h.cmake b/doc/generated/configure.h.cmake new file mode 100644 index 000000000..68174eb16 --- /dev/null +++ b/doc/generated/configure.h.cmake @@ -0,0 +1,32 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + 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. +*/ + +#ifdef CORRADE_IS_DEBUG_BUILD +#define MAGNUM_PLUGINS_IMAGECONVERTER_DIR "${MAGNUM_PLUGINS_IMAGECONVERTER_DEBUG_DIR}" +#define MAGNUM_PLUGINS_IMPORTER_DIR "${MAGNUM_PLUGINS_IMPORTER_DEBUG_DIR}" +#else +#define MAGNUM_PLUGINS_IMAGECONVERTER_DIR "${MAGNUM_PLUGINS_IMAGECONVERTER_DIR}" +#define MAGNUM_PLUGINS_IMPORTER_DIR "${MAGNUM_PLUGINS_IMPORTER_DIR}" +#endif diff --git a/doc/generated/shaders.cpp b/doc/generated/shaders.cpp new file mode 100644 index 000000000..73e12010e --- /dev/null +++ b/doc/generated/shaders.cpp @@ -0,0 +1,301 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + 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 +#include + +#ifdef CORRADE_TARGET_APPLE +#include +#elif defined(CORRADE_TARGET_UNIX) +#include +#elif defined(CORRADE_TARGET_WINDOWS) +#include +#else +#error No windowless application available on this platform +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "configure.h" + +using namespace Magnum; + +struct ShaderVisualizer: Platform::WindowlessApplication { + using Platform::WindowlessApplication::WindowlessApplication; + + int exec() override; + + std::string phong(); + std::string meshVisualizer(); + std::string flat(); + std::string vertexColor(); + + std::string vector(); + std::string distanceFieldVector(); + + std::unique_ptr _importer; +}; + +namespace { + constexpr const Vector2i ImageSize{256}; +} + +int ShaderVisualizer::exec() { + PluginManager::Manager converterManager{MAGNUM_PLUGINS_IMAGECONVERTER_DIR}; + std::unique_ptr converter = converterManager.loadAndInstantiate("PngImageConverter"); + if(!converter) { + Error() << "Cannot load image converter plugin"; + std::exit(1); + } + + PluginManager::Manager importerManager{MAGNUM_PLUGINS_IMPORTER_DIR}; + _importer = importerManager.loadAndInstantiate("PngImporter"); + if(!_importer) { + Error() << "Cannot load image importer plugin"; + std::exit(1); + } + + Renderbuffer multisampleColor, multisampleDepth; + multisampleColor.setStorageMultisample(16, RenderbufferFormat::RGBA8, ImageSize); + multisampleDepth.setStorageMultisample(16, RenderbufferFormat::DepthComponent24, ImageSize); + + Framebuffer multisampleFramebuffer{{{}, ImageSize}}; + multisampleFramebuffer.attachRenderbuffer(Framebuffer::ColorAttachment{0}, multisampleColor) + .attachRenderbuffer(Framebuffer::BufferAttachment::Depth, multisampleDepth) + .bind(FramebufferTarget::Draw); + CORRADE_INTERNAL_ASSERT(multisampleFramebuffer.checkStatus(FramebufferTarget::ReadDraw) == Framebuffer::Status::Complete); + + Renderbuffer color; + color.setStorage(RenderbufferFormat::RGBA8, ImageSize); + Framebuffer framebuffer{{{}, ImageSize}}; + framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment{0}, color); + + Renderer::enable(Renderer::Feature::DepthTest); + + for(auto fun: {&ShaderVisualizer::phong, + &ShaderVisualizer::meshVisualizer, + &ShaderVisualizer::flat, + &ShaderVisualizer::vertexColor, + &ShaderVisualizer::vector, + &ShaderVisualizer::distanceFieldVector}) { + multisampleFramebuffer.clear(FramebufferClear::Color|FramebufferClear::Depth); + + std::string filename = (this->*fun)(); + + AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), FramebufferBlit::Color); + Image2D result = framebuffer.read(framebuffer.viewport(), {ColorFormat::RGBA, ColorType::UnsignedByte}); + converter->exportToFile(result, Utility::Directory::join("../", "shaders-" + filename)); + } + + _importer.reset(); + + return 0; +} + +namespace { + const auto Projection = Matrix4::perspectiveProjection(35.0_degf, 1.0f, 0.001f, 100.0f); + const auto Transformation = Matrix4::translation(Vector3::zAxis(-5.0f)); + const auto BaseColor = Color3::fromHSV(216.0_degf, 0.85f, 1.0f); + const auto OutlineColor = Color3{0.95f}; +} + +std::string ShaderVisualizer::phong() { + std::unique_ptr vertices, indices; + Mesh mesh; + std::tie(mesh, vertices, indices) = MeshTools::compile(Primitives::UVSphere::solid(16, 32), BufferUsage::StaticDraw); + + Shaders::Phong shader; + shader.setAmbientColor(Color3(0.025f)) + .setDiffuseColor(BaseColor) + .setShininess(200.0f) + .setLightPosition({5.0f, 5.0f, 7.0f}) + .setProjectionMatrix(Projection) + .setTransformationMatrix(Transformation) + .setNormalMatrix(Transformation.rotationScaling()); + + mesh.draw(shader); + + return "phong.png"; +} + +std::string ShaderVisualizer::meshVisualizer() { + std::unique_ptr vertices, indices; + Mesh mesh; + std::tie(mesh, vertices, indices) = MeshTools::compile(Primitives::Icosphere::solid(1), BufferUsage::StaticDraw); + + const Matrix4 projection = Projection*Transformation* + Matrix4::rotationZ(13.7_degf)* + Matrix4::rotationX(-12.6_degf); + + Shaders::MeshVisualizer shader{Shaders::MeshVisualizer::Flag::Wireframe}; + shader.setColor(BaseColor) + .setWireframeColor(OutlineColor) + .setViewportSize(Vector2{ImageSize}) + .setTransformationProjectionMatrix(projection); + + mesh.draw(shader); + + return "meshvisualizer.png"; +} + +std::string ShaderVisualizer::flat() { + std::unique_ptr vertices, indices; + Mesh mesh; + std::tie(mesh, vertices, indices) = MeshTools::compile(Primitives::UVSphere::solid(16, 32), BufferUsage::StaticDraw); + + Shaders::Flat3D shader; + shader.setColor(BaseColor) + .setTransformationProjectionMatrix(Projection*Transformation); + + mesh.draw(shader); + + return "flat.png"; +} + +std::string ShaderVisualizer::vertexColor() { + Trade::MeshData3D sphere = Primitives::UVSphere::solid(32, 64); + + /* Color vertices nearest to given position */ + auto target = Vector3{2.0f, 2.0f, 7.0f}.normalized(); + std::vector colors; + colors.reserve(sphere.positions(0).size()); + for(Vector3 position: sphere.positions(0)) + colors.push_back(Color3::fromHSV(Math::lerp(240.0_degf, 420.0_degf, Math::max(1.0f - (position - target).length(), 0.0f)), 0.85f, 0.85f)); + + Buffer vertices, indices; + vertices.setData(MeshTools::interleave(sphere.positions(0), colors), BufferUsage::StaticDraw); + indices.setData(sphere.indices(), BufferUsage::StaticDraw); + + Mesh mesh; + mesh.setPrimitive(MeshPrimitive::Triangles) + .setCount(sphere.indices().size()) + .addVertexBuffer(vertices, 0, Shaders::VertexColor3D::Position{}, Shaders::VertexColor3D::Color{}) + .setIndexBuffer(indices, 0, Mesh::IndexType::UnsignedInt); + + Shaders::VertexColor3D shader; + shader.setTransformationProjectionMatrix(Projection*Transformation); + + mesh.draw(shader); + + return "vertexcolor.png"; +} + +std::string ShaderVisualizer::vector() { + std::optional image; + if(!_importer->openFile("vector.png") || !(image = _importer->image2D(0))) { + Error() << "Cannot open vector.png"; + return "vector.png"; + } + + Texture2D texture; + texture.setMinificationFilter(Sampler::Filter::Linear) + .setMagnificationFilter(Sampler::Filter::Linear) + .setWrapping(Sampler::Wrapping::ClampToEdge) + .setStorage(1, TextureFormat::RGBA8, image->size()) + .setSubImage(0, {}, *image); + + Mesh mesh; + std::unique_ptr vertices; + std::tie(mesh, vertices, std::ignore) = MeshTools::compile(Primitives::Square::solid(Primitives::Square::TextureCoords::Generate), BufferUsage::StaticDraw); + + Shaders::Vector2D shader; + shader.setColor(BaseColor) + .setVectorTexture(texture) + .setTransformationProjectionMatrix({}); + + Renderer::enable(Renderer::Feature::Blending); + Renderer::setBlendFunction(Renderer::BlendFunction::One, Renderer::BlendFunction::OneMinusSourceAlpha); + Renderer::setBlendEquation(Renderer::BlendEquation::Add, Renderer::BlendEquation::Add); + + mesh.draw(shader); + + Renderer::disable(Renderer::Feature::Blending); + + return "vector.png"; +} + +std::string ShaderVisualizer::distanceFieldVector() { + std::optional image; + if(!_importer->openFile("vector-distancefield.png") || !(image = _importer->image2D(0))) { + Error() << "Cannot open vector-distancefield.png"; + return "distancefieldvector.png"; + } + + Texture2D texture; + texture.setMinificationFilter(Sampler::Filter::Linear) + .setMagnificationFilter(Sampler::Filter::Linear) + .setWrapping(Sampler::Wrapping::ClampToEdge) + .setStorage(1, TextureFormat::RGBA8, image->size()) + .setSubImage(0, {}, *image); + + Mesh mesh; + std::unique_ptr vertices; + std::tie(mesh, vertices, std::ignore) = MeshTools::compile(Primitives::Square::solid(Primitives::Square::TextureCoords::Generate), BufferUsage::StaticDraw); + + Shaders::DistanceFieldVector2D shader; + shader.setColor(BaseColor) + .setOutlineColor(OutlineColor) + .setOutlineRange(0.6f, 0.4f) + .setVectorTexture(texture) + .setTransformationProjectionMatrix({}); + + Renderer::enable(Renderer::Feature::Blending); + Renderer::setBlendFunction(Renderer::BlendFunction::One, Renderer::BlendFunction::OneMinusSourceAlpha); + Renderer::setBlendEquation(Renderer::BlendEquation::Add, Renderer::BlendEquation::Add); + + mesh.draw(shader); + + Renderer::disable(Renderer::Feature::Blending); + + return "distancefieldvector.png"; +} + +MAGNUM_WINDOWLESSAPPLICATION_MAIN(ShaderVisualizer) diff --git a/doc/generated/vector-distancefield.png b/doc/generated/vector-distancefield.png new file mode 100644 index 000000000..5a94b2dc4 Binary files /dev/null and b/doc/generated/vector-distancefield.png differ diff --git a/doc/generated/vector.png b/doc/generated/vector.png new file mode 100644 index 000000000..dcd61aeab Binary files /dev/null and b/doc/generated/vector.png differ diff --git a/doc/generated/vector.svg b/doc/generated/vector.svg new file mode 100644 index 000000000..78056b8c6 --- /dev/null +++ b/doc/generated/vector.svg @@ -0,0 +1,79 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/doc/namespaces.dox b/doc/namespaces.dox index 365efd7f4..7e329e676 100644 --- a/doc/namespaces.dox +++ b/doc/namespaces.dox @@ -182,7 +182,7 @@ Collection of shaders for easy prototyping and basic usage. This library is built if `WITH_SHADERS` is enabled when building Magnum. To use this library, you need to request `Shaders` component of `Magnum` package in CMake and link to `${MAGNUM_MESHTOOLS_SHADERS}`. See @ref building and -@ref cmake for more information. +@ref cmake and @ref shaders for more information. */ /** @dir Magnum/Shapes diff --git a/doc/plugins.dox b/doc/plugins.dox index 2eae069b4..20b5b7da1 100644 --- a/doc/plugins.dox +++ b/doc/plugins.dox @@ -28,7 +28,7 @@ namespace Magnum { @brief Extending Magnum with additional functionality - Previous page: @ref transformations -- Next page: @ref scenegraph +- Next page: @ref shaders The base Magnum library contains math support, scene graph implementation and is able to interact with graphics and audio hardware. However, the base library @@ -211,7 +211,7 @@ to how static plugins are found above. See @ref cmake and @ref cmake-plugins for more information. - Previous page: @ref transformations -- Next page: @ref scenegraph +- Next page: @ref shaders */ } diff --git a/doc/scenegraph.dox b/doc/scenegraph.dox index 7a0ed5288..a333a1594 100644 --- a/doc/scenegraph.dox +++ b/doc/scenegraph.dox @@ -27,7 +27,7 @@ namespace Magnum { /** @page scenegraph Using scene graph @brief Overview of scene management capabilities. -- Previous page: @ref plugins +- Previous page: @ref shaders - Next page: @ref shapes Scene graph provides way to hiearchically manage your objects, their @@ -286,7 +286,7 @@ On destruction, Object3D destructor is called first, deleting MyFeature, which is wrong, because MyFeature is in the same object. After that (if the program didn't already crash) destructor of MyFeature is called (again). -- Previous page: @ref plugins +- Previous page: @ref shaders - Next page: @ref shapes */ } diff --git a/doc/shaders-distancefieldvector.png b/doc/shaders-distancefieldvector.png new file mode 100644 index 000000000..c54d99240 Binary files /dev/null and b/doc/shaders-distancefieldvector.png differ diff --git a/doc/shaders-flat.png b/doc/shaders-flat.png new file mode 100644 index 000000000..2aa2037ec Binary files /dev/null and b/doc/shaders-flat.png differ diff --git a/doc/shaders-meshvisualizer.png b/doc/shaders-meshvisualizer.png new file mode 100644 index 000000000..896dda575 Binary files /dev/null and b/doc/shaders-meshvisualizer.png differ diff --git a/doc/shaders-phong.png b/doc/shaders-phong.png new file mode 100644 index 000000000..2f1a44a33 Binary files /dev/null and b/doc/shaders-phong.png differ diff --git a/doc/shaders-vector.png b/doc/shaders-vector.png new file mode 100644 index 000000000..9697fdd7a Binary files /dev/null and b/doc/shaders-vector.png differ diff --git a/doc/shaders-vertexcolor.png b/doc/shaders-vertexcolor.png new file mode 100644 index 000000000..a865c87e0 Binary files /dev/null and b/doc/shaders-vertexcolor.png differ diff --git a/doc/shaders.dox b/doc/shaders.dox new file mode 100644 index 000000000..980364caf --- /dev/null +++ b/doc/shaders.dox @@ -0,0 +1,136 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + 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. +*/ + +namespace Magnum { +/** @page shaders Builtin shaders +@brief Overview and basic usage of builtin shaders. + +- Previous page: @ref plugins +- Next page: @ref scenegraph + +@tableofcontents + +Magnum contains a set of general-purpose shaders for easy prototyping, UI +rendering and data visualization/debugging in both 2D and 3D scenes. The +following shaders are available, see documentation of each class for sample +output and example setup: + +- @ref Shaders::Flat "Shaders::Flat*D" -- flat shading using single color or + texture +- @ref Shaders::Vector "Shaders::Vector*D" -- colored vector graphics +- @ref Shaders::DistanceFieldVector "Shaders::DistanceFieldVector*D" -- + colored and outlined vector graphics +- @ref Shaders::VertexColor "Shaders::VertexColor*D" -- vertex-colored meshes +- @ref Shaders::Phong -- Phong shading using colors or textures, 3D only +- @ref Shaders::MeshVisualizer -- wireframe visualization, 3D only + +All the builtin shaders can be used on unextended OpenGL 2.1 and OpenGL ES 2.0 +/ WebGL 1.0, but they try to use the most recent technology available to have +them as efficient as possible on every configuration. + +@section shaders-usage Usage + +Shader usage is divided into two parts: configuring vertex attributes in the +mesh and configuring the shader itself. + +Each shader expects some set of vertex attributes, thus when adding vertex +buffer into the mesh, you need to specify which shader attributes are on which +position in the buffer. See @ref Mesh::addVertexBuffer() for details and usage +examples. Example mesh configuration for @ref Shaders::Phong shader: +@code +struct Vertex { + Vector3 position; + Vector3 normal; + Vector2 textureCoordinates; +}; +Vertex data[] = { ... }; + +Buffer vertices; +vertices.setData(data, BufferUsage::StaticDraw); + +Mesh mesh; +mesh.addVertexBuffer(vertices, 0, + Shaders::Phong::Position{}, + Shaders::Phong::Normal{}, + Shaders::Phong::TextureCoordinates{}); +@endcode + +Each shader then has its own set of configuration functions. Some configuration +is static, specified commonly as flags in constructor, directly affecting +compiled shader code. Other configuration is specified through uniforms and +various binding points, commonly exposed through various setters. Example +configuration and rendering using @ref Shaders::Phong "Shaders::Phong": +@code +Matrix4 transformationMatrix, projectionMatrix; +Texture2D diffuseTexture, specularTexture; + +Shaders::Phong shader{Shaders::Phong::DiffuseTexture}; +shader.setDiffuseTexture(diffuseTexture) + .setLightPosition({5.0f, 5.0f, 7.0f}) + .setTransformationMatrix(transformationMatrix) + .setNormalMatrix(transformationMatrix.rotation()) + .setProjectionMatrix(projectionMatrix); + +mesh.draw(shader); +@endcode + +@section shaders-generic Generic vertex attributes + +Many shaders share the same vertex attribute definitions, such as positions, +normals, texture coordinates etc. It's thus possible to configure the mesh +for *generic* shader and then render it with any compatible shader. Definition +of generic attributes is available in @ref Shaders::Generic class. +Configuration of the above mesh using generic attributes could then look like +this: +@code +mesh.addVertexBuffer(vertices, 0, + Shaders::Generic3D::Position{}, + Shaders::Generic3D::Normal{}, + Shaders::Generic3D::TextureCoordinates{}); +@endcode +Note that in this particular case both configurations are equivalent, because +@ref Shaders::Phong also uses generic vertex attribute definitions. + +Then you can render the mesh using @ref Shaders::Phong shader like above, or +use for example @ref Shaders::Flat3D or even @ref Shaders::MeshVisualizer with +the same mesh reconfiguration. The unused attributes will be simply ignored. +@code +Shaders::MeshVisualizer visualizerShader{Shaders::MeshVisualizer::Wireframe}; +visualizerShader.setColor(Color3::fromHSV(216.0_degf, 0.85f, 1.0f)) + .setWireframeColor(Color3{0.95f}) + .setViewportSize(defaultFramebuffer.viewport().size()) + .setTransformationProjectionMatrix(projectionMatrix*transformationMatrix); + +mesh.draw(visualizerShader); +@endcode + +The @ref MeshTools::compile() utility configures meshes using generic vertex +attribute definitions to make them usable with any shader. + +- Previous page: @ref plugins +- Next page: @ref scenegraph + +*/ +} diff --git a/src/Magnum/MeshTools/Compile.h b/src/Magnum/MeshTools/Compile.h index 3cb41c795..e044a6c45 100644 --- a/src/Magnum/MeshTools/Compile.h +++ b/src/Magnum/MeshTools/Compile.h @@ -54,6 +54,8 @@ The second returned buffer may be `nullptr` if the mesh is not indexed. This is just a convenience function for creating generic meshes, you might want to use @ref interleave() and @ref compressIndices() functions instead for greater flexibility. + +@see @ref shaders-generic */ MAGNUM_MESHTOOLS_EXPORT std::tuple, std::unique_ptr> compile(const Trade::MeshData2D& meshData, BufferUsage usage); @@ -73,6 +75,8 @@ The second returned buffer may be `nullptr` if the mesh is not indexed. This is just a convenience function for creating generic meshes, you might want to use @ref interleave() and @ref compressIndices() functions instead for greater flexibility. + +@see @ref shaders-generic */ MAGNUM_MESHTOOLS_EXPORT std::tuple, std::unique_ptr> compile(const Trade::MeshData3D& meshData, BufferUsage usage); diff --git a/src/Magnum/Shaders/AbstractVector.h b/src/Magnum/Shaders/AbstractVector.h index 4c1fc5399..a882fa669 100644 --- a/src/Magnum/Shaders/AbstractVector.h +++ b/src/Magnum/Shaders/AbstractVector.h @@ -36,14 +36,24 @@ namespace Magnum { namespace Shaders { /** @brief Base for vector shaders -@see @ref AbstractVector2D, @ref AbstractVector3D +See @ref DistanceFieldVector and @ref Vector for more information. +@see @ref shaders, @ref AbstractVector2D, @ref AbstractVector3D */ template class AbstractVector: public AbstractShaderProgram { public: - /** @brief Vertex position */ + /** + * @brief Vertex position + * + * @ref shaders-generic "Generic attribute", @ref Vector2 in 2D, + * @ref Vector3 in 3D. + */ typedef typename Generic::Position Position; - /** @brief Texture coordinates */ + /** + * @brief 2D texture coordinates + * + * @ref shaders-generic "Generic attribute", @ref Vector2. + */ typedef typename Generic::TextureCoordinates TextureCoordinates; #ifdef MAGNUM_BUILD_DEPRECATED diff --git a/src/Magnum/Shaders/DistanceFieldVector.h b/src/Magnum/Shaders/DistanceFieldVector.h index ad9986bc5..630094fea 100644 --- a/src/Magnum/Shaders/DistanceFieldVector.h +++ b/src/Magnum/Shaders/DistanceFieldVector.h @@ -41,10 +41,52 @@ namespace Magnum { namespace Shaders { /** @brief Distance field vector shader -Renders vector art in form of signed distance field. See @ref TextureTools::distanceField() -for more information. Note that the final rendered outlook will greatly depend -on radius of input distance field and value passed to @ref setSmoothness(). -@see @ref DistanceFieldVector2D, @ref DistanceFieldVector3D +Renders vector graphics in form of signed distance field. See +@ref TextureTools::distanceField() for more information. Note that the final +rendered outlook will greatly depend on radius of input distance field and +value passed to @ref setSmoothness(). You need to provide @ref Position and +@ref TextureCoordinates attributes in your triangle mesh and call at least +@ref setTransformationProjectionMatrix(), @ref setColor() and +@ref setVectorTexture(). + +@image html shaders-distancefieldvector.png +@image latex shaders-distancefieldvector.png + +## Example usage + +Common mesh setup: +@code +struct Vertex { + Vector2 position; + Vector2 textureCoordinates; +}; +Vertex data[] = { ... }; + +Buffer vertices; +vertices.setData(data, BufferUsage::StaticDraw); + +Mesh mesh; +mesh.addVertexBuffer(vertices, 0, + Shaders::DistanceFieldVector2D::Position{}, + Shaders::DistanceFieldVector2D::TextureCoordinates{}); +@endcode + +Common rendering setup: +@code +Matrix3 transformationMatrix, projectionMatrix; +Texture2D texture; + +Shaders::DistanceFieldVector2D shader; +shader.setColor(Color3::fromHSV(216.0_degf, 0.85f, 1.0f)) + .setOutlineColor(Color3{0.95f}) + .setOutlineRange(0.6f, 0.4f) + .setVectorTexture(texture) + .setTransformationProjectionMatrix(projectionMatrix*transformationMatrix); + +mesh.draw(shader); +@endcode + +@see @ref shaders, @ref DistanceFieldVector2D, @ref DistanceFieldVector3D @todo Use fragment shader derivations to have proper smoothness in perspective/ large zoom levels, make it optional as it might have negative performance impact diff --git a/src/Magnum/Shaders/Flat.h b/src/Magnum/Shaders/Flat.h index cf920012c..5ceb14329 100644 --- a/src/Magnum/Shaders/Flat.h +++ b/src/Magnum/Shaders/Flat.h @@ -57,17 +57,88 @@ The texture will be multiplied with the color (which is white by default, thus it doesn't change texture color). For coloring the texture based on intensity you can use the @ref Vector shader. -@see @ref Flat2D, @ref Flat3D + +@image html shaders-flat.png +@image latex shaders-flat.png + +## Example usage + +### Colored mesh + +Common mesh setup: +@code +struct Vertex { + Vector3 position; +}; +Vertex data[] = { ... }; + +Buffer vertices; +vertices.setData(data, BufferUsage::StaticDraw); + +Mesh mesh; +mesh.addVertexBuffer(vertices, 0, Shaders::Flat3D::Position{}); +@endcode + +Common rendering setup: +@code +Matrix4 transformationMatrix = Matrix4::translation(Vector3::zAxis(-5.0f)); +Matrix4 projectionMatrix = Matrix4::perspectiveProjection(35.0_degf, 1.0f, 0.001f, 100.0f); + +Shaders::Flat3D shader; +shader.setColor(Color3::fromHSV(216.0_degf, 0.85f, 1.0f)) + .setTransformationProjectionMatrix(projectionMatrix*transformationMatrix); + +mesh.draw(shader); +@endcode + +### Textured mesh + +Common mesh setup: +@code +struct Vertex { + Vector3 position; + Vector2 textureCoordinates; +}; +Vertex data[] = { ... }; + +Buffer vertices; +vertices.setData(data, BufferUsage::StaticDraw); + +Mesh mesh; +mesh.addVertexBuffer(vertices, 0, + Shaders::Flat3D::Position{}, + Shaders::Flat3D::TextureCoordinates{}); +@endcode + +Common rendering setup: +@code +Matrix4 transformationMatrix, projectionMatrix; +Texture2D texture; + +Shaders::Flat3D shader{Shaders::Flat3D::Textured}; +shader.setTransformationProjectionMatrix(projectionMatrix*transformationMatrix) + .setTexture(texture); + +mesh.draw(shader); +@endcode + +@see @ref shaders, @ref Flat2D, @ref Flat3D */ template class MAGNUM_SHADERS_EXPORT Flat: public AbstractShaderProgram { public: - /** @brief Vertex position */ + /** + * @brief Vertex position + * + * @ref shaders-generic "Generic attribute", @ref Vector2 in 2D, + * @ref Vector3 in 3D. + */ typedef typename Generic::Position Position; /** - * @brief Texture coordinates + * @brief 2D texture coordinates * - * Used only if @ref Flag::Textured is set. + * @ref shaders-generic "Generic attribute", @ref Vector2. Used only if + * @ref Flag::Textured is set. */ typedef typename Generic::TextureCoordinates TextureCoordinates; diff --git a/src/Magnum/Shaders/Generic.h b/src/Magnum/Shaders/Generic.h index 24a386d5c..12e91d489 100644 --- a/src/Magnum/Shaders/Generic.h +++ b/src/Magnum/Shaders/Generic.h @@ -37,27 +37,10 @@ namespace Magnum { namespace Shaders { @brief Generic shader definition Definitions common for majority of shaders in @ref Shaders namespace, allowing -mesh configured for the generic shader to be used with any of them. +mesh configured for the generic shader to be used with any of them. See +@ref shaders-generic for more information. -Example usage (configuring the mesh for generic shader, then using it with -@ref Shaders::Phong): -@code -Mesh mesh; -Buffer vertexBuffer; - -// ... - -mesh.addVertexBuffer(vertexBuffer, 0, - Shaders::Generic3D::Position(), - Shaders::Generic3D::Normal(), - Shaders::Generic3D::TextureCoordinates()); - -Shaders::Phong phong; -// ... -mesh.draw(phong); -@endcode - -@see @ref Generic2D, @ref Generic3D +@see @ref shaders, @ref Generic2D, @ref Generic3D */ #ifndef DOXYGEN_GENERATING_OUTPUT template struct Generic; @@ -66,17 +49,21 @@ template struct Generic { /** * @brief Vertex position * - * Defined as @ref Vector2 in 2D and @ref Vector3 in 3D. + * @ref Vector2 in 2D and @ref Vector3 in 3D. */ typedef Attribute<0, T> Position; - /** @brief 2D texture coordinates */ + /** + * @brief 2D texture coordinates + * + * @ref Vector2. + */ typedef Attribute<1, Vector2> TextureCoordinates; /** * @brief Vertex normal * - * Defined only in 3D. + * @ref Vector3, defined only in 3D. */ typedef Attribute<2, Vector3> Normal; }; diff --git a/src/Magnum/Shaders/MeshVisualizer.h b/src/Magnum/Shaders/MeshVisualizer.h index dd9da04ed..1d19e8342 100644 --- a/src/Magnum/Shaders/MeshVisualizer.h +++ b/src/Magnum/Shaders/MeshVisualizer.h @@ -40,9 +40,12 @@ namespace Magnum { namespace Shaders { /** @brief Mesh visualization shader -Uses geometry shader to visualize wireframe. You need to provide @ref Position -attribute in your triangle mesh and call at least @ref setTransformationProjectionMatrix() -to be able to render. +Uses geometry shader to visualize wireframe of 3D meshes. You need to provide +@ref Position attribute in your triangle mesh and call at least +@ref setTransformationProjectionMatrix() to be able to render. + +@image html shaders-meshvisualizer.png +@image latex shaders-meshvisualizer.png ## Wireframe visualization @@ -63,20 +66,104 @@ you have OpenGL < 3.1 or OpenGL ES 2.0, you need to provide also @requires_es_extension Extension @extension{OES,standard_derivatives} for wireframe rendering. +## Example usage + +### Wireframe visualization with geometry shader (desktop GL) + +Common mesh setup: +@code +struct Vertex { + Vector3 position; +}; +Vertex data[] = { ... }; + +Buffer vertices; +vertices.setData(data, BufferUsage::StaticDraw); + +Mesh mesh; +mesh.addVertexBuffer(vertices, 0, Shaders::MeshVisualizer::Position{}); +@endcode + +Common rendering setup: +@code +Matrix4 transformationMatrix = Matrix4::translation(Vector3::zAxis(-5.0f)); +Matrix4 projectionMatrix = Matrix4::perspectiveProjection(35.0_degf, 1.0f, 0.001f, 100.0f); + +Shaders::MeshVisualizer shader{Shaders::MeshVisualizer::Wireframe}; +shader.setColor(Color3::fromHSV(216.0_degf, 0.85f, 1.0f)) + .setWireframeColor(Color3{0.95f}) + .setViewportSize(defaultFramebuffer.viewport().size()) + .setTransformationProjectionMatrix(projectionMatrix*transformationMatrix); + +mesh.draw(shader); +@endcode + +### Wireframe visualization without geometry shader on older hardware + +You need to provide also the @ref VertexIndex attribute. Mesh setup *in +addition to the above*: +@code +constexpr std::size_t vertexCount = std::extent::value; +Float vertexIndex[vertexCount]; +std::iota(vertexIndex, vertexIndex + vertexCount, 0.0f); + +Buffer vertexIndices; +vertexIndices.setData(vertexIndex, BufferUsage::StaticDraw); + +mesh.addVertexBuffer(vertexIndices, 0, Shaders::MeshVisualizer::VertexIndex{}); +@endcode + +Rendering setup: +@code +Matrix4 transformationMatrix, projectionMatrix; + +Shaders::MeshVisualizer shader{Shaders::MeshVisualizer::Wireframe| + Shaders::MeshVisualizer::NoGeometryShader}; +shader.setColor(Color3::fromHSV(216.0_degf, 0.85f, 1.0f)) + .setWireframeColor(Color3{0.95f}) + .setTransformationProjectionMatrix(projectionMatrix*transformationMatrix); + +mesh.draw(shader); +@endcode + +### Wireframe visualization of indexed meshes without geometry shader + +The vertices must be converted to non-indexed array. Mesh setup: +@code +std::vector indices{ ... }; +std::vector indexedPositions{ ... }; + +// De-indexing the position array +Buffer vertices; +vertices.setData(MeshTools::duplicate(indices, indexedPositions), BufferUsage::StaticDraw); + +Mesh mesh; +mesh.addVertexBuffer(vertices, 0, Shaders::MeshVisualizer::Position{}); +@endcode + +Rendering setup the same as above. + +@see @ref shaders @todo Understand and add support wireframe width/smoothness without GS */ class MAGNUM_SHADERS_EXPORT MeshVisualizer: public AbstractShaderProgram { public: - typedef Attribute<0, Vector3> Position; /**< @brief Vertex position */ + /** + * @brief Vertex position + * + * @ref shaders-generic "Generic attribute", @ref Vector3. + */ + typedef Attribute<0, Vector3> Position; /** * @brief Vertex index * - * Used only in OpenGL < 3.1 and OpenGL ES 2.0 if @ref Flag::Wireframe - * is enabled. This attribute specifies index of given vertex in - * triangle, i.e. `0` for first, `1` for second, `2` for third. In - * OpenGL 3.1, OpenGL ES 3.0 and newer this value is provided by the - * shader itself, so the attribute is not needed. + * @ref Magnum::Float "Float", used only in OpenGL < 3.1 and OpenGL ES + * 2.0 if @ref Flag::Wireframe is enabled. This attribute (modulo 3) + * specifies index of given vertex in triangle, i.e. `0` for first, `1` + * for second, `2` for third. In OpenGL 3.1, OpenGL ES 3.0 and newer + * this value is provided by the shader itself, so the attribute is not + * needed. */ typedef Attribute<3, Float> VertexIndex; diff --git a/src/Magnum/Shaders/Phong.h b/src/Magnum/Shaders/Phong.h index 63e5348de..91ddf8fbe 100644 --- a/src/Magnum/Shaders/Phong.h +++ b/src/Magnum/Shaders/Phong.h @@ -48,17 +48,108 @@ If you want to use texture instead of color, you need to provide also @ref TextureCoordinates attribute. Pass appropriate flags to constructor and then at render time don't forget to also call appropriate subset of @ref setAmbientTexture(), @ref setDiffuseTexture() and @ref setSpecularTexture(). + +@image html shaders-phong.png +@image latex shaders-phong.png + +## Example usage + +### Colored mesh + +Common mesh setup: +@code +struct Vertex { + Vector3 position; + Vector3 normal; +}; +Vertex data[] = { ... }; + +Buffer vertices; +vertices.setData(data, BufferUsage::StaticDraw); + +Mesh mesh; +mesh.addVertexBuffer(vertices, 0, + Shaders::Phong::Position{}, + Shaders::Phong::Normal{}); +@endcode + +Common rendering setup: +@code +Matrix4 transformationMatrix = Matrix4::translation(Vector3::zAxis(-5.0f)); +Matrix4 projectionMatrix = Matrix4::perspectiveProjection(35.0_degf, 1.0f, 0.001f, 100.0f); + +Shaders::Phong shader; +shader.setDiffuseColor(Color3::fromHSV(216.0_degf, 0.85f, 1.0f)) + .setShininess(200.0f) + .setLightPosition({5.0f, 5.0f, 7.0f}) + .setTransformationMatrix(transformationMatrix) + .setNormalMatrix(transformationMatrix.rotation()) + .setProjectionMatrix(projectionMatrix); + +mesh.draw(shader); +@endcode + +### Diffuse and specular texture + +Common mesh setup: +@code +struct Vertex { + Vector3 position; + Vector3 normal; + Vector2 textureCoordinates; +}; +Vertex data[] = { ... }; + +Buffer vertices; +vertices.setData(data, BufferUsage::StaticDraw); + +Mesh mesh; +mesh.addVertexBuffer(vertices, 0, + Shaders::Phong::Position{}, + Shaders::Phong::Normal{}, + Shaders::Phong::TextureCoordinates{}); +@endcode + +Common rendering setup: +@code +Matrix4 transformationMatrix, projectionMatrix; +Texture2D diffuseTexture, specularTexture; + +Shaders::Phong shader{Shaders::Phong::DiffuseTexture| + Shaders::Phong::SpecularTexture}; +shader.setTextures(nullptr, &diffuseTexture, &specularTexture) + .setLightPosition({5.0f, 5.0f, 7.0f}) + .setTransformationMatrix(transformationMatrix) + .setNormalMatrix(transformationMatrix.rotation()) + .setProjectionMatrix(projectionMatrix); + +mesh.draw(shader); +@endcode + +@see @ref shaders */ class MAGNUM_SHADERS_EXPORT Phong: public AbstractShaderProgram { public: - typedef Generic3D::Position Position; /**< @brief Vertex position */ - typedef Generic3D::Normal Normal; /**< @brief Normal direction */ + /** + * @brief Vertex position + * + * @ref shaders-generic "Generic attribute", @ref Vector3. + */ + typedef Generic3D::Position Position; + + /** + * @brief Normal direction + * + * @ref shaders-generic "Generic attribute", @ref Vector3. + */ + typedef Generic3D::Normal Normal; /** - * @brief Texture coordinates + * @brief 2D texture coordinates * - * Used only if one of @ref Flag::AmbientTexture, @ref Flag::DiffuseTexture - * or @ref Flag::SpecularTexture is set. + * @ref shaders-generic "Generic attribute", @ref Vector2, used only if + * at least one of @ref Flag::AmbientTexture, @ref Flag::DiffuseTexture + * and @ref Flag::SpecularTexture is set. */ typedef Generic3D::TextureCoordinates TextureCoordinates; @@ -121,7 +212,7 @@ class MAGNUM_SHADERS_EXPORT Phong: public AbstractShaderProgram { * @brief Set ambient color * @return Reference to self (for method chaining) * - * If not set, default value is `(0.0f, 0.0f, 0.0f)`. Has no effect if + * If not set, default value is `{0.0f, 0.0f, 0.0f}`. Has no effect if * @ref Flag::AmbientTexture is set. * @see @ref setAmbientTexture() */ @@ -158,7 +249,7 @@ class MAGNUM_SHADERS_EXPORT Phong: public AbstractShaderProgram { * @brief Set specular color * @return Reference to self (for method chaining) * - * If not set, default value is `(1.0f, 1.0f, 1.0f)`. Has no effect if + * If not set, default value is `{1.0f, 1.0f, 1.0f}`. Has no effect if * @ref Flag::SpecularTexture is set. * @see @ref setSpecularTexture() */ @@ -240,7 +331,7 @@ class MAGNUM_SHADERS_EXPORT Phong: public AbstractShaderProgram { * @brief Set light color * @return Reference to self (for method chaining) * - * If not set, default value is `(1.0f, 1.0f, 1.0f)`. + * If not set, default value is `{1.0f, 1.0f, 1.0f}`. */ Phong& setLightColor(const Color3& color) { setUniform(lightColorUniform, color); diff --git a/src/Magnum/Shaders/Vector.h b/src/Magnum/Shaders/Vector.h index 196b13366..13c69662a 100644 --- a/src/Magnum/Shaders/Vector.h +++ b/src/Magnum/Shaders/Vector.h @@ -43,8 +43,47 @@ namespace Magnum { namespace Shaders { Renders vector art in plain grayscale form. See also @ref DistanceFieldVector for more advanced effects. For rendering unchanged texture you can use the -@ref Flat shader. -@see @ref Vector2D, @ref Vector3D +@ref Flat shader. You need to provide @ref Position and @ref TextureCoordinates +attributes in your triangle mesh and call at least +@ref setTransformationProjectionMatrix(), @ref setColor() and +@ref setVectorTexture(). + +@image html shaders-vector.png +@image latex shaders-vector.png + +## Example usage + +Common mesh setup: +@code +struct Vertex { + Vector2 position; + Vector2 textureCoordinates; +}; +Vertex data[] = { ... }; + +Buffer vertices; +vertices.setData(data, BufferUsage::StaticDraw); + +Mesh mesh; +mesh.addVertexBuffer(vertices, 0, + Shaders::Vector2D::Position{}, + Shaders::Vector2D::TextureCoordinates{}); +@endcode + +Common rendering setup: +@code +Matrix3 transformationMatrix, projectionMatrix; +Texture2D texture; + +Shaders::Vector2D shader; +shader.setColor(Color3::fromHSV(216.0_degf, 0.85f, 1.0f)) + .setVectorTexture(texture) + .setTransformationProjectionMatrix(projectionMatrix*transformationMatrix); + +mesh.draw(shader); +@endcode + +@see @ref shaders, @ref Vector2D, @ref Vector3D */ template class MAGNUM_SHADERS_EXPORT Vector: public AbstractVector { public: diff --git a/src/Magnum/Shaders/VertexColor.h b/src/Magnum/Shaders/VertexColor.h index b7b8aafbd..97881ec57 100644 --- a/src/Magnum/Shaders/VertexColor.h +++ b/src/Magnum/Shaders/VertexColor.h @@ -41,15 +41,60 @@ namespace Magnum { namespace Shaders { /** @brief Vertex color shader -Draws vertex-colored mesh. -@see @ref VertexColor2D, @ref VertexColor3D +Draws vertex-colored mesh. You need to provide @ref Position and @ref Color +attributes in your triangle mesh and call at least +@ref setTransformationProjectionMatrix(). + +@image html shaders-vertexcolor.png +@image latex shaders-vertexcolor.png + +## Example usage + +Common mesh setup: +@code +struct Vertex { + Vector3 position; + Color3 color; +}; +Vertex data[] = { ... }; + +Buffer vertices; +vertices.setData(data, BufferUsage::StaticDraw); + +Mesh mesh; +mesh.addVertexBuffer(vertices, 0, + Shaders::VertexColor3D::Position{}, + Shaders::VertexColor3D::Color{}); +@endcode + +Common rendering setup: +@code +Matrix4 transformationMatrix = Matrix4::translation(Vector3::zAxis(-5.0f)); +Matrix4 projectionMatrix = Matrix4::perspectiveProjection(35.0_degf, 1.0f, 0.001f, 100.0f); + +Shaders::VertexColor3D shader; +shader.setTransformationProjectionMatrix(projectionMatrix*transformationMatrix); + +mesh.draw(shader); +@endcode + +@see @ref shaders, @ref VertexColor2D, @ref VertexColor3D */ template class MAGNUM_SHADERS_EXPORT VertexColor: public AbstractShaderProgram { public: - /** @brief Vertex position */ + /** + * @brief Vertex position + * + * @ref shaders-generic "Generic attribute", @ref Vector2 in 2D, + * @ref Vector3 in 3D. + */ typedef typename Generic::Position Position; - /** @brief Vertex color */ + /** + * @brief Vertex color + * + * @ref shaders-generic "Generic attribute", @ref Vector3. + */ typedef Attribute<3, Color3> Color; explicit VertexColor();