Notice to GitKraken users: A vulnerability has been found in the SSH key generation of GitKraken versions 7.6.0 to 8.0.0 (https://www.gitkraken.com/blog/weak-ssh-key-fix). If you use GitKraken and have generated a SSH key using one of these versions, please remove it both from your local workstation and from your LRZ GitLab profile.

21.10.2021, 9:00 - 11:00: Due to updates GitLab may be unavailable for some minutes between 09:00 and 11:00.

Commit ed72ad48 authored by schultezub's avatar schultezub
Browse files

* Various fixes in ImageDataXYZ

 * DevilImageReader renders into ImageDataRenderTarget (intermediate solution...)
 * further work on IxpvDemo pipeline
 * RenderTargetCompositor knows difference compositing

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@389 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent 51764877
......@@ -227,7 +227,7 @@ namespace campvis {
}
size_t numBytesPerElement = sizeof(ElementType);
size_t numElements = tgt::hmul(_size);
size_t numElements = tgt::hmul(newSize);
ElementType* newData = new ElementType[numElements];
// slice image data into new array
......
......@@ -85,6 +85,9 @@ namespace campvis {
void ImageDataGL::createTexture(const WeaklyTypedPointer& wtp) {
tgtAssert(wtp._pointer != 0, "Pointer to image data must not be 0!");
// Set OpenGL pixel alignment to 1 to avoid problems with NPOT textures
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
_texture = new tgt::Texture(reinterpret_cast<GLubyte*>(wtp._pointer), _size, wtp.getGlFormat(), wtp.getGlInternalFormat(), wtp.getGlDataType(), tgt::Texture::LINEAR);
switch (_dimensionality) {
case 1:
......@@ -101,6 +104,8 @@ namespace campvis {
break;
}
tgt::TextureUnit tempUnit;
tempUnit.activate();
_texture->bind();
// TODO: map signed types
......@@ -131,6 +136,7 @@ namespace campvis {
// revoke ownership of local pixel data from the texture
_texture->setPixelData(0);
tgt::TextureUnit::setZeroUnit();
LGL_ERROR;
}
......
......@@ -35,6 +35,8 @@
#include "tgt/shadermanager.h"
#include "tgt/tgt_gl.h"
#include "core/datastructures/imagedatagl.h"
namespace campvis {
const std::string ImageDataRenderTarget::loggerCat_ = "CAMPVis.core.datastructures.ImageDataRenderTarget";
......@@ -65,6 +67,32 @@ namespace campvis {
tgtAssert(_fbo != 0, "Framebuffer object is 0, something went terribly wrong...");
}
ImageDataRenderTarget::ImageDataRenderTarget(const ImageDataGL* colorTexture, const ImageDataGL* depthTexture /* = 0 */)
: ImageData(2, colorTexture->getSize())
, _colorTextures(0)
, _depthTexture(0)
, _fbo(0)
{
tgtAssert(colorTexture != 0, "Color texture must not be 0.");
if (!GpuCaps.isNpotSupported() && !GpuCaps.areTextureRectanglesSupported()) {
LWARNING("Neither non-power-of-two textures nor texture rectangles seem to be supported!");
}
_fbo = new tgt::FramebufferObject();
if (!_fbo) {
LERROR("Failed to initialize framebuffer object!");
return;
}
// TODO: finish implementation!
tgtAssert(false, "Method not yet fully implemented!");
// _fbo->activate();
// tgt::Texture* cc = colorTexture->getTexture()
// _fbo->attachTexture(cc, GL_COLOR_ATTACHMENT0);
}
ImageDataRenderTarget::~ImageDataRenderTarget() {
if (_fbo != 0) {
_fbo->activate();
......@@ -185,6 +213,9 @@ namespace campvis {
tgt::TextureUnit rtUnit;
rtUnit.activate();
// Set OpenGL pixel alignment to 1 to avoid problems with NPOT textures
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// create texture
tgt::Texture* tex = 0;
switch(internalFormat) {
......
......@@ -43,6 +43,7 @@ namespace tgt {
}
namespace campvis {
class ImageDataGL;
/**
* Stores render target data.
......@@ -66,6 +67,13 @@ namespace campvis {
*/
ImageDataRenderTarget(const tgt::svec3& size, GLint internalFormatColor = GL_RGBA8, GLint internalFormatDepth = GL_DEPTH_COMPONENT24);
/**
* Creates a new ImageDataRenderTarget from one color texture and one optional depth texture.
* \param colorTexture Color texture, must not be 0
* \param depthTexture Depth texture, optional, must have valid internal format and same dimensions as \a colorTexture
*/
ImageDataRenderTarget(const ImageDataGL* colorTexture, const ImageDataGL* depthTexture = 0);
/**
* Destructor
*/
......
......@@ -39,7 +39,7 @@ namespace campvis {
, _voxelSize(voxelSize)
, _realWorldValueMapping(realWorldValueMapping)
{
updateMatrixes();
updateMatrices();
}
const tgt::vec3& ImageMappingInformation::getOffset() const {
......@@ -58,7 +58,7 @@ namespace campvis {
_realWorldValueMapping = rwvm;
}
void ImageMappingInformation::updateMatrixes() {
void ImageMappingInformation::updateMatrices() {
_textureToWolrdTransformation = tgt::mat4::createTranslation(_offset) * tgt::mat4::createScale(_voxelSize * _size);
if (! _textureToWolrdTransformation.invert(_worldToTextureTransformation))
tgtAssert(false, "Could not invert texture-to-world matrix. That should not happen!");
......
......@@ -109,7 +109,7 @@ namespace campvis {
/**
* Updates the X-to-Y matrices.
*/
void updateMatrixes();
void updateMatrices();
tgt::vec3 _size; ///< Image size (number of elements, redundant...)
tgt::vec3 _offset; ///< Position of LLF corner in world coordinates (mm)
......
......@@ -36,10 +36,16 @@ out vec4 out_Color;
uniform vec2 _viewportSize;
uniform vec2 _viewportSizeRCP;
uniform Texture2D _colorTexture;
#ifndef NO_DEPTH
uniform Texture2D _depthTexture;
#endif
void main() {
vec2 fragCoord = gl_FragCoord.xy * _viewportSizeRCP;
out_Color = getElement2DNormalized(_colorTexture, fragCoord);
#ifndef NO_DEPTH
gl_FragDepth = getElement2DNormalized(_depthTexture, fragCoord).z;
#endif
}
......@@ -31,6 +31,6 @@ uniform vec4 _backgroundColor1;
uniform vec4 _backgroundColor2;
void renderBackground(in vec2 texCoords, out vec4 outColor) {
outColor = mix(_backgroundColor1, _backgroundColor2, texCoords.x * texCoords.y);
outColor = mix(_backgroundColor1, _backgroundColor2, 0.75 * texCoords.x * texCoords.y);
gl_FragDepth = 1.0;
}
\ No newline at end of file
......@@ -37,7 +37,7 @@ namespace campvis {
ProcessorDecoratorBackground::ProcessorDecoratorBackground()
: AbstractProcessorDecorator()
, _backgroundColor1("backgroundColor1", "Background Color 1", tgt::vec4(.9f, .9f, .9f, 1), tgt::vec4(0.f), tgt::vec4(1.f))
, _backgroundColor2("backgroundColor2", "Background Color 2", tgt::vec4(.7f, .7f, .7f, 1), tgt::vec4(0.f), tgt::vec4(1.f))
, _backgroundColor2("backgroundColor2", "Background Color 2", tgt::vec4(.6f, .6f, .6f, 1), tgt::vec4(0.f), tgt::vec4(1.f))
{
}
......
......@@ -132,7 +132,7 @@ namespace campvis {
* Returns the value of the currently selected option.
* \return _options[_value]._value
*/
T getValue() const;
T getOptionValue() const;
/**
......@@ -179,12 +179,12 @@ namespace campvis {
template<typename T>
const GenericOption<T>& campvis::GenericOptionProperty<T>::getOption() const {
return _options[_value];
return _options[getValue()];
}
template<typename T>
T campvis::GenericOptionProperty<T>::getValue() const {
return _options[_value]._value;
T campvis::GenericOptionProperty<T>::getOptionValue() const {
return _options[getValue()]._value;
}
template<typename T>
......
......@@ -342,8 +342,9 @@ void Texture::uploadTexture() {
format_, dataType_, pixels_);
break;
#endif
}
LGL_ERROR;
}
tgt::Color Texture::texelAsFloat(size_t x, size_t y) const {
......
......@@ -38,14 +38,17 @@
#include "tgt/texturereaderdevil.h"
#include "core/datastructures/imagedatagl.h"
#include "core/datastructures/imagedatarendertarget.h"
#include "core/datastructures/genericimagedatalocal.h"
#include "core/tools/quadrenderer.h"
namespace campvis {
const std::string DevilImageReader::loggerCat_ = "CAMPVis.modules.io.DevilImageReader";
DevilImageReader::DevilImageReader()
: AbstractProcessor()
DevilImageReader::DevilImageReader(GenericProperty<tgt::ivec2>& canvasSize)
: VisualizationProcessor(canvasSize)
, p_url("url", "Image URL", "")
, p_targetImageID("targetImageName", "Target Image ID", "DevilImageReader.output", DataNameProperty::WRITE)
, _devilTextureReader(0)
......@@ -60,12 +63,52 @@ namespace campvis {
delete _devilTextureReader;
}
void DevilImageReader::init() {
VisualizationProcessor::init();
_shader = ShdrMgr.loadSeparate("core/glsl/passthrough.vert", "core/glsl/copyimage.frag", "#define NO_DEPTH\n", false);
_shader->setAttributeLocation(0, "in_Position");
_shader->setAttributeLocation(1, "in_TexCoord");
}
void DevilImageReader::deinit() {
VisualizationProcessor::deinit();
ShdrMgr.dispose(_shader);
}
void DevilImageReader::process(DataContainer& data) {
tgt::Texture* tex = _devilTextureReader->loadTexture(p_url.getValue(), tgt::Texture::LINEAR, false, true, true, false);
if (tex != 0) {
ImageDataGL* image = ImageDataGL::createFromTexture(tex);
data.addData(p_targetImageID.getValue(), image);
ImageDataRenderTarget* rt = new ImageDataRenderTarget(tgt::svec3(_renderTargetSize.getValue(), 1));
glPushAttrib(GL_ALL_ATTRIB_BITS);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_ALWAYS);
_shader->activate();
_shader->setIgnoreUniformLocationError(true);
_shader->setUniform("_viewportSize", _renderTargetSize.getValue());
_shader->setUniform("_viewportSizeRCP", 1.f / tgt::vec2(_renderTargetSize.getValue()));
_shader->setIgnoreUniformLocationError(false);
tgt::TextureUnit texUnit;
image->bind(_shader, texUnit, "_colorTexture");
rt->activate();
LGL_ERROR;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QuadRdr.renderQuad();
rt->deactivate();
_shader->deactivate();
tgt::TextureUnit::setZeroUnit();
glPopAttrib();
LGL_ERROR;
data.addData(p_targetImageID.getValue(), rt);
p_targetImageID.issueWrite();
delete image;
}
else {
LERROR("Could not load image.");
......
......@@ -32,11 +32,12 @@
#include <string>
#include "core/pipeline/abstractprocessor.h"
#include "core/pipeline/visualizationprocessor.h"
#include "core/properties/datanameproperty.h"
#include "core/properties/genericproperty.h"
namespace tgt {
class Shader;
class TextureReaderDevil;
}
......@@ -47,12 +48,12 @@ namespace campvis {
*
* \note Full list of supported formats: http://openil.sourceforge.net/features.php
*/
class DevilImageReader : public AbstractProcessor {
class DevilImageReader : public VisualizationProcessor {
public:
/**
* Constructs a new DevilImageReader Processor
**/
DevilImageReader();
DevilImageReader(GenericProperty<tgt::ivec2>& canvasSize);
/**
* Destructor
......@@ -60,8 +61,14 @@ namespace campvis {
virtual ~DevilImageReader();
/// \see AbstractProcessor::init
virtual void init();
/// \see AbstractProcessor::deinit
virtual void deinit();
/**
* Reads the MHD file into an ImageDataDisk representation
* Reads the image file into an ImageDataRenderTarget
* \param data DataContainer to work on
*/
virtual void process(DataContainer& data);
......@@ -75,7 +82,7 @@ namespace campvis {
DataNameProperty p_targetImageID; ///< image ID for read image
protected:
tgt::Shader* _shader;
tgt::TextureReaderDevil* _devilTextureReader;
static const std::string loggerCat_;
......
......@@ -64,6 +64,20 @@ void main() {
out_Color = mix(firstColor, secondColor, _alpha);
gl_FragDepth = min(firstDepth, secondDepth);
}
else if (_compositingMethod == 3) {
// difference
vec4 firstColor = getElement2DNormalized(_firstColor, ex_TexCoord.xy);
float firstDepth = getElement2DNormalized(_firstDepth, ex_TexCoord.xy).z;
vec4 secondColor = getElement2DNormalized(_secondColor, ex_TexCoord.xy);
float secondDepth = getElement2DNormalized(_secondDepth, ex_TexCoord.xy).z;
out_Color = vec4(vec3(1.0) - abs(firstColor - secondColor).xyz, max(firstColor.w, secondColor.w));
gl_FragDepth = min(firstDepth, secondDepth);
}
else {
// should not occur, but makes the GLSL compiler happy
out_Color = vec4(0.0);
}
if (out_Color.a == 0) {
renderBackground(ex_TexCoord.xy, out_Color);
......
......@@ -39,7 +39,7 @@ namespace campvis {
IxpvDemo::IxpvDemo()
: VisualizationPipeline()
, _xrayReader()
, _xrayReader(_effectiveRenderTargetSize)
, _ctReader()
, _ctProxy()
, _ctFullEEP(_effectiveRenderTargetSize)
......@@ -52,19 +52,19 @@ namespace campvis {
, _camera("camera", "Camera")
, _trackballHandler(0)
{
addProcessor(&_xrayReader);
addProcessor(&_ctReader);
addProcessor(&_ctProxy);
addProcessor(&_ctFullEEP);
addProcessor(&_ctClippedEEP);
addProcessor(&_ctFullDRR);
addProcessor(&_ctClippedDRR);
// addProcessor(&_xrayReader);
//
// addProcessor(&_ctReader);
// addProcessor(&_ctProxy);
// addProcessor(&_ctFullEEP);
// addProcessor(&_ctClippedEEP);
// addProcessor(&_ctFullDRR);
// addProcessor(&_ctClippedDRR);
addProcessor(&_usReader);
addProcessor(&_usSliceExtractor);
addProcessor(&_compositor);
// addProcessor(&_compositor);
addProperty(&_camera);
......@@ -124,6 +124,12 @@ namespace campvis {
// = US Setup =====================================================================================
_usReader.p_url.setValue("D:\\Medical Data\\XrayDepthPerception\\DataCowLeg\\Ultrasound\\gaussianSmoothedUS_UChar.mhd");
_usReader.p_targetImageID.setValue("us.image");
_usReader.p_targetImageID.connect(&_usSliceExtractor.p_sourceImageID);
_usSliceExtractor.p_targetImageID.setValue("us.slice");
_usSliceExtractor.p_sliceNumber.setValue(0);
......@@ -132,9 +138,9 @@ namespace campvis {
_xrayReader.p_targetImageID.connect(&_compositor.p_firstImageId);
_ctFullDRR.p_targetImageID.connect(&_compositor.p_secondImageId);
_compositor.p_targetImageId.setValue("composed");
_compositor.p_compositingMethod.selectById("alpha");
_compositor.p_compositingMethod.selectById("diff");
_renderTargetID.setValue("ct.drr.full");
_renderTargetID.setValue("us.slice");
_trackballHandler->setViewportSize(_renderTargetSize);
}
......@@ -159,15 +165,16 @@ namespace campvis {
_ctFullDRR.p_transferFunction.getTF()->setIntensityDomain(tgt::vec2(ii.getLeft(), ii.getRight()));
_ctClippedDRR.p_transferFunction.getTF()->setImageHandle(dh);
_ctClippedDRR.p_transferFunction.getTF()->setIntensityDomain(tgt::vec2(ii.getLeft(), ii.getRight()));
}
{
tgt::GLContextScopedLock lock(_canvas->getContext());
ImageDataGL* gl = ImageDataConverter::tryConvert<ImageDataGL>(local);
if (gl != 0) {
_data.addData(_ctReader.p_targetImageID.getValue(), gl);
{
tgt::GLContextScopedLock lock(_canvas->getContext());
ImageDataGL* gl = ImageDataConverter::tryConvert<ImageDataGL>(local);
if (gl != 0) {
_data.addData(_ctReader.p_targetImageID.getValue(), gl);
}
}
CtxtMgr.releaseCurrentContext();
}
CtxtMgr.releaseCurrentContext();
tgt::Bounds volumeExtent = img->getWorldBounds();
tgt::vec3 pos = volumeExtent.center() - tgt::vec3(0, 0, tgt::length(volumeExtent.diagonal()));
......@@ -178,6 +185,31 @@ namespace campvis {
}
}
if (! _usReader.getInvalidationLevel().isValid()) {
executeProcessor(&_usReader);
// convert data
DataContainer::ScopedTypedData<ImageData> img(_data, _usReader.p_targetImageID.getValue());
if (img != 0) {
ImageDataLocal* local = ImageDataConverter::tryConvert<ImageDataLocal>(img);
if (local != 0) {
DataHandle dh = _data.addData("us.image", local);
Interval<float> ii = local->getNormalizedIntensityRange();
_usSliceExtractor.p_transferFunction.getTF()->setImageHandle(dh);
_usSliceExtractor.p_transferFunction.getTF()->setIntensityDomain(tgt::vec2(ii.getLeft(), ii.getRight()));
_usSliceExtractor.p_sliceNumber.setValue(125);
{
tgt::GLContextScopedLock lock(_canvas->getContext());
ImageDataGL* gl = ImageDataConverter::tryConvert<ImageDataGL>(local);
if (gl != 0) {
_data.addData("foobar-test", gl);
}
}
CtxtMgr.releaseCurrentContext();
}
}
}
for (std::vector<AbstractProcessor*>::iterator it = _processors.begin(); it != _processors.end(); ++it) {
if (! (*it)->getInvalidationLevel().isValid())
lockGLContextAndExecuteProcessor(*it);
......
......@@ -85,7 +85,6 @@ namespace campvis {
DRRRaycaster _ctClippedDRR;
MhdImageReader _usReader;
SliceExtractor _usSliceExtractor;
RenderTargetCompositor _compositor;
......
......@@ -43,10 +43,11 @@
namespace campvis {
static const GenericOption<CompositingMode> compositingOptions[3] = {
static const GenericOption<CompositingMode> compositingOptions[4] = {
GenericOption<CompositingMode>("first", "Only First", CompositingModeFirst),
GenericOption<CompositingMode>("second", "Only Second", CompositingModeSecond),
GenericOption<CompositingMode>("alpha", "Alpha Blending", CompositingModeAlpha)
GenericOption<CompositingMode>("alpha", "Alpha Blending", CompositingModeAlpha),
GenericOption<CompositingMode>("diff", "Difference", CompositingModeDifference)
};
const std::string RenderTargetCompositor::loggerCat_ = "CAMPVis.modules.vis.RenderTargetCompositor";
......@@ -56,7 +57,7 @@ namespace campvis {
, p_firstImageId("FirstImageId", "First Input Image", "", DataNameProperty::READ)
, p_secondImageId("SecondImageId", "Second Input Image", "", DataNameProperty::READ)
, p_targetImageId("TargetImageId", "Output Image", "", DataNameProperty::WRITE)
, p_compositingMethod("CompositingMethod", "Compositing Method", compositingOptions, 3)
, p_compositingMethod("CompositingMethod", "Compositing Method", compositingOptions, 4)
, p_alphaValue("AlphaValue", "AlphaValue", .5f, 0.f, 1.f)
, _shader(0)
{
......@@ -102,7 +103,7 @@ namespace campvis {
firstImage->bind(_shader, &firstColorUnit, &firstDepthUnit, "_firstColor", "_firstDepth");
secondImage->bind(_shader, &secondColorUnit, &secondDepthUnit, "_secondColor", "_secondDepth");
_shader->setUniform("_compositingMethod", p_compositingMethod.getValue());
_shader->setUniform("_compositingMethod", p_compositingMethod.getOptionValue());
_shader->setUniform("_alpha", p_alphaValue.getValue());
decorateRenderProlog(data, _shader);
......
......@@ -50,6 +50,7 @@ namespace campvis {
CompositingModeFirst = 0,
CompositingModeSecond = 1,
CompositingModeAlpha = 2,
CompositingModeDifference = 3,
};
}
......
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