//============================================================================ // Copyright (c) Kitware, Inc. // All rights reserved. // See LICENSE.txt for details. // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notice for more information. // // Copyright 2015 Sandia Corporation. // Copyright 2015 UT-Battelle, LLC. // Copyright 2015 Los Alamos National Security. // // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, // the U.S. Government retains certain rights in this software. // // Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National // Laboratory (LANL), the U.S. Government retains certain rights in // this software. //============================================================================ #include #include #include #include #include #include #include #include namespace vtkm { namespace rendering { namespace internal { class SurfaceConverter : public vtkm::worklet::WorkletMapField { vtkm::Matrix ViewProjMat; public: VTKM_CONT SurfaceConverter(const vtkm::Matrix viewProjMat) : ViewProjMat(viewProjMat) { } typedef void ControlSignature(FieldIn<>, WholeArrayInOut<>, FieldIn<>, FieldIn<>, FieldIn<>, ExecObject, ExecObject); typedef void ExecutionSignature(_1, _2, _3, _4, _5, _6, _7, WorkIndex); template VTKM_EXEC void operator()( const vtkm::Id& pixelIndex, ColorPortalType& colorBufferIn, const Precision& inDepth, const vtkm::Vec& origin, const vtkm::Vec& dir, vtkm::exec::ExecutionWholeArray& depthBuffer, vtkm::exec::ExecutionWholeArray>& colorBuffer, const vtkm::Id& index) const { vtkm::Vec intersection = origin + inDepth * dir; vtkm::Vec point; point[0] = static_cast(intersection[0]); point[1] = static_cast(intersection[1]); point[2] = static_cast(intersection[2]); point[3] = 1.f; vtkm::Vec newpoint; newpoint = vtkm::MatrixMultiply(this->ViewProjMat, point); newpoint[0] = newpoint[0] / newpoint[3]; newpoint[1] = newpoint[1] / newpoint[3]; newpoint[2] = newpoint[2] / newpoint[3]; vtkm::Float32 depth = newpoint[2]; depth = 0.5f * (depth) + 0.5f; vtkm::Vec color; color[0] = static_cast(colorBufferIn.Get(index * 4 + 0)); color[1] = static_cast(colorBufferIn.Get(index * 4 + 1)); color[2] = static_cast(colorBufferIn.Get(index * 4 + 2)); color[3] = static_cast(colorBufferIn.Get(index * 4 + 3)); // blend the mapped color with existing canvas color vtkm::Vec inColor = colorBuffer.Get(pixelIndex); vtkm::Float32 alpha = inColor[3] * (1.f - color[3]); color[0] = color[0] + inColor[0] * alpha; color[1] = color[1] + inColor[1] * alpha; color[2] = color[2] + inColor[2] * alpha; color[3] = alpha + color[3]; // clamp for (vtkm::Int32 i = 0; i < 4; ++i) { color[i] = vtkm::Min(1.f, vtkm::Max(color[i], 0.f)); } // The existng depth should already been feed into thge ray mapper // so no color contribution will exist past the existing depth. depthBuffer.Set(pixelIndex, depth); colorBuffer.Set(pixelIndex, color); } }; //class SurfaceConverter template struct WriteFunctor { protected: vtkm::rendering::CanvasRayTracer* Canvas; const vtkm::rendering::raytracing::Ray& Rays; const vtkm::cont::ArrayHandle& Colors; const vtkm::rendering::Camera& CameraView; vtkm::Matrix ViewProjMat; public: VTKM_CONT WriteFunctor(vtkm::rendering::CanvasRayTracer* canvas, const vtkm::rendering::raytracing::Ray& rays, const vtkm::cont::ArrayHandle& colors, const vtkm::rendering::Camera& camera) : Canvas(canvas) , Rays(rays) , Colors(colors) , CameraView(camera) { ViewProjMat = vtkm::MatrixMultiply( CameraView.CreateProjectionMatrix(Canvas->GetWidth(), Canvas->GetHeight()), CameraView.CreateViewMatrix()); } template VTKM_CONT bool operator()(Device) { VTKM_IS_DEVICE_ADAPTER_TAG(Device); vtkm::worklet::DispatcherMapField(SurfaceConverter(ViewProjMat)) .Invoke( Rays.PixelIdx, Colors, Rays.Distance, Rays.Origin, Rays.Dir, vtkm::exec::ExecutionWholeArray(Canvas->GetDepthBuffer()), vtkm::exec::ExecutionWholeArray>(Canvas->GetColorBuffer())); return true; } }; template VTKM_CONT void WriteToCanvas(const vtkm::rendering::raytracing::Ray& rays, const vtkm::cont::ArrayHandle& colors, const vtkm::rendering::Camera& camera, vtkm::rendering::CanvasRayTracer* canvas) { WriteFunctor functor(canvas, rays, colors, camera); vtkm::cont::TryExecute(functor); //Force the transfer so the vectors contain data from device canvas->GetColorBuffer().GetPortalControl().Get(0); canvas->GetDepthBuffer().GetPortalControl().Get(0); } } // namespace internal CanvasRayTracer::CanvasRayTracer(vtkm::Id width, vtkm::Id height) : Canvas(width, height) { } CanvasRayTracer::~CanvasRayTracer() { } void CanvasRayTracer::WriteToCanvas(const vtkm::rendering::raytracing::Ray& rays, const vtkm::cont::ArrayHandle& colors, const vtkm::rendering::Camera& camera) { internal::WriteToCanvas(rays, colors, camera, this); } void CanvasRayTracer::WriteToCanvas(const vtkm::rendering::raytracing::Ray& rays, const vtkm::cont::ArrayHandle& colors, const vtkm::rendering::Camera& camera) { internal::WriteToCanvas(rays, colors, camera, this); } vtkm::rendering::Canvas* CanvasRayTracer::NewCopy() const { return new vtkm::rendering::CanvasRayTracer(*this); } } }