在openscenegraph中执行计算机着色器后读取着色器存储缓冲区对象数据

时间:2016-05-12 03:59:18

标签: openscenegraph

我正在尝试在执行计算着色器后从着色器存储缓冲区对象读回数据,一个简单的浮点数组。我需要将这些数据放入运行osg库的应用程序代码中。在osgssbo示例之后,我设置了着色器存储缓冲区对象回调,但是当我读取数据时,数组元素的初始值不变。 Ssbo和着色器看起来很好并且正确执行。 感谢

这是我的基本代码:

#include <osgViewer/Viewer>
#include <osg/BufferIndexBinding>
#include <osgGA/TrackballManipulator>
#include <osg/GLExtensions>
using namespace osg;


class ShaderStorageBufferCBK : public osg::StateAttributeCallback
{
public:
    void operator() (osg::StateAttribute* attr, osg::NodeVisitor* nv)
    {
        //if you need to process the data in your app-code , better leaving it on GPU and processing there, uploading per frame will make it slow

        osg::ShaderStorageBufferBinding* ssbb = static_cast<osg::ShaderStorageBufferBinding*>(attr);
        osg::ShaderStorageBufferObject* ssbo
            = static_cast<osg::ShaderStorageBufferObject*>(ssbb->getBufferObject());

        osg::FloatArray* array = static_cast<osg::FloatArray*>(ssbo->getBufferData(0));

        for (int i = 0; i < array->size(); ++i){
            osg::notify(INFO) << array->at(i) << " ";
        }
        osg::notify(INFO) << std::endl;

    }
};


int mymain(){

    FloatArray * dati = new FloatArray;
    dati->push_back(1.2);
    dati->push_back(1.2);
    dati->push_back(1.2);
    dati->push_back(1.2);

    ShaderStorageBufferObject *ssbo = new osg::ShaderStorageBufferObject;
    dati->setBufferObject(ssbo);

    ShaderStorageBufferBinding * ssbb = new ShaderStorageBufferBinding(0, ssbo, 0, dati->size() * sizeof(GLfloat));
    ssbb->setUpdateCallback(new ShaderStorageBufferCBK);

    Shader * shader = new osg::Shader(osg::Shader::COMPUTE);
    shader->loadShaderSourceFromFile("shaders/lightpixels.cs");
    osg::ref_ptr<osg::Program> computeProg = new osg::Program;
    computeProg->setComputeGroups(1, 1, 1);
    shader->setType(Shader::COMPUTE);
    computeProg->addShader(shader);

    osg::Geometry * geom = createTexturedQuadGeometry(Vec3(-0.5, 0, -0.5), Vec3(1.0, 0, 0.0), Vec3(0, 0, 1.0));
    geom->getOrCreateStateSet()->setAttributeAndModes(computeProg);
    geom->getOrCreateStateSet()->setAttributeAndModes(ssbb, osg::StateAttribute::ON);

    osgViewer::Viewer viewer;
    viewer.setSceneData(geom);
    viewer.setUpViewInWindow(100, 100, 640, 480);
    viewer.realize();
    viewer.setCameraManipulator(new osgGA::TrackballManipulator());

    while (!viewer.done())
    {
        viewer.frame();
    }


    return 0;

}

琐碎的着色器代码是:

#version 430
layout (local_size_x = 1) in;

layout(std430, binding = 0) buffer destBuffer
{
      float data[];
};

void main() {
    data[0] = 348.0;
    data[2] = 23.0;
}

回调函数写的输出是:

1.2 1.2 1.2 1.2 

当我希望看到:

348 1.2 23 1.2

1 个答案:

答案 0 :(得分:0)

您可以使用osg GLExtensions来读取缓冲区数据,您可以阅读AtomicCounterBufferBinding::readData函数以供参考。