コード例 #1
0
ファイル: volumegl.cpp プロジェクト: alvin-me/MIVT
  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;
  }
コード例 #2
0
ファイル: volumegl.cpp プロジェクト: bsmr-opengl/voreen
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;
}