diff --git a/simgear/scene/material/matlib.cxx b/simgear/scene/material/matlib.cxx index 43d6c9d9..c8371454 100644 --- a/simgear/scene/material/matlib.cxx +++ b/simgear/scene/material/matlib.cxx @@ -354,30 +354,12 @@ SGMaterialCache::Atlas SGMaterialLib::getMaterialTextureAtlas(SGVec2f center, co atlas.image = new osg::Texture2DArray(); - osg::ref_ptr dimensionImage = new osg::Image(); - dimensionImage->allocateImage(512, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE); - atlas.dimensions = new osg::Texture1D(dimensionImage.get()); - atlas.dimensions->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST); - atlas.dimensions->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST); - atlas.dimensions->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP); - atlas.dimensions->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP); - - - osg::ref_ptr diffuseImage = new osg::Image(); - diffuseImage->allocateImage(512, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE); - atlas.diffuse = new osg::Texture1D(diffuseImage.get()); - atlas.diffuse->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST); - atlas.diffuse->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST); - atlas.diffuse->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP); - atlas.diffuse->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP); - - osg::ref_ptr specularImage = new osg::Image(); - specularImage->allocateImage(512, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE); - atlas.specular = new osg::Texture1D(specularImage.get()); - atlas.specular->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST); - atlas.specular->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST); - atlas.specular->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP); - atlas.specular->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP); + if (landclasslib.size() > 128) SG_LOG(SG_TERRAIN, SG_ALERT, "Too many landclass entries for uniform arrays"); + + atlas.dimensions = new osg::Uniform(osg::Uniform::Type::FLOAT_VEC4, "dimensionsArray", 128); + atlas.ambient = new osg::Uniform(osg::Uniform::Type::FLOAT_VEC4, "ambientArray", 128); + atlas.diffuse = new osg::Uniform(osg::Uniform::Type::FLOAT_VEC4, "diffuseArray", 128); + atlas.specular = new osg::Uniform(osg::Uniform::Type::FLOAT_VEC4, "specularArray", 128); atlas.image->setMaxAnisotropy(SGSceneFeatures::instance()->getTextureFilter()); atlas.image->setResizeNonPowerOfTwoHint(false); @@ -385,57 +367,53 @@ SGMaterialCache::Atlas SGMaterialLib::getMaterialTextureAtlas(SGVec2f center, co atlas.image->setWrap(osg::Texture::WRAP_S,osg::Texture::REPEAT); atlas.image->setWrap(osg::Texture::WRAP_T,osg::Texture::REPEAT); - int index = -1; + unsigned int index = 0; lc_iter = landclasslib.begin(); for (; lc_iter != landclasslib.end(); ++lc_iter) { - // index is incremented at the start of the loop so that we have a valid - // mapping based on the lanclassList, even if we fail to process the texture. - ++index; int i = lc_iter->first; SGMaterial* mat = find(lc_iter->second.first, center); atlas.index[i] = index; atlas.waterAtlas[i] = lc_iter->second.second; - if (mat == NULL) continue; + if (mat != NULL) { - // Just get the first texture in the first texture-set for the moment. - // Should add some variability in texture-set in the future. - const std::string texture = mat->get_one_texture(0,0); - if (texture.empty()) continue; + // Just get the first texture in the first texture-set for the moment. + // Should add some variability in texture-set in the future. + const std::string texture = mat->get_one_texture(0,0); + if (! texture.empty()) { + if (texture.empty()) continue; - SGPath texturePath = SGPath("Textures"); - //texturePath.append(texture); - std::string fullPath = SGModelLib::findDataFile(texture, options, texturePath); + SGPath texturePath = SGPath("Textures"); + //texturePath.append(texture); + std::string fullPath = SGModelLib::findDataFile(texture, options, texturePath); - if (fullPath.empty()) { - SG_LOG(SG_GENERAL, SG_ALERT, "Cannot find texture \"" - << texture << "\" in Textures folders when creating texture atlas"); - } - else - { - // Copy the texture into the atlas in the appropriate place - osg::ref_ptr subtexture = osgDB::readRefImageFile(fullPath, options); - - if (subtexture && subtexture->valid()) { - - if ((subtexture->s() != 2048) || (subtexture->t() != 2048)) { - subtexture->scaleImage(2048,2048,1); + if (fullPath.empty()) { + SG_LOG(SG_GENERAL, SG_ALERT, "Cannot find texture \"" + << texture << "\" in Textures folders when creating texture atlas"); } + else + { + // Copy the texture into the atlas in the appropriate place + osg::ref_ptr subtexture = osgDB::readRefImageFile(fullPath, options); - // Add other useful information, such as the texture size in m. - // As we pack the texture size into a texture, we need to scale to [0..1.0] - float x_size = (0 < mat->get_xsize()) ? mat->get_xsize()/10000.0 : 0.1f; - float y_size = (0 < mat->get_ysize()) ? mat->get_ysize()/10000.0 : 0.1f; + if (subtexture && subtexture->valid()) { - SG_LOG(SG_TERRAIN, SG_DEBUG, "Adding image " << fullPath << " to texture atlas " << x_size << " " << y_size); - atlas.image->setImage(index,subtexture); + if ((subtexture->s() != 2048) || (subtexture->t() != 2048)) { + subtexture->scaleImage(2048,2048,1); + } - atlas.dimensions->getImage()->setColor(osg::Vec4(x_size, y_size, mat->get_shininess(), 1.0f), index); - atlas.diffuse->getImage()->setColor(mat->get_diffuse(), index); - atlas.specular->getImage()->setColor(mat->get_specular(), index); + atlas.image->setImage(index,subtexture); + atlas.dimensions->setElement(index, osg::Vec4f(mat->get_xsize(), mat->get_ysize(), mat->get_shininess(), 1.0f)); + atlas.ambient->setElement(index, mat->get_ambient()); + atlas.diffuse->setElement(index, mat->get_diffuse()); + atlas.specular->setElement(index, mat->get_specular()); + } + + } } - } + + ++index; } // Cache for future lookups diff --git a/simgear/scene/material/matlib.hxx b/simgear/scene/material/matlib.hxx index e1649c6e..e80a1ca1 100644 --- a/simgear/scene/material/matlib.hxx +++ b/simgear/scene/material/matlib.hxx @@ -59,9 +59,10 @@ public: typedef struct { AtlasIndex index; AtlasImage image; - osg::ref_ptr dimensions; - osg::ref_ptr diffuse; - osg::ref_ptr specular; + osg::ref_ptr dimensions; + osg::ref_ptr ambient; + osg::ref_ptr diffuse; + osg::ref_ptr specular; WaterAtlas waterAtlas; } Atlas; diff --git a/simgear/scene/tgdb/VPBTechnique.cxx b/simgear/scene/tgdb/VPBTechnique.cxx index 4c625086..00e35d13 100644 --- a/simgear/scene/tgdb/VPBTechnique.cxx +++ b/simgear/scene/tgdb/VPBTechnique.cxx @@ -65,7 +65,7 @@ VPBTechnique::VPBTechnique(): _randomObjectsConstraintGroup = new osg::Group(); } -VPBTechnique::VPBTechnique(const SGReaderWriterOptions* options, const string& fileName): +VPBTechnique::VPBTechnique(const SGReaderWriterOptions* options, const string fileName): _fileName(fileName) { setFilterBias(0); @@ -1296,20 +1296,29 @@ void VPBTechnique::applyColorLayers(BufferData& buffer, Locator* masterLocator) // Firstly, we need to work out the texture file we want to load. Fortunately this follows the same // naming convention as the VPB scenery itself. auto tileID = _terrainTile->getTileID(); - SG_LOG(SG_TERRAIN, SG_DEBUG, "Using Photoscenery for " << tileID.level << " X" << tileID.x << " Y" << tileID.y); + SG_LOG(SG_TERRAIN, SG_DEBUG, "Using Photoscenery for " << _fileName << " " << tileID.level << " X" << tileID.x << " Y" << tileID.y); const osg::Vec3d world = buffer._transform->getMatrix().getTrans(); const SGGeod loc = SGGeod::fromCart(toSG(world)); const SGBucket bucket = SGBucket(loc); + SGPath orthotexture; - // Bit of a hack - we assume the Orthophotos are in the same FG_SCENERY top level as the .osgb tiles. - string base = _fileName.substr(0, _fileName.find("vpb")); - SGPath orthotexture = SGPath(base); - orthotexture.append("Orthophotos"); - orthotexture.append(bucket.gen_vpb_subtile(tileID.level, tileID.x, tileID.y) + ".dds"); - SG_LOG(SG_TERRAIN, SG_DEBUG, "Using phototexture " << orthotexture); + osgDB::FilePathList& pathList = _options->getDatabasePathList(); + bool found = false; - if (orthotexture.exists()) { + for (auto iter = pathList.begin(); !found && iter != pathList.end(); ++iter) { + orthotexture = SGPath(*iter); + orthotexture.append("Orthophotos"); + orthotexture.append(bucket.gen_vpb_subtile(tileID.level, tileID.x, tileID.y) + ".dds"); + SG_LOG(SG_TERRAIN, SG_DEBUG, "Looking for phototexture " << orthotexture); + + if (orthotexture.exists()) { + found = true; + SG_LOG(SG_TERRAIN, SG_DEBUG, "Found phototexture " << orthotexture); + } + } + + if (found) { // Set up the texture with wrapping of UV to reduce black edges at tile boundaries. osg::Texture2D* texture = SGLoadTexture2D(SGPath(orthotexture), _options, true, true); osg::StateSet* stateset = buffer._landGeode->getOrCreateStateSet(); @@ -1369,10 +1378,11 @@ void VPBTechnique::applyColorLayers(BufferData& buffer, Locator* masterLocator) osg::StateSet* stateset = buffer._landGeode->getOrCreateStateSet(); stateset->setTextureAttributeAndModes(0, texture2D, osg::StateAttribute::ON); stateset->setTextureAttributeAndModes(1, atlas.image, osg::StateAttribute::ON); - stateset->setTextureAttributeAndModes(2, atlas.dimensions, osg::StateAttribute::ON); - stateset->setTextureAttributeAndModes(3, atlas.diffuse, osg::StateAttribute::ON); - stateset->setTextureAttributeAndModes(4, atlas.specular, osg::StateAttribute::ON); stateset->addUniform(new osg::Uniform("photoScenery", false)); + stateset->addUniform(atlas.dimensions); + stateset->addUniform(atlas.ambient); + stateset->addUniform(atlas.diffuse); + stateset->addUniform(atlas.specular); } } diff --git a/simgear/scene/tgdb/VPBTechnique.hxx b/simgear/scene/tgdb/VPBTechnique.hxx index 4a36c923..766ef251 100644 --- a/simgear/scene/tgdb/VPBTechnique.hxx +++ b/simgear/scene/tgdb/VPBTechnique.hxx @@ -45,7 +45,7 @@ class VPBTechnique : public TerrainTechnique public: VPBTechnique(); - VPBTechnique(const SGReaderWriterOptions* options, const string& fileName); + VPBTechnique(const SGReaderWriterOptions* options, const string fileName); /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ VPBTechnique(const VPBTechnique&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);