liyihongcug 发表于 2020-4-14 10:43:59

RTTPICKEr分析

本帖最后由 liyihongcug 于 2020-4-14 10:45 编辑

RTTPICKEr 使用RTT 相机。
Picks objects using an RTT camera and Vertex Attributes.

说明如何操作
/**
         * Starts a pick operation. When the operation completes, invokes the callback
         * with the results. You can use this method if you want to use the picker directly
         * WITHOUT installing it as an EventHandler. If you use it as an EventHandler, you
         * do NOT need to call this method directly; the Picker will call it upon handling
         * a pick event (i.e., when Callback::accept returns true).
         *
         * Returns true if the pick was succesfully queued; false if not.
         */

着色器源码
{
    // SHADERS for the RTT pick camera.

    const char* pickVertexEncode =
      "#version " GLSL_VERSION_STR "\n"

      "#pragma vp_entryPoint oe_pick_encodeObjectID\n"
      "#pragma vp_location   vertex_clip\n"
      
      "uint oe_index_objectid; \n"                        // Vertex stage global containing the Object ID; set in ObjectIndex shader.

      "flat out vec4 oe_pick_encoded_objectid; \n"      // output encoded oid to fragment shader
      "flat out int oe_pick_color_contains_objectid; \n"// whether color already contains oid (written by another RTT camera)

      "void oe_pick_encodeObjectID(inout vec4 vertex) \n"
      "{ \n"
      "    oe_pick_color_contains_objectid = (oe_index_objectid == 1u) ? 1 : 0; \n"
      "    if ( oe_pick_color_contains_objectid == 0 ) \n"
      "    { \n"
      "      float b0 = float((oe_index_objectid & 0xff000000u) >> 24u); \n"
      "      float b1 = float((oe_index_objectid & 0x00ff0000u) >> 16u); \n"
      "      float b2 = float((oe_index_objectid & 0x0000ff00u) >> 8u ); \n"
      "      float b3 = float((oe_index_objectid & 0x000000ffu)       ); \n"
      "      oe_pick_encoded_objectid = vec4(b0, b1, b2, b3) / 255.0; \n"
      "    } \n"
      "} \n";

    const char* pickFragment =
      "#version " GLSL_VERSION_STR "\n"

      "#pragma vp_entryPoint oe_pick_renderEncodedObjectID\n"
      "#pragma vp_location   fragment_output\n"
      "#pragma vp_order      last\n"

      "flat in vec4 oe_pick_encoded_objectid; \n"
      "flat in int oe_pick_color_contains_objectid; \n"
      
      "out vec4 fragColor; \n"

      "void oe_pick_renderEncodedObjectID(inout vec4 color) \n"
      "{ \n"
      "    if ( oe_pick_color_contains_objectid == 1 ) \n"
      "      fragColor = color; \n"
      "    else \n"
      "      fragColor = oe_pick_encoded_objectid; \n"
      "} \n";
}


VirtualProgram*
RTTPicker::createRTTProgram()
{   
    VirtualProgram* vp = new VirtualProgram();
    vp->setName( "osgEarth::RTTPicker" );

    // Install RTT picker shaders:
    ShaderPackage pickShaders;
    pickShaders.add( "RTTPicker.vert.glsl", pickVertexEncode );
    pickShaders.add( "RTTPicker.frag.glsl", pickFragment );
    pickShaders.loadAll( vp );

    // Install shaders and bindings from the ObjectIndex:
    Registry::objectIndex()->loadShaders( vp );

    return vp;
}

RTTPicker::RTTPicker(int cameraSize)
{
    // group that will hold RTT children for all cameras
    _group = new osg::Group();

    // Size of the RTT camera image
    _rttSize = std::max(cameraSize, 4);   

    // pixels around the click to test
    _buffer = 2;
}

RTTPicker::~RTTPicker()
{
    // remove the RTT camera from all views
    for(int i=0; i<_pickContexts.size(); ++i)
    {
      PickContext& pc = _pickContexts;
      while( pc._pickCamera->getNumParents() > 0 )
      {
            pc._pickCamera->getParent(0)->removeChild( pc._pickCamera.get() );
      }
    }
}
osgEarth::VirtualProgram在apply时用到了osg::Program,也就是VirtualProgram最终是要通过osg::Program实现着色器功能,只不过VirtualProgram中还封装了一些其他内容(比如继承、抽象属性,着色器代码管理等),方便使用而已。
页: [1]
查看完整版本: RTTPICKEr分析