VirtualProgram* RTTPicker::createRTTProgram() { VirtualProgram* vp = new VirtualProgram(); vp->setName( "osgEarth::RTTPicker" ); // Install RTT picker shaders: ShaderPackage pickShaders; pickShaders.add( "RTTPicker.vert.glsl", pickVertexEncode ); pickShaders.add( "RTTPicker.frag.glsl", pickFragment ); pickShaders.loadAll( vp ); // Install shaders and bindings from the ObjectIndex: Registry::objectIndex()->loadShaders( vp ); return vp; }
bool BillboardExtension::connect(MapNode* mapNode) { if ( !mapNode ) { OE_WARN << LC << "Illegal: MapNode cannot be null." << std::endl; return false; } OE_INFO << LC << "Connecting to MapNode.\n"; if ( !_options.imageURI().isSet() ) { OE_WARN << LC << "Illegal: image URI is required" << std::endl; return false; } if ( !_options.featureOptions().isSet() ) { OE_WARN << LC << "Illegal: feature source is required" << std::endl; return false; } _features = FeatureSourceFactory::create( _options.featureOptions().value() ); if ( !_features.valid() ) { OE_WARN << LC << "Illegal: no valid feature source provided" << std::endl; return false; } //if ( _features->getGeometryType() != osgEarth::Symbology::Geometry::TYPE_POINTSET ) //{ // OE_WARN << LC << "Illegal: only points currently supported" << std::endl; // return false; //} _features->initialize( _dbOptions ); osg::Vec3dArray* verts; if ( _features->getFeatureProfile() ) { verts = new osg::Vec3dArray(); OE_NOTICE << "Reading features...\n"; osg::ref_ptr<FeatureCursor> cursor = _features->createFeatureCursor(); while ( cursor.valid() && cursor->hasMore() ) { Feature* f = cursor->nextFeature(); if ( f && f->getGeometry() ) { if ( f->getGeometry()->getComponentType() == Geometry::TYPE_POLYGON ) { FilterContext cx; cx.setProfile( new FeatureProfile(_features->getFeatureProfile()->getExtent()) ); ScatterFilter scatter; scatter.setDensity( _options.density().get() ); scatter.setRandom( true ); FeatureList featureList; featureList.push_back(f); scatter.push( featureList, cx ); } // Init a filter to tranform feature in desired SRS if (!mapNode->getMapSRS()->isEquivalentTo(_features->getFeatureProfile()->getSRS())) { FilterContext cx; cx.setProfile( new FeatureProfile(_features->getFeatureProfile()->getExtent()) ); TransformFilter xform( mapNode->getMapSRS() ); FeatureList featureList; featureList.push_back(f); cx = xform.push(featureList, cx); } GeometryIterator iter(f->getGeometry()); while(iter.hasMore()) { const Geometry* geom = iter.next(); osg::ref_ptr<osg::Vec3dArray> fVerts = geom->createVec3dArray(); verts->insert(verts->end(), fVerts->begin(), fVerts->end()); } } } } else { OE_WARN << LC << "Illegal: feature source has no SRS" << std::endl; return false; } if ( verts && verts->size() > 0 ) { OE_NOTICE << LC << "Read " << verts->size() << " points.\n"; //localize all the verts GeoPoint centroid; _features->getFeatureProfile()->getExtent().getCentroid(centroid); centroid = centroid.transform(mapNode->getMapSRS()); OE_NOTICE << "Centroid = " << centroid.x() << ", " << centroid.y() << "\n"; osg::Matrixd l2w, w2l; centroid.createLocalToWorld(l2w); w2l.invert(l2w); osg::MatrixTransform* mt = new osg::MatrixTransform; mt->setMatrix(l2w); OE_NOTICE << "Clamping elevations...\n"; osgEarth::ElevationQuery eq(mapNode->getMap()); eq.setFallBackOnNoData( true ); eq.getElevations(verts->asVector(), mapNode->getMapSRS(), true, 0.005); OE_NOTICE << "Building geometry...\n"; osg::Vec3Array* normals = new osg::Vec3Array(verts->size()); osg::Vec4Array* colors = new osg::Vec4Array(verts->size()); Random rng; for (int i=0; i < verts->size(); i++) { GeoPoint vert(mapNode->getMapSRS(), (*verts)[i], osgEarth::ALTMODE_ABSOLUTE); osg::Vec3d world; vert.toWorld(world); (*verts)[i] = world * w2l; osg::Vec3 normal = world; normal.normalize(); (*normals)[i] = osg::Matrix::transform3x3(normal, w2l); double n = rng.next(); (*colors)[i].set( n, n, n, 1 ); } //create geom and primitive sets osg::Geometry* geometry = new osg::Geometry(); geometry->setVertexArray( verts ); geometry->setNormalArray( normals ); geometry->setNormalBinding( osg::Geometry::BIND_PER_VERTEX ); geometry->setColorArray(colors); geometry->setColorBinding( osg::Geometry::BIND_PER_VERTEX ); geometry->addPrimitiveSet( new osg::DrawArrays( GL_POINTS, 0, verts->size() ) ); //create image and texture to render to osg::Texture2D* tex = new osg::Texture2D(_options.imageURI()->getImage(_dbOptions)); tex->setResizeNonPowerOfTwoHint(false); tex->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR ); tex->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR ); tex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); tex->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); geometry->setName("BillboardPoints"); osg::Geode* geode = new osg::Geode; geode->addDrawable(geometry); //osg::ref_ptr<StateSetCache> cache = new StateSetCache(); //Registry::shaderGenerator().run(geode, cache.get()); //set the texture related uniforms osg::StateSet* geode_ss = geode->getOrCreateStateSet(); geode_ss->setTextureAttributeAndModes( 2, tex, 1 ); geode_ss->getOrCreateUniform("billboard_tex", osg::Uniform::SAMPLER_2D)->set( 2 ); float bbWidth = (float)tex->getImage()->s() / 2.0f; float bbHeight = (float)tex->getImage()->t(); float aspect = (float)tex->getImage()->s() / (float)tex->getImage()->t(); if (_options.height().isSet()) { bbHeight = _options.height().get(); if (!_options.width().isSet()) { bbWidth = bbHeight * aspect / 2.0f; } } if (_options.width().isSet()) { bbWidth = _options.width().get() / 2.0f; if (!_options.height().isSet()) { bbHeight = _options.width().get() / aspect; } } geode_ss->getOrCreateUniform("billboard_width", osg::Uniform::FLOAT)->set( bbWidth ); geode_ss->getOrCreateUniform("billboard_height", osg::Uniform::FLOAT)->set( bbHeight ); geode_ss->setMode(GL_BLEND, osg::StateAttribute::ON); //for now just using an osg::Program //TODO: need to add GeometryShader support to the shader comp setup VirtualProgram* vp = VirtualProgram::getOrCreate(geode_ss); vp->setName( "osgEarth Billboard Extension" ); ShaderPackage shaders; shaders.add( "Billboard geometry shader", billboardGeomShader ); shaders.add( "Billboard fragment shader", billboardFragShader ); shaders.loadAll( vp ); geode_ss->setMode( GL_CULL_FACE, osg::StateAttribute::OFF ); geode->setCullingActive(false); mt->addChild(geode); mapNode->getModelLayerGroup()->addChild(mt); return true; } return false; }
void LayerShader::install(Layer* layer, TerrainResources* res) { if (!layer || !res) return; osg::StateSet* stateset = layer->getOrCreateStateSet(); VirtualProgram* vp = VirtualProgram::getOrCreate(stateset); ShaderPackage package; package.add("", _options.code()); package.loadAll(vp, layer->getReadOptions()); for (int i = 0; i < _options.samplers().size(); ++i) { const ShaderOptions::Sampler& sampler = _options.samplers()[i]; if (!sampler._name.empty()) { _reservations.push_back(TextureImageUnitReservation()); TextureImageUnitReservation& reservation = _reservations.back(); if (sampler._uris.size() == 1) // Texture2D { if (res->reserveTextureImageUnitForLayer(reservation, layer, "User shader sampler")) { osg::Image* image = sampler._uris[0].getImage(layer->getReadOptions()); if (image) { osg::Texture2D* tex = new osg::Texture2D(image); tex->setFilter(tex->MIN_FILTER, tex->NEAREST_MIPMAP_LINEAR); tex->setFilter(tex->MAG_FILTER, tex->LINEAR); tex->setWrap(tex->WRAP_S, tex->REPEAT); tex->setWrap(tex->WRAP_T, tex->REPEAT); tex->setUnRefImageDataAfterApply(true); tex->setMaxAnisotropy(4.0); tex->setResizeNonPowerOfTwoHint(false); stateset->setTextureAttribute(reservation.unit(), tex); stateset->addUniform(new osg::Uniform(sampler._name.c_str(), reservation.unit())); } } else { OE_WARN << LC << "Failed to allocate a texture image unit for this terrain shader sampler!\n"; } } else if (sampler._uris.size() > 1) // Texture2DArray { if (res->reserveTextureImageUnitForLayer(reservation, layer, "User shader sampler array")) { int sizeX = 0, sizeY = 0; osg::Texture2DArray* tex = new osg::Texture2DArray(); tex->setTextureSize(512, 512, sampler._uris.size()); tex->setTextureDepth(sampler._uris.size()); for (int j = 0; j < sampler._uris.size(); ++j) { const URI& uri = sampler._uris[j]; osg::ref_ptr<osg::Image> image = uri.getImage(layer->getReadOptions()); if (image) { OE_INFO << LC << " Added image from \"" << uri.full() << "\"\n"; tex->setImage(i, image); tex->setFilter(tex->MIN_FILTER, tex->NEAREST_MIPMAP_LINEAR); tex->setFilter(tex->MAG_FILTER, tex->LINEAR); tex->setWrap(tex->WRAP_S, tex->CLAMP_TO_EDGE); tex->setWrap(tex->WRAP_T, tex->CLAMP_TO_EDGE); tex->setUnRefImageDataAfterApply(true); tex->setResizeNonPowerOfTwoHint(false); stateset->setTextureAttribute(reservation.unit(), tex); stateset->addUniform(new osg::Uniform(sampler._name.c_str(), reservation.unit())); if (sizeX == 0) { sizeX = image->s(); sizeY = image->t(); tex->setTextureSize(sizeX, sizeY, sampler._uris.size()); } } } } else { OE_WARN << LC << "Failed to allocate a texture image unit for this terrain shader sampler!\n"; } } } } for (int i = 0; i < _options.uniforms().size(); ++i) { const ShaderOptions::Uniform& uniform = _options.uniforms()[i]; if (!uniform._name.empty() && uniform._value.isSet()) { osg::Uniform* u = new osg::Uniform(uniform._name.c_str(), (float)uniform._value.get()); stateset->addUniform(u); } } }