WS30: Improved material Uniforms
This commit is contained in:
parent
922ad8d2e7
commit
0e13e48123
@ -403,6 +403,11 @@ public:
|
||||
(0 < tex_height) ? 1000.0f/tex_height : 1.0f);
|
||||
}
|
||||
|
||||
float get_parameter(const std::string& param) const
|
||||
{
|
||||
return parameters->getFloatValue(param);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
|
@ -355,14 +355,17 @@ SGMaterialCache::Atlas SGMaterialLib::getMaterialTextureAtlas(SGVec2f center, co
|
||||
|
||||
atlas.image = new osg::Texture2DArray();
|
||||
|
||||
if (landclasslib.size() > 128) SG_LOG(SG_TERRAIN, SG_ALERT, "Too many landclass entries for uniform arrays");
|
||||
SG_LOG(SG_TERRAIN, SG_DEBUG, "Generating atlas of size " << landclasslib.size());
|
||||
if (landclasslib.size() > SGMaterialCache::MAX_MATERIALS) SG_LOG(SG_TERRAIN, SG_ALERT, "Too many landclass entries for uniform arrays: " << landclasslib.size() << " > " << SGMaterialCache::MAX_MATERIALS);
|
||||
|
||||
atlas.textureLookup1 = new osg::Uniform(osg::Uniform::Type::FLOAT_VEC4, "fg_textureLookup1", 128);
|
||||
atlas.textureLookup2 = new osg::Uniform(osg::Uniform::Type::FLOAT_VEC4, "fg_textureLookup2", 128);
|
||||
atlas.dimensions = new osg::Uniform(osg::Uniform::Type::FLOAT_VEC4, "fg_dimensionsArray", 128);
|
||||
atlas.ambient = new osg::Uniform(osg::Uniform::Type::FLOAT_VEC4, "fg_ambientArray", 128);
|
||||
atlas.diffuse = new osg::Uniform(osg::Uniform::Type::FLOAT_VEC4, "fg_diffuseArray", 128);
|
||||
atlas.specular = new osg::Uniform(osg::Uniform::Type::FLOAT_VEC4, "fg_specularArray", 128);
|
||||
atlas.textureLookup1 = new osg::Uniform(osg::Uniform::Type::FLOAT_VEC4, "fg_textureLookup1", SGMaterialCache::MAX_MATERIALS);
|
||||
atlas.textureLookup2 = new osg::Uniform(osg::Uniform::Type::FLOAT_VEC4, "fg_textureLookup2", SGMaterialCache::MAX_MATERIALS);
|
||||
atlas.dimensions = new osg::Uniform(osg::Uniform::Type::FLOAT_VEC4, "fg_dimensionsArray", SGMaterialCache::MAX_MATERIALS);
|
||||
atlas.ambient = new osg::Uniform(osg::Uniform::Type::FLOAT_VEC4, "fg_ambientArray", SGMaterialCache::MAX_MATERIALS);
|
||||
atlas.diffuse = new osg::Uniform(osg::Uniform::Type::FLOAT_VEC4, "fg_diffuseArray", SGMaterialCache::MAX_MATERIALS);
|
||||
atlas.specular = new osg::Uniform(osg::Uniform::Type::FLOAT_VEC4, "fg_specularArray", SGMaterialCache::MAX_MATERIALS);
|
||||
atlas.materialParams1= new osg::Uniform(osg::Uniform::Type::FLOAT_VEC4, "fg_materialParams1", SGMaterialCache::MAX_MATERIALS);
|
||||
atlas.materialParams2= new osg::Uniform(osg::Uniform::Type::FLOAT_VEC4, "fg_materialParams2", SGMaterialCache::MAX_MATERIALS);
|
||||
|
||||
atlas.image->setMaxAnisotropy(SGSceneFeatures::instance()->getTextureFilter());
|
||||
atlas.image->setResizeNonPowerOfTwoHint(false);
|
||||
@ -396,56 +399,76 @@ SGMaterialCache::Atlas SGMaterialLib::getMaterialTextureAtlas(SGVec2f center, co
|
||||
atlas.diffuse->setElement(materialLookupIndex, mat->get_diffuse());
|
||||
atlas.specular->setElement(materialLookupIndex, mat->get_specular());
|
||||
|
||||
// Add any missing textures into the atlas image
|
||||
for (std::size_t i = 0; i < mat->get_num_textures(0); ++i) {
|
||||
const std::string texture = mat->get_one_texture(0,i);
|
||||
if (! texture.empty()) {
|
||||
// The following are material parameters that are normally built into the Effect as Uniforms. In the WS30
|
||||
// case we need to pass them as an array, indexed against the material.
|
||||
atlas.materialParams1->setElement(materialLookupIndex, osg::Vec4f(mat->get_parameter("transition_model"), mat->get_parameter("hires_overlay_bias"), mat->get_parameter("grain_strength"), mat->get_parameter("intrinsic_wetness")));
|
||||
atlas.materialParams2->setElement(materialLookupIndex, osg::Vec4f(mat->get_parameter("dot_density"), mat->get_parameter("dot_size"), mat->get_parameter("dust_resistance"), mat->get_parameter("rock_strata")));
|
||||
|
||||
SGPath texturePath = SGPath("Textures");
|
||||
std::string fullPath = SGModelLib::findDataFile(texture, options, texturePath);
|
||||
// Similarly, there are specifically 7 textures that are defined in the materials that need to be passed into
|
||||
// the shader as an array based on the material lookup.
|
||||
//
|
||||
// The mapping from terrain-default.eff / terrain-overlay.eff is as follows
|
||||
//
|
||||
// TEXTURE NAME texture-unit Material texture index Default value
|
||||
// Primary texure 0 0 n/a
|
||||
// gradient_texture 2 13 Textures/Terrain/rock_alt.png
|
||||
// dot_texture 3 15 Textures/Terrain/void.png
|
||||
// grain_texture 4 14 Textures/Terrain/grain_texture.png
|
||||
// mix_texture 5 12 Textures/Terrain/void.png
|
||||
// detail_texture 7 11 Textures/Terrain/void.png
|
||||
// overlayPrimaryTex 7 20 Textures/Terrain/void.png
|
||||
// overlaySecondaryTex 8 21 Textures/Terrain/void.png
|
||||
|
||||
if (fullPath.empty()) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Cannot find texture \""
|
||||
<< texture << "\" in Textures folders when creating texture atlas");
|
||||
textureList[i] = -2;
|
||||
continue;
|
||||
}
|
||||
for (unsigned int i = 0; i < SGMaterialCache::MAX_TEXTURES; i++) {
|
||||
std::string texture = mat->get_one_texture(0,i);
|
||||
|
||||
if (atlas.textureMap.find(fullPath) == atlas.textureMap.end()) {
|
||||
// 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);
|
||||
}
|
||||
|
||||
atlas.image->setImage(imageIndex,subtexture);
|
||||
atlas.textureMap[fullPath] = imageIndex;
|
||||
++imageIndex;
|
||||
}
|
||||
}
|
||||
|
||||
// At this point we know that the texture is present in the
|
||||
// atlas and referenced in the textureMap, so add it to the materialLookup
|
||||
textureList[i] = atlas.textureMap[fullPath];
|
||||
//SG_LOG(SG_TERRAIN, SG_ALERT, "materialLookup Index: " << (materialLookupIndex * SGMaterialCache::MAX_TEXTURES + i) << " " << atlas.textureMap[fullPath] << " " << fullPath);
|
||||
} else {
|
||||
textureList[i] = -2;
|
||||
if (texture.empty()) {
|
||||
// This is a rather horrible hardcoded mapping of the default textures defined in
|
||||
// terrain-default.eff and terrain-overlay.eff which are in effect defaults to
|
||||
// the material definitions
|
||||
if (i < 13) texture = std::string("Textures/Terrain/void.png");
|
||||
if (i == 13) texture = std::string("Textures/Terrain/rock_alt.png");
|
||||
if (i == 14) texture = std::string("Textures/Terrain/grain_texture.png");
|
||||
if (i > 14) texture = std::string("Textures/Terrain/void.png");
|
||||
}
|
||||
}
|
||||
|
||||
// Fill out the rest of the array
|
||||
for (std::size_t i = mat->get_num_textures(0); i < SGMaterialCache::MAX_TEXTURES; ++i) {
|
||||
textureList[i] = -2;
|
||||
SGPath texturePath = SGPath("Textures");
|
||||
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");
|
||||
texture = std::string("Textures/Terrain/void.png");
|
||||
fullPath = SGModelLib::findDataFile(texture, options, texturePath);
|
||||
}
|
||||
|
||||
if (atlas.textureMap.find(fullPath) == atlas.textureMap.end()) {
|
||||
// Add any missing textures into the atlas image
|
||||
// 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);
|
||||
}
|
||||
|
||||
atlas.image->setImage(imageIndex,subtexture);
|
||||
atlas.textureMap[fullPath] = imageIndex;
|
||||
++imageIndex;
|
||||
}
|
||||
}
|
||||
|
||||
// At this point we know that the texture is present in the
|
||||
// atlas and referenced in the textureMap, so add it to the materialLookup
|
||||
textureList[i] = atlas.textureMap[fullPath];
|
||||
}
|
||||
|
||||
// We now have a textureList containing the full set of textures. Pack the relevant ones into the Vec4 of the index Uniform.
|
||||
// This is a bit of a hack to maintain compatibility with the WS2.0 material definitions, as the material definitions use the
|
||||
// 11-15th textures for the various overlay textures for terrain-default.eff, we do the same for ws30.eff
|
||||
atlas.textureLookup1->setElement(materialLookupIndex, osg::Vec4f( (float) (textureList[0] / 255.0), (float) (textureList[11] / 255.0), (float) (textureList[12] / 255.0), (float) (textureList[13] / 255.0)));
|
||||
atlas.textureLookup2->setElement(materialLookupIndex, osg::Vec4f( (float) (textureList[14] / 255.0), (float) (textureList[15] / 255.0), 0.0,0.0));
|
||||
atlas.textureLookup2->setElement(materialLookupIndex, osg::Vec4f( (float) (textureList[14] / 255.0), (float) (textureList[15] / 255.0), (float) (textureList[20] / 255.0), (float) (textureList[21] / 255.0)));
|
||||
}
|
||||
|
||||
++materialLookupIndex;
|
||||
@ -456,6 +479,17 @@ SGMaterialCache::Atlas SGMaterialLib::getMaterialTextureAtlas(SGVec2f center, co
|
||||
return atlas;
|
||||
}
|
||||
|
||||
void SGMaterialCache::addAtlasUniforms(osg::StateSet* stateset) {
|
||||
stateset->addUniform(_atlas.dimensions);
|
||||
stateset->addUniform(_atlas.ambient);
|
||||
stateset->addUniform(_atlas.diffuse);
|
||||
stateset->addUniform(_atlas.specular);
|
||||
stateset->addUniform(_atlas.textureLookup1);
|
||||
stateset->addUniform(_atlas.textureLookup2);
|
||||
stateset->addUniform(_atlas.materialParams1);
|
||||
stateset->addUniform(_atlas.materialParams2);
|
||||
}
|
||||
|
||||
// Destructor
|
||||
SGMaterialCache::~SGMaterialCache ( void ) {
|
||||
SG_LOG( SG_TERRAIN, SG_DEBUG, "SGMaterialCache::~SGMaterialCache() size=" << cache.size());
|
||||
|
@ -69,7 +69,10 @@ public:
|
||||
typedef std::map<int, bool> WaterAtlas;
|
||||
|
||||
// Maximum number of textures per texture-set for the Atlas.
|
||||
static const unsigned int MAX_TEXTURES = 16;
|
||||
static const unsigned int MAX_TEXTURES = 22;
|
||||
|
||||
// Maximum number of material entries in the atlas
|
||||
static const unsigned int MAX_MATERIALS = 64;
|
||||
|
||||
typedef struct {
|
||||
AtlasIndex index;
|
||||
@ -80,6 +83,10 @@ public:
|
||||
osg::ref_ptr<osg::Uniform> ambient;
|
||||
osg::ref_ptr<osg::Uniform> diffuse;
|
||||
osg::ref_ptr<osg::Uniform> specular;
|
||||
|
||||
osg::ref_ptr<osg::Uniform> materialParams1;
|
||||
osg::ref_ptr<osg::Uniform> materialParams2;
|
||||
|
||||
WaterAtlas waterAtlas;
|
||||
TextureMap textureMap;
|
||||
} Atlas;
|
||||
@ -97,6 +104,8 @@ public:
|
||||
|
||||
Atlas getAtlas() { return _atlas; };
|
||||
|
||||
void addAtlasUniforms(osg::StateSet* stateset);
|
||||
|
||||
// Destructor
|
||||
~SGMaterialCache ( void );
|
||||
|
||||
|
@ -1346,7 +1346,8 @@ void VPBTechnique::applyColorLayers(BufferData& buffer, Locator* masterLocator)
|
||||
const SGGeod loc = computeCenterGeod(buffer, masterLocator);
|
||||
SG_LOG(SG_TERRAIN, SG_DEBUG, "Applying VPB material " << loc);
|
||||
|
||||
SGMaterialCache::Atlas atlas = matlib->generateMatCache(loc, _options)->getAtlas();
|
||||
SGMaterialCache* matCache = matlib->generateMatCache(loc, _options);
|
||||
SGMaterialCache::Atlas atlas = matCache->getAtlas();
|
||||
SGMaterialCache::AtlasIndex atlasIndex = atlas.index;
|
||||
|
||||
// Set the "g" color channel to an index into the atlas index.
|
||||
@ -1385,14 +1386,9 @@ void VPBTechnique::applyColorLayers(BufferData& buffer, Locator* masterLocator)
|
||||
stateset->setTextureAttributeAndModes(0, texture2D, osg::StateAttribute::ON);
|
||||
stateset->setTextureAttributeAndModes(1, atlas.image, osg::StateAttribute::ON);
|
||||
stateset->addUniform(new osg::Uniform("fg_photoScenery", false));
|
||||
stateset->addUniform(atlas.dimensions);
|
||||
stateset->addUniform(atlas.ambient);
|
||||
stateset->addUniform(atlas.diffuse);
|
||||
stateset->addUniform(atlas.specular);
|
||||
stateset->addUniform(atlas.textureLookup1);
|
||||
stateset->addUniform(atlas.textureLookup2);
|
||||
stateset->addUniform(new osg::Uniform("fg_zUpTransform", osg::Matrixf(osg::Matrix::inverse(makeZUpFrameRelative(loc)))));
|
||||
stateset->addUniform(new osg::Uniform("fg_modelOffset", (osg::Vec3f) buffer._transform->getMatrix().getTrans()));
|
||||
matCache->addAtlasUniforms(stateset);
|
||||
//SG_LOG(SG_TERRAIN, SG_ALERT, "modeOffset:" << buffer._transform->getMatrix().getTrans().length() << " " << buffer._transform->getMatrix().getTrans());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user