From Art Tevs,
"A new texture class Texture2DArray derived from Texture extends the osg to support the new EXT_texture_array extensions. Texture arrays provides a feature for people interesting in GPGPU programming. Faetures and changes: - Full support for layered 2D textures. - New uniform types were added (sampler2DArray) - FrameBufferObject implementation were changed to support attaching of 2D array textures to the framebuffer - StateSet was slightly changed to support texture arrays. NOTE: array textures can not be used in fixed function pipeline. Thus using the layered texture as a statemode for a Drawable produce invalid enumerant OpenGL errors. - Image class was extended to support handling of array textures Tests: I have used this class as a new feature of my application. It works for me without problems (Note: Texture arrays were introduced only for shading languages and not for fixed function pipelines!!!). RTT with Texture2DArray works, as I have tested them as texture targets for a camera with 6 layers/faces (i.e. replacement for cube maps). I am using the array textures in shader programming. Array textures can be attached to the FBO and used as input and as output."
This commit is contained in:
@@ -132,6 +132,7 @@ SET(LIB_PUBLIC_HEADERS
|
||||
${HEADER_PATH}/Texture
|
||||
${HEADER_PATH}/Texture1D
|
||||
${HEADER_PATH}/Texture2D
|
||||
${HEADER_PATH}/Texture2DArray
|
||||
${HEADER_PATH}/Texture3D
|
||||
${HEADER_PATH}/TextureCubeMap
|
||||
${HEADER_PATH}/TextureRectangle
|
||||
@@ -283,6 +284,7 @@ ADD_LIBRARY(${LIB_NAME}
|
||||
Texture.cpp
|
||||
Texture1D.cpp
|
||||
Texture2D.cpp
|
||||
Texture2DArray.cpp
|
||||
Texture3D.cpp
|
||||
TextureCubeMap.cpp
|
||||
TextureRectangle.cpp
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <osg/Texture1D>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/Texture3D>
|
||||
#include <osg/Texture2DArray>
|
||||
#include <osg/TextureCubeMap>
|
||||
#include <osg/TextureRectangle>
|
||||
#include <osg/Notify>
|
||||
@@ -56,6 +57,7 @@ FBOExtensions::FBOExtensions(unsigned int contextID)
|
||||
LOAD_FBO_EXT(glFramebufferTexture1DEXT);
|
||||
LOAD_FBO_EXT(glFramebufferTexture2DEXT);
|
||||
LOAD_FBO_EXT(glFramebufferTexture3DEXT);
|
||||
LOAD_FBO_EXT(glFramebufferTextureLayerEXT);
|
||||
LOAD_FBO_EXT(glFramebufferRenderbufferEXT);
|
||||
LOAD_FBO_EXT(glGenerateMipmapEXT);
|
||||
|
||||
@@ -205,7 +207,8 @@ struct FrameBufferAttachment::Pimpl
|
||||
TEXTURE2D,
|
||||
TEXTURE3D,
|
||||
TEXTURECUBE,
|
||||
TEXTURERECT
|
||||
TEXTURERECT,
|
||||
TEXTURE2DARRAY
|
||||
};
|
||||
|
||||
TargetType targetType;
|
||||
@@ -269,6 +272,13 @@ FrameBufferAttachment::FrameBufferAttachment(Texture3D* target, int level, int z
|
||||
_ximpl->zoffset = zoffset;
|
||||
}
|
||||
|
||||
FrameBufferAttachment::FrameBufferAttachment(Texture2DArray* target, int layer, int level)
|
||||
{
|
||||
_ximpl = new Pimpl(Pimpl::TEXTURE2DARRAY, level);
|
||||
_ximpl->textureTarget = target;
|
||||
_ximpl->zoffset = layer;
|
||||
}
|
||||
|
||||
FrameBufferAttachment::FrameBufferAttachment(TextureCubeMap* target, int face, int level)
|
||||
{
|
||||
_ximpl = new Pimpl(Pimpl::TEXTURECUBE, level);
|
||||
@@ -312,6 +322,15 @@ FrameBufferAttachment::FrameBufferAttachment(Camera::Attachment& attachment)
|
||||
_ximpl->zoffset = attachment._face;
|
||||
return;
|
||||
}
|
||||
|
||||
osg::Texture2DArray* texture2DArray = dynamic_cast<osg::Texture2DArray*>(texture);
|
||||
if (texture2DArray)
|
||||
{
|
||||
_ximpl = new Pimpl(Pimpl::TEXTURE2DARRAY, attachment._level);
|
||||
_ximpl->textureTarget = texture2DArray;
|
||||
_ximpl->zoffset = attachment._face;
|
||||
return;
|
||||
}
|
||||
|
||||
osg::TextureCubeMap* textureCubeMap = dynamic_cast<osg::TextureCubeMap*>(texture);
|
||||
if (textureCubeMap)
|
||||
@@ -429,6 +448,9 @@ void FrameBufferAttachment::attach(State &state, GLenum attachment_point, const
|
||||
case Pimpl::TEXTURE3D:
|
||||
ext->glFramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, attachment_point, GL_TEXTURE_3D, tobj->_id, _ximpl->level, _ximpl->zoffset);
|
||||
break;
|
||||
case Pimpl::TEXTURE2DARRAY:
|
||||
ext->glFramebufferTextureLayerEXT(GL_FRAMEBUFFER_EXT, attachment_point, tobj->_id, _ximpl->level, _ximpl->zoffset);
|
||||
break;
|
||||
case Pimpl::TEXTURERECT:
|
||||
ext->glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment_point, GL_TEXTURE_RECTANGLE, tobj->_id, 0);
|
||||
break;
|
||||
@@ -588,6 +610,7 @@ void FrameBufferObject::apply(State &state) const
|
||||
|
||||
}
|
||||
|
||||
|
||||
ext->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboID);
|
||||
|
||||
if (dirtyAttachmentList)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <osg/StateSet>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/Texture3D>
|
||||
#include <osg/Texture2DArray>
|
||||
|
||||
#include "dxtctool.h"
|
||||
|
||||
@@ -522,14 +523,25 @@ void Image::readImageFromCurrentTexture(unsigned int contextID, bool copyMipMaps
|
||||
{
|
||||
const osg::Texture::Extensions* extensions = osg::Texture::getExtensions(contextID,true);
|
||||
const osg::Texture3D::Extensions* extensions3D = osg::Texture3D::getExtensions(contextID,true);
|
||||
const osg::Texture2DArray::Extensions* extensions2DArray = osg::Texture2DArray::getExtensions(contextID,true);
|
||||
|
||||
|
||||
GLboolean binding1D, binding2D, binding3D;
|
||||
GLboolean binding1D, binding2D, binding3D, binding2DArray;
|
||||
glGetBooleanv(GL_TEXTURE_BINDING_1D, &binding1D);
|
||||
glGetBooleanv(GL_TEXTURE_BINDING_2D, &binding2D);
|
||||
glGetBooleanv(GL_TEXTURE_BINDING_3D, &binding3D);
|
||||
|
||||
|
||||
if (extensions2DArray->isTexture2DArraySupported())
|
||||
{
|
||||
glGetBooleanv(GL_TEXTURE_BINDING_2D_ARRAY_EXT, &binding2DArray);
|
||||
}
|
||||
else
|
||||
{
|
||||
binding2DArray - GL_FALSE;
|
||||
}
|
||||
|
||||
GLenum textureMode = binding1D ? GL_TEXTURE_1D : binding2D ? GL_TEXTURE_2D : binding3D ? GL_TEXTURE_3D : 0;
|
||||
GLenum textureMode = binding1D ? GL_TEXTURE_1D : binding2D ? GL_TEXTURE_2D : binding3D ? GL_TEXTURE_3D : binding2DArray ? GL_TEXTURE_2D_ARRAY_EXT : 0;
|
||||
|
||||
if (textureMode==0) return;
|
||||
|
||||
@@ -562,14 +574,21 @@ void Image::readImageFromCurrentTexture(unsigned int contextID, bool copyMipMaps
|
||||
{
|
||||
if (extensions->isCompressedTexImage2DSupported())
|
||||
{
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_ARB,&compressed);
|
||||
glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_COMPRESSED_ARB,&compressed);
|
||||
}
|
||||
}
|
||||
else if (textureMode==GL_TEXTURE_3D)
|
||||
{
|
||||
if (extensions3D->isCompressedTexImage3DSupported())
|
||||
{
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_3D, 0, GL_TEXTURE_COMPRESSED_ARB,&compressed);
|
||||
glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_COMPRESSED_ARB,&compressed);
|
||||
}
|
||||
}
|
||||
else if (textureMode==GL_TEXTURE_2D_ARRAY_EXT)
|
||||
{
|
||||
if (extensions2DArray->isCompressedTexImage3DSupported())
|
||||
{
|
||||
glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_COMPRESSED_ARB,&compressed);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
#include <osg/TextureCubeMap>
|
||||
#include <osg/TextureRectangle>
|
||||
#include <osg/Texture2DArray>
|
||||
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
@@ -48,7 +49,8 @@ class TextureGLModeSet
|
||||
_textureModeSet.insert(GL_TEXTURE_3D);
|
||||
|
||||
_textureModeSet.insert(GL_TEXTURE_CUBE_MAP);
|
||||
_textureModeSet.insert(GL_TEXTURE_RECTANGLE_NV);
|
||||
_textureModeSet.insert(GL_TEXTURE_RECTANGLE_NV);
|
||||
_textureModeSet.insert(GL_TEXTURE_2D_ARRAY_EXT);
|
||||
|
||||
_textureModeSet.insert(GL_TEXTURE_GEN_Q);
|
||||
_textureModeSet.insert(GL_TEXTURE_GEN_R);
|
||||
|
||||
574
src/osg/Texture2DArray.cpp
Normal file
574
src/osg/Texture2DArray.cpp
Normal file
@@ -0,0 +1,574 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
|
||||
*
|
||||
* This library is open source and may be redistributed and/or modified under
|
||||
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
#include <osg/GLExtensions>
|
||||
#include <osg/Texture2DArray>
|
||||
#include <osg/State>
|
||||
#include <osg/Notify>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
using namespace osg;
|
||||
|
||||
Texture2DArray::Texture2DArray():
|
||||
_textureWidth(0),
|
||||
_textureHeight(0),
|
||||
_textureDepth(0),
|
||||
_numMipmapLevels(0)
|
||||
{
|
||||
}
|
||||
|
||||
Texture2DArray::Texture2DArray(const Texture2DArray& text,const CopyOp& copyop):
|
||||
Texture(text,copyop),
|
||||
_textureWidth(text._textureWidth),
|
||||
_textureHeight(text._textureHeight),
|
||||
_textureDepth(text._textureDepth),
|
||||
_numMipmapLevels(text._numMipmapLevels),
|
||||
_subloadCallback(text._subloadCallback)
|
||||
{
|
||||
// copy all images by iterating through all of them
|
||||
for (int i=0; i < text._textureDepth; i++)
|
||||
{
|
||||
_images.push_back(copyop(text._images[i].get()));
|
||||
_modifiedCount.push_back(ImageModifiedCount());
|
||||
}
|
||||
}
|
||||
|
||||
Texture2DArray::~Texture2DArray()
|
||||
{
|
||||
}
|
||||
|
||||
int Texture2DArray::compare(const StateAttribute& sa) const
|
||||
{
|
||||
// check the types are equal and then create the rhs variable
|
||||
// used by the COMPARE_StateAttribute_Paramter macro's below.
|
||||
COMPARE_StateAttribute_Types(Texture2DArray,sa)
|
||||
|
||||
bool noImages = true;
|
||||
for (int n=0; n < _textureDepth; n++)
|
||||
{
|
||||
if (noImages && _images[n].valid()) noImages = false;
|
||||
if (noImages && rhs._images[n].valid()) noImages = false;
|
||||
|
||||
if (_images[n]!=rhs._images[n]) // smart pointer comparison.
|
||||
{
|
||||
if (_images[n].valid())
|
||||
{
|
||||
if (rhs._images[n].valid())
|
||||
{
|
||||
int result = _images[n]->compare(*rhs._images[n]);
|
||||
if (result!=0) return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1; // valid lhs._image is greater than null.
|
||||
}
|
||||
}
|
||||
else if (rhs._images[n].valid())
|
||||
{
|
||||
return -1; // valid rhs._image is greater than null.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (noImages)
|
||||
{
|
||||
int result = compareTextureObjects(rhs);
|
||||
if (result!=0) return result;
|
||||
}
|
||||
|
||||
int result = compareTexture(rhs);
|
||||
if (result!=0) return result;
|
||||
|
||||
// compare each paramter in turn against the rhs.
|
||||
COMPARE_StateAttribute_Parameter(_textureWidth)
|
||||
COMPARE_StateAttribute_Parameter(_textureHeight)
|
||||
COMPARE_StateAttribute_Parameter(_textureDepth)
|
||||
COMPARE_StateAttribute_Parameter(_subloadCallback)
|
||||
|
||||
return 0; // passed all the above comparison macro's, must be equal.
|
||||
}
|
||||
|
||||
void Texture2DArray::setImage(unsigned int layer, Image* image)
|
||||
{
|
||||
// check if the layer exceeds the texture depth
|
||||
if (layer >= _textureDepth)
|
||||
{
|
||||
// print warning and do nothing
|
||||
notify(WARN)<<"Warning: Texture2DArray::setImage(..) failed, the given layer number is bigger then the size of the texture array."<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// set image
|
||||
_images[layer] = image;
|
||||
_modifiedCount[layer].setAllElementsTo(0);
|
||||
}
|
||||
|
||||
void Texture2DArray::setTextureSize(int width, int height, int depth)
|
||||
{
|
||||
// set dimensions
|
||||
_textureWidth = width;
|
||||
_textureHeight = height;
|
||||
setTextureDepth(depth);
|
||||
}
|
||||
|
||||
void Texture2DArray::setTextureDepth(int depth)
|
||||
{
|
||||
// if we decrease the number of layers, then delete non-used
|
||||
if (depth < _textureDepth)
|
||||
{
|
||||
_images.resize(depth);
|
||||
_modifiedCount.resize(depth);
|
||||
}
|
||||
|
||||
// if we increase the array, then add new empty elements
|
||||
if (depth > _textureDepth)
|
||||
{
|
||||
_images.resize(depth, ref_ptr<Image>(0));
|
||||
_modifiedCount.resize(depth, ImageModifiedCount());
|
||||
}
|
||||
|
||||
// resize the texture array
|
||||
_textureDepth = depth;
|
||||
}
|
||||
|
||||
Image* Texture2DArray::getImage(unsigned int layer)
|
||||
{
|
||||
return _images[layer].get();
|
||||
}
|
||||
|
||||
const Image* Texture2DArray::getImage(unsigned int layer) const
|
||||
{
|
||||
return _images[layer].get();
|
||||
}
|
||||
|
||||
bool Texture2DArray::imagesValid() const
|
||||
{
|
||||
if (_textureDepth < 1) return false;
|
||||
for (int n=0; n < _textureDepth; n++)
|
||||
{
|
||||
if (!_images[n].valid() || !_images[n]->data())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Texture2DArray::computeInternalFormat() const
|
||||
{
|
||||
if (imagesValid()) computeInternalFormatWithImage(*_images[0]);
|
||||
}
|
||||
|
||||
|
||||
void Texture2DArray::apply(State& state) const
|
||||
{
|
||||
// get the contextID (user defined ID of 0 upwards) for the
|
||||
// current OpenGL context.
|
||||
const unsigned int contextID = state.getContextID();
|
||||
const Extensions* extensions = getExtensions(contextID,true);
|
||||
|
||||
// if not supported, then return
|
||||
if (!extensions->isTexture2DArraySupported() || !extensions->isTexture3DSupported())
|
||||
{
|
||||
notify(WARN)<<"Warning: Texture2DArray::apply(..) failed, 2D texture arrays are not support by OpenGL driver."<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// get the texture object for the current contextID.
|
||||
TextureObject* textureObject = getTextureObject(contextID);
|
||||
|
||||
// if we already have an texture object, then
|
||||
if (textureObject != 0)
|
||||
{
|
||||
// bind texture object
|
||||
textureObject->bind();
|
||||
|
||||
// if texture parameters changed, then reset them
|
||||
if (getTextureParameterDirty(state.getContextID())) applyTexParameters(GL_TEXTURE_2D_ARRAY_EXT,state);
|
||||
|
||||
// if subload is specified, then use it to subload the images to GPU memory
|
||||
if (_subloadCallback.valid())
|
||||
{
|
||||
_subloadCallback->subload(*this,state);
|
||||
}
|
||||
else
|
||||
{
|
||||
// for each image of the texture array do
|
||||
for (int n=0; n < _textureDepth; n++)
|
||||
{
|
||||
osg::Image* image = _images[n].get();
|
||||
|
||||
// if image content is modified, then upload it to the GPU memory
|
||||
if (image && getModifiedCount(n,contextID) != image->getModifiedCount())
|
||||
{
|
||||
applyTexImage2DArray_subload(state, image, _textureWidth, _textureHeight, n, _numMipmapLevels);
|
||||
getModifiedCount(n,contextID) = image->getModifiedCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// there is no texture object, but exists a subload callback, so use it to upload images
|
||||
else if (_subloadCallback.valid())
|
||||
{
|
||||
// generate texture (i.e. glGenTexture) and apply parameters
|
||||
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(contextID, GL_TEXTURE_2D_ARRAY_EXT);
|
||||
textureObject->bind();
|
||||
applyTexParameters(GL_TEXTURE_2D_ARRAY_EXT, state);
|
||||
_subloadCallback->load(*this,state);
|
||||
}
|
||||
|
||||
// nothing before, but we have valid images, so do manual upload and create texture object manually
|
||||
else if (imagesValid())
|
||||
{
|
||||
|
||||
// compute the internal texture format, this set the _internalFormat to an appropriate value.
|
||||
computeInternalFormat();
|
||||
|
||||
// compute the dimensions of the texture.
|
||||
computeRequiredTextureDimensions(state,*_images[0],_textureWidth, _textureHeight, _numMipmapLevels);
|
||||
|
||||
// create texture object
|
||||
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(
|
||||
contextID,GL_TEXTURE_2D_ARRAY_EXT,_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,_textureDepth,0);
|
||||
|
||||
// bind texture
|
||||
textureObject->bind();
|
||||
applyTexParameters(GL_TEXTURE_2D_ARRAY_EXT, state);
|
||||
|
||||
// now for each layer do
|
||||
for (int n=0; n<_textureDepth; n++)
|
||||
{
|
||||
// if image is valid then upload it to the texture memory
|
||||
osg::Image* image = _images[n].get();
|
||||
if (image)
|
||||
{
|
||||
applyTexImage2DArray_subload(state, image, _textureWidth, _textureHeight, n, _numMipmapLevels);
|
||||
getModifiedCount(n,contextID) = image->getModifiedCount();
|
||||
}
|
||||
}
|
||||
textureObject->setAllocated(_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,_textureDepth,0);
|
||||
|
||||
// no idea what this for ;-)
|
||||
if (_unrefImageDataAfterApply && areAllTextureObjectsLoaded())
|
||||
{
|
||||
Texture2DArray* non_const_this = const_cast<Texture2DArray*>(this);
|
||||
for (int n=0; n<_textureDepth; n++)
|
||||
{
|
||||
if (_images[n].valid() && _images[n]->getDataVariance()==STATIC)
|
||||
{
|
||||
non_const_this->_images[n] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// No images present, but dimensions are set. So create empty texture
|
||||
else if ( (_textureWidth > 0) && (_textureHeight > 0) && (_textureDepth > 0) && (_internalFormat!=0) )
|
||||
{
|
||||
// generate texture
|
||||
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(
|
||||
contextID, GL_TEXTURE_2D_ARRAY_EXT,_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,_textureDepth,0);
|
||||
|
||||
textureObject->bind();
|
||||
applyTexParameters(GL_TEXTURE_2D_ARRAY_EXT,state);
|
||||
|
||||
extensions->glTexImage3D( GL_TEXTURE_2D_ARRAY_EXT, 0, _internalFormat,
|
||||
_textureWidth, _textureHeight, _textureDepth,
|
||||
_borderWidth,
|
||||
_sourceFormat ? _sourceFormat : _internalFormat,
|
||||
_sourceType ? _sourceType : GL_UNSIGNED_BYTE,
|
||||
0);
|
||||
|
||||
}
|
||||
|
||||
// nothing before, so just unbind the texture target
|
||||
else
|
||||
{
|
||||
glBindTexture( GL_TEXTURE_2D_ARRAY_EXT, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
void Texture2DArray::applyTexImage2DArray_subload(State& state, Image* image, GLsizei& inwidth, GLsizei& inheight, GLsizei& indepth, GLsizei& numMipmapLevels) const
|
||||
{
|
||||
// if we don't have a valid image we can't create a texture!
|
||||
if (!imagesValid())
|
||||
return;
|
||||
|
||||
// get the contextID (user defined ID of 0 upwards) for the
|
||||
// current OpenGL context.
|
||||
const unsigned int contextID = state.getContextID();
|
||||
const Extensions* extensions = getExtensions(contextID,true);
|
||||
const Texture::Extensions* texExtensions = Texture::getExtensions(contextID,true);
|
||||
GLenum target = GL_TEXTURE_2D_ARRAY_EXT;
|
||||
|
||||
// compute the internal texture format, this set the _internalFormat to an appropriate value.
|
||||
computeInternalFormat();
|
||||
|
||||
// select the internalFormat required for the texture.
|
||||
bool compressed = isCompressedInternalFormat(_internalFormat);
|
||||
bool compressed_image = isCompressedInternalFormat((GLenum)image->getPixelFormat());
|
||||
|
||||
// if the required layer is exceeds the maximum allowed layer sizes
|
||||
if (indepth > extensions->maxLayerCount())
|
||||
{
|
||||
// we give a warning and do nothing
|
||||
notify(WARN)<<"Warning: Texture2DArray::applyTexImage2DArray_subload(..) the given layer number exceeds the maximum number of supported layers."<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
//Rescale if resize hint is set or NPOT not supported or dimensions exceed max size
|
||||
if( _resizeNonPowerOfTwoHint || !texExtensions->isNonPowerOfTwoTextureSupported(_min_filter)
|
||||
|| inwidth > extensions->max2DSize()
|
||||
|| inheight > extensions->max2DSize())
|
||||
image->ensureValidSizeForTexturing(extensions->max2DSize());
|
||||
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT,image->getPacking());
|
||||
|
||||
// if no special mipmapping is required, then
|
||||
if( _min_filter == LINEAR || _min_filter == NEAREST )
|
||||
{
|
||||
numMipmapLevels = 1;
|
||||
|
||||
// upload non-compressed image
|
||||
if (!compressed_image)
|
||||
{
|
||||
extensions->glTexImage3D( target, 0, _internalFormat,
|
||||
inwidth, inheight, indepth,
|
||||
_borderWidth,
|
||||
(GLenum)image->getPixelFormat(),
|
||||
(GLenum)image->getDataType(),
|
||||
image->data() );
|
||||
}
|
||||
|
||||
// if we support compression and image is compressed, then
|
||||
else if (extensions->isCompressedTexImage3DSupported())
|
||||
{
|
||||
// notify(WARN)<<"glCompressedTexImage3D "<<inwidth<<", "<<inheight<<", "<<indepth<<std::endl;
|
||||
numMipmapLevels = 1;
|
||||
|
||||
GLint blockSize, size;
|
||||
getCompressedSize(_internalFormat, inwidth, inheight, indepth, blockSize,size);
|
||||
|
||||
extensions->glCompressedTexImage3D(target, 0, _internalFormat,
|
||||
inwidth, inheight, indepth,
|
||||
_borderWidth,
|
||||
size,
|
||||
image->data());
|
||||
}
|
||||
|
||||
// we want to use mipmapping, so enable it
|
||||
}else
|
||||
{
|
||||
// image does not provide mipmaps, so we have to create them
|
||||
if(!image->isMipmap())
|
||||
{
|
||||
notify(WARN)<<"Warning: Texture2DArray::applyTexImage2DArray_subload(..) automagic mipmap generation is currently not implemented."<<std::endl;
|
||||
|
||||
// the image object does provide mipmaps, so upload the in the certain levels of a layer
|
||||
}else
|
||||
{
|
||||
numMipmapLevels = image->getNumMipmapLevels();
|
||||
|
||||
int width = image->s();
|
||||
int height = image->t();
|
||||
int depth = image->r();
|
||||
|
||||
for( GLsizei k = 0 ; k < numMipmapLevels && (width || height || depth) ;k++)
|
||||
{
|
||||
|
||||
if (width == 0)
|
||||
width = 1;
|
||||
if (height == 0)
|
||||
height = 1;
|
||||
if (depth == 0)
|
||||
depth = 1;
|
||||
|
||||
extensions->glTexImage3D( target, k, _internalFormat,
|
||||
width, height, depth, _borderWidth,
|
||||
(GLenum)image->getPixelFormat(),
|
||||
(GLenum)image->getDataType(),
|
||||
image->getMipmapData(k));
|
||||
|
||||
width >>= 1;
|
||||
height >>= 1;
|
||||
depth >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// set new sizes back
|
||||
inwidth = image->s();
|
||||
inheight = image->t();
|
||||
}
|
||||
|
||||
|
||||
void Texture2DArray::copyTexSubImage2DArray(State& state, int xoffset, int yoffset, int zoffset, int x, int y, int width, int height )
|
||||
{
|
||||
const unsigned int contextID = state.getContextID();
|
||||
const Extensions* extensions = getExtensions(contextID,true);
|
||||
|
||||
// get the texture object for the current contextID.
|
||||
TextureObject* textureObject = getTextureObject(contextID);
|
||||
|
||||
// if texture object is valid
|
||||
if (textureObject != 0)
|
||||
{
|
||||
textureObject->bind();
|
||||
|
||||
applyTexParameters(GL_TEXTURE_2D_ARRAY_EXT,state);
|
||||
extensions->glCopyTexSubImage3D( GL_TEXTURE_2D_ARRAY_EXT, 0, xoffset,yoffset,zoffset, x, y, width, height);
|
||||
|
||||
// inform state that this texture is the current one bound.
|
||||
state.haveAppliedTextureAttribute(state.getActiveTextureUnit(), this);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
notify(WARN)<<"Warning: Texture2DArray::copyTexSubImage2DArray(..) failed, cannot not copy to a non existant texture."<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
typedef buffered_value< ref_ptr<Texture2DArray::Extensions> > BufferedExtensions;
|
||||
static BufferedExtensions s_extensions;
|
||||
|
||||
Texture2DArray::Extensions* Texture2DArray::getExtensions(unsigned int contextID,bool createIfNotInitalized)
|
||||
{
|
||||
if (!s_extensions[contextID] && createIfNotInitalized) s_extensions[contextID] = new Extensions(contextID);
|
||||
return s_extensions[contextID].get();
|
||||
}
|
||||
|
||||
void Texture2DArray::setExtensions(unsigned int contextID,Extensions* extensions)
|
||||
{
|
||||
s_extensions[contextID] = extensions;
|
||||
}
|
||||
|
||||
Texture2DArray::Extensions::Extensions(unsigned int contextID)
|
||||
{
|
||||
setupGLExtensions(contextID);
|
||||
}
|
||||
|
||||
Texture2DArray::Extensions::Extensions(const Extensions& rhs):
|
||||
Referenced()
|
||||
{
|
||||
_isTexture3DSupported = rhs._isTexture3DSupported;
|
||||
_isTexture2DArraySupported = rhs._isTexture2DArraySupported;
|
||||
|
||||
_max2DSize = rhs._max2DSize;
|
||||
_maxLayerCount = rhs._maxLayerCount;
|
||||
|
||||
_glTexImage3D = rhs._glTexImage3D;
|
||||
_glTexSubImage3D = rhs._glTexSubImage3D;
|
||||
_glCopyTexSubImage3D = rhs._glCopyTexSubImage3D;
|
||||
_glCompressedTexImage3D = rhs._glCompressedTexImage3D;
|
||||
_glCompressedTexSubImage3D = rhs._glCompressedTexSubImage3D;;
|
||||
}
|
||||
|
||||
void Texture2DArray::Extensions::lowestCommonDenominator(const Extensions& rhs)
|
||||
{
|
||||
if (!rhs._isTexture3DSupported) _isTexture3DSupported = false;
|
||||
if (!rhs._isTexture2DArraySupported) _isTexture2DArraySupported = false;
|
||||
if (rhs._max2DSize<_max2DSize) _max2DSize = rhs._max2DSize;
|
||||
if (rhs._maxLayerCount<_maxLayerCount) _maxLayerCount = rhs._maxLayerCount;
|
||||
|
||||
if (!rhs._glTexImage3D) _glTexImage3D = 0;
|
||||
if (!rhs._glTexSubImage3D) _glTexSubImage3D = 0;
|
||||
if (!rhs._glCompressedTexImage3D) _glTexImage3D = 0;
|
||||
if (!rhs._glCompressedTexSubImage3D) _glTexSubImage3D = 0;
|
||||
if (!rhs._glCopyTexSubImage3D) _glCopyTexSubImage3D = 0;
|
||||
}
|
||||
|
||||
void Texture2DArray::Extensions::setupGLExtensions(unsigned int contextID)
|
||||
{
|
||||
_isTexture3DSupported = isGLExtensionSupported(contextID,"GL_EXT_texture3D");
|
||||
_isTexture2DArraySupported = isGLExtensionSupported(contextID,"GL_EXT_texture_array");
|
||||
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &_max2DSize);
|
||||
glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS_EXT, &_maxLayerCount);
|
||||
|
||||
_glTexImage3D = getGLExtensionFuncPtr("glTexImage3D","glTexImage3DEXT");
|
||||
_glTexSubImage3D = getGLExtensionFuncPtr("glTexSubImage3D","glTexSubImage3DEXT");
|
||||
_glCompressedTexImage3D = getGLExtensionFuncPtr("glCompressedTexImage3D","glCompressedTexImage3DARB");
|
||||
_glCompressedTexSubImage3D = getGLExtensionFuncPtr("glCompressedTexSubImage3D","glCompressedTexSubImage3DARB");
|
||||
_glCopyTexSubImage3D = getGLExtensionFuncPtr("glCopyTexSubImage3D","glCopyTexSubImage3DEXT");
|
||||
}
|
||||
|
||||
void Texture2DArray::Extensions::glTexImage3D( GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels) const
|
||||
{
|
||||
if (_glTexImage3D)
|
||||
{
|
||||
typedef void (APIENTRY * GLTexImage3DProc) ( GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
|
||||
((GLTexImage3DProc)_glTexImage3D)( target, level, internalFormat, width, height, depth, border, format, type, pixels);
|
||||
}
|
||||
else
|
||||
{
|
||||
notify(WARN)<<"Error: glTexImage3D not supported by OpenGL driver"<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void Texture2DArray::Extensions::glTexSubImage3D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels) const
|
||||
{
|
||||
if (_glTexSubImage3D)
|
||||
{
|
||||
typedef void (APIENTRY * GLTexSubImage3DProc) ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
|
||||
((GLTexSubImage3DProc)_glTexSubImage3D)( target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
|
||||
}
|
||||
else
|
||||
{
|
||||
notify(WARN)<<"Error: glTexSubImage3D not supported by OpenGL driver"<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void Texture2DArray::Extensions::glCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data) const
|
||||
{
|
||||
if (_glCompressedTexImage3D)
|
||||
{
|
||||
typedef void (APIENTRY * CompressedTexImage3DArbProc) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
|
||||
((CompressedTexImage3DArbProc)_glCompressedTexImage3D)(target, level, internalformat, width, height, depth, border, imageSize, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
notify(WARN)<<"Error: glCompressedTexImage3D not supported by OpenGL driver"<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void Texture2DArray::Extensions::glCompressedTexSubImage3D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data ) const
|
||||
{
|
||||
if (_glCompressedTexSubImage3D)
|
||||
{
|
||||
typedef void (APIENTRY * CompressedTexSubImage3DArbProc) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
|
||||
((CompressedTexSubImage3DArbProc)_glCompressedTexSubImage3D)(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
notify(WARN)<<"Error: glCompressedTexImage2D not supported by OpenGL driver"<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void Texture2DArray::Extensions::glCopyTexSubImage3D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height ) const
|
||||
{
|
||||
if (_glCopyTexSubImage3D)
|
||||
{
|
||||
typedef void (APIENTRY * GLCopyTexSubImageProc) ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height );
|
||||
((GLCopyTexSubImageProc)_glCopyTexSubImage3D)(target, level, xoffset, yoffset, zoffset, x, y, width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
notify(WARN)<<"Error: glCopyTexSubImage3D not supported by OpenGL driver"<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,10 +265,14 @@ const char* Uniform::getTypename( Type t )
|
||||
case FLOAT_MAT4: return "mat4";
|
||||
case SAMPLER_1D: return "sampler1D";
|
||||
case SAMPLER_2D: return "sampler2D";
|
||||
case SAMPLER_1D_ARRAY: return "sampler1DArray";
|
||||
case SAMPLER_2D_ARRAY: return "sampler2DArray";
|
||||
case SAMPLER_3D: return "sampler3D";
|
||||
case SAMPLER_CUBE: return "samplerCube";
|
||||
case SAMPLER_1D_SHADOW: return "sampler1DShadow";
|
||||
case SAMPLER_2D_SHADOW: return "sampler2DShadow";
|
||||
case SAMPLER_1D_ARRAY_SHADOW: return "sampler1DArrayShadow";
|
||||
case SAMPLER_2D_ARRAY_SHADOW: return "sampler2DArrayShadow";
|
||||
default: return "UNDEFINED";
|
||||
}
|
||||
}
|
||||
@@ -282,10 +286,14 @@ int Uniform::getTypeNumComponents( Type t )
|
||||
case BOOL:
|
||||
case SAMPLER_1D:
|
||||
case SAMPLER_2D:
|
||||
case SAMPLER_1D_ARRAY:
|
||||
case SAMPLER_2D_ARRAY:
|
||||
case SAMPLER_3D:
|
||||
case SAMPLER_CUBE:
|
||||
case SAMPLER_1D_SHADOW:
|
||||
case SAMPLER_2D_SHADOW:
|
||||
case SAMPLER_1D_ARRAY_SHADOW:
|
||||
case SAMPLER_2D_ARRAY_SHADOW:
|
||||
return 1;
|
||||
|
||||
case FLOAT_VEC2:
|
||||
@@ -334,10 +342,14 @@ Uniform::Type Uniform::getTypeId( const std::string& tname )
|
||||
if( tname == "mat4" ) return FLOAT_MAT4;
|
||||
if( tname == "sampler1D" ) return SAMPLER_1D;
|
||||
if( tname == "sampler2D" ) return SAMPLER_2D;
|
||||
if( tname == "sampler1DArray" ) return SAMPLER_1D_ARRAY;
|
||||
if( tname == "sampler2DArray" ) return SAMPLER_2D_ARRAY;
|
||||
if( tname == "sampler3D" ) return SAMPLER_3D;
|
||||
if( tname == "samplerCube" ) return SAMPLER_CUBE;
|
||||
if( tname == "sampler1DShadow" ) return SAMPLER_1D_SHADOW;
|
||||
if( tname == "sampler2DShadow" ) return SAMPLER_2D_SHADOW;
|
||||
if( tname == "sampler1DArrayShadow" ) return SAMPLER_1D_ARRAY_SHADOW;
|
||||
if( tname == "sampler2DArrayShadow" ) return SAMPLER_2D_ARRAY_SHADOW;
|
||||
return UNDEFINED;
|
||||
}
|
||||
|
||||
@@ -348,10 +360,14 @@ Uniform::Type Uniform::getGlApiType( Type t )
|
||||
case BOOL:
|
||||
case SAMPLER_1D:
|
||||
case SAMPLER_2D:
|
||||
case SAMPLER_1D_ARRAY:
|
||||
case SAMPLER_2D_ARRAY:
|
||||
case SAMPLER_3D:
|
||||
case SAMPLER_CUBE:
|
||||
case SAMPLER_1D_SHADOW:
|
||||
case SAMPLER_2D_SHADOW:
|
||||
case SAMPLER_1D_ARRAY_SHADOW:
|
||||
case SAMPLER_2D_ARRAY_SHADOW:
|
||||
return INT;
|
||||
|
||||
case BOOL_VEC2:
|
||||
@@ -391,10 +407,14 @@ GLenum Uniform::getInternalArrayType( Type t )
|
||||
case BOOL_VEC4:
|
||||
case SAMPLER_1D:
|
||||
case SAMPLER_2D:
|
||||
case SAMPLER_1D_ARRAY:
|
||||
case SAMPLER_2D_ARRAY:
|
||||
case SAMPLER_3D:
|
||||
case SAMPLER_CUBE:
|
||||
case SAMPLER_1D_SHADOW:
|
||||
case SAMPLER_2D_SHADOW:
|
||||
case SAMPLER_1D_ARRAY_SHADOW:
|
||||
case SAMPLER_2D_ARRAY_SHADOW:
|
||||
return GL_INT;
|
||||
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user