Beispiel #1
0
// Attempts to position unplaced rectangles from the layout into this row.
int TextureLayoutRow::Generate(TextureLayout& layout, int max_width, int y)
{
	int placed_rectangles = 0;

	while(!layout.unplaced_rectangles.empty())
	{
		TextureLayoutRectangle* rectangle = layout.unplaced_rectangles.front();
		if (placed_width + rectangle->GetDimensions().x + 1 > max_width)
			break;

		// Increment the row height if necessary.
		height = Math::Max(height, rectangle->GetDimensions().y);

		// Add this glyph onto our list and mark it as placed.
		rectangles.push_back(rectangle);
		if (layout.has_generated)
			rectangle->Place(layout.GetNumTextures()-1, Vector2i(placed_width, y));
		else
			rectangle->Place(layout.GetNumTextures(), Vector2i(placed_width, y));
		++placed_rectangles;

		// Increment our width. An extra pixel is added on so the rectangles aren't pushed up
		// against each other. This will avoid filtering artifacts.
		if (rectangle->GetDimensions().x > 0)
			placed_width += rectangle->GetDimensions().x + 1;

		layout.rectangles.push_back(rectangle);
		layout.unplaced_rectangles.pop();
	}

	return placed_rectangles;
}
void
TextureCompositorMultiTexture::applyLayerUpdate(osg::StateSet*       stateSet,
                                                UID                  layerUID,
                                                const GeoImage&      preparedImage,
                                                const TileKey&       tileKey,
                                                const TextureLayout& layout,
                                                osg::StateSet*       parentStateSet) const
{
    osg::Texture2D* tex = s_getTexture( stateSet, layerUID, layout, parentStateSet, _minFilter, _magFilter);
    if ( tex )
    {
        osg::Image* image = preparedImage.getImage();
        image->dirty(); // required for ensure the texture recognizes the image as new data
        tex->setImage( image );

        // set up proper mipmapping filters:
        if (_enableMipmapping &&
            _enableMipmappingOnUpdatedTextures &&
            ImageUtils::isPowerOfTwo( image ) &&
            !(!image->isMipmap() && ImageUtils::isCompressed(image)) )
        {
            if ( tex->getFilter(osg::Texture::MIN_FILTER) != _minFilter )
                tex->setFilter( osg::Texture::MIN_FILTER, _minFilter );
        }
        else if ( tex->getFilter(osg::Texture::MIN_FILTER) != osg::Texture::LINEAR )
        {
            tex->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR );
        }

        bool lodBlending = layout.getSlot(layerUID, 1) >= 0;

        if (_enableMipmapping &&
            _enableMipmappingOnUpdatedTextures &&
            lodBlending )
        {
            int slot = layout.getSlot(layerUID, 0);

            // update the timestamp on the image layer to support blending.
            float now = (float)osg::Timer::instance()->delta_s( osg::Timer::instance()->getStartTick(), osg::Timer::instance()->tick() );
            ArrayUniform stampUniform( "osgearth_SlotStamp", osg::Uniform::FLOAT, stateSet, layout.getMaxUsedSlot() + 1 );
            stampUniform.setElement( slot, now );

            // set the texture matrix to properly position the blend (parent) texture
            osg::Matrix mat;
            if ( parentStateSet != 0L )
            {
                unsigned tileX, tileY;
                tileKey.getTileXY(tileX, tileY);

                mat(0,0) = 0.5f;
                mat(1,1) = 0.5f;
                mat(3,0) = (float)(tileX % 2) * 0.5f;
                mat(3,1) = (float)(1 - tileY % 2) * 0.5f;
            }

            ArrayUniform texMatUniform( "osgearth_TexBlendMatrix", osg::Uniform::FLOAT_MAT4, stateSet, layout.getMaxUsedSlot() + 1 );
            texMatUniform.setElement( slot, mat );
        }
    }
}
	void RenderColourLayerToTexture::doRender( Position const & p_position
		, Size const & p_size
		, TextureLayout const & p_texture
		, RenderPipeline & p_pipeline
		, MatrixUbo & p_matrixUbo
		, GeometryBuffers const & p_geometryBuffers
		, uint32_t p_layer )
	{
		REQUIRE( p_texture.getLayersCount() > p_layer );
		m_viewport.setPosition( p_position );
		m_viewport.resize( p_size );
		m_viewport.update();
		m_viewport.apply();

		REQUIRE( m_layerIndexUniform );
		m_layerIndexUniform->setValue( p_layer );

		p_matrixUbo.update( m_viewport.getProjection() );
		p_pipeline.apply();
		m_layerIndexUniform->update();

		p_texture.bind( MinTextureIndex );
		m_sampler->bind( MinTextureIndex );
		p_geometryBuffers.draw( uint32_t( m_arrayVertex.size() ), 0u );
		m_sampler->unbind( MinTextureIndex );
		p_texture.unbind( MinTextureIndex );
	}
