标签: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