Merge branch 'master' into osganimation
This commit is contained in:
@@ -118,7 +118,8 @@ void DisplaySettings::setDisplaySettings(const DisplaySettings& vs)
|
||||
_swapMethod = vs._swapMethod;
|
||||
|
||||
_vertexBufferHint = vs._vertexBufferHint;
|
||||
_shaderHint = vs._shaderHint;
|
||||
|
||||
setShaderHint(_shaderHint);
|
||||
|
||||
_keystoneHint = vs._keystoneHint;
|
||||
_keystoneFileNames = vs._keystoneFileNames;
|
||||
@@ -250,23 +251,17 @@ void DisplaySettings::setDefaults()
|
||||
// _vertexBufferHint = VERTEX_ARRAY_OBJECT;
|
||||
|
||||
#if defined(OSG_GLES3_AVAILABLE)
|
||||
_shaderHint = SHADER_GLES3;
|
||||
OSG_INFO<<"DisplaySettings::SHADER_GLES3"<<std::endl;
|
||||
setShaderHint(SHADER_GLES3);
|
||||
#elif defined(OSG_GLES2_AVAILABLE)
|
||||
_shaderHint = SHADER_GLES2;
|
||||
OSG_INFO<<"DisplaySettings::SHADER_GLES2"<<std::endl;
|
||||
setShaderHint(SHADER_GLES2);
|
||||
#elif defined(OSG_GL3_AVAILABLE)
|
||||
_shaderHint = SHADER_GL3;
|
||||
OSG_INFO<<"DisplaySettings::SHADER_GL3"<<std::endl;
|
||||
setShaderHint(SHADER_GL3);
|
||||
#elif defined(OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE)
|
||||
OSG_INFO<<"DisplaySettings::SHADER_NONE"<<std::endl;
|
||||
_shaderHint = SHADER_NONE;
|
||||
setShaderHint(SHADER_NONE);
|
||||
#else
|
||||
OSG_INFO<<"DisplaySettings::SHADER_GL2"<<std::endl;
|
||||
_shaderHint = SHADER_GL2;
|
||||
setShaderHint(SHADER_GL2);
|
||||
#endif
|
||||
|
||||
|
||||
_keystoneHint = false;
|
||||
|
||||
_OSXMenubarBehavior = MENUBAR_AUTO_HIDE;
|
||||
@@ -390,6 +385,9 @@ static ApplicationUsageProxy DisplaySetting_e31(ApplicationUsage::ENVIRONMENTAL_
|
||||
static ApplicationUsageProxy DisplaySetting_e32(ApplicationUsage::ENVIRONMENTAL_VARIABLE,
|
||||
"OSG_VERTEX_BUFFER_HINT <value>",
|
||||
"Set the hint to what backend osg::Geometry implementation to use. NO_PREFERENCE | VERTEX_BUFFER_OBJECT | VERTEX_ARRAY_OBJECT");
|
||||
static ApplicationUsageProxy DisplaySetting_e33(ApplicationUsage::ENVIRONMENTAL_VARIABLE,
|
||||
"OSG_TEXT_SHADER_TECHNIQUE <value>",
|
||||
"Set the defafult osgText::ShaderTechnique. ALL_FEATURES | ALL | GREYSCALE | SIGNED_DISTANCE_FIELD | SDF | NO_TEXT_SHADER | NONE");
|
||||
|
||||
void DisplaySettings::readEnvironmentalVariables()
|
||||
{
|
||||
@@ -725,26 +723,30 @@ void DisplaySettings::readEnvironmentalVariables()
|
||||
{
|
||||
if (strcmp(ptr,"GL2")==0)
|
||||
{
|
||||
_shaderHint = SHADER_GL2;
|
||||
setShaderHint(SHADER_GL2);
|
||||
}
|
||||
else if (strcmp(ptr,"GL3")==0)
|
||||
{
|
||||
_shaderHint = SHADER_GL3;
|
||||
setShaderHint(SHADER_GL3);
|
||||
}
|
||||
else if (strcmp(ptr,"GLES2")==0)
|
||||
{
|
||||
_shaderHint = SHADER_GLES2;
|
||||
setShaderHint(SHADER_GLES2);
|
||||
}
|
||||
else if (strcmp(ptr,"GLES3")==0)
|
||||
{
|
||||
_shaderHint = SHADER_GLES3;
|
||||
setShaderHint(SHADER_GLES3);
|
||||
}
|
||||
else if (strcmp(ptr,"NONE")==0)
|
||||
{
|
||||
_shaderHint = SHADER_NONE;
|
||||
setShaderHint(SHADER_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
if ((ptr = getenv("OSG_TEXT_SHADER_TECHNIQUE")) != 0)
|
||||
{
|
||||
setTextShaderTechnique(ptr);
|
||||
}
|
||||
|
||||
if( (ptr = getenv("OSG_KEYSTONE")) != 0)
|
||||
{
|
||||
@@ -1098,3 +1100,84 @@ osg::Matrixd DisplaySettings::computeRightEyeViewImplementation(const osg::Matri
|
||||
0.0,0.0,1.0,0.0,
|
||||
-es,0.0,0.0,1.0);
|
||||
}
|
||||
|
||||
void DisplaySettings::setShaderHint(ShaderHint hint, bool setShaderValues)
|
||||
{
|
||||
_shaderHint = hint;
|
||||
if (setShaderValues)
|
||||
{
|
||||
switch(_shaderHint)
|
||||
{
|
||||
case(SHADER_GLES3) :
|
||||
setValue("OSG_GLSL_VERSION", "#version 300 es");
|
||||
setValue("OSG_PRECISION_FLOAT", "precision highp float;");
|
||||
setValue("OSG_VARYING_IN", "in");
|
||||
setValue("OSG_VARYING_OUT", "out");
|
||||
OSG_NOTICE<<"DisplaySettings::SHADER_GLES3"<<std::endl;
|
||||
break;
|
||||
case(SHADER_GLES2) :
|
||||
setValue("OSG_GLSL_VERSION", "");
|
||||
setValue("OSG_PRECISION_FLOAT", "precision highp float;");
|
||||
setValue("OSG_VARYING_IN", "varying");
|
||||
setValue("OSG_VARYING_OUT", "varying");
|
||||
OSG_NOTICE<<"DisplaySettings::SHADER_GLES2"<<std::endl;
|
||||
break;
|
||||
case(SHADER_GL3) :
|
||||
setValue("OSG_GLSL_VERSION", "#version 330");
|
||||
setValue("OSG_PRECISION_FLOAT", "");
|
||||
setValue("OSG_VARYING_IN", "in");
|
||||
setValue("OSG_VARYING_OUT", "out");
|
||||
OSG_NOTICE<<"DisplaySettings::SHADER_GL3"<<std::endl;
|
||||
break;
|
||||
case(SHADER_GL2) :
|
||||
setValue("OSG_GLSL_VERSION", "");
|
||||
setValue("OSG_PRECISION_FLOAT", "");
|
||||
setValue("OSG_VARYING_IN", "varying");
|
||||
setValue("OSG_VARYING_OUT", "varying");
|
||||
OSG_NOTICE<<"DisplaySettings::SHADER_GL2"<<std::endl;
|
||||
break;
|
||||
case(SHADER_NONE) :
|
||||
setValue("OSG_GLSL_VERSION", "");
|
||||
setValue("OSG_PRECISION_FLOAT", "");
|
||||
setValue("OSG_VARYING_IN", "varying");
|
||||
setValue("OSG_VARYING_OUT", "varying");
|
||||
OSG_NOTICE<<"DisplaySettings::NONE"<<std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DisplaySettings::setValue(const std::string& name, const std::string& value)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_valueMapMutex);
|
||||
|
||||
_valueMap[name] = value;
|
||||
}
|
||||
|
||||
bool DisplaySettings::getValue(const std::string& name, std::string& value, bool use_getenv_fallback) const
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_valueMapMutex);
|
||||
|
||||
ValueMap::iterator itr = _valueMap.find(name);
|
||||
if (itr!=_valueMap.end())
|
||||
{
|
||||
value = itr->second;
|
||||
OSG_INFO<<"DisplaySettings::getValue("<<name<<") found existing value = ["<<value<<"]"<<std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!use_getenv_fallback) return false;
|
||||
|
||||
const char* str = getenv(name.c_str());
|
||||
if (str)
|
||||
{
|
||||
OSG_INFO<<"DisplaySettings::getValue("<<name<<") found getenv value = ["<<value<<"]"<<std::endl;
|
||||
_valueMap[name] = value = str;
|
||||
return true;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -1719,7 +1947,7 @@ bool Image::isImageTranslucent() const
|
||||
case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT):
|
||||
case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT):
|
||||
case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT):
|
||||
return dxtc_tool::CompressedImageTranslucent(_s, _t, _pixelFormat, _data);
|
||||
return dxtc_tool::isCompressedImageTranslucent(_s, _t, _pixelFormat, _data);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -1919,18 +2147,29 @@ Vec4 _readColor(GLenum pixelFormat, T* data,float scale)
|
||||
|
||||
Vec4 Image::getColor(unsigned int s,unsigned t,unsigned r) const
|
||||
{
|
||||
const unsigned char* ptr = data(s,t,r);
|
||||
|
||||
switch(_dataType)
|
||||
if (isCompressed())
|
||||
{
|
||||
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);
|
||||
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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
@@ -618,30 +631,32 @@ void Shader::PerContextShader::compileShader(osg::State& state)
|
||||
#endif
|
||||
|
||||
std::string source = _shader->getShaderSource();
|
||||
if (_shader->getType()==osg::Shader::VERTEX && (state.getUseVertexAttributeAliasing() || state.getUseModelViewAndProjectionUniforms()))
|
||||
// if (_shader->getType()==osg::Shader::VERTEX && (state.getUseVertexAttributeAliasing() || state.getUseModelViewAndProjectionUniforms()))
|
||||
{
|
||||
state.convertVertexShaderSourceToOsgBuiltIns(source);
|
||||
}
|
||||
|
||||
|
||||
if (osg::getNotifyLevel()>=osg::INFO)
|
||||
{
|
||||
std::string sourceWithLineNumbers = insertLineNumbers(source);
|
||||
OSG_INFO << "\nCompiling " << _shader->getTypename()
|
||||
<< " source:\n" << sourceWithLineNumbers << std::endl;
|
||||
}
|
||||
|
||||
GLint compiled = GL_FALSE;
|
||||
|
||||
// OSG_NOTICE<<"Compiling PerContextShader "<<this<<" ShaderDefine="<<getDefineString()<<std::endl;
|
||||
// OSG_NOTICE<<"Compiling PerContextShader "<<this<<" DefineString="<<getDefineString()<<std::endl;
|
||||
|
||||
if (_defineStr.empty())
|
||||
{
|
||||
const GLchar* sourceText = reinterpret_cast<const GLchar*>(source.c_str());
|
||||
_extensions->glShaderSource( _glShaderHandle, 1, &sourceText, NULL );
|
||||
|
||||
if (osg::getNotifyLevel()>=osg::INFO)
|
||||
{
|
||||
std::string sourceWithLineNumbers = insertLineNumbers(source);
|
||||
OSG_INFO << "\nCompiling A :" << _shader->getTypename()
|
||||
<< " source:\n" << sourceWithLineNumbers << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Convert all windows line endings to \n
|
||||
replaceAll(source, "\r\n", " \n");
|
||||
|
||||
std::string versionLine;
|
||||
unsigned int lineNum = 0;
|
||||
@@ -675,21 +690,40 @@ void Shader::PerContextShader::compileShader(osg::State& state)
|
||||
|
||||
if (!versionLine.empty())
|
||||
{
|
||||
// OSG_NOTICE<<"Shader::PerContextShader::compileShader() : Found #version, lineNum = "<<lineNum<<" ["<<versionLine<<"] new source = ["<<source<<"]"<<std::endl;
|
||||
const GLchar* sourceText[3];
|
||||
//OSG_NOTICE<<"glShaderSource() ["<<versionLine<<"] "<<std::endl<<"["<<_defineStr<<"], ["<<sourceText<<"]"<<std::endl;
|
||||
sourceText[0] = reinterpret_cast<const GLchar*>(versionLine.c_str());
|
||||
sourceText[1] = reinterpret_cast<const GLchar*>(_defineStr.c_str());
|
||||
sourceText[2] = reinterpret_cast<const GLchar*>(source.c_str());
|
||||
_extensions->glShaderSource( _glShaderHandle, 3, sourceText, NULL );
|
||||
|
||||
if (osg::getNotifyLevel()>=osg::INFO)
|
||||
{
|
||||
std::string sourceWithLineNumbers = insertLineNumbers(versionLine+_defineStr+source);
|
||||
OSG_INFO << "\nCompiling B: " << _shader->getTypename()
|
||||
<< " source:\n" << sourceWithLineNumbers << std::endl;
|
||||
}
|
||||
|
||||
// OSG_NOTICE<<" Version Line : ["<<std::endl<<versionLine<<"]"<<std::endl;
|
||||
// OSG_NOTICE<<" DefineStr : ["<<std::endl<<_defineStr<<"]"<<std::endl;
|
||||
// OSG_NOTICE<<" Source : ["<<std::endl<<source<<"]"<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
const GLchar* sourceText[2];
|
||||
//OSG_NOTICE<<"glShaderSource() ["<<_defineStr<<"], ["<<sourceText<<"]"<<std::endl;
|
||||
sourceText[0] = reinterpret_cast<const GLchar*>(_defineStr.c_str());
|
||||
sourceText[1] = reinterpret_cast<const GLchar*>(source.c_str());
|
||||
_extensions->glShaderSource( _glShaderHandle, 2, sourceText, NULL );
|
||||
|
||||
|
||||
if (osg::getNotifyLevel()>=osg::INFO)
|
||||
{
|
||||
std::string sourceWithLineNumbers = insertLineNumbers(_defineStr+source);
|
||||
OSG_INFO << "\nCompiling C: " << _shader->getTypename()
|
||||
<< " source:\n" << sourceWithLineNumbers << std::endl;
|
||||
}
|
||||
|
||||
// OSG_NOTICE<<" DefineStr : ["<<std::endl<<_defineStr<<"]"<<std::endl;
|
||||
// OSG_NOTICE<<" Source : ["<<std::endl<<source<<"]"<<std::endl;
|
||||
}
|
||||
}
|
||||
_extensions->glCompileShader( _glShaderHandle );
|
||||
|
||||
@@ -1216,13 +1216,69 @@ namespace State_Utils
|
||||
source.insert(declPos, qualifier + declarationPrefix + newStr + std::string(";\n"));
|
||||
}
|
||||
}
|
||||
|
||||
void replaceVar(const osg::State& state, std::string& str, std::string::size_type start_pos, std::string::size_type num_chars)
|
||||
{
|
||||
std::string var_str(str.substr(start_pos+1, num_chars-1));
|
||||
std::string value;
|
||||
if (state.getActiveDisplaySettings()->getValue(var_str, value))
|
||||
{
|
||||
str.replace(start_pos, num_chars, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
str.erase(start_pos, num_chars);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void substitudeEnvVars(const osg::State& state, std::string& str)
|
||||
{
|
||||
std::string::size_type pos = 0;
|
||||
while (pos<str.size() && ((pos=str.find_first_of("$'\"", pos)) != std::string::npos))
|
||||
{
|
||||
if (pos==str.size())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (str[pos]=='"' || str[pos]=='\'')
|
||||
{
|
||||
std::string::size_type start_quote = pos;
|
||||
++pos;
|
||||
pos = str.find(str[start_quote], pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string::size_type start_var = pos;
|
||||
++pos;
|
||||
pos = str.find_first_not_of("ABCDEFGHIJKLMNOPQRTSUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_", pos);
|
||||
std::string var_str;
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
|
||||
replaceVar(state, str, start_var, pos-start_var);
|
||||
pos = start_var;
|
||||
}
|
||||
else
|
||||
{
|
||||
replaceVar(state, str, start_var, str.size()-start_var);
|
||||
pos = start_var;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool State::convertVertexShaderSourceToOsgBuiltIns(std::string& source) const
|
||||
{
|
||||
OSG_INFO<<"State::convertShaderSourceToOsgBuiltIns()"<<std::endl;
|
||||
OSG_DEBUG<<"State::convertShaderSourceToOsgBuiltIns()"<<std::endl;
|
||||
|
||||
OSG_DEBUG<<"++Before Converted source "<<std::endl<<source<<std::endl<<"++++++++"<<std::endl;
|
||||
|
||||
|
||||
State_Utils::substitudeEnvVars(*this, source);
|
||||
|
||||
OSG_INFO<<"++Before Converted source "<<std::endl<<source<<std::endl<<"++++++++"<<std::endl;
|
||||
|
||||
std::string attributeQualifier("attribute ");
|
||||
|
||||
@@ -1279,7 +1335,7 @@ bool State::convertVertexShaderSourceToOsgBuiltIns(std::string& source) const
|
||||
}
|
||||
}
|
||||
|
||||
OSG_INFO<<"-------- Converted source "<<std::endl<<source<<std::endl<<"----------------"<<std::endl;
|
||||
OSG_DEBUG<<"-------- Converted source "<<std::endl<<source<<std::endl<<"----------------"<<std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -118,6 +118,8 @@ struct VertexArrayDispatch : public VertexArrayState::ArrayDispatch
|
||||
{
|
||||
VertexArrayDispatch() {}
|
||||
|
||||
virtual const char* className() const { return "VertexArrayDispatch"; }
|
||||
|
||||
virtual void enable_and_dispatch(osg::State&, const osg::Array* new_array)
|
||||
{
|
||||
VAS_NOTICE<<" VertexArrayDispatch::enable_and_dispatch("<<new_array->getNumElements()<<")"<<std::endl;
|
||||
@@ -171,6 +173,8 @@ struct ColorArrayDispatch : public VertexArrayState::ArrayDispatch
|
||||
{
|
||||
ColorArrayDispatch() {}
|
||||
|
||||
virtual const char* className() const { return "ColorArrayDispatch"; }
|
||||
|
||||
virtual void enable_and_dispatch(osg::State&, const osg::Array* new_array)
|
||||
{
|
||||
VAS_NOTICE<<" ColorArrayDispatch::enable_and_dispatch("<<new_array->getNumElements()<<")"<<std::endl;
|
||||
@@ -225,6 +229,8 @@ struct NormalArrayDispatch : public VertexArrayState::ArrayDispatch
|
||||
{
|
||||
NormalArrayDispatch() {}
|
||||
|
||||
virtual const char* className() const { return "NormalArrayDispatch"; }
|
||||
|
||||
virtual void enable_and_dispatch(osg::State&, const osg::Array* new_array)
|
||||
{
|
||||
VAS_NOTICE<<" NormalArrayDispatch::enable_and_dispatch("<<new_array->getNumElements()<<")"<<std::endl;
|
||||
@@ -286,6 +292,8 @@ struct SecondaryColorArrayDispatch : public VertexArrayState::ArrayDispatch
|
||||
{
|
||||
SecondaryColorArrayDispatch() {}
|
||||
|
||||
virtual const char* className() const { return "SecondaryColorArrayDispatch"; }
|
||||
|
||||
virtual void enable_and_dispatch(osg::State& state, const osg::Array* new_array)
|
||||
{
|
||||
glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
|
||||
@@ -331,6 +339,8 @@ struct FogCoordArrayDispatch : public VertexArrayState::ArrayDispatch
|
||||
{
|
||||
FogCoordArrayDispatch() {}
|
||||
|
||||
virtual const char* className() const { return "FogCoordArrayDispatch"; }
|
||||
|
||||
virtual void enable_and_dispatch(osg::State& state, const osg::Array* new_array)
|
||||
{
|
||||
glEnableClientState(GL_FOG_COORDINATE_ARRAY);
|
||||
@@ -367,6 +377,8 @@ struct TexCoordArrayDispatch : public VertexArrayState::ArrayDispatch
|
||||
{
|
||||
TexCoordArrayDispatch(unsigned int in_unit) : unit(in_unit) {}
|
||||
|
||||
virtual const char* className() const { return "TexCoordArrayDispatch"; }
|
||||
|
||||
virtual void enable_and_dispatch(osg::State& state, const osg::Array* new_array)
|
||||
{
|
||||
VAS_NOTICE<<" TexCoordArrayDispatch::enable_and_dispatch("<<new_array->getNumElements()<<") unit="<<unit<<std::endl;
|
||||
@@ -436,6 +448,8 @@ struct VertexAttribArrayDispatch : public VertexArrayState::ArrayDispatch
|
||||
{
|
||||
VertexAttribArrayDispatch(unsigned int in_unit) : unit(in_unit) {}
|
||||
|
||||
virtual const char* className() const { return "VertexAttribArrayDispatch"; }
|
||||
|
||||
inline void callVertexAttribPointer(GLExtensions* ext, const osg::Array* new_array, const GLvoid * ptr)
|
||||
{
|
||||
if (new_array->getPreserveDataType())
|
||||
@@ -728,11 +742,13 @@ 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)
|
||||
lazyDisablingOfVertexAttributes();
|
||||
applyDisablingOfVertexAttributes(state);
|
||||
unbindVertexBufferObject();
|
||||
|
||||
//lazyDisablingOfVertexAttributes();
|
||||
//applyDisablingOfVertexAttributes(state);
|
||||
|
||||
glInterleavedArrays( format, stride, pointer);
|
||||
#else
|
||||
|
||||
@@ -166,11 +166,28 @@ struct DXT1TexelsBlock
|
||||
unsigned short color_1; // extreme
|
||||
unsigned int texels4x4; // interpolated colors (2 bits per texel)
|
||||
};
|
||||
|
||||
bool CompressedImageTranslucent(size_t width, size_t height, GLenum format, void * imageData)
|
||||
struct DXT3TexelsBlock
|
||||
{
|
||||
// OSG_NOTICE<<"CompressedImageTranslucent("<<width<<", "<<height<<", "<<format<<", "<<imageData<<")"<<std::endl;
|
||||
unsigned short alpha4[4]; // alpha values (4 bits per texel) - 64 bits
|
||||
unsigned short color_0; // colors at their
|
||||
unsigned short color_1; // extreme
|
||||
unsigned int texels4x4; // interpolated colors (2 bits per texel)
|
||||
};
|
||||
|
||||
struct DXT5TexelsBlock
|
||||
{
|
||||
unsigned char alpha_0; // alpha at their
|
||||
unsigned char alpha_1; // extreme
|
||||
unsigned char alpha3[6]; // alpha index values (3 bits per texel)
|
||||
unsigned short color_0; // colors at their
|
||||
unsigned short color_1; // extreme
|
||||
unsigned int texels4x4; // interpolated colors (2 bits per texel)
|
||||
};
|
||||
|
||||
bool isCompressedImageTranslucent(size_t width, size_t height, GLenum format, void * imageData)
|
||||
{
|
||||
// OSG_NOTICE<<"isCompressedImageTranslucent("<<width<<", "<<height<<", "<<format<<", "<<imageData<<")"<<std::endl;
|
||||
int blockCount = ((width + 3) >> 2) * ((height + 3) >> 2);
|
||||
switch(format)
|
||||
{
|
||||
case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT):
|
||||
@@ -182,9 +199,8 @@ bool CompressedImageTranslucent(size_t width, size_t height, GLenum format, void
|
||||
|
||||
// Only do the check on the first mipmap level, and stop when we
|
||||
// see the first alpha texel
|
||||
int i = (width*height)/16;
|
||||
bool foundAlpha = false;
|
||||
while ((!foundAlpha) && (i>0))
|
||||
int i = blockCount;
|
||||
while (i>0)
|
||||
{
|
||||
// See if this block might contain transparent texels
|
||||
if (texelsBlock->color_0<=texelsBlock->color_1)
|
||||
@@ -192,7 +208,7 @@ bool CompressedImageTranslucent(size_t width, size_t height, GLenum format, void
|
||||
// Scan the texels block for the '11' bit pattern that
|
||||
// indicates a transparent texel
|
||||
int j = 0;
|
||||
while ((!foundAlpha) && (j < 32))
|
||||
while (j < 32)
|
||||
{
|
||||
// Check for the '11' bit pattern on this texel
|
||||
if ( ((texelsBlock->texels4x4 >> j) & 0x03) == 0x03)
|
||||
@@ -214,11 +230,67 @@ bool CompressedImageTranslucent(size_t width, size_t height, GLenum format, void
|
||||
}
|
||||
|
||||
case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT):
|
||||
return true;
|
||||
|
||||
{
|
||||
const DXT3TexelsBlock *texelsBlock = reinterpret_cast<const DXT3TexelsBlock*>(imageData);
|
||||
// Only do the check on the first mipmap level, and stop when we see the first alpha texel
|
||||
int i = blockCount;
|
||||
while (i>0)
|
||||
{
|
||||
for (int j =0; j < 4; ++j)
|
||||
if ( texelsBlock->alpha4[j] != 0xFFFF) //4 pixels at once
|
||||
return true; //not fully opaque
|
||||
// Next block
|
||||
--i;
|
||||
++texelsBlock;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT):
|
||||
return true;
|
||||
{
|
||||
const DXT5TexelsBlock *texelsBlock = reinterpret_cast<const DXT5TexelsBlock*>(imageData);
|
||||
// Only do the check on the first mipmap level, and stop when we see the first alpha texel
|
||||
int i = blockCount;
|
||||
unsigned char alphaBlock[8];
|
||||
while (i>0)
|
||||
{
|
||||
bool eightStep = texelsBlock->alpha_0 > texelsBlock->alpha_1;
|
||||
alphaBlock[0] = texelsBlock->alpha_0;
|
||||
alphaBlock[1] = texelsBlock->alpha_1;
|
||||
if (eightStep) {
|
||||
if (texelsBlock->alpha_0 < 255) return true; //not fully opaque
|
||||
alphaBlock[2] = (6 * alphaBlock[0] + 1 * alphaBlock[1] + 3) / 7; // bit code 010
|
||||
alphaBlock[3] = (5 * alphaBlock[0] + 2 * alphaBlock[1] + 3) / 7; // bit code 011
|
||||
alphaBlock[4] = (4 * alphaBlock[0] + 3 * alphaBlock[1] + 3) / 7; // bit code 100
|
||||
alphaBlock[5] = (3 * alphaBlock[0] + 4 * alphaBlock[1] + 3) / 7; // bit code 101
|
||||
alphaBlock[6] = (2 * alphaBlock[0] + 5 * alphaBlock[1] + 3) / 7; // bit code 110
|
||||
alphaBlock[7] = (1 * alphaBlock[0] + 6 * alphaBlock[1] + 3) / 7; // bit code 111
|
||||
} else {
|
||||
alphaBlock[2] = (4 * alphaBlock[0] + 1 * alphaBlock[1] + 2) / 5; // bit code 010
|
||||
alphaBlock[3] = (3 * alphaBlock[0] + 2 * alphaBlock[1] + 2) / 5; // bit code 011
|
||||
alphaBlock[4] = (2 * alphaBlock[0] + 3 * alphaBlock[1] + 2) / 5; // bit code 100
|
||||
alphaBlock[5] = (1 * alphaBlock[0] + 4 * alphaBlock[1] + 2) / 5; // bit code 101
|
||||
alphaBlock[6] = 0; // bit code 110
|
||||
alphaBlock[7] = 255; // bit code 111
|
||||
}
|
||||
|
||||
int last_added_byte = 1;
|
||||
unsigned short running_a_index = texelsBlock->alpha3[0] + (((unsigned short)texelsBlock->alpha3[last_added_byte]) << 8);
|
||||
for (int j = 0; j < 16; ++j) {
|
||||
unsigned char alphaIndex = running_a_index & 0x7;
|
||||
if (alphaBlock[alphaIndex] < 255) return true; //not fully opaque
|
||||
running_a_index >>= 3;
|
||||
if ((3 * j / 8) == last_added_byte) {
|
||||
++last_added_byte;
|
||||
//(&texelsBlock->alpha3[0]) to avoid gcc warning: array subscript is above array bounds [-Warray-bounds]
|
||||
running_a_index += (((unsigned short)(&(texelsBlock->alpha3[0]))[last_added_byte]) << (8 - (3 * j & 0x7)));
|
||||
}
|
||||
}
|
||||
// Next block
|
||||
--i;
|
||||
++texelsBlock;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -226,4 +298,361 @@ bool CompressedImageTranslucent(size_t width, size_t height, GLenum format, void
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned short interpolateColors21(unsigned short color1, unsigned short color2) {
|
||||
unsigned short result = (((color1 >> 11) * 2 + (color2 >> 11) + 1) / 3) << 11;
|
||||
result += (((color1 >> 5 & 0x3F) * 2 + (color2 >> 5 & 0x3F) + 1) / 3) << 5;
|
||||
result += (((color1 & 0x1F) * 2 + (color2 & 0x1F) + 1) / 3);
|
||||
return result;
|
||||
}
|
||||
unsigned short interpolateColors11(unsigned short color1, unsigned short color2) {
|
||||
unsigned short result = (((color1 >> 11) + (color2 >> 11) ) / 2) << 11;
|
||||
result += (((color1 >> 5 & 0x3F) + (color2 >> 5 & 0x3F)) / 2) << 5;
|
||||
result += (((color1 & 0x1F) + (color2 & 0x1F) ) / 2);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool CompressedImageGetColor(unsigned char color[4], unsigned int s, unsigned int t, unsigned int r, int width, int height, int depth, GLenum format, unsigned char *imageData)
|
||||
{
|
||||
unsigned short color16 = 0;//RGB 5:6:5 format
|
||||
|
||||
|
||||
unsigned int slab4Count = (depth & ~0x3); //4*floor(d/4)
|
||||
unsigned int col = (s >> 2);//(floor(x/4)
|
||||
unsigned int row = (t >> 2);//(floor(y/4)
|
||||
unsigned int blockWidth = (width + 3) >> 2;//ceil(w/4)
|
||||
unsigned int blockHeight = (height + 3) >> 2;//ceil(h/4)
|
||||
int blockNumber = col + blockWidth * row ; // block to jump to
|
||||
|
||||
if (depth > 1) {
|
||||
// https://www.opengl.org/registry/specs/NV/texture_compression_vtc.txt
|
||||
// if (z >= 4*floor(d/4)) {
|
||||
// blockIndex = blocksize * (ceil(w/4) * ceil(h/4) * 4*floor(d/4) + floor(x/4) + ceil(w/4) * (floor(y/4) + ceil(h/4) * (z-4*floor(d/4)) ));
|
||||
// } else {
|
||||
// blockIndex = blocksize * 4 * (floor(x/4) + ceil(w/4) * (floor(y/4) + ceil(h/4) * floor(z/4)));
|
||||
// }
|
||||
// note floor(a/4) = (a >> 2)
|
||||
// note 4*floor(a/4) = a & ~0x3
|
||||
// note ceil(a/4) = ((a + 3) >> 2)
|
||||
//
|
||||
// rewrite: this describes the final blocks as consecutive 4x4x1 blocks - and thats not in the wording of the specs
|
||||
// if (r >= slab4Count) {
|
||||
// blockNumber = (blockWidth * blockHeight * slab4Count + col + blockWidth * (row + blockHeight * (r-slab4Count) ));
|
||||
// } else {
|
||||
// blockNumber = 4 * (col + blockWidth * (row + blockHeight * (r >> 2)) );
|
||||
// }
|
||||
|
||||
// or in the version of the openGL specs:
|
||||
// if (z >= 4*floor(d/4)) {
|
||||
// blockIndex = blocksize * (ceil(w/4) * ceil(h/4) * 4*floor(d/4) + (z - 4*floor(d/4)) * ( (floor(x/4) + ceil(w/4) * (floor(y/4) );
|
||||
// } else {
|
||||
// blockIndex = blocksize * 4 * (floor(x/4) + ceil(w/4) * (floor(y/4) + ceil(h/4) * floor(z/4)));
|
||||
// }
|
||||
|
||||
unsigned int sub_r = r & 0x3;//(r-slab4Count)
|
||||
if (r >= slab4Count) { //slice number beyond 4x4x4 slabs
|
||||
unsigned int blockDepth = depth & 0x3;// equals: depth - slab4Count;//depth of this final block: 1/2/3 in case of 4x4x1; 4x4x2 or 4x4x3 bricks
|
||||
blockNumber = (blockWidth * blockHeight * slab4Count //jump full 4x4x4 slabs
|
||||
+ blockDepth * ( col + blockWidth * row )
|
||||
+ sub_r);
|
||||
} else {
|
||||
blockNumber = 4 * (col + blockWidth * (row + blockHeight * (r >> 2)) ) + sub_r;
|
||||
}
|
||||
}
|
||||
|
||||
int sub_s = s & 0x3;
|
||||
int sub_t = t & 0x3;
|
||||
switch (format)
|
||||
{
|
||||
case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT) :
|
||||
case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) :
|
||||
{
|
||||
const DXT1TexelsBlock *texelsBlock = reinterpret_cast<const DXT1TexelsBlock*>(imageData);
|
||||
texelsBlock += blockNumber; //jump to block
|
||||
char index = (texelsBlock->texels4x4 >> (2 * sub_s + 8 * sub_t)) & 0x3; //two bit "index value"
|
||||
color[3] = 255;
|
||||
switch (index) {
|
||||
case 0:
|
||||
color16 = texelsBlock->color_0;
|
||||
break;
|
||||
case 1:
|
||||
color16 = texelsBlock->color_1;
|
||||
break;
|
||||
case 2:
|
||||
if (texelsBlock->color_0 > texelsBlock->color_1) {
|
||||
color16 = interpolateColors21(texelsBlock->color_0, texelsBlock->color_1);
|
||||
}
|
||||
else {
|
||||
color16 = interpolateColors11(texelsBlock->color_0, texelsBlock->color_1);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (texelsBlock->color_0 > texelsBlock->color_1) {
|
||||
color16 = interpolateColors21(texelsBlock->color_1, texelsBlock->color_0);
|
||||
}
|
||||
else {
|
||||
color16 = 0;//black
|
||||
if (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) color[3] = 0;//transparent
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) :
|
||||
{
|
||||
const DXT3TexelsBlock *texelsBlock = reinterpret_cast<const DXT3TexelsBlock*>(imageData);
|
||||
texelsBlock += blockNumber; //jump to block
|
||||
color[3] = 17 * (texelsBlock->alpha4[sub_t] >> 4 * sub_s & 0xF);
|
||||
char index = (texelsBlock->texels4x4 >> (2 * sub_s + 8 * sub_t)) & 0x3; //two bit "index value"
|
||||
switch (index) {
|
||||
case 0:
|
||||
color16 = texelsBlock->color_0;
|
||||
break;
|
||||
case 1:
|
||||
color16 = texelsBlock->color_1;
|
||||
break;
|
||||
case 2:
|
||||
color16 = interpolateColors21(texelsBlock->color_0, texelsBlock->color_1);
|
||||
break;
|
||||
case 3:
|
||||
color16 = interpolateColors21(texelsBlock->color_1, texelsBlock->color_0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) :
|
||||
{
|
||||
const DXT5TexelsBlock *texelsBlock = reinterpret_cast<const DXT5TexelsBlock*>(imageData);
|
||||
texelsBlock += blockNumber; //jump to block
|
||||
char index = (texelsBlock->texels4x4 >> (2 * sub_s + 8 * sub_t)) & 0x3; //two bit "index value"
|
||||
switch (index) {
|
||||
case 0:
|
||||
color16 = texelsBlock->color_0;
|
||||
break;
|
||||
case 1:
|
||||
color16 = texelsBlock->color_1;
|
||||
break;
|
||||
case 2:
|
||||
color16 = interpolateColors21(texelsBlock->color_0, texelsBlock->color_1);
|
||||
break;
|
||||
case 3:
|
||||
color16 = interpolateColors21(texelsBlock->color_1, texelsBlock->color_0);
|
||||
break;
|
||||
}
|
||||
char pixel = sub_s + 4 * sub_t;//pixel number in block: 0 - 15
|
||||
char firstBit = 3 * pixel;//least significant bit: range 0 - 45
|
||||
unsigned char alpha_index;
|
||||
if ((firstBit & 0x7) < 6) {
|
||||
alpha_index = texelsBlock->alpha3[firstBit >> 3] >> (firstBit & 0x7) & 0x7;//grab byte containing least significant bit; shift and get 3 bits
|
||||
} else {
|
||||
alpha_index = texelsBlock->alpha3[firstBit >> 3] >> (firstBit & 0x7);
|
||||
alpha_index |= texelsBlock->alpha3[1 + (firstBit >> 3)] << (8 - (firstBit & 0x7));
|
||||
alpha_index &= 0x7;
|
||||
}
|
||||
if (alpha_index == 0) {
|
||||
color[3] = texelsBlock->alpha_0;
|
||||
} else {
|
||||
if (alpha_index == 1) {
|
||||
color[3] = texelsBlock->alpha_1;
|
||||
} else {
|
||||
if (texelsBlock->alpha_0 > texelsBlock->alpha_1) {
|
||||
color[3] = ((unsigned short)texelsBlock->alpha_0 * (8 - alpha_index) + (unsigned short)texelsBlock->alpha_1 * (alpha_index - 1) + 3) / 7;
|
||||
} else {
|
||||
if (alpha_index < 6) {
|
||||
color[3] = ((unsigned short)texelsBlock->alpha_0 * (6 - alpha_index) + (unsigned short)texelsBlock->alpha_1 * (alpha_index - 1) + 3) / 5;
|
||||
} else {
|
||||
if (alpha_index == 6) {
|
||||
color[3] = 0;
|
||||
} else {
|
||||
color[3] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
unsigned short colorChannel = color16 >> 11;//red - 5 bits
|
||||
color[0] = colorChannel << 3 | colorChannel >> 2 ;
|
||||
colorChannel = color16 >> 5 & 0x3F;//green - 6 bits
|
||||
color[1] = colorChannel << 2 | colorChannel >> 3;
|
||||
colorChannel = color16 & 0x1F;//blue - 5 bits
|
||||
color[2] = colorChannel << 3 | colorChannel >> 2;
|
||||
return true;
|
||||
}
|
||||
void compressedBlockOrientationConversion(const GLenum format, const unsigned char *src_block, unsigned char *dst_block, const osg::Vec3i& srcOrigin, const osg::Vec3i& rowDelta, const osg::Vec3i& columnDelta)
|
||||
{
|
||||
unsigned int src_texels4x4;
|
||||
unsigned int *dst_texels4x4 = NULL;
|
||||
switch (format)
|
||||
{
|
||||
case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT) :
|
||||
case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) :
|
||||
{
|
||||
const DXT1TexelsBlock *src_texelsBlock = reinterpret_cast<const DXT1TexelsBlock*>(src_block);
|
||||
//make a copy as source might be equal to destination
|
||||
src_texels4x4 = src_texelsBlock->texels4x4; // interpolated colors (2 bits per texel)
|
||||
DXT1TexelsBlock *dst_texelsBlock = reinterpret_cast<DXT1TexelsBlock*>(dst_block);
|
||||
dst_texels4x4 = &dst_texelsBlock->texels4x4;
|
||||
|
||||
break;
|
||||
}
|
||||
case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) :
|
||||
{
|
||||
const DXT3TexelsBlock *src_texelsBlock = reinterpret_cast<const DXT3TexelsBlock*>(src_block);
|
||||
//make a copy as source might be equal to destination
|
||||
src_texels4x4 = src_texelsBlock->texels4x4; // interpolated colors (2 bits per texel)
|
||||
DXT3TexelsBlock *dst_texelsBlock = reinterpret_cast<DXT3TexelsBlock*>(dst_block);
|
||||
dst_texels4x4 = &dst_texelsBlock->texels4x4;
|
||||
unsigned short src_alpha4[4]; // alpha values (4 bits per texel) - 64 bits
|
||||
|
||||
memcpy(src_alpha4, src_texelsBlock->alpha4, 4 * sizeof(unsigned short));//make a copy as source might be equal to destination
|
||||
|
||||
memset(dst_texelsBlock->alpha4, 0, 4 * sizeof(unsigned short)); //clear
|
||||
osg::Vec3i source_pixel(srcOrigin);
|
||||
for (int r = 0; r<4; r++)//rows
|
||||
{
|
||||
for (int c = 0; c<4; c++)//columns
|
||||
{
|
||||
int sub_s = source_pixel.x() & 0x3;
|
||||
int sub_t = source_pixel.y() & 0x3;
|
||||
int shiftBits = 4 * sub_s;
|
||||
unsigned int alpha_value = src_alpha4[sub_t] >> shiftBits & 0xf; //four bit alpha values
|
||||
|
||||
shiftBits = 4 * c;//destination
|
||||
alpha_value <<= shiftBits;
|
||||
dst_texelsBlock->alpha4[r] |= alpha_value;
|
||||
|
||||
source_pixel = source_pixel + rowDelta;
|
||||
}
|
||||
source_pixel = source_pixel + columnDelta;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) :
|
||||
{
|
||||
const DXT5TexelsBlock *src_texelsBlock = reinterpret_cast<const DXT5TexelsBlock*>(src_block);
|
||||
//make a copy as source might be equal to destination
|
||||
src_texels4x4 = src_texelsBlock->texels4x4; // interpolated colors (2 bits per texel)
|
||||
DXT5TexelsBlock *dst_texelsBlock = reinterpret_cast<DXT5TexelsBlock*>(dst_block);
|
||||
dst_texels4x4 = &dst_texelsBlock->texels4x4;
|
||||
|
||||
unsigned char src_alpha3[6]; // alpha index values (3 bits per texel)
|
||||
|
||||
memcpy(src_alpha3, src_texelsBlock->alpha3, 6 * sizeof(unsigned char));//make a copy as source might be equal to destination
|
||||
|
||||
memset(dst_texelsBlock->alpha3, 0, 6 * sizeof(unsigned char)); //clear
|
||||
osg::Vec3i source_pixel(srcOrigin);
|
||||
unsigned int last_added_byte = 1;
|
||||
unsigned short running_a_index = src_texelsBlock->alpha3[0] + (((unsigned short)src_texelsBlock->alpha3[last_added_byte]) << 8);
|
||||
unsigned int j = 0;
|
||||
for (int r = 0; r<4; r++)//rows
|
||||
{
|
||||
for (int c = 0; c<4; c++)//columns
|
||||
{
|
||||
int sub_s = source_pixel.x() & 0x3;
|
||||
int sub_t = source_pixel.y() & 0x3;
|
||||
|
||||
unsigned char alphaIndex = running_a_index & 0x7;
|
||||
//store alphaIndex in output position:
|
||||
int shiftBits = 3 * sub_s + 12 * sub_t;//LSB
|
||||
dst_texelsBlock->alpha3[shiftBits >> 3] |= alphaIndex << (shiftBits & 0x7);
|
||||
if ((shiftBits & 0x7) > 5) {
|
||||
dst_texelsBlock->alpha3[1 + (shiftBits >> 3)] |= alphaIndex >> (8 - (shiftBits & 0x7));
|
||||
}
|
||||
|
||||
running_a_index >>= 3;
|
||||
if ((3 * ++j / 8) == last_added_byte) {
|
||||
++last_added_byte;
|
||||
//(&texelsBlock->alpha3[0]) to avoid gcc warning: array subscript is above array bounds [-Warray-bounds]
|
||||
running_a_index += (((unsigned short)(&(src_texelsBlock->alpha3[0]))[last_added_byte]) << (8 - (3 * j & 0x7)));
|
||||
}
|
||||
source_pixel = source_pixel + rowDelta;
|
||||
}
|
||||
source_pixel = source_pixel + columnDelta;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}//switch
|
||||
|
||||
//all formats: rearrange the colors
|
||||
*dst_texels4x4 = 0;//clear
|
||||
osg::Vec3i source_pixel(srcOrigin);
|
||||
for (int r = 0; r<4; r++)//rows
|
||||
{
|
||||
for (int c = 0; c<4; c++)//columns
|
||||
{
|
||||
int sub_s = source_pixel.x() & 0x3;
|
||||
int sub_t = source_pixel.y() & 0x3;
|
||||
int shiftBits = 2 * sub_s + 8 * sub_t;
|
||||
unsigned int index = (src_texels4x4 >> (shiftBits)) & 0x3; //two bit "index value"
|
||||
|
||||
shiftBits = 2 * c + 8 * r;//destination
|
||||
index <<= shiftBits;
|
||||
*dst_texels4x4 |= index;
|
||||
|
||||
source_pixel = source_pixel + rowDelta;
|
||||
}
|
||||
source_pixel = source_pixel + columnDelta;
|
||||
}
|
||||
}
|
||||
|
||||
void compressedBlockStripAlhpa(const GLenum format, const unsigned char *src_block, unsigned char *dst_block) {
|
||||
unsigned int src_texels4x4;
|
||||
char reshuffle[4] = { 1, 0, 3, 2 };
|
||||
switch (format)
|
||||
{
|
||||
default:
|
||||
case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT) :
|
||||
case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) :
|
||||
{
|
||||
const DXT1TexelsBlock *src_texelsBlock = reinterpret_cast<const DXT1TexelsBlock*>(src_block);
|
||||
//make a copy as source might be equal to destination
|
||||
src_texels4x4 = src_texelsBlock->texels4x4; // interpolated colors (2 bits per texel)
|
||||
DXT1TexelsBlock *dst_texelsBlock = reinterpret_cast<DXT1TexelsBlock*>(dst_block);
|
||||
if (src_texelsBlock->color_0 > src_texelsBlock->color_1) {
|
||||
// Four-color block
|
||||
memcpy(dst_texelsBlock, src_texelsBlock, sizeof(DXT1TexelsBlock));
|
||||
} else {
|
||||
dst_texelsBlock->color_0 = src_texelsBlock->color_1;
|
||||
dst_texelsBlock->color_1 = src_texelsBlock->color_0;
|
||||
dst_texelsBlock->texels4x4 = 0;
|
||||
for (unsigned int shiftBits = 0; shiftBits < 32; shiftBits += 2) {
|
||||
unsigned char index = src_texels4x4 >> shiftBits & 0x3; //two bit "index value"
|
||||
dst_texelsBlock->texels4x4 |= reshuffle[index] << shiftBits;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) :
|
||||
case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) :
|
||||
{
|
||||
const DXT3TexelsBlock *src_texelsBlock = reinterpret_cast<const DXT3TexelsBlock*>(src_block);
|
||||
//make a copy as source might be equal to destination
|
||||
src_texels4x4 = src_texelsBlock->texels4x4; // interpolated colors (2 bits per texel)
|
||||
DXT1TexelsBlock *dst_texelsBlock = reinterpret_cast<DXT1TexelsBlock*>(dst_block);
|
||||
if (src_texelsBlock->color_0 > src_texelsBlock->color_1) {
|
||||
// Four-color block
|
||||
memcpy(dst_texelsBlock, src_texelsBlock, sizeof(DXT3TexelsBlock));
|
||||
}
|
||||
else {
|
||||
dst_texelsBlock->color_0 = src_texelsBlock->color_1;
|
||||
dst_texelsBlock->color_1 = src_texelsBlock->color_0;
|
||||
dst_texelsBlock->texels4x4 = 0;
|
||||
for (unsigned int shiftBits = 0; shiftBits < 32; shiftBits += 2) {
|
||||
unsigned char index = src_texels4x4 >> shiftBits & 0x3; //two bit "index value"
|
||||
dst_texelsBlock->texels4x4 |= reshuffle[index] << shiftBits;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace dxtc_tool
|
||||
|
||||
@@ -31,17 +31,18 @@
|
||||
// Current version: 1.00 BETA 1 (27/08/2002)
|
||||
//
|
||||
// Comment: Only works with DXTC mode supported by OpenGL.
|
||||
// (currently: DXT1/DXT3/DXT5)
|
||||
// (currently: DXT1/DXT3/DXT5)
|
||||
//
|
||||
// History: -
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef DXTCTOOL_H
|
||||
#define DXTCTOOL_H
|
||||
#define DXTCTOOL_H
|
||||
|
||||
#include <osg/GL>
|
||||
#include <osg/Texture>
|
||||
#include <osg/Vec3i>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
@@ -78,10 +79,19 @@ bool isDXTC(GLenum pixelFormat);
|
||||
|
||||
bool VerticalFlip(size_t Width, size_t Height, GLenum Format, void * pPixels);
|
||||
|
||||
bool CompressedImageTranslucent(size_t Width, size_t Height, GLenum Format, void * pPixels);
|
||||
bool isCompressedImageTranslucent(size_t Width, size_t Height, GLenum Format, void * pPixels);
|
||||
|
||||
//interpolate RGB565 colors with 2/3 part color1 and 1/3 part color2
|
||||
unsigned short interpolateColors21(unsigned short color1, unsigned short color2);
|
||||
//interpolate RGB565 colors with equal weights
|
||||
unsigned short interpolateColors11(unsigned short color1, unsigned short color2);
|
||||
|
||||
// Class holding reference to DXTC image pixels
|
||||
bool CompressedImageGetColor(unsigned char color[4], unsigned int s, unsigned int t, unsigned int r, int width, int height, int depth, GLenum format, unsigned char *imageData);
|
||||
|
||||
void compressedBlockOrientationConversion(const GLenum format, const unsigned char *src_block, unsigned char *dst_block, const osg::Vec3i& srcOrigin, const osg::Vec3i& rowDelta, const osg::Vec3i& columnDelta);
|
||||
|
||||
void compressedBlockStripAlhpa(const GLenum format, const unsigned char *src_block, unsigned char *dst_block);
|
||||
// Class holding reference to DXTC image pixels
|
||||
class dxtc_pixels
|
||||
{
|
||||
public:
|
||||
@@ -102,7 +112,7 @@ protected:
|
||||
inline bool SupportedFormat() const;
|
||||
|
||||
// Vertical flipping functions
|
||||
void VFlip_DXT1() const;
|
||||
void VFlip_DXT1() const;
|
||||
void VFlip_DXT3() const;
|
||||
void VFlip_DXT5() const;
|
||||
|
||||
@@ -116,7 +126,7 @@ protected:
|
||||
inline void BVF_Alpha_DXT5_H2(void * const pBlock) const; // V. flip one alpha (DXT5) block with its virtual height == 2
|
||||
inline void BVF_Alpha_DXT5_H4(void * const pBlock) const; // V. flip one alpha (DXT5) block with its virtual height == 4
|
||||
inline void BVF_Alpha_DXT5(void * const pBlock1, void * const pBlock2) const; // V. flip and swap two alpha (DXT5) blocks, with their virtual height == 4
|
||||
|
||||
|
||||
// Block localization functions
|
||||
inline void * GetBlock(size_t i, size_t j, size_t BlockSize) const;
|
||||
|
||||
@@ -155,7 +165,7 @@ inline bool isDXTC(GLenum pixelFormat)
|
||||
}
|
||||
|
||||
inline bool VerticalFlip(size_t Width, size_t Height, GLenum Format, void * pPixels) {
|
||||
return (dxtc_pixels(Width, Height, Format, pPixels)).VFlip();
|
||||
return (dxtc_pixels(Width, Height, Format, pPixels)).VFlip();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -16,21 +16,14 @@
|
||||
|
||||
using namespace osgDB;
|
||||
|
||||
static long long prev_tellg = 0;
|
||||
|
||||
void InputIterator::checkStream() const
|
||||
{
|
||||
if (_in->rdstate()&_in->failbit)
|
||||
{
|
||||
OSG_NOTICE<<"InputIterator::checkStream() : _in->rdstate() "<<_in->rdstate()<<", "<<_in->failbit<<std::endl;
|
||||
OSG_NOTICE<<" _in->tellg() = "<<_in->tellg()<<std::endl;
|
||||
OSG_NOTICE<<" prev_tellg = "<<prev_tellg<<std::endl;
|
||||
_failed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev_tellg = _in->tellg();
|
||||
}
|
||||
}
|
||||
|
||||
void InputIterator::readComponentArray( char* s, unsigned int numElements, unsigned int numComponentsPerElements, unsigned int componentSizeInBytes)
|
||||
|
||||
@@ -278,19 +278,6 @@ void FreeTypeFont::setFontResolution(const osgText::FontResolution& fontSize)
|
||||
|
||||
int width = fontSize.first;
|
||||
int height = fontSize.second;
|
||||
int maxAxis = std::max(width, height);
|
||||
int margin = _facade->getGlyphImageMargin() + (int)((float)maxAxis * _facade->getGlyphImageMarginRatio());
|
||||
|
||||
if ((unsigned int)(width+2*margin) > _facade->getTextureWidthHint() ||
|
||||
(unsigned int)(width+2*margin) > _facade->getTextureHeightHint())
|
||||
{
|
||||
OSG_WARN<<"Warning: FreeTypeFont::setSize("<<width<<","<<height<<") sizes too large,"<<std::endl;
|
||||
|
||||
width = _facade->getTextureWidthHint()-2*margin;
|
||||
height = _facade->getTextureHeightHint()-2*margin;
|
||||
|
||||
OSG_WARN<<" sizes capped ("<<width<<","<<height<<") to fit int current glyph texture size."<<std::endl;
|
||||
}
|
||||
|
||||
FT_Error error = FT_Set_Pixel_Sizes( _face, /* handle to face object */
|
||||
width, /* pixel_width */
|
||||
@@ -351,6 +338,8 @@ osgText::Glyph* FreeTypeFont::getGlyph(const osgText::FontResolution& fontRes, u
|
||||
|
||||
osg::ref_ptr<osgText::Glyph> glyph = new osgText::Glyph(_facade, charcode);
|
||||
|
||||
glyph->setFontResolution(fontRes);
|
||||
|
||||
unsigned int dataSize = width*height;
|
||||
unsigned char* data = new unsigned char[dataSize];
|
||||
|
||||
@@ -359,14 +348,12 @@ osgText::Glyph* FreeTypeFont::getGlyph(const osgText::FontResolution& fontRes, u
|
||||
for(unsigned char* p=data;p<data+dataSize;) { *p++ = 0; }
|
||||
|
||||
glyph->setImage(width,height,1,
|
||||
OSGTEXT_GLYPH_INTERNALFORMAT,
|
||||
OSGTEXT_GLYPH_FORMAT, GL_UNSIGNED_BYTE,
|
||||
GL_ALPHA,
|
||||
GL_ALPHA, GL_UNSIGNED_BYTE,
|
||||
data,
|
||||
osg::Image::USE_NEW_DELETE,
|
||||
1);
|
||||
|
||||
glyph->setInternalTextureFormat(OSGTEXT_GLYPH_INTERNALFORMAT);
|
||||
|
||||
// copy image across to osgText::Glyph image.
|
||||
switch(glyphslot->bitmap.pixel_mode)
|
||||
{
|
||||
|
||||
@@ -90,7 +90,7 @@ void Text::write(DataOutputStream* out){
|
||||
out->writeFloat(getBackdropVerticalOffset());
|
||||
|
||||
out->writeVec4(getBackdropColor());
|
||||
out->writeUInt(getBackdropImplementation());
|
||||
out->writeUInt(4); // old DELAYED_DEPTH_WRITES
|
||||
|
||||
out->writeUInt(getColorGradientMode());
|
||||
out->writeVec4(getColorGradientTopLeft());
|
||||
@@ -213,7 +213,7 @@ void Text::read(DataInputStream* in){
|
||||
setBackdropOffset(horizontalOffset,verticalOffset);
|
||||
|
||||
setBackdropColor(in->readVec4());
|
||||
setBackdropImplementation((osgText::Text::BackdropImplementation) in->readUInt());
|
||||
in->readUInt(); // read old BackdropImplementation value, no longer used
|
||||
setColorGradientMode((osgText::Text::ColorGradientMode) in->readUInt());
|
||||
|
||||
osg::Vec4 colorGradientTopLeft,colorGradientBottomLeft,colorGradientBottomRight,colorGradientTopRight;
|
||||
|
||||
@@ -546,27 +546,27 @@ void OBJWriterNodeVisitor::processGeometry(osg::Geometry* geo, osg::Matrix& m) {
|
||||
|
||||
}
|
||||
|
||||
void OBJWriterNodeVisitor::apply(osg::Geometry& geometry)
|
||||
{
|
||||
osg::Matrix m = osg::computeLocalToWorld(getNodePath());
|
||||
|
||||
pushStateSet(geometry.getStateSet());
|
||||
|
||||
processGeometry(&geometry,m);
|
||||
|
||||
popStateSet(geometry.getStateSet());
|
||||
}
|
||||
|
||||
void OBJWriterNodeVisitor::apply( osg::Geode &node )
|
||||
{
|
||||
|
||||
pushStateSet(node.getStateSet());
|
||||
_nameStack.push_back(node.getName());
|
||||
osg::Matrix m = osg::computeLocalToWorld(getNodePath());
|
||||
unsigned int count = node.getNumDrawables();
|
||||
for ( unsigned int i = 0; i < count; i++ )
|
||||
{
|
||||
osg::Geometry *g = node.getDrawable( i )->asGeometry();
|
||||
if ( g != NULL )
|
||||
{
|
||||
pushStateSet(g->getStateSet());
|
||||
|
||||
processGeometry(g,m);
|
||||
|
||||
popStateSet(g->getStateSet());
|
||||
}
|
||||
node.getDrawable( i )->accept(*this);
|
||||
}
|
||||
|
||||
|
||||
popStateSet(node.getStateSet());
|
||||
_nameStack.pop_back();
|
||||
}
|
||||
|
||||
@@ -65,9 +65,10 @@ class OBJWriterNodeVisitor: public osg::NodeVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
virtual void apply(osg::Geode &node);
|
||||
virtual void apply(osg::Geometry & geometry);
|
||||
virtual void apply(osg::Geode & node);
|
||||
|
||||
virtual void apply(osg::Group &node)
|
||||
virtual void apply(osg::Group & node)
|
||||
{
|
||||
pushStateSet(node.getStateSet());
|
||||
_nameStack.push_back( node.getName().empty() ? node.className() : node.getName() );
|
||||
@@ -78,14 +79,6 @@ class OBJWriterNodeVisitor: public osg::NodeVisitor {
|
||||
traverse( node );
|
||||
|
||||
_nameStack.pop_back();
|
||||
popStateSet(node.getStateSet());
|
||||
}
|
||||
|
||||
void traverse (osg::Node &node)
|
||||
{
|
||||
pushStateSet(node.getStateSet());
|
||||
|
||||
osg::NodeVisitor::traverse( node );
|
||||
|
||||
popStateSet(node.getStateSet());
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -307,6 +307,18 @@ class ReaderWriterPNG : public osgDB::ReaderWriter
|
||||
pixelFormat = GL_RGBA;
|
||||
|
||||
int internalFormat = pixelFormat;
|
||||
if (depth > 8)
|
||||
{
|
||||
switch(color)
|
||||
{
|
||||
case(GL_LUMINANCE): internalFormat = GL_LUMINANCE16; break;
|
||||
case(GL_ALPHA): internalFormat = GL_ALPHA16; break;
|
||||
case(GL_LUMINANCE_ALPHA): internalFormat = GL_LUMINANCE16_ALPHA16; break;
|
||||
case(GL_RGB): internalFormat = GL_RGB16; break;
|
||||
case(GL_RGBA): internalFormat = GL_RGBA16; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
png_destroy_read_struct(&png, &info, &endinfo);
|
||||
|
||||
|
||||
@@ -398,17 +398,26 @@ class ReaderWriterVNC : public osgDB::ReaderWriter
|
||||
options->getAuthenticationMap() :
|
||||
osgDB::Registry::instance()->getAuthenticationMap();
|
||||
|
||||
const osgDB::AuthenticationDetails* details = authenticationMap ?
|
||||
authenticationMap->getAuthenticationDetails(hostname) :
|
||||
0;
|
||||
|
||||
// configure authentication if required.
|
||||
if (details)
|
||||
if (authenticationMap != NULL)
|
||||
{
|
||||
OSG_NOTICE<<"Passing in password = "<<details->password<<std::endl;
|
||||
const osgDB::AuthenticationDetails* details = authenticationMap->getAuthenticationDetails(hostname);
|
||||
if (details == NULL)
|
||||
{
|
||||
size_t pos = hostname.find(":");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
details = authenticationMap->getAuthenticationDetails(hostname.substr(0, pos));
|
||||
}
|
||||
}
|
||||
|
||||
image->_username = details->username;
|
||||
image->_password = details->password;
|
||||
// configure authentication if required.
|
||||
if (details != NULL)
|
||||
{
|
||||
OSG_NOTICE << "Passing in password = " << details->password << std::endl;
|
||||
|
||||
image->_username = details->username;
|
||||
image->_password = details->password;
|
||||
}
|
||||
}
|
||||
|
||||
if (options && !options->getOptionString().empty())
|
||||
|
||||
@@ -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;
|
||||
{
|
||||
|
||||
25
src/osgTerrain/shaders/lighting_vert.cpp
Normal file
25
src/osgTerrain/shaders/lighting_vert.cpp
Normal 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";
|
||||
@@ -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";
|
||||
|
||||
@@ -24,8 +24,11 @@ using namespace osgText;
|
||||
|
||||
DefaultFont::DefaultFont()
|
||||
{
|
||||
_fontSize = FontResolution(8,12);
|
||||
|
||||
_minFilterHint = osg::Texture::LINEAR_MIPMAP_LINEAR;
|
||||
_magFilterHint = osg::Texture::NEAREST;
|
||||
_magFilterHint = osg::Texture::LINEAR;
|
||||
|
||||
constructGlyphs();
|
||||
}
|
||||
|
||||
@@ -198,14 +201,12 @@ void DefaultFont::constructGlyphs()
|
||||
for(unsigned char* p=data;p<data+dataSize;) { *p++ = 0; }
|
||||
|
||||
glyph->setImage(sourceWidth,sourceHeight,1,
|
||||
OSGTEXT_GLYPH_INTERNALFORMAT,
|
||||
OSGTEXT_GLYPH_FORMAT, GL_UNSIGNED_BYTE,
|
||||
GL_ALPHA,
|
||||
GL_ALPHA, GL_UNSIGNED_BYTE,
|
||||
data,
|
||||
osg::Image::USE_NEW_DELETE,
|
||||
1);
|
||||
|
||||
glyph->setInternalTextureFormat(OSGTEXT_GLYPH_INTERNALFORMAT);
|
||||
|
||||
// now populate data array by converting bitmap into a luminance_alpha map.
|
||||
unsigned char* ptr = rasters[i-32];
|
||||
unsigned char value_on = 255;
|
||||
@@ -233,6 +234,8 @@ void DefaultFont::constructGlyphs()
|
||||
glyph->setVerticalBearing(osg::Vec2(0.5f,1.0f)); // top middle.
|
||||
glyph->setVerticalAdvance(sourceHeight*coord_scale);
|
||||
|
||||
glyph->setFontResolution(fontRes);
|
||||
|
||||
addGlyph(fontRes,i,glyph.get());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,81 +32,6 @@
|
||||
using namespace osgText;
|
||||
using namespace std;
|
||||
|
||||
#if (!defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GLES3_AVAILABLE))
|
||||
#define GLSL_VERSION_STR "330 core"
|
||||
#define GLYPH_CMP "r"
|
||||
#else
|
||||
#define GLSL_VERSION_STR "300 es"
|
||||
#define GLYPH_CMP "a"
|
||||
#endif
|
||||
|
||||
static const char* gl3_TextVertexShader = {
|
||||
"#version " GLSL_VERSION_STR "\n"
|
||||
"// gl3_TextVertexShader\n"
|
||||
"#ifdef GL_ES\n"
|
||||
" precision highp float;\n"
|
||||
"#endif\n"
|
||||
"in vec4 osg_Vertex;\n"
|
||||
"in vec4 osg_Color;\n"
|
||||
"in vec4 osg_MultiTexCoord0;\n"
|
||||
"uniform mat4 osg_ModelViewProjectionMatrix;\n"
|
||||
"out vec2 texCoord;\n"
|
||||
"out vec4 vertexColor;\n"
|
||||
"void main(void)\n"
|
||||
"{\n"
|
||||
" gl_Position = osg_ModelViewProjectionMatrix * osg_Vertex;\n"
|
||||
" texCoord = osg_MultiTexCoord0.xy;\n"
|
||||
" vertexColor = osg_Color; \n"
|
||||
"}\n"
|
||||
};
|
||||
|
||||
static const char* gl3_TextFragmentShader = {
|
||||
"#version " GLSL_VERSION_STR "\n"
|
||||
"// gl3_TextFragmentShader\n"
|
||||
"#ifdef GL_ES\n"
|
||||
" precision highp float;\n"
|
||||
"#endif\n"
|
||||
"uniform sampler2D glyphTexture;\n"
|
||||
"in vec2 texCoord;\n"
|
||||
"in vec4 vertexColor;\n"
|
||||
"out vec4 color;\n"
|
||||
"void main(void)\n"
|
||||
"{\n"
|
||||
" if (texCoord.x>=0.0) color = vertexColor * vec4(1.0, 1.0, 1.0, texture(glyphTexture, texCoord)." GLYPH_CMP ");\n"
|
||||
" else color = vertexColor;\n"
|
||||
"}\n"
|
||||
};
|
||||
|
||||
static const char* gl2_TextVertexShader = {
|
||||
"// gl2_TextVertexShader\n"
|
||||
"#ifdef GL_ES\n"
|
||||
" precision highp float;\n"
|
||||
"#endif\n"
|
||||
"varying vec2 texCoord;\n"
|
||||
"varying vec4 vertexColor;\n"
|
||||
"void main(void)\n"
|
||||
"{\n"
|
||||
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
|
||||
" texCoord = gl_MultiTexCoord0.xy;\n"
|
||||
" vertexColor = gl_Color; \n"
|
||||
"}\n"
|
||||
};
|
||||
|
||||
static const char* gl2_TextFragmentShader = {
|
||||
"// gl2_TextFragmentShader\n"
|
||||
"#ifdef GL_ES\n"
|
||||
" precision highp float;\n"
|
||||
"#endif\n"
|
||||
"uniform sampler2D glyphTexture;\n"
|
||||
"varying vec2 texCoord;\n"
|
||||
"varying vec4 vertexColor;\n"
|
||||
"void main(void)\n"
|
||||
"{\n"
|
||||
" if (texCoord.x>=0.0) gl_FragColor = vertexColor * vec4(1.0, 1.0, 1.0, texture2D(glyphTexture, texCoord).a);\n"
|
||||
" else gl_FragColor = vertexColor;\n"
|
||||
"}\n"
|
||||
};
|
||||
|
||||
osg::ref_ptr<Font>& Font::getDefaultFont()
|
||||
{
|
||||
static OpenThreads::Mutex s_DefaultFontMutex;
|
||||
@@ -299,67 +224,24 @@ osg::ref_ptr<Font> osgText::readRefFontStream(std::istream& stream, const osgDB:
|
||||
|
||||
Font::Font(FontImplementation* implementation):
|
||||
osg::Object(true),
|
||||
_margin(1),
|
||||
_marginRatio(0.02),
|
||||
_textureWidthHint(1024),
|
||||
_textureHeightHint(1024),
|
||||
_minFilterHint(osg::Texture::LINEAR_MIPMAP_LINEAR),
|
||||
_magFilterHint(osg::Texture::LINEAR),
|
||||
_maxAnisotropy(16),
|
||||
_depth(1),
|
||||
_numCurveSamples(10)
|
||||
{
|
||||
setImplementation(implementation);
|
||||
|
||||
_texenv = new osg::TexEnv;
|
||||
_stateset = new osg::StateSet;
|
||||
|
||||
_stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||
_stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||
_stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
|
||||
|
||||
#if defined(OSG_GL_FIXED_FUNCTION_AVAILABLE)
|
||||
|
||||
OSG_INFO<<"Font::Font() Fixed function pipeline"<<std::endl;
|
||||
|
||||
_stateset->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON);
|
||||
#endif
|
||||
|
||||
osg::DisplaySettings::ShaderHint shaderHint = osg::DisplaySettings::instance()->getShaderHint();
|
||||
if (shaderHint==osg::DisplaySettings::SHADER_GL3 || shaderHint==osg::DisplaySettings::SHADER_GLES3)
|
||||
{
|
||||
|
||||
OSG_INFO<<"Font::Font() Setting up GL3 compatible shaders"<<std::endl;
|
||||
|
||||
osg::ref_ptr<osg::Program> program = new osg::Program;
|
||||
program->addShader(new osg::Shader(osg::Shader::VERTEX, gl3_TextVertexShader));
|
||||
program->addShader(new osg::Shader(osg::Shader::FRAGMENT, gl3_TextFragmentShader));
|
||||
_stateset->setAttributeAndModes(program.get());
|
||||
_stateset->addUniform(new osg::Uniform("glyphTexture", 0));
|
||||
|
||||
}
|
||||
else if (shaderHint==osg::DisplaySettings::SHADER_GL2 || shaderHint==osg::DisplaySettings::SHADER_GLES2)
|
||||
{
|
||||
|
||||
|
||||
OSG_INFO<<"Font::Font() Setting up GL2 compatible shaders"<<std::endl;
|
||||
|
||||
osg::ref_ptr<osg::Program> program = new osg::Program;
|
||||
program->addShader(new osg::Shader(osg::Shader::VERTEX, gl2_TextVertexShader));
|
||||
program->addShader(new osg::Shader(osg::Shader::FRAGMENT, gl2_TextFragmentShader));
|
||||
_stateset->setAttributeAndModes(program.get());
|
||||
_stateset->addUniform(new osg::Uniform("glyphTexture", 0));
|
||||
|
||||
}
|
||||
|
||||
char *ptr;
|
||||
if( (ptr = getenv("OSG_MAX_TEXTURE_SIZE")) != 0)
|
||||
if ((ptr = getenv("OSG_MAX_TEXTURE_SIZE")) != 0)
|
||||
{
|
||||
unsigned int osg_max_size = atoi(ptr);
|
||||
|
||||
if (osg_max_size<_textureWidthHint) _textureWidthHint = osg_max_size;
|
||||
if (osg_max_size<_textureHeightHint) _textureHeightHint = osg_max_size;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Font::~Font()
|
||||
@@ -390,26 +272,6 @@ std::string Font::getFileName() const
|
||||
return std::string();
|
||||
}
|
||||
|
||||
void Font::setGlyphImageMargin(unsigned int margin)
|
||||
{
|
||||
_margin = margin;
|
||||
}
|
||||
|
||||
unsigned int Font::getGlyphImageMargin() const
|
||||
{
|
||||
return _margin;
|
||||
}
|
||||
|
||||
void Font::setGlyphImageMarginRatio(float ratio)
|
||||
{
|
||||
_marginRatio = ratio;
|
||||
}
|
||||
|
||||
float Font::getGlyphImageMarginRatio() const
|
||||
{
|
||||
return _marginRatio;
|
||||
}
|
||||
|
||||
void Font::setTextureSizeHint(unsigned int width,unsigned int height)
|
||||
{
|
||||
_textureWidthHint = width;
|
||||
@@ -518,9 +380,6 @@ void Font::setThreadSafeRefUnref(bool threadSafe)
|
||||
{
|
||||
osg::Object::setThreadSafeRefUnref(threadSafe);
|
||||
|
||||
if (_texenv.valid()) _texenv->setThreadSafeRefUnref(threadSafe);
|
||||
if (_stateset.valid()) _stateset->setThreadSafeRefUnref(threadSafe);
|
||||
|
||||
for(GlyphTextureList::const_iterator itr=_glyphTextureList.begin();
|
||||
itr!=_glyphTextureList.end();
|
||||
++itr)
|
||||
@@ -531,7 +390,12 @@ void Font::setThreadSafeRefUnref(bool threadSafe)
|
||||
|
||||
void Font::resizeGLObjectBuffers(unsigned int maxSize)
|
||||
{
|
||||
if (_stateset.valid()) _stateset->resizeGLObjectBuffers(maxSize);
|
||||
for(StateSets::iterator itr = _statesets.begin();
|
||||
itr != _statesets.end();
|
||||
++itr)
|
||||
{
|
||||
(*itr)->resizeGLObjectBuffers(maxSize);
|
||||
}
|
||||
|
||||
for(GlyphTextureList::const_iterator itr=_glyphTextureList.begin();
|
||||
itr!=_glyphTextureList.end();
|
||||
@@ -543,7 +407,12 @@ void Font::resizeGLObjectBuffers(unsigned int maxSize)
|
||||
|
||||
void Font::releaseGLObjects(osg::State* state) const
|
||||
{
|
||||
if (_stateset.valid()) _stateset->releaseGLObjects(state);
|
||||
for(StateSets::const_iterator itr = _statesets.begin();
|
||||
itr != _statesets.end();
|
||||
++itr)
|
||||
{
|
||||
(*itr)->releaseGLObjects(state);
|
||||
}
|
||||
|
||||
for(GlyphTextureList::const_iterator itr=_glyphTextureList.begin();
|
||||
itr!=_glyphTextureList.end();
|
||||
@@ -576,6 +445,10 @@ void Font::addGlyph(const FontResolution& fontRes, unsigned int charcode, Glyph*
|
||||
|
||||
_sizeGlyphMap[fontRes][charcode]=glyph;
|
||||
|
||||
}
|
||||
|
||||
void Font::assignGlyphToGlyphTexture(Glyph* glyph, ShaderTechnique shaderTechnique)
|
||||
{
|
||||
int posX=0,posY=0;
|
||||
|
||||
GlyphTexture* glyphTexture = 0;
|
||||
@@ -583,12 +456,12 @@ void Font::addGlyph(const FontResolution& fontRes, unsigned int charcode, Glyph*
|
||||
itr!=_glyphTextureList.end() && !glyphTexture;
|
||||
++itr)
|
||||
{
|
||||
if ((*itr)->getSpaceForGlyph(glyph,posX,posY)) glyphTexture = itr->get();
|
||||
if ((*itr)->getShaderTechnique()==shaderTechnique && (*itr)->getSpaceForGlyph(glyph,posX,posY)) glyphTexture = itr->get();
|
||||
}
|
||||
|
||||
if (glyphTexture)
|
||||
{
|
||||
//cout << " found space for texture "<<glyphTexture<<" posX="<<posX<<" posY="<<posY<<endl;
|
||||
//cout << " Font::assignGlyphToGlyphTexture() found space for texture "<<glyphTexture<<" posX="<<posX<<" posY="<<posY<<endl;
|
||||
}
|
||||
|
||||
if (!glyphTexture)
|
||||
@@ -602,12 +475,11 @@ void Font::addGlyph(const FontResolution& fontRes, unsigned int charcode, Glyph*
|
||||
OSG_INFO<< " Font " << this<< ", numberOfTexturesAllocated "<<numberOfTexturesAllocated<<std::endl;
|
||||
|
||||
// reserve enough space for the glyphs.
|
||||
glyphTexture->setGlyphImageMargin(_margin);
|
||||
glyphTexture->setGlyphImageMarginRatio(_marginRatio);
|
||||
glyphTexture->setShaderTechnique(shaderTechnique);
|
||||
glyphTexture->setTextureSize(_textureWidthHint,_textureHeightHint);
|
||||
glyphTexture->setFilter(osg::Texture::MIN_FILTER,_minFilterHint);
|
||||
glyphTexture->setFilter(osg::Texture::MAG_FILTER,_magFilterHint);
|
||||
glyphTexture->setMaxAnisotropy(8);
|
||||
glyphTexture->setMaxAnisotropy(_maxAnisotropy);
|
||||
|
||||
_glyphTextureList.push_back(glyphTexture);
|
||||
|
||||
@@ -621,5 +493,4 @@ void Font::addGlyph(const FontResolution& fontRes, unsigned int charcode, Glyph*
|
||||
|
||||
// add the glyph into the texture.
|
||||
glyphTexture->addGlyph(glyph,posX,posY);
|
||||
|
||||
}
|
||||
|
||||
@@ -28,9 +28,34 @@
|
||||
using namespace osgText;
|
||||
using namespace std;
|
||||
|
||||
// GL_ALPHA and GL_LUMINANCE_ALPHA are deprecated in GL3/GL4 core profile, use GL_RED & GL_RB in this case.
|
||||
#if defined(OSG_GL3_AVAILABLE) && !defined(OSG_GL2_AVAILABLE) && !defined(OSG_GL1_AVAILABLE)
|
||||
#define OSGTEXT_GLYPH_ALPHA_FORMAT GL_RED
|
||||
#define OSGTEXT_GLYPH_ALPHA_INTERNALFORMAT GL_R8
|
||||
#define OSGTEXT_GLYPH_SDF_FORMAT GL_RG
|
||||
#define OSGTEXT_GLYPH_SDF_INTERNALFORMAT GL_RG8
|
||||
#else
|
||||
#define OSGTEXT_GLYPH_ALPHA_FORMAT GL_ALPHA
|
||||
#define OSGTEXT_GLYPH_ALPHA_INTERNALFORMAT GL_ALPHA
|
||||
#define OSGTEXT_GLYPH_SDF_FORMAT GL_LUMINANCE_ALPHA
|
||||
#define OSGTEXT_GLYPH_SDF_INTERNALFORMAT GL_LUMINANCE_ALPHA
|
||||
#endif
|
||||
|
||||
|
||||
#if 0
|
||||
#define TEXTURE_IMAGE_NUM_CHANNELS 1
|
||||
#define TEXTURE_IMAGE_FORMAT OSGTEXT_GLYPH_FORMAT
|
||||
#else
|
||||
#define TEXTURE_IMAGE_NUM_CHANNELS 2
|
||||
#define TEXTURE_IMAGE_FORMAT GL_RGBA
|
||||
#endif
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// GlyphTexture
|
||||
//
|
||||
GlyphTexture::GlyphTexture():
|
||||
_margin(1),
|
||||
_marginRatio(0.02f),
|
||||
_usedY(0),
|
||||
_partUsedX(0),
|
||||
_partUsedY(0)
|
||||
@@ -51,27 +76,52 @@ int GlyphTexture::compare(const osg::StateAttribute& rhs) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GlyphTexture::getEffectMargin(const Glyph* glyph)
|
||||
{
|
||||
if (_shaderTechnique==GREYSCALE) return 0;
|
||||
else return osg::maximum(glyph->getFontResolution().second/6, 2u);
|
||||
}
|
||||
|
||||
int GlyphTexture::getTexelMargin(const Glyph* glyph)
|
||||
{
|
||||
int width = glyph->s();
|
||||
int height = glyph->t();
|
||||
int effect_margin = getEffectMargin(glyph);
|
||||
|
||||
int max_dimension = osg::maximum(width, height) + 2 * effect_margin;
|
||||
int margin = osg::maximum(max_dimension/4, 2) + effect_margin;
|
||||
|
||||
return margin;
|
||||
}
|
||||
|
||||
bool GlyphTexture::getSpaceForGlyph(Glyph* glyph, int& posX, int& posY)
|
||||
{
|
||||
int maxAxis = osg::maximum(glyph->s(), glyph->t());
|
||||
int margin = _margin + (int)((float)maxAxis * _marginRatio);
|
||||
int width = glyph->s();
|
||||
int height = glyph->t();
|
||||
|
||||
int width = glyph->s()+2*margin;
|
||||
int height = glyph->t()+2*margin;
|
||||
int margin = getTexelMargin(glyph);
|
||||
|
||||
// first check box (_partUsedX,_usedY) to (width,height)
|
||||
if (width <= (getTextureWidth()-_partUsedX) &&
|
||||
height <= (getTextureHeight()-_usedY))
|
||||
width += 2*margin;
|
||||
height += 2*margin;
|
||||
|
||||
int interval = 4;
|
||||
|
||||
int partUsedX = ((_partUsedX % interval) == 0) ? _partUsedX : (((_partUsedX/interval)+1)*interval);
|
||||
int partUsedY = ((_partUsedY % interval) == 0) ? _partUsedY : (((_partUsedY/interval)+1)*interval);
|
||||
int usedY = ((_usedY % interval) == 0) ? _usedY : (((_usedY/interval)+1)*interval);
|
||||
|
||||
// first check box (partUsedX, usedY) to (width,height)
|
||||
if (width <= (getTextureWidth()-partUsedX) &&
|
||||
height <= (getTextureHeight()-usedY))
|
||||
{
|
||||
// can fit in existing row.
|
||||
|
||||
// record the position in which the texture will be stored.
|
||||
posX = _partUsedX+margin;
|
||||
posY = _usedY+margin;
|
||||
posX = partUsedX+margin;
|
||||
posY = usedY+margin;
|
||||
|
||||
// move used markers on.
|
||||
_partUsedX += width;
|
||||
_partUsedX = posX+width;
|
||||
if (_usedY+height>_partUsedY) _partUsedY = _usedY+height;
|
||||
|
||||
return true;
|
||||
@@ -83,14 +133,14 @@ bool GlyphTexture::getSpaceForGlyph(Glyph* glyph, int& posX, int& posY)
|
||||
{
|
||||
// can fit next row.
|
||||
_partUsedX = 0;
|
||||
_usedY = _partUsedY;
|
||||
_usedY = partUsedY;
|
||||
|
||||
posX = _partUsedX+margin;
|
||||
posY = _usedY+margin;
|
||||
|
||||
// move used markers on.
|
||||
_partUsedX += width;
|
||||
if (_usedY+height>_partUsedY) _partUsedY = _usedY+height;
|
||||
_partUsedX = posX+width;
|
||||
_partUsedY = _usedY+height;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -101,23 +151,237 @@ bool GlyphTexture::getSpaceForGlyph(Glyph* glyph, int& posX, int& posY)
|
||||
|
||||
void GlyphTexture::addGlyph(Glyph* glyph, int posX, int posY)
|
||||
{
|
||||
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
||||
|
||||
if (!_image.valid()) createImage();
|
||||
|
||||
_glyphs.push_back(glyph);
|
||||
|
||||
// set up the details of where to place glyph's image in the texture.
|
||||
glyph->setTexture(this);
|
||||
glyph->setTexturePosition(posX,posY);
|
||||
osg::ref_ptr<Glyph::TextureInfo> info = new Glyph::TextureInfo(
|
||||
this,
|
||||
posX, posY,
|
||||
osg::Vec2( static_cast<float>(posX)/static_cast<float>(getTextureWidth()), static_cast<float>(posY)/static_cast<float>(getTextureHeight()) ), // minTexCoord
|
||||
osg::Vec2( static_cast<float>(posX+glyph->s())/static_cast<float>(getTextureWidth()), static_cast<float>(posY+glyph->t())/static_cast<float>(getTextureHeight()) ), // maxTexCoord
|
||||
float(getTexelMargin(glyph))); // margin
|
||||
|
||||
glyph->setMinTexCoord( osg::Vec2( static_cast<float>(posX)/static_cast<float>(getTextureWidth()),
|
||||
static_cast<float>(posY)/static_cast<float>(getTextureHeight()) ) );
|
||||
glyph->setMaxTexCoord( osg::Vec2( static_cast<float>(posX+glyph->s())/static_cast<float>(getTextureWidth()),
|
||||
static_cast<float>(posY+glyph->t())/static_cast<float>(getTextureHeight()) ) );
|
||||
glyph->setTextureInfo(_shaderTechnique, info.get());
|
||||
|
||||
_image->copySubImage(glyph->getTexturePositionX(), glyph->getTexturePositionY(), 0, glyph);
|
||||
copyGlyphImage(glyph, info);
|
||||
}
|
||||
|
||||
void GlyphTexture::copyGlyphImage(Glyph* glyph, Glyph::TextureInfo* info)
|
||||
{
|
||||
_image->dirty();
|
||||
|
||||
if (_shaderTechnique<=GREYSCALE)
|
||||
{
|
||||
// OSG_NOTICE<<"GlyphTexture::copyGlyphImage() greyscale copying. glyphTexture="<<this<<", glyph="<<glyph->getGlyphCode()<<std::endl;
|
||||
// make sure the glyph image settings and the target image are consisent before copying.
|
||||
glyph->setPixelFormat(_image->getPixelFormat());
|
||||
glyph->setInternalTextureFormat(_image->getPixelFormat());
|
||||
_image->copySubImage(info->texturePositionX, info->texturePositionY, 0, glyph);
|
||||
return;
|
||||
}
|
||||
|
||||
// OSG_NOTICE<<"GlyphTexture::copyGlyphImage() generating signed distance field. glyphTexture="<<this<<", glyph="<<glyph->getGlyphCode()<<std::endl;
|
||||
|
||||
int src_columns = glyph->s();
|
||||
int src_rows = glyph->t();
|
||||
unsigned char* src_data = glyph->data();
|
||||
|
||||
int dest_columns = _image->s();
|
||||
int dest_rows = _image->t();
|
||||
unsigned char* dest_data = _image->data(info->texturePositionX, info->texturePositionY);
|
||||
|
||||
int search_distance = getEffectMargin(glyph);
|
||||
|
||||
int left = -search_distance;
|
||||
int right = glyph->s()+search_distance;
|
||||
int lower = -search_distance;
|
||||
int upper = glyph->t()+search_distance;
|
||||
|
||||
float multiplier = 1.0/255.0f;
|
||||
|
||||
float max_distance = sqrtf(float(search_distance)*float(search_distance)*2.0);
|
||||
|
||||
if ((left+info->texturePositionX)<0) left = -info->texturePositionX;
|
||||
if ((right+info->texturePositionX)>=dest_columns) right = dest_columns-info->texturePositionX-1;
|
||||
|
||||
if ((lower+info->texturePositionY)<0) lower = -info->texturePositionY;
|
||||
if ((upper+info->texturePositionY)>=dest_rows) upper = dest_rows-info->texturePositionY-1;
|
||||
|
||||
|
||||
int num_components = osg::Image::computeNumComponents(_image->getPixelFormat());
|
||||
int bytes_per_pixel = osg::Image::computePixelSizeInBits(_image->getPixelFormat(),_image->getDataType())/8;
|
||||
int alpha_offset = (_image->getPixelFormat()==GL_LUMINANCE_ALPHA) ? 1 : 0;
|
||||
int sdf_offset = (_image->getPixelFormat()==GL_LUMINANCE_ALPHA) ? 0 : 1;
|
||||
|
||||
|
||||
unsigned char full_on = 255;
|
||||
unsigned char mid_point = full_on/2;
|
||||
float mid_point_f = float(mid_point)*multiplier;
|
||||
|
||||
for(int dr=lower; dr<=upper; ++dr)
|
||||
{
|
||||
for(int dc=left; dc<=right; ++dc)
|
||||
{
|
||||
unsigned char value = 0;
|
||||
|
||||
unsigned char center_value = 0;
|
||||
if (dr>=0 && dr<src_rows && dc>=0 && dc<src_columns) center_value = *(src_data + dr*src_columns + dc);
|
||||
|
||||
float center_value_f = center_value*multiplier;
|
||||
float min_distance = max_distance;
|
||||
|
||||
if (center_value>0 && center_value<full_on)
|
||||
{
|
||||
if (center_value_f>=mid_point_f)
|
||||
{
|
||||
min_distance = center_value_f-mid_point_f;
|
||||
value = 128+(min_distance/max_distance)*127;
|
||||
}
|
||||
else
|
||||
{
|
||||
min_distance = mid_point_f-center_value_f;
|
||||
value = 127-(min_distance/max_distance)*127;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int radius=1; radius<search_distance; ++radius)
|
||||
{
|
||||
for(int span=-radius; span<=radius; ++span)
|
||||
{
|
||||
{
|
||||
// left
|
||||
int dx = -radius;
|
||||
int dy = span;
|
||||
|
||||
int c = dc+dx;
|
||||
int r = dr+dy;
|
||||
|
||||
unsigned char local_value = 0;
|
||||
if (r>=0 && r<src_rows && c>=0 && c<src_columns) local_value = *(src_data + r*src_columns + c);
|
||||
if (local_value!=center_value)
|
||||
{
|
||||
float local_value_f = float(local_value)*multiplier;
|
||||
|
||||
float D = sqrtf(float(dx*dx) + float(dy*dy));
|
||||
float local_multiplier = (abs(dx)>abs(dy)) ? D/float(abs(dx)) : D/float(abs(dy));
|
||||
|
||||
float local_distance = sqrtf(float(radius*radius)+float(span*span));
|
||||
if (center_value==0) local_distance += (mid_point_f-local_value_f)*local_multiplier;
|
||||
else local_distance += (local_value_f - mid_point_f)*local_multiplier;
|
||||
|
||||
if (local_distance<min_distance) min_distance = local_distance;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// top
|
||||
int dx = span;
|
||||
int dy = radius;
|
||||
|
||||
int c = dc+dx;
|
||||
int r = dr+dy;
|
||||
|
||||
unsigned char local_value = 0;
|
||||
if (r>=0 && r<src_rows && c>=0 && c<src_columns) local_value = *(src_data + r*src_columns + c);
|
||||
if (local_value!=center_value)
|
||||
{
|
||||
float local_value_f = float(local_value)*multiplier;
|
||||
|
||||
float D = sqrtf(float(dx*dx) + float(dy*dy));
|
||||
float local_multiplier = (abs(dx)>abs(dy)) ? D/float(abs(dx)) : D/float(abs(dy));
|
||||
|
||||
float local_distance = sqrtf(float(radius*radius)+float(span*span));
|
||||
if (center_value==0) local_distance += (mid_point_f-local_value_f)*local_multiplier;
|
||||
else local_distance += (local_value_f - mid_point_f)*local_multiplier;
|
||||
|
||||
if (local_distance<min_distance) min_distance = local_distance;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// right
|
||||
int dx = radius;
|
||||
int dy = span;
|
||||
|
||||
int c = dc+dx;
|
||||
int r = dr+dy;
|
||||
|
||||
unsigned char local_value = 0;
|
||||
if (r>=0 && r<src_rows && c>=0 && c<src_columns) local_value = *(src_data + r*src_columns + c);
|
||||
if (local_value!=center_value)
|
||||
{
|
||||
float local_value_f = float(local_value)*multiplier;
|
||||
|
||||
float D = sqrtf(float(dx*dx) + float(dy*dy));
|
||||
float local_multiplier = (abs(dx)>abs(dy)) ? D/float(abs(dx)) : D/float(abs(dy));
|
||||
|
||||
float local_distance = sqrtf(float(radius*radius)+float(span*span));
|
||||
|
||||
if (center_value==0) local_distance += (mid_point_f-local_value_f)*local_multiplier;
|
||||
else local_distance += (local_value_f - mid_point_f)*local_multiplier;
|
||||
|
||||
if (local_distance<min_distance) min_distance = local_distance;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// bottom
|
||||
int dx = span;
|
||||
int dy = -radius;
|
||||
|
||||
int c = dc+dx;
|
||||
int r = dr+dy;
|
||||
|
||||
unsigned char local_value = 0;
|
||||
if (r>=0 && r<src_rows && c>=0 && c<src_columns) local_value = *(src_data + r*src_columns + c);
|
||||
if (local_value!=center_value)
|
||||
{
|
||||
float local_value_f = float(local_value)*multiplier;
|
||||
|
||||
float D = sqrtf(float(dx*dx) + float(dy*dy));
|
||||
float local_multiplier = (abs(dx)>abs(dy)) ? D/float(abs(dx)) : D/float(abs(dy));
|
||||
|
||||
float local_distance = sqrtf(float(radius*radius)+float(span*span));
|
||||
if (center_value==0) local_distance += (mid_point_f-local_value_f)*local_multiplier;
|
||||
else local_distance += (local_value_f - mid_point_f)*local_multiplier;
|
||||
|
||||
if (local_distance<min_distance) min_distance = local_distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (center_value_f>=0.5)
|
||||
{
|
||||
value = 128+(min_distance/max_distance)*127;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = 127-(min_distance/max_distance)*127;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned char* dest_ptr = dest_data + (dr*dest_columns + dc)*bytes_per_pixel;
|
||||
if (num_components==2)
|
||||
{
|
||||
// signed distance field value
|
||||
*(dest_ptr+sdf_offset) = value;
|
||||
|
||||
// original alpha value from glyph image
|
||||
*(dest_ptr+alpha_offset) = center_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
*(dest_ptr) = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GlyphTexture::setThreadSafeRefUnref(bool threadSafe)
|
||||
@@ -147,22 +411,26 @@ osg::Image* GlyphTexture::createImage()
|
||||
{
|
||||
if (!_image)
|
||||
{
|
||||
_image = new osg::Image;
|
||||
_image->allocateImage(getTextureWidth(), getTextureHeight(), 1, OSGTEXT_GLYPH_FORMAT, GL_UNSIGNED_BYTE);
|
||||
memset(_image->data(), 0, _image->getTotalSizeInBytes());
|
||||
OSG_INFO<<"GlyphTexture::createImage() : Creating image 0x"<<std::hex<<TEXTURE_IMAGE_FORMAT<<std::dec<<std::endl;
|
||||
|
||||
for(GlyphRefList::iterator itr = _glyphs.begin();
|
||||
itr != _glyphs.end();
|
||||
++itr)
|
||||
{
|
||||
Glyph* glyph = itr->get();
|
||||
_image->copySubImage(glyph->getTexturePositionX(), glyph->getTexturePositionY(), 0, glyph);
|
||||
}
|
||||
_image = new osg::Image;
|
||||
|
||||
GLenum imageFormat = (_shaderTechnique<=GREYSCALE) ? OSGTEXT_GLYPH_ALPHA_FORMAT : OSGTEXT_GLYPH_SDF_FORMAT;
|
||||
GLenum internalFormat = (_shaderTechnique<=GREYSCALE) ? OSGTEXT_GLYPH_ALPHA_INTERNALFORMAT : OSGTEXT_GLYPH_SDF_INTERNALFORMAT;
|
||||
|
||||
_image->allocateImage(getTextureWidth(), getTextureHeight(), 1, imageFormat, GL_UNSIGNED_BYTE);
|
||||
_image->setInternalTextureFormat(internalFormat);
|
||||
|
||||
memset(_image->data(), 0, _image->getTotalSizeInBytes());
|
||||
}
|
||||
|
||||
return _image.get();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Glyph
|
||||
//
|
||||
// all the methods in Font::Glyph have been made non inline because VisualStudio6.0 is STUPID, STUPID, STUPID PILE OF JUNK.
|
||||
Glyph::Glyph(Font* font, unsigned int glyphCode):
|
||||
_font(font),
|
||||
@@ -172,12 +440,7 @@ Glyph::Glyph(Font* font, unsigned int glyphCode):
|
||||
_horizontalBearing(0.0f,0.f),
|
||||
_horizontalAdvance(0.f),
|
||||
_verticalBearing(0.0f,0.f),
|
||||
_verticalAdvance(0.f),
|
||||
_texture(0),
|
||||
_texturePosX(0),
|
||||
_texturePosY(0),
|
||||
_minTexCoord(0.0f,0.0f),
|
||||
_maxTexCoord(0.0f,0.0f)
|
||||
_verticalAdvance(0.f)
|
||||
{
|
||||
setThreadSafeRefUnref(true);
|
||||
}
|
||||
@@ -198,67 +461,37 @@ const osg::Vec2& Glyph::getVerticalBearing() const { return _verticalBearing; }
|
||||
void Glyph::setVerticalAdvance(float advance) { _verticalAdvance=advance; }
|
||||
float Glyph::getVerticalAdvance() const { return _verticalAdvance; }
|
||||
|
||||
void Glyph::setTexture(GlyphTexture* texture) { _texture = texture; }
|
||||
GlyphTexture* Glyph::getTexture() { return _texture; }
|
||||
const GlyphTexture* Glyph::getTexture() const { return _texture; }
|
||||
|
||||
void Glyph::setTexturePosition(int posX,int posY) { _texturePosX = posX; _texturePosY = posY; }
|
||||
int Glyph::getTexturePositionX() const { return _texturePosX; }
|
||||
int Glyph::getTexturePositionY() const { return _texturePosY; }
|
||||
|
||||
void Glyph::setMinTexCoord(const osg::Vec2& coord) { _minTexCoord=coord; }
|
||||
const osg::Vec2& Glyph::getMinTexCoord() const { return _minTexCoord; }
|
||||
|
||||
void Glyph::setMaxTexCoord(const osg::Vec2& coord) { _maxTexCoord=coord; }
|
||||
const osg::Vec2& Glyph::getMaxTexCoord() const { return _maxTexCoord; }
|
||||
|
||||
void Glyph::subload() const
|
||||
void Glyph::setTextureInfo(ShaderTechnique technique, TextureInfo* info)
|
||||
{
|
||||
GLenum errorNo = glGetError();
|
||||
if (errorNo!=GL_NO_ERROR)
|
||||
if (technique>=_textureInfoList.size())
|
||||
{
|
||||
const GLubyte* msg = osg::gluErrorString(errorNo);
|
||||
if (msg) { OSG_WARN<<"before Glyph::subload(): detected OpenGL error: "<<msg<<std::endl; }
|
||||
else { OSG_WARN<<"before Glyph::subload(): detected OpenGL error number: "<<errorNo<<std::endl; }
|
||||
}
|
||||
|
||||
if(s() <= 0 || t() <= 0)
|
||||
{
|
||||
OSG_INFO<<"Glyph::subload(): texture sub-image width and/or height of 0, ignoring operation."<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT,getPacking());
|
||||
|
||||
#if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE)
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH,getRowLength());
|
||||
#endif
|
||||
|
||||
glTexSubImage2D(GL_TEXTURE_2D,0,
|
||||
_texturePosX,_texturePosY,
|
||||
s(),t(),
|
||||
(GLenum)getPixelFormat(),
|
||||
(GLenum)getDataType(),
|
||||
data());
|
||||
|
||||
errorNo = glGetError();
|
||||
if (errorNo!=GL_NO_ERROR)
|
||||
{
|
||||
|
||||
|
||||
const GLubyte* msg = osg::gluErrorString(errorNo);
|
||||
if (msg) { OSG_WARN<<"after Glyph::subload() : detected OpenGL error: "<<msg<<std::endl; }
|
||||
else { OSG_WARN<<"after Glyph::subload() : detected OpenGL error number: "<<errorNo<<std::endl; }
|
||||
|
||||
OSG_WARN<< "\tglTexSubImage2D(0x"<<hex<<GL_TEXTURE_2D<<dec<<" ,"<<0<<"\t"<<std::endl<<
|
||||
"\t "<<_texturePosX<<" ,"<<_texturePosY<<std::endl<<
|
||||
"\t "<<s()<<" ,"<<t()<<std::endl<<hex<<
|
||||
"\t 0x"<<(GLenum)getPixelFormat()<<std::endl<<
|
||||
"\t 0x"<<(GLenum)getDataType()<<std::endl<<
|
||||
"\t "<<static_cast<const void*>(data())<<");"<<dec<<std::endl;
|
||||
_textureInfoList.resize(technique+1);
|
||||
}
|
||||
_textureInfoList[technique] = info;
|
||||
}
|
||||
|
||||
const Glyph::TextureInfo* Glyph::getTextureInfo(ShaderTechnique technique) const
|
||||
{
|
||||
return (technique<_textureInfoList.size()) ? _textureInfoList[technique].get() : 0;
|
||||
}
|
||||
|
||||
Glyph::TextureInfo* Glyph::getOrCreateTextureInfo(ShaderTechnique technique)
|
||||
{
|
||||
if (technique>=_textureInfoList.size())
|
||||
{
|
||||
_textureInfoList.resize(technique+1);
|
||||
}
|
||||
if (!_textureInfoList[technique])
|
||||
{
|
||||
_font->assignGlyphToGlyphTexture(this, technique);
|
||||
}
|
||||
return _textureInfoList[technique].get();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Glyph3D
|
||||
//
|
||||
Glyph3D::Glyph3D(Font* font, unsigned int glyphCode):
|
||||
osg::Referenced(true),
|
||||
_font(font),
|
||||
|
||||
@@ -25,13 +25,19 @@
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
#define DEBUG_MESSAGE_LEVEL osg::INFO
|
||||
#define DEBUG_MESSAGE osg::notify(DEBUG_MESSAGE_LEVEL)
|
||||
|
||||
using namespace osg;
|
||||
using namespace osgText;
|
||||
|
||||
Text::Text():
|
||||
_shaderTechnique(GREYSCALE),
|
||||
_enableDepthWrites(true),
|
||||
_backdropType(NONE),
|
||||
_backdropImplementation(DELAYED_DEPTH_WRITES),
|
||||
_backdropHorizontalOffset(0.07f),
|
||||
_backdropVerticalOffset(0.07f),
|
||||
_backdropColor(0.0f, 0.0f, 0.0f, 1.0f),
|
||||
@@ -42,13 +48,24 @@ Text::Text():
|
||||
_colorGradientTopRight(1.0f, 1.0f, 1.0f, 1.0f)
|
||||
{
|
||||
_supportsVertexBufferObjects = true;
|
||||
|
||||
const std::string& str = osg::DisplaySettings::instance()->getTextShaderTechnique();
|
||||
if (!str.empty())
|
||||
{
|
||||
if (str=="ALL_FEATURES" || str=="ALL") _shaderTechnique = ALL_FEATURES;
|
||||
else if (str=="GREYSCALE") _shaderTechnique = GREYSCALE;
|
||||
else if (str=="SIGNED_DISTANCE_FIELD" || str=="SDF") _shaderTechnique = SIGNED_DISTANCE_FIELD;
|
||||
else if (str=="NO_TEXT_SHADER" || str=="NONE") _shaderTechnique = NO_TEXT_SHADER;
|
||||
}
|
||||
|
||||
assignStateSet();
|
||||
}
|
||||
|
||||
Text::Text(const Text& text,const osg::CopyOp& copyop):
|
||||
osgText::TextBase(text,copyop),
|
||||
_shaderTechnique(text._shaderTechnique),
|
||||
_enableDepthWrites(text._enableDepthWrites),
|
||||
_backdropType(text._backdropType),
|
||||
_backdropImplementation(text._backdropImplementation),
|
||||
_backdropHorizontalOffset(text._backdropHorizontalOffset),
|
||||
_backdropVerticalOffset(text._backdropVerticalOffset),
|
||||
_backdropColor(text._backdropColor),
|
||||
@@ -65,21 +82,170 @@ Text::~Text()
|
||||
{
|
||||
}
|
||||
|
||||
void Text::setFont(osg::ref_ptr<Font> font)
|
||||
|
||||
void Text::setShaderTechnique(ShaderTechnique technique)
|
||||
{
|
||||
if (_font==font) return;
|
||||
if (_shaderTechnique==technique) return;
|
||||
|
||||
osg::StateSet* previousFontStateSet = _font.valid() ? _font->getStateSet() : Font::getDefaultFont()->getStateSet();
|
||||
osg::StateSet* newFontStateSet = font.valid() ? font->getStateSet() : Font::getDefaultFont()->getStateSet();
|
||||
_shaderTechnique = technique;
|
||||
|
||||
if (getStateSet() == previousFontStateSet)
|
||||
{
|
||||
setStateSet( newFontStateSet );
|
||||
}
|
||||
assignStateSet();
|
||||
|
||||
TextBase::setFont(font);
|
||||
computeGlyphRepresentation();
|
||||
}
|
||||
|
||||
osg::StateSet* Text::createStateSet()
|
||||
{
|
||||
Font* activeFont = getActiveFont();
|
||||
if (!activeFont) return 0;
|
||||
|
||||
Font::StateSets& statesets = activeFont->getCachedStateSets();
|
||||
|
||||
std::stringstream ss;
|
||||
ss<<std::fixed<<std::setprecision(3);
|
||||
|
||||
osg::StateSet::DefineList defineList;
|
||||
if (_backdropType!=NONE)
|
||||
{
|
||||
ss.str("");
|
||||
ss << "vec4("<<_backdropColor.r()<<", "<<_backdropColor.g()<<", "<<_backdropColor.b()<<", "<<_backdropColor.a()<<")";
|
||||
|
||||
defineList["BACKDROP_COLOR"] = osg::StateSet::DefinePair(ss.str(), osg::StateAttribute::ON);
|
||||
|
||||
|
||||
if (_backdropType==OUTLINE)
|
||||
{
|
||||
ss.str("");
|
||||
ss <<_backdropHorizontalOffset;
|
||||
defineList["OUTLINE"] = osg::StateSet::DefinePair(ss.str(), osg::StateAttribute::ON);
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::Vec2 offset(_backdropHorizontalOffset, _backdropVerticalOffset);
|
||||
switch(_backdropType)
|
||||
{
|
||||
case(DROP_SHADOW_BOTTOM_RIGHT) : offset.set(_backdropHorizontalOffset, -_backdropVerticalOffset); break;
|
||||
case(DROP_SHADOW_CENTER_RIGHT) : offset.set(_backdropHorizontalOffset, 0.0f); break;
|
||||
case(DROP_SHADOW_TOP_RIGHT) : offset.set(_backdropHorizontalOffset, _backdropVerticalOffset); break;
|
||||
case(DROP_SHADOW_BOTTOM_CENTER) : offset.set(0.0f, -_backdropVerticalOffset); break;
|
||||
case(DROP_SHADOW_TOP_CENTER) : offset.set(0.0f, _backdropVerticalOffset); break;
|
||||
case(DROP_SHADOW_BOTTOM_LEFT) : offset.set(-_backdropHorizontalOffset, -_backdropVerticalOffset); break;
|
||||
case(DROP_SHADOW_CENTER_LEFT) : offset.set(-_backdropHorizontalOffset, 0.0f); break;
|
||||
case(DROP_SHADOW_TOP_LEFT) : offset.set(-_backdropHorizontalOffset, _backdropVerticalOffset); break;
|
||||
default : break;
|
||||
}
|
||||
|
||||
ss.str("");
|
||||
ss << "vec2("<<offset.x()<<", "<<offset.y()<<")";
|
||||
|
||||
defineList["SHADOW"] = osg::StateSet::DefinePair(ss.str(), osg::StateAttribute::ON);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
ss<<std::fixed<<std::setprecision(1);
|
||||
|
||||
ss.str("");
|
||||
ss << float(_fontSize.second);
|
||||
|
||||
defineList["GLYPH_DIMENSION"] = osg::StateSet::DefinePair(ss.str(), osg::StateAttribute::ON);
|
||||
|
||||
ss.str("");
|
||||
ss << float(activeFont->getTextureWidthHint());
|
||||
defineList["TEXTURE_DIMENSION"] = osg::StateSet::DefinePair(ss.str(), osg::StateAttribute::ON);
|
||||
}
|
||||
|
||||
if (_shaderTechnique>GREYSCALE)
|
||||
{
|
||||
defineList["SIGNED_DISTNACE_FIELD"] = osg::StateSet::DefinePair("1", osg::StateAttribute::ON);
|
||||
}
|
||||
|
||||
#if 0
|
||||
OSG_NOTICE<<"Text::createStateSet() defines:"<<defineList.size()<<std::endl;
|
||||
for(osg::StateSet::DefineList::iterator itr = defineList.begin();
|
||||
itr != defineList.end();
|
||||
++itr)
|
||||
{
|
||||
OSG_NOTICE<<" define["<<itr->first<<"] = "<<itr->second.first<<std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!statesets.empty())
|
||||
{
|
||||
for(Font::StateSets::iterator itr = statesets.begin();
|
||||
itr != statesets.end();
|
||||
++itr)
|
||||
{
|
||||
if ((*itr)->getDefineList()==defineList)
|
||||
{
|
||||
// OSG_NOTICE<<"Text::createStateSet() : Matched DefineList, return StateSet "<<itr->get()<<std::endl;
|
||||
return itr->get();
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (osg::isNotifyEnabled(DEBUG_MESSAGE_LEVEL))
|
||||
{
|
||||
DEBUG_MESSAGE<<"Text::createStateSet() ShaderTechnique ";
|
||||
switch(_shaderTechnique)
|
||||
{
|
||||
case(NO_TEXT_SHADER) : DEBUG_MESSAGE<<"NO_TEXT_SHADER"<<std::endl; break;
|
||||
case(GREYSCALE) : DEBUG_MESSAGE<<"GREYSCALE"<<std::endl; break;
|
||||
case(SIGNED_DISTANCE_FIELD) : DEBUG_MESSAGE<<"SIGNED_DISTANCE_FIELD"<<std::endl; break;
|
||||
case(ALL_FEATURES) : DEBUG_MESSAGE<<"ALL_FEATURES"<<std::endl; break;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_MESSAGE<<"Text::createStateSet() : Not Matched DefineList, creating new StateSet"<<std::endl;
|
||||
|
||||
osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;
|
||||
|
||||
stateset->setDefineList(defineList);
|
||||
|
||||
statesets.push_back(stateset.get());
|
||||
|
||||
stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||
stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||
stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
|
||||
|
||||
|
||||
#if defined(OSG_GL_FIXED_FUNCTION_AVAILABLE)
|
||||
osg::DisplaySettings::ShaderHint shaderHint = osg::DisplaySettings::instance()->getShaderHint();
|
||||
if (_shaderTechnique==NO_TEXT_SHADER && shaderHint==osg::DisplaySettings::SHADER_NONE)
|
||||
{
|
||||
DEBUG_MESSAGE<<"Font::Font() Fixed function pipeline"<<std::endl;
|
||||
|
||||
stateset->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON);
|
||||
return stateset.release();
|
||||
}
|
||||
#endif
|
||||
|
||||
// set up the StateSet to use shaders
|
||||
stateset->addUniform(new osg::Uniform("glyphTexture", 0));
|
||||
|
||||
osg::ref_ptr<osg::Program> program = new osg::Program;
|
||||
stateset->setAttributeAndModes(program.get());
|
||||
|
||||
{
|
||||
DEBUG_MESSAGE<<"Using shaders/text.vert"<<std::endl;
|
||||
|
||||
#include "shaders/text_vert.cpp"
|
||||
program->addShader(osgDB::readRefShaderFileWithFallback(osg::Shader::VERTEX, "shaders/text.vert", text_vert));
|
||||
}
|
||||
|
||||
{
|
||||
DEBUG_MESSAGE<<"Using shaders/text.frag"<<std::endl;
|
||||
|
||||
#include "shaders/text_frag.cpp"
|
||||
program->addShader(osgDB::readRefShaderFileWithFallback(osg::Shader::FRAGMENT, "shaders/text.frag", text_frag));
|
||||
}
|
||||
|
||||
return stateset.release();
|
||||
}
|
||||
|
||||
Font* Text::getActiveFont()
|
||||
{
|
||||
@@ -225,22 +391,20 @@ String::iterator Text::computeLastCharacterOnLine(osg::Vec2& cursor, String::ite
|
||||
void Text::addGlyphQuad(Glyph* glyph, const osg::Vec2& minc, const osg::Vec2& maxc, const osg::Vec2& mintc, const osg::Vec2& maxtc)
|
||||
{
|
||||
// set up the coords of the quad
|
||||
GlyphQuads& glyphquad = _textureGlyphQuadMap[glyph->getTexture()];
|
||||
const Glyph::TextureInfo* info = glyph->getOrCreateTextureInfo(_shaderTechnique);
|
||||
GlyphTexture* glyphTexture = info ? info->texture : 0;
|
||||
GlyphQuads& glyphquad = _textureGlyphQuadMap[glyphTexture];
|
||||
|
||||
glyphquad._glyphs.push_back(glyph);
|
||||
|
||||
osg::DrawElements* primitives = 0;
|
||||
if (glyphquad._primitives.empty())
|
||||
osg::DrawElements* primitives = glyphquad._primitives.get();
|
||||
if (!primitives)
|
||||
{
|
||||
unsigned int maxIndices = _text.size()*4;
|
||||
if (maxIndices>=16384) primitives = new osg::DrawElementsUInt(GL_TRIANGLES);
|
||||
else primitives = new osg::DrawElementsUShort(GL_TRIANGLES);
|
||||
primitives->setBufferObject(_ebo.get());
|
||||
glyphquad._primitives.push_back(primitives);
|
||||
}
|
||||
else
|
||||
{
|
||||
primitives = glyphquad._primitives[0].get();
|
||||
glyphquad._primitives = primitives;
|
||||
}
|
||||
|
||||
|
||||
@@ -280,25 +444,18 @@ void Text::computeGlyphRepresentation()
|
||||
if (!_texcoords) { _texcoords = new osg::Vec2Array(osg::Array::BIND_PER_VERTEX); _texcoords->setBufferObject(_vbo.get()); }
|
||||
else _texcoords->clear();
|
||||
|
||||
#if 0
|
||||
_textureGlyphQuadMap.clear();
|
||||
#else
|
||||
for(TextureGlyphQuadMap::iterator itr = _textureGlyphQuadMap.begin();
|
||||
itr != _textureGlyphQuadMap.end();
|
||||
++itr)
|
||||
{
|
||||
GlyphQuads& glyphquads = itr->second;
|
||||
glyphquads._glyphs.clear();
|
||||
for(Primitives::iterator pitr = glyphquads._primitives.begin();
|
||||
pitr != glyphquads._primitives.end();
|
||||
++pitr)
|
||||
if (glyphquads._primitives.valid())
|
||||
{
|
||||
(*pitr)->resizeElements(0);
|
||||
(*pitr)->dirty();
|
||||
glyphquads._primitives->resizeElements(0);
|
||||
glyphquads._primitives->dirty();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
_lineCount = 0;
|
||||
@@ -487,45 +644,53 @@ void Text::computeGlyphRepresentation()
|
||||
local.x() += bearing.x() * wr;
|
||||
local.y() += bearing.y() * hr;
|
||||
|
||||
|
||||
// Adjust coordinates and texture coordinates to avoid
|
||||
// clipping the edges of antialiased characters.
|
||||
osg::Vec2 mintc = glyph->getMinTexCoord();
|
||||
osg::Vec2 maxtc = glyph->getMaxTexCoord();
|
||||
osg::Vec2 vDiff = maxtc - mintc;
|
||||
|
||||
float fHorizTCMargin = 1.0f / glyph->getTexture()->getTextureWidth();
|
||||
float fVertTCMargin = 1.0f / glyph->getTexture()->getTextureHeight();
|
||||
float fHorizQuadMargin = vDiff.x() == 0.0f ? 0.0f : width * fHorizTCMargin / vDiff.x();
|
||||
float fVertQuadMargin = vDiff.y() == 0.0f ? 0.0f : height * fVertTCMargin / vDiff.y();
|
||||
|
||||
mintc.x() -= fHorizTCMargin;
|
||||
mintc.y() -= fVertTCMargin;
|
||||
maxtc.x() += fHorizTCMargin;
|
||||
maxtc.y() += fVertTCMargin;
|
||||
osg::Vec2 minc = local+osg::Vec2(0.0f-fHorizQuadMargin,0.0f-fVertQuadMargin);
|
||||
osg::Vec2 maxc = local+osg::Vec2(width+fHorizQuadMargin,height+fVertQuadMargin);
|
||||
|
||||
addGlyphQuad(glyph, minc, maxc, mintc, maxtc);
|
||||
|
||||
// move the cursor onto the next character.
|
||||
// also expand bounding box
|
||||
switch(_layout)
|
||||
const Glyph::TextureInfo* info = glyph->getOrCreateTextureInfo(_shaderTechnique);
|
||||
if (info)
|
||||
{
|
||||
case LEFT_TO_RIGHT:
|
||||
cursor.x() += glyph->getHorizontalAdvance() * wr;
|
||||
_textBB.expandBy(osg::Vec3(minc.x(), minc.y(), 0.0f)); //lower left corner
|
||||
_textBB.expandBy(osg::Vec3(maxc.x(), maxc.y(), 0.0f)); //upper right corner
|
||||
break;
|
||||
case VERTICAL:
|
||||
cursor.y() -= glyph->getVerticalAdvance() * hr;
|
||||
_textBB.expandBy(osg::Vec3(minc.x(),maxc.y(),0.0f)); //upper left corner
|
||||
_textBB.expandBy(osg::Vec3(maxc.x(),minc.y(),0.0f)); //lower right corner
|
||||
break;
|
||||
case RIGHT_TO_LEFT:
|
||||
_textBB.expandBy(osg::Vec3(maxc.x(),minc.y(),0.0f)); //lower right corner
|
||||
_textBB.expandBy(osg::Vec3(minc.x(),maxc.y(),0.0f)); //upper left corner
|
||||
break;
|
||||
// Adjust coordinates and texture coordinates to avoid
|
||||
// clipping the edges of antialiased characters.
|
||||
osg::Vec2 mintc = info->minTexCoord;
|
||||
osg::Vec2 maxtc = info->maxTexCoord;
|
||||
osg::Vec2 vDiff = maxtc - mintc;
|
||||
float texelMargin = info->texelMargin;
|
||||
|
||||
float fHorizTCMargin = texelMargin / info->texture->getTextureWidth();
|
||||
float fVertTCMargin = texelMargin / info->texture->getTextureHeight();
|
||||
float fHorizQuadMargin = vDiff.x() == 0.0f ? 0.0f : width * fHorizTCMargin / vDiff.x();
|
||||
float fVertQuadMargin = vDiff.y() == 0.0f ? 0.0f : height * fVertTCMargin / vDiff.y();
|
||||
|
||||
mintc.x() -= fHorizTCMargin;
|
||||
mintc.y() -= fVertTCMargin;
|
||||
maxtc.x() += fHorizTCMargin;
|
||||
maxtc.y() += fVertTCMargin;
|
||||
osg::Vec2 minc = local+osg::Vec2(0.0f-fHorizQuadMargin,0.0f-fVertQuadMargin);
|
||||
osg::Vec2 maxc = local+osg::Vec2(width+fHorizQuadMargin,height+fVertQuadMargin);
|
||||
|
||||
addGlyphQuad(glyph, minc, maxc, mintc, maxtc);
|
||||
|
||||
// move the cursor onto the next character.
|
||||
// also expand bounding box
|
||||
switch(_layout)
|
||||
{
|
||||
case LEFT_TO_RIGHT:
|
||||
cursor.x() += glyph->getHorizontalAdvance() * wr;
|
||||
_textBB.expandBy(osg::Vec3(minc.x(), minc.y(), 0.0f)); //lower left corner
|
||||
_textBB.expandBy(osg::Vec3(maxc.x(), maxc.y(), 0.0f)); //upper right corner
|
||||
break;
|
||||
case VERTICAL:
|
||||
cursor.y() -= glyph->getVerticalAdvance() * hr;
|
||||
_textBB.expandBy(osg::Vec3(minc.x(),maxc.y(),0.0f)); //upper left corner
|
||||
_textBB.expandBy(osg::Vec3(maxc.x(),minc.y(),0.0f)); //lower right corner
|
||||
break;
|
||||
case RIGHT_TO_LEFT:
|
||||
_textBB.expandBy(osg::Vec3(maxc.x(),minc.y(),0.0f)); //lower right corner
|
||||
_textBB.expandBy(osg::Vec3(minc.x(),maxc.y(),0.0f)); //upper left corner
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OSG_NOTICE<<"No TextureInfo for "<<charcode<<std::endl;
|
||||
}
|
||||
|
||||
previous_charcode = charcode;
|
||||
@@ -622,153 +787,10 @@ void Text::computePositionsImplementation()
|
||||
{
|
||||
TextBase::computePositionsImplementation();
|
||||
|
||||
computeBackdropPositions();
|
||||
computeBackdropBoundingBox();
|
||||
computeBoundingBoxMargin();
|
||||
}
|
||||
|
||||
// Presumes the atc matrix is already up-to-date
|
||||
void Text::computeBackdropPositions()
|
||||
{
|
||||
if(_backdropType == NONE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float avg_width = 0.0f;
|
||||
float avg_height = 0.0f;
|
||||
|
||||
// FIXME: OPTIMIZE: This function produces the same value regardless of contextID.
|
||||
// Since we tend to loop over contextID, we should cache this value some how
|
||||
// instead of recomputing it each time.
|
||||
bool is_valid_size = computeAverageGlyphWidthAndHeight(avg_width, avg_height);
|
||||
if (!is_valid_size) return;
|
||||
|
||||
unsigned int backdrop_index;
|
||||
unsigned int max_backdrop_index;
|
||||
if(_backdropType == OUTLINE)
|
||||
{
|
||||
// For outline, we want to draw the in every direction
|
||||
backdrop_index = 1;
|
||||
max_backdrop_index = backdrop_index+8;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Yes, this may seem a little strange,
|
||||
// but since the code is using references,
|
||||
// I would have to duplicate the following code twice
|
||||
// for each part of the if/else because I can't
|
||||
// declare a reference without setting it immediately
|
||||
// and it wouldn't survive the scope.
|
||||
// So it happens that the _backdropType value matches
|
||||
// the index in the array I want to store the coordinates
|
||||
// in. So I'll just setup the for-loop so it only does
|
||||
// the one direction I'm interested in.
|
||||
backdrop_index = _backdropType+1;
|
||||
max_backdrop_index = backdrop_index+1;
|
||||
}
|
||||
|
||||
for( ; backdrop_index < max_backdrop_index; backdrop_index++)
|
||||
{
|
||||
float horizontal_shift_direction;
|
||||
float vertical_shift_direction;
|
||||
switch(backdrop_index)
|
||||
{
|
||||
case DROP_SHADOW_BOTTOM_RIGHT:
|
||||
{
|
||||
horizontal_shift_direction = 1.0f;
|
||||
vertical_shift_direction = -1.0f;
|
||||
break;
|
||||
}
|
||||
case DROP_SHADOW_CENTER_RIGHT:
|
||||
{
|
||||
horizontal_shift_direction = 1.0f;
|
||||
vertical_shift_direction = 0.0f;
|
||||
break;
|
||||
}
|
||||
case DROP_SHADOW_TOP_RIGHT:
|
||||
{
|
||||
horizontal_shift_direction = 1.0f;
|
||||
vertical_shift_direction = 1.0f;
|
||||
break;
|
||||
}
|
||||
case DROP_SHADOW_BOTTOM_CENTER:
|
||||
{
|
||||
horizontal_shift_direction = 0.0f;
|
||||
vertical_shift_direction = -1.0f;
|
||||
break;
|
||||
}
|
||||
case DROP_SHADOW_TOP_CENTER:
|
||||
{
|
||||
horizontal_shift_direction = 0.0f;
|
||||
vertical_shift_direction = 1.0f;
|
||||
break;
|
||||
}
|
||||
case DROP_SHADOW_BOTTOM_LEFT:
|
||||
{
|
||||
horizontal_shift_direction = -1.0f;
|
||||
vertical_shift_direction = -1.0f;
|
||||
break;
|
||||
}
|
||||
case DROP_SHADOW_CENTER_LEFT:
|
||||
{
|
||||
horizontal_shift_direction = -1.0f;
|
||||
vertical_shift_direction = 0.0f;
|
||||
break;
|
||||
}
|
||||
case DROP_SHADOW_TOP_LEFT:
|
||||
{
|
||||
horizontal_shift_direction = -1.0f;
|
||||
vertical_shift_direction = 1.0f;
|
||||
break;
|
||||
}
|
||||
default: // error
|
||||
{
|
||||
horizontal_shift_direction = 1.0f;
|
||||
vertical_shift_direction = -1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// now apply matrix to the glyphs.
|
||||
for(TextureGlyphQuadMap::iterator titr=_textureGlyphQuadMap.begin();
|
||||
titr!=_textureGlyphQuadMap.end();
|
||||
++titr)
|
||||
{
|
||||
GlyphQuads& glyphquad = titr->second;
|
||||
|
||||
osg::DrawElements* src_primitives = glyphquad._primitives[0].get();
|
||||
|
||||
for(unsigned int i=glyphquad._primitives.size(); i<=backdrop_index; ++i)
|
||||
{
|
||||
osg::DrawElementsUShort* dst_primitives = new osg::DrawElementsUShort(GL_TRIANGLES);
|
||||
dst_primitives->setBufferObject(src_primitives->getBufferObject());
|
||||
glyphquad._primitives.push_back(dst_primitives);
|
||||
}
|
||||
|
||||
osg::DrawElements* dst_primitives = glyphquad._primitives[backdrop_index].get();
|
||||
dst_primitives->resizeElements(0);
|
||||
|
||||
unsigned int numCoords = src_primitives->getNumIndices();
|
||||
|
||||
Coords& src_coords = _coords;
|
||||
TexCoords& src_texcoords = _texcoords;
|
||||
|
||||
Coords& dst_coords = _coords;
|
||||
TexCoords& dst_texcoords = _texcoords;
|
||||
|
||||
for(unsigned int i=0;i<numCoords;++i)
|
||||
{
|
||||
unsigned int si = (*src_primitives).getElement(i);
|
||||
osg::Vec3 v(horizontal_shift_direction * _backdropHorizontalOffset * avg_width + (*src_coords)[si].x(), vertical_shift_direction * _backdropVerticalOffset * avg_height + (*src_coords)[si].y(), 0.0f);
|
||||
unsigned int di = dst_coords->size();
|
||||
(*dst_primitives).addElement(di);
|
||||
(*dst_coords).push_back(v);
|
||||
(*dst_texcoords).push_back((*src_texcoords)[si]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This method adjusts the bounding box to account for the expanded area caused by the backdrop.
|
||||
// This assumes that the bounding box has already been computed for the text without the backdrop.
|
||||
void Text::computeBackdropBoundingBox()
|
||||
@@ -1095,6 +1117,8 @@ void Text::drawImplementation(osg::RenderInfo& renderInfo) const
|
||||
|
||||
void Text::drawImplementationSinglePass(osg::State& state, const osg::Vec4& colorMultiplier) const
|
||||
{
|
||||
if (colorMultiplier.a()==0.0f || _color.a()==0.0f) return;
|
||||
|
||||
osg::VertexArrayState* vas = state.getCurrentVertexArrayState();
|
||||
bool usingVertexBufferObjects = state.useVertexBufferObject(_supportsVertexBufferObjects && _useVertexBufferObjects);
|
||||
bool usingVertexArrayObjects = usingVertexBufferObjects && state.useVertexArrayObject(_useVertexArrayObject);
|
||||
@@ -1117,7 +1141,6 @@ void Text::drawImplementationSinglePass(osg::State& state, const osg::Vec4& colo
|
||||
}
|
||||
|
||||
if (_drawMode & TEXT)
|
||||
// if (false)
|
||||
{
|
||||
for(TextureGlyphQuadMap::const_iterator titr=_textureGlyphQuadMap.begin();
|
||||
titr!=_textureGlyphQuadMap.end();
|
||||
@@ -1128,33 +1151,6 @@ void Text::drawImplementationSinglePass(osg::State& state, const osg::Vec4& colo
|
||||
|
||||
const GlyphQuads& glyphquad = titr->second;
|
||||
|
||||
#if 1
|
||||
if(_backdropType != NONE)
|
||||
{
|
||||
unsigned int backdrop_index;
|
||||
unsigned int max_backdrop_index;
|
||||
if(_backdropType == OUTLINE)
|
||||
{
|
||||
backdrop_index = 1;
|
||||
max_backdrop_index = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
backdrop_index = _backdropType+1;
|
||||
max_backdrop_index = backdrop_index+1;
|
||||
}
|
||||
|
||||
if (max_backdrop_index>glyphquad._primitives.size()) max_backdrop_index=glyphquad._primitives.size();
|
||||
|
||||
state.disableColorPointer();
|
||||
state.Color(_backdropColor.r(),_backdropColor.g(),_backdropColor.b(),_backdropColor.a());
|
||||
|
||||
for( ; backdrop_index < max_backdrop_index; backdrop_index++)
|
||||
{
|
||||
glyphquad._primitives[backdrop_index]->draw(state, usingVertexBufferObjects);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(_colorGradientMode == SOLID)
|
||||
{
|
||||
vas->disableColorArray(state);
|
||||
@@ -1168,7 +1164,7 @@ void Text::drawImplementationSinglePass(osg::State& state, const osg::Vec4& colo
|
||||
}
|
||||
}
|
||||
|
||||
glyphquad._primitives[0]->draw(state, usingVertexBufferObjects);
|
||||
glyphquad._primitives->draw(state, usingVertexBufferObjects);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1216,9 +1212,6 @@ void Text::drawImplementation(osg::State& state, const osg::Vec4& colorMultiplie
|
||||
vas->applyDisablingOfVertexAttributes(state);
|
||||
}
|
||||
|
||||
#if 0
|
||||
drawImplementationSinglePass(state, colorMultiplier);
|
||||
#else
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
drawImplementationSinglePass(state, colorMultiplier);
|
||||
@@ -1235,7 +1228,6 @@ void Text::drawImplementation(osg::State& state, const osg::Vec4& colorMultiplie
|
||||
}
|
||||
|
||||
state.haveAppliedAttribute(osg::StateAttribute::DEPTH);
|
||||
#endif
|
||||
|
||||
if (usingVertexBufferObjects && !usingVertexArrayObjects)
|
||||
{
|
||||
@@ -1273,16 +1265,16 @@ void Text::accept(osg::PrimitiveFunctor& pf) const
|
||||
++titr)
|
||||
{
|
||||
const GlyphQuads& glyphquad = titr->second;
|
||||
if (!glyphquad._primitives.empty())
|
||||
if (glyphquad._primitives.valid())
|
||||
{
|
||||
const osg::DrawElementsUShort* drawElementsUShort = dynamic_cast<const osg::DrawElementsUShort*>(glyphquad._primitives[0].get());
|
||||
const osg::DrawElementsUShort* drawElementsUShort = dynamic_cast<const osg::DrawElementsUShort*>(glyphquad._primitives.get());
|
||||
if (drawElementsUShort)
|
||||
{
|
||||
pf.drawElements(GL_TRIANGLES, drawElementsUShort->size(), &(drawElementsUShort->front()));
|
||||
}
|
||||
else
|
||||
{
|
||||
const osg::DrawElementsUInt* drawElementsUInt = dynamic_cast<const osg::DrawElementsUInt*>(glyphquad._primitives[0].get());
|
||||
const osg::DrawElementsUInt* drawElementsUInt = dynamic_cast<const osg::DrawElementsUInt*>(glyphquad._primitives.get());
|
||||
if (drawElementsUInt)
|
||||
{
|
||||
pf.drawElements(GL_TRIANGLES, drawElementsUInt->size(), &(drawElementsUInt->front()));
|
||||
@@ -1322,22 +1314,19 @@ void Text::setBackdropType(BackdropType type)
|
||||
if (_backdropType==type) return;
|
||||
|
||||
_backdropType = type;
|
||||
|
||||
assignStateSet();
|
||||
|
||||
computeGlyphRepresentation();
|
||||
}
|
||||
|
||||
void Text::setBackdropImplementation(BackdropImplementation implementation)
|
||||
{
|
||||
if (_backdropImplementation==implementation) return;
|
||||
|
||||
_backdropImplementation = implementation;
|
||||
computeGlyphRepresentation();
|
||||
}
|
||||
|
||||
|
||||
void Text::setBackdropOffset(float offset)
|
||||
{
|
||||
_backdropHorizontalOffset = offset;
|
||||
_backdropVerticalOffset = offset;
|
||||
|
||||
assignStateSet();
|
||||
|
||||
computeGlyphRepresentation();
|
||||
}
|
||||
|
||||
@@ -1345,12 +1334,17 @@ void Text::setBackdropOffset(float horizontal, float vertical)
|
||||
{
|
||||
_backdropHorizontalOffset = horizontal;
|
||||
_backdropVerticalOffset = vertical;
|
||||
|
||||
assignStateSet();
|
||||
|
||||
computeGlyphRepresentation();
|
||||
}
|
||||
|
||||
void Text::setBackdropColor(const osg::Vec4& color)
|
||||
{
|
||||
_backdropColor = color;
|
||||
|
||||
assignStateSet();
|
||||
}
|
||||
|
||||
void Text::setColorGradientMode(ColorGradientMode mode)
|
||||
@@ -1391,20 +1385,10 @@ Text::GlyphQuads::GlyphQuads(const GlyphQuads&)
|
||||
|
||||
void Text::GlyphQuads::resizeGLObjectBuffers(unsigned int maxSize)
|
||||
{
|
||||
for(Primitives::iterator itr = _primitives.begin();
|
||||
itr != _primitives.end();
|
||||
++itr)
|
||||
{
|
||||
(*itr)->resizeGLObjectBuffers(maxSize);
|
||||
}
|
||||
if (_primitives.valid()) _primitives->resizeGLObjectBuffers(maxSize);
|
||||
}
|
||||
|
||||
void Text::GlyphQuads::releaseGLObjects(osg::State* state) const
|
||||
{
|
||||
for(Primitives::const_iterator itr = _primitives.begin();
|
||||
itr != _primitives.end();
|
||||
++itr)
|
||||
{
|
||||
(*itr)->releaseGLObjects(state);
|
||||
}
|
||||
if (_primitives.valid()) _primitives->releaseGLObjects(state);
|
||||
}
|
||||
|
||||
@@ -438,9 +438,11 @@ void Text3D::computeGlyphRepresentation()
|
||||
{
|
||||
(*_coords)[i] += position;
|
||||
}
|
||||
_coords->dirty();
|
||||
|
||||
// copy normals
|
||||
_normals->insert(_normals->end(), src_normals->begin(), src_normals->end());
|
||||
_normals->dirty();
|
||||
|
||||
copyAndOffsetPrimitiveSets(_frontPrimitiveSetList, it->_glyphGeometry->getFrontPrimitiveSetList(), base);
|
||||
copyAndOffsetPrimitiveSets(_wallPrimitiveSetList, it->_glyphGeometry->getWallPrimitiveSetList(), base);
|
||||
|
||||
@@ -50,7 +50,6 @@ TextBase::TextBase():
|
||||
_lineCount(0),
|
||||
_glyphNormalized(false)
|
||||
{
|
||||
setStateSet(Font::getDefaultFont()->getStateSet());
|
||||
setUseDisplayList(false);
|
||||
setSupportsDisplayList(false);
|
||||
|
||||
@@ -89,6 +88,11 @@ TextBase::~TextBase()
|
||||
{
|
||||
}
|
||||
|
||||
osg::StateSet* TextBase::createStateSet()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TextBase::initArraysAndBuffers()
|
||||
{
|
||||
_vbo = new osg::VertexBufferObject;
|
||||
@@ -182,6 +186,10 @@ void TextBase::setColor(const osg::Vec4& color)
|
||||
_color = color;
|
||||
}
|
||||
|
||||
void TextBase::assignStateSet()
|
||||
{
|
||||
setStateSet(createStateSet());
|
||||
}
|
||||
|
||||
void TextBase::setFont(osg::ref_ptr<Font> font)
|
||||
{
|
||||
@@ -189,6 +197,8 @@ void TextBase::setFont(osg::ref_ptr<Font> font)
|
||||
|
||||
_font = font;
|
||||
|
||||
assignStateSet();
|
||||
|
||||
computeGlyphRepresentation();
|
||||
}
|
||||
|
||||
@@ -203,6 +213,9 @@ void TextBase::setFontResolution(unsigned int width, unsigned int height)
|
||||
if (_fontSize==size) return;
|
||||
|
||||
_fontSize = size;
|
||||
|
||||
assignStateSet();
|
||||
|
||||
computeGlyphRepresentation();
|
||||
}
|
||||
|
||||
|
||||
257
src/osgText/shaders/text_frag.cpp
Normal file
257
src/osgText/shaders/text_frag.cpp
Normal file
@@ -0,0 +1,257 @@
|
||||
char text_frag[] = "$OSG_GLSL_VERSION\n"
|
||||
"\n"
|
||||
"#pragma import_defines( BACKDROP_COLOR, SHADOW, OUTLINE, SIGNED_DISTNACE_FIELD, TEXTURE_DIMENSION, GLYPH_DIMENSION)\n"
|
||||
"\n"
|
||||
"#ifdef GL_ES\n"
|
||||
" #extension GL_OES_standard_derivatives : enable\n"
|
||||
" #ifndef GL_OES_standard_derivatives\n"
|
||||
" #undef SIGNED_DISTNACE_FIELD\n"
|
||||
" #endif\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"#if !defined(GL_ES)\n"
|
||||
" #if __VERSION__>=400\n"
|
||||
" #define osg_TextureQueryLOD textureQueryLod\n"
|
||||
" #else\n"
|
||||
" #extension GL_ARB_texture_query_lod : enable\n"
|
||||
" #ifdef GL_ARB_texture_query_lod\n"
|
||||
" #define osg_TextureQueryLOD textureQueryLOD\n"
|
||||
" #endif\n"
|
||||
" #endif\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"$OSG_PRECISION_FLOAT\n"
|
||||
"\n"
|
||||
"#if __VERSION__>=130\n"
|
||||
" #define TEXTURE texture\n"
|
||||
" #define TEXTURELOD textureLod\n"
|
||||
" out vec4 osg_FragColor;\n"
|
||||
"#else\n"
|
||||
" #define TEXTURE texture2D\n"
|
||||
" #define TEXTURELOD texture2DLod\n"
|
||||
" #define osg_FragColor gl_FragColor\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#if !defined(GL_ES) && __VERSION__>=130\n"
|
||||
" #define ALPHA r\n"
|
||||
" #define SDF g\n"
|
||||
"#else\n"
|
||||
" #define ALPHA a\n"
|
||||
" #define SDF r\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"uniform sampler2D glyphTexture;\n"
|
||||
"\n"
|
||||
"$OSG_VARYING_IN vec2 texCoord;\n"
|
||||
"$OSG_VARYING_IN vec4 vertexColor;\n"
|
||||
"\n"
|
||||
"#ifndef TEXTURE_DIMENSION\n"
|
||||
"const float TEXTURE_DIMENSION = 1024.0;\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"#ifndef GLYPH_DIMENSION\n"
|
||||
"const float GLYPH_DIMENSION = 32.0;\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"#ifdef SIGNED_DISTNACE_FIELD\n"
|
||||
"\n"
|
||||
"float distanceFromEdge(vec2 tc)\n"
|
||||
"{\n"
|
||||
" float center_alpha = TEXTURELOD(glyphTexture, tc, 0.0).SDF;\n"
|
||||
" if (center_alpha==0.0) return -1.0;\n"
|
||||
"\n"
|
||||
" //float distance_scale = (1.0/4.0)*1.41;\n"
|
||||
" float distance_scale = (1.0/6.0)*1.41;\n"
|
||||
" //float distance_scale = (1.0/8.0)*1.41;\n"
|
||||
"\n"
|
||||
" return (center_alpha-0.5)*distance_scale;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"vec4 distanceFieldColorSample(float edge_distance, float blend_width, float blend_half_width)\n"
|
||||
"{\n"
|
||||
"#ifdef OUTLINE\n"
|
||||
" float outline_width = OUTLINE*0.5;\n"
|
||||
" if (edge_distance>blend_half_width)\n"
|
||||
" {\n"
|
||||
" return vertexColor;\n"
|
||||
" }\n"
|
||||
" else if (edge_distance>-blend_half_width)\n"
|
||||
" {\n"
|
||||
" return mix(vertexColor, vec4(BACKDROP_COLOR.rgb, BACKDROP_COLOR.a*vertexColor.a), smoothstep(0.0, 1.0, (blend_half_width-edge_distance)/(blend_width)));\n"
|
||||
" }\n"
|
||||
" else if (edge_distance>(blend_half_width-outline_width))\n"
|
||||
" {\n"
|
||||
" return vec4(BACKDROP_COLOR.rgb, BACKDROP_COLOR.a*vertexColor.a);\n"
|
||||
" }\n"
|
||||
" else if (edge_distance>-(outline_width+blend_half_width))\n"
|
||||
" {\n"
|
||||
" return vec4(BACKDROP_COLOR.rgb, vertexColor.a * ((blend_half_width+outline_width+edge_distance)/blend_width));\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
" {\n"
|
||||
" return vec4(0.0, 0.0, 0.0, 0.0);\n"
|
||||
" }\n"
|
||||
"#else\n"
|
||||
" if (edge_distance>blend_half_width)\n"
|
||||
" {\n"
|
||||
" return vertexColor;\n"
|
||||
" }\n"
|
||||
" else if (edge_distance>-blend_half_width)\n"
|
||||
" {\n"
|
||||
" return vec4(vertexColor.rgb, vertexColor.a * smoothstep(1.0, 0.0, (blend_half_width-edge_distance)/(blend_width)));\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
" {\n"
|
||||
" return vec4(0.0, 0.0, 0.0, 0.0);\n"
|
||||
" }\n"
|
||||
"#endif\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"vec4 textColor(vec2 src_texCoord)\n"
|
||||
"{\n"
|
||||
" float sample_distance_scale = 0.75;\n"
|
||||
" vec2 dx = dFdx(src_texCoord)*sample_distance_scale;\n"
|
||||
" vec2 dy = dFdy(src_texCoord)*sample_distance_scale;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
" float distance_across_pixel = length(dx+dy)*(TEXTURE_DIMENSION/GLYPH_DIMENSION);\n"
|
||||
"\n"
|
||||
" // compute the appropriate number of samples required to avoid aliasing.\n"
|
||||
" int maxNumSamplesAcrossSide = 4;\n"
|
||||
"\n"
|
||||
" int numSamplesX = int(TEXTURE_DIMENSION * length(dx));\n"
|
||||
" int numSamplesY = int(TEXTURE_DIMENSION * length(dy));\n"
|
||||
" if (numSamplesX<2) numSamplesX = 2;\n"
|
||||
" if (numSamplesY<2) numSamplesY = 2;\n"
|
||||
" if (numSamplesX>maxNumSamplesAcrossSide) numSamplesX = maxNumSamplesAcrossSide;\n"
|
||||
" if (numSamplesY>maxNumSamplesAcrossSide) numSamplesY = maxNumSamplesAcrossSide;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
" vec2 delta_tx = dx/float(numSamplesX-1);\n"
|
||||
" vec2 delta_ty = dy/float(numSamplesY-1);\n"
|
||||
"\n"
|
||||
" float numSamples = float(numSamplesX)*float(numSamplesY);\n"
|
||||
" float scale = 1.0/numSamples;\n"
|
||||
" vec4 total_color = vec4(0.0,0.0,0.0,0.0);\n"
|
||||
"\n"
|
||||
" float blend_width = 1.5*distance_across_pixel/numSamples;\n"
|
||||
" float blend_half_width = blend_width*0.5;\n"
|
||||
"\n"
|
||||
" // check whether fragment is wholly within or outwith glyph body+outline\n"
|
||||
" float cd = distanceFromEdge(src_texCoord); // central distance (distance from center to edge)\n"
|
||||
" if (cd-blend_half_width>distance_across_pixel) return vertexColor; // pixel fully within glyph body\n"
|
||||
"\n"
|
||||
" #ifdef OUTLINE\n"
|
||||
" float outline_width = OUTLINE*0.5;\n"
|
||||
" if ((-cd-outline_width-blend_half_width)>distance_across_pixel) return vec4(0.0, 0.0, 0.0, 0.0); // pixel fully outside outline+glyph body\n"
|
||||
" #else\n"
|
||||
" if (-cd-blend_half_width>distance_across_pixel) return vec4(0.0, 0.0, 0.0, 0.0); // pixel fully outside glyph body\n"
|
||||
" #endif\n"
|
||||
"\n"
|
||||
"\n"
|
||||
" // use multi-sampling to provide high quality antialised fragments\n"
|
||||
" vec2 origin = src_texCoord - dx*0.5 - dy*0.5;\n"
|
||||
" for(;numSamplesY>0; --numSamplesY)\n"
|
||||
" {\n"
|
||||
" vec2 pos = origin;\n"
|
||||
" int numX = numSamplesX;\n"
|
||||
" for(;numX>0; --numX)\n"
|
||||
" {\n"
|
||||
" vec4 c = distanceFieldColorSample(distanceFromEdge(pos), blend_width, blend_half_width);\n"
|
||||
" total_color = total_color + c * c.a;\n"
|
||||
" pos += delta_tx;\n"
|
||||
" }\n"
|
||||
" origin += delta_ty;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" total_color.rgb /= total_color.a;\n"
|
||||
" total_color.a *= scale;\n"
|
||||
"\n"
|
||||
" return total_color;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"#else\n"
|
||||
"\n"
|
||||
"vec4 textColor(vec2 src_texCoord)\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"#ifdef OUTLINE\n"
|
||||
"\n"
|
||||
" float alpha = TEXTURE(glyphTexture, src_texCoord).ALPHA;\n"
|
||||
" float delta_tc = 1.6*OUTLINE*GLYPH_DIMENSION/TEXTURE_DIMENSION;\n"
|
||||
"\n"
|
||||
" float outline_alpha = alpha;\n"
|
||||
" vec2 origin = src_texCoord-vec2(delta_tc*0.5, delta_tc*0.5);\n"
|
||||
"\n"
|
||||
" float numSamples = 3.0;\n"
|
||||
" delta_tc = delta_tc/(numSamples-1.0);\n"
|
||||
"\n"
|
||||
" float background_alpha = 1.0;\n"
|
||||
"\n"
|
||||
" for(float i=0.0; i<numSamples; ++i)\n"
|
||||
" {\n"
|
||||
" for(float j=0.0; j<numSamples; ++j)\n"
|
||||
" {\n"
|
||||
" float local_alpha = TEXTURE(glyphTexture, origin + vec2(i*delta_tc, j*delta_tc)).ALPHA;\n"
|
||||
" outline_alpha = max(outline_alpha, local_alpha);\n"
|
||||
" background_alpha = background_alpha * (1.0-local_alpha);\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" #ifdef osg_TextureQueryLOD\n"
|
||||
" float mipmapLevel = osg_TextureQueryLOD(glyphTexture, src_texCoord).x;\n"
|
||||
" if (mipmapLevel<1.0)\n"
|
||||
" {\n"
|
||||
" outline_alpha = mix(1.0-background_alpha, outline_alpha, mipmapLevel/1.0);\n"
|
||||
" }\n"
|
||||
" #endif\n"
|
||||
"\n"
|
||||
" if (outline_alpha<alpha) outline_alpha = alpha;\n"
|
||||
" if (outline_alpha>1.0) outline_alpha = 1.0;\n"
|
||||
"\n"
|
||||
" if (outline_alpha==0.0) return vec4(0.0, 0.0, 0.0, 0.0); // outside glyph and outline\n"
|
||||
"\n"
|
||||
" vec4 color = mix(BACKDROP_COLOR, vertexColor, smoothstep(0.0, 1.0, alpha));\n"
|
||||
" color.a = vertexColor.a * smoothstep(0.0, 1.0, outline_alpha);\n"
|
||||
"\n"
|
||||
" return color;\n"
|
||||
"\n"
|
||||
"#else\n"
|
||||
"\n"
|
||||
" float alpha = TEXTURE(glyphTexture, src_texCoord).ALPHA;\n"
|
||||
" if (alpha==0.0) vec4(0.0, 0.0, 0.0, 0.0);\n"
|
||||
" return vec4(vertexColor.rgb, vertexColor.a * alpha);\n"
|
||||
"\n"
|
||||
"#endif\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"void main(void)\n"
|
||||
"{\n"
|
||||
" if (texCoord.x<0.0 && texCoord.y<0.0)\n"
|
||||
" {\n"
|
||||
" osg_FragColor = vertexColor;\n"
|
||||
" return;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
"#ifdef SHADOW\n"
|
||||
" float scale = -1.0*GLYPH_DIMENSION/TEXTURE_DIMENSION;\n"
|
||||
" vec2 delta_tc = SHADOW*scale;\n"
|
||||
" vec4 shadow_color = textColor(texCoord+delta_tc);\n"
|
||||
" shadow_color.rgb = BACKDROP_COLOR.rgb;\n"
|
||||
"\n"
|
||||
" vec4 glyph_color = textColor(texCoord);\n"
|
||||
" vec4 color = mix(shadow_color, glyph_color, glyph_color.a);\n"
|
||||
"#else\n"
|
||||
" vec4 color = textColor(texCoord);\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
" if (color.a==0.0) discard;\n"
|
||||
"\n"
|
||||
" osg_FragColor = color;\n"
|
||||
"}\n"
|
||||
"\n";
|
||||
13
src/osgText/shaders/text_vert.cpp
Normal file
13
src/osgText/shaders/text_vert.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
char text_vert[] = "$OSG_GLSL_VERSION\n"
|
||||
"$OSG_PRECISION_FLOAT\n"
|
||||
"\n"
|
||||
"$OSG_VARYING_OUT vec2 texCoord;\n"
|
||||
"$OSG_VARYING_OUT vec4 vertexColor;\n"
|
||||
"\n"
|
||||
"void main(void)\n"
|
||||
"{\n"
|
||||
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
|
||||
" texCoord = gl_MultiTexCoord0.xy;\n"
|
||||
" vertexColor = gl_Color;\n"
|
||||
"}\n"
|
||||
"\n";
|
||||
@@ -153,6 +153,23 @@ void GLObjectsVisitor::apply(osg::StateSet& stateset)
|
||||
}
|
||||
}
|
||||
|
||||
void GLObjectsVisitor::compile(osg::Node& node)
|
||||
{
|
||||
if (_renderInfo.getState())
|
||||
{
|
||||
node.accept(*this);
|
||||
|
||||
if (_lastCompiledProgram.valid())
|
||||
{
|
||||
osg::State* state = _renderInfo.getState();
|
||||
osg::GLExtensions* extensions = state->get<osg::GLExtensions>();
|
||||
extensions->glUseProgram(0);
|
||||
_renderInfo.getState()->setLastAppliedProgramObject(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// GLObjectsOperation
|
||||
|
||||
@@ -299,13 +299,17 @@ struct IntersectFunctor
|
||||
return;
|
||||
}
|
||||
|
||||
Vec3 in = v0*r0 + v1*r1 + v2*r2;
|
||||
// Remap ratio into the range of LineSegment
|
||||
const osg::Vec3d& lsStart = _settings->_lineSegIntersector->getStart();
|
||||
const osg::Vec3d& lsEnd = _settings->_lineSegIntersector->getEnd();
|
||||
double remap_ratio = ((_start - lsStart).length() + r*_length)/(lsEnd - lsStart).length();
|
||||
|
||||
Vec3 in = lsStart*(1.0 - remap_ratio) + lsEnd*remap_ratio; // == v0*r0 + v1*r1 + v2*r2;
|
||||
Vec3 normal = E1^E2;
|
||||
normal.normalize();
|
||||
|
||||
|
||||
LineSegmentIntersector::Intersection hit;
|
||||
hit.ratio = r;
|
||||
hit.ratio = remap_ratio;
|
||||
hit.matrix = _settings->_iv->getModelMatrix();
|
||||
hit.nodePath = _settings->_iv->getNodePath();
|
||||
hit.drawable = _settings->_drawable;
|
||||
@@ -500,7 +504,7 @@ void LineSegmentIntersector::intersect(osgUtil::IntersectionVisitor& iv, osg::Dr
|
||||
if (reachedLimit()) return;
|
||||
|
||||
osg::Vec3d s(_start), e(_end);
|
||||
if ( !intersectAndClip( s, e, drawable->getBoundingBox() ) ) return;
|
||||
if ( drawable->isCullingActive() && !intersectAndClip( s, e, drawable->getBoundingBox() ) ) return;
|
||||
|
||||
if (iv.getDoDummyTraversal()) return;
|
||||
|
||||
|
||||
@@ -1100,3 +1100,6 @@ public:
|
||||
REGISTER_WINDOWINGSYSTEMINTERFACE(Carbon, CarbonWindowingSystemInterface)
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -199,7 +199,7 @@ static NSRect convertToQuartzCoordinates(const NSRect& rect)
|
||||
// the app-delegate, handling quit-requests
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
|
||||
@interface CocoaAppDelegate : NSObject
|
||||
@interface CocoaAppDelegate : NSObject <NSApplicationDelegate>
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -571,7 +571,6 @@ void Renderer::compile()
|
||||
{
|
||||
DEBUG_MESSAGE<<"Renderer::compile()"<<std::endl;
|
||||
|
||||
|
||||
_compileOnNextDraw = false;
|
||||
|
||||
osgUtil::SceneView* sceneView = _sceneView[0].get();
|
||||
@@ -583,7 +582,7 @@ void Renderer::compile()
|
||||
{
|
||||
osgUtil::GLObjectsVisitor glov;
|
||||
glov.setState(sceneView->getState());
|
||||
sceneView->getSceneData()->accept(glov);
|
||||
glov.compile(*(sceneView->getSceneData()));
|
||||
}
|
||||
|
||||
sceneView->getState()->checkGLErrors("After Renderer::compile");
|
||||
|
||||
@@ -134,7 +134,6 @@ void Label::setFontColor(const Color& c) {
|
||||
|
||||
void Label::setShadow(point_type offset) {
|
||||
_text->setBackdropType(osgText::Text::DROP_SHADOW_BOTTOM_RIGHT);
|
||||
_text->setBackdropImplementation(osgText::Text::NO_DEPTH_BUFFER);
|
||||
_text->setBackdropOffset(offset);
|
||||
|
||||
_calculateSize(getTextSize());
|
||||
|
||||
@@ -57,27 +57,6 @@ std::string convertBackdropTypeEnumToString(osgText::Text::BackdropType backdrop
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
osgText::Text::BackdropImplementation convertBackdropImplementationStringToEnum(std::string & str)
|
||||
{
|
||||
if (str=="POLYGON_OFFSET") return osgText::Text::POLYGON_OFFSET;
|
||||
else if (str=="NO_DEPTH_BUFFER") return osgText::Text::NO_DEPTH_BUFFER;
|
||||
else if (str=="DEPTH_RANGE") return osgText::Text::DEPTH_RANGE;
|
||||
else if (str=="STENCIL_BUFFER") return osgText::Text::STENCIL_BUFFER;
|
||||
else return static_cast<osgText::Text::BackdropImplementation>(-1);
|
||||
}
|
||||
std::string convertBackdropImplementationEnumToString(osgText::Text::BackdropImplementation backdropImplementation)
|
||||
{
|
||||
switch (backdropImplementation)
|
||||
{
|
||||
case osgText::Text::POLYGON_OFFSET: return "POLYGON_OFFSET";
|
||||
case osgText::Text::NO_DEPTH_BUFFER: return "NO_DEPTH_BUFFER";
|
||||
case osgText::Text::DEPTH_RANGE: return "DEPTH_RANGE";
|
||||
case osgText::Text::STENCIL_BUFFER: return "STENCIL_BUFFER";
|
||||
default : return "";
|
||||
}
|
||||
}
|
||||
|
||||
osgText::Text::ColorGradientMode convertColorGradientModeStringToEnum(std::string & str)
|
||||
{
|
||||
if (str=="SOLID") return osgText::Text::SOLID;
|
||||
@@ -155,12 +134,6 @@ bool Text_readLocalData(osg::Object &obj, osgDB::Input &fr)
|
||||
// backdropImplementation
|
||||
if (fr[0].matchWord("backdropImplementation"))
|
||||
{
|
||||
std::string str = fr[1].getStr();
|
||||
osgText::Text::BackdropImplementation backdropImplementation = convertBackdropImplementationStringToEnum(str);
|
||||
|
||||
if (backdropImplementation != static_cast<osgText::Text::BackdropImplementation>(-1))
|
||||
text.setBackdropImplementation(backdropImplementation);
|
||||
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
}
|
||||
@@ -254,9 +227,6 @@ bool Text_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
|
||||
osg::Vec4 c = text.getBackdropColor();
|
||||
fw.indent() << "backdropColor " << c.x() << " " << c.y() << " " << c.z() << " " << c.w() << std::endl;
|
||||
|
||||
// backdropImplementation
|
||||
fw.indent() << "backdropImplementation " << convertBackdropImplementationEnumToString(text.getBackdropImplementation()) << std::endl;
|
||||
|
||||
// colorGradientMode
|
||||
fw.indent() << "colorGradientMode " << convertColorGradientModeEnumToString(text.getColorGradientMode()) << std::endl;
|
||||
|
||||
|
||||
@@ -3,25 +3,34 @@
|
||||
USE_SERIALIZER_WRAPPER(AlphaFunc)
|
||||
USE_SERIALIZER_WRAPPER(AnimationPath)
|
||||
USE_SERIALIZER_WRAPPER(AnimationPathCallback)
|
||||
USE_SERIALIZER_WRAPPER(AtomicCounterBufferBinding)
|
||||
USE_SERIALIZER_WRAPPER(AudioSink)
|
||||
USE_SERIALIZER_WRAPPER(AudioStream)
|
||||
USE_SERIALIZER_WRAPPER(AutoTransform)
|
||||
USE_SERIALIZER_WRAPPER(Billboard)
|
||||
USE_SERIALIZER_WRAPPER(BlendColor)
|
||||
USE_SERIALIZER_WRAPPER(BlendEquation)
|
||||
USE_SERIALIZER_WRAPPER(BlendEquationi)
|
||||
USE_SERIALIZER_WRAPPER(BlendFunc)
|
||||
USE_SERIALIZER_WRAPPER(BlendFunci)
|
||||
USE_SERIALIZER_WRAPPER(BoolValueObject)
|
||||
USE_SERIALIZER_WRAPPER(Box)
|
||||
USE_SERIALIZER_WRAPPER(BufferData)
|
||||
USE_SERIALIZER_WRAPPER(BufferIndexBinding)
|
||||
USE_SERIALIZER_WRAPPER(BufferObject)
|
||||
USE_SERIALIZER_WRAPPER(Callback)
|
||||
USE_SERIALIZER_WRAPPER(CallbackObject)
|
||||
USE_SERIALIZER_WRAPPER(Camera)
|
||||
USE_SERIALIZER_WRAPPER(CameraView)
|
||||
USE_SERIALIZER_WRAPPER(Capsule)
|
||||
USE_SERIALIZER_WRAPPER(ClampColor)
|
||||
USE_SERIALIZER_WRAPPER(ClearNode)
|
||||
USE_SERIALIZER_WRAPPER(ClipNode)
|
||||
USE_SERIALIZER_WRAPPER(ClipControl)
|
||||
USE_SERIALIZER_WRAPPER(ClipPlane)
|
||||
USE_SERIALIZER_WRAPPER(ClusterCullingCallback)
|
||||
USE_SERIALIZER_WRAPPER(ColorMask)
|
||||
USE_SERIALIZER_WRAPPER(ColorMaski)
|
||||
USE_SERIALIZER_WRAPPER(ColorMatrix)
|
||||
USE_SERIALIZER_WRAPPER(CompositeShape)
|
||||
USE_SERIALIZER_WRAPPER(ComputeBoundingBoxCallback)
|
||||
@@ -32,9 +41,11 @@ USE_SERIALIZER_WRAPPER(ConvexPlanarOccluder)
|
||||
USE_SERIALIZER_WRAPPER(CoordinateSystemNode)
|
||||
USE_SERIALIZER_WRAPPER(CullFace)
|
||||
USE_SERIALIZER_WRAPPER(Cylinder)
|
||||
USE_SERIALIZER_WRAPPER(DefaultUserDataContainer)
|
||||
USE_SERIALIZER_WRAPPER(Depth)
|
||||
USE_SERIALIZER_WRAPPER(Drawable)
|
||||
USE_SERIALIZER_WRAPPER(DrawPixels)
|
||||
USE_SERIALIZER_WRAPPER(ElementBufferObject)
|
||||
USE_SERIALIZER_WRAPPER(EllipsoidModel)
|
||||
USE_SERIALIZER_WRAPPER(Fog)
|
||||
USE_SERIALIZER_WRAPPER(FragmentProgram)
|
||||
@@ -77,10 +88,14 @@ USE_SERIALIZER_WRAPPER(Projection)
|
||||
USE_SERIALIZER_WRAPPER(ProxyNode)
|
||||
USE_SERIALIZER_WRAPPER(SampleMaski)
|
||||
USE_SERIALIZER_WRAPPER(Scissor)
|
||||
USE_SERIALIZER_WRAPPER(Script)
|
||||
USE_SERIALIZER_WRAPPER(ScriptNodeCallback)
|
||||
USE_SERIALIZER_WRAPPER(Sequence)
|
||||
USE_SERIALIZER_WRAPPER(ShadeModel)
|
||||
USE_SERIALIZER_WRAPPER(Shader)
|
||||
USE_SERIALIZER_WRAPPER(ShaderAttribute)
|
||||
USE_SERIALIZER_WRAPPER(ShaderBinary)
|
||||
USE_SERIALIZER_WRAPPER(ShaderStorageBufferBinding)
|
||||
USE_SERIALIZER_WRAPPER(Shape)
|
||||
USE_SERIALIZER_WRAPPER(ShapeDrawable)
|
||||
USE_SERIALIZER_WRAPPER(Sphere)
|
||||
@@ -101,16 +116,21 @@ USE_SERIALIZER_WRAPPER(Texture1D)
|
||||
USE_SERIALIZER_WRAPPER(Texture2D)
|
||||
USE_SERIALIZER_WRAPPER(Texture2DArray)
|
||||
USE_SERIALIZER_WRAPPER(Texture3D)
|
||||
USE_SERIALIZER_WRAPPER(TextureBuffer)
|
||||
USE_SERIALIZER_WRAPPER(TextureCubeMap)
|
||||
USE_SERIALIZER_WRAPPER(TextureRectangle)
|
||||
USE_SERIALIZER_WRAPPER(TransferFunction)
|
||||
USE_SERIALIZER_WRAPPER(TransferFunction1D)
|
||||
USE_SERIALIZER_WRAPPER(Transform)
|
||||
USE_SERIALIZER_WRAPPER(TransformFeedbackBufferBinding)
|
||||
USE_SERIALIZER_WRAPPER(TriangleMesh)
|
||||
USE_SERIALIZER_WRAPPER(Uniform)
|
||||
USE_SERIALIZER_WRAPPER(UniformBufferBinding)
|
||||
USE_SERIALIZER_WRAPPER(UniformCallback)
|
||||
USE_SERIALIZER_WRAPPER(UpdateCallback)
|
||||
USE_SERIALIZER_WRAPPER(UserDataContainer)
|
||||
USE_SERIALIZER_WRAPPER(VertexAttribDivisor)
|
||||
USE_SERIALIZER_WRAPPER(VertexBufferObject)
|
||||
USE_SERIALIZER_WRAPPER(VertexProgram)
|
||||
USE_SERIALIZER_WRAPPER(Viewport)
|
||||
|
||||
@@ -164,5 +184,21 @@ USE_SERIALIZER_WRAPPER(DrawElementsUByte)
|
||||
USE_SERIALIZER_WRAPPER(DrawElementsUShort)
|
||||
USE_SERIALIZER_WRAPPER(DrawElementsUInt)
|
||||
|
||||
#ifdef OSG_HAS_MULTIDRAWARRAYS
|
||||
USE_SERIALIZER_WRAPPER(MultiDrawArrays)
|
||||
#endif
|
||||
|
||||
// PrimitiveSetIndirect
|
||||
USE_SERIALIZER_WRAPPER(IndirectCommandDrawArrays)
|
||||
USE_SERIALIZER_WRAPPER(IndirectCommandDrawElements)
|
||||
USE_SERIALIZER_WRAPPER(osgDefaultIndirectCommandDrawArrays)
|
||||
USE_SERIALIZER_WRAPPER(osgDefaultIndirectCommandDrawElements)
|
||||
USE_SERIALIZER_WRAPPER(DrawArraysIndirect)
|
||||
USE_SERIALIZER_WRAPPER(MultiDrawArraysIndirect)
|
||||
USE_SERIALIZER_WRAPPER(DrawElementsIndirect)
|
||||
USE_SERIALIZER_WRAPPER(DrawElementsIndirectUByte)
|
||||
USE_SERIALIZER_WRAPPER(DrawElementsIndirectUShort)
|
||||
USE_SERIALIZER_WRAPPER(DrawElementsIndirectUInt)
|
||||
|
||||
extern "C" void wrapper_serializer_library_osg(void) {}
|
||||
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
11
src/osgWrappers/serializers/osg/ShaderAttribute.cpp
Normal file
11
src/osgWrappers/serializers/osg/ShaderAttribute.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#include <osg/ShaderAttribute>
|
||||
#include <osgDB/ObjectWrapper>
|
||||
#include <osgDB/InputStream>
|
||||
#include <osgDB/OutputStream>
|
||||
|
||||
REGISTER_OBJECT_WRAPPER( ShaderAttribute,
|
||||
/*new osg::ShaderAttribute*/NULL,
|
||||
osg::ShaderAttribute,
|
||||
"osg::Object osg::StateAttribute osg::ShaderAttribute" )
|
||||
{
|
||||
}
|
||||
Reference in New Issue
Block a user