Commit 3018dc6b authored by Christian Schulte zu Berge's avatar Christian Schulte zu Berge
Browse files

Merge branch 'development' of campcloud.informatik.tu-muenchen.de:berge/campvis into development

parents a2e9b6e7 55afab18
......@@ -11,7 +11,7 @@ IF(${ModuleEnabled})
# Header files (including GLSL files so that they'll appear in VS projects)
FILE(GLOB ThisModHeaders RELATIVE ${ModulesDir}
modules/advancedusvis/datastructures/*.frag
modules/advancedusvis/datastructures/*.h
modules/advancedusvis/glsl/*.frag
modules/advancedusvis/glsl/*.vert
modules/advancedusvis/pipelines/*.h
......@@ -26,7 +26,7 @@ IF(${ModuleEnabled})
SET(ThisModShaderDirectories "modules/advancedusvis/glsl")
SET(ThisModShaderDirectories "modules/advancedusvis/sampledata")
SET(ThisModDependencies vis io preprocessing)
SET(ThisModDependencies vis io preprocessing randomwalk)
ENDIF(${ModuleEnabled})
SET(ThisModStatus TESTING)
......
......@@ -39,6 +39,22 @@ namespace campvis {
class AbstractPointPredicate : public MetaProperty {
public:
// class AbstractColorModulationDecorator {
// public:
// AbstractColorModulationDecorator(AbstractPointPredicate* parent)
// : _parent(parent)
// {}
//
// virtual ~AbstractColorModulationDecorator() {}
//
// virtual const std::string& getHuePart() const = 0;
// virtual const std::string& getSaturationPart() const = 0;
// virtual const std::string& getIntensityPart() const = 0;
// protected:
// AbstractPointPredicate* _parent;
// };
AbstractPointPredicate(const std::string& inputVariable, const std::string& name, const std::string& title);
virtual ~AbstractPointPredicate();
......@@ -164,6 +180,8 @@ namespace campvis {
virtual std::string getPredicateEvaluationGlslString() const;
virtual void setupShader(tgt::Shader* shader) const;
const std::string& getRangeUniformname() const { return _rangeUniformName; };
Vec2Property p_range;
protected:
......
......@@ -31,7 +31,9 @@ namespace campvis {
const std::string PointPredicateHistogram::loggerCat_ = "CAMPVis.modules.advancedusvis.PointPredicateHistogram";;
PointPredicateHistogram::PointPredicateHistogram() {
PointPredicateHistogram::PointPredicateHistogram()
: _glslModulationHackForIvus(false)
{
}
......@@ -60,11 +62,12 @@ namespace campvis {
s_headerChanged.emitSignal();
}
void PointPredicateHistogram::resetPredicates() {
void PointPredicateHistogram::resetPredicates(bool resetColors) {
float imp = 1.f / _predicates.size();
for (size_t i = 0; i < _predicates.size(); ++i) {
_predicates[i]->p_importance.setValue(imp);
_predicates[i]->p_color.setValue(tgt::vec2(0.f));
if (resetColors)
_predicates[i]->p_color.setValue(tgt::vec2(0.f));
}
s_configurationChanged.emitSignal();
......@@ -80,40 +83,81 @@ namespace campvis {
toReturn += _predicates[i]->getGlslHeader();
}
toReturn +=
"vec4 performPredicateBasedShading(in float intensity, in float gradientMagnitude, in float gradientAngle, float viewAngle, in float snr, in float vesselness, in float confidence, in uint label) {\n"
" float impCount = 0.0;\n"
" float hueCount = 0.0;\n"
" vec4 impSum = vec4(0.0, 0.0, 0.0, 1.0);\n";
for (size_t i = 0; i < _predicates.size(); ++i) {
if (_predicates[i]->isEnabled()) {
toReturn +=
" if " + _predicates[i]->getPredicateEvaluationGlslString() + " {\n"
" float imp = pow(" + _predicates[i]->getImportanceUniformName() + " * " + StringUtils::toString(_predicates.size()) + ", 2.0);\n"
" impSum.x += " + _predicates[i]->getColorUniformName() + ".x * " + _predicates[i]->getColorUniformName() + ".y * imp;\n"
" impSum.y += " + _predicates[i]->getColorUniformName() + ".y * imp;\n"
" impSum.z += " + _predicates[i]->getIntensityHackUniformName() + ";\n"
" impSum.a += 1.0;\n"
" hueCount += " + _predicates[i]->getColorUniformName() + ".y * imp;\n"
" impCount += imp;\n"
" }\n";
if (_glslModulationHackForIvus) {
toReturn +=
"vec4 performPredicateBasedShading(" + _predicateFunctionArgumentString + ") {\n"
" vec4 enumerator = vec4(0.0, 0.0, 0.0, 0.0);\n"
" vec4 denominator = vec4(0.0, 0.0, 0.0, 0.0);\n";
for (size_t i = 0; i < _predicates.size(); ++i) {
if (_predicates[i]->isEnabled()) {
toReturn +=
" if (" + _predicates[i]->getImportanceUniformName() + " > 0.01 && " + _predicates[i]->getPredicateEvaluationGlslString() + ") {\n"
" float kappa = pow(" + _predicates[i]->getImportanceUniformName() + " * " + StringUtils::toString(_predicates.size()) + ", 2.0);\n";
if (RangePointPredicate* tester = dynamic_cast<RangePointPredicate*>(_predicates[i]))
toReturn += " float chromaFactor = (" + _predicates[i]->getInputVariable() + " - " + tester->getRangeUniformname() + ".x) / (" + tester->getRangeUniformname() + ".y - " + tester->getRangeUniformname() + ".x);\n";
else
toReturn += " float chromaFactor = " + _predicates[i]->getInputVariable() + ";\n";
toReturn +=
/* hue */ " enumerator.x = kappa * " + _predicates[i]->getColorUniformName() + ".x * " + _predicates[i]->getColorUniformName() + ".y * chromaFactor;\n"
/* chroma */ " enumerator.y = kappa * " + _predicates[i]->getColorUniformName() + ".y * chromaFactor;\n"
/* intensity */ " enumerator.z = cm;\n"
/* importance */ " enumerator.w = kappa;\n"
" denominator.x += kappa * " + _predicates[i]->getColorUniformName() + ".y * chromaFactor;\n"
" denominator.y += kappa;\n"
" denominator.z += 1.0;\n"
" denominator.w += 1.0;\n"
" }\n";
}
}
toReturn +=
" if (denominator.w > 0.0) {\n"
" return enumerator / denominator;\n"
" }\n"
" else\n"
" return vec4(0.0);\n"
"}\n\n";
}
else {
toReturn +=
"vec4 performPredicateBasedShading(" + _predicateFunctionArgumentString + ") {\n"
" float impCount = 0.0;\n"
" float hueCount = 0.0;\n"
" vec4 impSum = vec4(0.0, 0.0, 0.0, 1.0);\n";
for (size_t i = 0; i < _predicates.size(); ++i) {
if (_predicates[i]->isEnabled()) {
toReturn +=
" if " + _predicates[i]->getPredicateEvaluationGlslString() + " {\n"
" float imp = pow(" + _predicates[i]->getImportanceUniformName() + " * " + StringUtils::toString(_predicates.size()) + ", 2.0);\n"
" impSum.x += " + _predicates[i]->getColorUniformName() + ".x * " + _predicates[i]->getColorUniformName() + ".y * imp;\n"
" impSum.y += " + _predicates[i]->getColorUniformName() + ".y * imp;\n"
" impSum.z += " + _predicates[i]->getIntensityHackUniformName() + ";\n"
" impSum.a += 1.0;\n"
" hueCount += " + _predicates[i]->getColorUniformName() + ".y * imp;\n"
" impCount += imp;\n"
" }\n";
}
}
toReturn +=
" if (impCount > 0.0) {\n"
" impSum.x /= hueCount;\n"
" impSum.y /= impCount;\n"
" impSum.a = impCount / impSum.a;\n"
" }\n"
" else\n"
" impSum = vec4(0.0);\n"
" return impSum;\n"
"}\n\n";
toReturn +=
" if (impCount > 0.0) {\n"
" impSum.x /= hueCount;\n"
" impSum.y /= impCount;\n"
" impSum.a = impCount / impSum.a;\n"
" }\n"
" else\n"
" impSum = vec4(0.0);\n"
" return impSum;\n"
"}\n\n";
}
toReturn +=
"uint computePredicateBitfield(in float intensity, in float gradientMagnitude, in float gradientAngle, float viewAngle, in float snr, in float vesselness, in float confidence, in uint label) {\n"
"uint computePredicateBitfield(" + _predicateFunctionArgumentString + ") {\n"
" uint toReturn = 0U;\n";
for (size_t i = 0; i < _predicates.size(); ++i) {
......@@ -155,4 +199,8 @@ namespace campvis {
_predicates[i]->unlockAllProperties();
}
void PointPredicateHistogram::setPredicateFunctionArgumentString(const std::string& pfas) {
_predicateFunctionArgumentString = pfas;
}
}
\ No newline at end of file
......@@ -70,7 +70,7 @@ namespace campvis {
/**
* Resets the predicate histogram to default setting.
*/
void resetPredicates();
void resetPredicates(bool resetColors = true);
/**
* Returns the vector of predicates.
......@@ -90,12 +90,20 @@ namespace campvis {
*/
void setupRenderShader(tgt::Shader* shader) const;
/**
* Sets the GLSL predicate function argument string.
* \param pfas the GLSL predicate function argument string (without parentheses)
*/
void setPredicateFunctionArgumentString(const std::string& pfas);
/// Signal emitted when this predicate histogram's configuration (importance, color, ...) has changed
sigslot::signal0 s_configurationChanged;
/// Signal emitted when this predicate histogram's GLSL header has changed
sigslot::signal0 s_headerChanged;
bool _glslModulationHackForIvus;
private:
/// Slot called when a predicate's configuration has changed
void onPredicateConfigurationChanged();
......@@ -104,6 +112,9 @@ namespace campvis {
/// vector of all voxel predicates
std::vector<AbstractPointPredicate*> _predicates;
/// The GLSL predicate function argument string (without parentheses).
std::string _predicateFunctionArgumentString;
static const std::string loggerCat_;
......
......@@ -70,6 +70,7 @@ namespace campvis {
}
void PointPredicateEvaluator::init() {
p_histogram.getPredicateHistogram()->setPredicateFunctionArgumentString("in float intensity, in float gradientMagnitude, in float gradientAngle, float viewAngle, in float snr, in float vesselness, in float confidence, in uint label");
VisualizationProcessor::init();
_shader = ShdrMgr.loadWithCustomGlslVersion("core/glsl/passthrough.vert", "", "modules/advancedusvis/glsl/pointpredicateevaluator.frag", generateHeader(), "400");
......
......@@ -62,8 +62,10 @@ namespace campvis {
}
void PointPredicateRaycaster::init() {
p_predicateHistogram.s_headerChanged.connect(this, &PointPredicateRaycaster::onHistogramHeaderChanged);
p_predicateHistogram.getPredicateHistogram()->setPredicateFunctionArgumentString("in float intensity, in float gradientMagnitude, in float gradientAngle, float viewAngle, in float snr, in float vesselness, in float confidence, in uint label");
RaycastingProcessor::init();
p_predicateHistogram.s_headerChanged.connect(this, &PointPredicateRaycaster::onHistogramHeaderChanged);
}
void PointPredicateRaycaster::deinit() {
......
......@@ -66,7 +66,7 @@ namespace campvis {
// We ensure all shared properties to be of correct type the base class method.
// Hence, static_cast ist safe.
setHistogramPointer(static_cast<PointPredicateHistogramProperty*>(prop)->_histogram);
static_cast<PointPredicateHistogramProperty*>(prop)->setHistogramPointer(this->_histogram);
}
PointPredicateHistogram* PointPredicateHistogramProperty::getPredicateHistogram() {
......@@ -146,7 +146,10 @@ namespace campvis {
do {
// set each underflowed value to 0 and adjust the other importances by an according fraction.
std::for_each(underflowIndices.begin(), underflowIndices.end(), [&] (int underflowIndex) {
tgtAssert(! adjustableIndices.empty(), "The vector of adjustable indices is empty, but we need at least one. This should not happen!");
if (adjustableIndices.empty()) {
LERROR("The vector of adjustable indices is empty, but we need at least one. This should not happen!");
return;
}
float delta = newImportances[underflowIndex] / adjustableIndices.size();
std::for_each(adjustableIndices.begin(), adjustableIndices.end(), [&] (int index) {
......@@ -178,7 +181,10 @@ namespace campvis {
predicates[i]->p_importance.setValue(newImportances[i]);
sum += newImportances[i];
}
tgtAssert(std::abs(sum - 1.f) < 0.0001f, "Sum of importances is not 1 - sth. went wrong!");
if (std::abs(sum - 1.f) > 0.001f)
LERROR("Sum of importances is not 1 - sth. went wrong!");
--_ignoreSignals;
s_changed.emitSignal(this);
......
......@@ -74,6 +74,9 @@ namespace campvis {
layout->addWidget(narf, 1, 0, 1, 3);
_lwPredicates->setVisible(false);
narf->setVisible(false);
_slHue = new QSlider(Qt::Vertical, mainWidget);
_slHue->setMinimum(0);
_slHue->setMaximum(100);
......
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2014, 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.
//
// ================================================================================================
layout(location = 0) out vec4 out_Color; ///< outgoing fragment color
layout(location = 1) out vec4 out_FHP; ///< outgoing fragment first hitpoint
layout(location = 2) out vec4 out_FHN; ///< outgoing fragment first hit normal
#include "tools/colorspace.frag"
#include "tools/gradient.frag"
#include "tools/raycasting.frag"
#include "tools/shading.frag"
#include "tools/texture2d.frag"
#include "tools/texture3d.frag"
#include "tools/transferfunction.frag"
#define NUM_PREDICATE_SETS 3
uniform vec2 _viewportSizeRCP;
uniform float _jitterStepSizeMultiplier;
// ray entry points
uniform sampler2D _entryPoints;
uniform sampler2D _entryPointsDepth;
uniform TextureParameters2D _entryParams;
// ray exit points
uniform sampler2D _exitPoints;
uniform sampler2D _exitPointsDepth;
uniform TextureParameters2D _exitParams;
// volume
uniform sampler3D _volume;
uniform TextureParameters3D _volumeTextureParams;
uniform sampler3D _cm;
uniform TextureParameters3D _cmParams;
uniform sampler3D _tc;
uniform TextureParameters3D _tcParams;
uniform sampler3D _plaque;
uniform TextureParameters3D _plaqueParams;
uniform float _minDepth;
uniform float _maxDepth;
// Transfer function
uniform sampler1D _transferFunction;
uniform TFParameters1D _transferFunctionParams;
uniform LightSource _lightSource;
uniform vec3 _cameraPosition;
uniform float _samplingStepSize;
// TODO: copy+paste from Voreen - eliminate or improve.
const float SAMPLING_BASE_INTERVAL_RCP = 200.0;
uniform vec2 _intensityRange = vec2(0.05, 1.0);
uniform float _intensityImportance = 1.0;
uniform vec2 _gradientMagnitudeRange = vec2(0.03, 1.0);
uniform float _gradientMagnitudeImportance = 2.0;
uniform int _boneBit = 3;
uniform float _boneImportance = 1.2;
uniform int _muscleBit = 1;
uniform float _muscleImportance = 1.75;
uniform int _contextBit = 2;
uniform float _contextImportance = 1.2;
uniform vec3 _scanningDirection = vec3(0.0, 1.0, 0.0);
float hadd(in vec3 v) {
return v.x + v.y + v.z;
}
float hmax(in vec3 v) {
return max(v.x, max(v.y, v.z));
}
/**
* Performs the raycasting and returns the final fragment color.
*/
vec4 performRaycasting(in vec3 entryPoint, in vec3 exitPoint, in vec2 texCoords) {
vec4 result = vec4(0.0);
float importance = 0.0;
float firstHitT = -1.0;
// calculate ray parameters
vec3 direction = exitPoint.rgb - entryPoint.rgb;
float t = 0.0;
float tend = length(direction);
direction = normalize(direction);
float depthEntry = texture(_entryPointsDepth, texCoords).z;
float depthExit = texture(_exitPointsDepth, texCoords).z;
jitterEntryPoint(entryPoint, direction, _samplingStepSize * _jitterStepSizeMultiplier);
while (t < tend) {
// compute sample position
vec3 samplePosition = entryPoint.rgb + t * direction;
// lookup intensity and TF
float intensity = texture(_volume, samplePosition).r;
float D = smoothstep(_minDepth, _maxDepth, calculateDepthValue(t/tend, depthEntry, depthExit));
vec3 gradient = computeGradient(_volume, _volumeTextureParams, samplePosition);
// perform compositing
vec4 color = lookupTF(_transferFunction, _transferFunctionParams, intensity);
if (color.a > 0.0) {
float cm = texture(_cm, samplePosition).r;
vec4 tc = texture(_tc, samplePosition);
float plaque = texture(_plaque, samplePosition).r;
vec3 worldPosition = textureToWorld(_volumeTextureParams, samplePosition).xyz;
vec4 pr = performPredicateBasedShading(intensity, cm, tc, plaque);
float imp = pr.a;
if (imp > 0.0) {
// if (pr.z > 0.0)
// color = clamp(color + pr.z, 0.0, 1.0);
#ifdef ENABLE_SHADING
// compute gradient (needed for shading and normals)
color.rgb = calculatePhongShading(worldPosition, _lightSource, _cameraPosition, gradient, color.rgb, color.rgb, vec3(1.0, 1.0, 1.0));
#endif
// perform predicate-based shading
color.a = 1.0 - pow(1.0 - color.a, _samplingStepSize * SAMPLING_BASE_INTERVAL_RCP);
vec3 hsl = rgb2hcy(color.rgb * color.a);
hsl.xy += pr.xy;
hsl.x = mod(hsl.x, 1.0);
//hsl.z = cm / 2.0;
color.rgb = hcy2rgb(hsl);
// perform depth-based shading
const float DBS = 0.01;
//color.r += DBS * (0.5 - D);
//color.b += DBS * (D - 0.5);
float vis = 1.0 - exp(importance - imp);
float m = (imp <= importance || (1.0 - result.a) >= vis) ? 1.0 : (1.0 - vis) / result.a;
vec3 cc = m * result.rgb + (1.0 - m * result.a) * color.rgb;
float aa = m * result.a * (1.0 - color.a) + color.a;
result.a = result.a * (1.0 - color.a) + color.a;
result.rgb = (aa == 0.0) ? vec3(0.0) : (result.a * cc) / aa;
importance = max(importance, log(color.a + (1.0 - color.a) * exp(importance - imp)) + imp);
}
}
// save first hit ray parameter for depth value calculation
if (firstHitT < 0.0 && result.a > 0.0) {
firstHitT = t;
out_FHP = vec4(samplePosition, 1.0);
out_FHN = vec4(normalize(computeGradient(_volume, _volumeTextureParams, samplePosition)), 1.0);
}
// advance to the next evaluation point along the ray
t += _samplingStepSize;
}
// calculate depth value from ray parameter
gl_FragDepth = 1.0;
if (firstHitT >= 0.0) {
gl_FragDepth = calculateDepthValue(firstHitT/tend, depthEntry, depthExit);
}
return result;
}
/***
* The main method.
***/
void main() {
vec2 p = gl_FragCoord.xy * _viewportSizeRCP;
vec3 frontPos = texture(_entryPoints, p).rgb;
vec3 backPos = texture(_exitPoints, p).rgb;
//determine whether the ray has to be casted
if (frontPos == backPos) {
//background need no raycasting
discard;
} else {
//fragCoords are lying inside the boundingbox
out_Color = performRaycasting(frontPos, backPos, p);
}
}
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2014, 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;
in vec4 ex_Color;
out vec4 out_Color;
#include "tools/colorspace.frag"
#include "tools/texture3d.frag"
#include "tools/transferfunction.frag"
uniform sampler3D _ivus;
uniform TextureParameters3D _ivusParams;
uniform sampler3D _cm;
uniform TextureParameters3D _cmParams;
uniform sampler3D _tc;
uniform TextureParameters3D _tcParams;
uniform sampler3D _plaque;
uniform TextureParameters3D _plaqueParams;
uniform mat4 _texCoordsMatrix;
uniform bool _mixWithIvus = true;
uniform bool _useTexturing = true;
uniform bool _useSolidColor = true;
uniform vec4 _color = vec4(1.0, 1.0, 1.0, 1.0);
void main() {
if (_useTexturing) {
vec3 texel = (_texCoordsMatrix * vec4(ex_TexCoord, 1.0)).xyz;
float ivus = texture(_ivus, texel).r;
float cm = texture(_cm, texel).r;
vec4 tc = texture(_tc, texel);
float plaque = texture(_plaque, texel).r;
vec4 pr = performPredicateBasedShading(ivus, cm, tc, plaque);
vec3 hcy = vec3(pr.xy, cm * smoothstep(0.0, 0.5, pr.y));
vec3 mixed = hcy2rgb(hcy);
if (_mixWithIvus)
// mixed = max(vec3(ivus), mixed);
mixed = mix(vec3(ivus), mixed, max(cm, pr.y));
// mixed = mix(vec3(ivus), mixed, min(cm, pr.y));
//vec3 mixed = mix(vec3(1.0), vec3(1.0, 0.5, 0.0), max(cm, pr.y));
out_Color = vec4(mixed, 1.0);
//vec3 hsl = rgb2hcy(vec3(ivus));
//hsl.xy += pr.xy;
//hsl.x = mod(hsl.x, 1.0);
//hsl.y *= cm;