zoukankan      html  css  js  c++  java
  • [原][译]关于osgEarth::VirtualProgram说明

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

    cpp中的说明:

      VirtualProgram支持在osgEarth中进行GLSL着色器合成。 它会在运行时自动将着色器功能组装为完整的着色器程序。 您可以随时添加或删除功能(注入点)。
      VirtualProgram(VP)是osg :: StateAttribute。 但是与大多数属性不同,VP将继承状态堆栈中其他VP的属性。
      VirtualProgram最初是由Wojciech Lewandowski完成的VirtualProgram着色器合成工作改编而成,在OSG的osgvirtualprogram示例中可以看到。

    Shader Composition

    着色器的合成系统

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

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

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

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

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

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

    Framework Basics(基础框架介绍)

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

    下面,我们看看osgEarth创建的main()的伪代码:

    注意: LOCATION_XXXXX 是表示可以在着色器的执行管道中的哪个点插入我们自定义的函数。

    // 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;
    }

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

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

    VirtualProgram

    可编程着色器

    osgEarth引入了一个新的osg状态属性,名为VirtualProgram的运行时着色器合成器。因为VirtualProgramosg::StateAttribute,你可以将其附加到场景图中的任何节点上。

    使用VirtualProgram的着色器可以在场景树中作为一个更高层次的渲染存在。

    通过这种方式,你可以在osgEarth中添加、组合、重写每个着色器函数。

    在运行时,VirtualProgram将查看当前状态并组装一个完整的osg::Program,它使用内置main(),调用VirtualProgram注入所有着色器功能。

     

    Adding Functions

    添加函数方案:

    从我们前面看到的生成主管道中,osgEarth会调用用户自定义函数。

    这些自定义函数不在osgEarth默认生成的着色器中,但可以作为着色器代码“注入”到管道中各个位置。

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

    // haze_vertex:   将放在顶点着色器的view部分
    out vec3 v_pos;
    void setup_haze(inout vec4 vertexView)
    {
        v_pos = vertexView.xyz;
    }
    
    // haze_fragment:  将放在片元着色器的lighting部分 
    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++:       oe中加入这两个函数,将两个着色器函数放入正确位置
    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()调用。

    目前OE有六个可插入点,如下:

    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)

    每个VERTEX定位都可让您在特定坐标空间中的顶点上进行操作。 您可以更改顶点,但必须将其放在相同的空间中。

    顶点定位如下:

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

    片元定位如下:

    COLORING 着色: 在应用照明之前,解析片段颜色时调用这里的函数。纹理或颜色调整通常发生在这一阶段。
    LIGHTING 照明: 这里的功能影响到片元中的光照等算法。例如计算:太阳照明、凹凸贴图或法线贴图等。
    OUTPUT 输出: 这里是设置gl_FragColor的地方。默认情况下,内置片段main()将设置它。但是你可以设置一个输出着色器来替换这种方式。这样做的一个典型例子是实现MRT渲染(请参阅osgEarth_mrt示例)。

     

    Shader Packages

    更多着色器函数库

    Shader组合框架还提供了一个ShaderPackage支持更高级的着色器管理方法:

    VirtualProgram Metadata

    可编程着色器的元数据

    正如我们所看到的,当您向管道中添加一个着色器函数时,可以使用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,添加您的代码,并在VirtualProgram中调用Load即可

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

    它采用“文件名”,因为着色器可以在外部文件中调用。

    这个vp_location取值如下:

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

     

    External GLSL Files

    外部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文件,或者将它们保持在内联状态--无论哪种方式,应用程序仍然可以工作。

     

    Include Files

    引用文件

    这个ShaderPackage如果引用其他文件:你的GLSL代码只要引用其他文件名就可以调用里面的函数。若要包含其他文件,需要使用自定义#pragma,请执行以下操作:

    #pragma include myCode.vertex.glsl

    就像在C++中一样,include引用将直接内联加载其他文件(或源代码)。因此,你所引用的文件必须是结构化的。

    再次提醒:引用的内容与引用文件必须用同一个 ShaderPackage.


    Concepts Specific to osgEarth

    特定于osgEarth的可编程着色器概念

    尽管可编程着色器框架包含在osgEarth SDK中,但它实际上与地图渲染无关。

    下面,我们将介绍osgEarth对着色器组合所做的一些特别的操作。

    Terrain Variables

    地形变量

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

    重要提醒:以前缀   “ OE_ ”  或者  “ osgEarth_ ”  开头的着色变量请保留给 osgEarth 内部使用。

    Uniforms:

    oe_tile_key:

    (vec4) elements 0-2 hold the x, y, and LOD tile key values; element 3 holds the tile’s bounding sphere radius (in meters)

    前三个元素包含x、y和LOD的瓦片键值;第四个元素 保存瓦片的包围盒半径(以米为单位)。

    oe_layer_tex:

    (sampler2D) texture applied to the current layer of the current tile

    纹理,适用于当前瓦片的当前层

    oe_layer_texc:

    (vec4) texture coordinates for current tile

    当前瓦片的纹理坐标

    oe_layer_tilec:

    (vec4) unit coordinates for the current tile (0..1 in x and y)

    当前瓦片的单位坐标(x和y中的0..1)

    oe_layer_uid:

    (int) Unique ID of the active layer

    活动层的唯一ID

    oe_layer_order:

    (int) Render order of the active layer

    活动层的渲染顺序

     oe_layer_opacity:

    (float) Opacity [0..1] of the active layer

    活动层的不透明度[0到1]

    Vertex attributes:

    oe_terrain_attr:
     

    (vec4) elements 0-2 hold the unit height vector for a terrain vertex, and element 3 holds the raw terrain elevation value

    前三个元素为地形顶点的单位高度向量,最后一个元素为原始地形海拔值。

    oe_terrain_attr2:
     

    (vec4) element 0 holds the parent tile’s elevation value; elements 1-3 are currently unused.

    第一个元素为父级瓷砖的高程值;后三个元素目前未使用.

    Shared Image Layers

    共享图像层

    如果你希望一次访问多个图像层。比如:你可能需要一个掩蔽层,以显示土地和水。你可能真的不想绘制这一层,但您想要使用它来调整其他可见层。你可以用 共享图像层。在Map,将图像层标记为共享 (using ImageLayerOptions::shared(),渲染器会将其提供给所有其他层进行二采样。

    详情参阅  osgearth_sharedlayer.cpp 的用法示例!

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////以上是官方文档原内容的翻译,下面介绍下目前的OE部分

    OE目前支持了几何着色器

    // User function injection points.插入点位置:
            enum FunctionLocation
            {
                // vertex is in model space (equivalent to gl_Vertex).模型空间
                LOCATION_VERTEX_MODEL,
    
                // vertex is in view(aka eye) coordinates, with the camera at 0,0,0 视口空间
                // looking down the -Z axis.
                LOCATION_VERTEX_VIEW,
    
                // vertex is in post-perspective coordinates; [-w..w] along each axis裁剪空间
                LOCATION_VERTEX_CLIP,
    
                // tessellation control shader; model space
                LOCATION_TESS_CONTROL,
    
                // tessellation evalulation shader; model space
                LOCATION_TESS_EVALUATION,
    
                // geometry shader; inputs are in model space.
                LOCATION_GEOMETRY,
    
                // fragment is being colored.
                LOCATION_FRAGMENT_COLORING,
    
                // fragment is being lit.
                LOCATION_FRAGMENT_LIGHTING,
    
                // fragment output is being assigned.
                LOCATION_FRAGMENT_OUTPUT,
    
                // not defined.
                LOCATION_UNDEFINED
            };
  • 相关阅读:
    OGRE源代码resource分析
    全排列
    各种让人无语的库
    python Kmeans算法
    Linux服务器安装MariaDB数据库
    初探SEO,BSP收录速度测试
    MetaWeblog API调用
    Patterns
    腾讯。。。对Linux的支持程度直接扼杀了Linux在国内用户群的增长
    个人电子商务网站建设之——整站静态化实现的选择、设计与实现(二):静态页面的实现方式;
  • 原文地址:https://www.cnblogs.com/lyggqm/p/12836601.html
Copyright © 2011-2022 走看看