Add other files.....

This commit is contained in:
Dave Pugmire 2023-02-16 21:56:18 -05:00
parent fd613f2c84
commit a6856a3f3a
6 changed files with 1049 additions and 0 deletions

123
README Normal file

@ -0,0 +1,123 @@
vtkh:
tests/vtkh/vtk-h_render.cpp
TEST(vtkh_render, vtkh_bg_color)
make data
bounds
camera setup.
vtkh::MakeRender(...)
vtkh::Render: info needed to create a single image. N domains = N canvases
camera, bounds, FG/BG colors
vtkh::RayTracer tracer;
tracer.SetInput(...);
vtkh::Scene scene;
scene.AddRender(render);
scene.AddRenderer(&tracer);
scene.Render();
vtkh::RayTracer : public vtkh::Renderer
--it returns a vtkm::rendering::CanvasRayTracer(width,height)
DoExecute() does the rendering
PostExecute() does the compositing.
vtkh::Scene
list of vtkh::Renderer (raytracer, ...)
vector of vtkh::Render (camera, data, fg/bg)
Scene::Render():
for each renderer:
renderer->Update() does the rendering.
(do opaque, then volume)
RenderWorldAnnotations()
Render::RenderWorldAnnotations()
if rank != 0 then RETURN
Annotator annotator(canvas, camera, m_scene_bounds)
annotator.RenderWorldAnnotations()
RenderScreenAnnotations()
vtkh::Image. pixels, depth, composite order, ...
vtkh::Renderer : public Filter
DoExecute:
for each ds in m_input
m_mapper->RenderCells(ds)
this->Composite(...)
vtkh::Compositor
Composite()
calls RadixKCompositor, etc.
vtkh::Render
camera
image name
width/height/bounds
fg/bg colors
vtkh::RayTracer
SetInput: dataset
SetField: scalar
vtkh::Scene
AddRender: vtkh::Render
AddRenderer: vtkh::RayTracer
vtkh::Scene.Render();
=======================================================================================
vtkm:
vtkm::rendering::Scene
AddActor: dataset
Render(mapper, canvas, camera)
vtkm::rendering::View
camera
canvas
mapper
scene
annotations
Paint() does the rendering
vtkm::rendering::Canvas
Fg/Bg
color/depth buffers
model/view mtx
============================================
VTK-m: simpler example... ?
examples/demo/Demo.cxx
vtkm::rendering::Camera (look at, up, clip, etc).
vtkm::rendering::Actor (dataset)
vtkm::rendering::CanvasRayTracer (x,y)
vtkm::rendering::Scene (actor)
vtkm::rendering::View3D view (scene, mapper, canvas, camera, bg)
view.Paint() (renders the image).
=========================================================================================
Comparing classes, etc.
Camera: the same. vtkm::rendering::Camera
Scene:
vtkm: vector of vtkm::rendering::Actor
vtkh: list/vector of vtkh::Renderer, batchsize, has_volume.
vtkh::Render aprox equal to vtkm::rendering::View

@ -0,0 +1,104 @@
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// Copyright (c) 2018, Lawrence Livermore National Security, LLC.
//
// Produced at the Lawrence Livermore National Laboratory
//
// LLNL-CODE-749865
//
// All rights reserved.
//
// This file is part of Rover.
//
// Please also read rover/LICENSE
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the disclaimer below.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the disclaimer (as noted below) in the
// documentation and/or other materials provided with the distribution.
//
// * Neither the name of the LLNS/LLNL nor the names of its contributors may
// be used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL SECURITY,
// LLC, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
// IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
#ifndef rover_absorption_partial_h
#define rover_absorption_partial_h
#include <assert.h>
namespace vtkh
{
template <typename FloatType>
struct AbsorptionPartial
{
typedef FloatType ValueType;
int m_pixel_id;
double m_depth;
std::vector<FloatType> m_bins;
AbsorptionPartial()
: m_pixel_id(0)
, m_depth(0.f)
{
}
void print() {}
bool operator<(const AbsorptionPartial<FloatType>& other) const
{
//
// In absorption only we can blend the same
// pixel ids in any order
//
return m_pixel_id < other.m_pixel_id;
}
inline void blend(const AbsorptionPartial<FloatType>& other)
{
const int num_bins = static_cast<int>(m_bins.size());
assert(num_bins == (int)other.m_bins.size());
for (int i = 0; i < num_bins; ++i)
{
m_bins[i] *= other.m_bins[i];
}
}
static void composite_background(std::vector<AbsorptionPartial>& partials,
const std::vector<FloatType>& background)
{
const int size = static_cast<int>(partials.size());
AbsorptionPartial<FloatType> bg;
bg.m_bins = background;
#ifdef VTKH_OPENMP_ENABLED
#pragma omp parallel for
#endif
for (int i = 0; i < size; ++i)
{
partials[i].blend(bg);
}
}
};
} // namespace rover
#endif

