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 d97de6a8 authored by Christian Schulte zu Berge's avatar Christian Schulte zu Berge
Browse files

Merge branch 'ipsvi-raycaster' into 'master'

Ipsvi raycaster



See merge request !5
parents 3739711e d259aab2
......@@ -46,7 +46,11 @@ vec3 computeGradientForwardDifferencesLod(in sampler3D tex, in TextureParameters
* \param texCoords Lookup position in texture coordinates
*/
vec3 computeGradientForwardDifferences(in sampler3D tex, in TextureParameters3D texParams, in vec3 texCoords) {
return computeGradientForwardDifferencesLod(tex, texParams, texCoords, 0.0);
float v = texture(tex, texCoords).r;
float dx = textureOffset(tex, texCoords, ivec3(1, 0, 0)).r;
float dy = textureOffset(tex, texCoords, ivec3(0, 1, 0)).r;
float dz = textureOffset(tex, texCoords, ivec3(0, 0, 1)).r;
return vec3(dx - v, dy - v, dz - v) * texParams._voxelSize;
}
/**
......@@ -73,7 +77,13 @@ vec3 computeGradientCentralDifferencesLod(in sampler3D tex, in TextureParameters
* \param texCoords Lookup position in texture coordinates
*/
vec3 computeGradientCentralDifferences(in sampler3D tex, in TextureParameters3D texParams, in vec3 texCoords) {
return computeGradientCentralDifferencesLod(tex, texParams, texCoords, 0.0);
float dx = textureOffset(tex, texCoords, ivec3(1, 0, 0)).r;
float dy = textureOffset(tex, texCoords, ivec3(0, 1, 0)).r;
float dz = textureOffset(tex, texCoords, ivec3(0, 0, 1)).r;
float mdx = textureOffset(tex, texCoords, ivec3(-1, 0, 0)).r;
float mdy = textureOffset(tex, texCoords, ivec3(0, -1, 0)).r;
float mdz = textureOffset(tex, texCoords, ivec3(0, 0, -1)).r;
return vec3(dx - mdx, dy - mdy, dz - mdz) * texParams._voxelSize * 0.5;
}
......
......@@ -115,7 +115,7 @@ vec3 calculatePhongShading(in vec3 position, in LightSource light, in vec3 camer
* \param normal Normal
* \param materialColor Material color (used for all shading coefficients)
*/
vec3 calculatePhongShading(in vec3 position, in LightSource light, in vec3 camera, in vec3 normal, in vec3 materialColor) {
vec3 calculatePhongShading(in vec3 position, in vec3 ambientColorOverride, LightSource light, in vec3 camera, in vec3 normal, in vec3 materialColor) {
vec3 N = normalize(normal);
vec3 V = normalize(camera - position);
......@@ -124,7 +124,7 @@ vec3 calculatePhongShading(in vec3 position, in LightSource light, in vec3 camer
float d = length(L);
L /= d;
vec3 toReturn = materialColor * light._ambientColor; // ambient term
vec3 toReturn = materialColor * ambientColorOverride; // ambient term
toReturn += materialColor * getDiffuseTerm(light._diffuseColor, N, L);
toReturn += materialColor * getSpecularTerm(light._specularColor, N, L, V, light._shininess);
#ifdef PHONG_APPLY_ATTENUATION
......@@ -133,6 +133,19 @@ vec3 calculatePhongShading(in vec3 position, in LightSource light, in vec3 camer
return toReturn;
}
/**
* Computes the phong shading according to the given parameters.
*
* \param position sample position
* \param light LightSource
* \param camera Camera position
* \param normal Normal
* \param materialColor Material color (used for all shading coefficients)
*/
vec3 calculatePhongShading(in vec3 position, in LightSource light, in vec3 camera, in vec3 normal, in vec3 materialColor) {
return calculatePhongShading(position, light._ambientColor, light, camera, normal, materialColor);
}
/**
* Computes the phong shading intensity according to the given parameters.
......
......@@ -61,7 +61,7 @@ vec4 textureToWorld(in TextureParameters3D texParams, in vec4 texCoords) {
*/
vec3 textureToWorld(in TextureParameters3D texParams, in vec3 texCoords) {
vec4 v = textureToWorld(texParams, vec4(texCoords, 1.0));
return v.xyz;
return (v / v.w).xyz;
}
/**
......@@ -82,6 +82,7 @@ vec4 worldToTexture(in TextureParameters3D texParams, in vec4 worldCoords) {
* \param worldCoords world coordinates
* \return \a texCoords transformes to texture coordinates.
*/
vec4 worldToTexture(in TextureParameters3D texParams, in vec3 worldCoords) {
return worldToTexture(texParams, vec4(worldCoords, 1.0));
vec3 worldToTexture(in TextureParameters3D texParams, in vec3 worldCoords) {
vec4 v = worldToTexture(texParams, vec4(worldCoords, 1.0));
return (v / v.w).xyz;
}
......@@ -38,10 +38,8 @@ namespace campvis {
ProcessorDecoratorGradient::ProcessorDecoratorGradient()
: AbstractProcessorDecorator()
, p_gradientMethod("GradientMethod", "Gradient Computation Method", gradientOptions, 4)
, p_lod("GradientLod", "LOD for Gradient Computation", 0.5f, 0.f, 5.f, .1f, 1)
{
p_gradientMethod.setValue(1);
p_gradientMethod.s_changed.connect(this, &ProcessorDecoratorGradient::onGradientMethodChanged);
}
ProcessorDecoratorGradient::~ProcessorDecoratorGradient() {
......@@ -50,19 +48,16 @@ namespace campvis {
void ProcessorDecoratorGradient::addProperties(AbstractProcessor* propCollection) {
propCollection->addProperty(p_gradientMethod, AbstractProcessor::INVALID_SHADER | AbstractProcessor::INVALID_RESULT);
propCollection->addProperty(p_lod);
}
std::string ProcessorDecoratorGradient::generateHeader() const {
std::string toReturn;
switch (p_gradientMethod.getOptionValue()) {
case ForwardDifferences:
toReturn.append("#define computeGradient(tex, texParams, texCoords) computeGradientForwardDifferencesLod(tex, texParams, texCoords, _gradientLod)\n");
toReturn.append("uniform float _gradientLod = 0.0;\n");
toReturn.append("#define computeGradient(tex, texParams, texCoords) computeGradientForwardDifferences(tex, texParams, texCoords)\n");
break;
case CentralDifferences:
toReturn.append("#define computeGradient(tex, texParams, texCoords) computeGradientCentralDifferencesLod(tex, texParams, texCoords, _gradientLod)\n");
toReturn.append("uniform float _gradientLod = 0.0;\n");
toReturn.append("#define computeGradient(tex, texParams, texCoords) computeGradientCentralDifferences(tex, texParams, texCoords)\n");
break;
case FilteredCentralDifferences:
toReturn.append("#define computeGradient(tex, texParams, texCoords) computeGradientFilteredCentralDifferences(tex, texParams, texCoords)\n");
......@@ -78,14 +73,4 @@ namespace campvis {
return toReturn;
}
void ProcessorDecoratorGradient::renderProlog(const DataContainer& dataContainer, cgt::Shader* shader) {
if (p_gradientMethod.getOptionValue() == ForwardDifferences || p_gradientMethod.getOptionValue() == CentralDifferences) {
shader->setUniform("_gradientLod", p_lod.getValue());
}
}
void ProcessorDecoratorGradient::onGradientMethodChanged(const AbstractProperty* prop) {
p_lod.setVisible(p_gradientMethod.getOptionValue() == ForwardDifferences || p_gradientMethod.getOptionValue() == CentralDifferences);
}
}
......@@ -59,16 +59,10 @@ namespace campvis {
protected:
/// \see AbstractProcessorDecorator::addProperties()
void addProperties(AbstractProcessor* propCollection);
/// \see AbstractProcessorDecorator::renderProlog()
virtual void renderProlog(const DataContainer& dataContainer, cgt::Shader* shader);
/// \see AbstractProcessorDecorator::generateHeader()
std::string generateHeader() const;
/// Callback method when p_gradientMethod has changed
void onGradientMethodChanged(const AbstractProperty* prop);
GenericOptionProperty<GradientMethod> p_gradientMethod; ///< Method for calculating the gradients
FloatProperty p_lod; ///< LOD to use for texture lookup during gradient computation
};
......
......@@ -95,17 +95,6 @@ namespace campvis {
if (img != nullptr && entryPoints != nullptr && exitPoints != nullptr && camera != nullptr) {
if (img->getDimensionality() == 3) {
// little hack to support LOD texture lookup for the gradients:
// if texture does not yet have mipmaps, create them.
const cgt::Texture* tex = img->getTexture();
if (tex->getFilter() != cgt::Texture::MIPMAP) {
const_cast<cgt::Texture*>(tex)->setFilter(cgt::Texture::MIPMAP);
glGenerateMipmap(GL_TEXTURE_3D);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
LGL_ERROR;
}
_shader->activate();
_shader->setIgnoreUniformLocationError(true);
......
......@@ -472,6 +472,9 @@ const GpuCapabilities::GlVersion GpuCapabilities::GlVersion::CGT_GL_VERSION_3_3(
const GpuCapabilities::GlVersion GpuCapabilities::GlVersion::CGT_GL_VERSION_4_0(4,0,0);
const GpuCapabilities::GlVersion GpuCapabilities::GlVersion::CGT_GL_VERSION_4_1(4,1,0);
const GpuCapabilities::GlVersion GpuCapabilities::GlVersion::CGT_GL_VERSION_4_2(4,2,0);
const GpuCapabilities::GlVersion GpuCapabilities::GlVersion::CGT_GL_VERSION_4_3(4,3,0);
const GpuCapabilities::GlVersion GpuCapabilities::GlVersion::CGT_GL_VERSION_4_4(4,4,0);
const GpuCapabilities::GlVersion GpuCapabilities::GlVersion::CGT_GL_VERSION_4_5(4,5,0);
const GpuCapabilities::GlVersion GpuCapabilities::GlVersion::SHADER_VERSION_110(1,10); ///< GLSL version 1.10
const GpuCapabilities::GlVersion GpuCapabilities::GlVersion::SHADER_VERSION_120(1,20); ///< GLSL version 1.20
......@@ -482,6 +485,9 @@ const GpuCapabilities::GlVersion GpuCapabilities::GlVersion::SHADER_VERSION_330(
const GpuCapabilities::GlVersion GpuCapabilities::GlVersion::SHADER_VERSION_400(4, 0); ///< GLSL version 4.00
const GpuCapabilities::GlVersion GpuCapabilities::GlVersion::SHADER_VERSION_410(4,10); ///< GLSL version 4.10
const GpuCapabilities::GlVersion GpuCapabilities::GlVersion::SHADER_VERSION_420(4,20); ///< GLSL version 4.20
const GpuCapabilities::GlVersion GpuCapabilities::GlVersion::SHADER_VERSION_430(4,30); ///< GLSL version 4.30
const GpuCapabilities::GlVersion GpuCapabilities::GlVersion::SHADER_VERSION_440(4,40); ///< GLSL version 4.40
const GpuCapabilities::GlVersion GpuCapabilities::GlVersion::SHADER_VERSION_450(4,50); ///< GLSL version 4.50
GpuCapabilities::GlVersion::GlVersion(int major, int minor, int release)
: major_(major), minor_(minor), release_(release)
......
......@@ -114,6 +114,9 @@ public:
static const GlVersion CGT_GL_VERSION_4_0;
static const GlVersion CGT_GL_VERSION_4_1;
static const GlVersion CGT_GL_VERSION_4_2;
static const GlVersion CGT_GL_VERSION_4_3;
static const GlVersion CGT_GL_VERSION_4_4;
static const GlVersion CGT_GL_VERSION_4_5;
static const GlVersion SHADER_VERSION_110; ///< GLSL version 1.10
static const GlVersion SHADER_VERSION_120; ///< GLSL version 1.20
......@@ -124,6 +127,9 @@ public:
static const GlVersion SHADER_VERSION_400; ///< GLSL version 4.00
static const GlVersion SHADER_VERSION_410; ///< GLSL version 4.10
static const GlVersion SHADER_VERSION_420; ///< GLSL version 4.20
static const GlVersion SHADER_VERSION_430; ///< GLSL version 4.30
static const GlVersion SHADER_VERSION_440; ///< GLSL version 4.40
static const GlVersion SHADER_VERSION_450; ///< GLSL version 4.50
};
......
......@@ -73,6 +73,7 @@ const float SAMPLING_BASE_INTERVAL_RCP = 200.0;
vec4 performRaycasting(in vec3 entryPoint, in vec3 exitPoint, in vec2 texCoords) {
vec4 result = vec4(0.0);
vec3 direction = exitPoint - entryPoint;
float len = length(direction);
// Adjust direction a bit to prevent division by zero
direction.x = (abs(direction.x) < 0.0000001) ? 0.0000001 : direction.x;
......@@ -129,7 +130,7 @@ vec4 performRaycasting(in vec3 entryPoint, in vec3 exitPoint, in vec2 texCoords)
}
// advance to the next evaluation point along the ray
tNear += _samplingStepSize;
tNear += _samplingStepSize / len;
}
......
// ================================================================================================
//
// 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"
#include "modules/vis/glsl/voxelhierarchy.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;
// DRR volume
uniform sampler3D _volume;
uniform TextureParameters3D _volumeTextureParams;
// Transfer function
uniform sampler1D _transferFunction;
uniform TFParameters1D _transferFunctionParams;
// Illumination cache
uniform layout(r32f) image2D _icImageIn;
uniform layout(r32f) image2D _icImageOut;
uniform vec3 _icOrigin;
uniform vec3 _icNormal;
uniform vec3 _icRightVector;
uniform vec3 _icUpVector;
uniform float _shadowIntensity = 0.5;
// Voxel Hierarchy Lookup volume
uniform usampler2D _voxelHierarchy;
uniform int _vhMaxMipMapLevel;
uniform LightSource _lightSource;
uniform vec3 _cameraPosition;
uniform float _samplingStepSize;
const float SAMPLING_BASE_INTERVAL_RCP = 200.0;
// projects a vector in world coordinates onto the IC
// returns world coordinates
ivec2 calcIcSamplePosition(vec3 worldPosition) {
// project world position onto IC plane
const vec3 diag = worldPosition - _icOrigin;
const float distance = abs(dot(diag, _icNormal));
const vec3 worldProjected = diag - (-distance * _icNormal);
// transforms world coordinates (have to be lying on the IC plane) to IC pixel space
return ivec2(round(dot(worldProjected, _icRightVector)), round(dot(worldProjected, _icUpVector)));
}
// the composite function can be used for additional shadow ray integration
// from the current sample to the position of the IC.
// However, it's currently not used for performance reasons
void composite(vec3 startPosition, vec3 endPosition, inout float opacity) {
vec3 direction = endPosition - startPosition;
float t = _samplingStepSize;
jitterFloat(t, _samplingStepSize); // jitter startpoint to avoid ringing artifacts (not really effective...)
float tend = min(length(direction), 4*_samplingStepSize);
direction = normalize(direction);
while (t < tend) {
// lookup intensity and TF
vec3 samplePosition = startPosition.xyz + t * direction;
float intensity = texture(_volume, samplePosition).r;
float tfOpacity = lookupTF(_transferFunction, _transferFunctionParams, intensity).a;
opacity = opacity + (1.0 - opacity) * tfOpacity;
t += _samplingStepSize;
}
}
/**
* 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 len = length(direction);
// Adjust direction a bit to prevent division by zero
direction.x = (abs(direction.x) < 0.0001) ? 0.0001 : direction.x;
direction.y = (abs(direction.y) < 0.0001) ? 0.0001 : direction.y;
direction.z = (abs(direction.z) < 0.0001) ? 0.0001 : direction.z;
OFFSET = (0.25 / (1 << _vhMaxMipMapLevel)); //< offset value used to avoid self-intersection or previous voxel intersection.
float t = clipFirstHitpoint(_voxelHierarchy, _vhMaxMipMapLevel, entryPoint, direction, 0.0, 1.0);
float tend = 1.0 - clipFirstHitpoint(_voxelHierarchy, _vhMaxMipMapLevel, exitPoint, -direction, 0.0, 1.0);
jitterEntryPoint(entryPoint, direction, _samplingStepSize * _jitterStepSizeMultiplier);
ivec2 icPositionPrev = calcIcSamplePosition(textureToWorld(_volumeTextureParams, entryPoint.rgb + t * direction));
float icIn = imageLoad(_icImageIn, icPositionPrev).r;
float icOut = (0.0);
bool toBeSaved = false;
while (t < tend) {
// compute sample position
vec3 samplePosition = entryPoint.rgb + t * direction;
vec3 worldPos = textureToWorld(_volumeTextureParams, samplePosition);
ivec2 icPosition = calcIcSamplePosition(worldPos);
// optimization: Only store/load when the icPosition has changed
// otherwise we can reuse the variables from the previous sample
if (icPositionPrev != icPosition) {
// write illumination information
if (toBeSaved)
imageStore(_icImageOut, icPositionPrev, vec4(icOut));
toBeSaved = false;
// load illumination information
icIn = imageLoad(_icImageIn, icPosition).r;
// perform a compositing from samplePosition to the samplePosition of the IC
// Currently disabled since it leads to ringing artifacts...
//if (icIn.xyz != vec3(0.0))
// composite(samplePosition, icIn.xyz, icIn.a);
}
// lookup intensity and TF
float intensity = texture(_volume, samplePosition).r;
vec4 color = lookupTF(_transferFunction, _transferFunctionParams, intensity);
// perform compositing
if (color.a > 0.0) {
// compute gradient (needed for shading and normals)
vec3 gradient = computeGradient(_volume, _volumeTextureParams, samplePosition);
// accomodate for variable sampling rates
color.a = 1.0 - pow(1.0 - color.a, _samplingStepSize * SAMPLING_BASE_INTERVAL_RCP);
// perform global illumination
// back-to-front compositing from light-direction
// (for now, we ignore the color contribution and store the world position instead)
// icOut.rgb = ((1.0 - color.a) * icIn.rgb) + (color.a * color.rgb);
//icOut.xyz = samplePosition;
icOut = ((1.0 - color.a) * icIn) + color.a;
toBeSaved = true;
// apply shadowing
const vec3 ambientColorOverride = _lightSource._ambientColor * (1.0 - icIn * _shadowIntensity);
color.rgb = calculatePhongShading(worldPos, ambientColorOverride, _lightSource, _cameraPosition, gradient, color.rgb);
// front-to-back compositing along view direction
result.rgb = result.rgb + color.rgb * color.a * (1.0 - result.a);
result.a = result.a + (1.0 -result.a) * color.a;
icPositionPrev = icPosition;
}
// 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(icPosition, 0.0, 0.0);// vec4(normalize(computeGradient(_volume, _volumeTextureParams, samplePosition)), 1.0);
}
// early ray termination (disabled!)
//if (result.a > 0.975) {
// result.a = 1.0;
// t = tend;
//}
// advance to the next evaluation point along the ray
t += _samplingStepSize / len;
}
if (toBeSaved)
imageStore(_icImageOut, icPositionPrev, vec4(icOut));
// 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);
}
}
\ No newline at end of file
......@@ -67,7 +67,7 @@ namespace campvis {
dvrTF->addGeometry(TFGeometry1D::createQuad(cgt::vec2(.19f, .28f), cgt::col4(89, 89, 89, 155), cgt::col4(89, 89, 89, 155)));
dvrTF->addGeometry(TFGeometry1D::createQuad(cgt::vec2(.41f, .51f), cgt::col4(170, 170, 128, 64), cgt::col4(192, 192, 128, 64)));
static_cast<TransferFunctionProperty*>(_vr.getNestedProperty("RaycasterProps::TransferFunction"))->replaceTF(dvrTF);
static_cast<FloatProperty*>(_vr.getNestedProperty("RaycasterProps::SamplingRate"))->setValue(4.f);
static_cast<FloatProperty*>(_vr.getNestedProperty("RaycasterProps::SamplingRate"))->setValue(2.f);
}
}
\ No newline at end of file
......@@ -55,8 +55,6 @@ namespace campvis {
}
void AdvOptimizedRaycaster::init() {
RaycastingProcessor::init();
_vhm = new VoxelHierarchyMapper();
......@@ -84,10 +82,6 @@ namespace campvis {
ScopedTypedData<LightSourceData> light(data, p_lightId.getValue());
if (p_enableShading.getValue() == false || light != nullptr) {
// undo MIPMAP hack from RaycastingProcessor, as mipmapping results in artifacts during ray clipping...
if (image->getTexture()->getFilter() != cgt::Texture::LINEAR)
const_cast<cgt::Texture*>(image->getTexture())->setFilter(cgt::Texture::LINEAR);
_shader->activate();
cgt::TextureUnit xorUnit, bbvUnit;
......
// ================================================================================================
//
// 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 "ipsviraycaster.h"
#include "core/tools/quadrenderer.h"
#include "core/datastructures/cameradata.h"
#include "core/datastructures/lightsourcedata.h"
#include "core/datastructures/renderdata.h"
#include "core/datastructures/genericimagerepresentationlocal.h"
#include "core/pipeline/processordecoratorgradient.h"
#include "modules/vis/tools/voxelhierarchymapper.h"
#include <tbb/tbb.h>
namespace campvis {
const std::string IpsviRaycaster::loggerCat_ = "CAMPVis.modules.vis.IpsviRaycaster";
IpsviRaycaster::IpsviRaycaster(IVec2Property* viewportSizeProp)
: RaycastingProcessor(viewportSizeProp, "modules/vis/glsl/ipsviraycaster.frag", true, "440")
, p_lightId("LightId", "Input Light Source", "lightsource", DataNameProperty::READ)
, p_sweepLineWidth("SweepLineWidth", "Sweep Line Width", 2, 1, 32)
, p_icTextureSize("IcTextureSize", "Illumination Cache Texture Size", cgt::ivec2(512), cgt::ivec2(32), cgt::ivec2(2048))
, p_shadowIntensity("ShadowIntensity", "Shadow Intensity", .75f, 0.f, 1.f)
, _vhm(nullptr)
, _gl44Supported(false)
{
_icTextures[0] = nullptr;
_icTextures[1] = nullptr;
addProperty(p_lightId);
addProperty(p_sweepLineWidth);
addProperty(p_icTextureSize, INVALID_RESULT | INVALID_IC_TEXTURES);
addProperty(p_shadowIntensity);
setPropertyInvalidationLevel(p_transferFunction, INVALID_BBV | INVALID_RESULT);
setPropertyInvalidationLevel(p_sourceImageID, INVALID_BBV | INVALID_RESULT);
addDecorator(new ProcessorDecoratorGradient());
decoratePropertyCollection(this);
}
IpsviRaycaster::~IpsviRaycaster() {
}
void IpsviRaycaster::init() {
// get supported OpenGL version
// if OpenGL 4.4 is not supported, abort the initialization, since compiling the shader will fail.
_gl44Supported = (GpuCaps.getGlVersion() >= cgt::GpuCapabilities::GlVersion::CGT_GL_VERSION_4_4);
_gl44Supported &= (GpuCaps.getShaderVersion() >= cgt::GpuCapabilities::GlVersion::SHADER_VERSION_440);
if (! _gl44Supported) {
LERROR("This system does not support OpenGL 4.4, which is required for the IpsviRaycaster. Raycaster deactivated.");
return;
}
RaycastingProcessor::init();
_vhm = new VoxelHierarchyMapper();
invalidate(INVALID_BBV | INVALID_IC_TEXTURES);
}
void IpsviRaycaster::deinit() {
// nothing to deinitialize, if this processor has never been initialized.
if (!_gl44Supported)
return;
delete _vhm;
delete _icTextures[0];
delete _icTextures[1];