The expiration time for new job artifacts in CI/CD pipelines is now 30 days (GitLab default). Previously generated artifacts in already completed jobs will not be affected by the change. The latest artifacts for all jobs in the latest successful pipelines will be kept. More information: https://gitlab.lrz.de/help/user/admin_area/settings/continuous_integration.html#default-artifacts-expiration

Commit e20da19c authored by Jakob Weiss's avatar Jakob Weiss
Browse files

Added / fixed stereo module

Somehow I messed up the cherrypick/merge history.
Stereo module provides basic processors for a compositor and a camera
generator to generate stereo images.
parent f75772e3
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2015, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universitaet Muenchen
// Boltzmannstr. 3, 85748 Garching b. Muenchen, Germany
//
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
// ================================================================================================
in vec3 ex_TexCoord;
out vec4 out_Color;
#include "tools/texture2d.frag"
uniform sampler2D _colorTextureLeft;
uniform sampler2D _colorTextureRight;
void main() {
out_Color = vec4(ex_TexCoord, 1.0);
#ifdef MODE_INTERLACE_VERT
//Vertical Interlaced
if (mod(trunc(gl_FragCoord.x), 2.0) < 0.5)
out_Color = texture2D(_colorTextureLeft, vec2(ex_TexCoord));
else
out_Color = texture2D(_colorTextureRight, vec2(ex_TexCoord));
#endif
#ifdef MODE_INTERLACE_HORIZ
//Vertical Interlaced
if (mod(trunc(gl_FragCoord.y), 2.0) < 0.5)
out_Color = texture2D(_colorTextureLeft, vec2(ex_TexCoord));
else
out_Color = texture2D(_colorTextureRight, vec2(ex_TexCoord));
#endif
#ifdef MODE_SIDEBYSIDE_VERT
// Vertical Side-by-Side (i.e. top/bottom)
if(ex_TexCoord.y < 0.5)
out_Color = texture2D(_colorTextureLeft, vec2(ex_TexCoord.x, ex_TexCoord.y * 2.0));
else
out_Color = texture2D(_colorTextureRight, vec2(ex_TexCoord.x, (ex_TexCoord.y - 0.5) * 2.0));
#endif
#ifdef MODE_SIDEBYSIDE_HORIZ
// Horizontal Side-by-Side (i.e. left/right)
if(ex_TexCoord.x < 0.5)
out_Color = texture2D(_colorTextureLeft, vec2(ex_TexCoord.x * 2.0, ex_TexCoord.y));
else
out_Color = texture2D(_colorTextureRight, vec2((ex_TexCoord.x - 0.5) * 2.0, ex_TexCoord.y));
#endif
#ifdef MODE_ANAGLYPH_MCALLISTER
// Anaglyph rendering based on https://research.csc.ncsu.edu/stereographics/LS.pdf
// anaglyph color transform matrices for red/cyan
mat3 P_L = mat3(
0.4155, -0.0458, -0.0545, // first column
0.4710, -0.0484, -0.0614, // second column
0.1670, -0.0258, 0.0128 // third column
);
mat3 P_R = mat3(
-0.0109, 0.3756, -0.0651, // first column
-0.0365, 0.7333, -0.1286, // second column
-0.0060, 0.0111, 1.2968 // third column
);
vec4 cLeft = texture2D(_colorTextureLeft, vec2(ex_TexCoord));
vec4 cRight = texture2D(_colorTextureRight, vec2(ex_TexCoord));
out_Color = clamp(vec4(P_L*cLeft.xyz + P_R * cRight.xyz, 1.0f), 0.0, 1.0);
#endif
// Code for half-color and optimized anaglyph from https://wiki.delphigl.com/index.php/shader_Stereoscopy
#ifdef MODE_ANAGLYPH_HALFCOLOR
//Half-Color Anaglyph
vec3 cleft = texture2D(_colorTextureLeft, vec2(ex_TexCoord)).xyz;
vec3 cright = texture2D(_colorTextureRight, vec2(ex_TexCoord)).xyz;
out_Color.r = 0.299*cleft.r + 0.587*cleft.g + 0.114*cleft.b; //Half-Color
out_Color.g = cright.g;
out_Color.b = cright.b;
#endif
#ifdef MODE_ANAGLYPH_WIMMER
//"Optimized Anaglyph" by Peteter Wimmer http://www.3dtv.at/knowhow/AnaglyphComparison_en.aspx
vec3 cleft = texture2D(_colorTextureLeft, vec2(ex_TexCoord)).xyz;
vec3 cright = texture2D(_colorTextureRight, vec2(ex_TexCoord)).xyz;
//out_Color.r = 0.7*cleft.g + 0.3*cleft.b; // no gamma correction
out_Color.r = pow(0.7*cleft.g + 0.3*cleft.b, 1.5); // with gamma correction
out_Color.g = cright.g;
out_Color.b = cright.b;
#endif
}
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2015, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universitaet Muenchen
// Boltzmannstr. 3, 85748 Garching b. Muenchen, Germany
//
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
// ================================================================================================
#ifndef STEREOPIPELINE_H__
#define STEREOPIPELINE_H__
#include "core/pipeline/autoevaluationpipeline.h"
#include "modules/modulesapi.h"
#include "modules/base/processors/lightsourceprovider.h"
#include "modules/base/processors/trackballcameraprovider.h"
#include "modules/io/processors/vtkimagereader.h"
#include "modules/vis/processors/geometryrenderer.h"
#include "modules/vis/processors/rendertargetcompositor.h"
#include "modules/stereo/processors/stereocompositor.h"
#include "modules/stereo/processors/stereocameragenerator.h"
namespace campvis {
template <class WrappedPipeline>
class CAMPVIS_MODULES_API StereoPipeline: public WrappedPipeline {
public:
/**
* [UNFINISHED / NOT IMPLEMENTED] Creates a StereoRenderDemo pipeline. Wraps an existing pipeline and modifies it for stereo rendering.
* \param dataContainer Reference to the DataContainer containing local working set of data
* for this pipeline, must be valid the whole lifetime of this pipeline.
*/
explicit StereoPipeline(DataContainer& dc)
: WrappedPipeline(dc)
, _stereoCamGenerator()
, _stereoComp(&_canvasSize)
{
};
/**
* Virtual Destructor
**/
virtual ~StereoPipeline()
{
}
/// \see AutoEvaluationPipeline::init()
virtual void init() override
{
addProcessor(&_stereoCamGenerator);
WrappedPipeline::init();
addProcessor(&_stereoComp);
_stereoComp.init(); // we must init this ourselves since this is normally called in the base class init()
_stereoComp.p_outputImage.setValue("Stereo.Final");
_renderTargetID.setValue("Stereo.Final");
}
/// \see AutoEvaluationPipeline::deinit()
virtual void deinit() override {
WrappedPipeline::deinit();
}
virtual void executePipeline() override {
std::cout << "Executing Pipeline.." << std::endl;
WrappedPipeline::executePipeline();
}
/// \see AbstractPipeline::getName()
virtual std::string getName() const { return getId(); };
static const std::string getId() { return std::string("Stereo<") + WrappedPipeline::getId() + ">"; };
protected:
/**
* Slot getting called when one of the observed processors got validated.
* Updates the camera properties, when the input image has changed.
* \param processor The processor that emitted the signal
*/
virtual void onProcessorValidated(AbstractProcessor* processor) override {
std::cout << "Processor " << processor->getInstanceName() << " validated." << std::endl;
};
protected:
StereoCameraGenerator _stereoCamGenerator;
StereoCompositor _stereoComp;
};
}
#endif // STEREOPIPELINE_H__
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2015, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universitaet Muenchen
// Boltzmannstr. 3, 85748 Garching b. Muenchen, Germany
//
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
// ================================================================================================
#include "stereorenderdemo.h"
#include "cgt/texturereadertga.h"
#include "core/datastructures/imagedata.h"
#include "core/datastructures/imagerepresentationgl.h"
#include "core/classification/geometry1dtransferfunction.h"
#include "core/classification/tfgeometry1d.h"
#include "core/datastructures/geometrydatafactory.h"
namespace campvis {
StereoRenderDemo::StereoRenderDemo(DataContainer& dc)
: AutoEvaluationPipeline(dc, getId())
, _tcp(&_canvasSize)
, _lsp()
, _geometryReader()
, _lvRendererL(&_canvasSize)
, _teapotRendererL(&_canvasSize)
, _compositorL(&_canvasSize)
, _lvRendererR(&_canvasSize)
, _teapotRendererR(&_canvasSize)
, _compositorR(&_canvasSize)
, _stereoComp(&_canvasSize)
{
addEventListenerToBack(&_tcp);
addProcessor(&_tcp);
addProcessor(&_stereoCamGenerator);
addProcessor(&_lsp);
addProcessor(&_geometryReader);
addProcessor(&_teapotRendererL);
addProcessor(&_lvRendererL);
addProcessor(&_compositorL);
addProcessor(&_teapotRendererR);
addProcessor(&_lvRendererR);
addProcessor(&_compositorR);
addProcessor(&_stereoComp);
}
StereoRenderDemo::~StereoRenderDemo() {
_geometryReader.s_validated.disconnect(this);
}
void StereoRenderDemo::init() {
AutoEvaluationPipeline::init();
// load textureData from file
cgt::TextureReaderTga trt;
cgt::Texture* campTexture = trt.loadTexture(ShdrMgr.completePath("/modules/vis/sampledata/camplogo.tga"), cgt::Texture::LINEAR);
ImageData* textureData = new ImageData(2, campTexture->getDimensions(), campTexture->getNumChannels());
ImageRepresentationGL::create(textureData, campTexture);
getDataContainer().addData("CampTexture", textureData);
// connect slots
_geometryReader.s_validated.connect(this, &StereoRenderDemo::onProcessorValidated);
// create Teapot
auto teapot = GeometryDataFactory::createTeapot();
teapot->applyTransformationToVertices(cgt::mat4::createScale(cgt::vec3(50.f)));
getDataContainer().addData("teapot", teapot.release());
// setup pipeline
_geometryReader.p_url.setValue(ShdrMgr.completePath("/modules/vis/sampledata/left_ventricle_mesh.vtk"));
_geometryReader.p_targetImageID.setValue("reader.output");
_lvRendererL.p_geometryID.setValue("reader.output");
_lvRendererL.p_renderTargetID.setValue("lv.render.left");
_lvRendererL.p_renderMode.selectById("triangles");
_lvRendererL.p_camera.setValue("camera.left");
_lvRendererL.p_solidColor.setValue(cgt::vec4(0.8f, 0.f, 0.f, .9f));
_lvRendererR.p_geometryID.setValue("reader.output");
_lvRendererR.p_renderTargetID.setValue("lv.render.right");
_lvRendererR.p_renderMode.selectById("triangles");
_lvRendererR.p_camera.setValue("camera.right");
_lvRendererR.p_solidColor.setValue(cgt::vec4(0.8f, 0.f, 0.f, .9f));
_teapotRendererL.p_geometryID.setValue("teapot");
_teapotRendererL.p_renderTargetID.setValue("teapot.render.left");
_teapotRendererL.p_renderMode.selectById("trianglestrip");
_teapotRendererL.p_showWireframe.setValue(false);
_teapotRendererL.p_camera.setValue("camera.left");
_teapotRendererL.p_solidColor.setValue(cgt::vec4(1.f, 0.5f, 0.f, 1.f));
_teapotRendererR.p_geometryID.setValue("teapot");
_teapotRendererR.p_renderTargetID.setValue("teapot.render.right");
_teapotRendererR.p_renderMode.selectById("trianglestrip");
_teapotRendererR.p_showWireframe.setValue(false);
_teapotRendererR.p_camera.setValue("camera.right");
_teapotRendererR.p_solidColor.setValue(cgt::vec4(1.f, 0.5f, 0.f, 1.f));
_compositorL.p_firstImageId.setValue("lv.render.left");
_compositorL.p_secondImageId.setValue("teapot.render.left");
_compositorL.p_compositingMethod.selectById("depth");
_compositorL.p_targetImageId.setValue("combine.left");
_compositorL.p_enableBackground.setValue(false);
_compositorR.p_firstImageId.setValue("lv.render.right");
_compositorR.p_secondImageId.setValue("teapot.render.right");
_compositorR.p_compositingMethod.selectById("depth");
_compositorR.p_targetImageId.setValue("combine.right");
_compositorR.p_enableBackground.setValue(false);
_stereoComp.p_inputLeft.setValue("combine.left");
_stereoComp.p_inputRight.setValue("combine.right");
_stereoComp.p_outputImage.setValue("stereocombined");
// setup the eye viewport size
_lvRendererL.setViewportSizeProperty(&_stereoComp.p_preferredInputViewports);
_teapotRendererL.setViewportSizeProperty(&_stereoComp.p_preferredInputViewports);
_compositorL.setViewportSizeProperty(&_stereoComp.p_preferredInputViewports);
_lvRendererR.setViewportSizeProperty(&_stereoComp.p_preferredInputViewports);
_teapotRendererR.setViewportSizeProperty(&_stereoComp.p_preferredInputViewports);
_compositorR.setViewportSizeProperty(&_stereoComp.p_preferredInputViewports);
_renderTargetID.setValue("stereocombined");
}
void StereoRenderDemo::deinit() {
_geometryReader.s_validated.disconnect(this);
AutoEvaluationPipeline::deinit();
}
void StereoRenderDemo::onProcessorValidated(AbstractProcessor* processor) {
if (processor == &_geometryReader) {
// update camera
ScopedTypedData<IHasWorldBounds> lv(*_dataContainer, _geometryReader.p_targetImageID.getValue());
ScopedTypedData<IHasWorldBounds> teapot(*_dataContainer, "teapot");
if (lv != 0 && teapot != 0) {
cgt::Bounds unionBounds;
//unionBounds.addVolume(lv->getWorldBounds());
unionBounds.addVolume(teapot->getWorldBounds());
_tcp.reinitializeCamera(unionBounds);
}
}
}
}
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2015, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universitaet Muenchen
// Boltzmannstr. 3, 85748 Garching b. Muenchen, Germany
//
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
// ================================================================================================
#ifndef STEREORENDERDEMO_H__
#define STEREORENDERDEMO_H__
#include "core/pipeline/autoevaluationpipeline.h"
#include "modules/modulesapi.h"
#include "modules/base/processors/lightsourceprovider.h"
#include "modules/base/processors/trackballcameraprovider.h"
#include "modules/io/processors/vtkimagereader.h"
#include "modules/vis/processors/geometryrenderer.h"
#include "modules/vis/processors/rendertargetcompositor.h"
#include "modules/stereo/processors/stereocompositor.h"
#include "modules/stereo/processors/stereocameragenerator.h"
namespace campvis {
class CAMPVIS_MODULES_API StereoRenderDemo : public AutoEvaluationPipeline {
public:
/**
* Creates a StereoRenderDemo pipeline.
* \param dataContainer Reference to the DataContainer containing local working set of data
* for this pipeline, must be valid the whole lifetime of this pipeline.
*/
explicit StereoRenderDemo(DataContainer& dc);
/**
* Virtual Destructor
**/
virtual ~StereoRenderDemo();
/// \see AutoEvaluationPipeline::init()
virtual void init();
/// \see AutoEvaluationPipeline::deinit()
virtual void deinit();
/// \see AbstractPipeline::getName()
virtual std::string getName() const { return getId(); };
static const std::string getId() { return "StereoRenderDemo"; };
protected:
/**
* Slot getting called when one of the observed processors got validated.
* Updates the camera properties, when the input image has changed.
* \param processor The processor that emitted the signal
*/
virtual void onProcessorValidated(AbstractProcessor* processor);
TrackballCameraProvider _tcp;
StereoCameraGenerator _stereoCamGenerator;
LightSourceProvider _lsp;
VtkImageReader _geometryReader;
GeometryRenderer _lvRendererL;
GeometryRenderer _teapotRendererL;
RenderTargetCompositor _compositorL;
GeometryRenderer _lvRendererR;
GeometryRenderer _teapotRendererR;
RenderTargetCompositor _compositorR;
StereoCompositor _stereoComp;
};
}
#endif // STEREORENDERDEMO_H__
#ifndef STEREOPAIRGENERATOR_H__
#define STEREOPAIRGENERATOR_H__
#include "core/pipeline/abstractprocessor.h"
#include "core/properties/datanameproperty.h"
#include "core/properties/floatingpointproperty.h"
#include "modules/modulesapi.h"
namespace campvis {
/**
* TODO
*/
class CAMPVIS_MODULES_API StereoCameraGenerator : public AbstractProcessor {
public:
/**
* Constructs a new StereoPairGenerator Processor
**/
StereoCameraGenerator();
/**
* Destructor
**/
virtual ~StereoCameraGenerator();
/// \see AbstractProcessor::init()
virtual void init();
/// \see AbstractProcessor::deinit()
virtual void deinit();
/// To be used in ProcessorFactory static methods
static const std::string getId() { return "StereoCameraGenerator"; };
/// \see AbstractProcessor::getName()
virtual const std::string getName() const { return getId(); };
/// \see AbstractProcessor::getDescription()
virtual const std::string getDescription() const { return "StereoCameraGenerator"; };
/// \see AbstractProcessor::getAuthor()
virtual const std::string getAuthor() const { return "Jakob Weiss <jakob.weiss@in.tum.de>"; };
/// \see AbstractProcessor::getProcessorState()
virtual ProcessorState getProcessorState() const { return AbstractProcessor::EXPERIMENTAL; };
/**
*
* \param dataContainer DataContainer to work on
*/
virtual void updateResult(DataContainer& dataContainer);
/// \see AbstractProcessor::updateProperties
virtual void updateProperties(DataContainer& dataContainer);
DataNameProperty p_sourceCameraID;
FloatProperty p_baseline;
protected:
private:
static std::string loggerCat_;
};
}
#endif // STEREOPAIRGENERATOR_H__
\ No newline at end of file
# modules/oct/oct.cmake
# CMake file for the oct module
# Set module status (valid values are STABLE, TESTING and EXPERIMENTAL)
SET(ThisModStatus TESTING)
# Set whether this module has external dependencies that are not shipped with CAMPVis.
SET(ThisModExternalDependencies TRUE)
# The files and assignments need only to be parsed if the module is enabled
IF(ModuleEnabled)
# Source files:
FILE(GLOB ThisModSources RELATIVE ${ModulesDir}
modules/stereo/pipelines/*.cpp
modules/stereo/processors/*.cpp
modules/stereo/datastructures/*.cpp
modules/stereo/properties/*.cpp
modules/stereo/*.cpp
)
# Header files (including GLSL files so that they'll appear in VS projects)
FILE(GLOB ThisModHeaders RELATIVE ${ModulesDir}
modules/stereo/glsl/*.frag
modules/stereo/glsl/*.geom
modules/stereo/glsl/*.vert
modules/stereo/pipelines/*.h
modules/stereo/processors/*.h
modules/stereo/datastructures/*.h
modules/stereo/properties/*.h
)
# Define the GLSL shader path, so that all needed shaders will be deployed to target directory
SET(ThisModShaderDirectories "modules/stereo/glsl")
# Define dependency modules (the pipelines in the vis modules use processors from io)
#SET(ThisModDependencies io)
ENDIF(ModuleEnabled)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment