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

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

Extended GlReduction to also support the reduction of 3D images.

parent bcdae20a
......@@ -32,16 +32,45 @@ out vec4 out_Color;
#include "tools/texture2d.frag"
uniform sampler2D _texture;
uniform vec2 _texCoordsShift;
#ifdef REDUCTION_2D
uniform sampler2D _texture;
uniform vec2 _texCoordsShift;
#endif
#ifdef REDUCTION_3D
uniform sampler3D _texture;
uniform vec2 _texCoordsShift;
uniform int _textureDepth;
#endif
void main() {
vec2 tmp = ex_TexCoord.xy - _texCoordsShift;
#ifdef REDUCTION_2D
// 2D reduction:
vec4 a = texture(_texture, tmp);
vec4 b = textureOffset(_texture, tmp, ivec2(1, 0));
vec4 c = textureOffset(_texture, tmp, ivec2(0, 1));
vec4 d = textureOffset(_texture, tmp, ivec2(1, 1));
#endif
#ifdef REDUCTION_3D
// 3D reduction along depth:
float textureDepthRCP = 1.0 / _textureDepth;
vec4 a = texture(_texture, vec3(tmp, textureDepthRCP/2.0));
vec4 b = textureOffset(_texture, vec3(tmp, textureDepthRCP/2.0), ivec3(1, 0, 0));
vec4 c = textureOffset(_texture, vec3(tmp, textureDepthRCP/2.0), ivec3(0, 1, 0));
vec4 d = textureOffset(_texture, vec3(tmp, textureDepthRCP/2.0), ivec3(1, 1, 0));
for (float z = 3.0 * textureDepthRCP / 2.0; z < 1.0; z += textureDepthRCP) {
a = REDUCTION_OP_2(a, texture(_texture, vec3(tmp, z)));
b = REDUCTION_OP_2(b, textureOffset(_texture, vec3(tmp, z), ivec3(1, 0, 0)));
c = REDUCTION_OP_2(c, textureOffset(_texture, vec3(tmp, z), ivec3(0, 1, 0)));
d = REDUCTION_OP_2(d, textureOffset(_texture, vec3(tmp, z), ivec3(1, 1, 0)));
}
#endif
out_Color = REDUCTION_OP(a, b, c, d);
// final reduction of the four pixels
out_Color = REDUCTION_OP_4(a, b, c, d);
}
......@@ -50,26 +50,31 @@ namespace campvis {
GlReduction::GlReduction(ReductionOperator reductionOperator)
: _reductionOperator(reductionOperator)
, _shader(0)
, _shader2d(0)
, _shader3d(0)
, _fbo(0)
{
_shader = ShdrMgr.loadSeparate("core/glsl/passthrough.vert", "core/glsl/tools/glreduction.frag", generateGlslHeader(_reductionOperator), false);
if (_shader == 0) {
_shader2d = ShdrMgr.loadSeparate("core/glsl/passthrough.vert", "core/glsl/tools/glreduction.frag", generateGlslHeader(_reductionOperator) + "#define REDUCTION_2D\n", false);
_shader3d = ShdrMgr.loadSeparate("core/glsl/passthrough.vert", "core/glsl/tools/glreduction.frag", generateGlslHeader(_reductionOperator) + "#define REDUCTION_3D\n", false);
if (_shader2d == 0 || _shader3d == 0) {
LERROR("Could not load Shader for OpenGL reduction. Reduction will not work!");
return;
}
_shader->setAttributeLocation(0, "in_Position");
_shader->setAttributeLocation(1, "in_TexCoord");
_shader2d->setAttributeLocation(0, "in_Position");
_shader2d->setAttributeLocation(1, "in_TexCoord");
_shader3d->setAttributeLocation(0, "in_Position");
_shader3d->setAttributeLocation(1, "in_TexCoord");
}
GlReduction::~GlReduction() {
ShdrMgr.dispose(_shader);
ShdrMgr.dispose(_shader2d);
ShdrMgr.dispose(_shader3d);
}
std::vector<float> GlReduction::reduce(const ImageData* image) {
tgtAssert(image != 0, "Image must not be 0!");
if (_shader == 0) {
if (_shader2d == 0 || _shader3d == 0) {
LERROR("Could not load Shader for OpenGL reduction. Reduction will not work!");
return std::vector<float>();
}
......@@ -91,7 +96,7 @@ namespace campvis {
std::vector<float> toReturn;
tgtAssert(texture != 0, "Image must not be 0!");
if (_shader == 0) {
if (_shader2d == 0 || _shader3d == 0) {
LERROR("Could not load Shader for OpenGL reduction. Reduction will not work!");
return toReturn;
}
......@@ -100,8 +105,6 @@ namespace campvis {
return toReturn;
}
tgtAssert(texture->getDimensions().z == 1, "Reduction of 3D images not yet implemented! Somebody was too lazy (or stressed - deadline was close) to do that...");
const tgt::ivec3& size = texture->getDimensions();
tgt::vec2 texCoordShift = tgt::vec2(.5f) / tgt::vec2(size.xy());
tgt::ivec2 currentSize = size.xy();
......@@ -130,17 +133,24 @@ namespace campvis {
LGL_ERROR;
// perform first reduction step outside:
_shader->activate();
tgt::Shader* leShader = (texture->getDimensions().z == 1) ? _shader2d : _shader3d;
leShader->activate();
_fbo->attachTexture(tempTextures[readTex]);
inputUnit.activate();
texture->bind();
_shader->setUniform("_texture", inputUnit.getUnitNumber());
_shader->setUniform("_texCoordsShift", texCoordShift);
leShader->setUniform("_texture", inputUnit.getUnitNumber());
leShader->setUniform("_texCoordsShift", texCoordShift);
if (leShader == _shader3d)
leShader->setUniform("_textureDepth", texture->getDimensions().z);
glViewport(startSize.x - currentSize.x, startSize.y - currentSize.y, currentSize.x, currentSize.y);
QuadRdr.renderQuad();
leShader->deactivate();
LGL_ERROR;
_shader2d->activate();
_shader2d->setUniform("_texture", inputUnit.getUnitNumber());
reduceSizes(currentSize, texCoordShift);
glViewport(startSize.x - currentSize.x, startSize.y - currentSize.y, currentSize.x, currentSize.y);
......@@ -149,7 +159,7 @@ namespace campvis {
_fbo->attachTexture(tempTextures[writeTex]);
tempTextures[readTex]->bind();
_shader->setUniform("_texCoordsShift", texCoordShift);
_shader2d->setUniform("_texCoordsShift", texCoordShift);
QuadRdr.renderQuad();
LGL_ERROR;
......@@ -157,7 +167,7 @@ namespace campvis {
std::swap(writeTex, readTex);
}
_shader->deactivate();
_shader2d->deactivate();
// read back stuff
......@@ -197,25 +207,35 @@ namespace campvis {
std::string GlReduction::generateGlslHeader(ReductionOperator reductionOperator) {
switch (reductionOperator) {
case MIN:
return "#define REDUCTION_OP(a, b, c, d) min(a, min(b, min(c, d)))";
break;
case MAX:
return "#define REDUCTION_OP(a, b, c, d) max(a, max(b, max(c, d)))";
break;
case PLUS:
return "#define REDUCTION_OP(a, b, c, d) a+b+c+d";
break;
case MULTIPLICATION:
return "#define REDUCTION_OP(a, b, c, d) a*b*c*d";
break;
case MIN_MAX:
return "#define REDUCTION_OP(a, b, c, d) vec4(min(a.r, min(b.r, min(c.r, d.r))), max(a.g, max(b.g, max(c.g, d.g))), 0.0, 0.0)";
break;
default:
tgtAssert(false, "Should not reach this, wrong enum value?");
return "";
break;
case MIN:
return
"#define REDUCTION_OP_2(a, b) min(a, b)\n"
"#define REDUCTION_OP_4(a, b, c, d) min(a, min(b, min(c, d)))\n";
break;
case MAX:
return
"#define REDUCTION_OP_2(a, b) max(a, b)\n"
"#define REDUCTION_OP_4(a, b, c, d) max(a, max(b, max(c, d)))\n";
break;
case PLUS:
return
"#define REDUCTION_OP_2(a, b) a+b\n"
"#define REDUCTION_OP_4(a, b, c, d) a+b+c+d\n";
break;
case MULTIPLICATION:
return
"#define REDUCTION_OP_2(a, b) a*b\n"
"#define REDUCTION_OP_4(a, b, c, d) a*b*c*d\n";
break;
case MIN_MAX_DEPTH_ONLY:
return
"#define REDUCTION_OP_2(a, b) vec4(min(a.r, b.r), max(a.g, b.g), 0.0, 0.0)\n"
"#define REDUCTION_OP_4(a, b, c, d) vec4(min(a.r, min(b.r, min(c.r, d.r))), max(a.g, max(b.g, max(c.g, d.g))), 0.0, 0.0)\n";
break;
default:
tgtAssert(false, "Should not reach this, wrong enum value?");
return "";
break;
}
}
......
......@@ -59,7 +59,7 @@ namespace campvis {
MAX, ///< Maximum
PLUS, ///< Sum (plus)
MULTIPLICATION, ///< Product (multiplication)
MIN_MAX ///< Minimum/Maximum (WORKS ONLY with single channel images!)
MIN_MAX_DEPTH_ONLY ///< Minimum/Maximum (CAUTION: WORKS ONLY with depth images!!!)
};
/**
......@@ -109,7 +109,8 @@ namespace campvis {
ReductionOperator _reductionOperator; ///< Operation to be performed by reduction
tgt::Shader* _shader; ///< OpenGL shader performing the reduction
tgt::Shader* _shader2d; ///< OpenGL shader performing 2D reduction
tgt::Shader* _shader3d; ///< OpenGL shader performing 3D reduction
tgt::FramebufferObject* _fbo; ///< FBO performing the reduction
const static std::string loggerCat_;
......
......@@ -306,9 +306,9 @@ namespace campvis {
referenceUnit.activate();
// create temporary texture for result
tgt::Texture* similarityTex = new tgt::Texture(0, tgt::ivec3(size), GL_RED, GL_R32F, GL_FLOAT, tgt::Texture::NEAREST);
similarityTex->uploadTexture();
similarityTex->setWrapping(tgt::Texture::CLAMP);
tgt::Texture* differenceImage = new tgt::Texture(0, tgt::ivec3(size), GL_RED, GL_R32F, GL_FLOAT, tgt::Texture::LINEAR);
differenceImage->uploadTexture();
differenceImage->setWrapping(tgt::Texture::CLAMP_TO_EDGE);
// bind input images
_differenceShader->activate();
......@@ -328,7 +328,7 @@ namespace campvis {
for (int z = 0; z < size.z; ++z) {
float texZ = static_cast<float>(z)/static_cast<float>(size.z) + .5f/static_cast<float>(size.z);
_differenceShader->setUniform("_zTex", texZ);
_fbo->attachTexture(similarityTex, GL_COLOR_ATTACHMENT0, 0, z);
_fbo->attachTexture(differenceImage, GL_COLOR_ATTACHMENT0, 0, z);
QuadRdr.renderQuad();
}
_differenceShader->deactivate();
......@@ -336,7 +336,7 @@ namespace campvis {
// put difference image into DataContainer
ImageData* id = new ImageData(3, size, 1);
ImageRepresentationGL::create(id, similarityTex);
ImageRepresentationGL::create(id, differenceImage);
id->setMappingInformation(referenceImage->getParent()->getMappingInformation());
dc->addData(p_differenceImageId.getValue(), id);
......
......@@ -75,7 +75,7 @@ namespace campvis {
_shader->setAttributeLocation(0, "in_Position");
_shader->setAttributeLocation(1, "in_TexCoord");
_glReduction = new GlReduction(GlReduction::MIN_MAX);
_glReduction = new GlReduction(GlReduction::MIN_MAX_DEPTH_ONLY);
}
void DepthDarkening::deinit() {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment