rujialiu
Topic Author
Posts: 4
Joined: 07 Apr 2017, 11:06

How to Render a canvas to a high-resolution texture?

07 Apr 2017, 11:17

Hi!

One of our GUI draws vector graphics on a canvas. We want to provde an "export to file" functionality to the user, is there an easy way to do it? Note that the exported texture usually have much higher resolution for printing, so I can't just dump the content of the current render window.

In WPF we can create a RenderTargetBitmap rtb and use rtb.Render(canvas) to render the canvas into the bitmap and save it to file, but in Noesis GUI I can't find a similar way to do it. Do I need to implement it on my own? If so, can anyone show me (roughly) how to do it?

BTW: I'm using Noesis GUI 2.0 and the functionality only needs to support D3D11.

Thanks!
 
nokola
Posts: 186
Joined: 10 Mar 2015, 05:29

Re: How to Render a canvas to a high-resolution texture?

07 Apr 2017, 17:37

I've managed to get high-res (8K, iPhone/iPad retina) screenshots from Unity Editor, see here: viewtopic.php?f=3&t=1048
Had to do a couple workarounds. In the code in the above post, I have some commented out code that renders to texture.
Unfortunately the render-to-texture commented out code crashes. I'm going to play with it and report a bug if I can't get it to work.
If you manage to get it to work please let us know!
 
User avatar
jsantos
Site Admin
Posts: 2563
Joined: 20 Jan 2012, 17:18
Contact:

Re: How to Render a canvas to a high-resolution texture?

07 Apr 2017, 23:34

You could also have a look at NoesisXamlEditor.cs where we have all the code to generate previews and thumbnail. That code is rendering UI into textures.
 
nokola
Posts: 186
Joined: 10 Mar 2015, 05:29

Re: How to Render a canvas to a high-resolution texture?

08 Apr 2017, 03:30

Thanks for the info!
 
rujialiu
Topic Author
Posts: 4
Joined: 07 Apr 2017, 11:06

Re: How to Render a canvas to a high-resolution texture?

09 Apr 2017, 10:30

You could also have a look at NoesisXamlEditor.cs where we have all the code to generate previews and thumbnail. That code is rendering UI into textures.
Thanks, but I don't use Unity. I use Ogre with C++, so it should be quite different (and sorry, I didn't even find NoesisXamlEditor.cs in the SDK)

I managed to make screen capture working as follows:
void renderToTargetDX11(FrameworkElement* element, ID3D11RenderTargetView* rt) {
    if(rt) g_pImmediateContext->OMSetRenderTargets(1, &rt, g_pDepthStencilView);
    if (element != NULL){
        IView* view = element->GetView();
        view->GetRenderer()->Render();
    }
}

void captureScreen(Noesis::Gui::FrameworkElement* element) {

...

    ID3D11Texture2D* rtt_d3d;
    ID3D11RenderTargetView* renderTargetView;

    // get rtt_d3d/renderTargetView with Ogre, code omitted

    renderToTargetDX11(element, renderTargetView);

    // write rtt_d3d to a file, code omitted

}
However, if I resize the canvas to a higher resolution and render, the saved file will be partially black. I'm doing the following:
    int paperWidth = 3507; // 300 dpi A4 paper
    int paperHeight = 2480;

    Noesis::Gui::FrameworkElement* element = static_cast<Noesis::Gui::FrameworkElement*>(canvas);

    if (element != NULL){
        canvas->setWidth(paperWidth);
        canvas->setHeight(paperHeight);
        // and clear canvas's children and recreate new ones, code ommited
 

        Noesis::IView* view = element->GetView();
        view->Update(0);
        view->GetRenderer()->UpdateRenderTree();
        if (view->GetRenderer()->NeedsOffscreen()) {
            view->GetRenderer()->RenderOffscreen(); // didn't arrive here, though
        }
    }     

    ID3D11Texture2D* rtt_d3d;
    ID3D11RenderTargetView* renderTargetView;

    // get rtt_d3d/renderTargetView with Ogre, code omitted

    renderToTargetDX11(element, renderTargetView);

    // write rtt_d3d to a file, code omitted
 

    // restore canvas
    canvas->setWidth(backupWidth);
    canvas->setHeight(backupHeight);
Suppose my window is 800x600, then I got a 3507x2480 jpg file in which the canvas only occupies the top-left 800x600 pixel region. Other parts of the image are black.

I also tried some other things:
view->SetSize(paperWidth, paperHeight); // doesn't work, have STRANGE effect

