Notice: If you are member of any public project or group, please make sure that your GitLab username is not the same as the LRZ identifier/Kennung (see https://gitlab.lrz.de/profile/account). Please change your username if necessary. For more information see the section "Public projects / Öffentliche Projekte" at https://doku.lrz.de/display/PUBLIC/GitLab . Thank you!

Commit e20da19c authored by Jakob Weiss's avatar Jakob Weiss

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