RenderKit / ospray

An Open, Scalable, Portable, Ray Tracing Based Rendering Engine for High-Fidelity Visualization
http://ospray.org
Apache License 2.0
1.02k stars 186 forks source link

Saving the rendered image using Frame buffer #157

Closed pratikshaandhare closed 7 years ago

pratikshaandhare commented 7 years ago

Hi, I need to save the rendered image of the loaded .obj file from exampleViewerSg.cpp by copying the renderer data to a frame buffer and then saving/writing it as in tutorial.cpp. We are not able to use the below code as we are not using OSPrenderer ospRenderFrame(framebuffer, renderer, OSP_FB_COLOR | OSP_FB_ACCUM); const uint32_t fb = (uint32_t)ospMapFrameBuffer(framebuffer, OSP_FB_COLOR);

Please kindly advise me .

johguenther commented 7 years ago

You can save the current rendering to disk as ospimguiviewer.ppm by pressing "!". Our example viewers use the cpp-wrappers, thus either do

swatinair123 commented 7 years ago

Hi , I am trying to save. write the buffer in ospExampleViewerSg.cpp.I am able to see the .obj file in GuiViewer. But I am unable to save the rendered image in the frame buffer because

ospexampleviewersg

But it shows that mappedFB.size() is zero but bbox.empty() is not true. Can u pls help me in figuring out the issue.

I have added these line to ospExampleViewerSg.cpp after the world node is created.

for (auto file : files) {
        std::string filenew = file;
        FileName fn = filenew;
        auto importerNode_ptr = sg::createNode(fn.name(), "Importer");
            auto &importerNode = *importerNode_ptr;
            importerNode["fileName"].setValue(fn.str());
            //......Changes made for loading the objs ..
            //auto world_ptr= sg::createNode(fn.name(), "World");
            //sg::importOBJ(world_ptr, fn.name());
           /* auto world_ptr = sg::createNode("world", "World");
            auto &world = *world_ptr;
            sg::importOBJ(world_ptr, fn);*/
            world += importerNode_ptr;
            //renderer_ptr->traverse("commit");
    }
        ospray::ImGuiViewerSg window(renderer_ptr, rendererDW);
////...Added ...
        sg::AsyncRenderEngineSg renderEngine(renderer_ptr, rendererDW);
        renderer_ptr->traverse("verify");
        renderer_ptr->traverse("commit");
        auto bbox = renderer_ptr->child("world").bounds();
        if (bbox.empty()) {
            bbox.lower = vec3f(-5, 0, -5);
            bbox.upper = vec3f(5, 10, 5);
        }
        //setWorldBounds(bbox);
        renderEngine.setFbSize({ 1024, 768 });

        renderEngine.start();

          //.....//     
        std::vector<uint32_t> pixelBuffer;
        double lastFrameFPS;
        //if (renderEngine.hasNewFrame()) {
            auto &mappedFB = renderEngine.mapFramebuffer();

            //std::cout  << renderEngine.mapFramebuffer().size();

            size_t nPixels = 1024 * 749;
            std::cout << "size of mapped buffer" << mappedFB.size();
            if (mappedFB.size() == nPixels) {
                auto *srcPixels = mappedFB.data();
                auto *dstPixels = pixelBuffer.data();
                memcpy(dstPixels, srcPixels, nPixels * sizeof(uint32_t));
                lastFrameFPS = renderEngine.lastFrameFps();
                //  renderTime = 1.f / lastFrameFPS;
            }

            renderEngine.unmapFramebuffer();
johguenther commented 7 years ago

Maybe that is because the frame is not finished yet with rendering (which is asynchronous): do not comment-out line 340 but really wait until renderEngine.hasNewFrame().

swatinair123 commented 7 years ago