element->UpdateLayout(); // nothing's different

view->GetRenderer()->SetRenderRegion(0, 0, paperWidth, paperHeight);// doesn'twork for large area, but works if paperWidth/paperHeight are smaller than the main window

Am I missing something? Does Noesis somehow limits the render region to the main window?
 
Ziriax
Posts: 60
Joined: 10 Dec 2015, 17:59
Location: Belgium
Contact:

Re: How to Render a canvas to a high-resolution texture?

09 Apr 2017, 12:57

Does it work when you resize to a lower resolution?
Peter Verswyvelen,
Strongly Typed Solutions
 
rujialiu
Topic Author
Posts: 4
Joined: 07 Apr 2017, 11:06

Re: How to Render a canvas to a high-resolution texture?

10 Apr 2017, 15:57

Does it work when you resize to a lower resolution?
Good question! Unfortunately, no (I didn't try until you asked this). Now I feels that I'm misunderstanding something (I'm a novice). Now I'm doing this:
    // first, create a BRAND NEW canvas, set the widht/height to paperWidth and paperHeight, draw everything in (0-paperWidth-1) x (0-paperHeight-)
    Noesis::Ptr<Noesis::IView> view = Noesis::GUI::CreateView(canvas);
    view->GetRenderer()->Init(g_context.GetPtr());
    view->SetSize(paperWidth, paperHeight);
    view->Update(0);
    view->GetRenderer()->UpdateRenderTree();
    if (view->GetRenderer()->NeedsOffscreen()) {
        view->GetRenderer()->RenderOffscreen();
    }
    
    // create Texture/RenderTargetView with Ogre, as before
    renderToTargetDX11(canvas, renderTargetView);
    // dump the content of the texture to file, with Ogre
Now that when paperWidth/paperHeight is bigger than the current screen size, only the top-left corner are drawed, but it's not "cropped", it's scaled instead; If paperWidth/paperHeight is smaller, the result looks like the canvas is "centered" in the screen, and then only the top-left corner is rendered, so it looks "cropped" instead of scaled.

I'm quite confused. Any suggestion would be welcome. Thanks!
 
User avatar
sfernandez
Site Admin
Posts: 1628
Joined: 22 Dec 2011, 19:20

Re: How to Render a canvas to a high-resolution texture?

11 Apr 2017, 16:49

In C++ you should be able to render to a high-res texture by doing the following:
noesisView->SetSize(bigWidth, bigHeight);
noesisView->Update(currentTimeInSecs);

Noesis::IRenderer* noesisRenderer = view->GetRenderer();
noesisRenderer->UpdateRenderTree();
if (noesisRenderer->NeedsOffscreen())
  noesisRenderer->RenderOffscreen();

// Set texture render target
// Set render target viewport
// Clear render target
// Render other parts of the scene

noesisRenderer->Render();

// Copy texture content to a file
// Restore noesisView size
It shouldn't be necessary to create a new Noesis::IView to do the screenshot.
 
rujialiu
Topic Author
Posts: 4
Joined: 07 Apr 2017, 11:06

Re: How to Render a canvas to a high-resolution texture?

20 Apr 2017, 05:09

We've finally fixed the problem. All the methods posted here (including my own) are conceptually correct, but when it comes to implementation details, the real problem is that we forgot to call RSSetViewports() after changing render target, so D3D11 is still using the old viewport, thus restricted to the current window size. I'm posting the complete working snippet in case anyone needs it:
void setRenderTargetDX11(ID3D11RenderTargetView* rt) {
    if (rt)
        g_pImmediateContext->OMSetRenderTargets(1, &rt, g_pDepthStencilView);
}
 
void renderToTargetDX11(FrameworkElement* element, ID3D11RenderTargetView* rt) {
    setRenderTargetDX11((ID3D11RenderTargetView*)rt);
    if (element != NULL){
        D3D11_VIEWPORT vp = { 0.0f, 0.0f, (FLOAT)element->GetWidth(), (FLOAT)element->GetHeight(), 0.0f, 1.0f };
        g_pImmediateContext->RSSetViewports(1, &vp); // don't forget this!
 
        IView* view = element->GetView();
        view->GetRenderer()->Render();
    }
}
Thank you all!
 
User avatar
sfernandez
Site Admin
Posts: 1628
Joined: 22 Dec 2011, 19:20

Re: How to Render a canvas to a high-resolution texture?

20 Apr 2017, 18:47

Thanks for sharing ;)

Who is online

Users browsing this forum: No registered users and 5 guests