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 88c45357 authored by Jakob Weiss's avatar Jakob Weiss

Implemented local ambient occlusion raycaster

Raycaster is based on the technique described in "Local Ambient Occlusion
in Direct Volume Rendering" by F. Hernell, P. Ljung, A. Ynnermann in IEEE
TVCG 2010.
Implementation does not allow for precomputed LAO volumes but instead
estimates the LAO term per sample.
parent e835e6f7
......@@ -109,7 +109,7 @@ namespace campvis {
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));
}
......@@ -163,4 +163,4 @@ namespace campvis {
return cgt::vec2(_keyPoints.front()._position, _keyPoints.back()._position);
}
}
\ No newline at end of file
}
......@@ -132,7 +132,7 @@ namespace campvis {
* \param color Color for ramp
* \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.
......
......@@ -171,4 +171,22 @@ float getPhongShadingIntensity(in vec3 position, in LightSource light, in vec3 c
toReturn *= computeAttenuation(light._attenuation, d);
#endif
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/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/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/processors/laoraycaster.h"
namespace campvis {
// explicitly instantiate templates to register the pipelines
//template class PipelineRegistrar<OCTStereoPlaneDemo>;
template class SmartProcessorRegistrar<LAORaycaster>;
}
// ================================================================================================
//
// 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 float _aoSphereRadius;
uniform float _aoGamma;
uniform float _aoOpacityScale;
uniform float _aoEmissiveScale;
#define AO_GAMMA _aoGamma
#define AO_OPACITY_SCALE _aoOpacityScale
#define AO_EMISSIVE_SCALE _aoEmissiveScale
#include "../../modules/advancedraycasting/glsl/localambientocclusion.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;
// Transfer function
uniform sampler1D _aoEmissiveTF;
uniform TFParameters1D _aoEmissiveTFParams;
uniform LightSource _lightSource;
uniform vec3 _cameraPosition;
uniform float _samplingStepSize;
const float SAMPLING_BASE_INTERVAL_RCP = 200.0;
/**
* 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);
// precompute the LAO ray directions
vec4 aoRayDirs[NUM_AO_RAYS];
initLAODirs(aoRayDirs, _aoSphereRadius, _volumeTextureParams);
while (t < tend) {
// compute sample position
vec3 samplePosition = entryPoint.rgb + t * direction;
// lookup intensity and TF
float intensity = texture(_volume, samplePosition).r;
vec4 color = lookupTF(_transferFunction, _transferFunctionParams, intensity);
// perform compositing
if (color.a > 0.0) {
vec3 n;
vec3 ambientOcclusion = computeLAO(samplePosition, aoRayDirs, _volume, _transferFunction, _transferFunctionParams, _aoEmissiveTF, _aoEmissiveTFParams, n);
#ifdef ENABLE_SHADING
// compute gradient (needed for shading and normals)
vec3 gradient = computeGradient(_volume, _volumeTextureParams, 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(_volumeTextureParams._textureToWorldMatrixInvTransp * vec4(gradient, 0.0)).xyz; // negated because gradient is along increasing intensity but we want a surface normal
vec3 normal = -normalize(_volumeTextureParams._textureToWorldMatrixInvTransp * vec4(n, 0.0)).xyz; // negated because gradient is along increasing intensity but we want a surface normal
color.rgb = calculatePhongShading(worldPos.xyz / worldPos.w, ambientOcclusion, _lightSource, _cameraPosition, normal, color.rgb);
#else
color.rgb *= ambientOcclusion;
#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.0) {
firstHitT = t;
out_FHP = vec4(samplePosition, 1.0);
out_FHN = vec4(normalize(computeGradient(_volume, _volumeTextureParams, 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;
}
/***
* 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-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>
#include "tools/transferfunction.frag"
// The number of rays in each direction
#ifndef NUM_AO_RAYS
#define NUM_AO_RAYS 12
#endif
// The number of steps in each direction
#ifndef NUM_AO_RAY_STEPS
#define NUM_AO_RAY_STEPS 12
#endif
// The gamma factor that controls the visual strength of the AO term
#ifndef AO_GAMMA
#define AO_GAMMA 1.0
#endif
// factor to control the strength of emissive materials.
#ifndef AO_EMISSIVE_SCALE
#define AO_EMISSIVE_SCALE 5.0
#endif
// factor to control the transparency used when computing the AO effect
#ifndef AO_OPACITY_SCALE
#define AO_OPACITY_SCALE 1.0
#endif
const float AO_SAMPLING_BASE_INTERVAL_RCP = 200.0;
vec3 nthSphereSample(float R, int n, int N) {
float golden_angle = 3.1415926535 * (3. - sqrt(5.));
float theta = golden_angle * float(n);
float t = float(n) / float(N - 1);
float z = (1. - t) * (1 - 1.0 / float(N)) + t * (1.0 / float(N) - 1); // TODO use mix() here
float radius = sqrt(1 - z * z);
return R * vec3(radius * cos(theta), radius * sin(theta), z);
}
vec4 computeLAORay(vec3 pos, vec3 dir, float aoStepSize, sampler3D tex, sampler1D volumeTF, TFParameters1D volumeTFParams, sampler1D aoEmissiveTF, TFParameters1D aoEmissiveTFParams)
{
vec3 aoStep = dir;
vec3 aoRayPos = pos + aoStep; // offset
vec4 aoColor = vec4(vec3(0), 1.0);
for(int i=0; i < NUM_AO_RAY_STEPS; ++i) {
// sample AO ray
float aoIntensity = texture(tex, aoRayPos).r;
vec4 aoSampleColor = lookupTF(volumeTF, volumeTFParams, aoIntensity);
float aoSampleOpacity = aoSampleColor.a * AO_OPACITY_SCALE; // Volume tf sample is used for it's opacity value
vec4 aoSampleEmissive = lookupTF(aoEmissiveTF, aoEmissiveTFParams, aoIntensity); // AO sample is used for the material's emissive color
//testing
aoSampleEmissive.rgb = aoSampleColor.rgb*aoSampleEmissive.a;
// compensate step size
aoSampleOpacity = 1.0 - pow(1.0 - aoSampleOpacity, AO_GAMMA * aoStepSize * AO_SAMPLING_BASE_INTERVAL_RCP);
//aoSampleEmissive.rgb *= aoStepSize * AO_SAMPLING_BASE_INTERVAL_RCP * aoSampleEmissive.a; // ao emissive color is multiplied by alpha for controlling the intensity
// accumulate
aoColor.rgb += (vec3(1) + AO_EMISSIVE_SCALE * aoSampleEmissive.rgb) * aoColor.a;
aoColor.a *= (1 - aoSampleOpacity);
aoRayPos += aoStep;
}
return aoColor;
}
void initLAODirs(inout vec4 aoRayDirs[NUM_AO_RAYS], float aoSphereRadius, TextureParameters3D volumeParameters) {
//Normalize for anisotropic voxel sizes
vec3 anisotropicVoxel = volumeParameters._sizeRCP;// * volumeParameters._voxelSizeRCP;
vec3 anisotropicRayStep = anisotropicVoxel / NUM_AO_RAY_STEPS;
for(int i=0; i < NUM_AO_RAYS; ++i) {
aoRayDirs[i].rgb = anisotropicRayStep * nthSphereSample(aoSphereRadius, i, NUM_AO_RAYS);
aoRayDirs[i].a = length(aoRayDirs[i].rgb);
}
}
vec3 computeLAO(vec3 position, in vec4 aoRayDirs[NUM_AO_RAYS], sampler3D tex, sampler1D volumeTF, TFParameters1D volumeTFParams, sampler1D aoEmissiveTF, TFParameters1D aoEmissiveTFParams, inout vec3 minOcclusionDir)
{
minOcclusionDir = vec3(0);
if(NUM_AO_RAYS*NUM_AO_RAY_STEPS > 0) {
vec3 ambient = vec3(0);
for(int i=0; i < NUM_AO_RAYS; ++i) {
//vec3 dir = nthSphereSample(1.0, i, NUM_AO_RAYS);
vec4 dir = aoRayDirs[i];
vec4 aoRayColor = computeLAORay(position, dir.rgb, dir.a, tex, volumeTF, volumeTFParams, aoEmissiveTF, aoEmissiveTFParams);
ambient += aoRayColor.rgb;
minOcclusionDir += (1.- aoRayColor.a) * dir.rgb;
}
minOcclusionDir = normalize(minOcclusionDir);
// normalize against number of samples
return ambient / (NUM_AO_RAYS * NUM_AO_RAY_STEPS);
}
else
return vec3(1);
}
vec3 computeLAO(vec3 position, in vec4 aoRayDirs[NUM_AO_RAYS], sampler3D tex, sampler1D volumeTF, TFParameters1D volumeTFParams, sampler1D aoEmissiveTF, TFParameters1D aoEmissiveTFParams)
{
vec3 minOcclusionDir;
return computeLAO(position, aoRayDirs, tex, volumeTF, volumeTFParams, aoEmissiveTF, aoEmissiveTFParams, minOcclusionDir);
}
// ================================================================================================
//
// 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 "laoraycaster.h"
#include "core/tools/quadrenderer.h"
#include "core/datastructures/lightsourcedata.h"
#include "core/datastructures/cameradata.h"
#include "core/datastructures/renderdata.h"
#include "core/datastructures/genericimagerepresentationlocal.h"
#include "core/datastructures/facegeometry.h"
#include "core/pipeline/processordecoratorgradient.h"
#include "core/classification/geometry1dtransferfunction.h"
#include <tbb/tbb.h>
namespace campvis {
const std::string LAORaycaster::loggerCat_ = "CAMPVis.modules.advrc.LAORaycaster";
LAORaycaster::LAORaycaster(IVec2Property* viewportSizeProp)
: RaycastingProcessor(viewportSizeProp, "modules/advancedraycasting/glsl/laoraycaster.frag", true)
, p_enableShading("EnableShading", "Enable Shading", false)
, 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)
, p_lightId("LightId", "Input Light Source", "lightsource", DataNameProperty::READ)
, p_quadGeometry("QuadGeometry", "Quad Geometry", "", DataNameProperty::READ)
{
addDecorator(new ProcessorDecoratorGradient());
addProperty(p_enableShading, INVALID_RESULT | INVALID_PROPERTIES | INVALID_SHADER);
addProperty(p_aoRays, INVALID_RESULT | INVALID_PROPERTIES | INVALID_SHADER);
addProperty(p_aoSamples, INVALID_RESULT | INVALID_PROPERTIES | INVALID_SHADER);
addProperty(p_aoSphereRadius);
addProperty(p_aoOpacityScale);
addProperty(p_aoEffectGamma);
addProperty(p_aoEmissiveTransferFunction);
addProperty(p_aoEmissiveScale);
addProperty(p_lightId);
addProperty(p_quadGeometry);
decoratePropertyCollection(this);
}
LAORaycaster::~LAORaycaster() {
}
void LAORaycaster::init() {
RaycastingProcessor::init();
}
void LAORaycaster::deinit() {
RaycastingProcessor::deinit();
}
void LAORaycaster::processImpl(DataContainer& data, ImageRepresentationGL::ScopedRepresentation& image) {
ScopedTypedData<LightSourceData> light(data, p_lightId.getValue());
ScopedTypedData<RenderData, true> outputImage(data, p_targetImageID.getValue());
ScopedTypedData<FaceGeometry> quadGeometry(data, p_quadGeometry.getValue(), true);
ScopedTypedData<CameraData> cam(data, p_camera.getValue());
if (p_enableShading.getValue() == false || light != nullptr) {
auto aotf = p_aoEmissiveTransferFunction.getTF();
cgt::TextureUnit aoTFUnit;
aotf->bind(_shader, aoTFUnit, "_aoEmissiveTF", "_aoEmissiveTFParams");
FramebufferActivationGuard fag(this);
createAndAttachTexture(GL_RGBA8, &outputImage);
createAndAttachTexture(GL_RGBA32F, &outputImage);
createAndAttachTexture(GL_RGBA32F, &outputImage);
createAndAttachDepthTexture(&outputImage);
static const GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 , GL_COLOR_ATTACHMENT2 };
glDrawBuffers(3, buffers);
if (p_enableShading.getValue() && light != nullptr) {
light->bind(_shader, "_lightSource");
}
_shader->setUniform("_aoSphereRadius", p_aoSphereRadius.getValue());
_shader->setUniform("_aoGamma", p_aoEffectGamma.getValue());
_shader->setUniform("_aoEmissiveScale", p_aoEmissiveScale.getValue());
_shader->setUniform("_aoOpacityScale", p_aoOpacityScale.getValue());
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (quadGeometry && cam) {
_shader->setUniform("_viewMatrix", cam->getCamera().getViewMatrix());
_shader->setUniform("_projectionMatrix", cam->getCamera().getProjectionMatrix());
quadGeometry->render(GL_TRIANGLE_FAN);
}
else {
QuadRdr.renderQuad();
}
// restore state
glDrawBuffers(1, buffers);
glDisable(GL_DEPTH_TEST);
LGL_ERROR;
data.addData(p_targetImageID.getValue(), new RenderData(_fbo));
}
else {
LDEBUG("Could not load light source from DataContainer.");
}
}
std::string LAORaycaster::generateHeader() const {
std::string toReturn = RaycastingProcessor::generateHeader();
if (p_enableShading.getValue())
toReturn += "#define ENABLE_SHADING\n";
toReturn += "#define NUM_AO_RAYS " + std::to_string(p_aoRays.getValue()) + "\n";
toReturn += "#define NUM_AO_RAY_STEPS " + std::to_string(p_aoSamples.getValue()) + "\n";
return toReturn;
}
void LAORaycaster::updateProperties(DataContainer& dataContainer) {
RaycastingProcessor::updateProperties(dataContainer);
p_lightId.setVisible(p_enableShading.getValue());
p_aoEmissiveTransferFunction.setVisible(p_aoEmissiveScale.getValue() > 0);
}
}
// ================================================================================================
//
// 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 LAORAYCASTER_H__
#define LAORAYCASTER_H__
#include "core/pipeline/raycastingprocessor.h"
#include "core/properties/floatingpointproperty.h"
#include "core/properties/genericproperty.h"
#include "core/properties/transferfunctionproperty.h"
#include "modules/modulesapi.h"
#include <string>
namespace cgt {
class Shader;
}
namespace campvis {
/**
* TODO
*/
class CAMPVIS_MODULES_API LAORaycaster : public RaycastingProcessor {
public:
/**
* Constructs a new SimpleRaycaster Processor
**/
explicit LAORaycaster(IVec2Property* viewportSizeProp);
/**
* Destructor
**/
virtual ~LAORaycaster();
/**
* To be used in ProcessorFactory static methods
*/
static const std::string getId() { return "LAORaycaster"; };
/// \see AbstractProcessor::getName()
virtual const std::string getName() const { return getId(); };
/// \see AbstractProcessor::getDescription()
virtual const std::string getDescription() const { return "Raycaster using Local Ambient Occlusion for gradient-free shading and emissive effects."; };
/// \see AbstractProcessor::getAuthor()
virtual const std::string getAuthor() const { return "Jakob Weiss <jakob.weiss@tum.de>"; };
/// \see AbstractProcessor::getProcessorState()
virtual ProcessorState getProcessorState() const { return AbstractProcessor::TESTING; };
/// \see AbstractProcessor::init
virtual void init();
/// \see AbstractProcessor::deinit
virtual void deinit();
BoolProperty p_enableShading; ///< Flag whether to enable shading
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
DataNameProperty p_lightId; ///< Name/ID for the LightSource to use
DataNameProperty p_quadGeometry;
protected:
/// \see AbstractProcessor::updateProperties()
virtual void updateProperties(DataContainer& dataContainer);
/// \see RaycastingProcessor::processImpl()
virtual void processImpl(DataContainer& data, ImageRepresentationGL::ScopedRepresentation& image);
/// \see RaycastingProcessor::generateHeader()
virtual std::string generateHeader() const;
static const std::string loggerCat_;
};
}
#endif // LAORAYCASTER_H__
......@@ -67,11 +67,6 @@ uniform float _shadowIntensity;
const float SAMPLING_BASE_INTERVAL_RCP = 200.0;
void blendUnder(inout vec4 result, in vec4 color) {
result.rgb = result.rgb + color.rgb * color.a * (1.0 - result.a);
result.a = result.a + (1.0 -result.a) * color.a;
}
/**