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 5cbfe490 authored by Jakob Weiss's avatar Jakob Weiss
Browse files

Merge branch 'advanced-raycasting' into campvis-nx

parents e20da19c cd918f81
...@@ -109,7 +109,7 @@ namespace campvis { ...@@ -109,7 +109,7 @@ namespace campvis {
return new TFGeometry1D(keyPoints); return new TFGeometry1D(keyPoints);
} }
TFGeometry1D* TFGeometry1D::crateRamp(const cgt::vec2& interval, const cgt::col4& color) { TFGeometry1D* TFGeometry1D::createRamp(const cgt::vec2& interval, const cgt::col4& color) {
return createQuad(interval, cgt::col4(color.xyz(), 0), cgt::col4(color.xyz(), 255)); return createQuad(interval, cgt::col4(color.xyz(), 0), cgt::col4(color.xyz(), 255));
} }
...@@ -163,4 +163,4 @@ namespace campvis { ...@@ -163,4 +163,4 @@ namespace campvis {
return cgt::vec2(_keyPoints.front()._position, _keyPoints.back()._position); return cgt::vec2(_keyPoints.front()._position, _keyPoints.back()._position);
} }
} }
\ No newline at end of file
...@@ -132,7 +132,7 @@ namespace campvis { ...@@ -132,7 +132,7 @@ namespace campvis {
* \param color Color for ramp * \param color Color for ramp
* \return A TFGeometry1D modelling a ramp with two KeyPoints. * \return A TFGeometry1D modelling a ramp with two KeyPoints.
*/ */
static TFGeometry1D* crateRamp(const cgt::vec2& interval, const cgt::col4& color); static TFGeometry1D* createRamp(const cgt::vec2& interval, const cgt::col4& color);
/** /**
* Creates a diverging color map of two diverging colors blending over white. * Creates a diverging color map of two diverging colors blending over white.
......
...@@ -171,4 +171,22 @@ float getPhongShadingIntensity(in vec3 position, in LightSource light, in vec3 c ...@@ -171,4 +171,22 @@ float getPhongShadingIntensity(in vec3 position, in LightSource light, in vec3 c
toReturn *= computeAttenuation(light._attenuation, d); toReturn *= computeAttenuation(light._attenuation, d);
#endif #endif
return (toReturn.x + toReturn.y + toReturn.z) / 3.0; return (toReturn.x + toReturn.y + toReturn.z) / 3.0;
} }
\ No newline at end of file
vec3 calculateContourShading(in vec3 position, in vec3 camera, in vec3 normal, in vec3 materialColor, in vec3 outlineColor, in float contourExponent) {
float outlineStrength = 1. - pow(clamp(-dot(normalize(normal), normalize(position - camera)), 0, 1), contourExponent);
return mix(materialColor, outlineColor, outlineStrength);
}
vec4 calculateContourShading2(in vec3 position, in vec3 camera, in vec3 normal, in vec4 materialColor, in vec4 outlineColor, in float contourExponent) {
float outlineStrength = 1. - pow(clamp(dot(normal, normalize(camera - position)), 0, 1), contourExponent);
return outlineStrength * outlineColor;
}
void blendUnder(inout vec4 colorAbove, in vec4 colorBelow)
{
colorAbove.rgb = colorAbove.rgb + colorBelow.rgb * colorBelow.a * (1.0 - colorAbove.a);
colorAbove.a = colorAbove.a + (1.0 -colorAbove.a) * colorBelow.a;
}
# CMake file for vis module
SET(ThisModStatus EXPERIMENTAL)
IF(${ModuleEnabled})
# Source files:
FILE(GLOB ThisModSources RELATIVE ${ModulesDir}
modules/advancedraycasting/decorators/*.cpp
modules/advancedraycasting/pipelines/*.cpp
modules/advancedraycasting/processors/*.cpp
modules/advancedraycasting/tools/*.cpp
modules/advancedraycasting/*.cpp
)
# Header files (including GLSL files so that they'll appear in VS projects)
FILE(GLOB ThisModHeaders RELATIVE ${ModulesDir}
modules/advancedraycasting/glsl/*.frag
modules/advancedraycasting/glsl/*.geom
modules/advancedraycasting/glsl/*.vert
modules/advancedraycasting/glsl/*.comp
modules/advancedraycasting/decorators/*.h
modules/advancedraycasting/pipelines/*.h
modules/advancedraycasting/processors/*.h
modules/advancedraycasting/tools/*.h
)
LIST(APPEND ThisModShaderDirectories "modules/vis/glsl")
SET(ThisModDependencies base vis)
ENDIF(${ModuleEnabled})
SET(ThisModStatus STABLE)
SET(ThisModExternalDependencies FALSE)
// ================================================================================================
//
// 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 "core/pipeline/pipelinefactory.h"
#include "core/pipeline/processorfactory.h"
#include "modules/advancedraycasting/pipelines/preintegratedraycasterdemo.h"
#include "modules/advancedraycasting/processors/ambientvolumegenerator.h"
#include "modules/advancedraycasting/processors/laoraycaster.h"
#include "modules/advancedraycasting/processors/preintegratedraycaster.h"
#include "modules/advancedraycasting/processors/tfpreintegrator.h"
namespace campvis {
// explicitly instantiate templates to register the pipelines
template class PipelineRegistrar<PreintegratedRayCasterDemo>;
template class SmartProcessorRegistrar<AmbientVolumeGenerator>;
template class SmartProcessorRegistrar<LAORaycaster>;
template class SmartProcessorRegistrar<PreintegratedRaycaster>;
template class SmartProcessorRegistrar<TFPreIntegrator>;
}
// ================================================================================================
//
// 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 "localambientocclusiondecorator.h"
#include "cgt/shadermanager.h"
#include "cgt/textureunit.h"
#include "core/properties/propertycollection.h"
#include "core/datastructures/imagerepresentationgl.h"
#include "core/datastructures/renderdata.h"
#include "core/classification/geometry1dtransferfunction.h"
namespace campvis {
LocalAmbientOcclusionDecorator::LocalAmbientOcclusionDecorator()
: AbstractProcessorDecorator()
, p_aoRays("AORays", "Number of directional samples", 8, 0, 50)
, p_aoSamples("AOSamples", "Number of Samples per ray (controls size of AO sphere)", 10, 0, 80)
, p_aoSphereRadius("AOSphereRadius", "AO Sphere Radius [voxels]", 8.0f, 0.1f, 50.0f, 0.25f)
, p_aoOpacityScale("OpacityScale", "Opacity Scaling", 1.0f, 0.0f, 5.f)
, p_aoEffectGamma("AOEffectGamma", "AO Scale Gamma", 1.0f, .0f, 5.f)
, p_aoEmissiveTransferFunction("AOTransferFunction", "Emissive Transfer Function", new Geometry1DTransferFunction(128))
, p_aoEmissiveScale("EmissiveScale", "Emissive Color Scaling", 1.0f, 0.0f, 10.f)
{
}
LocalAmbientOcclusionDecorator::~LocalAmbientOcclusionDecorator() {
}
void LocalAmbientOcclusionDecorator::addProperties(AbstractProcessor* propCollection) {
propCollection->addProperty(p_aoRays, AbstractProcessor::INVALID_RESULT | AbstractProcessor::INVALID_PROPERTIES | AbstractProcessor::INVALID_SHADER);
propCollection->addProperty(p_aoSamples, AbstractProcessor::INVALID_RESULT | AbstractProcessor::INVALID_PROPERTIES | AbstractProcessor::INVALID_SHADER);
propCollection->addProperty(p_aoSphereRadius);
propCollection->addProperty(p_aoOpacityScale);
propCollection->addProperty(p_aoEffectGamma);
propCollection->addProperty(p_aoEmissiveTransferFunction);
propCollection->addProperty(p_aoEmissiveScale);
}
void LocalAmbientOcclusionDecorator::renderProlog(const DataContainer& dataContainer, cgt::Shader* shader) {
auto aotf = p_aoEmissiveTransferFunction.getTF();
_aoTFUnit = std::make_unique<cgt::TextureUnit>();
aotf->bind(shader, *_aoTFUnit, "_aoEmissiveTF", "_aoEmissiveTFParams");
shader->setUniform("_aoSphereRadius", p_aoSphereRadius.getValue());
shader->setUniform("_aoGamma", p_aoEffectGamma.getValue());
shader->setUniform("_aoEmissiveScale", p_aoEmissiveScale.getValue());
shader->setUniform("_aoOpacityScale", p_aoOpacityScale.getValue());
}
void LocalAmbientOcclusionDecorator::renderEpilog(cgt::Shader * shader)
{
// delete the TF texture unit
_aoTFUnit = nullptr;
}
std::string LocalAmbientOcclusionDecorator::generateHeader() const
{
std::string toReturn;
// the defines need to exist before the include
toReturn +=
"#define NUM_AO_RAYS " + std::to_string(p_aoRays.getValue()) + "\n"
"#define NUM_AO_RAY_STEPS " + std::to_string(p_aoSamples.getValue()) + "\n"
"\n"
"uniform float _aoSphereRadius;\n"
"uniform float _aoGamma;\n"
"uniform float _aoOpacityScale;\n"
"uniform float _aoEmissiveScale;\n"
"\n"
"#define AO_GAMMA _aoGamma\n"
"#define AO_OPACITY_SCALE _aoOpacityScale\n"
"#define AO_EMISSIVE_SCALE _aoEmissiveScale\n";
// the include has the actual functions
toReturn += "#include \"modules/advancedraycasting/glsl/localambientocclusion.frag\"\n";
return toReturn;
}
}
// ================================================================================================
//
// 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 LOCALAMBIENTOCCLUSIONDECORATOR_H__
#define LOCALAMBIENTOCCLUSIONDECORATOR_H__
#include "core/pipeline/abstractprocessordecorator.h"
#include "core/properties/floatingpointproperty.h"
#include "core/properties/datanameproperty.h"
#include "core/properties/colorproperty.h"
#include "core/properties/optionproperty.h"
#include "core/properties/transferfunctionproperty.h"
#include "modules/modulesapi.h"
namespace cgt {
class TextureUnit;
}
namespace campvis {
/**
* \class RaycastingGridDecorator
* Provides a fragment shader function that can test samples and modify their opacity valued to
*/
class CAMPVIS_MODULES_API LocalAmbientOcclusionDecorator : public AbstractProcessorDecorator {
public:
LocalAmbientOcclusionDecorator();
virtual ~LocalAmbientOcclusionDecorator();
protected:
void addProperties(AbstractProcessor* propCollection) override;
virtual void renderProlog(const DataContainer& dataContainer, cgt::Shader* shader) override;
virtual void renderEpilog(cgt::Shader* shader) override;
virtual std::string generateHeader() const override;
IntProperty p_aoRays; ///< Number of directional AO samples
IntProperty p_aoSamples; ///< Number of steps per directional sample
FloatProperty p_aoSphereRadius; ///< The AO Sphere radius in voxels
FloatProperty p_aoEffectGamma; ///< Gamma controls the strength of the AO effect
FloatProperty p_aoOpacityScale; ///< Scales opacity when sampling for AO rays
TransferFunctionProperty p_aoEmissiveTransferFunction;
FloatProperty p_aoEmissiveScale; ///< Scales the emissive color to increase/decrease the emissive effect
std::unique_ptr<cgt::TextureUnit> _aoTFUnit;
};
}
#endif // LOCALAMBIENTOCCLUSIONDECORATOR_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.
//
// ================================================================================================
// (c) 2017 Jakob Weiss <jakob.weiss@tum.de>
// ==================== Shader for median filtering. ====================
// Expects the following dynamic defines:
//
// #define OUTPUT_TEXTURE_FORMAT
// The texture format of the output texture. Preferrably specified through Texture::calcMatchingWriteFormat()
//
// uniform _outputImage
// dynamically defined (i|u)image(1|2|3)D uniform to allow imageStore operation of the output
// #define TEXTURE_DIMENSIONALITY
// The dimensionality of the texture [1,2,3]
// The work group size can be overridden by dynamic defines
#ifndef WORK_GROUP_SIZE_X
#define WORK_GROUP_SIZE_X 1
#endif
#ifndef WORK_GROUP_SIZE_Y
#define WORK_GROUP_SIZE_Y 1
#endif
#ifndef WORK_GROUP_SIZE_Z
#define WORK_GROUP_SIZE_Z 1
#endif
#include "tools/transferfunction.frag"
// volume
uniform sampler3D _volume;
uniform TextureParameters3D _volumeTextureParams;
// Transfer function
uniform sampler1D _transferFunction;
uniform TFParameters1D _transferFunctionParams;
// Transfer function
uniform sampler1D _aoEmissiveTF;
uniform TFParameters1D _aoEmissiveTFParams;
layout(local_size_x = WORK_GROUP_SIZE_X, local_size_y = WORK_GROUP_SIZE_Y, local_size_z = WORK_GROUP_SIZE_Z) in;
void main() {
// get index in global work group i.e x,y position
ivec3 pixel_coords = ivec3(gl_GlobalInvocationID.xyz);
vec3 samplePosition = vec3(pixel_coords)*_volumeTextureParams._sizeRCP;
float sampleIntensity = texture(_volume, samplePosition).r;
vec4 sampleTFColor = lookupTF(_transferFunction, _transferFunctionParams, sampleIntensity);
// precompute the LAO ray directions
vec4 aoRayDirs[NUM_AO_RAYS];
initLAODirs(aoRayDirs, _aoSphereRadius, _volumeTextureParams);
vec3 ambientOcclusion = computeLAO(samplePosition, aoRayDirs, _volume, _transferFunction, _transferFunctionParams, _aoEmissiveTF, _aoEmissiveTFParams);
vec4 result = vec4(ambientOcclusion, sampleTFColor.a);
// output to a specific pixel in the image
#if TEXTURE_DIMENSIONALITY == 1
imageStore(_outputImage, pixel_coords.x, vec4(result));
#elif TEXTURE_DIMENSIONALITY == 2
imageStore(_outputImage, pixel_coords.xy, vec4(result));
#else
imageStore(_outputImage, pixel_coords, vec4(result));
#endif
}
// (c) 2017 Jakob Weiss
/**
** Prerequisites: **
- _samplingStepSize
- _jitterStepSizeMultiplier
- _lightSource
- vec4 getSampleColor(vec3 sampleTexPos)
- float getSampleAlpha(vec3 sampleTexPos)
- vec3 getSampleGradient(vec3 sampleTexPos)
If ENABLE_SHADOWING is set:
- _lightSource
- _shadowIntensity
If ENABLE_SHADING is set:
- _lightSource
- _cameraPosition
*/
/**
* 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 firstHitT = -1.0;
// calculate ray parameters
vec3 direction = exitPoint.rgb - entryPoint.rgb;
float t = 0.0;
float tend = length(direction);
direction = normalize(direction);
jitterEntryPoint(entryPoint, direction, _samplingStepSize * _jitterStepSizeMultiplier);
#ifdef ENABLE_SHADOWING
vec3 lightSourcePositionInTex = worldToTexture(_volumeTextureParams, _lightSource._position);
#endif
while (t < tend) {
// compute sample position
vec3 samplePosition = entryPoint.rgb + t * direction;
// lookup intensity and TF
vec4 color = getSampleColor(samplePosition);
#ifdef ENABLE_SHADOWING
float shadowSamplingStepSize = 2 * _samplingStepSize;
// compute direction from sample to light
vec3 L = normalize(lightSourcePositionInTex - samplePosition) * shadowSamplingStepSize;
// simple and expensive implementation of hard shadows
if (color.a > 0.01) {
bool finished = false;
vec3 shadowSamplePosition = samplePosition + L;
jitterEntryPoint(shadowSamplePosition, L, _jitterStepSizeMultiplier);
int lightSamples = SHADOW_STEPS;
float shadowFactor = 0.0;
// traverse ray from sample to light
while (! finished) {
// grab transparency for the shadow sample
shadowFactor += getSampleAlpha(shadowSamplePosition);
shadowSamplePosition += L;
finished = //(shadowFactor > 0.95)
--lightSamples < 0
|| any(lessThan(shadowSamplePosition, vec3(0.0, 0.0, 0.0)))
|| any(greaterThan(shadowSamplePosition, vec3(1.0, 1.0, 1.0)));
}
// apply shadow to color
color.rgb *= exp(- shadowFactor * shadowSamplingStepSize * _shadowIntensity * SAMPLING_BASE_INTERVAL_RCP);
}
#endif // ENABLE_SHADOWS
// perform compositing
if (color.a > 0.0) {
#ifdef ENABLE_SHADING
// compute gradient (needed for shading and normals)
vec3 gradient = getSampleGradient(samplePosition);
vec4 worldPos = _volumeTextureParams._textureToWorldMatrix * vec4(samplePosition, 1.0); // calling textureToWorld here crashes Intel HD driver and nVidia driver in debug mode, hence, let's calc it manually...
vec3 normal = -normalize(vec4(gradient, 0.0)).xyz; // negated because gradient is along increasing intensity but we want a surface normal
color.rgb = calculatePhongShading(worldPos.xyz / worldPos.w, _lightSource, _cameraPosition, normal, color.rgb);
#endif
// accomodate for variable sampling rates
color.a = 1.0 - pow(1.0 - color.a, _samplingStepSize * SAMPLING_BASE_INTERVAL_RCP);
blendUnder(result, color);
}
// save first hit ray parameter for depth value calculation
if (firstHitT < 0.0 && result.a > 0.3) {
firstHitT = t;
out_FHP = vec4(samplePosition, 1.0);
out_FHN = vec4(-normalize(getSampleGradient(samplePosition)), 1.0);
}
// early ray termination
if (result.a > 0.975) {
result.a = 1.0;
t = tend;
}
// 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) {
float depthEntry = texture(_entryPointsDepth, texCoords).z;
float depthExit = texture(_exitPointsDepth, texCoords).z;
gl_FragDepth = calculateDepthValue(firstHitT/tend, depthEntry, depthExit);
}
return result;
}
// ================================================================================================
//
// 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.
//
// ================================================================================================
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/gradient.frag"
#include "tools/raycasting.frag"
#include "tools/shading.frag"
#include "tools/texture2d.frag"
#include "tools/texture3d.frag"
#include "tools/transferfunction.frag"
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;
// Transfer function
uniform sampler1D _transferFunction;
uniform TFParameters1D _transferFunctionParams;
// Transfe