@ -0,0 +1,141 @@
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// Copyright (c) 2018, Lawrence Livermore National Security, LLC.
//
// Produced at the Lawrence Livermore National Laboratory
//
// LLNL-CODE-749865
//
// All rights reserved.
//
// This file is part of Rover.
//
// Please also read rover/LICENSE
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the disclaimer below.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the disclaimer (as noted below) in the
// documentation and/or other materials provided with the distribution.
//
// * Neither the name of the LLNS/LLNL nor the names of its contributors may
// be used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL SECURITY,
// LLC, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
// IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
#ifndef rover_emission_partial_h
#define rover_emission_partial_h
#include <assert.h>
namespace vtkh
{
template <typename FloatType>
struct EmissionPartial
{
typedef FloatType ValueType;
int m_pixel_id;
double m_depth;
std::vector<FloatType> m_bins;
std::vector<FloatType> m_emission_bins;
EmissionPartial()
: m_pixel_id(0)
, m_depth(0.f)
{
}
void alter_bin(int bin, FloatType value)
{
m_bins[bin] = value;
m_emission_bins[bin] = value;
}
void print()
{
std::cout << "Partial id " << m_pixel_id << "\n";
std::cout << "Absorption : ";
for (int i = 0; i < m_bins.size(); ++i)
{
std::cout << m_bins[i] << " ";
}
std::cout << "\n";
std::cout << "Emission: ";
for (int i = 0; i < m_bins.size(); ++i)
{
std::cout << m_emission_bins[i] << " ";
}
std::cout << "\n";
}
bool operator<(const EmissionPartial<FloatType>& other) const
{
if (m_pixel_id != other.m_pixel_id)
{
return m_pixel_id < other.m_pixel_id;
}
else
{
return m_depth < other.m_depth;
}
}
inline void blend_absorption(const EmissionPartial<FloatType>& other)
{
const int num_bins = static_cast<int>(m_bins.size());
assert(num_bins == (int)other.m_bins.size());
for (int i = 0; i < num_bins; ++i)
{
m_bins[i] *= other.m_bins[i];
}
}
inline void blend_emission(EmissionPartial<FloatType>& other)
{
const int num_bins = static_cast<int>(m_bins.size());
assert(num_bins == (int)other.m_bins.size());
for (int i = 0; i < num_bins; ++i)
{
m_emission_bins[i] *= other.m_bins[i];
}
}
inline void add_emission(EmissionPartial<FloatType>& other)
{
const int num_bins = static_cast<int>(m_bins.size());
assert(num_bins == (int)other.m_bins.size());
for (int i = 0; i < num_bins; ++i)
{
m_emission_bins[i] += other.m_emission_bins[i];
}
}
static void composite_background(std::vector<EmissionPartial>& partials,
const std::vector<FloatType>& background)
{
//for(
}
};
} // namespace rover
#endif

