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

Commit cd918f81 authored by Jakob Weiss's avatar Jakob Weiss

Advanced Raycasting features

* ambient occlusion refactored as a decorator
* pre-integrated raycaster and processor to pre-integrate TF
parent 88c45357
...@@ -4,7 +4,8 @@ SET(ThisModStatus EXPERIMENTAL) ...@@ -4,7 +4,8 @@ SET(ThisModStatus EXPERIMENTAL)
IF(${ModuleEnabled}) IF(${ModuleEnabled})
# Source files: # Source files:
FILE(GLOB ThisModSources RELATIVE ${ModulesDir} FILE(GLOB ThisModSources RELATIVE ${ModulesDir}
modules/advancedraycasting/decorators/*.cpp
modules/advancedraycasting/pipelines/*.cpp modules/advancedraycasting/pipelines/*.cpp
modules/advancedraycasting/processors/*.cpp modules/advancedraycasting/processors/*.cpp
modules/advancedraycasting/tools/*.cpp modules/advancedraycasting/tools/*.cpp
...@@ -17,7 +18,8 @@ IF(${ModuleEnabled}) ...@@ -17,7 +18,8 @@ IF(${ModuleEnabled})
modules/advancedraycasting/glsl/*.geom modules/advancedraycasting/glsl/*.geom
modules/advancedraycasting/glsl/*.vert modules/advancedraycasting/glsl/*.vert
modules/advancedraycasting/glsl/*.comp modules/advancedraycasting/glsl/*.comp
modules/advancedraycasting/pipelines/*.h modules/advancedraycasting/decorators/*.h
modules/advancedraycasting/pipelines/*.h
modules/advancedraycasting/processors/*.h modules/advancedraycasting/processors/*.h
modules/advancedraycasting/tools/*.h modules/advancedraycasting/tools/*.h
) )
......
...@@ -25,13 +25,21 @@ ...@@ -25,13 +25,21 @@
#include "core/pipeline/pipelinefactory.h" #include "core/pipeline/pipelinefactory.h"
#include "core/pipeline/processorfactory.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/laoraycaster.h"
#include "modules/advancedraycasting/processors/preintegratedraycaster.h"
#include "modules/advancedraycasting/processors/tfpreintegrator.h"
namespace campvis { namespace campvis {
// explicitly instantiate templates to register the pipelines // explicitly instantiate templates to register the pipelines
//template class PipelineRegistrar<OCTStereoPlaneDemo>; template class PipelineRegistrar<PreintegratedRayCasterDemo>;
template class SmartProcessorRegistrar<AmbientVolumeGenerator>;
template class SmartProcessorRegistrar<LAORaycaster>; 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;
}
...@@ -34,17 +34,6 @@ layout(location = 2) out vec4 out_FHN; ///< outgoing fragment first hit no ...@@ -34,17 +34,6 @@ layout(location = 2) out vec4 out_FHN; ///< outgoing fragment first hit no
#include "tools/transferfunction.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 vec2 _viewportSizeRCP;
uniform float _jitterStepSizeMultiplier; uniform float _jitterStepSizeMultiplier;
...@@ -78,6 +67,7 @@ uniform float _samplingStepSize; ...@@ -78,6 +67,7 @@ uniform float _samplingStepSize;
const float SAMPLING_BASE_INTERVAL_RCP = 200.0; const float SAMPLING_BASE_INTERVAL_RCP = 200.0;
//#define DEBUG_AO_DIRECTIONS
/** /**
* Performs the raycasting and returns the final fragment color. * Performs the raycasting and returns the final fragment color.
...@@ -106,10 +96,39 @@ vec4 performRaycasting(in vec3 entryPoint, in vec3 exitPoint, in vec2 texCoords) ...@@ -106,10 +96,39 @@ vec4 performRaycasting(in vec3 entryPoint, in vec3 exitPoint, in vec2 texCoords)
float intensity = texture(_volume, samplePosition).r; float intensity = texture(_volume, samplePosition).r;
vec4 color = lookupTF(_transferFunction, _transferFunctionParams, intensity); vec4 color = lookupTF(_transferFunction, _transferFunctionParams, intensity);
#ifdef DEBUG_AO_DIRECTIONS
// allows to quickly check if the ray directions are uniformly distributed even for non-uniform volume/voxel sizes
color = vec4(0);
for(int i=0; i < NUM_AO_RAYS; ++i) {
//vec3 dir = nthSphereSample(1.0, i, NUM_AO_RAYS);
vec4 dir = aoRayDirs[i];
vec3 p = samplePosition - vec3(0.5);// + dir.xyz*200;
float d = 1. - clamp(dot(normalize(p), normalize(dir.xyz)), 0, 1);
float r = length(p) - 10*length(dir.xyz);
//r *= smoothstep(0.4, 0.5, length(p));
float a= clamp(exp(-d*d/0.01) * exp(-r*r/0.001), 0, 1);
if(r > 0 && color.a < a) {
color.rgb = abs(normalize(dir.xyz));
color.a = a;
}
}
// accomodate for variable sampling rates
color.a = 1.0 - pow(1.0 - color.a, _samplingStepSize * SAMPLING_BASE_INTERVAL_RCP);
blendUnder(result, color);
#else
// perform compositing // perform compositing
if (color.a > 0.0) { if (color.a > 0.0) {
vec3 n; vec3 n;
vec3 ambientOcclusion = computeLAO(samplePosition, aoRayDirs, _volume, _transferFunction, _transferFunctionParams, _aoEmissiveTF, _aoEmissiveTFParams, n); vec3 ambientOcclusion = computeLAO(samplePosition, aoRayDirs, _volume, _transferFunction, _transferFunctionParams, _aoEmissiveTF, _aoEmissiveTFParams, n);
vec4 aoSampleColor = lookupTF(_aoEmissiveTF, _aoEmissiveTFParams, intensity);
// emissive transfer function overrides the original TF color
if(aoSampleColor.a > 0) {
color.rgb = aoSampleColor.rgb;
}
#ifdef ENABLE_SHADING #ifdef ENABLE_SHADING
// compute gradient (needed for shading and normals) // compute gradient (needed for shading and normals)
...@@ -119,15 +138,19 @@ vec4 performRaycasting(in vec3 entryPoint, in vec3 exitPoint, in vec2 texCoords) ...@@ -119,15 +138,19 @@ vec4 performRaycasting(in vec3 entryPoint, in vec3 exitPoint, in vec2 texCoords)
vec3 normal = -normalize(_volumeTextureParams._textureToWorldMatrixInvTransp * vec4(n, 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); color.rgb = calculatePhongShading(worldPos.xyz / worldPos.w, ambientOcclusion, _lightSource, _cameraPosition, normal, color.rgb);
#else #else
color.rgb *= ambientOcclusion; color.rgb *= ambientOcclusion;//*normalize(abs(n));
#endif #endif
// With this enabled, raycaster will show the influence of the AO comptuation. useful for parameter tuning and debugging
#ifdef SHOW_AO_ONLY
color.rgb = ambientOcclusion;
#endif
// accomodate for variable sampling rates // accomodate for variable sampling rates
color.a = 1.0 - pow(1.0 - color.a, _samplingStepSize * SAMPLING_BASE_INTERVAL_RCP); color.a = 1.0 - pow(1.0 - color.a, _samplingStepSize * SAMPLING_BASE_INTERVAL_RCP);
blendUnder(result, color); blendUnder(result, color);
} }
#endif
// save first hit ray parameter for depth value calculation // save first hit ray parameter for depth value calculation
if (firstHitT < 0.0 && result.a > 0.0) { if (firstHitT < 0.0 && result.a > 0.0) {
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
// (c) 2017 Jakob Weiss <jakob.weiss@tum.de> // (c) 2017 Jakob Weiss <jakob.weiss@tum.de>
#include "tools/transferfunction.frag" #include "tools/transferfunction.frag"
#include "tools/texture3d.frag"
// The number of rays in each direction // The number of rays in each direction
#ifndef NUM_AO_RAYS #ifndef NUM_AO_RAYS
...@@ -77,16 +78,12 @@ vec4 computeLAORay(vec3 pos, vec3 dir, float aoStepSize, sampler3D tex, sampler1 ...@@ -77,16 +78,12 @@ vec4 computeLAORay(vec3 pos, vec3 dir, float aoStepSize, sampler3D tex, sampler1
float aoSampleOpacity = aoSampleColor.a * AO_OPACITY_SCALE; // Volume tf sample is used for it's opacity value 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 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 // compensate step size
aoSampleOpacity = 1.0 - pow(1.0 - aoSampleOpacity, AO_GAMMA * aoStepSize * AO_SAMPLING_BASE_INTERVAL_RCP); 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 aoSampleEmissive.rgb *= aoStepSize * AO_SAMPLING_BASE_INTERVAL_RCP * aoSampleEmissive.a; // ao emissive color is multiplied by alpha for controlling the intensity
// accumulate // accumulate
aoColor.rgb += (vec3(1) + AO_EMISSIVE_SCALE * aoSampleEmissive.rgb) * aoColor.a; aoColor.rgb += (vec3(1) + AO_EMISSIVE_SCALE * aoSampleEmissive.rgb) * aoColor.a;
aoColor.a *= (1 - aoSampleOpacity); aoColor.a *= (1 - aoSampleOpacity);
aoRayPos += aoStep; aoRayPos += aoStep;
...@@ -95,13 +92,22 @@ vec4 computeLAORay(vec3 pos, vec3 dir, float aoStepSize, sampler3D tex, sampler1 ...@@ -95,13 +92,22 @@ vec4 computeLAORay(vec3 pos, vec3 dir, float aoStepSize, sampler3D tex, sampler1
return aoColor; return aoColor;
} }
void initLAODirs(inout vec4 aoRayDirs[NUM_AO_RAYS], float aoSphereRadius, TextureParameters3D volumeParameters) { void initLAODirs(inout vec4 aoRayDirs[NUM_AO_RAYS], float aoSphereRadius, TextureParameters3D volumeParameters)
{
//Normalize for anisotropic voxel sizes //Normalize for anisotropic voxel sizes
vec3 anisotropicVoxel = volumeParameters._sizeRCP;// * volumeParameters._voxelSizeRCP; vec3 anisotropicVoxel = volumeParameters._sizeRCP * volumeParameters._voxelSizeRCP;
vec3 anisotropicRayStep = anisotropicVoxel / NUM_AO_RAY_STEPS; vec3 anisotropicRayStep = anisotropicVoxel / NUM_AO_RAY_STEPS;
float voxelSize = length(volumeParameters._sizeRCP) / sqrt(3);
float scale = aoSphereRadius * voxelSize / NUM_AO_RAY_STEPS;
for(int i=0; i < NUM_AO_RAYS; ++i) { for(int i=0; i < NUM_AO_RAYS; ++i) {
aoRayDirs[i].rgb = anisotropicRayStep * nthSphereSample(aoSphereRadius, i, NUM_AO_RAYS); vec4 dir = vec4( nthSphereSample(1.0, i, NUM_AO_RAYS), 0.0);
aoRayDirs[i].a = length(aoRayDirs[i].rgb); aoRayDirs[i].xyz = scale * normalize((volumeParameters._worldToTextureMatrixInvTransp * dir).xyz);
//this is somehow slower to compute...
//aoRayDirs[i].xyz = anisotropicRayStep * nthSphereSample(aoSphereRadius, i, NUM_AO_RAYS);
aoRayDirs[i].w = length(aoRayDirs[i].xyz);
} }
} }
...@@ -114,10 +120,10 @@ vec3 computeLAO(vec3 position, in vec4 aoRayDirs[NUM_AO_RAYS], sampler3D tex, sa ...@@ -114,10 +120,10 @@ vec3 computeLAO(vec3 position, in vec4 aoRayDirs[NUM_AO_RAYS], sampler3D tex, sa
for(int i=0; i < NUM_AO_RAYS; ++i) { for(int i=0; i < NUM_AO_RAYS; ++i) {
//vec3 dir = nthSphereSample(1.0, i, NUM_AO_RAYS); //vec3 dir = nthSphereSample(1.0, i, NUM_AO_RAYS);
vec4 dir = aoRayDirs[i]; vec4 dir = aoRayDirs[i];
vec4 aoRayColor = computeLAORay(position, dir.rgb, dir.a, tex, volumeTF, volumeTFParams, aoEmissiveTF, aoEmissiveTFParams); vec4 aoRayColor = computeLAORay(position, dir.xyz, dir.w, tex, volumeTF, volumeTFParams, aoEmissiveTF, aoEmissiveTFParams);
ambient += aoRayColor.rgb; ambient += aoRayColor.rgb;
minOcclusionDir += (1.- aoRayColor.a) * dir.rgb; minOcclusionDir += (1.- aoRayColor.a) * dir.xyz;
} }
minOcclusionDir = normalize(minOcclusionDir); minOcclusionDir = normalize(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.
//