WS30 Uniform arrays and photoscenery search path

This commit is contained in:
Stuart Buchanan 2021-11-10 22:57:08 +00:00
parent 2ec9df7597
commit 0470375889
4 changed files with 64 additions and 75 deletions

View File

@ -354,30 +354,12 @@ SGMaterialCache::Atlas SGMaterialLib::getMaterialTextureAtlas(SGVec2f center, co
atlas.image = new osg::Texture2DArray(); atlas.image = new osg::Texture2DArray();
osg::ref_ptr<osg::Image> dimensionImage = new osg::Image(); if (landclasslib.size() > 128) SG_LOG(SG_TERRAIN, SG_ALERT, "Too many landclass entries for uniform arrays");
dimensionImage->allocateImage(512, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE);
atlas.dimensions = new osg::Texture1D(dimensionImage.get()); atlas.dimensions = new osg::Uniform(osg::Uniform::Type::FLOAT_VEC4, "dimensionsArray", 128);
atlas.dimensions->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST); atlas.ambient = new osg::Uniform(osg::Uniform::Type::FLOAT_VEC4, "ambientArray", 128);
atlas.dimensions->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST); atlas.diffuse = new osg::Uniform(osg::Uniform::Type::FLOAT_VEC4, "diffuseArray", 128);
atlas.dimensions->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP); atlas.specular = new osg::Uniform(osg::Uniform::Type::FLOAT_VEC4, "specularArray", 128);
atlas.dimensions->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP);
osg::ref_ptr<osg::Image> 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<osg::Image> 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);
atlas.image->setMaxAnisotropy(SGSceneFeatures::instance()->getTextureFilter()); atlas.image->setMaxAnisotropy(SGSceneFeatures::instance()->getTextureFilter());
atlas.image->setResizeNonPowerOfTwoHint(false); 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_S,osg::Texture::REPEAT);
atlas.image->setWrap(osg::Texture::WRAP_T,osg::Texture::REPEAT); atlas.image->setWrap(osg::Texture::WRAP_T,osg::Texture::REPEAT);
int index = -1; unsigned int index = 0;
lc_iter = landclasslib.begin(); lc_iter = landclasslib.begin();
for (; lc_iter != landclasslib.end(); ++lc_iter) { 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; int i = lc_iter->first;
SGMaterial* mat = find(lc_iter->second.first, center); SGMaterial* mat = find(lc_iter->second.first, center);
atlas.index[i] = index; atlas.index[i] = index;
atlas.waterAtlas[i] = lc_iter->second.second; 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. // Just get the first texture in the first texture-set for the moment.
// Should add some variability in texture-set in the future. // Should add some variability in texture-set in the future.
const std::string texture = mat->get_one_texture(0,0); const std::string texture = mat->get_one_texture(0,0);
if (texture.empty()) continue; if (! texture.empty()) {
if (texture.empty()) continue;
SGPath texturePath = SGPath("Textures"); SGPath texturePath = SGPath("Textures");
//texturePath.append(texture); //texturePath.append(texture);
std::string fullPath = SGModelLib::findDataFile(texture, options, texturePath); std::string fullPath = SGModelLib::findDataFile(texture, options, texturePath);
if (fullPath.empty()) { if (fullPath.empty()) {
SG_LOG(SG_GENERAL, SG_ALERT, "Cannot find texture \"" SG_LOG(SG_GENERAL, SG_ALERT, "Cannot find texture \""
<< texture << "\" in Textures folders when creating texture atlas"); << texture << "\" in Textures folders when creating texture atlas");
}
else
{
// Copy the texture into the atlas in the appropriate place
osg::ref_ptr<osg::Image> subtexture = osgDB::readRefImageFile(fullPath, options);
if (subtexture && subtexture->valid()) {
if ((subtexture->s() != 2048) || (subtexture->t() != 2048)) {
subtexture->scaleImage(2048,2048,1);
} }
else
{
// Copy the texture into the atlas in the appropriate place
osg::ref_ptr<osg::Image> subtexture = osgDB::readRefImageFile(fullPath, options);
// Add other useful information, such as the texture size in m. if (subtexture && subtexture->valid()) {
// 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;
SG_LOG(SG_TERRAIN, SG_DEBUG, "Adding image " << fullPath << " to texture atlas " << x_size << " " << y_size); if ((subtexture->s() != 2048) || (subtexture->t() != 2048)) {
atlas.image->setImage(index,subtexture); subtexture->scaleImage(2048,2048,1);
}
atlas.dimensions->getImage()->setColor(osg::Vec4(x_size, y_size, mat->get_shininess(), 1.0f), index); atlas.image->setImage(index,subtexture);
atlas.diffuse->getImage()->setColor(mat->get_diffuse(), index); atlas.dimensions->setElement(index, osg::Vec4f(mat->get_xsize(), mat->get_ysize(), mat->get_shininess(), 1.0f));
atlas.specular->getImage()->setColor(mat->get_specular(), index); 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 // Cache for future lookups

View File

@ -59,9 +59,10 @@ public:
typedef struct { typedef struct {
AtlasIndex index; AtlasIndex index;
AtlasImage image; AtlasImage image;
osg::ref_ptr<osg::Texture1D> dimensions; osg::ref_ptr<osg::Uniform> dimensions;
osg::ref_ptr<osg::Texture1D> diffuse; osg::ref_ptr<osg::Uniform> ambient;
osg::ref_ptr<osg::Texture1D> specular; osg::ref_ptr<osg::Uniform> diffuse;
osg::ref_ptr<osg::Uniform> specular;
WaterAtlas waterAtlas; WaterAtlas waterAtlas;
} Atlas; } Atlas;

View File

@ -65,7 +65,7 @@ VPBTechnique::VPBTechnique():
_randomObjectsConstraintGroup = new osg::Group(); _randomObjectsConstraintGroup = new osg::Group();
} }
VPBTechnique::VPBTechnique(const SGReaderWriterOptions* options, const string& fileName): VPBTechnique::VPBTechnique(const SGReaderWriterOptions* options, const string fileName):
_fileName(fileName) _fileName(fileName)
{ {
setFilterBias(0); 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 // 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. // naming convention as the VPB scenery itself.
auto tileID = _terrainTile->getTileID(); 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 osg::Vec3d world = buffer._transform->getMatrix().getTrans();
const SGGeod loc = SGGeod::fromCart(toSG(world)); const SGGeod loc = SGGeod::fromCart(toSG(world));
const SGBucket bucket = SGBucket(loc); 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. osgDB::FilePathList& pathList = _options->getDatabasePathList();
string base = _fileName.substr(0, _fileName.find("vpb")); bool found = false;
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);
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. // 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::Texture2D* texture = SGLoadTexture2D(SGPath(orthotexture), _options, true, true);
osg::StateSet* stateset = buffer._landGeode->getOrCreateStateSet(); osg::StateSet* stateset = buffer._landGeode->getOrCreateStateSet();
@ -1369,10 +1378,11 @@ void VPBTechnique::applyColorLayers(BufferData& buffer, Locator* masterLocator)
osg::StateSet* stateset = buffer._landGeode->getOrCreateStateSet(); osg::StateSet* stateset = buffer._landGeode->getOrCreateStateSet();
stateset->setTextureAttributeAndModes(0, texture2D, osg::StateAttribute::ON); stateset->setTextureAttributeAndModes(0, texture2D, osg::StateAttribute::ON);
stateset->setTextureAttributeAndModes(1, atlas.image, 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(new osg::Uniform("photoScenery", false));
stateset->addUniform(atlas.dimensions);
stateset->addUniform(atlas.ambient);
stateset->addUniform(atlas.diffuse);
stateset->addUniform(atlas.specular);
} }
} }

View File

@ -45,7 +45,7 @@ class VPBTechnique : public TerrainTechnique
public: public:
VPBTechnique(); 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.*/ /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
VPBTechnique(const VPBTechnique&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); VPBTechnique(const VPBTechnique&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);