首页 > 其他 > 详细

[原][译]关于osgEarth::VirtualProgram

时间:2020-05-06 16:17:53      阅读:150      评论:0      收藏:0      [点我收藏+]

英文原文:http://docs.osgearth.org/en/latest/developer/shader_composition.html

Shader Composition

着色器的合成系统

 

Shader Composition(使用组合着色器的原因)

osgEarth在其几种渲染模式中使用GLSL着色器。 默认情况下,osgEarth将检测图形硬件的功能并自动选择合适的模式使用。

由于osgEarth依赖着色器,因此作为开发人员,您可能希望自定义渲染或在GLSL中添加自己的效果和功能。 使用着色器的任何人都会遇到相同的挑战:

  • 着色器程序是整体的。 添加新的着色器代码要求您复制,修改和替换现有代码,以免失去其功能。
  • 使您的更改与原始代码的着色器的更改保持同步是维护的噩梦。
  • 维护着色器main()的多个版本既麻烦又困难。
  • 随着GLSL代码库的复杂性增加和添加更多功能,维护可怕的“超级着色器”变得难以管理。

着色器合成(Shader Composition )通过将着色器管道模块化来解决这些问题。 您可以在程序中的任何位置添加和删除功能,而无需复制,粘贴或修改其他人的GLSL代码。

接下来,我们将讨论osgEarth的着色器合成框架的结构。

 

Framework Basics(基础框架介绍)

组合着色器的框架自动提供main()函数。 您无需编写它们。 而且,你可以编写模块化函数,并告诉框架在哪里执行它们。

下面,你可以看到osgEarth创建的main()函数。

LOCATION_ *指示符允许您在着色器的执行管道中的各个点插入函数。

以下是osgEarth的内置着色器主函数的伪代码:

// VERTEX SHADER:

void main(void)
{
    vec4 vertex = gl_Vertex;

    // "LOCATION_VERTEX_MODEL" user functions are called here:
    model_func_1(vertex);
    model_func_2(vertex);
    ...

    vertex = gl_ModelViewMatrix * vertex;

    // "LOCATION_VERTEX_VIEW" user functions are called here:
    view_func_1(vertex);
    ...

    vertex = gl_ProjectionMatrix * vertex;

    // "LOCATION_VERTEX_CLIP" user functions are called last:
    clip_func_1(vertex);
    ...

    gl_Position = vertex;
}


// FRAGMENT SHADER:

void main(void)
{
    vec4 color = gl_Color;
    ...

    // "LOCATION_FRAGMENT_COLORING" user functions are called here:
    coloring_func_1(color);
    ...

    // "LOCATION_FRAGMENT_LIGHTING" user functions are called here:
    lighting_func_1(color);
    ...

    gl_FragColor = color;
}

 

如您所见,我们已经做出了指定功能注入点的设计决定。申请。这并不是说它们对所有事物都是完美的,而是说我们相信这种方法使框架易于使用,而不是太“低级”。

重要:着色器组合框架此时只支持顶点和片段着色器。它不支持几何或镶嵌着色器。我们计划在将来增加这一点。

 

虚拟程序

osgEarth引入了一个新的osg状态属性,名为VirtualProgram执行运行时着色器组合的。自VirtualProgramosg::StateAttribute,您可以将一个附加到场景图中的任何节点。属于VirtualProgram可以覆盖更高的场景图上的着色器。通过这种方式,您可以在osgEarth中添加、组合和重写单个着色器函数。

在运行时,VirtualProgram将查看当前状态并组装一个完整的osg::Program,它使用内置main()s,并调用通过VirtualProgram.

添加函数

从我们前面看到的生成的主管道中,osgEarth调用用户函数。这些不存在于osgEarth生成的默认着色器中;相反,它们代表了您作为开发人员可以“注入”到着色器管道中各个位置的代码。

例如,让我们使用用户函数创建一个简单的“模糊”效果:

// haze_vertex:
out vec3 v_pos;
void setup_haze(inout vec4 vertexView)
{
    v_pos = vertexView.xyz;
}

// haze_fragment:
in vec3 v_pos;
void apply_haze(inout vec4 color)
{
    float dist = clamp( length(v_pos)/10000000.0, 0, 0.75 );
    color = mix(color, vec4(0.5, 0.5, 0.5, 1.0), dist);
}

// C++:
VirtualProgram* vp = VirtualProgram::getOrCreate( stateSet );

vp->setFunction( "setup_haze", haze_vertex,   ShaderComp::LOCATION_VERTEX_VIEW);
vp->setFunction( "apply_haze", haze_fragment, ShaderComp::LOCATION_FRAGMENT_LIGHTING);

在本例中,函数setup_haze在内置顶点函数之后,从内置顶点着色器main()调用。这个apply_haze函数在内置片段函数之后从核心片段着色器main()调用。

有六个插入点,如下:

LocationShader TypeSignature
ShaderComp::LOCATION_VERTEX_MODEL VERTEX void func(inout vec4 vertex)
ShaderComp::LOCATION_VERTEX_VIEW VERTEX void func(inout vec4 vertex)
ShaderComp::LOCATION_VERTEX_CLIP VERTEX void func(inout vec4 vertex)
ShaderComp::LOCATION_FRAGMENT_COLORING FRAGMENT void func(inout vec4 color)
ShaderComp::LOCATION_FRAGMENT_LIGHTING FRAGMENT void func(inout vec4 color)
ShaderComp::LOCATION_FRAGMENT_OUTPUT FRAGMENT void func(inout vec4 color)

每个顶点位置都允许您在一个特定的顶点上操作。坐标空间。你可以改变顶点,但你把它放在同一个空间里。

