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 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)
IF(${ModuleEnabled})
# Source files:
FILE(GLOB ThisModSources RELATIVE ${ModulesDir}
FILE(GLOB ThisModSources RELATIVE ${ModulesDir}
modules/advancedraycasting/decorators/*.cpp
modules/advancedraycasting/pipelines/*.cpp
modules/advancedraycasting/processors/*.cpp
modules/advancedraycasting/tools/*.cpp
......@@ -17,7 +18,8 @@ IF(${ModuleEnabled})
modules/advancedraycasting/glsl/*.geom
modules/advancedraycasting/glsl/*.vert
modules/advancedraycasting/glsl/*.comp
modules/advancedraycasting/pipelines/*.h
modules/advancedraycasting/decorators/*.h
modules/advancedraycasting/pipelines/*.h
modules/advancedraycasting/processors/*.h
modules/advancedraycasting/tools/*.h
)
......
......@@ -25,13 +25,21 @@
#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<OCTStereoPlaneDemo>;
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;
}
......@@ -34,17 +34,6 @@ layout(location = 2) out vec4 out_FHN; ///< outgoing fragment first hit no
#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;
......@@ -78,6 +67,7 @@ uniform float _samplingStepSize;
const float SAMPLING_BASE_INTERVAL_RCP = 200.0;
//#define DEBUG_AO_DIRECTIONS
/**
* Performs the raycasting and returns the final fragment color.
......@@ -106,10 +96,39 @@ vec4 performRaycasting(in vec3 entryPoint, in vec3 exitPoint, in vec2 texCoords)
float intensity = texture(_volume, samplePosition).r;
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
if (color.a > 0.0) {
vec3 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
// compute gradient (needed for shading and normals)
......@@ -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
color.rgb = calculatePhongShading(worldPos.xyz / worldPos.w, ambientOcclusion, _lightSource, _cameraPosition, normal, color.rgb);
#else
color.rgb *= ambientOcclusion;
color.rgb *= ambientOcclusion;//*normalize(abs(n));
#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
color.a = 1.0 - pow(1.0 - color.a, _samplingStepSize * SAMPLING_BASE_INTERVAL_RCP);
blendUnder(result, color);
}
#endif
// save first hit ray parameter for depth value calculation
if (firstHitT < 0.0 && result.a > 0.0) {
......
......@@ -25,6 +25,7 @@
// (c) 2017 Jakob Weiss <jakob.weiss@tum.de>
#include "tools/transferfunction.frag"
#include "tools/texture3d.frag"
// The number of rays in each direction
#ifndef NUM_AO_RAYS
......@@ -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
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
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.a *= (1 - aoSampleOpacity);
aoRayPos += aoStep;
......@@ -95,13 +92,22 @@ vec4 computeLAORay(vec3 pos, vec3 dir, float aoStepSize, sampler3D tex, sampler1
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
vec3 anisotropicVoxel = volumeParameters._sizeRCP;// * volumeParameters._voxelSizeRCP;
vec3 anisotropicVoxel = volumeParameters._sizeRCP * volumeParameters._voxelSizeRCP;
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) {
aoRayDirs[i].rgb = anisotropicRayStep * nthSphereSample(aoSphereRadius, i, NUM_AO_RAYS);
aoRayDirs[i].a = length(aoRayDirs[i].rgb);
vec4 dir = vec4( nthSphereSample(1.0, i, NUM_AO_RAYS), 0.0);
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
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);
vec4 aoRayColor = computeLAORay(position, dir.xyz, dir.w, tex, volumeTF, volumeTFParams, aoEmissiveTF, aoEmissiveTFParams);
ambient += aoRayColor.rgb;
minOcclusionDir += (1.- aoRayColor.a) * dir.rgb;
minOcclusionDir += (1.- aoRayColor.a) * dir.xyz;
}
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.
//
// ================================================================================================
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"
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;
// pre-integrated volume
uniform sampler3D _volume;
uniform TextureParameters3D _volumeTextureParams;
uniform LightSource _lightSource;
uniform vec3 _cameraPosition;
uniform float _samplingStepSize;
#ifdef ENABLE_SHADOWING
uniform float _shadowIntensity;
#endif
const float SAMPLING_BASE_INTERVAL_RCP = 200.0;
float getSampleIntensity(vec3 pos) {
return texture(_volume, pos).r;
}
vec4 getSampleColor(vec3 pos) {
return texture(_volume, pos);
}
float getSampleAlpha(vec3 pos) {
return getSampleColor(pos).a;
}
vec3 getSampleGradient(vec3 pos) {
float dx = textureOffset(_volume, pos, ivec3(1, 0, 0)).a;
float dy = textureOffset(_volume, pos, ivec3(0, 1, 0)).a;
float dz = textureOffset(_volume, pos, ivec3(0, 0, 1)).a;
float mdx = textureOffset(_volume, pos, ivec3(-1, 0, 0)).a;
float mdy = textureOffset(_volume, pos, ivec3(0, -1, 0)).a;
float mdz = textureOffset(_volume, pos, ivec3(0, 0, -1)).a;
return vec3(dx - mdx, dy - mdy, dz - mdz) * _volumeTextureParams._voxelSizeRCP * 0.5;
}
#include "modules/advancedraycasting/glsl/genericraycastingloop.frag"
/***
* 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