From 30b5bbe7d5b94d8754863552483860e0f026ec76 Mon Sep 17 00:00:00 2001 From: Stuart Buchanan Date: Tue, 1 Feb 2022 17:05:31 +0000 Subject: [PATCH] WS30: Add property controlling splitting water mesh Previously a separate mesh was created for parts of the terrain identified as being water. This adds a property (/scenery/elevation-mesh/separate-water-mesh) which controls whether this separate mesh is generated. --- simgear/scene/material/matlib.cxx | 31 ++++++++++++++++++++++++-- simgear/scene/material/matlib.hxx | 18 +++++++++++++++ simgear/scene/tgdb/VPBTechnique.cxx | 4 +++- simgear/scene/util/SGSceneFeatures.hxx | 4 ++++ 4 files changed, 54 insertions(+), 3 deletions(-) diff --git a/simgear/scene/material/matlib.cxx b/simgear/scene/material/matlib.cxx index e5499504..02ec3d44 100644 --- a/simgear/scene/material/matlib.cxx +++ b/simgear/scene/material/matlib.cxx @@ -367,8 +367,9 @@ SGMaterialCache::Atlas SGMaterialLib::getMaterialTextureAtlas(SGVec2f center, co 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.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.materialParams3 = new osg::Uniform(osg::Uniform::Type::FLOAT_VEC4, "fg_materialParams3", SGMaterialCache::MAX_MATERIALS); atlas.image->setMaxAnisotropy(SGSceneFeatures::instance()->getTextureFilter()); atlas.image->setResizeNonPowerOfTwoHint(false); @@ -377,6 +378,23 @@ SGMaterialCache::Atlas SGMaterialLib::getMaterialTextureAtlas(SGVec2f center, co atlas.image->setWrap(osg::Texture::WRAP_T,osg::Texture::REPEAT); unsigned int imageIndex = 0u; // Index into the image + + // Add hardcoded atlas images first. + unsigned int standardTextureCount = size(SGMaterialCache::STANDARD_TEXTURES); + for (; imageIndex < standardTextureCount; imageIndex++) { + // Copy the texture into the atlas in the appropriate place + osg::ref_ptr subtexture = osgDB::readRefImageFile(SGMaterialCache::STANDARD_TEXTURES[imageIndex], options); + + if (subtexture && subtexture->valid()) { + if ((subtexture->s() != 2048) || (subtexture->t() != 2048)) { + subtexture->scaleImage(2048,2048,1); + } + + atlas.image->setImage(imageIndex,subtexture); + atlas.textureMap[SGMaterialCache::STANDARD_TEXTURES[imageIndex]] = imageIndex; + } + } + unsigned int materialLookupIndex = 0u; // Index into the material lookup lc_iter = landclasslib.begin(); for (; lc_iter != landclasslib.end(); ++lc_iter) { @@ -406,6 +424,14 @@ SGMaterialCache::Atlas SGMaterialLib::getMaterialTextureAtlas(SGVec2f center, co // 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"))); + + float water = 0.0; + if (mat->get_effect_name() == "Effects/water") { + SG_LOG(SG_GENERAL, SG_ALERT, " Found water effect " << mat->get_names()[0]); + water = 1.0; + } + + atlas.materialParams3->setElement(materialLookupIndex, osg::Vec4f(water, 0.0, 0.0, 0.0)); // 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. @@ -491,6 +517,7 @@ void SGMaterialCache::addAtlasUniforms(osg::StateSet* stateset) { stateset->addUniform(_atlas.textureLookup2); stateset->addUniform(_atlas.materialParams1); stateset->addUniform(_atlas.materialParams2); + stateset->addUniform(_atlas.materialParams3); } // Destructor diff --git a/simgear/scene/material/matlib.hxx b/simgear/scene/material/matlib.hxx index 1a485e8f..2dfbbfdf 100644 --- a/simgear/scene/material/matlib.hxx +++ b/simgear/scene/material/matlib.hxx @@ -74,6 +74,23 @@ public: // Maximum number of material entries in the atlas static const unsigned int MAX_MATERIALS = 64; + // Standard textures, used by water shader in particular. + // Indexes are hardcoded in Shaders/ws30-water.frag + inline static const std::string STANDARD_TEXTURES[] = { + "Textures/Terrain/water.png", + "Textures/Water/water-reflection-ws30.png", + "Textures/Water/waves-ver10-nm-ws30.png", + "Textures/Water/water_sine_nmap-ws30.png", + "Textures/Water/water-reflection-grey-ws30.png", + "Textures/Water/sea_foam-ws30.png", + "Textures/Water/perlin-noise-nm.png", + + // The following two textures are large and don't have an alpha channel. Ignoring for now. + //"Textures/Globe/ocean_depth_1.png", + //"Textures/Globe/globe_colors.jpg", + "Textures/Terrain/packice-overlay.png" + }; + typedef struct { AtlasIndex index; AtlasImage image; @@ -86,6 +103,7 @@ public: osg::ref_ptr materialParams1; osg::ref_ptr materialParams2; + osg::ref_ptr materialParams3; WaterAtlas waterAtlas; TextureMap textureMap; diff --git a/simgear/scene/tgdb/VPBTechnique.cxx b/simgear/scene/tgdb/VPBTechnique.cxx index 6b5406fd..17612d64 100644 --- a/simgear/scene/tgdb/VPBTechnique.cxx +++ b/simgear/scene/tgdb/VPBTechnique.cxx @@ -834,6 +834,7 @@ void VPBTechnique::generateGeometry(BufferData& buffer, Locator* masterLocator, double scaleHeight = SGSceneFeatures::instance()->getVPBVerticalScale(); double sampleRatio = SGSceneFeatures::instance()->getVPBSampleRatio(); double constraint_gap = SGSceneFeatures::instance()->getVPBConstraintGap(); + bool separateWaterMesh = SGSceneFeatures::instance()->getVPBSeparateWaterMesh(); unsigned int minimumNumColumns = 16u; unsigned int minimumNumRows = 16u; @@ -994,7 +995,8 @@ void VPBTechnique::generateGeometry(BufferData& buffer, Locator* masterLocator, bool w10 = false; bool w11 = false; - if (landclassImage && matlib) { + if (separateWaterMesh && landclassImage && matlib) { + // If we are generating a separate water mesh, the work out which of the vertices are in appropriate watery materials. if (i00>=0) w00 = atlas.waterAtlas[int(round(landclassImage->getColor((*texcoords)[i00]).r() * 255.0))]; if (i01>=0) w01 = atlas.waterAtlas[int(round(landclassImage->getColor((*texcoords)[i01]).r() * 255.0))]; if (i10>=0) w10 = atlas.waterAtlas[int(round(landclassImage->getColor((*texcoords)[i10]).r() * 255.0))]; diff --git a/simgear/scene/util/SGSceneFeatures.hxx b/simgear/scene/util/SGSceneFeatures.hxx index 4a02efe9..3161bd7b 100644 --- a/simgear/scene/util/SGSceneFeatures.hxx +++ b/simgear/scene/util/SGSceneFeatures.hxx @@ -73,6 +73,9 @@ public: float getVPBVerticalScale() const { return _VPBVerticalScale; } void setVPBVerticalScale(const float val) { _VPBVerticalScale = val; } + bool getVPBSeparateWaterMesh() const { return _VPBSeparateWaterMesh; } + void setVPBSeparateWaterMesh(const bool val) { _VPBSeparateWaterMesh = val; } + void setEnablePointSpriteLights(bool enable) { _pointSpriteLights = enable; @@ -159,6 +162,7 @@ private: bool _distanceAttenuationLights; int _textureFilter; bool _VPBActive; + bool _VPBSeparateWaterMesh; float _VPBConstraintGap; float _VPBRangeFactor; float _VPBMaxRange;