@ -0,0 +1,537 @@
//============================================================================
// 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.
//============================================================================
#include <algorithm>
#include <assert.h>
#include <limits>
#include <vtkm/rendering/compositing/PartialCompositor.h>
#ifdef VTKM_ENABLE_MPI
#include "vtkh_diy_partial_collect.hpp"
#include "vtkh_diy_partial_redistribute.hpp"
#include <mpi.h>
#endif
namespace vtkh
{
namespace detail
{
template <template <typename> class PartialType, typename FloatType>
void BlendPartials(const int& total_segments,
const int& total_partial_comps,
std::vector<int>& pixel_work_ids,
std::vector<PartialType<FloatType>>& partials,
std::vector<PartialType<FloatType>>& output_partials,
const int output_offset)
{
//
// Perform the compositing and output the result in the output
//
#ifdef VTKH_OPENMP_ENABLED
#pragma omp parallel for
#endif
for (int i = 0; i < total_segments; ++i)
{
int current_index = pixel_work_ids[i];
PartialType<FloatType> result = partials[current_index];
++current_index;
PartialType<FloatType> next = partials[current_index];
// TODO: we could just count the amount of work and make this a for loop(vectorize??)
while (result.m_pixel_id == next.m_pixel_id)
{
result.blend(next);
if (current_index + 1 >= total_partial_comps)
{
// we could break early for volumes,
// but blending past 1.0 alpha is no op.
break;
}
++current_index;
next = partials[current_index];
}
output_partials[output_offset + i] = result;
}
//placeholder
//PartialType<FloatType>::composite_background(output_partials, background_values);
}
template <typename T>
void BlendEmission(const int& total_segments,
const int& total_partial_comps,
std::vector<int>& pixel_work_ids,
std::vector<EmissionPartial<T>>& partials,
std::vector<EmissionPartial<T>>& output_partials,
const int output_offset)
{
//
// Perform the compositing and output the result in the output
// This code computes the optical depth (total absorption)
// along each rays path.
//
#ifdef VTKH_OPENMP_ENABLED
#pragma omp parallel for
#endif
for (int i = 0; i < total_segments; ++i)
{
int current_index = pixel_work_ids[i];
EmissionPartial<T> result = partials[current_index];
++current_index;
EmissionPartial<T> next = partials[current_index];
// TODO: we could just count the amount of work and make this a for loop(vectorize??)
while (result.m_pixel_id == next.m_pixel_id)
{
result.blend_absorption(next);
if (current_index == total_partial_comps - 1)
{
break;
}
++current_index;
next = partials[current_index];
}
output_partials[output_offset + i] = result;
}
//placeholder
//EmissionPartial::composite_background(output_partials);
// TODO: now blend source signature with output
//
// Emission bins contain the amout of energy that leaves each
// ray segment. To compute the amount of energy that reaches
// the detector, we must multiply the segments emissed energy
// by the optical depth of the remaining path to the detector.
// To calculate the optical depth of the remaining path, we
// do perform a reverse scan of absorption for each pixel id
//
#ifdef VTKH_OPENMP_ENABLED
#pragma omp parallel for
#endif
for (int i = 0; i < total_segments; ++i)
{
const int segment_start = pixel_work_ids[i];
int current_index = segment_start;
//
// move forward to the end of the segment
//
while (partials[current_index].m_pixel_id == partials[current_index + 1].m_pixel_id)
{
++current_index;
if (current_index == total_partial_comps - 1)
{
break;
}
}
//
// set the intensity emerging out of the last segment
//
output_partials[output_offset + i].m_emission_bins = partials[current_index].m_emission_bins;
//
// now move backwards accumulating absorption for each segment
// and then blending the intensity emerging from the previous
// segment.
//
current_index--;
while (current_index != segment_start - 1)
{
partials[current_index].blend_absorption(partials[current_index + 1]);
// mult this segments emission by the absorption in front
partials[current_index].blend_emission(partials[current_index + 1]);
// add remaining emissed engery to the output
output_partials[output_offset + i].add_emission(partials[current_index]);
--current_index;
}
}
}
template <>
void BlendPartials<EmissionPartial, float>(const int& total_segments,
const int& total_partial_comps,
std::vector<int>& pixel_work_ids,
std::vector<EmissionPartial<float>>& partials,
std::vector<EmissionPartial<float>>& output_partials,
const int output_offset)
{
BlendEmission(
total_segments, total_partial_comps, pixel_work_ids, partials, output_partials, output_offset);
}
template <>
void BlendPartials<EmissionPartial, double>(const int& total_segments,
const int& total_partial_comps,
std::vector<int>& pixel_work_ids,
std::vector<EmissionPartial<double>>& partials,
std::vector<EmissionPartial<double>>& output_partials,
const int output_offset)
{
BlendEmission(
total_segments, total_partial_comps, pixel_work_ids, partials, output_partials, output_offset);
}
} // namespace detail
//--------------------------------------------------------------------------------------------
template <typename PartialType>
PartialCompositor<PartialType>::PartialCompositor()
{
}
//--------------------------------------------------------------------------------------------
template <typename PartialType>
PartialCompositor<PartialType>::~PartialCompositor()
{
}
//--------------------------------------------------------------------------------------------
template <typename PartialType>
void PartialCompositor<PartialType>::merge(const std::vector<std::vector<PartialType>>& in_partials,
std::vector<PartialType>& partials,
int& global_min_pixel,
int& global_max_pixel)
{
int total_partial_comps = 0;
const int num_partial_images = static_cast<int>(in_partials.size());
int* offsets = new int[num_partial_images];
int* pixel_mins = new int[num_partial_images];
int* pixel_maxs = new int[num_partial_images];
for (int i = 0; i < num_partial_images; ++i)
{
offsets[i] = total_partial_comps;
total_partial_comps += in_partials[i].size();
}
partials.resize(total_partial_comps);
#ifdef VTKH_OPENMP_ENABLED
#pragma omp parallel for
#endif
for (int i = 0; i < num_partial_images; ++i)
{
//
// Extract the partial composites into a contiguous array
//
std::copy(in_partials[i].begin(), in_partials[i].end(), partials.begin() + offsets[i]);
} // for each partial image
//
// Calculate the range of pixel ids
//
int max_pixel = std::numeric_limits<int>::min();
#ifdef VTKH_OPENMP_ENABLED
#pragma omp parallel for reduction(max : max_pixel)
#endif
for (int i = 0; i < total_partial_comps; ++i)
{
int val = partials[i].m_pixel_id;
if (val > max_pixel)
{
max_pixel = val;
}
}
int min_pixel = std::numeric_limits<int>::max();
#ifdef VTKH_OPENMP_ENABLED
#pragma omp parallel for reduction(min : min_pixel)
#endif
for (int i = 0; i < total_partial_comps; ++i)
{
int val = partials[i].m_pixel_id;
if (val < min_pixel)
{
min_pixel = val;
}
}
//
// determine the global pixel mins and maxs
//
global_min_pixel = min_pixel;
global_max_pixel = max_pixel;
#ifdef VTKM_ENABLE_MPI
MPI_Comm comm_handle = MPI_Comm_f2c(m_mpi_comm_id);
int rank_min = global_min_pixel;
int rank_max = global_max_pixel;
int mpi_min;
int mpi_max;
MPI_Allreduce(&rank_min, &mpi_min, 1, MPI_INT, MPI_MIN, comm_handle);
MPI_Allreduce(&rank_max, &mpi_max, 1, MPI_INT, MPI_MAX, comm_handle);
global_min_pixel = mpi_min;
global_max_pixel = mpi_max;
#endif
delete[] offsets;
delete[] pixel_mins;
delete[] pixel_maxs;
}
//--------------------------------------------------------------------------------------------
template <typename PartialType>
void PartialCompositor<PartialType>::composite_partials(std::vector<PartialType>& partials,
std::vector<PartialType>& output_partials)
{
const int total_partial_comps = partials.size();
if (total_partial_comps == 0)
{
output_partials = partials;
return;
}
//
// Sort the composites
//
std::sort(partials.begin(), partials.end());
//
// Find the number of unique pixel_ids with work
//
std::vector<unsigned char> work_flags;
std::vector<unsigned char> unique_flags;
work_flags.resize(total_partial_comps);
unique_flags.resize(total_partial_comps);
//
// just check the first and last entries manualy to reduce the
// loop complexity
//
if (partials[0].m_pixel_id == partials[1].m_pixel_id)
{
work_flags[0] = 1;
unique_flags[0] = 0;
}
else
{
work_flags[0] = 0;
unique_flags[0] = 1;
}
if (partials[total_partial_comps - 1].m_pixel_id != partials[total_partial_comps - 2].m_pixel_id)
{
unique_flags[total_partial_comps - 1] = 1;
}
else
{
unique_flags[total_partial_comps - 1] = 0;
}
const int n_minus_one = total_partial_comps - 1;
#ifdef VTKH_OPENMP_ENABLED
#pragma omp parallel for
#endif
for (int i = 1; i < n_minus_one; ++i)
{
unsigned char work_flag = 0;
unsigned char unique_flag = 0;
bool is_begining = false;
if (partials[i].m_pixel_id != partials[i - 1].m_pixel_id)
{
is_begining = true;
}
bool has_compositing_work = false;
if (partials[i].m_pixel_id == partials[i + 1].m_pixel_id)
{
has_compositing_work = true;
}
if (is_begining && has_compositing_work)
{
work_flag = 1;
}
if (is_begining && !has_compositing_work)
{
unique_flag = 1;
}
work_flags[i] = work_flag;
unique_flags[i] = unique_flag;
}
// count the number of of unique pixels
int total_segments = 0;
#ifdef VTKH_OPENMP_ENABLED
#pragma omp parallel for shared(work_flags) reduction(+ : total_segments)
#endif
for (int i = 0; i < total_partial_comps; ++i)
{
total_segments += work_flags[i];
}
int total_unique_pixels = 0;
#ifdef VTKH_OPENMP_ENABLED
#pragma omp parallel for shared(unique_flags) reduction(+ : total_unique_pixels)
#endif
for (int i = 0; i < total_partial_comps; ++i)
{
total_unique_pixels += unique_flags[i];
}
if (total_segments == 0)
{
//nothing to do
}
//
// find the pixel indexes that have compositing work
//
std::vector<int> pixel_work_ids;
pixel_work_ids.resize(total_segments);
int current_index = 0;
for (int i = 0; i < total_partial_comps; ++i)
{
if (work_flags[i] == 1)
{
pixel_work_ids[current_index] = i;
++current_index;
}
}
//
// find the pixel indexes that have NO compositing work
//
std::vector<int> unique_ids;
unique_ids.resize(total_unique_pixels);
current_index = 0;
for (int i = 0; i < total_partial_comps; ++i)
{
if (unique_flags[i] == 1)
{
unique_ids[current_index] = i;
++current_index;
}
}
const int total_output_pixels = total_unique_pixels + total_segments;
output_partials.resize(total_output_pixels);
//
// Gather the unique pixels into the output
//
#ifdef VTKH_OPENMP_ENABLED
#pragma omp parallel for
#endif
for (int i = 0; i < total_unique_pixels; ++i)
{
PartialType result = partials[unique_ids[i]];
output_partials[i] = result;
}
//
// perform compositing if there are more than
// one segment per ray
//
detail::BlendPartials(total_segments,
total_partial_comps,
pixel_work_ids,
partials,
output_partials,
total_unique_pixels);
}
//--------------------------------------------------------------------------------------------
template <typename PartialType>
void PartialCompositor<PartialType>::composite(
std::vector<std::vector<PartialType>>& partial_images,
std::vector<PartialType>& output_partials)
{
int global_partial_images = partial_images.size();
#ifdef VTKM_ENABLE_MPI
MPI_Comm comm_handle = MPI_Comm_f2c(m_mpi_comm_id);
int local_partials = global_partial_images;
MPI_Allreduce(&local_partials, &global_partial_images, 1, MPI_INT, MPI_SUM, comm_handle);
#endif
#ifdef VTKM_ENABLE_MPI
// we could have no data, but it could exist elsewhere
#endif
std::vector<PartialType> partials;
int global_min_pixel;
int global_max_pixel;
merge(partial_images, partials, global_min_pixel, global_max_pixel);
if (global_min_pixel > global_max_pixel)
{
// just bail
return;
}
#ifdef VTKM_ENABLE_MPI
//
// Exchange partials with other ranks
//
redistribute(partials, comm_handle, global_min_pixel, global_max_pixel);
MPI_Barrier(comm_handle);
#endif
const int total_partial_comps = partials.size();
//
// TODO: check to see if we have less than one
//
//assert(total_partial_comps > 1);
composite_partials(partials, output_partials);
#ifdef VTKM_ENABLE_MPI
//
// Collect all of the distibuted pixels
//
collect(output_partials, comm_handle);
MPI_Barrier(comm_handle);
#endif
}
template <typename PartialType>
void PartialCompositor<PartialType>::set_background(std::vector<vtkm::Float32>& background_values)
{
const size_t size = background_values.size();
m_background_values.resize(size);
for (size_t i = 0; i < size; ++i)
{
m_background_values[i] = background_values[i];
}
}
template <typename PartialType>
void PartialCompositor<PartialType>::set_background(std::vector<vtkm::Float64>& background_values)
{
const size_t size = background_values.size();
m_background_values.resize(size);
for (size_t i = 0; i < size; ++i)
{
m_background_values[i] = background_values[i];
}
}
template <typename PartialType>
void PartialCompositor<PartialType>::set_comm_handle(int mpi_comm_id)
{
m_mpi_comm_id = mpi_comm_id;
}
//Explicit function instantiations
template class VTKH_API PartialCompositor<VolumePartial<vtkm::Float32>>;
template class VTKH_API PartialCompositor<VolumePartial<vtkm::Float64>>;
template class VTKH_API PartialCompositor<AbsorptionPartial<vtkm::Float32>>;
template class VTKH_API PartialCompositor<AbsorptionPartial<vtkm::Float64>>;
template class VTKH_API PartialCompositor<EmissionPartial<vtkm::Float32>>;
template class VTKH_API PartialCompositor<EmissionPartial<vtkm::Float64>>;
} // namespace vtkh