Hi, As per the above sugestion i have given the sleep () command and now renderEngine.hasNewFrame() is true. But mappedFB.size() is always equal to 90000. Can i change the size_t nPixels t=90000 and change the height to 300 and width to 300 So the condition if (mappedFB.size() == nPixels) is never reached and I am not able to write the buffer . Please kindly advise if there is any mistake.

johguenther commented 7 years ago

If you want to change the resolution of the rendered image you need to create a new framebuffer (with the correct width and height). See the documentation and FrameBuffer.h.

pratikshaandhare commented 7 years ago

Hi , I am using the below code for rendering without the gui part as I want to save the rendered buffer to a ppm file. I tried loading two different objs but always the mappedFB.size()=90000 .Can you please advise me if the code I am using is correct ?

In the GUI I am able to view the obj fully and clearly but when I am saving using writePPM function only the output is saved partially.

sg::AsyncRenderEngineSg renderEngine(renderer_ptr, rendererDW);
        renderer_ptr->traverse("verify");
        renderer_ptr->traverse("commit");
        auto bbox = renderer_ptr->child("world").bounds();
        if (bbox.empty()) {
            bbox.lower = vec3f(-5, 0, -5);
            bbox.upper = vec3f(5, 10, 5);
        }
        //setWorldBounds(bbox);
        renderEngine.setFbSize({ 1024, 768 });

        renderEngine.start();

          //.....//     
        std::vector<uint32_t> pixelBuffer;
        double lastFrameFPS;
        //if (renderEngine.hasNewFrame()) {
            auto &mappedFB = renderEngine.mapFramebuffer();

            //std::cout  << renderEngine.mapFramebuffer().size();

            size_t nPixels =  300*300;
            std::cout << "size of mapped buffer" << mappedFB.size();
            if (mappedFB.size() == nPixels) {
johguenther commented 7 years ago

Did you try the integrated screenshot feature (pressing "!") and un-commenting if (renderEngine.hasNewFrame()) as suggested in previous answers? If you do not need the GUI anyway, then have a look at included the ospBenchmark application, which can already save the rendered image to disk (after a configurable number of accumulated frames).

swatinair123 commented 7 years ago

Hi, yes we had tried uncommenting and we had given a sleep(25).and the condition renderEngine.hasnewframe() was true. The code was modified as

code: Sleep(1000); if (renderEngine_new.hasNewFrame()) {

auto &mappedFB = renderEngine_new.mapFramebuffer(); size_t nPixels = 90000; if (mappedFB.size() == nPixels) { auto srcPixels = mappedFB.data(); auto dstPixels = renderEngine_new.pixelBuffer->data(); memcpy(dstPixels, mappedFB.data(), nPixels * sizeof(uint32_t)); writePPM("Image" + to_string(i) + ".ppm",768 , 1024, dstPixels); }

Here for any obj we load we are getting mappedFB.size() =90000.

We will try the above suggestion.

Thanks a lot.

On 28-Jul-2017 17:02, "Johannes Günther" notifications@github.com wrote:

Did you try the integrated screenshot feature (pressing "!") and un-commenting if (renderEngine.hasNewFrame()) as suggested in previous answers? If you do not need the GUI anyway, then have a look at included the ospBenchmark application, which can already save the rendered image to disk (after a configurable number of accumulated frames).

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/ospray/ospray/issues/157#issuecomment-318629370, or mute the thread https://github.com/notifications/unsubscribe-auth/AWbURFtn909w1qJQ_9TnUXPkb3OBhV7nks5sScavgaJpZM4OcbPu .

swatinair123 commented 7 years ago

Hi, I have tried the suggestions but always mappedFB.size() =90000 for any obj loaded.in ospexampleViewerSg. I am able to save only some part of size 90000 as the image to be saved is 1024*768.Please kindly advise. what could be the possible changes to be made in the above code so that the size of the frame buffer also changes.

johguenther commented 7 years ago

Change the window size / the size of the framebuffer, e.g. ospExampleViewer -win 1024x768 file.obj.