osg例解析のosgatomiccounter(1)
コードには、まず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);