From 270b932d213fa076c723bd1c7c4f5b438e369dc2 Mon Sep 17 00:00:00 2001 From: Lukas Werner <lks.werner@fau.de> Date: Sat, 3 Feb 2018 12:32:10 +0100 Subject: [PATCH] Added Color class --- src/pe/raytracing/Color.h | 78 +++++++++++++++++++++++++++++++++ src/pe/raytracing/Lighting.h | 15 ++++--- src/pe/raytracing/Raytracer.cpp | 10 ++--- src/pe/raytracing/Raytracer.h | 62 ++++++++++---------------- tests/pe/Raytracing.cpp | 9 ++-- 5 files changed, 120 insertions(+), 54 deletions(-) create mode 100644 src/pe/raytracing/Color.h diff --git a/src/pe/raytracing/Color.h b/src/pe/raytracing/Color.h new file mode 100644 index 000000000..9bf6cfee7 --- /dev/null +++ b/src/pe/raytracing/Color.h @@ -0,0 +1,78 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// waLBerla is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \author Lukas Werner +// +//====================================================================================================================== + +#pragma once + +#include "core/math/Vector3.h" + +namespace walberla { +namespace pe { +namespace raytracing { +class Color: public Vector3<real_t> { +public: + /*!\name Constructors */ + //@{ + /*!\brief Instantiation constructor for the Color class. Defaults to white. + */ + Color () : Color(1, 1, 1) { + + } + + /*!\brief Instantiation constructor for the Color class. + * \param r Red component + * \param g Green component + * \param b Blue component + * Instantiation constructor for the Color class with RGB components. Each value should be between 0 and 1 (soft limits) + */ + Color (real_t r, real_t g, real_t b) : Vector3<real_t>(r, g, b) { + + } + //@} + + /*!\brief Instantiation constructor for the Color class. + * \param r Red component + * \param g Green component + * \param b Blue component + * Instantiation constructor for the Color class with RGB components. Each value should be between 0 and 1 (soft limits) + */ + Color (const Vec3& vector) : Color(vector[0], vector[1], vector[2]) { + + } + //@} + + /*!\brief Multiply this color with another component wise. + * \return Color with components of this and other multiplied. + */ + inline Color mulComponentWise(const Color& other) const { + return Color((*this)[0]*other[0], + (*this)[1]*other[1], + (*this)[2]*other[2]); + } + + /*!\brief Clamps this colors component values between 0 and 1. + */ + inline void clamp() { + (*this)[0] = std::min(std::max((*this)[0], real_t(0)), real_t(1)); + (*this)[1] = std::min(std::max((*this)[1], real_t(0)), real_t(1)); + (*this)[2] = std::min(std::max((*this)[2], real_t(0)), real_t(1)); + } +}; +} +} +} diff --git a/src/pe/raytracing/Lighting.h b/src/pe/raytracing/Lighting.h index e4a045659..29ff1e3b3 100644 --- a/src/pe/raytracing/Lighting.h +++ b/src/pe/raytracing/Lighting.h @@ -23,15 +23,16 @@ #include <pe/basic.h> #include <pe/Types.h> #include <core/math/Vector3.h> +#include <pe/raytracing/Color.h> namespace walberla { namespace pe { namespace raytracing { struct Lighting { Vec3 pointLightOrigin; - Vec3 diffuseColor; - Vec3 specularColor; - Vec3 ambientColor; + Color diffuseColor; + Color specularColor; + Color ambientColor; /*!\brief Instantiation constructor for the Lighting struct. */ @@ -46,7 +47,7 @@ struct Lighting { * \param ambientColor Color of the ambient light. */ Lighting (const Vec3& _pointLightOrigin, - const Vec3& _diffuseColor, const Vec3& _specularColor, const Vec3& _ambientColor) + const Color& _diffuseColor, const Color& _specularColor, const Color& _ambientColor) : pointLightOrigin(_pointLightOrigin), diffuseColor(_diffuseColor), specularColor(_specularColor), ambientColor(_ambientColor) { @@ -63,9 +64,9 @@ struct Lighting { WALBERLA_CHECK(config.isValid(), "No valid config passed to raytracer lighting."); pointLightOrigin = config.getParameter<Vec3>("pointLightOrigin"); - diffuseColor = config.getParameter<Vec3>("diffuseColor", Vec3(1,1,1)); - specularColor = config.getParameter<Vec3>("specularColor", Vec3(1,1,1)); - ambientColor = config.getParameter<Vec3>("ambientColor", Vec3(0.5,0.5,0.5)); + diffuseColor = config.getParameter<Color>("diffuseColor", Color(1,1,1)); + specularColor = config.getParameter<Color>("specularColor", Color(1,1,1)); + ambientColor = config.getParameter<Color>("ambientColor", Color(0.5,0.5,0.5)); } }; } diff --git a/src/pe/raytracing/Raytracer.cpp b/src/pe/raytracing/Raytracer.cpp index 7eaed3b7f..785f865c9 100644 --- a/src/pe/raytracing/Raytracer.cpp +++ b/src/pe/raytracing/Raytracer.cpp @@ -50,7 +50,7 @@ Raytracer::Raytracer(const shared_ptr<BlockStorage> forest, BlockDataID storageI real_t fov_vertical, const Vec3& cameraPosition, const Vec3& lookAtPoint, const Vec3& upVector, const Lighting& lighting, - const Vec3& backgroundColor, + const Color& backgroundColor, real_t blockAABBIntersectionPadding) : forest_(forest), storageID_(storageID), globalBodyStorage_(globalBodyStorage), pixelsHorizontal_(pixelsHorizontal), pixelsVertical_(pixelsVertical), @@ -110,7 +110,7 @@ Raytracer::Raytracer(const shared_ptr<BlockStorage> forest, BlockDataID storageI lookAtPoint_ = config.getParameter<Vec3>("lookAt"); upVector_ = config.getParameter<Vec3>("upVector"); lighting_ = Lighting(config.getBlock("Lighting")); - backgroundColor_ = config.getParameter<Vec3>("backgroundColor", Vec3(0.1, 0.1, 0.1)); + backgroundColor_ = config.getParameter<Color>("backgroundColor", Vec3(0.1, 0.1, 0.1)); blockAABBIntersectionPadding_ = config.getParameter<real_t>("blockAABBIntersectionPadding", real_t(0.0)); @@ -208,7 +208,7 @@ void Raytracer::writeTBufferToFile(const std::vector<real_t>& tBuffer, const std * \param timestep Timestep this image is from. * \param isGlobalImage Whether this image is the fully stitched together one. */ -void Raytracer::writeImageBufferToFile(const std::vector<Vec3>& imageBuffer, size_t timestep, bool isGlobalImage) const { +void Raytracer::writeImageBufferToFile(const std::vector<Color>& imageBuffer, size_t timestep, bool isGlobalImage) const { WALBERLA_CHECK(timestep < 100000, "Raytracer only supports outputting 99 999 timesteps."); mpi::MPIRank rank = mpi::MPIManager::instance()->rank(); uint8_t padding = (timestep < 10 ? 4 : @@ -224,7 +224,7 @@ void Raytracer::writeImageBufferToFile(const std::vector<Vec3>& imageBuffer, siz * \param imageBuffer Buffer with color vectors. * \param fileName Name of the output file. */ -void Raytracer::writeImageBufferToFile(const std::vector<Vec3>& imageBuffer, const std::string& fileName) const { +void Raytracer::writeImageBufferToFile(const std::vector<Color>& imageBuffer, const std::string& fileName) const { namespace fs = boost::filesystem; fs::path dir (getImageOutputDirectory()); @@ -236,7 +236,7 @@ void Raytracer::writeImageBufferToFile(const std::vector<Vec3>& imageBuffer, con for (size_t y = pixelsVertical_-1; y > 0; y--) { for (size_t x = 0; x < pixelsHorizontal_; x++) { size_t i = coordinateToArrayIndex(x, y); - const Vec3& color = imageBuffer[i]; + const Color& color = imageBuffer[i]; char r = (char)(255 * color[0]); char g = (char)(255 * color[1]); char b = (char)(255 * color[2]); diff --git a/src/pe/raytracing/Raytracer.h b/src/pe/raytracing/Raytracer.h index 6afa38e18..5bb9fa77b 100644 --- a/src/pe/raytracing/Raytracer.h +++ b/src/pe/raytracing/Raytracer.h @@ -59,7 +59,7 @@ public: real_t fov_vertical, const Vec3& cameraPosition, const Vec3& lookAtPoint, const Vec3& upVector, const Lighting& lighting, - const Vec3& backgroundColor = Vec3(0.1, 0.1, 0.1), + const Color& backgroundColor = Color(0.1, 0.1, 0.1), real_t blockAABBIntersectionPadding = real_t(0.0)); explicit Raytracer(const shared_ptr<BlockStorage> forest, BlockDataID storageID, const shared_ptr<BodyStorage> globalBodyStorage, @@ -82,7 +82,7 @@ private: marks the center of the view plane.*/ Vec3 upVector_; //!< The vector indicating the upwards direction of the camera. Lighting lighting_; //!< The lighting of the scene. - Vec3 backgroundColor_; //!< Background color of the scene. + Color backgroundColor_; //!< Background color of the scene. real_t blockAABBIntersectionPadding_; /*!< The padding applied in block AABB intersection pretesting, as some objects within a block might protrude from the block's AABB.*/ @@ -115,7 +115,7 @@ public: inline const Vec3& getCameraPosition() const; inline const Vec3& getLookAtPoint() const; inline const Vec3& getUpVector() const; - inline const Vec3& getBackgroundColor() const; + inline const Color& getBackgroundColor() const; inline bool getTBufferOutputEnabled() const; inline const std::string& getTBufferOutputDirectory() const; inline bool getImageOutputEnabled() const; @@ -125,7 +125,7 @@ public: /*!\name Set functions */ //@{ - inline void setBackgroundColor(const Vec3& color); + inline void setBackgroundColor(const Color& color); inline void setTBufferOutputEnabled(const bool enabled); inline void setTBufferOutputDirectory(const std::string& path); inline void setImageOutputEnabled(const bool enabled); @@ -142,14 +142,13 @@ public: private: void writeTBufferToFile(const std::vector<real_t>& tBuffer, size_t timestep, bool isGlobalImage = false) const; void writeTBufferToFile(const std::vector<real_t>& tBuffer, const std::string& fileName) const; - void writeImageBufferToFile(const std::vector<Vec3>& imageBuffer, size_t timestep, bool isGlobalImage = false) const; - void writeImageBufferToFile(const std::vector<Vec3>& imageBuffer, const std::string& fileName) const; + void writeImageBufferToFile(const std::vector<Color>& imageBuffer, size_t timestep, bool isGlobalImage = false) const; + void writeImageBufferToFile(const std::vector<Color>& imageBuffer, const std::string& fileName) const; inline bool isPlaneVisible(const PlaneID plane, const Ray& ray) const; inline size_t coordinateToArrayIndex(size_t x, size_t y) const; - inline Vec3 multiplyColors(const Vec3& a, const Vec3& b) const; - inline Vec3 getColor(const BodyID body, const Ray& ray, real_t t, const Vec3& n) const; + inline Color getColor(const BodyID body, const Ray& ray, real_t t, const Vec3& n) const; //@} }; @@ -214,7 +213,7 @@ inline const Vec3& Raytracer::getUpVector() const { * * Returns the background color of the scene. */ -inline const Vec3& Raytracer::getBackgroundColor() const { +inline const Color& Raytracer::getBackgroundColor() const { return backgroundColor_; } @@ -262,7 +261,7 @@ inline const std::string& Raytracer::getImageOutputDirectory() const { * * \param color New background color. */ -inline void Raytracer::setBackgroundColor(const Vec3& color) { +inline void Raytracer::setBackgroundColor(const Color& color) { backgroundColor_ = color; } @@ -346,7 +345,7 @@ void Raytracer::rayTrace(const size_t timestep) { int rank = mpi::MPIManager::instance()->rank(); std::vector<real_t> tBuffer(pixelsVertical_ * pixelsHorizontal_, inf); - std::vector<Vec3> imageBuffer(pixelsVertical_ * pixelsHorizontal_); + std::vector<Color> imageBuffer(pixelsVertical_ * pixelsHorizontal_); std::vector<BodyIntersectionInfo> intersections; // contains for each pixel information about an intersection, if existent real_t t, t_closest; @@ -417,7 +416,7 @@ void Raytracer::rayTrace(const size_t timestep) { } if (!realIsIdentical(t_closest, inf) && body_closest != NULL) { - Vec3 color = getColor(body_closest, ray, t_closest, n_closest); + Color color = getColor(body_closest, ray, t_closest, n_closest); imageBuffer[coordinateToArrayIndex(x, y)] = color; BodyIntersectionInfo intersectionInfo = { x, @@ -445,7 +444,7 @@ void Raytracer::rayTrace(const size_t timestep) { } int gatheredIntersectionCount = 0; std::vector<real_t> fullTBuffer(pixelsHorizontal_ * pixelsVertical_, inf); - std::vector<Vec3> fullImageBuffer(pixelsHorizontal_ * pixelsVertical_, backgroundColor_); + std::vector<Color> fullImageBuffer(pixelsHorizontal_ * pixelsVertical_, backgroundColor_); mpi::RecvBuffer recvBuffer; mpi::gathervBuffer(sendBuffer, recvBuffer, 0); @@ -501,17 +500,6 @@ void Raytracer::rayTrace(const size_t timestep) { } } -/*!\brief Multiplies same-index components of two vectors. - * - * \param a Vector to multiply. - * \param b Vector to multiply. - * - * \return Vec3 with components a[i] * b[i] - */ -inline Vec3 Raytracer::multiplyColors(const Vec3& a, const Vec3& b) const { - return Vec3(a[0]*b[0], a[1]*b[1], a[2]*b[2]); -} - /*!\brief Computes the color for a certain intersection. * * \param body Intersected body. @@ -519,29 +507,29 @@ inline Vec3 Raytracer::multiplyColors(const Vec3& a, const Vec3& b) const { * \param t Distance from eye to intersection point. * \param n Intersection normal at the intersection point. * - * \return Vector with RGB color components. + * \return Computed color. */ -inline Vec3 Raytracer::getColor(const BodyID body, const Ray& ray, real_t t, const Vec3& n) const { +inline Color Raytracer::getColor(const BodyID body, const Ray& ray, real_t t, const Vec3& n) const { //---- - Vec3 diffuseColor(0.6, 0, 0.9); - Vec3 specularColor(0.8, 0.8, 0.8); - Vec3 ambientColor(0.5, 0, 0.8); + Color diffuseColor(0.6, 0, 0.9); + Color specularColor(0.8, 0.8, 0.8); + Color ambientColor(0.5, 0, 0.8); real_t shininess = 100; if (body->getTypeID() == Plane::getStaticTypeID()) { - diffuseColor = Vec3(real_t(0.7), real_t(0.7), real_t(0.7)); + diffuseColor = Color(real_t(0.7), real_t(0.7), real_t(0.7)); ambientColor.set(real_t(0.5), real_t(0.5), real_t(0.5)); specularColor.set(real_t(0), real_t(0), real_t(0)); shininess = real_t(0); } if (body->getTypeID() == Sphere::getStaticTypeID()) { - diffuseColor = Vec3(real_t(0.98), real_t(0.1), real_t(0.1)); + diffuseColor = Color(real_t(0.98), real_t(0.1), real_t(0.1)); ambientColor.set(real_t(0.6), real_t(0.05), real_t(0.05)); specularColor.set(real_t(1), real_t(1), real_t(1)); shininess = real_t(30); } if (body->getTypeID() == Capsule::getStaticTypeID()) { - diffuseColor = Vec3(real_t(0.15), real_t(0.44), real_t(0.91)); + diffuseColor = Color(real_t(0.15), real_t(0.44), real_t(0.91)); ambientColor.set(real_t(0), real_t(0), real_t(0.3)); specularColor.set(real_t(1), real_t(1), real_t(1)); shininess = real_t(20); @@ -564,15 +552,13 @@ inline Vec3 Raytracer::getColor(const BodyID body, const Ray& ray, real_t t, con specular = real_c(pow(specularAngle, shininess)); } - Vec3 color = multiplyColors(lighting_.ambientColor, ambientColor) - + multiplyColors(lighting_.diffuseColor, diffuseColor)*lambertian - + multiplyColors(lighting_.specularColor, specularColor)*specular; + Color color = lighting_.ambientColor.mulComponentWise(ambientColor) + + lighting_.diffuseColor.mulComponentWise(diffuseColor)*lambertian + + lighting_.specularColor.mulComponentWise(specularColor)*specular; // Capping of color channels to 1. // Capping instead of scaling will make specular highlights stronger. - color[0] = std::min(real_t(1), color[0]); - color[1] = std::min(real_t(1), color[1]); - color[2] = std::min(real_t(1), color[2]); + color.clamp(); return color; } diff --git a/tests/pe/Raytracing.cpp b/tests/pe/Raytracing.cpp index ee9d0528d..ba13106b2 100644 --- a/tests/pe/Raytracing.cpp +++ b/tests/pe/Raytracing.cpp @@ -19,6 +19,7 @@ #include <pe/raytracing/Ray.h> #include <pe/raytracing/Intersects.h> #include <pe/raytracing/Raytracer.h> +#include <pe/raytracing/Color.h> using namespace walberla; using namespace walberla::pe; @@ -214,15 +215,15 @@ void RaytracerTest() { shared_ptr<BlockForest> forest = createBlockForest(AABB(0,0,0,10,10,10), Vec3(1,1,1), Vec3(false, false, false)); auto storageID = forest->addBlockData(createStorageDataHandling<BodyTuple>(), "Storage"); Lighting lighting(Vec3(0, 5, 8), // 8, 5, 9.5 gut für ebenen, 0,5,8 - Vec3(1, 1, 1), //diffuse - Vec3(1, 1, 1), //specular - Vec3(0.4, 0.4, 0.4)); //ambient + Color(1, 1, 1), //diffuse + Color(1, 1, 1), //specular + Color(0.4, 0.4, 0.4)); //ambient Raytracer raytracer(forest, storageID, globalBodyStorage, size_t(640), size_t(480), 49.13, Vec3(-5,5,5), Vec3(-1,5,5), Vec3(0,0,1), //-5,5,5; -1,5,5 lighting, - Vec3(0.2,0.2,0.2)); + Color(0.2,0.2,0.2)); MaterialID iron = Material::find("iron"); -- GitLab