模型: 顶点是几何中未转换的原始值。
意见: 顶点相对于眼点,它位于原点(0,0,0),指向-Z轴。在视图空间中,原始顶点已被gl_ModelViewMatrix.
剪辑: 后投影剪辑空间。剪辑空间位于所有三个轴的[-w.w]范围内,是将原始顶点转换为gl_ModelViewProjectionMatrix.

碎片位置如下。

着色: 在应用照明之前,在解析片段颜色时调用这里的函数。纹理或颜色调整通常发生在这一阶段。
照明: 这里的功能影响到应用于片段颜色的照明。这就是太阳照明、碰撞映射或正常映射等通常发生的地方。
产出: 这里是设置gl_FragColor的地方。默认情况下,内置片段main()将为您设置它。但是您可以设置一个输出着色器来替换您自己的这种行为。这样做的一个典型原因是实现MRT呈现(请参阅osgEarth_mrt示例)。

着色包

早些时候,我们向您展示了如何使用VirtualProgram。Shader组合框架还提供了一个ShaderPackage支持更高级的着色器管理方法。我们现在将讨论其中的一些问题。

虚拟程序元数据

正如我们所看到的,当您向管道中添加一个着色器函数时,可以使用VirtualProgram您需要告诉osgEarth要调用的GLSL函数的名称,以及调用它的管道中的位置,如下所示:

VirtualProgram* vp;
....
vp->setFunction( "color_it_red", shaderSource, ShaderComp::LOCATION_FRAGMENT_COLORING );

这很管用。但是,如果函数名或注入位置发生变化,则需要记住使GLSL代码与setFunction()参数。

这将更容易在一次指定这一切。一个ShaderPackage就让你这么做吧。以下是一个例子:

#version 110

#pragma vp_entryPoint  color_it_red
#pragma vp_location    fragment_coloring
#pragma vp_order       1.0

void color_it_red(inout vec4 color)
{
    color.r = 1.0;
}

现在不用打电话VirtualProgram::setFunction()目录中,您可以创建一个ShaderPackage,添加您的代码,并调用Load在VirtualProgram:

ShaderPackage package;
package.add( shaderFileName, shaderSource );
package.load( virtualProgram, shaderFileName );

它采用“文件名”,因为着色器可以在外部文件中。但这不是一项要求。阅读更多细节。

这个vp_location值遵循基于代码的值,如下所示:

  • vertex_model
  • vertex_view
  • vertex_clip
  • fragment_coloring
  • fragment_lighting
  • fragment_output

外部GLSL文件

这个ShaderPackage允许您从文件或字符串加载GLSL代码。当你打电话给add方法,这将告诉包(A)首先使用该文件名查找文件并从该文件加载;(B)如果不存在该文件,则使用源字符串中的代码。

让我们来看看这个例子:

ShaderPackage package;
package.add( "myshader.frag.glsl", backupSourceCode );
...
package.load( virtualProgram, "myshader.frag.glsl" );

包将尝试从GLSL文件加载着色器。它将在OSG_FILE_PATH。如果它找不到文件,它将从软件包中与该着色器相关联的备份源代码中加载着色器。

osgEarth在内部使用这种技术“内联”其股票着色代码。这使您可以选择使用应用程序部署GLSL文件,或者将它们保持在内联状态--无论哪种方式,应用程序仍然可以工作。

包括档案

这个ShaderPackage如果包括文件。您的GLSL代码可以包括通过引用同一包中的任何其他着色器的文件名。使用自定义#pragma若要包含其他文件,请执行以下操作:

#pragma include myCode.vertex.glsl

就像在C++中一样,包括将直接内联加载其他文件(或源代码)。因此,您所包含的文件必须是结构化的,就好像您已经将其正确地放置在包含文件中一样。)这意味着它不能拥有自己的#version例如,字符串。)

再次:包容者包括e必须以相同的方式注册ShaderPackage.


特定于osgEarth的概念

尽管虚拟程序框架包含在osgEarth SDK中,但它实际上与地图呈现无关。在本节中,我们将介绍osgEarth对着色器组合所做的一些事情。

 

地形变量

有一些内置的着色器uniformsvariables这是osgEarth地形引擎使用的,也是开发者可以使用的。

重要:以前缀`OO_`或`osgEarth_`开头的着色变量保留给osgEarth内部使用。

制服:

OE_TLAY_KEY: (向量4)元素0-2包含x、y和LOD的平铺键值;元素3保存瓷砖的边界球半径(以米为单位)。
OE_Layer_Tex: (Sampler2D)纹理应用于当前瓷砖的当前层
OE_Layer_texc: (向量4)当前瓷砖的纹理坐标
OE_Layer_Tilec: (向量4)当前瓷砖的单位坐标(x和y中的0..1)
OE_Layer_UID: (Int)活动层的唯一ID
OE层顺序: (Int)呈现活动层的顺序
OE层不透明度:
  (浮点)活动层的不透明度[0..1]

顶点属性:

OE地形攻击:
  (向量4)元素0-2持有地形顶点的单位高度矢量,元素3保存原始地形海拔值。
OE地形吸引2:
  元素0保存父母瓷砖的标高值;元素1-3目前未使用.

共享图像层

有时,您希望一次访问多个图像层。例如,您可能有一个掩蔽层,以指示土地和水。你可能真的不想这一层,但您想要使用它来调整另一个可见层。

你可以用共享图像层。在Map,将图像层标记为共享(使用ImageLayerOptions::shared()),渲染器将提供给第二采样器中的所有其他层。

请参阅osgearth_sharedlayer.cpp作为一个用法示例!

 

[原][译]关于osgEarth::VirtualProgram

原文:https://www.cnblogs.com/lyggqm/p/12836601.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!