Commit 76156663 authored by Christian Schulte zu Berge's avatar Christian Schulte zu Berge
Browse files

Merge branch 'merge-advancedusvis' into 'development'

Merge Pre-Paper Work

Cleaned and squashed version of the various works done for the different paper deadlines during the last months.
parents 79f58d99 70f14e1a
......@@ -64,6 +64,24 @@ SET(CampvisApplicationToBeMocced
tools/bufferinglog.h
)
# add additional sources from the activated modules
FOREACH(ModFile ${CampvisModulesApplicationSources})
# adjust relative path
SET(ModFileRelative ../modules/${ModFile})
LIST(APPEND CampvisApplicationSources ${ModFileRelative})
ENDFOREACH()
FOREACH(ModFile ${CampvisModulesApplicationHeaders})
# adjust relative path
SET(ModFileRelative ../modules/${ModFile})
LIST(APPEND CampvisApplicationHeaders ${ModFileRelative})
ENDFOREACH()
FOREACH(ModFile ${CampvisModulesApplicationToBeMocced})
# adjust relative path
SET(ModFileRelative ../modules/${ModFile})
LIST(APPEND CampvisApplicationToBeMocced ${ModFileRelative})
ENDFOREACH()
#
# Qt related stuff:
#
......
......@@ -98,7 +98,8 @@ IF(WIN32)
# C4503: The decorated name was longer than the compiler limit (4096), and was truncated.
# Occurs in AutoEvaluatePipeline due to some nested nested map-iterator-map. Could
# not be deactivated locally...
LIST(APPEND CampvisGlobalDefinitions /wd4251 /wd4290 /wd4390 /wd4503)
# C4068: Unknown Pragma since we use some GCC pragmas in the code.
LIST(APPEND CampvisGlobalDefinitions /wd4251 /wd4290 /wd4390 /wd4503 /wd4068)
# enable parallel builds in Visual Studio
LIST(APPEND CampvisGlobalDefinitions /MP)
......
......@@ -89,6 +89,9 @@ MACRO(INCLUDE_MODULE ModuleDirectory ModuleListFile)
LIST(APPEND CampvisModulesHeaders ${ThisModHeaders})
LIST(APPEND CampvisModulesCoreSources ${ThisModCoreSources})
LIST(APPEND CampvisModulesCoreHeaders ${ThisModCoreHeaders})
LIST(APPEND CampvisModulesApplicationSources ${ThisModApplicationSources})
LIST(APPEND CampvisModulesApplicationHeaders ${ThisModApplicationHeaders})
LIST(APPEND CampvisModulesApplicationToBeMocced ${ThisModApplicationToBeMocced})
LIST(APPEND CampvisExternalDllsDebug ${ThisModExternalDllsDebug})
LIST(APPEND CampvisExternalDllsRelease ${ThisModExternalDllsRelease})
......@@ -116,6 +119,9 @@ MACRO(INCLUDE_MODULE ModuleDirectory ModuleListFile)
UNSET(ThisModHeaders)
UNSET(ThisModCoreSources)
UNSET(ThisModCoreHeaders)
UNSET(CampvisApplicationSources)
UNSET(CampvisApplicationHeaders)
UNSET(CampvisApplicationToBeMocced)
UNSET(ThisModExternalDllsDebug)
UNSET(ThisModExternalDllsRelease)
UNSET(ThisModShaderDirectories)
......
......@@ -25,6 +25,7 @@
#include "datacontainer.h"
#include "tgt/assert.h"
#include "tgt/logmanager.h"
#include "core/datastructures/abstractdata.h"
namespace campvis {
......@@ -41,14 +42,27 @@ namespace campvis {
}
DataHandle DataContainer::addData(const std::string& name, AbstractData* data) {
if (name.empty()) {
LERROR("Tried to add data with empty name to DataContainer.");
return DataHandle(0);
}
tgtAssert(data != 0, "The Data must not be 0.");
tgtAssert(!name.empty(), "The data's name must not be empty.");
DataHandle dh(data);
addDataHandle(name, dh);
return dh;
}
void DataContainer::addDataHandle(const std::string& name, const DataHandle& dh) {
if (name.empty()) {
LERROR("Tried to add data with empty name to DataContainer.");
return;
}
tgtAssert(dh.getData() != 0, "The data in the DataHandle must not be 0!");
tgtAssert(!name.empty(), "The data's name must not be empty.");
{
//tbb::spin_mutex::scoped_lock lock(_localMutex);
tbb::concurrent_unordered_map<std::string, DataHandle>::iterator it = _handles.find(name);
......
......@@ -106,6 +106,9 @@ namespace campvis {
}
void FaceGeometry::render(GLenum mode) const {
if (_vertices.empty())
return;
createGLBuffers();
if (_buffersDirty) {
LERROR("Cannot render without initialized OpenGL buffers.");
......
......@@ -186,7 +186,7 @@ namespace campvis {
}
_texture->uploadTexture();
_texture->setWrapping(tgt::Texture::CLAMP);
_texture->setWrapping(tgt::Texture::CLAMP_TO_EDGE);
if (isInteger && isSigned) {
// restore default
......
......@@ -118,6 +118,9 @@ namespace campvis {
void IndexedMeshGeometry::render(GLenum mode) const {
if (_indices.empty())
return;
createGLBuffers();
if (_buffersDirty) {
LERROR("Cannot render without initialized OpenGL buffers.");
......
......@@ -78,6 +78,9 @@ namespace campvis {
void MeshGeometry::render(GLenum mode) const {
if (_faces.empty())
return;
createGLBuffers();
if (_buffersDirty) {
LERROR("Cannot render without initialized OpenGL buffers.");
......
......@@ -134,6 +134,9 @@ namespace campvis {
}
void MultiIndexedGeometry::render(GLenum mode) const {
if (_counts.empty())
return;
createGLBuffers();
if (_buffersDirty) {
LERROR("Cannot render without initialized OpenGL buffers.");
......
......@@ -27,31 +27,55 @@
/**
* Compute the gradient using forward differences on the texture's red channel.
* \param tex 3D texture to calculate gradients for
* \param texParams Texture parameters struct (needs texParams._voxelSize)
* \param texCoords Lookup position in texture coordinates
* \param lod Explicit LOD in texture to look up
*/
vec3 computeGradientForwardDifferences(in sampler3D tex, in TextureParameters3D texParams, in vec3 texCoords) {
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;
vec3 computeGradientForwardDifferencesLod(in sampler3D tex, in TextureParameters3D texParams, in vec3 texCoords, in float lod) {
float v = textureLod(tex, texCoords, lod).r;
float dx = textureLodOffset(tex, texCoords, lod, ivec3(1, 0, 0)).r;
float dy = textureLodOffset(tex, texCoords, lod, ivec3(0, 1, 0)).r;
float dz = textureLodOffset(tex, texCoords, lod, ivec3(0, 0, 1)).r;
return vec3(v - dx, v - dy, v - dz) * texParams._voxelSize;
}
/**
* Compute the gradient using forward differences on the texture's red channel.
* \param tex 3D texture to calculate gradients for
* \param texParams Texture parameters struct (needs texParams._voxelSize)
* \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);
}
/**
* Compute the gradient using central differences on the texture's red channel.
* \param tex 3D texture to calculate gradients for
* \param texParams Texture parameters struct (needs texParams._voxelSize)
* \param texCoords Lookup position in texture coordinates
* \param lod Explicit LOD in texture to look up
*/
vec3 computeGradientCentralDifferences(in sampler3D tex, in TextureParameters3D texParams, in vec3 texCoords) {
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;
vec3 computeGradientCentralDifferencesLod(in sampler3D tex, in TextureParameters3D texParams, in vec3 texCoords, in float lod) {
float dx = textureLodOffset(tex, texCoords, lod, ivec3(1, 0, 0)).r;
float dy = textureLodOffset(tex, texCoords, lod, ivec3(0, 1, 0)).r;
float dz = textureLodOffset(tex, texCoords, lod, ivec3(0, 0, 1)).r;
float mdx = textureLodOffset(tex, texCoords, lod, ivec3(-1, 0, 0)).r;
float mdy = textureLodOffset(tex, texCoords, lod, ivec3(0, -1, 0)).r;
float mdz = textureLodOffset(tex, texCoords, lod, ivec3(0, 0, -1)).r;
return vec3(mdx - dx, mdy - dy, mdz - dz) * texParams._voxelSize * 0.5;
}
/**
* Compute the gradient using central differences on the texture's red channel.
* \param tex 3D texture to calculate gradients for
* \param texParams Texture parameters struct (needs texParams._voxelSize)
* \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);
}
/**
* Compute the gradient using filtered central differences on the texture's red channel.
......@@ -178,3 +202,100 @@ vec3 computeGradientSobel(in sampler3D tex, in vec3 texCoords) {
return -sobelScale * sobel;
}
/**
* Compute the Hessian matrix of the input image using central differences twice.
* \param tex 3D gradient texture to calculate Hessian for
* \param texCoords Lookup position in texture coordinates
*/
mat3 computeHessianCentralDifferencesLod(in sampler3D tex, in TextureParameters3D texParams, in vec3 texCoords, in float lod) {
vec3 offset = texParams._sizeRCP * pow(2.0, lod);
// compute first derivatives using central differences
vec3 dx = computeGradientCentralDifferencesLod(tex, texParams, texCoords + vec3(offset.x, 0.0, 0.0), lod);
vec3 dy = computeGradientCentralDifferencesLod(tex, texParams, texCoords + vec3(0.0, offset.y, 0.0), lod);
vec3 dz = computeGradientCentralDifferencesLod(tex, texParams, texCoords + vec3(0.0, 0.0, offset.z), lod);
vec3 mdx = computeGradientCentralDifferencesLod(tex, texParams, texCoords - vec3(offset.x, 0.0, 0.0), lod);
vec3 mdy = computeGradientCentralDifferencesLod(tex, texParams, texCoords - vec3(0.0, offset.y, 0.0), lod);
vec3 mdz = computeGradientCentralDifferencesLod(tex, texParams, texCoords - vec3(0.0, 0.0, offset.z), lod);
// compute hessian matrix columns (second order derivatives) using central differences of gradients
vec3 vdx = (dx - mdx) * texParams._voxelSize * 0.5;
vec3 vdy = (dy - mdy) * texParams._voxelSize * 0.5;
vec3 vdz = (dz - mdz) * texParams._voxelSize * 0.5;
return mat3(vdx, vdy, vdz);
}
/**
* Compute the Hessian matrix using central differences on the gradient texture's RGB channel.
* \param tex 3D gradient texture to calculate Hessian for
* \param texCoords Lookup position in texture coordinates
*/
mat3 computeGradientHessianCentralDifferencesLod(in sampler3D tex, in TextureParameters3D texParams, in vec3 texCoords, in float lod) {
vec3 offset = texParams._sizeRCP * pow(2.0, lod);
vec3 dx = textureLod(tex, texCoords + vec3(offset.x, 0.0, 0.0), lod).rgb;
vec3 dy = textureLod(tex, texCoords + vec3(0.0, offset.y, 0.0), lod).rgb;
vec3 dz = textureLod(tex, texCoords + vec3(0.0, 0.0, offset.z), lod).rgb;
vec3 mdx = textureLod(tex, texCoords - vec3(offset.x, 0.0, 0.0), lod).rgb;
vec3 mdy = textureLod(tex, texCoords - vec3(0.0, offset.y, 0.0), lod).rgb;
vec3 mdz = textureLod(tex, texCoords - vec3(0.0, 0.0, offset.z), lod).rgb;
float dxx = dx.x - mdx.x;
float dxy = dx.y - mdx.y;
float dxz = dx.z - mdx.z;
float dyx = dy.x - mdy.x;
float dyy = dy.y - mdy.y;
float dyz = dy.z - mdy.z;
float dzx = dz.x - mdz.x;
float dzy = dz.y - mdz.y;
float dzz = dz.z - mdz.z;
mat3 hessian = mat3(dxx, (dyx + dxy) / 2.0, (dzx + dxz) / 2.0,
(dxy + dyx) / 2.0, dyy, (dzy + dyz) / 2.0,
(dxz + dzx) / 2.0, (dyz + dzy) / 2.0, dzz);
//hessian *= (texParams._voxelSize * 0.5;
return hessian;
}
/**
* Compute the Hessian matrix using central differences on the gradient texture's RGB channel.
* \param tex 3D gradient texture to calculate Hessian for
* \param texCoords Lookup position in texture coordinates
*/
mat3 computeHessianCentralDifferences(in sampler3D tex, in TextureParameters3D texParams, in vec3 texCoords) {
return computeHessianCentralDifferencesLod(tex, texParams, texCoords, 0.0);
}
// code inspiured by http://en.wikipedia.org/wiki/Eigenvalue_algorithm#3.C3.973_matrices
vec3 computeEigenvalues(in mat3 hessian) {
const float PI = 3.1415926535897932384626433832795;
vec3 toReturn;
float p1 = (hessian[1][0] * hessian[1][0]) + (hessian[2][0] * hessian[2][0]) + (hessian[2][1] * hessian[2][1]);
if (p1 == 0.0) {
toReturn.x = hessian[0][0];
toReturn.y = hessian[1][1];
toReturn.z = hessian[2][2];
}
else {
float q = (hessian[0][0] + hessian[1][1] + hessian[2][2]) / 3.0;
float p2 = (hessian[0][0] - q) * (hessian[0][0] - q) + (hessian[1][1] - q) * (hessian[1][1] - q) + (hessian[2][2] - q) * (hessian[2][2] - q) + 2.0 * p1;
float p = sqrt(p2 / 6.0);
mat3 B = (1.0 - p) * (hessian - mat3(q));
float r = determinant(B) / 2.0;
float phi = acos(clamp(r, -1.0, 1.0)) / 3.0;
toReturn.x = q + (2.0 * p * cos(phi));
toReturn.z = q + (2.0 * p * cos(phi + (2.0 * PI / 3.0)));
toReturn.y = 3.0 * q - toReturn.x - toReturn.z;
}
return toReturn;
}
\ No newline at end of file
......@@ -22,6 +22,8 @@
//
// ================================================================================================
const float positiveInfinity = 1.0 / 0.0;
/**
* Code adapted from: https://www.marcusbannerman.co.uk/index.php/component/content/article/42-articles/97-vol-render-optimizations.htm
*/
......@@ -30,6 +32,34 @@ void jitterEntryPoint(inout vec3 position, in vec3 direction, in float stepSize)
position = position + direction * (stepSize * random);
}
/**
* Computes the intersection of the given ray with the given axis-aligned box.
* \param rayOrigin Origin of ray
* \param rayDirection Direction of ray
* \param boxLlf Lower-Left-front corner of box
* \param boxUrb Upper-right-back corner of box
* \param t Starting point for ray-box intersection (as fraction origin/(origin+direction)),
* set to 0 to start at origin
*/
float rayBoxIntersection(in vec3 rayOrigin, in vec3 rayDirection, in vec3 boxLlf, in vec3 boxUrb, in float t) {
vec3 tMin = (boxLlf - rayOrigin) / rayDirection;
vec3 tMax = (boxUrb - rayOrigin) / rayDirection;
// TODO: these many ifs are expensive - the lessThan bvec solution below should be faster but does not work for some reason...
if (tMin.x < t) tMin.x = positiveInfinity;
if (tMin.y < t) tMin.y = positiveInfinity;
if (tMin.z < t) tMin.z = positiveInfinity;
if (tMax.x < t) tMax.x = positiveInfinity;
if (tMax.y < t) tMax.y = positiveInfinity;
if (tMax.z < t) tMax.z = positiveInfinity;
//tMin += vec3(lessThan(tMin, vec3(t, t, t))) * positiveInfinity;
//tMax += vec3(lessThan(tMax, vec3(t, t, t))) * positiveInfinity;
return min(min(tMin.x, min(tMin.y, tMin.z)) , min(tMax.x, min(tMax.y, tMax.z)));
}
/**
* Converts a depth value in eye space to the corresponding depth value in viewport space.
* \param depth Depth value in eye space.
......
......@@ -48,29 +48,16 @@ float computeAttenuation(in vec3 attenuation, in float d) {
return min(att, 1.0);
}
/**
* Computes the ambient term according to the given material color \a ka and ambient intensity \a ia.
*
* \param ka Material ambient color
* \param ia Ambient light intensity
*/
vec3 getAmbientTerm(in vec3 ka, in vec3 ia) {
return ka * ia;
}
/**
* Computes the diffuse term according to the given parameters.
*
* \param kd Material diffuse color
* \param id Diffuse light intensity
* \param N Surface normal
* \param L Normalized light vector
*/
vec3 getDiffuseTerm(in vec3 kd, in vec3 id, in vec3 N, in vec3 L) {
vec3 getDiffuseTerm(in vec3 id, in vec3 N, in vec3 L) {
float NdotL = max(dot(N, L), 0.0);
return kd * id * NdotL;
return id * NdotL;
}
......@@ -84,10 +71,10 @@ vec3 getDiffuseTerm(in vec3 kd, in vec3 id, in vec3 N, in vec3 L) {
* \param V View vector
* \param shininess Shininess coefficient
*/
vec3 getSpecularTerm(in vec3 ks, in vec3 is, in vec3 N, in vec3 L, in vec3 V, in float shininess) {
vec3 getSpecularTerm(in vec3 is, in vec3 N, in vec3 L, in vec3 V, in float shininess) {
vec3 H = normalize(V + L);
float NdotH = pow(max(dot(N, H), 0.0), shininess);
return ks * is * NdotH;
return is * NdotH;
}
/**
......@@ -110,9 +97,9 @@ vec3 calculatePhongShading(in vec3 position, in LightSource light, in vec3 camer
float d = length(L);
L /= d;
vec3 toReturn = getAmbientTerm(ka, light._ambientColor);
toReturn += getDiffuseTerm(kd, light._diffuseColor, N, L);
toReturn += getSpecularTerm(ks, light._specularColor, N, L, V, light._shininess);
vec3 toReturn = ka * light._ambientColor; // ambient term
toReturn += kd * getDiffuseTerm(light._diffuseColor, N, L);
toReturn += ks * getSpecularTerm(light._specularColor, N, L, V, light._shininess);
#ifdef PHONG_APPLY_ATTENUATION
toReturn *= computeAttenuation(light._attenuation, d);
#endif
......@@ -137,11 +124,38 @@ vec3 calculatePhongShading(in vec3 position, in LightSource light, in vec3 camer
float d = length(L);
L /= d;
vec3 toReturn = getAmbientTerm(materialColor, light._ambientColor);
toReturn += getDiffuseTerm(materialColor, light._diffuseColor, N, L);
toReturn += getSpecularTerm(materialColor, light._specularColor, N, L, V, light._shininess);
vec3 toReturn = materialColor * light._ambientColor; // ambient term
toReturn += materialColor * getDiffuseTerm(light._diffuseColor, N, L);
toReturn += materialColor * getSpecularTerm(light._specularColor, N, L, V, light._shininess);
#ifdef PHONG_APPLY_ATTENUATION
toReturn *= computeAttenuation(light._attenuation, d);
#endif
return toReturn;
}
/**
* Computes the phong shading intensity according to the given parameters.
*
* \param position sample position
* \param light LightSource
* \param camera Camera position
* \param normal Normal
*/
float getPhongShadingIntensity(in vec3 position, in LightSource light, in vec3 camera, in vec3 normal) {
vec3 N = normalize(normal);
vec3 V = normalize(camera - position);
// get light source distance for attenuation and normalize light vector
vec3 L = light._position - position;
float d = length(L);
L /= d;
vec3 toReturn = light._ambientColor; // ambient term
toReturn += getDiffuseTerm(light._diffuseColor, N, L);
toReturn += getSpecularTerm(light._specularColor, N, L, V, light._shininess);
#ifdef PHONG_APPLY_ATTENUATION
toReturn *= computeAttenuation(light._attenuation, d);
#endif
return (toReturn.x + toReturn.y + toReturn.z) / 3.0;
}
\ No newline at end of file
......@@ -37,26 +37,32 @@ namespace campvis {
ProcessorDecoratorGradient::ProcessorDecoratorGradient()
: AbstractProcessorDecorator()
, _gradientMethod("GradientMethod", "Gradient Computation Method", gradientOptions, 4, AbstractProcessor::INVALID_SHADER | AbstractProcessor::INVALID_RESULT)
, p_gradientMethod("GradientMethod", "Gradient Computation Method", gradientOptions, 4, AbstractProcessor::INVALID_SHADER | AbstractProcessor::INVALID_RESULT)
, p_lod("GradientLod", "LOD for Gradient Computation", 0.5f, 0.f, 5.f, .1f, 1)
{
_gradientMethod.setValue(1);
p_gradientMethod.setValue(1);
p_gradientMethod.s_changed.connect(this, &ProcessorDecoratorGradient::onGradientMethodChanged);
}
ProcessorDecoratorGradient::~ProcessorDecoratorGradient() {
p_gradientMethod.s_changed.disconnect(this);
}
void ProcessorDecoratorGradient::addProperties(HasPropertyCollection* propCollection) {
propCollection->addProperty(&_gradientMethod);
propCollection->addProperty(&p_gradientMethod);
propCollection->addProperty(&p_lod);
}
std::string ProcessorDecoratorGradient::generateHeader() const {
std::string toReturn;
switch (_gradientMethod.getOptionValue()) {
switch (p_gradientMethod.getOptionValue()) {
case ForwardDifferences:
toReturn.append("#define computeGradient(tex, texParams, texCoords) computeGradientForwardDifferences(tex, texParams, texCoords)\n");
toReturn.append("#define computeGradient(tex, texParams, texCoords) computeGradientForwardDifferencesLod(tex, texParams, texCoords, _gradientLod)\n");
toReturn.append("uniform float _gradientLod = 0.0;\n");
break;
case CentralDifferences:
toReturn.append("#define computeGradient(tex, texParams, texCoords) computeGradientCentralDifferences(tex, texParams, texCoords)\n");
toReturn.append("#define computeGradient(tex, texParams, texCoords) computeGradientCentralDifferencesLod(tex, texParams, texCoords, _gradientLod)\n");
toReturn.append("uniform float _gradientLod = 0.0;\n");
break;
case FilteredCentralDifferences:
toReturn.append("#define computeGradient(tex, texParams, texCoords) computeGradientFilteredCentralDifferences(tex, texParams, texCoords)\n");
......@@ -72,4 +78,14 @@ namespace campvis {
return toReturn;
}
void ProcessorDecoratorGradient::renderProlog(const DataContainer& dataContainer, tgt::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);
}
}
......@@ -25,7 +25,9 @@
#ifndef PROCESSORDECORATORGRADIENT_H__
#define PROCESSORDECORATORGRADIENT_H__
#include "sigslot/sigslot.h"
#include "tgt/textureunit.h"
#include "core/pipeline/abstractprocessordecorator.h"
#include "core/properties/floatingpointproperty.h"
#include "core/properties/genericproperty.h"
......@@ -39,7 +41,7 @@ namespace campvis {
* generateHeader() to define computeGradient(tex, texParams, texCoords) in GLSL calling
* the selected function.
*/
class CAMPVIS_CORE_API ProcessorDecoratorGradient : public AbstractProcessorDecorator {
class CAMPVIS_CORE_API ProcessorDecoratorGradient : public AbstractProcessorDecorator, public sigslot::has_slots<> {
public:
/// Method for online-calculating gradients
enum GradientMethod {
......@@ -57,10 +59,17 @@ namespace campvis {
protected:
/// \see AbstractProcessorDecorator::addProperties()
void addProperties(HasPropertyCollection* propCollection);
/// \see AbstractProcessorDecorator::renderProlog()
virtual void renderProlog(const DataContainer& dataContainer, tgt::Shader* shader);
/// \see AbstractProcessorDecorator::generateHeader()
std::string generateHeader() const;
GenericOptionProperty<GradientMethod> _gradientMethod; ///< Method for calculating the gradients
/// 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
};
}
......
......@@ -30,6 +30,7 @@
#include "core/datastructures/imagedata.h"
#include "core/datastructures/renderdata.h"
#include "core/tools/glreduction.h"
#include "core/classification/simpletransferfunction.h"
......@@ -70,11 +71,18 @@ namespace campvis {
_shader = ShdrMgr.loadWithCustomGlslVersion("core/glsl/passthrough.vert", "", _fragmentShaderFilename, generateHeader(), _customGlslVersion);
_shader->setAttributeLocation(0, "in_Position");
_shader->setAttributeLocation(1, "in_TexCoord");
_minReduction = new GlReduction(GlReduction::MIN);
_maxReduction = new GlReduction(GlReduction::MAX);
}
void RaycastingProcessor::deinit() {
ShdrMgr.dispose(_shader);
_shader = 0;
delete _minReduction;
delete _maxReduction;
VisualizationProcessor::deinit();
}
......@@ -85,15 +93,45 @@ namespace campvis {
if (img != 0 && entryPoints != 0 && exitPoints != 0) {
if (img->getDimensionality() == 3) {
// little hack to support LOD texture lookup for the gradients:
// if texture does not yet have mipmaps, create them.
const tgt::Texture* tex = img->getTexture();
if (tex->getFilter() != tgt::Texture::MIPMAP) {
const_cast<tgt::Texture*>(tex)->setFilter(tgt::Texture::MIPMAP);
glGenerateMipmap(GL_TEXTURE_3D);