@ -0,0 +1,53 @@
//============================================================================
// 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.
//============================================================================
#ifndef vtkm_rendering_compositing_partial_compositor_h
#define vtkm_rendering_compositing_partial_compositor_h
#include <vtkm/rendering/vtkm_rendering_export.h>
#include "AbsorptionPartial.hpp"
#include "EmissionPartial.hpp"
#include "VolumePartial.hpp"
#include <iostream>
#include <vector>
#include <vtkm/Types.h>
namespace vtkh
{
template <typename PartialType>
class VTKM_RENDERING_EXPORT PartialCompositor
{
public:
PartialCompositor();
~PartialCompositor();
void composite(std::vector<std::vector<PartialType>>& partial_images,
std::vector<PartialType>& output_partials);
void set_background(std::vector<vtkm::Float32>& background_values);
void set_background(std::vector<vtkm::Float64>& background_values);
void set_comm_handle(int mpi_comm_id);
protected:
void merge(const std::vector<std::vector<PartialType>>& in_partials,
std::vector<PartialType>& partials,
int& global_min_pixel,
int& global_max_pixel);
void composite_partials(std::vector<PartialType>& partials,
std::vector<PartialType>& output_partials);
std::vector<typename PartialType::ValueType> m_background_values;
int m_mpi_comm_id;
};
}; // namespace rover
#endif //vtkm_rendering_compositing_partial_compositor_h

