标签:color fail when gear mode ping uil 自己的 visible
以oe2.8 为例,剖析一下画等高线的过程, 在新版本的OE中, 替换为一个visibleLayer.
先看初始化过程
void
ContourMap::init()
{
    // negative means unset:
    _unit = -1;
    // uniforms we‘ll need:
    _xferMin     = new osg::Uniform(osg::Uniform::FLOAT,      "oe_contour_min" );
    _xferRange   = new osg::Uniform(osg::Uniform::FLOAT,      "oe_contour_range" );
    _xferSampler = new osg::Uniform(osg::Uniform::SAMPLER_1D, "oe_contour_xfer" );
    _opacityUniform = new osg::Uniform(osg::Uniform::FLOAT,   "oe_contour_opacity" );
    // Create a 1D texture from the transfer function‘s image.
    _xferTexture = new osg::Texture1D();
    _xferTexture->setResizeNonPowerOfTwoHint( false );
    _xferTexture->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR );
    _xferTexture->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR );
    _xferTexture->setWrap( osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE );
定义了一系列的UNiform , 可以看出主要用shader来实现等高线。
接下来看:
void
ContourMap::setTransferFunction(osg::TransferFunction1D* xfer)
{
    _xfer = xfer;
    _xferTexture->setImage( _xfer->getImage() );
    _xferMin->set( _xfer->getMinimum() );
    _xferRange->set( _xfer->getMaximum() - _xfer->getMinimum() );
}
void
ContourMap::dirty()
{
    _opacityUniform->set(opacity().getOrUse(1.0f));
    
    // build a transfer function.
    osg::TransferFunction1D* xfer = new osg::TransferFunction1D();
    float s = 2500.0f;
    if ( grayscale() == true )
    {
        xfer->setColor( -1.0000 * s, osg::Vec4f(.125,.125,.125, 1), false);
        xfer->setColor( -0.2500 * s, osg::Vec4f(.25,.25,.25, 1), false);
        xfer->setColor(  0.0000 * s, osg::Vec4f(.375,.375,.375, 1), false);
        xfer->setColor(  0.0062 * s, osg::Vec4f(.5,.5,.5,1), false);
        xfer->setColor(  0.1250 * s, osg::Vec4f(.625,.625,.625,1), false);
        xfer->setColor(  0.3250 * s, osg::Vec4f(.75,.75,.75,1), false);
        xfer->setColor(  0.7500 * s, osg::Vec4f(.875,.875,.875,1), false);
        xfer->setColor(  1.0000 * s, osg::Vec4f(1,1,1,1), false);
    }
    else
    {
        xfer->setColor( -1.0000 * s, osg::Vec4f(0, 0, 0.5, 1), false);
        xfer->setColor( -0.2500 * s, osg::Vec4f(0, 0, 1, 1), false);
        xfer->setColor(  0.0000 * s, osg::Vec4f(0, .5, 1, 1), false);
        xfer->setColor(  0.0062 * s, osg::Vec4f(.84,.84,.25,1), false);
        xfer->setColor(  0.1250 * s, osg::Vec4f(.125,.62,0,1), false);
        xfer->setColor(  0.3250 * s, osg::Vec4f(.80,.70,.47,1), false);
        xfer->setColor(  0.7500 * s, osg::Vec4f(.5,.5,.5,1), false);
        xfer->setColor(  1.0000 * s, osg::Vec4f(1,1,1,1), false);
    }
    xfer->updateImage();
    this->setTransferFunction( xfer );
}
dirty 函数在init 里面被调用, 设置一个transferFunction 。 这个transferfunction 有何作用,尚未清楚。网上找了一大圈也没找到,
看来OSG社区真的是没落了。
在OSG代码里找到这样一段话:
/** TransferFunction is a class that provide a 1D,2D or 3D colour look up table * that can be used on the GPU as a 1D, 2D or 3D texture. * Typically uses include mapping heights to colours when contouring terrain, * or mapping intensities to colours when volume rendering. */
就是一段颜色查找表,用来将高度或密度映射到颜色区间。
接下来:
void
ContourMap::setTransferFunction(osg::TransferFunction1D* xfer)
{
    _xfer = xfer;
    _xferTexture->setImage( _xfer->getImage() );
    _xferMin->set( _xfer->getMinimum() );
    _xferRange->set( _xfer->getMaximum() - _xfer->getMinimum() );
}
根据颜色lookup table , 设置自己的uniform 变量。
void
ContourMap::onInstall(TerrainEngineNode* engine)
{
    if ( engine )
    {
        if ( !engine->getResources()->reserveTextureImageUnit(_unit, "ContourMap") )
        {
            OE_WARN << LC << "Failed to reserve a texture image unit; disabled." << std::endl;
            return;
        }
        osg::StateSet* stateset = engine->getOrCreateStateSet();
        // Install the texture and its sampler uniform:
        stateset->setTextureAttributeAndModes( _unit, _xferTexture.get(), osg::StateAttribute::ON );
        stateset->addUniform( _xferSampler.get() );
        _xferSampler->set( _unit );
        // (By the way: if you want to draw image layers on top of the contoured terrain,
        // set the "priority" parameter to setFunction() to a negative number so that it draws
        // before the terrain‘s layers.)
        VirtualProgram* vp = VirtualProgram::getOrCreate(stateset);
        Shaders pkg;
        //pkg.load(vp, pkg.ContourMap_Vertex);
        pkg.load(vp, pkg.ContourMap_Fragment);
        // Install some uniforms that tell the shader the height range of the color map.
        stateset->addUniform( _xferMin.get() );
        _xferMin->set( _xfer->getMinimum() );
        stateset->addUniform( _xferRange.get() );
        _xferRange->set( _xfer->getMaximum() - _xfer->getMinimum() );
        stateset->addUniform( _opacityUniform.get() );
    }
}
接下来就是把 contourmap effect 跟 engine 联系起来 。 通过创建 virtualProgram , 让virtualprogram 和 engine 的stateset 链接。 重要的实现方式在shader 代码里, 继续来找
下面是shader 的实现方式
#version $GLSL_VERSION_STR
$GLSL_DEFAULT_PRECISION_FLOAT
#pragma vp_entryPoint oe_contour_fragment
#pragma vp_location   fragment_coloring
#pragma vp_order      0.2
varying vec4 oe_layer_tilec;
uniform sampler1D oe_contour_xfer;
uniform float oe_contour_opacity;
uniform float oe_contour_min;
uniform float oe_contour_range;
float oe_terrain_getElevation(in vec2 uv);
void oe_contour_fragment( inout vec4 color )
{
    float height = oe_terrain_getElevation(oe_layer_tilec.st);
    float height_normalized = (height-oe_contour_min)/oe_contour_range;
    float lookup = clamp( height_normalized, 0.0, 1.0 );
    vec4 texel = texture1D( oe_contour_xfer, lookup );
    color.rgb = mix(color.rgb, texel.rgb, texel.a * oe_contour_opacity);
}
可以看出,这个shader 很简洁, 先查找到高度。 oe_ 前缀的都是内置的shader uniform . 让后把高度归一化, 最后通过lookup table 得到fragment color .
标签:color fail when gear mode ping uil 自己的 visible
原文地址:https://www.cnblogs.com/enigma19971/p/12893589.html