Merge branch 'master' into text_improvements

This commit is contained in:
Robert Osfield
2017-10-20 14:14:14 +01:00
25 changed files with 622 additions and 138 deletions

View File

@@ -241,11 +241,17 @@ Image::Image(const Image& image,const CopyOp& copyop):
{
unsigned int size = image.getTotalSizeInBytesIncludingMipmaps();
setData(new unsigned char [size],USE_NEW_DELETE);
unsigned char* dest_ptr = _data;
for(DataIterator itr(&image); itr.valid(); ++itr)
if (unsigned char* dest_ptr = _data)
{
memcpy(dest_ptr, itr.data(), itr.size());
dest_ptr += itr.size();
for(DataIterator itr(&image); itr.valid(); ++itr)
{
memcpy(dest_ptr, itr.data(), itr.size());
dest_ptr += itr.size();
}
}
else
{
OSG_WARN<<"Warning: Image::Image(const Image&, const CopyOp&) out of memory, no image copy made."<<std::endl;
}
}
}
@@ -602,7 +608,36 @@ unsigned int Image::computeNumComponents(GLenum pixelFormat)
case(GL_BGRA_INTEGER_EXT): return 4;
case(GL_LUMINANCE_INTEGER_EXT): return 1;
case(GL_LUMINANCE_ALPHA_INTEGER_EXT): return 2;
case(GL_SRGB8) : return 3;
case(GL_SRGB8_ALPHA8) : return 4;
case (GL_COMPRESSED_RGBA_ASTC_4x4_KHR) : return 4;
case (GL_COMPRESSED_RGBA_ASTC_5x4_KHR) : return 4;
case (GL_COMPRESSED_RGBA_ASTC_5x5_KHR) : return 4;
case (GL_COMPRESSED_RGBA_ASTC_6x5_KHR) : return 4;
case (GL_COMPRESSED_RGBA_ASTC_6x6_KHR) : return 4;
case (GL_COMPRESSED_RGBA_ASTC_8x5_KHR) : return 4;
case (GL_COMPRESSED_RGBA_ASTC_8x6_KHR) : return 4;
case (GL_COMPRESSED_RGBA_ASTC_8x8_KHR) : return 4;
case (GL_COMPRESSED_RGBA_ASTC_10x5_KHR) : return 4;
case (GL_COMPRESSED_RGBA_ASTC_10x6_KHR) : return 4;
case (GL_COMPRESSED_RGBA_ASTC_10x8_KHR) : return 4;
case (GL_COMPRESSED_RGBA_ASTC_10x10_KHR) : return 4;
case (GL_COMPRESSED_RGBA_ASTC_12x10_KHR) : return 4;
case (GL_COMPRESSED_RGBA_ASTC_12x12_KHR) : return 4;
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR) : return 4;
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR) : return 4;
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR) : return 4;
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR) : return 4;
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR) : return 4;
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR) : return 4;
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR) : return 4;
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR) : return 4;
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR) : return 4;
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR) : return 4;
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR) : return 4;
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR) : return 4;
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR) : return 4;
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR) : return 4;
default:
{
OSG_WARN<<"error pixelFormat = "<<std::hex<<pixelFormat<<std::dec<<std::endl;
@@ -665,6 +700,51 @@ unsigned int Image::computePixelSizeInBits(GLenum format,GLenum type)
return 0;
default: break;
}
switch (format)
{//handle GL_KHR_texture_compression_astc_hdr
case (GL_COMPRESSED_RGBA_ASTC_4x4_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_5x4_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_5x5_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_6x5_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_6x6_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_8x5_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_8x6_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_8x8_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_10x5_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_10x6_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_10x8_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_10x10_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_12x10_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_12x12_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR) :
{
osg::Vec3i footprint = computeBlockFootprint(format);
unsigned int pixelsPerBlock = footprint.x() * footprint.y();
unsigned int bitsPerBlock = computeBlockSize(format, 0);//16 x 8 = 128
unsigned int bitsPerPixel = bitsPerBlock / pixelsPerBlock;
if (bitsPerBlock == bitsPerPixel * pixelsPerBlock) {
OSG_WARN << "Image::computePixelSizeInBits(format,type) : bits per pixel (" << bitsPerPixel << ") is not an integer for GL_KHR_texture_compression_astc_hdr sizes other than 4x4 and 8x8." << std::endl;
return bitsPerPixel;
} else {
OSG_WARN << "Image::computePixelSizeInBits(format,type) : bits per pixel (" << bitsPerBlock << "/" << pixelsPerBlock << ") is not an integer for GL_KHR_texture_compression_astc_hdr size" << footprint.x() << "x" << footprint.y() << "." << std::endl;
}
return 0;
}
default: break;
}
switch(format)
{
@@ -725,6 +805,71 @@ unsigned int Image::computePixelSizeInBits(GLenum format,GLenum type)
}
osg::Vec3i Image::computeBlockFootprint(GLenum pixelFormat) {
switch (pixelFormat)
{
case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT) :
case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) :
case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) :
case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) :
return osg::Vec3i(4,4,4);//opengl 3d dxt: r value means (max)4 consecutive blocks in r direction packed into a slab.
case(GL_COMPRESSED_SIGNED_RED_RGTC1_EXT) :
case(GL_COMPRESSED_RED_RGTC1_EXT) :
case(GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT) :
case(GL_COMPRESSED_RED_GREEN_RGTC2_EXT) :
case(GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG) :
case(GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG) :
case(GL_ETC1_RGB8_OES) :
case(GL_COMPRESSED_RGB8_ETC2) :
case(GL_COMPRESSED_SRGB8_ETC2) :
case(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2) :
case(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2) :
case(GL_COMPRESSED_RGBA8_ETC2_EAC) :
case(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC) :
case(GL_COMPRESSED_R11_EAC) :
case(GL_COMPRESSED_SIGNED_R11_EAC) :
case(GL_COMPRESSED_RG11_EAC) :
case(GL_COMPRESSED_SIGNED_RG11_EAC) :
return osg::Vec3i(4, 4, 1);//not sure about r
case(GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG) :
case(GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG) :
return osg::Vec3i(8, 4, 1);//no 3d texture support in pvrtc at all
case (GL_COMPRESSED_RGBA_ASTC_4x4_KHR) : return osg::Vec3i(4, 4, 1);
case (GL_COMPRESSED_RGBA_ASTC_5x4_KHR) : return osg::Vec3i(5, 4, 1);
case (GL_COMPRESSED_RGBA_ASTC_5x5_KHR) : return osg::Vec3i(5, 5, 1);
case (GL_COMPRESSED_RGBA_ASTC_6x5_KHR) : return osg::Vec3i(6, 5, 1);
case (GL_COMPRESSED_RGBA_ASTC_6x6_KHR) : return osg::Vec3i(6, 6, 1);
case (GL_COMPRESSED_RGBA_ASTC_8x5_KHR) : return osg::Vec3i(8, 5, 1);
case (GL_COMPRESSED_RGBA_ASTC_8x6_KHR) : return osg::Vec3i(8, 6, 1);
case (GL_COMPRESSED_RGBA_ASTC_8x8_KHR) : return osg::Vec3i(8, 8, 1);
case (GL_COMPRESSED_RGBA_ASTC_10x5_KHR) : return osg::Vec3i(10, 5, 1);
case (GL_COMPRESSED_RGBA_ASTC_10x6_KHR) : return osg::Vec3i(10, 6, 1);
case (GL_COMPRESSED_RGBA_ASTC_10x8_KHR) : return osg::Vec3i(10, 8, 1);
case (GL_COMPRESSED_RGBA_ASTC_10x10_KHR) : return osg::Vec3i(10, 10, 1);
case (GL_COMPRESSED_RGBA_ASTC_12x10_KHR) : return osg::Vec3i(12, 10, 1);
case (GL_COMPRESSED_RGBA_ASTC_12x12_KHR) : return osg::Vec3i(12, 12, 1);
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR) : return osg::Vec3i(4, 4, 1);
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR) : return osg::Vec3i(5, 4, 1);
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR) : return osg::Vec3i(5, 5, 1);
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR) : return osg::Vec3i(6, 5, 1);
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR) : return osg::Vec3i(6, 6, 1);
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR) : return osg::Vec3i(8, 5, 1);
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR) : return osg::Vec3i(8, 6, 1);
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR) : return osg::Vec3i(8, 8, 1);
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR) : return osg::Vec3i(10, 5, 1);
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR) : return osg::Vec3i(10, 6, 1);
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR) : return osg::Vec3i(10, 8, 1);
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR) : return osg::Vec3i(10, 10, 1);
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR) : return osg::Vec3i(12, 10, 1);
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR) : return osg::Vec3i(12, 12, 1);
default:
break;
}
return osg::Vec3i(1,1,1);
}
//returns the max(size of a 2D block in bytes,packing)
unsigned int Image::computeBlockSize(GLenum pixelFormat, GLenum packing)
{
switch(pixelFormat)
@@ -761,6 +906,35 @@ unsigned int Image::computeBlockSize(GLenum pixelFormat, GLenum packing)
case(GL_COMPRESSED_RG11_EAC):
case(GL_COMPRESSED_SIGNED_RG11_EAC):
return osg::maximum(16u,packing); // block size of 16
case (GL_COMPRESSED_RGBA_ASTC_4x4_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_5x4_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_5x5_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_6x5_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_6x6_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_8x5_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_8x6_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_8x8_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_10x5_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_10x6_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_10x8_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_10x10_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_12x10_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_12x12_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR) :
return osg::maximum(16u, packing); // block size of 16
default:
break;
}
@@ -780,29 +954,18 @@ unsigned int Image::computeImageSizeInBytes(int width,int height, int depth, GLe
{
if (width<=0 || height<=0 || depth<=0) return 0;
// Taking advantage of the fact that
// DXT formats are defined as 4 successive numbers:
// GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
// GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
// GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
// GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
if( pixelFormat >= GL_COMPRESSED_RGB_S3TC_DXT1_EXT &&
pixelFormat <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT )
{
width = (width + 3) & ~3;
height = (height + 3) & ~3;
}
// 3dc ATI formats
// GL_COMPRESSED_RED_RGTC1_EXT 0x8DBB
// GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC
// GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD
// GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE
if( pixelFormat >= GL_COMPRESSED_RED_RGTC1_EXT &&
pixelFormat <= GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT )
{
width = (width + 3) & ~3;
height = (height + 3) & ~3;
int blockSize = computeBlockSize(pixelFormat, 0);
if (blockSize > 0) {
osg::Vec3i footprint = computeBlockFootprint(pixelFormat);
width = (width + footprint.x() - 1) / footprint.x();
height = (height + footprint.y() - 1) / footprint.y();
unsigned int size = blockSize * width;
size = roudUpToMultiple(size, packing);
size *= height;
size = roudUpToMultiple(size, slice_packing);
size *= depth;
size = roudUpToMultiple(size, image_packing);
return size;
}
// compute size of one row
@@ -821,6 +984,13 @@ unsigned int Image::computeImageSizeInBytes(int width,int height, int depth, GLe
return osg::maximum( size, computeBlockSize(pixelFormat, packing) );
}
int Image::roudUpToMultiple(int s, int pack) {
if (pack < 2) return s;
s += pack - 1;
s -= s % pack;
return s;
}
int Image::computeNearestPowerOfTwo(int s,float bias)
{
if ((s & (s-1))!=0)
@@ -880,6 +1050,34 @@ bool Image::isCompressed() const
case(GL_COMPRESSED_SIGNED_R11_EAC):
case(GL_COMPRESSED_RG11_EAC):
case(GL_COMPRESSED_SIGNED_RG11_EAC):
case (GL_COMPRESSED_RGBA_ASTC_4x4_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_5x4_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_5x5_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_6x5_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_6x6_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_8x5_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_8x6_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_8x8_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_10x5_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_10x6_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_10x8_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_10x10_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_12x10_KHR) :
case (GL_COMPRESSED_RGBA_ASTC_12x12_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR) :
case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR) :
return true;
default:
return false;
@@ -1189,7 +1387,7 @@ void Image::readImageFromCurrentTexture(unsigned int contextID, bool copyMipMaps
unsigned char* data = new unsigned char[total_size];
if (!data)
{
OSG_WARN<<"Warning: Image::readImageFromCurrentTexture(..) out of memory, now image read."<<std::endl;
OSG_WARN<<"Warning: Image::readImageFromCurrentTexture(..) out of memory, no image read."<<std::endl;
return;
}
@@ -1256,7 +1454,7 @@ void Image::readImageFromCurrentTexture(unsigned int contextID, bool copyMipMaps
unsigned char* data = new unsigned char[total_size];
if (!data)
{
OSG_WARN<<"Warning: Image::readImageFromCurrentTexture(..) out of memory, now image read."<<std::endl;
OSG_WARN<<"Warning: Image::readImageFromCurrentTexture(..) out of memory, no image read."<<std::endl;
return;
}
@@ -1409,8 +1607,38 @@ void Image::copySubImage(int s_offset, int t_offset, int r_offset, const osg::Im
return;
}
void* data_destination = data(s_offset,t_offset,r_offset);
unsigned char* data_destination = data(s_offset, t_offset, r_offset);
if (isCompressed())
{
osg::Vec3i footprint = computeBlockFootprint(_pixelFormat);
if (footprint.x() == 4 && footprint.y() == 4) {
if ((source->s() & 0x3) || (source->t() & 0x3) || (s_offset & 0x3) || (t_offset & 0x3))
{
OSG_WARN << "Error Image::copySubImage() did not succeed : size " << source->s() << "x" << source->t() << " or offset " << s_offset<< "," << t_offset << " not multiple of 4." << std::endl;
return;
}
} else {
if ((source->s() % footprint.x()) || (source->t() % footprint.y()) || (s_offset % footprint.x()) || (t_offset% footprint.y()))
{
OSG_WARN << "Error Image::copySubImage() did not succeed : size " << source->s() << "x" << source->t() << " or offset " << s_offset << "," << t_offset << " not multiple of footprint " << footprint.x() << "x" << footprint.y() << std::endl;
return;
}
}
unsigned int rowWidthInBlocks = (_s + footprint.x() - 1) / footprint.x();
unsigned int blockSize = computeBlockSize(_pixelFormat, 0);
data_destination = _data + blockSize * (rowWidthInBlocks * t_offset + (s_offset / footprint.x()));
unsigned int copy_width = (osg::minimum(source->s(), _s - s_offset) + footprint.x() - 1) / footprint.x();
unsigned int copy_height = (osg::minimum(source->t(), _t - t_offset) + footprint.y() - 1) / footprint.y();
unsigned int dstRowStep = blockSize * rowWidthInBlocks;
unsigned int srcRowStep = blockSize * (source->_s + footprint.x() - 1) / footprint.x();
const unsigned char* data_source = source->data(0, 0, 0);
for (unsigned int row = 0; row < copy_height; row += 1) { //copy blocks in a row, footprint.y() rows at a time
memcpy(data_destination, data_source, copy_width * blockSize);
data_source += srcRowStep;
data_destination += dstRowStep;
}
return;
}
PixelStorageModes psm;
psm.pack_alignment = _packing;
psm.pack_row_length = _rowLength!=0 ? _rowLength : _s;
@@ -1919,24 +2147,29 @@ Vec4 _readColor(GLenum pixelFormat, T* data,float scale)
Vec4 Image::getColor(unsigned int s,unsigned t,unsigned r) const
{
if (dxtc_tool::isDXTC(_pixelFormat)) {
unsigned char color[4];
if (dxtc_tool::CompressedImageGetColor(color, s, t, r, _s, _t, _r, _pixelFormat, _data)) {
return Vec4(((float)color[0]) / 255.0f, ((float)color[1]) / 255.0f, ((float)color[2]) / 255.0f, ((float)color[3]) / 255.0f );
if (isCompressed())
{
if (dxtc_tool::isDXTC(_pixelFormat)) {
unsigned char color[4];
if (dxtc_tool::CompressedImageGetColor(color, s, t, r, _s, _t, _r, _pixelFormat, _data)) {
return Vec4(((float)color[0]) / 255.0f, ((float)color[1]) / 255.0f, ((float)color[2]) / 255.0f, ((float)color[3]) / 255.0f );
}
}
}
const unsigned char* ptr = data(s,t,r);
switch(_dataType)
else
{
case(GL_BYTE): return _readColor(_pixelFormat, (char*)ptr, 1.0f/128.0f);
case(GL_UNSIGNED_BYTE): return _readColor(_pixelFormat, (unsigned char*)ptr, 1.0f/255.0f);
case(GL_SHORT): return _readColor(_pixelFormat, (short*)ptr, 1.0f/32768.0f);
case(GL_UNSIGNED_SHORT): return _readColor(_pixelFormat, (unsigned short*)ptr, 1.0f/65535.0f);
case(GL_INT): return _readColor(_pixelFormat, (int*)ptr, 1.0f/2147483648.0f);
case(GL_UNSIGNED_INT): return _readColor(_pixelFormat, (unsigned int*)ptr, 1.0f/4294967295.0f);
case(GL_FLOAT): return _readColor(_pixelFormat, (float*)ptr, 1.0f);
case(GL_DOUBLE): return _readColor(_pixelFormat, (double*)ptr, 1.0f);
const unsigned char* ptr = data(s,t,r);
switch(_dataType)
{
case(GL_BYTE): return _readColor(_pixelFormat, (char*)ptr, 1.0f/128.0f);
case(GL_UNSIGNED_BYTE): return _readColor(_pixelFormat, (unsigned char*)ptr, 1.0f/255.0f);
case(GL_SHORT): return _readColor(_pixelFormat, (short*)ptr, 1.0f/32768.0f);
case(GL_UNSIGNED_SHORT): return _readColor(_pixelFormat, (unsigned short*)ptr, 1.0f/65535.0f);
case(GL_INT): return _readColor(_pixelFormat, (int*)ptr, 1.0f/2147483648.0f);
case(GL_UNSIGNED_INT): return _readColor(_pixelFormat, (unsigned int*)ptr, 1.0f/4294967295.0f);
case(GL_FLOAT): return _readColor(_pixelFormat, (float*)ptr, 1.0f);
case(GL_DOUBLE): return _readColor(_pixelFormat, (double*)ptr, 1.0f);
}
}
return Vec4(1.0f,1.0f,1.0f,1.0f);
}

View File

@@ -20,6 +20,7 @@
#include <osg/Notify>
#include <osg/io_utils>
#include "dxtctool.h"
namespace osg
{
@@ -716,6 +717,49 @@ OSG_EXPORT osg::Image* createImageWithOrientationConversion(const osg::Image* sr
unsigned int pixelSizeInBits = srcImage->getPixelSizeInBits();
unsigned int pixelSizeInBytes = pixelSizeInBits/8;
unsigned int pixelSizeRemainder = pixelSizeInBits%8;
if (dxtc_tool::isDXTC(srcImage->getPixelFormat()))
{
unsigned int DXTblockSize = 8;
if ((srcImage->getPixelFormat() == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) || (srcImage->getPixelFormat() == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)) DXTblockSize = 16;
unsigned int DXTblocksWidht = (srcImage->s() + 3) / 4;//width in 4x4 blocks
unsigned int DXTblocksHeight = (srcImage->t() + 3) / 4;//height in 4x4 blocks
unsigned int dst_DXTblocksWidht = (width + 3) / 4;//width in 4x4 blocks
unsigned int dst_DXTblocksHeight = (height + 3) / 4;//height in 4x4 blocks
dstImage->allocateImage(width, height, depth, srcImage->getPixelFormat(), srcImage->getDataType());
// copy across the pixels from the source image to the destination image.
if (depth != 1)
{
OSG_NOTICE << "Warning: createImageWithOrientationConversion(..) cannot handle dxt-compressed images with depth." << std::endl;
return const_cast<osg::Image*>(srcImage);
}
for (int l = 0; l<depth; l+=4)
{
for (int r = 0; r<height; r+=4)
{
osg::Vec3i cp(srcOrigin.x() + columnDelta.x()*r + layerDelta.x()*l,
srcOrigin.y() + columnDelta.y()*r + layerDelta.y()*l,
srcOrigin.z() + columnDelta.z()*r + layerDelta.z()*l);
for (int c = 0; c<width; c+=4)
{
unsigned int src_blockIndex = (cp.x() >> 2) + DXTblocksWidht * ((cp.y() >> 2) + (cp.z() >> 2) * DXTblocksHeight);
const unsigned char *src_block = srcImage->data() + src_blockIndex * DXTblockSize;
unsigned int dst_blockIndex = (c >> 2) + dst_DXTblocksWidht * ((r >> 2) + (l >> 2) * dst_DXTblocksHeight);
unsigned char *dst_block = dstImage->data() + dst_blockIndex * DXTblockSize;
memcpy((void *)dst_block, (void *)src_block, DXTblockSize);
osg::Vec3i srcSubOrigin(cp.x() & 0x7, cp.y() & 0x7, cp.z() & 0x7);
dxtc_tool::compressedBlockOrientationConversion(srcImage->getPixelFormat(),src_block, dst_block, srcSubOrigin, rowDelta, columnDelta);
cp.x() += 4 * rowDelta.x();
cp.y() += 4 * rowDelta.y();
cp.z() += 4 * rowDelta.z();
}
}
}
return dstImage.release();
}
if (pixelSizeRemainder!=0)
{
OSG_NOTICE<<"Warning: createImageWithOrientationConversion(..) cannot handle non byte aligned pixel formats."<<std::endl;

View File

@@ -89,6 +89,19 @@ struct NoneOf
const char* _str;
};
// Replaces all occurrences of "from" with the contents of "to"
// It does only one pass, i.e. new matches created in a position before the current match are not replaced
void replaceAll(std::string& str, const std::string& from, const std::string& to)
{
std::string::size_type pos = 0;
while ((pos = str.find(from, pos)) != std::string::npos)
{
str.replace(pos, from.length(), to);
pos += to.length();
}
}
}
using namespace osg;
@@ -642,6 +655,8 @@ void Shader::PerContextShader::compileShader(osg::State& state)
}
else
{
// Convert all windows line endings to \n
replaceAll(source, "\r\n", " \n");
std::string versionLine;
unsigned int lineNum = 0;

View File

@@ -168,10 +168,10 @@ void Texture1D::apply(State& state) const
}
else if (_image.valid() && getModifiedCount(contextID) != _image->getModifiedCount())
{
applyTexImage1D(GL_TEXTURE_1D,_image.get(),state, _textureWidth, _numMipmapLevels);
// update the modified count to show that it is up to date.
getModifiedCount(contextID) = _image->getModifiedCount();
applyTexImage1D(GL_TEXTURE_1D,_image.get(),state, _textureWidth, _numMipmapLevels);
}
}
@@ -206,13 +206,13 @@ void Texture1D::apply(State& state) const
applyTexParameters(GL_TEXTURE_1D,state);
// update the modified count to show that it is upto date.
getModifiedCount(contextID) = _image->getModifiedCount();
applyTexImage1D(GL_TEXTURE_1D,_image.get(),state, _textureWidth, _numMipmapLevels);
textureObject->setAllocated(_numMipmapLevels,_internalFormat,_textureWidth,1,1,0);
// update the modified count to show that it is up to date.
getModifiedCount(contextID) = _image->getModifiedCount();
_textureObjectBuffer[contextID] = textureObject;
// unref image data?

View File

@@ -202,12 +202,11 @@ void Texture2D::apply(State& state) const
}
else if (_image.valid() && getModifiedCount(contextID) != _image->getModifiedCount())
{
applyTexImage2D_subload(state,GL_TEXTURE_2D,_image.get(),
_textureWidth, _textureHeight, _internalFormat, _numMipmapLevels);
// update the modified tag to show that it is up to date.
getModifiedCount(contextID) = _image->getModifiedCount();
applyTexImage2D_subload(state,GL_TEXTURE_2D,_image.get(),
_textureWidth, _textureHeight, _internalFormat, _numMipmapLevels);
}
else if (_readPBuffer.valid())
{
@@ -224,6 +223,8 @@ void Texture2D::apply(State& state) const
applyTexParameters(GL_TEXTURE_2D,state);
if (_image.valid()) getModifiedCount(contextID) = _image->getModifiedCount();
_subloadCallback->load(*this,state);
textureObject->setAllocated(_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,1,_borderWidth);
@@ -235,7 +236,6 @@ void Texture2D::apply(State& state) const
//glBindTexture( GL_TEXTURE_2D, handle );
// update the modified tag to show that it is up to date.
if (_image.valid()) getModifiedCount(contextID) = _image->getModifiedCount();
}
else if (_image.valid() && _image->data())
{
@@ -255,6 +255,9 @@ void Texture2D::apply(State& state) const
applyTexParameters(GL_TEXTURE_2D,state);
// update the modified tag to show that it is up to date.
getModifiedCount(contextID) = image->getModifiedCount();
if (textureObject->isAllocated() && image->supportsTextureSubloading())
{
//OSG_NOTICE<<"Reusing texture object"<<std::endl;
@@ -270,9 +273,6 @@ void Texture2D::apply(State& state) const
textureObject->setAllocated(true);
}
// update the modified tag to show that it is up to date.
getModifiedCount(contextID) = image->getModifiedCount();
// unref image data?
if (isSafeToUnrefImageData(state) && image->getDataVariance()==STATIC)
{

View File

@@ -297,8 +297,8 @@ void Texture2DArray::apply(State& state) const
{
if (getModifiedCount(n,contextID) != image->getModifiedCount())
{
applyTexImage2DArray_subload(state, image, n, _textureWidth, _textureHeight, image->r(), _internalFormat, _numMipmapLevels);
getModifiedCount(n,contextID) = image->getModifiedCount();
applyTexImage2DArray_subload(state, image, n, _textureWidth, _textureHeight, image->r(), _internalFormat, _numMipmapLevels);
}
n += image->r();
}
@@ -380,8 +380,8 @@ void Texture2DArray::apply(State& state) const
{
if (getModifiedCount(n,contextID) != image->getModifiedCount())
{
applyTexImage2DArray_subload(state, image, n, _textureWidth, _textureHeight, image->r(), _internalFormat, _numMipmapLevels);
getModifiedCount(n,contextID) = image->getModifiedCount();
applyTexImage2DArray_subload(state, image, n, _textureWidth, _textureHeight, image->r(), _internalFormat, _numMipmapLevels);
}
n += image->r();
}

View File

@@ -249,12 +249,12 @@ void Texture3D::apply(State& state) const
}
else if (_image.get() && getModifiedCount(contextID) != _image->getModifiedCount())
{
computeRequiredTextureDimensions(state,*_image,_textureWidth, _textureHeight, _textureDepth,_numMipmapLevels);
applyTexImage3D(GL_TEXTURE_3D,_image.get(),state, _textureWidth, _textureHeight, _textureDepth,_numMipmapLevels);
// update the modified count to show that it is up to date.
getModifiedCount(contextID) = _image->getModifiedCount();
computeRequiredTextureDimensions(state,*_image,_textureWidth, _textureHeight, _textureDepth,_numMipmapLevels);
applyTexImage3D(GL_TEXTURE_3D,_image.get(),state, _textureWidth, _textureHeight, _textureDepth,_numMipmapLevels);
}
}
@@ -291,6 +291,8 @@ void Texture3D::apply(State& state) const
textureObject->bind();
// update the modified count to show that it is up to date.
getModifiedCount(contextID) = _image->getModifiedCount();
applyTexParameters(GL_TEXTURE_3D,state);
@@ -298,9 +300,6 @@ void Texture3D::apply(State& state) const
textureObject->setAllocated(_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,_textureDepth,0);
// update the modified count to show that it is up to date.
getModifiedCount(contextID) = _image->getModifiedCount();
// unref image data?
if (isSafeToUnrefImageData(state) && _image->getDataVariance()==STATIC)
{

View File

@@ -163,6 +163,8 @@ void TextureBuffer::apply(State& state) const
const GLExtensions* extensions = state.get<GLExtensions>();
if(_bufferData.valid() &&_modifiedCount[contextID]!=_bufferData->getModifiedCount() )
{
_modifiedCount[contextID]=_bufferData->getModifiedCount() ;
GLBufferObject* glBufferObject = _bufferData->getBufferObject()->getOrCreateGLBufferObject(contextID);
if (glBufferObject)
{
@@ -174,7 +176,6 @@ void TextureBuffer::apply(State& state) const
}
_modifiedCount[contextID]=_bufferData->getModifiedCount() ;
}
textureObject->bind();
@@ -198,6 +199,8 @@ void TextureBuffer::apply(State& state) const
{
const GLExtensions* extensions = state.get<GLExtensions>();
_modifiedCount[contextID] = _bufferData->getModifiedCount();
textureObject = generateAndAssignTextureObject(contextID, GL_TEXTURE_BUFFER);
textureObject->_profile._internalFormat=_internalFormat;
textureObject->bind();
@@ -221,7 +224,6 @@ void TextureBuffer::apply(State& state) const
textureObject->bind();
extensions->glTexBuffer(GL_TEXTURE_BUFFER, _internalFormat, glBufferObject->getGLObjectID());
_modifiedCount[contextID] = _bufferData->getModifiedCount();
}
}

View File

@@ -246,8 +246,8 @@ void TextureCubeMap::apply(State& state) const
const osg::Image* image = _images[n].get();
if (image && getModifiedCount((Face)n,contextID) != image->getModifiedCount())
{
applyTexImage2D_subload( state, faceTarget[n], _images[n].get(), _textureWidth, _textureHeight, _internalFormat, _numMipmapLevels);
getModifiedCount((Face)n,contextID) = image->getModifiedCount();
applyTexImage2D_subload( state, faceTarget[n], _images[n].get(), _textureWidth, _textureHeight, _internalFormat, _numMipmapLevels);
}
}
}
@@ -297,6 +297,7 @@ void TextureCubeMap::apply(State& state) const
const osg::Image* image = _images[n].get();
if (image)
{
getModifiedCount((Face)n,contextID) = image->getModifiedCount();
if (textureObject->isAllocated())
{
applyTexImage2D_subload( state, faceTarget[n], image, _textureWidth, _textureHeight, _internalFormat, _numMipmapLevels);
@@ -305,7 +306,6 @@ void TextureCubeMap::apply(State& state) const
{
applyTexImage2D_load( state, faceTarget[n], image, _textureWidth, _textureHeight, _numMipmapLevels);
}
getModifiedCount((Face)n,contextID) = image->getModifiedCount();
}

View File

@@ -204,10 +204,10 @@ void TextureRectangle::apply(State& state) const
}
else if (_image.valid() && getModifiedCount(contextID) != _image->getModifiedCount())
{
applyTexImage_subload(GL_TEXTURE_RECTANGLE, _image.get(), state, _textureWidth, _textureHeight, _internalFormat);
// update the modified count to show that it is up to date.
getModifiedCount(contextID) = _image->getModifiedCount();
applyTexImage_subload(GL_TEXTURE_RECTANGLE, _image.get(), state, _textureWidth, _textureHeight, _internalFormat);
}
}
else if (_subloadCallback.valid())

View File

@@ -742,7 +742,7 @@ void VertexArrayState::setArray(ArrayDispatch* vad, osg::State& state, GLint siz
}
}
void VertexArrayState::setInterleavedArrays( osg::State& state, GLenum format, GLsizei stride, const GLvoid* pointer)
void VertexArrayState::setInterleavedArrays(osg::State& /*state*/, GLenum format, GLsizei stride, const GLvoid* pointer)
{
#if defined(OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE) && !defined(OSG_GLES1_AVAILABLE)
unbindVertexBufferObject();

View File

@@ -142,7 +142,8 @@ public:
protected:
struct ObjOptionsStruct {
class ObjOptionsStruct {
public:
bool rotate;
bool noTesselateLargePolygons;
bool noTriStripPolygons;
@@ -155,6 +156,17 @@ protected:
TextureAllocationMap textureUnitAllocation;
/// Coordinates precision.
int precision;
ObjOptionsStruct()
{
rotate = true;
noTesselateLargePolygons = false;
noTriStripPolygons = false;
generateFacetNormals = false;
fixBlackMaterials = true;
noReverseFaces = false;
precision = std::numeric_limits<double>::digits10 + 2;
}
};
typedef std::map< std::string, osg::ref_ptr<osg::StateSet> > MaterialToStateSetMap;
@@ -831,13 +843,6 @@ osg::Node* ReaderWriterOBJ::convertModelToSceneGraph(obj::Model& model, ObjOptio
ReaderWriterOBJ::ObjOptionsStruct ReaderWriterOBJ::parseOptions(const osgDB::ReaderWriter::Options* options) const
{
ObjOptionsStruct localOptions;
localOptions.rotate = true;
localOptions.noTesselateLargePolygons = false;
localOptions.noTriStripPolygons = false;
localOptions.generateFacetNormals = false;
localOptions.fixBlackMaterials = true;
localOptions.noReverseFaces = false;
localOptions.precision = std::numeric_limits<double>::digits10 + 2;
if (options!=NULL)
{

View File

@@ -546,7 +546,7 @@ osg::Node* VertexData::readPlyFile( const char* filename, const bool ignoreColor
}
else if (_texcoord.valid())
{
geom->setTexCoordArray(0, _texcoord);
geom->setTexCoordArray(0, _texcoord.get());
}
// If the model has normals, add them to the geometry

View File

@@ -554,7 +554,10 @@ osg::ref_ptr<osg::Program> GeometryPool::getOrCreateProgram(LayerTypes& layerTyp
_programMap[layerTypes] = program;
// add shader that provides the lighting functions
program->addShader(osgDB::readRefShaderFile("shaders/lighting.vert"));
{
#include "shaders/lighting_vert.cpp"
program->addShader(osgDB::readRefShaderFileWithFallback(osg::Shader::VERTEX, "shaders/lighting.vert", lighting_vert));
}
// OSG_NOTICE<<") creating new Program "<<program.get()<<std::endl;
{

View File

@@ -0,0 +1,25 @@
char lighting_vert[] = "#pragma requires(LIGHTING)\n"
"\n"
"void directionalLight( int lightNum, vec3 normal, inout vec4 color )\n"
"{\n"
" vec3 n = normalize(gl_NormalMatrix * normal);\n"
"\n"
" float NdotL = dot( n, normalize(gl_LightSource[lightNum].position.xyz) );\n"
" NdotL = max( 0.0, NdotL );\n"
"\n"
" float NdotHV = dot( n, gl_LightSource[lightNum].halfVector.xyz );\n"
" NdotHV = max( 0.0, NdotHV );\n"
"#if 1\n"
" color *= gl_LightSource[lightNum].ambient +\n"
" gl_LightSource[lightNum].diffuse * NdotL;\n"
"#else\n"
" color *= gl_FrontLightModelProduct.sceneColor +\n"
" gl_FrontLightProduct[lightNum].ambient +\n"
" gl_FrontLightProduct[lightNum].diffuse * NdotL;\n"
"#endif\n"
"#if 0\n"
" if ( NdotL * NdotHV > 0.0 )\n"
" color += gl_FrontLightProduct[lightNum].specular * pow( NdotHV, gl_FrontMaterial.shininess );\n"
"#endif\n"
"}\n"
"\n";

View File

@@ -125,5 +125,5 @@ char terrain_displacement_mapping_vert[] = "#version 120\n"
" vec3 position = gl_Vertex.xyz + gl_Normal.xyz * height_center;\n"
" gl_Position = gl_ModelViewProjectionMatrix * vec4(position,1.0);\n"
"\n"
"};\n"
"}\n"
"\n";

View File

@@ -145,6 +145,39 @@ static bool writeComputeGroups( osgDB::OutputStream& os, const osg::Program& att
return true;
}
static bool checkBindUniformBlock( const osg::Program& node )
{
return true;
}
static bool readBindUniformBlock( osgDB::InputStream& is, osg::Program& p )
{
unsigned int size = 0; is >> size >> is.BEGIN_BRACKET;
std::string name; unsigned int index;
for ( unsigned int i=0; i<size; ++i )
{
is >>name; is >>index;
p.addBindUniformBlock(name, index);
}
is >> is.END_BRACKET;
return true;
}
static bool writeBindUniformBlock( osgDB::OutputStream& os, const osg::Program& p )
{
unsigned int size = p.getUniformBlockBindingList().size();
os << size << os.BEGIN_BRACKET << std::endl;
for(osg::Program::UniformBlockBindingList::const_iterator bbit = p.getUniformBlockBindingList().begin();
bbit != p.getUniformBlockBindingList().end(); ++bbit)
{
os << bbit->first;
os << bbit->second;
}
os << os.END_BRACKET << std::endl;
return true;
}
REGISTER_OBJECT_WRAPPER( Program,
new osg::Program,
osg::Program,
@@ -167,4 +200,8 @@ REGISTER_OBJECT_WRAPPER( Program,
ADD_USER_SERIALIZER( FeedBackVaryingsName );
ADD_USER_SERIALIZER( FeedBackMode );
}
{
UPDATE_TO_VERSION_SCOPED( 150 )
ADD_USER_SERIALIZER( BindUniformBlock );
}
}