@ -0,0 +1,91 @@
//============================================================================
// 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.
//============================================================================
#ifndef rover_volume_block_h
#define rover_volume_block_h
#include <limits>
namespace vtkh
{
template <typename FloatType>
struct VolumePartial
{
typedef FloatType ValueType;
int m_pixel_id;
float m_depth;
float m_pixel[3];
float m_alpha;
VolumePartial()
: m_pixel_id(0)
, m_depth(0.f)
, m_alpha(0.f)
{
m_pixel[0] = 0;
m_pixel[1] = 0;
m_pixel[2] = 0;
}
void print() const
{
std::cout << "[id : " << m_pixel_id << ", red : " << m_pixel[0] << ","
<< " green : " << m_pixel[1] << ", blue : " << m_pixel[2] << ", alpha " << m_alpha
<< ", depth : " << m_depth << "]\n";
}
bool operator<(const VolumePartial& other) const
{
if (m_pixel_id != other.m_pixel_id)
{
return m_pixel_id < other.m_pixel_id;
}
else
{
return m_depth < other.m_depth;
}
}
inline void blend(const VolumePartial& other)
{
if (m_alpha >= 1.f || other.m_alpha == 0.f)
return;
const float opacity = (1.f - m_alpha);
m_pixel[0] += opacity * other.m_pixel[0];
m_pixel[1] += opacity * other.m_pixel[1];
m_pixel[2] += opacity * other.m_pixel[2];
m_alpha += opacity * other.m_alpha;
m_alpha = m_alpha > 1.f ? 1.f : m_alpha;
}
static void composite_background(std::vector<VolumePartial>& partials,
const std::vector<FloatType>& background)
{
VolumePartial bg_color;
bg_color.m_pixel[0] = static_cast<float>(background[0]);
bg_color.m_pixel[1] = static_cast<float>(background[1]);
bg_color.m_pixel[2] = static_cast<float>(background[2]);
bg_color.m_alpha = static_cast<float>(background[3]);
//
// Gather the unique pixels into the output
//
const int total_pixels = static_cast<int>(partials.size());
#ifdef VTKH_OPENMP_ENABLED
#pragma omp parallel for
#endif
for (int i = 0; i < total_pixels; ++i)
{
partials[i].blend(bg_color);
}
}
};
} // namespace
#endif