osg例解析のosgatomiccounter(1)

3483 ワード

  • 概要
  • OSgAtomicCounterは主にOpenGL 4.2を用いて導入された新しい拡張GL_をどのように使用するかを示した.ARB_shader_atomic_counters,Atomic Counterの紹介は別のブログの紹介を参考にすることができます:OpenGLバッファオブジェクトのAtomic Counter Object
  • を実現
    コードには、まずosg::Camera::DrawCallbackが定義されています.フレームごとのレンダリングが完了した後、このフレームの合計数を記録します.つまり、Fragment Shaderが何回呼び出されたかを記録します.ShaderのAtomic Counter変数で呼び出された回数を統計します.
            virtual void operator () (osg::RenderInfo& renderInfo) const
            {
                _acbb->readData(*renderInfo.getState(), *_atomicCounterArray);
                unsigned int numPixel = osg::maximum(1u, _atomicCounterArray->front());
    
                if ((renderInfo.getView()->getFrameStamp()->getFrameNumber() % 10) == 0)
                {
                    OSG_INFO << "osgatomiccounter : draw " << numPixel << " pixels." << std::endl;
                }
    
                _invNumPixelUniform->set( 1.0f / static_cast<float>(numPixel) );
            }

    次は2つのShaderのコードで、上記のブログを参照することができます.Shaderは非常に簡単で、主に色成分を通じて各画素を染色します.上記のinvNumPixelと組み合わせて、先に描いた画素の色を薄くすることができます.カウンタが大きくなるにつれて、得られる色もますます濃くなります.
    ResetAtomicCounterの役割は、青色成分のデータを無効にすることです.つまり、青色成分のAtomic Bufferバッファは、画素点の数を記録するだけですが、描画では使用できません.そうしないと、シーンは淡い黄色から黄色ではなく、黒から白にグラデーションされます.つまり、青色値成分を常に0にする
    次はmain関数セクションです.
    オペレータの設定とEventHandlerを追加する部分は簡単ですが、主に説明する部分はAtomic Counter Bufferを設定する場所で、以下の注記を参照してください.
    //      , Shader    
    osg::StateSet * ss = loadedModel->asGeode()->getDrawable(0)->getOrCreateStateSet();
    ss->setAttributeAndModes( createProgram(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED );
    ss = loadedModel->getOrCreateStateSet();
    //             
    osg::ref_ptr<osg::UIntArray> atomicCounterArrayRedAndGreen = new osg::UIntArray;
    atomicCounterArrayRedAndGreen->push_back(0);
    atomicCounterArrayRedAndGreen->push_back(0);
    osg::ref_ptr<osg::UIntArray> atomicCounterArrayBlue = new osg::UIntArray;
    atomicCounterArrayBlue->push_back(0);
    
    //             
    osg::ref_ptr<osg::AtomicCounterBufferObject> acboRedAndGreen = new osg::AtomicCounterBufferObject;
    acboRedAndGreen->setUsage(GL_STREAM_COPY);
    atomicCounterArrayRedAndGreen->setBufferObject(acboRedAndGreen.get());
    
    osg::ref_ptr<osg::AtomicCounterBufferObject> acboBlue = new osg::AtomicCounterBufferObject;
    acboBlue->setUsage(GL_STREAM_COPY);
    atomicCounterArrayBlue->setBufferObject(acboBlue.get());
    
    //            ( Shader layout  bindingpoint  )
    osg::ref_ptr<osg::AtomicCounterBufferBinding> acbbRedAndGreen = new osg::AtomicCounterBufferBinding(0, acboRedAndGreen.get(), 0, sizeof(GLuint)*3);
    ss->setAttributeAndModes(acbbRedAndGreen.get());
    
    osg::ref_ptr<osg::AtomicCounterBufferBinding> acbbBlue = new osg::AtomicCounterBufferBinding(2, acboBlue.get(), 0, sizeof(GLuint));
    ss->setAttributeAndModes(acbbBlue.get());
    
    //          ,       
    acbbRedAndGreen->setUpdateCallback(new ResetAtomicCounter);
    acbbBlue->setUpdateCallback(new ResetAtomicCounter);
    
    //            
    osg::ref_ptr<osg::Uniform> invNumPixelUniform = new osg::Uniform("invNumPixel", 1.0f/(800.0f*600.0f));
    ss->addUniform( invNumPixelUniform.get() );
    
    AdaptNumPixelUniform * drawCallback = new AdaptNumPixelUniform;
    drawCallback->_invNumPixelUniform = invNumPixelUniform;
    drawCallback->_acbb = acbbBlue;
    
    viewer.getCamera()->setFinalDrawCallback(drawCallback);