void VolumeGL::generateTexture(const VolumeRAM* volume) throw (tgt::Exception, std::bad_alloc) { if (!GpuCaps.is3DTexturingSupported()) { std::string message = "3D textures apparently not supported by the OpenGL driver"; LERROR(message); throw Exception(message); } if (!GpuCaps.isNpotSupported() && !glm::all(glm::isPowerOfTwo(getDimensions()))) { std::string message = "Non-power-of-two textures apparently not supported by the OpenGL driver"; LERROR(message); throw Exception(message); } // // Determine GL format // GLint format = 0; ///< The format of textures which will are created. GLint internalFormat = 0; ///< The internal format of the textures which are created. GLenum dataType = 0; ///< The data type of the textures which are created. float scale = 1.f; ///< rescale data from normalized interger to interger. // scalar if (dynamic_cast<const VolumeAtomic<uint8_t>*>(volume)) { format = GL_RED; internalFormat = GL_R8; dataType = GL_UNSIGNED_BYTE; scale = (float)std::numeric_limits<uint8_t>::max(); } else if (dynamic_cast<const VolumeAtomic<int8_t>*>(volume)) { format = GL_RED; internalFormat = GL_R8; dataType = GL_BYTE; scale = (float)std::numeric_limits<int8_t>::max(); } else if (dynamic_cast<const VolumeAtomic<uint16_t>*>(volume)) { format = GL_RED; internalFormat = GL_R16; dataType = GL_UNSIGNED_SHORT; scale = (float)std::numeric_limits<uint16_t>::max(); } else if (dynamic_cast<const VolumeAtomic<int16_t>*>(volume)) { format = GL_RED; internalFormat = GL_R16; dataType = GL_SHORT; scale = (float)std::numeric_limits<int16_t>::max(); } else if (dynamic_cast<const VolumeAtomic<uint32_t>*>(volume)) { format = GL_RED; internalFormat = GL_R; dataType = GL_UNSIGNED_INT; scale = (float)std::numeric_limits<uint32_t>::max(); } else if (dynamic_cast<const VolumeAtomic<int32_t>*>(volume)) { format = GL_RED; internalFormat = GL_R; dataType = GL_INT; scale = (float)std::numeric_limits<int32_t>::max(); } else if (dynamic_cast<const VolumeAtomic<uint64_t>*>(volume)) { std::string message = "VolumeRAM_UInt64 not supported as OpenGL volume."; LERROR(message); throw tgt::Exception(message); } else if (dynamic_cast<const VolumeAtomic<int64_t>*>(volume)) { std::string message = "VolumeRAM_Int64 not supported as OpenGL volume."; LERROR(message); throw tgt::Exception(message); } else if (dynamic_cast<const VolumeAtomic<float>*>(volume)) { format = GL_RED; internalFormat = GL_R32F; dataType = GL_FLOAT; scale = (float)std::numeric_limits<float>::max(); } else if (dynamic_cast<const VolumeAtomic<double>*>(volume)) { std::string message = "VolumeRAM_Double not supported as OpenGL volume."; LERROR(message); throw tgt::Exception(message); } else { LERROR("unknown or unsupported volume type"); } // // Create texture // glPixelStorei(GL_UNPACK_ALIGNMENT, 1); VolumeTexture* vTex = 0; char* tempVolumeData = 0; if (volume->getDimensions().z > 1) { // multi-slice volume => just create OGL texture from it vTex = new VolumeTexture(static_cast<const GLubyte*>(volume->getData()), volume->getDimensions(), format, internalFormat, dataType, Texture::LINEAR); } else { // single-slice volume (not allowed as OGL texture) => double slice LWARNING("OpenGL does not allow 3D textures consisting of only one slice: cloning slice"); try { tempVolumeData = new char[2 * volume->getNumBytes()]; memcpy(tempVolumeData, volume->getData(), volume->getNumBytes()); memcpy(tempVolumeData + volume->getNumBytes(), volume->getData(), volume->getNumBytes()); vTex = new VolumeTexture(reinterpret_cast<const GLubyte*>(tempVolumeData), glm::ivec3(volume->getDimensions().x, volume->getDimensions().y, volume->getDimensions().z * 2), format, internalFormat, dataType, Texture::LINEAR); } catch (std::bad_alloc&) { LERROR("bad allocation while creating OpenGL texture"); throw tgt::Exception("bad allocation while creating OpenGL texture"); } } assert(vTex); LGL_ERROR; vTex->bind(); // map signed integer types from [-MIN_INT:MAX_INT] to [0.0:1.0] in order to avoid clamping of negative values if (volume->isInteger() && volume->isSigned()) { glPushAttrib(GL_ALL_ATTRIB_BITS); glPixelTransferf(GL_RED_SCALE, 0.5f); glPixelTransferf(GL_GREEN_SCALE, 0.5f); glPixelTransferf(GL_BLUE_SCALE, 0.5f); glPixelTransferf(GL_ALPHA_SCALE, 0.5f); glPixelTransferf(GL_RED_BIAS, 0.5f); glPixelTransferf(GL_GREEN_BIAS, 0.5f); glPixelTransferf(GL_BLUE_BIAS, 0.5f); glPixelTransferf(GL_ALPHA_BIAS, 0.5f); pixelTransferMapping_ = ValueMapping(1/scale * 0.5f, 0.5f, ""); } else pixelTransferMapping_ = ValueMapping(1 / scale, 0.f, ""); if (volume->getData()) vTex->uploadTexture(); // reset pixel transfer if (volume->isInteger() && volume->isSigned()) { glPopAttrib(); } // set texture wrap to clamp vTex->setWrapping(Texture::CLAMP); LGL_ERROR; // prevent deleting twice vTex->setPixelData(0); delete[] tempVolumeData; tempVolumeData = 0; // append to internal data structure texture_ = vTex; LGL_ERROR; }
void VolumeGL::generateTexture(const Volume* volume) throw (VoreenException, std::bad_alloc) { if (!tgt::hand(tgt::greaterThan(volume->getDimensions(), svec3(1)))) { std::stringstream message; message << "OpenGL volumes must have a size greater than one in all dimensions. Actual size: " << volume->getDimensions(); LERROR(message.str()); throw VoreenException(message.str()); } if (!GpuCaps.is3DTexturingSupported()) { std::string message = "3D textures apparently not supported by the OpenGL driver"; LERROR(message); throw VoreenException(message); } if (!GpuCaps.isNpotSupported() && !isPowerOfTwo(getDimensions())) { std::string message = "Non-power-of-two textures apparently not supported by the OpenGL driver"; LERROR(message); throw VoreenException(message); } // // Determine GL format // GLint format; ///< The format of textures which will are created. GLint internalFormat; ///< The internal format of the textures which are created. GLenum dataType; ///< The data type of the textures which are created. // scalar if (dynamic_cast<const VolumeAtomic<uint8_t>*>(volume)) { format = GL_ALPHA; internalFormat = GL_ALPHA8; dataType = GL_UNSIGNED_BYTE; } else if (dynamic_cast<const VolumeAtomic<int8_t>*>(volume)) { format = GL_ALPHA; internalFormat = GL_ALPHA8; dataType = GL_BYTE; } else if (dynamic_cast<const VolumeAtomic<uint16_t>*>(volume)) { format = GL_ALPHA; internalFormat = GL_ALPHA16; dataType = GL_UNSIGNED_SHORT; } else if (dynamic_cast<const VolumeAtomic<int16_t>*>(volume)) { format = GL_ALPHA; internalFormat = GL_ALPHA16; dataType = GL_SHORT; } else if (dynamic_cast<const VolumeAtomic<uint32_t>*>(volume)) { format = GL_ALPHA; internalFormat = GL_ALPHA; dataType = GL_UNSIGNED_INT; } else if (dynamic_cast<const VolumeAtomic<int32_t>*>(volume)) { format = GL_ALPHA; internalFormat = GL_ALPHA; dataType = GL_INT; } else if (dynamic_cast<const VolumeAtomic<uint64_t>*>(volume)) { std::string message = "VolumeUInt64 not supported as OpenGL volume."; LERROR(message); throw VoreenException(message); } else if (dynamic_cast<const VolumeAtomic<int64_t>*>(volume)) { std::string message = "VolumeInt64 not supported as OpenGL volume."; LERROR(message); throw VoreenException(message); } else if (dynamic_cast<const VolumeAtomic<float>*>(volume)) { format = GL_ALPHA; internalFormat = GL_ALPHA; dataType = GL_FLOAT; } else if (dynamic_cast<const VolumeAtomic<double>*>(volume)) { std::string message = "VolumeDouble not supported as OpenGL volume."; LERROR(message); throw VoreenException(message); } // vec2 else if (dynamic_cast<const VolumeAtomic<tgt::Vector2<uint8_t> >*>(volume)) { format = GL_LUMINANCE_ALPHA; internalFormat = GL_LUMINANCE_ALPHA; dataType = GL_UNSIGNED_BYTE; } else if (dynamic_cast<const VolumeAtomic<tgt::Vector2<int8_t> >*>(volume)) { format = GL_LUMINANCE_ALPHA; internalFormat = GL_LUMINANCE_ALPHA; dataType = GL_BYTE; } else if (dynamic_cast<const VolumeAtomic<tgt::Vector2<uint16_t> >*>(volume)) { format = GL_LUMINANCE_ALPHA; internalFormat = GL_LUMINANCE_ALPHA; dataType = GL_UNSIGNED_SHORT; } else if (dynamic_cast<const VolumeAtomic<tgt::Vector2<int16_t> >*>(volume)) { format = GL_LUMINANCE_ALPHA; internalFormat = GL_LUMINANCE_ALPHA; dataType = GL_SHORT; } else if (dynamic_cast<const VolumeAtomic<tgt::Vector2<uint32_t> >*>(volume)) { format = GL_LUMINANCE_ALPHA; internalFormat = GL_LUMINANCE_ALPHA; dataType = GL_UNSIGNED_INT; } else if (dynamic_cast<const VolumeAtomic<tgt::Vector2<int32_t> >*>(volume)) { format = GL_LUMINANCE_ALPHA; internalFormat = GL_LUMINANCE_ALPHA; dataType = GL_INT; } else if (dynamic_cast<const VolumeAtomic<tgt::Vector2<uint64_t> >*>(volume)) { std::string message = "Volume2xUInt64 not supported as OpenGL volume."; LERROR(message); throw VoreenException(message); } else if (dynamic_cast<const VolumeAtomic<tgt::Vector2<int64_t> >*>(volume)) { std::string message = "Volume2xInt64 not supported as OpenGL volume."; LERROR(message); throw VoreenException(message); } else if (dynamic_cast<const VolumeAtomic<tgt::Vector2<float> >*>(volume)) { format = GL_LUMINANCE_ALPHA; internalFormat = GL_LUMINANCE_ALPHA; dataType = GL_FLOAT; } else if (dynamic_cast<const VolumeAtomic<tgt::Vector2<double> >*>(volume)) { std::string message = "Volume2xDouble not supported as OpenGL volume."; LERROR(message); throw VoreenException(message); } // vec3 else if (dynamic_cast<const VolumeAtomic<tgt::Vector3<uint8_t> >*>(volume)) { format = GL_RGB; internalFormat = GL_RGB8; dataType = GL_UNSIGNED_BYTE; } else if (dynamic_cast<const VolumeAtomic<tgt::Vector3<int8_t> >*>(volume)) { format = GL_RGB; internalFormat = GL_RGB8; dataType = GL_BYTE; } else if (dynamic_cast<const VolumeAtomic<tgt::Vector3<uint16_t> >*>(volume)) { format = GL_RGB; internalFormat = GL_RGB16; dataType = GL_UNSIGNED_SHORT; } else if (dynamic_cast<const VolumeAtomic<tgt::Vector3<int16_t> >*>(volume)) { format = GL_RGB; internalFormat = GL_RGB16; dataType = GL_SHORT; } else if (dynamic_cast<const VolumeAtomic<tgt::Vector3<uint32_t> >*>(volume)) { format = GL_RGB; internalFormat = GL_RGB; dataType = GL_UNSIGNED_INT; } else if (dynamic_cast<const VolumeAtomic<tgt::Vector3<int32_t> >*>(volume)) { format = GL_RGB; internalFormat = GL_RGB; dataType = GL_INT; } else if (dynamic_cast<const VolumeAtomic<tgt::Vector3<uint64_t> >*>(volume)) { std::string message = "Volume3xUInt64 not supported as OpenGL volume."; LERROR(message); throw VoreenException(message); } else if (dynamic_cast<const VolumeAtomic<tgt::Vector3<int64_t> >*>(volume)) { std::string message = "Volume3xInt64 not supported as OpenGL volume."; LERROR(message); throw VoreenException(message); } else if (dynamic_cast<const VolumeAtomic<tgt::Vector3<float> >*>(volume)) { format = GL_RGB; internalFormat = GL_RGB; dataType = GL_FLOAT; } else if (dynamic_cast<const VolumeAtomic<tgt::Vector3<double> >*>(volume)) { std::string message = "Volume3xDouble not supported as OpenGL volume."; LERROR(message); throw VoreenException(message); } // vec4 else if (dynamic_cast<const VolumeAtomic<tgt::Vector4<uint8_t> >*>(volume)) { format = GL_RGBA; internalFormat = GL_RGBA8; dataType = GL_UNSIGNED_BYTE; } else if (dynamic_cast<const VolumeAtomic<tgt::Vector4<int8_t> >*>(volume)) { format = GL_RGBA; internalFormat = GL_RGBA8; dataType = GL_BYTE; } else if (dynamic_cast<const VolumeAtomic<tgt::Vector4<uint16_t> >*>(volume)) { format = GL_RGBA; internalFormat = GL_RGBA16; dataType = GL_UNSIGNED_SHORT; } else if (dynamic_cast<const VolumeAtomic<tgt::Vector4<int16_t> >*>(volume)) { format = GL_RGBA; internalFormat = GL_RGBA16; dataType = GL_SHORT; } else if (dynamic_cast<const VolumeAtomic<tgt::Vector4<uint32_t> >*>(volume)) { format = GL_RGBA; internalFormat = GL_RGBA; dataType = GL_UNSIGNED_INT; } else if (dynamic_cast<const VolumeAtomic<tgt::Vector4<int32_t> >*>(volume)) { format = GL_RGBA; internalFormat = GL_RGBA; dataType = GL_INT; } else if (dynamic_cast<const VolumeAtomic<tgt::Vector4<uint64_t> >*>(volume)) { std::string message = "Volume4xUInt64 not supported as OpenGL volume."; LERROR(message); throw VoreenException(message); } else if (dynamic_cast<const VolumeAtomic<tgt::Vector4<int64_t> >*>(volume)) { std::string message = "Volume4xInt64 not supported as OpenGL volume."; LERROR(message); throw VoreenException(message); } else if (dynamic_cast<const VolumeAtomic<tgt::Vector4<float> >*>(volume)) { format = GL_RGBA; internalFormat = GL_RGBA; dataType = GL_FLOAT; } else if (dynamic_cast<const VolumeAtomic<tgt::Vector4<double> >*>(volume)) { std::string message = "Volume4xDouble not supported as OpenGL volume."; LERROR(message); throw VoreenException(message); } // special types (TODO: extract from here) #ifdef VRN_MODULE_FLOWREEN else if (dynamic_cast<const VolumeFlow3D*>(volume)) { format = GL_RGB; internalFormat = GL_RGB16; dataType = GL_FLOAT; } #endif else { LERROR("unknown or unsupported volume type"); } // // Create texture // glPixelStorei(GL_UNPACK_ALIGNMENT, 1); VolumeTexture* vTex = 0; tgt::vec3* temp2 = 0; #ifdef VRN_MODULE_FLOWREEN // Textures containing flow data need to contain data // within range [0.0, 1.0], so the values have to be mapped const VolumeFlow3D* flowTex = dynamic_cast<const VolumeFlow3D*>(volume); if (flowTex) { const float minValue = flowTex->getMinValue(); const float maxValue = flowTex->getMaxValue(); const float range = (maxValue - minValue); const tgt::vec3* const voxels = flowTex->voxel(); temp2 = new tgt::vec3[volume->getNumVoxels()]; for (size_t i = 0; i < volume->getNumVoxels(); ++i) { if (voxels[i] != tgt::vec3::zero) { temp2[i].x = (voxels[i].x - minValue) / range; temp2[i].y = (voxels[i].y - minValue) / range; temp2[i].z = (voxels[i].z - minValue) / range; } } } #endif // use temp data if this was created if (temp2) { vTex = new VolumeTexture(reinterpret_cast<GLubyte*>(temp2), volume->getDimensionsWithBorder(), format, internalFormat, dataType, tgt::Texture::LINEAR); } else { vTex = new VolumeTexture(static_cast<const GLubyte*>(volume->getData()), volume->getDimensionsWithBorder(), format, internalFormat, dataType, tgt::Texture::LINEAR); } LGL_ERROR; vTex->bind(); if (volume->getData()) vTex->uploadTexture(); // set texture wrap to clamp vTex->setWrapping(tgt::Texture::CLAMP); LGL_ERROR; // delete temporary data that has eventually be created delete[] temp2; // prevent deleting twice vTex->setPixelData(0); // append to internal data structure texture_ = vTex; LGL_ERROR; }