From 81a6b6ff3d7faed43f0bcbe211cdb1385519c731 Mon Sep 17 00:00:00 2001 From: Lukas Werner <lks.werner@fau.de> Date: Thu, 5 Dec 2013 23:06:52 +0100 Subject: [PATCH] Added basic antialiasing using supersampling --- src/pe/raytracing/Raytracer.cpp | 38 ++++++++++++++++--------- src/pe/raytracing/Raytracer.h | 13 +++++---- tests/pe/Raytracing.cpp | 50 ++++++++++++++++----------------- 3 files changed, 58 insertions(+), 43 deletions(-) diff --git a/src/pe/raytracing/Raytracer.cpp b/src/pe/raytracing/Raytracer.cpp index ac75c6f93..0664440ec 100644 --- a/src/pe/raytracing/Raytracer.cpp +++ b/src/pe/raytracing/Raytracer.cpp @@ -75,7 +75,7 @@ Raytracer::Raytracer(const shared_ptr<BlockStorage> forest, const BlockDataID st const shared_ptr<BodyStorage> globalBodyStorage, const BlockDataID ccdID, uint16_t pixelsHorizontal, uint16_t pixelsVertical, - real_t fov_vertical, + real_t fov_vertical, uint8_t antiAliasFactor, const Vec3& cameraPosition, const Vec3& lookAtPoint, const Vec3& upVector, const Lighting& lighting, const Color& backgroundColor, @@ -83,7 +83,7 @@ Raytracer::Raytracer(const shared_ptr<BlockStorage> forest, const BlockDataID st std::function<ShadingParameters (const BodyID)> bodyToShadingParamsFunction) : forest_(forest), storageID_(storageID), globalBodyStorage_(globalBodyStorage), ccdID_(ccdID), pixelsHorizontal_(pixelsHorizontal), pixelsVertical_(pixelsVertical), - fov_vertical_(fov_vertical), + fov_vertical_(fov_vertical), antiAliasFactor_(antiAliasFactor), cameraPosition_(cameraPosition), lookAtPoint_(lookAtPoint), upVector_(upVector), lighting_(lighting), backgroundColor_(backgroundColor), @@ -109,12 +109,13 @@ Raytracer::Raytracer(const shared_ptr<BlockStorage> forest, const BlockDataID st * \param storageID Storage ID of the block data storage the raytracer operates on. * \param config Config block for the raytracer. * - * The config block has to contain image_x (int), image_y (int), fov_vertical (real, in degrees) - * and tbuffer_output_directory (string) parameters. Additionally a vector of reals - * for each of cameraPosition, lookAt and the upVector. Optional is blockAABBIntersectionPadding (real) and backgroundColor (Vec3). + * The config block has to contain image_x (int), image_y (int), fov_vertical (real, in degrees) and + * antiAliasFactor (uint, between 1 and 4). Additionally a vector of reals for each of cameraPosition, lookAt + * and the upVector. Optional is blockAABBIntersectionPadding (real) and backgroundColor (Vec3). * To output both process local and global tbuffers after raytracing, set tbuffer_output_directory (string). * For image output after raytracing, set image_output_directory (string); for local image output additionally set - * local_image_output_enabled (bool) to true. outputFilenameTimestepZeroPadding (int) sets zero padding for timesteps of output filenames. + * local_image_output_enabled (bool) to true. outputFilenameTimestepZeroPadding (int) sets zero padding + * for timesteps of output filenames. * For the lighting a config block named Lighting has to be defined, information about its contents is in Lighting.h. */ Raytracer::Raytracer(const shared_ptr<BlockStorage> forest, const BlockDataID storageID, @@ -131,6 +132,7 @@ Raytracer::Raytracer(const shared_ptr<BlockStorage> forest, const BlockDataID st pixelsHorizontal_ = config.getParameter<uint16_t>("image_x"); pixelsVertical_ = config.getParameter<uint16_t>("image_y"); fov_vertical_ = config.getParameter<real_t>("fov_vertical"); + antiAliasFactor_ = config.getParameter<uint8_t>("antiAliasFactor", 1); if (config.isDefined("tbuffer_output_directory")) { setTBufferOutputEnabled(true); @@ -196,8 +198,8 @@ void Raytracer::setupView_() { viewingPlaneWidth_ = viewingPlaneHeight_ * aspectRatio_; viewingPlaneOrigin_ = lookAtPoint_ - u_*viewingPlaneWidth_/real_t(2.) - v_*viewingPlaneHeight_/real_t(2.); - pixelWidth_ = viewingPlaneWidth_ / real_c(pixelsHorizontal_); - pixelHeight_ = viewingPlaneHeight_ / real_c(pixelsVertical_); + pixelWidth_ = viewingPlaneWidth_ / real_c(pixelsHorizontal_*antiAliasFactor_); + pixelHeight_ = viewingPlaneHeight_ / real_c(pixelsVertical_*antiAliasFactor_); } /*!\brief Utility function for initializing the attribute filenameRankWidth. @@ -360,12 +362,22 @@ void Raytracer::writeImageToFile(const std::vector<BodyIntersectionInfo>& inters std::vector<u_char> lodeImageBuffer(pixelsHorizontal_*pixelsVertical_*3); uint32_t l = 0; + real_t patchSize = real_c(antiAliasFactor_*antiAliasFactor_); for (int y = pixelsVertical_-1; y >= 0; y--) { - for (size_t x = 0; x < pixelsHorizontal_; x++) { - size_t i = coordinateToArrayIndex(x, uint_c(y)); - u_char r = (u_char)(255 * intersectionsBuffer[i].r); - u_char g = (u_char)(255 * intersectionsBuffer[i].g); - u_char b = (u_char)(255 * intersectionsBuffer[i].b); + for (uint x = 0; x < pixelsHorizontal_; x++) { + real_t r_sum = 0, g_sum = 0, b_sum = 0; + for (uint ay = y*antiAliasFactor_; ay < (y+1)*antiAliasFactor_; ay++) { + for (uint ax = x*antiAliasFactor_; ax < (x+1)*antiAliasFactor_; ax++) { + size_t i = coordinateToArrayIndex(ax, ay); + r_sum += intersectionsBuffer[i].r; + g_sum += intersectionsBuffer[i].g; + b_sum += intersectionsBuffer[i].b; + } + } + u_char r = (u_char)(255 * (r_sum/patchSize)); + u_char g = (u_char)(255 * (g_sum/patchSize)); + u_char b = (u_char)(255 * (b_sum/patchSize)); + lodeImageBuffer[l] = r; lodeImageBuffer[l+1] = g; lodeImageBuffer[l+2] = b; diff --git a/src/pe/raytracing/Raytracer.h b/src/pe/raytracing/Raytracer.h index f3ecb4983..3f25bdba9 100644 --- a/src/pe/raytracing/Raytracer.h +++ b/src/pe/raytracing/Raytracer.h @@ -71,7 +71,7 @@ public: const shared_ptr<BodyStorage> globalBodyStorage, const BlockDataID ccdID, uint16_t pixelsHorizontal, uint16_t pixelsVertical, - real_t fov_vertical, + real_t fov_vertical, uint8_t antiAliasFactor, const Vec3& cameraPosition, const Vec3& lookAtPoint, const Vec3& upVector, const Lighting& lighting, const Color& backgroundColor = Color(real_t(0.1), real_t(0.1), real_t(0.1)), @@ -95,6 +95,8 @@ private: uint16_t pixelsHorizontal_; //!< The horizontal amount of pixels of the generated image. uint16_t pixelsVertical_; //!< The vertical amount of pixels of the generated image. real_t fov_vertical_; //!< The vertical field-of-view of the camera. + uint8_t antiAliasFactor_; /*!< Factor used for oversampling. Should be between 1 (fast, but jagged edges) + * and 4 (16 times slower, very smooth edges).*/ Vec3 cameraPosition_; //!< The position of the camera in the global world frame. Vec3 lookAtPoint_; /*!< The point the camera looks at in the global world frame, marks the center of the view plane.*/ @@ -420,7 +422,7 @@ inline bool Raytracer::isPlaneVisible(const PlaneID plane, const Ray& ray) const * \return Array index. */ inline size_t Raytracer::coordinateToArrayIndex(size_t x, size_t y) const { - return y*pixelsHorizontal_ + x; + return y*pixelsHorizontal_*antiAliasFactor_ + x; } /*!\brief Traces a ray in the global body storage and finds the closest ray-body intersection. @@ -547,7 +549,8 @@ void Raytracer::generateImage(const size_t timestep, WcTimingTree* tt) { real_t inf = std::numeric_limits<real_t>::max(); std::vector<BodyIntersectionInfo> intersections; - std::vector<BodyIntersectionInfo> intersectionsBuffer(pixelsVertical_ * pixelsHorizontal_); // contains for each pixel information about an intersection, if existent + // contains for each pixel information about an intersection: + std::vector<BodyIntersectionInfo> intersectionsBuffer(pixelsVertical_*antiAliasFactor_ * pixelsHorizontal_*antiAliasFactor_); if (raytracingAlgorithm_ == RAYTRACE_HASHGRIDS || raytracingAlgorithm_ == RAYTRACE_COMPARE_BOTH || raytracingAlgorithm_ == RAYTRACE_COMPARE_BOTH_STRICTLY) { @@ -576,8 +579,8 @@ void Raytracer::generateImage(const size_t timestep, WcTimingTree* tt) { #endif if (tt != NULL) tt->start("Intersection Testing"); - for (size_t x = 0; x < pixelsHorizontal_; x++) { - for (size_t y = 0; y < pixelsVertical_; y++) { + for (size_t x = 0; x < pixelsHorizontal_*antiAliasFactor_; x++) { + for (size_t y = 0; y < pixelsVertical_*antiAliasFactor_; y++) { Vec3 pixelLocation = viewingPlaneOrigin_ + u_*(real_c(x)+real_t(0.5))*pixelWidth_ + v_*(real_c(y)+real_t(0.5))*pixelHeight_; Vec3 direction = (pixelLocation - cameraPosition_).getNormalized(); ray.setDirection(direction); diff --git a/tests/pe/Raytracing.cpp b/tests/pe/Raytracing.cpp index c12dda18c..5b450b9d1 100644 --- a/tests/pe/Raytracing.cpp +++ b/tests/pe/Raytracing.cpp @@ -233,7 +233,7 @@ ShadingParameters customBodyToShadingParams(const BodyID body) { } } -void RaytracerTest(Raytracer::Algorithm raytracingAlgorithm = Raytracer::RAYTRACE_HASHGRIDS) { +void RaytracerTest(Raytracer::Algorithm raytracingAlgorithm = Raytracer::RAYTRACE_HASHGRIDS, uint8_t antiAliasFactor = 1) { WALBERLA_LOG_INFO("Raytracer"); shared_ptr<BodyStorage> globalBodyStorage = make_shared<BodyStorage>(); shared_ptr<BlockForest> forest = createBlockForest(AABB(0,0,0,10,10,10), Vector3<uint_t>(1,1,1), Vector3<bool>(false, false, false)); @@ -246,7 +246,7 @@ void RaytracerTest(Raytracer::Algorithm raytracingAlgorithm = Raytracer::RAYTRAC Color(real_t(0.4), real_t(0.4), real_t(0.4))); //ambient Raytracer raytracer(forest, storageID, globalBodyStorage, ccdID, size_t(640), size_t(480), - real_t(49.13), + real_t(49.13), antiAliasFactor, Vec3(-5,5,5), Vec3(-1,5,5), Vec3(0,0,1), //-5,5,5; -1,5,5 lighting, Color(real_t(0.2), real_t(0.2), real_t(0.2)), @@ -335,7 +335,7 @@ ShadingParameters customSpheresBodyToShadingParams(const BodyID body) { } } -void RaytracerSpheresTestScene(Raytracer::Algorithm raytracingAlgorithm = Raytracer::RAYTRACE_HASHGRIDS) { +void RaytracerSpheresTestScene(Raytracer::Algorithm raytracingAlgorithm = Raytracer::RAYTRACE_HASHGRIDS, uint8_t antiAliasFactor = 1) { WALBERLA_LOG_INFO("Raytracer Spheres Scene"); shared_ptr<BodyStorage> globalBodyStorage = make_shared<BodyStorage>(); shared_ptr<BlockForest> forest = createBlockForest(AABB(0,0,0,10,10,10), Vector3<uint_t>(1,1,1), Vector3<bool>(false, false, false)); @@ -348,7 +348,7 @@ void RaytracerSpheresTestScene(Raytracer::Algorithm raytracingAlgorithm = Raytra Color(real_t(0.4), real_t(0.4), real_t(0.4))); //ambient Raytracer raytracer(forest, storageID, globalBodyStorage, ccdID, size_t(640), size_t(480), - real_t(49.13), + real_t(49.13), antiAliasFactor, Vec3(-5,5,5), Vec3(-1,5,5), Vec3(0,0,1), //-5,5,5; -1,5,5 lighting, Color(real_t(0.2),real_t(0.2),real_t(0.2)), @@ -387,7 +387,7 @@ ShadingParameters customHashGridsBodyToShadingParams(const BodyID body) { } -void HashGridsTest(Raytracer::Algorithm raytracingAlgorithm, +void HashGridsTest(Raytracer::Algorithm raytracingAlgorithm, uint8_t antiAliasFactor, size_t boxes, size_t capsules, size_t spheres, size_t numberOfViews = 1, real_t boxLenMin = real_t(0.1), real_t boxLenMax = real_t(0.2), bool boxRotation = false, real_t capRadiusMin = real_t(0.1), real_t capRadiusMax = real_t(0.2), real_t capLenMin = real_t(0.1), real_t capLenMax = real_t(0.3), @@ -529,7 +529,7 @@ void HashGridsTest(Raytracer::Algorithm raytracingAlgorithm, Raytracer raytracer(forest, storageID, globalBodyStorage, ccdID, size_t(640), size_t(480), - real_t(49.13), + real_t(49.13), antiAliasFactor, std::get<0>(vector), std::get<1>(vector), std::get<2>(vector), @@ -558,7 +558,7 @@ ShadingParameters customArtifactsBodyToShadingParams(const BodyID body) { return defaultShadingParams(body); } -void raytraceArtifactsForest(Raytracer::Algorithm raytracingAlgorithm, +void raytraceArtifactsForest(Raytracer::Algorithm raytracingAlgorithm, uint8_t antiAliasFactor, const shared_ptr<BlockStorage> forest, const BlockDataID storageID, const shared_ptr<BodyStorage> globalBodyStorage, const BlockDataID ccdID, @@ -573,7 +573,7 @@ void raytraceArtifactsForest(Raytracer::Algorithm raytracingAlgorithm, Raytracer raytracer(forest, storageID, globalBodyStorage, ccdID, size_t(640), size_t(480), - real_t(49.13), + real_t(49.13), antiAliasFactor, cameraPosition, lookAtPoint, upVector, @@ -593,7 +593,7 @@ void raytraceArtifactsForest(Raytracer::Algorithm raytracingAlgorithm, } } -void HashGridsArtifactsTest(Raytracer::Algorithm raytracingAlgorithm, +void HashGridsArtifactsTest(Raytracer::Algorithm raytracingAlgorithm, uint8_t antiAliasFactor, size_t boxes, real_t boxLenMin = real_t(0.1), real_t boxLenMax = real_t(0.2)) { WALBERLA_LOG_INFO_ON_ROOT("HashGrids Artifacts Test - In negative Z direction"); @@ -628,13 +628,13 @@ void HashGridsArtifactsTest(Raytracer::Algorithm raytracingAlgorithm, WALBERLA_CHECK(box_ != NULL); } - raytraceArtifactsForest(raytracingAlgorithm, + raytraceArtifactsForest(raytracingAlgorithm, antiAliasFactor, forest, storageID, globalBodyStorage, ccdID, Vec3(2, 2, 7), Vec3(2, 2, 4), Vec3(0,1,0), boxes, 3); } -void HashGridsFromNegativeArtifactsTest(Raytracer::Algorithm raytracingAlgorithm, +void HashGridsFromNegativeArtifactsTest(Raytracer::Algorithm raytracingAlgorithm, uint8_t antiAliasFactor, size_t boxes, real_t boxLenMin = real_t(0.1), real_t boxLenMax = real_t(0.2)) { WALBERLA_LOG_INFO_ON_ROOT("HashGrids Artifacts Test - In positive Z direction"); @@ -673,13 +673,13 @@ void HashGridsFromNegativeArtifactsTest(Raytracer::Algorithm raytracingAlgorithm WALBERLA_CHECK(box_ != NULL); } - raytraceArtifactsForest(raytracingAlgorithm, + raytraceArtifactsForest(raytracingAlgorithm, antiAliasFactor, forest, storageID, globalBodyStorage, ccdID, Vec3(2, 2, -3), Vec3(2, 2, 0), Vec3(0,1,0), boxes, 4); } -void HashGridsFromNegativeXArtifactsTest(Raytracer::Algorithm raytracingAlgorithm, +void HashGridsFromNegativeXArtifactsTest(Raytracer::Algorithm raytracingAlgorithm, uint8_t antiAliasFactor, size_t boxes, real_t boxLenMin = real_t(0.1), real_t boxLenMax = real_t(0.2)) { WALBERLA_LOG_INFO_ON_ROOT("HashGrids Artifacts Test - In positive X direction"); WALBERLA_LOG_INFO_ON_ROOT(" Generating " << boxes << " boxes"); @@ -716,7 +716,7 @@ void HashGridsFromNegativeXArtifactsTest(Raytracer::Algorithm raytracingAlgorith WALBERLA_CHECK(box_ != NULL); } - raytraceArtifactsForest(raytracingAlgorithm, + raytraceArtifactsForest(raytracingAlgorithm, antiAliasFactor, forest, storageID, globalBodyStorage, ccdID, Vec3(-3, 2, 2), Vec3(0, 2, 2), Vec3(0,0,1), boxes, 6); @@ -727,7 +727,7 @@ Vec3 minCornerToGpos(const Vec3& minCorner, real_t lengths) { return minCorner + Vec3(lengths/2, lengths/2, lengths/2); } -void HashGridsTestScene(Raytracer::Algorithm raytracingAlgorithm = Raytracer::RAYTRACE_HASHGRIDS) { +void HashGridsTestScene(Raytracer::Algorithm raytracingAlgorithm = Raytracer::RAYTRACE_HASHGRIDS, uint8_t antiAliasFactor = 1) { WALBERLA_LOG_INFO_ON_ROOT("HashGrids Test Scene"); shared_ptr<BodyStorage> globalBodyStorage = make_shared<BodyStorage>(); @@ -813,7 +813,7 @@ void HashGridsTestScene(Raytracer::Algorithm raytracingAlgorithm = Raytracer::RA for (auto& vector: viewVectors) { Raytracer raytracer(forest, storageID, globalBodyStorage, ccdID, size_t(640), size_t(480), - real_t(49.13), + real_t(49.13), antiAliasFactor, std::get<0>(vector), std::get<1>(vector), std::get<2>(vector), @@ -851,22 +851,22 @@ int main( int argc, char** argv ) CapsuleIntersectsTest(); const Raytracer::Algorithm algorithm = Raytracer::RAYTRACE_COMPARE_BOTH_STRICTLY; - - RaytracerTest(algorithm); - //RaytracerSpheresTestScene(algorithm); - HashGridsTestScene(algorithm); - HashGridsTest(algorithm, + const uint8_t antiAliasFactor = 1; + RaytracerTest(algorithm, antiAliasFactor); + //RaytracerSpheresTestScene(algorithm, antiAliasFactor); + HashGridsTestScene(algorithm, antiAliasFactor); + HashGridsTest(algorithm, antiAliasFactor, 50, 30, 130, 10); - HashGridsTest(algorithm, + HashGridsTest(algorithm, antiAliasFactor, 60, 60, 3, 1, real_t(0.1), real_t(0.3), true, real_t(0.1), real_t(0.2), real_t(0.1), real_t(0.2), real_t(0.5), real_t(0.6)); - HashGridsArtifactsTest(algorithm, 750, real_t(0.2), real_t(0.3)); - HashGridsFromNegativeArtifactsTest(algorithm, 750, real_t(0.2), real_t(0.3)); - HashGridsFromNegativeXArtifactsTest(algorithm, 750, real_t(0.2), real_t(0.3)); + HashGridsArtifactsTest(algorithm, antiAliasFactor, 750, real_t(0.2), real_t(0.3)); + HashGridsFromNegativeArtifactsTest(algorithm, antiAliasFactor, 750, real_t(0.2), real_t(0.3)); + HashGridsFromNegativeXArtifactsTest(algorithm, antiAliasFactor, 750, real_t(0.2), real_t(0.3)); return EXIT_SUCCESS; } -- GitLab