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

Merge branch 'registration' of /mnt/bigone/git/repositories/berge/campvis into development

parents c9cbf53e 23a878ea
......@@ -315,7 +315,7 @@ namespace campvis {
size_t index = 0;
size_t remainder = 0;
while (numBytes > 1024 && index < 5) {
while (numBytes > 1024 && index < 4) {
remainder = numBytes % 1024;
numBytes /= 1024;
++index;
......
......@@ -257,6 +257,7 @@ namespace campvis {
// deactivate Shader and FBO
_shader->deactivate();
_fbo->detachTexture(GL_COLOR_ATTACHMENT0);
_fbo->detachAll();
_fbo->deactivate();
LGL_ERROR;
......
......@@ -59,8 +59,8 @@ namespace campvis {
}
void ImageMappingInformation::updateMatrices() {
_textureToWolrdTransformation = tgt::mat4::createTranslation(_offset) * tgt::mat4::createScale(_voxelSize * _size);
if (! _textureToWolrdTransformation.invert(_worldToTextureTransformation))
_textureToWorldTransformation = tgt::mat4::createTranslation(_offset) * tgt::mat4::createScale(_voxelSize * _size);
if (! _textureToWorldTransformation.invert(_worldToTextureTransformation))
tgtAssert(false, "Could not invert texture-to-world matrix. That should not happen!");
_voxelToWorldTransformation = tgt::mat4::createTranslation(_offset) * tgt::mat4::createScale(_voxelSize);
......@@ -69,7 +69,7 @@ namespace campvis {
}
const tgt::mat4& ImageMappingInformation::getTextureToWorldMatrix() const {
return _textureToWolrdTransformation;
return _textureToWorldTransformation;
}
const tgt::mat4& ImageMappingInformation::getWorldToTextureMatrix() const {
......
......@@ -71,7 +71,7 @@ namespace campvis {
/**
* Gets the transformation matrix from texture to world coordinates.
* \return _textureToWolrdTransformation
* \return _textureToWorldTransformation
*/
const tgt::mat4& getTextureToWorldMatrix() const;
......@@ -117,7 +117,7 @@ namespace campvis {
LinearMapping<float> _realWorldValueMapping; ///< Linear mapping for mapping element values to real world values
tgt::mat4 _textureToWolrdTransformation; ///< Transformation matrix from texture to world coordinates
tgt::mat4 _textureToWorldTransformation; ///< Transformation matrix from texture to world coordinates
tgt::mat4 _worldToTextureTransformation; ///< Transformation matrix from world to texture coordinates
tgt::mat4 _voxelToWorldTransformation; ///< Transformation matrix from voxel to world coordinates
......
......@@ -62,6 +62,8 @@ namespace campvis {
, _texture(texture)
{
tgtAssert(texture != 0, "Given texture must not be 0.");
tgtAssert(parent->getDimensionality() >= 3 || texture->getDimensions().z == 1, "Dimensionality of Parent and texture mismatch!");
tgtAssert(parent->getDimensionality() >= 2 || texture->getDimensions().y == 1, "Dimensionality of Parent and texture mismatch!");
}
ImageRepresentationGL::ImageRepresentationGL(ImageData* parent, const WeaklyTypedPointer& wtp)
......@@ -249,6 +251,7 @@ namespace campvis {
shader->setUniform(texParamsUniform + "._voxelSize", _parent->getMappingInformation().getVoxelSize());
shader->setUniform(texParamsUniform + "._voxelSizeRCP", tgt::vec3(1.f) / _parent->getMappingInformation().getVoxelSize());
shader->setUniform(texParamsUniform + "._textureToWorldMatrix", _parent->getMappingInformation().getTextureToWorldMatrix());
shader->setUniform(texParamsUniform + "._worldToTextureMatrix", _parent->getMappingInformation().getWorldToTextureMatrix());
shader->setUniform(texParamsUniform + "._realWorldMapping", tgt::vec2(_parent->getMappingInformation().getRealWorldMapping()._shift, _parent->getMappingInformation().getRealWorldMapping()._scale));
break;
......@@ -292,5 +295,9 @@ namespace campvis {
return WeaklyTypedPointer(WeaklyTypedPointer::baseType(_texture->getDataType()), _texture->getNumChannels(), _texture->getPixelData());
}
void ImageRepresentationGL::unbind() const {
_texture->unbind();
}
}
\ No newline at end of file
......@@ -118,6 +118,12 @@ namespace campvis {
const std::string& texUniform = "_texture",
const std::string& texParamsUniform = "_textureParams") const;
/**
* Unbinds the currently bound image from the current texture unit.
* \note This is not necessarily this texture but the texture of the same type bound to this texture unit!
*/
void unbind() const;
/**
* Download the OpenGL texture from the GPU memory to the texture cpu buffer.
* \return _texture
......
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universität München
// Boltzmannstr. 3, 85748 Garching b. München, Germany
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// The licensing of this softare is not yet resolved. Until then, redistribution in source or
// binary forms outside the CAMP chair is not permitted, unless explicitly stated in legal form.
// However, the names of the original authors and the above copyright notice must retain in its
// original state in any case.
//
// Legal disclaimer provided by the BSD license:
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// ================================================================================================
in vec3 ex_TexCoord;
out vec4 out_Color;
#include "tools/texture2d.frag"
uniform sampler2D _texture;
uniform TextureParameters2D _textureParams;
uniform vec2 _texCoordsMultiplier;
void main() {
vec2 tmp = ex_TexCoord.xy * _texCoordsMultiplier * 2.0;
ivec2 texel = ivec2((tmp * _textureParams._size));
vec4 a = texelFetch(_texture, texel, 0);
vec4 b = texelFetch(_texture, texel + ivec2(1, 0), 0);
vec4 c = texelFetch(_texture, texel + ivec2(0, 1), 0);
vec4 d = texelFetch(_texture, texel + ivec2(1, 1), 0);
out_Color = REDUCTION_OP(a, b, c, d);
}
......@@ -73,6 +73,17 @@ vec4 getElement3DNormalized(in sampler3D tex, in TextureParameters3D texParams,
return texture(tex, texCoords);
}
/**
* Transforms texture coordinates for texture \a tex to world coordinates using the texture's
* texture-to-world matrix.
* \param texParams TextureParameters3D struct with texture for lookup
* \param texCoords texture coordinates
* \return \a texCoords transformes to woorld coordinates.
*/
vec4 textureToWorld(in TextureParameters3D texParams, in vec4 texCoords) {
return texParams._textureToWorldMatrix * texCoords;
}
/**
* Transforms texture coordinates for texture \a tex to world coordinates using the texture's
* texture-to-world matrix.
......@@ -81,7 +92,18 @@ vec4 getElement3DNormalized(in sampler3D tex, in TextureParameters3D texParams,
* \return \a texCoords transformes to woorld coordinates.
*/
vec4 textureToWorld(in TextureParameters3D texParams, in vec3 texCoords) {
return texParams._textureToWorldMatrix * vec4(texCoords, 1.0);
return textureToWorld(texParams, vec4(texCoords, 1.0));
}
/**
* Transforms world coordinates for texture \a tex to texture coordinates using the texture's
* world-to-texture matrix.
* \param texParams TextureParameters3D struct with texture for lookup
* \param worldCoords world coordinates
* \return \a texCoords transformes to texture coordinates.
*/
vec4 worldToTexture(in TextureParameters3D texParams, in vec4 worldCoords) {
return texParams._worldToTextureMatrix * worldCoords;
}
/**
......@@ -92,7 +114,7 @@ vec4 textureToWorld(in TextureParameters3D texParams, in vec3 texCoords) {
* \return \a texCoords transformes to texture coordinates.
*/
vec4 worldToTexture(in TextureParameters3D texParams, in vec3 worldCoords) {
return texParams._worldToTextureMatrix * vec4(worldCoords, 1.0);
return worldToTexture(texParams, vec4(worldCoords, 1.0));
}
float applyRealWorldMapping(in TextureParameters3D tex, in float value) {
......
......@@ -44,9 +44,6 @@ namespace campvis {
, _fbo(0)
, _viewportSizeProperty(viewportSizeProp)
{
tgtAssert(_viewportSizeProperty != 0, "Pointer must not be 0!");
addProperty(&p_lqMode);
}
VisualizationProcessor::~VisualizationProcessor() {
......@@ -55,13 +52,15 @@ namespace campvis {
void VisualizationProcessor::init() {
AbstractProcessor::init();
tgtAssert(_viewportSizeProperty != 0, "The pointer to the viewport size property must not be 0!");
addProperty(&p_lqMode);
_fbo = new tgt::FramebufferObject();
_viewportSizeProperty->s_changed.connect<VisualizationProcessor>(this, &VisualizationProcessor::onPropertyChanged);
}
void VisualizationProcessor::deinit() {
_viewportSizeProperty->s_changed.disconnect(this);
_fbo->detachAll();
delete _fbo;
AbstractProcessor::deinit();
}
......
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universität München
// Boltzmannstr. 3, 85748 Garching b. München, Germany
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// The licensing of this softare is not yet resolved. Until then, redistribution in source or
// binary forms outside the CAMP chair is not permitted, unless explicitly stated in legal form.
// However, the names of the original authors and the above copyright notice must retain in its
// original state in any case.
//
// Legal disclaimer provided by the BSD license:
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// ================================================================================================
#include "glreduction.h"
#include "tgt/logmanager.h"
#include "tgt/framebufferobject.h"
#include "tgt/shadermanager.h"
#include "tgt/texture.h"
#include "tgt/textureunit.h"
#include "core/datastructures/facegeometry.h"
#include "core/datastructures/imagedata.h"
#include "core/datastructures/imagerepresentationgl.h"
#include "core/tools/quadrenderer.h"
#include <algorithm>
#define DIV_CEIL(x,y) ((x) > 0) ? (1 + ((x) - 1)/(y)) : ((x) / (y))
namespace campvis {
const std::string GlReduction::loggerCat_ = "CAMPVis.modules.registration.GlReduction";
GlReduction::GlReduction(ReductionOperator reductionOperator)
: _reductionOperator(reductionOperator)
, _shader(0)
, _fbo(0)
{
_shader = ShdrMgr.loadSeparate("core/glsl/passthrough.vert", "core/glsl/tools/glreduction.frag", generateGlslHeader(_reductionOperator), false);
if (_shader == 0) {
LERROR("Could not load Shader for OpenGL reduction. Reduction will not work!");
return;
}
_shader->setAttributeLocation(0, "in_Position");
_shader->setAttributeLocation(1, "in_TexCoord");
}
GlReduction::~GlReduction() {
ShdrMgr.dispose(_shader);
}
std::vector<float> GlReduction::reduce(const ImageData* image) {
tgtAssert(image != 0, "Image must not be 0!");
if (_shader == 0) {
LERROR("Could not load Shader for OpenGL reduction. Reduction will not work!");
return std::vector<float>();
}
if (image == 0) {
LERROR("Empty image received - nothing to reduce!");
return std::vector<float>();
}
const ImageRepresentationGL* repGl = image->getRepresentation<ImageRepresentationGL>();
if (repGl == 0) {
LERROR("Could not convert input image to OpenGL texture - no reduction possible!");
return std::vector<float>();
}
return reduce(repGl->getTexture());
}
std::vector<float> GlReduction::reduce(const tgt::Texture* texture) {
std::vector<float> toReturn;
tgtAssert(texture != 0, "Image must not be 0!");
if (_shader == 0) {
LERROR("Could not load Shader for OpenGL reduction. Reduction will not work!");
return toReturn;
}
if (texture == 0) {
LERROR("Empty texture received - nothing to reduce!");
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...");
std::vector<float> readBackBuffer;
const tgt::ivec3& size = texture->getDimensions();
tgt::vec2 texCoordMultiplier(1.f);
tgt::ivec2 currentSize = size.xy();
reduceSizes(currentSize, texCoordMultiplier);
// Set OpenGL pixel alignment to 1 to avoid problems with NPOT textures
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// get a free texture unit
tgt::TextureUnit inputUnit;
// create temporary textures
tgt::Texture* tempTextures[2];
for (size_t i = 0; i < 2; ++i) {
tempTextures[i] = new tgt::Texture(0, tgt::ivec3(currentSize, 1), GL_RGBA, GL_RGBA32F, GL_FLOAT, tgt::Texture::NEAREST);
tempTextures[i]->uploadTexture();
tempTextures[i]->setWrapping(tgt::Texture::CLAMP);
}
size_t readTex = 0;
size_t writeTex = 1;
// create and initialize FBO
_fbo = new tgt::FramebufferObject();
_fbo->activate();
LGL_ERROR;
// perform first reduction step outside:
_shader->activate();
_fbo->attachTexture(tempTextures[readTex]);
_shader->setIgnoreUniformLocationError(true);
inputUnit.activate();
texture->bind();
_shader->setUniform("_texture", inputUnit.getUnitNumber());
_shader->setUniform("_textureParams._size", tgt::vec2(size.xy()));
_shader->setUniform("_textureParams._sizeRCP", tgt::vec2(1.f) / tgt::vec2(size.xy()));
_shader->setUniform("_textureParams._numChannels", static_cast<int>(texture->getNumChannels()));
_shader->setIgnoreUniformLocationError(false);
glViewport(0, 0, currentSize.x, currentSize.y);
_shader->setUniform("_texCoordsMultiplier", texCoordMultiplier);
QuadRdr.renderQuad();
LGL_ERROR;
// perform reduction until 1x1 texture remains
while (currentSize.x > 1 || currentSize.y > 1) {
reduceSizes(currentSize, texCoordMultiplier);
_fbo->attachTexture(tempTextures[writeTex]);
tempTextures[readTex]->bind();
glViewport(0, 0, currentSize.x, currentSize.y);
_shader->setUniform("_texCoordsMultiplier", texCoordMultiplier);
QuadRdr.renderQuad();
LGL_ERROR;
//_fbo->detachTexture(GL_COLOR_ATTACHMENT0);
std::swap(writeTex, readTex);
}
_shader->deactivate();
// read back stuff
GLenum readBackFormat = tempTextures[readTex]->getFormat();
size_t channels = tempTextures[readTex]->getNumChannels();
toReturn.resize(currentSize.x * currentSize.y * channels);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glReadPixels(0, 0, currentSize.x, currentSize.y, readBackFormat, GL_FLOAT, &toReturn.front());
LGL_ERROR;
// clean up...
_fbo->detachAll();
_fbo->deactivate();
delete _fbo;
_fbo = 0;
delete tempTextures[0];
delete tempTextures[1];
LGL_ERROR;
return toReturn;
}
void GlReduction::reduceSizes(tgt::ivec2& currentSize, tgt::vec2& texCoordMultiplier) {
if (currentSize.x > 1) {
currentSize.x = DIV_CEIL(currentSize.x, 2);
texCoordMultiplier.x /= 2.f;
}
if (currentSize.y > 1) {
currentSize.y = DIV_CEIL(currentSize.y, 2);
texCoordMultiplier.y /= 2.f;
}
}
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;
default:
tgtAssert(false, "Should not reach this, wrong enum value?");
return "";
break;
}
}
}
\ No newline at end of file
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universität München
// Boltzmannstr. 3, 85748 Garching b. München, Germany
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// The licensing of this softare is not yet resolved. Until then, redistribution in source or
// binary forms outside the CAMP chair is not permitted, unless explicitly stated in legal form.
// However, the names of the original authors and the above copyright notice must retain in its
// original state in any case.
//
// Legal disclaimer provided by the BSD license:
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// ================================================================================================
#ifndef GLREDUCTION_H__
#define GLREDUCTION_H__
#include "tgt/exception.h"
#include "tgt/tgt_gl.h"
#include "tgt/vector.h"
#include <string>
#include <vector>
namespace tgt {
class FramebufferObject;
class Shader;
class Texture;
}
namespace campvis {
class ImageData;
class FaceGeometry;
/**
* Class performing a reduction of 2D image data using OpenGL.
* \note All methods need to be called from a valid OpenGL context.
*/
class GlReduction {
public:
/// Operation to be performed by reduction
enum ReductionOperator {
MIN, ///< Minimum
MAX, ///< Maximum
PLUS, ///< Sum (plus)
MULTIPLICATION ///< Product (multiplication)
};
/**
* Constructor
* \param reductionOperator Operation to be performed by reduction
*/
GlReduction(ReductionOperator reductionOperator);
/**
* Destructor
*/
~GlReduction();
/**
* Performs the reduction on the given image.
* \note Image must be two-dimensional!
* \note Reduction will be performed on a copy, \a image will not change.
* \param image Pointer to ImageData to perform reduction on, must be two-dimensional.
* \return A vector of floats containing the reduction results for each channel of the input image.
*/
std::vector<float> reduce(const ImageData* image);
/**
* Performs the reduction on the given OpenGL texture.
* \note Image must be two-dimensional!
* \note Reduction will be performed on a copy, \a texture will not change.
* \param image Pointer to a texture to perform reduction on, must be two-dimensional.
* \return A vector of floats containing the reduction results for each channel of the input texture.
*/
std::vector<float> reduce(const tgt::Texture* texture);
private:
/**
* Performs a reduction of \a currentSize in each dimension and adjusts \a texCoordMultiplier.
* \param currentSize Current size to reduce (ceiling division by 2)
* \param texCoordMultiplier Tex coordinates multiplier to adjust (divide by 2 if dimension got reduced)
*/
static void reduceSizes(tgt::ivec2& currentSize, tgt::vec2& texCoordMultiplier);
/**
* Generates the GLSL header corresponding to the given reduction operator.
* \param reductionOperator Operation to be performed by reduction
* \return A std::string with the corresponding GLSL header.
*/
static std::string generateGlslHeader(ReductionOperator reductionOperator);
ReductionOperator _reductionOperator; ///< Operation to be performed by reduction
tgt::Shader* _shader; ///< OpenGL shader performing the reduction
tgt::FramebufferObject* _fbo; ///< FBO performing the reduction
const static std::string loggerCat_;
};
}
#endif // GLREDUCTION_H__
......@@ -71,6 +71,7 @@ void FramebufferObject::attachTexture(Texture* texture, GLenum attachment, int m
glFramebufferTexture2D( GL_FRAMEBUFFER, attachment, texture->getType(), texture->getId(), mipLevel );
break;
}
LGL_ERROR;
size_t index = decodeAttachment(attachment);
attachments_[index] = texture;
......@@ -100,6 +101,7 @@ void FramebufferObject::detachTexture(GLenum attachment) {
break;
}
attachments_[index] = 0;
LGL_ERROR;
if (index < TGT_FRAMEBUFFEROBJECT_MAX_SUPPORTED_COLOR_ATTACHMENTS)
--numColorAttachments_;
......
......@@ -78,7 +78,7 @@ public:
/// A wrapper to get the camera from the Canvas
Camera* getCamera() const;
protected:
/**
* This is meant be overridden to do the according openGL paintings
* is not meant to be called directly, will be called by repaint().
......
......@@ -141,6 +141,14 @@ public:
glBindTexture(type_ , id_);
}
/**
* unbind the current texture from the active texture unit and target.
*/
void unbind() const
{
glBindTexture(type_, 0);
}
/**
* Enable texturing on the active texture unit.
*/
......
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012, all rights reserved,