目标:(七十八)中的问题152
先上效果图:
思路是:不同的高程采用不同的颜色进行着色,需要对rex引擎现有的片段着色器进行修改。默认的片段着色器是这样的(见osgEarth的Rex引擎原理分析(五十四)rex引擎默认的几个着色器功能分析):
#version 330 compatibility
#pragma vp_name VP Fragment Shader Main
#extension GL_ARB_gpu_shader5 : enable
// Fragment output
out vec4 vp_FragColor;
// Fragment stage inputs:
in VP_PerVertex {
float oe_layer_rangeOpacity;
float oe_rex_morphFactor;
vec2 oe_normalMapCoords;
vec3 oe_UpVectorView;
vec3 oe_normalMapBinormal;
vec3 vp_Normal;
vec4 oe_layer_texc;
vec4 oe_layer_texcParent;
vec4 oe_layer_tilec;
vec4 vp_Color;
vec4 vp_Vertex;
} vp_in;
// Fragment stage globals:
float oe_layer_rangeOpacity;
float oe_rex_morphFactor;
vec2 oe_normalMapCoords;
vec3 oe_UpVectorView;
vec3 oe_normalMapBinormal;
vec3 vp_Normal;
vec4 oe_layer_texc;
vec4 oe_layer_texcParent;
vec4 oe_layer_tilec;
vec4 vp_Color;
vec4 vp_Vertex;
// Function declarations:
void oe_normalMapFragment(inout vec4 color);
void oe_rexEngine_frag(inout vec4 color);
void main(void)
{
oe_layer_rangeOpacity = vp_in.oe_layer_rangeOpacity;
oe_rex_morphFactor = vp_in.oe_rex_morphFactor;
oe_normalMapCoords = vp_in.oe_normalMapCoords;
oe_UpVectorView = vp_in.oe_UpVectorView;
oe_normalMapBinormal = vp_in.oe_normalMapBinormal;
vp_Normal = vp_in.vp_Normal;
oe_layer_texc = vp_in.oe_layer_texc;
oe_layer_texcParent = vp_in.oe_layer_texcParent;
oe_layer_tilec = vp_in.oe_layer_tilec;
vp_Color = vp_in.vp_Color;
vp_Vertex = vp_in.vp_Vertex;
vp_Normal = normalize(vp_Normal);
oe_normalMapFragment( vp_Color );
oe_rexEngine_frag( vp_Color );
vp_FragColor = vp_Color;
}
注意这里有一个oe_layer_tilec,其中的st分量记录的是片段的纹理坐标,根据这个坐标就可以获取高程值,根据这个高程值给vp_Color赋不同值,就可以不渲染影像数据,而是采用基于高程的着色方案,也就是晕渲图的制作。这里需要生成一个片段着色器文件,其中有一个函数负责根据oe_layer_tilec.st来修改vp_Color,这个着色器文件函数顺序一定要放在最后,否则他的效果会被其他着色器函数修改,也就是vp_order要大。
写好这个片段着色器文件后,要将其注入到rex引擎的着色器程序中,注入方法为:
osg::Group* container=dynamic_cast<osg::Group*>(mapNode->getChild(1));
osgEarth::OverlayDecorator* deco= dynamic_cast<osgEarth::OverlayDecorator*>(container->getChild(0));
osgEarth::Drivers::RexTerrainEngine::RexTerrainEngineNode* Rexter=dynamic_cast<osgEarth::Drivers::RexTerrainEngine::RexTerrainEngineNode*>(deco->getChild(0));
//加入自定义的着色器
osg::StateSet* surfaceStateSet = Rexter->getSurfaceStateSet();
osgEarth::VirtualProgram* surfaceVP = osgEarth::VirtualProgram::getOrCreate(surfaceStateSet);
osgEarth::ShaderPackage package;
//package.load(surfaceVP, package.ENGINE_VERT_VIEW);
package.load(surfaceVP, "elevation.frag.glsl");
着色器文件elevation.frag.glsl内容为:
#version $GLSL_VERSION_STR
$GLSL_DEFAULT_PRECISION_FLOAT
#pragma vp_name REX Engine - Fragment
#pragma vp_entryPoint elevation_last_frag
#pragma vp_location fragment_coloring
#pragma vp_order 0.9
// SDK functions:
float oe_terrain_getElevation();
void elevation_last_frag(inout vec4 color)
{
vec4 vec4ColorArray[64];
vec4ColorArray[ 0] = vec4(0.00000, 0.00000, 0.56250, 1.0);
vec4ColorArray[ 1] = vec4(0.00000, 0.00000, 0.62500, 1.0);
vec4ColorArray[ 2] = vec4(0.00000, 0.00000, 0.68750, 1.0);
vec4ColorArray[ 3] = vec4(0.00000, 0.00000, 0.75000, 1.0);
vec4ColorArray[ 4] = vec4(0.00000, 0.00000, 0.81250, 1.0);
vec4ColorArray[ 5] = vec4(0.00000, 0.00000, 0.87500, 1.0);
vec4ColorArray[ 6] = vec4(0.00000, 0.00000, 0.93750, 1.0);
vec4ColorArray[ 7] = vec4(0.00000, 0.00000, 1.00000, 1.0);
vec4ColorArray[ 8] = vec4(0.00000, 0.06250, 1.00000, 1.0);
vec4ColorArray[ 9] = vec4(0.00000, 0.12500, 1.00000, 1.0);
vec4ColorArray[10] = vec4(0.00000, 0.18750, 1.00000, 1.0);
vec4ColorArray[11] = vec4(0.00000, 0.25000, 1.00000, 1.0);
v