// Attempts to position unplaced rectangles from the layout into this row.
int TextureLayoutRow::Generate(TextureLayout& layout, int max_width, int y)
{
	int width = 1;
	int first_unplaced_index = 0;
	int placed_rectangles = 0;

	while (width < max_width)
	{
		// Find the first unplaced rectangle we can fit.
		int index;
		for (index = first_unplaced_index; index < layout.GetNumRectangles(); ++index)
		{
			TextureLayoutRectangle& rectangle = layout.GetRectangle(index);
			if (!rectangle.IsPlaced())
			{
				if (width + rectangle.GetDimensions().x + 1 <= max_width)
					break;
			}
		}

		if (index == layout.GetNumRectangles())
			return placed_rectangles;

		TextureLayoutRectangle& rectangle = layout.GetRectangle(index);

		// Increment the row height if necessary.
		height = Math::Max(height, rectangle.GetDimensions().y);

		// Add this glyph onto our list and mark it as placed.
		rectangles.push_back(&rectangle);
		rectangle.Place(layout.GetNumTextures(), Vector2i(width, y));
		++placed_rectangles;

		// Increment our width. An extra pixel is added on so the rectangles aren't pushed up
		// against each other. This will avoid filtering artifacts.
		if (rectangle.GetDimensions().x > 0)
			width += rectangle.GetDimensions().x + 1;

		first_unplaced_index = index + 1;
	}

	return placed_rectangles;
}
void
TextureCompositorMultiTexture::updateMasterStateSet(osg::StateSet*       stateSet,
                                                    const TextureLayout& layout    ) const
{
    int numSlots = layout.getMaxUsedSlot() + 1;
    int maxUnits = numSlots;

    if ( _useGPU )
    {
        // Validate against the max number of GPU texture units:
        if ( maxUnits > Registry::instance()->getCapabilities().getMaxGPUTextureUnits() )
        {
            maxUnits = Registry::instance()->getCapabilities().getMaxGPUTextureUnits();

            OE_WARN << LC
                << "Warning! You have exceeded the number of texture units available on your GPU ("
                << maxUnits << "). Consider using another compositing mode."
                << std::endl;
        }

        VirtualProgram* vp = static_cast<VirtualProgram*>( stateSet->getAttribute(VirtualProgram::SA_TYPE) );
        // see if we have any blended layers:
        bool hasBlending = layout.containsSecondarySlots( maxUnits );

        // Why are these marked as PROTECTED? See the comments in MapNode.cpp for the answer.
        // (Where it sets up the top-level VirtualProgram)

        vp->setFunction(
            "oe_multicomp_vertex",
            s_createTextureVertexShader(layout, hasBlending),
            ShaderComp::LOCATION_VERTEX_MODEL,
            0.0 );

        vp->setFunction(
            "oe_multicomp_fragment",
            s_createTextureFragShaderFunction(layout, maxUnits, hasBlending, _lodTransitionTime),
            ShaderComp::LOCATION_FRAGMENT_COLORING,
            0.0 );

        //vp->setShader(
        //    "osgearth_vert_setupColoring",
        //    s_createTextureVertexShader(layout, hasBlending),
        //    osg::StateAttribute::ON | osg::StateAttribute::PROTECTED );

        //vp->setShader(
        //    "osgearth_frag_applyColoring",
        //    s_createTextureFragShaderFunction(layout, maxUnits, hasBlending, _lodTransitionTime),
        //    osg::StateAttribute::ON | osg::StateAttribute::PROTECTED );
    }

    else
    {
        // Forcably disable shaders
        stateSet->setAttributeAndModes( new osg::Program(), osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );

        // Validate against the maximum number of textures available in FFP mode.
        if ( maxUnits > Registry::instance()->getCapabilities().getMaxFFPTextureUnits() )
        {
            maxUnits = Registry::instance()->getCapabilities().getMaxFFPTextureUnits();
            OE_WARN << LC <<
                "Warning! You have exceeded the number of texture units available in fixed-function pipeline "
                "mode on your graphics hardware (" << maxUnits << "). Consider using another "
                "compositing mode." << std::endl;
        }

        // FFP multitexturing requires that we set up a series of TexCombine attributes:
        if (maxUnits == 1)
        {
            osg::TexEnv* texenv = new osg::TexEnv(osg::TexEnv::MODULATE);
            stateSet->setTextureAttributeAndModes(0, texenv, osg::StateAttribute::ON);
        }
        else if (maxUnits >= 2)
        {
            //Blend together the colors and accumulate the alpha values of textures 0 and 1 on unit 0
            {
                osg::TexEnvCombine* texenv = new osg::TexEnvCombine;
                texenv->setCombine_RGB(osg::TexEnvCombine::INTERPOLATE);
                texenv->setCombine_Alpha(osg::TexEnvCombine::ADD);

                texenv->setSource0_RGB(osg::TexEnvCombine::TEXTURE0+1);
                texenv->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR);
                texenv->setSource0_Alpha(osg::TexEnvCombine::TEXTURE0+1);
                texenv->setOperand0_Alpha(osg::TexEnvCombine::SRC_ALPHA);

                texenv->setSource1_RGB(osg::TexEnvCombine::TEXTURE0+0);
                texenv->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR);
                texenv->setSource1_Alpha(osg::TexEnvCombine::TEXTURE0+0);
                texenv->setOperand1_Alpha(osg::TexEnvCombine::SRC_ALPHA);

                texenv->setSource2_RGB(osg::TexEnvCombine::TEXTURE0+1);
                texenv->setOperand2_RGB(osg::TexEnvCombine::SRC_ALPHA);

                stateSet->setTextureAttributeAndModes(0, texenv, osg::StateAttribute::ON);
            }


            //For textures 2 and beyond, blend them together with the previous
            //Add the alpha values of this unit and the previous unit
            for (int unit = 1; unit < maxUnits-1; ++unit)
            {
                osg::TexEnvCombine* texenv = new osg::TexEnvCombine;
                texenv->setCombine_RGB(osg::TexEnvCombine::INTERPOLATE);
                texenv->setCombine_Alpha(osg::TexEnvCombine::ADD);

                texenv->setSource0_RGB(osg::TexEnvCombine::TEXTURE0+unit+1);
                texenv->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR);
                texenv->setSource0_Alpha(osg::TexEnvCombine::TEXTURE0+unit+1);
                texenv->setOperand0_Alpha(osg::TexEnvCombine::SRC_ALPHA);

                texenv->setSource1_RGB(osg::TexEnvCombine::PREVIOUS);
                texenv->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR);
                texenv->setSource1_Alpha(osg::TexEnvCombine::PREVIOUS);
                texenv->setOperand1_Alpha(osg::TexEnvCombine::SRC_ALPHA);

                texenv->setSource2_RGB(osg::TexEnvCombine::TEXTURE0+unit+1);
                texenv->setOperand2_RGB(osg::TexEnvCombine::SRC_ALPHA);

                stateSet->setTextureAttributeAndModes(unit, texenv, osg::StateAttribute::ON);
            }

            //Modulate the colors to get proper lighting on the last unit
            //Keep the alpha results from the previous stage
            {
                osg::TexEnvCombine* texenv = new osg::TexEnvCombine;
                texenv->setCombine_RGB(osg::TexEnvCombine::MODULATE);
                texenv->setCombine_Alpha(osg::TexEnvCombine::REPLACE);

                texenv->setSource0_RGB(osg::TexEnvCombine::PREVIOUS);
                texenv->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR);
                texenv->setSource0_Alpha(osg::TexEnvCombine::PREVIOUS);
                texenv->setOperand0_Alpha(osg::TexEnvCombine::SRC_ALPHA);

                texenv->setSource1_RGB(osg::TexEnvCombine::PRIMARY_COLOR);
                texenv->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR);
                stateSet->setTextureAttributeAndModes(maxUnits-1, texenv, osg::StateAttribute::ON);
            }
        }
    }
}
void
TextureCompositorTexArray::applyLayerUpdate(osg::StateSet*       stateSet,
                                            UID                  layerUID,
                                            const GeoImage&      preparedImage,
                                            const TileKey&       tileKey,
                                            const TextureLayout& layout,
                                            osg::StateSet*       parentStateSet) const
{
    GeoExtent tileExtent(tileKey.getExtent());
    int slot = layout.getSlot( layerUID );
    if ( slot < 0 )
        return; // means the layer no longer exists

    // access the texture array, creating or growing it if necessary:
    osg::Texture2DArray* texture = s_getTexture( stateSet, layout, 0,
                                                 textureSize() );
    ensureSampler( stateSet, 0 );
    // assign the new image at the proper position in the texture array.
    osg::Image* image = preparedImage.getImage();
    assignImage(texture, slot, image);
    
    // update the region uniform to reflect the geo extent of the image:
    const GeoExtent& imageExtent = preparedImage.getExtent();
    osg::Vec4 tileTransform;
    getImageTransform(tileExtent, imageExtent, tileTransform);

    // access the region uniform, creating or growing it if necessary:
    ArrayUniform regionUni( "region", osg::Uniform::FLOAT, stateSet, layout.getMaxUsedSlot()+1 );
    if ( regionUni.isValid() )
    {
        int layerOffset = slot * 8;
        for (int i = 0; i < 4; ++i)
            regionUni.setElement( layerOffset + i, tileTransform[i]);
        //region->dirty();
    }
    
    if ( layout.isBlendingEnabled( layerUID ) && regionUni.isValid() )
    {
        osg::Uniform* secondarySampler = ensureSampler( stateSet, 1 );
        osg::Texture2DArray* parentTexture = 0;
        const unsigned parentLayerOffset = slot * 8 + 4;
        if ( parentStateSet )
        {
            ArrayUniform parentRegion( "region", osg::Uniform::FLOAT, parentStateSet, layout.getMaxUsedSlot()+1 );

            //osg::Uniform* parentRegion = s_getRegionUniform( parentStateSet,
            //                                                 layout );
            GeoExtent parentExtent(tileKey.createParentKey().getExtent());
            float widthRatio, heightRatio;
            parentRegion.getElement(slot * 8 + 2, widthRatio);
            parentRegion.getElement(slot * 8 + 3, heightRatio);
            float parentImageWidth =  parentExtent.width() / widthRatio;
            float parentImageHeight = parentExtent.height() / heightRatio;
            float xRatio, yRatio;
            parentRegion.getElement(slot * 8, xRatio);
            parentRegion.getElement(slot * 8 + 1, yRatio);
            float ParentImageXmin = parentExtent.xMin() - xRatio * parentImageWidth;
            float ParentImageYmin = parentExtent.yMin() - yRatio * parentImageHeight;
            regionUni.setElement(parentLayerOffset,
                               static_cast<float>((tileExtent.xMin() - ParentImageXmin) / parentImageWidth));
            regionUni.setElement(parentLayerOffset + 1,
                               static_cast<float>((tileExtent.yMin() - ParentImageYmin) / parentImageHeight));
            regionUni.setElement(parentLayerOffset + 2,
                               static_cast<float>(tileExtent.width() / parentImageWidth));
            regionUni.setElement(parentLayerOffset + 3,
                               static_cast<float>(tileExtent.height() / parentImageHeight));
            //regionUni.dirty();
            parentTexture = static_cast<osg::Texture2DArray*>(parentStateSet->getTextureAttribute(0, osg::StateAttribute::TEXTURE));
        }
        else
        {
            // setting the parent transform values to -1 disabled blending for this layer. #hack -gw
            for (int i = 0; i < 4; ++i)
                regionUni.setElement(parentLayerOffset + i, tileTransform[i]);
        }

        if (parentTexture)
            stateSet->setTextureAttribute(1, parentTexture, osg::StateAttribute::ON);
        else
            secondarySampler->set(0);

        // update the timestamp on the image layer to support fade-in blending.
        float now = (float)osg::Timer::instance()->delta_s( osg::Timer::instance()->getStartTick(), osg::Timer::instance()->tick() );
        ArrayUniform stampUniform( "osgearth_SlotStamp", osg::Uniform::FLOAT, stateSet, layout.getMaxUsedSlot()+1 );
        stampUniform.setElement( slot, now );
    }
}