Rogus
Posts: 12
Joined: Fri Nov 06, 2015 9:41 pm
Location: Warsaw, Poland

[SOLVED] alternative to vgClear

Sun Feb 26, 2017 1:04 pm

Hi everybody

can anyone show an alternative to vgClear when it comes to removing drawn objects from the screen? vgClear is great as long as the drawn objects are not rotated about a certain point. As soon as I rotate something the clearing rectangle should also be rotated, but with vgClear that's not the case. I tried using masking and VG_CLEAR_MASK but the docs for masking are not that descriptive and I couldn't get it to work...

What I'm trying to do: I have a circle (let's say with radius 300) and a small rectangle (width 60 height 10) going around the circle. The rectangle changes its position according to some input data. The problem is that the rectangle is rotated about the center of the circle so it moves on the circumference. With every rotation I have to remove the old rectangle and draw a new one, so the idea is to clear the rectangle with a mask rotated be the old angle and draw a new rectangle with a new angle. Since vgClear doesn't rotate the clearing area it keeps clearing only the rectangle at the top, nothing else. I cannot increase the clearing area since this will remove other data from the screen (and redrawing that data will make it blink).

If someone could show an example of removing an object in such a way that the removing rectangle is approximately the size of the object (e.g. surrounding a circle) and can be rotated just like the object with the same rotation that would be great :)
Last edited by Rogus on Wed Mar 01, 2017 6:47 am, edited 1 time in total.

User avatar
Paeryn
Posts: 1950
Joined: Wed Nov 23, 2011 1:10 am
Location: Sheffield, England

Re: alternative to vgClear

Sun Feb 26, 2017 5:53 pm

You could always just over-draw the rectangle with a rectangle of the clearing colour, though you'd probably have to modify it slightly to counter artefacts left by anti-aliasing which could end up partially erasing anything directly adjacent.

Why does re-drawing make things blink? The OpenVG window should be double buffered and so as long as what you re-draw is the same there shouldn't be any blinking when clearing and redrawing (as long as you don't call eglSwapBuffers() inbetween).

Just thought, you could always make a copy of the area where the rectangle will be drawn to and copy it back to "erase" it. Not very elegant or optimised but at a push (reading from the display surface isn't the best thing to do often as it can seriously harm framerates)...

Code: Select all

    // Create a simple rectangle that we will draw and erase
    VGPath rect;
    rect = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F,
              1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL);
    vguRect(rect, 0, 0, 50, 50);

    // Move and rotate coordinates to where we will draw it
    vgTranslate(50, 50);
    vgRotate(45);

    // Get bounding box of the rectangle in screen coordinates
    VGfloat x, y, w, h;
    vgPathTransformedBounds(rect, &x, &y, &w, &h);
    printf("bounds = %f,%f x %f,%f\n", x, y, w, h);

    // bounding box slightly enlarged to counter any anti-aliasing bleeding into neighbouring pixels
    VGint bx = (int)x-1;
    VGint by= (int)y-1;
    VGint bw = (int)w+2;
    VGint bh = (int)h+2;
    VGImage background;
    background = vgCreateImage(VG_sRGBA_8888, bw, bh,
            VG_IMAGE_QUALITY_NONANTIALIASED);
    // Grab a copy of the area underneath where we will draw to
    vgGetPixels(background, 0, 0, bx, by, bw, bh);

    // Draw rectangle
    vgDrawPath(rect, VG_STROKE_PATH | VG_FILL_PATH);

    // Do whatever you want else here...

    // Restore area where the rectangle was drawn to
    vgSetPixels(bx, by, background, 0, 0, bw, bh);
    vgDestroyImage(background);
She who travels light — forgot something.

Rogus
Posts: 12
Joined: Fri Nov 06, 2015 9:41 pm
Location: Warsaw, Poland

Re: alternative to vgClear

Mon Feb 27, 2017 3:09 pm

Thanks for a descriptive answer :)

The problem with using the clear colour is that I use the default of all zeros, so when I set the colour to all zeros nothing gets drawn (or a transparent rectangle on my already drawn rectangle).

As for the blinking it's "part of the design" due to layer switching. When I draw a circle on one layer I call a function to switch to another layer (on which the rectangle is drawn) and in that function I have buffer swapping. Might have to rethink that feature.

Would making a clear mask using vgMask somehow solve the problem? Unfortunately I'm not familiar with using masks in OpenVG and I'm afraid it might work the same way as setting all zeros to the fill colour and then drawing something :( I'll keep trying different combinations to see if it works.

User avatar
Paeryn
Posts: 1950
Joined: Wed Nov 23, 2011 1:10 am
Location: Sheffield, England

Re: alternative to vgClear

Mon Feb 27, 2017 3:57 pm

When you say you set the colour to all zeros do you include the alpha value in that, in which case yes you are drawing totally transparent paths, you need to keep the alpha at 1.0 otherwise you draw translucently.

What do you mean by layers, do you have separate OpenVG windows? OpenVG only has one layer (well, there's the mask layer but that's different).

The mask layer is like drawing with a stencil over the top of the window. Values of 0.0 are the solid parts of the stencil and values of 1.0 are the holes in the stencil (and values in-between allow partial drawing, allows you to have soft edges rather than strict all-or-nothing). When used any pixels to draw will have their coverage values multiplied by the coverage value in the mask layer at that location first, so for pixels where the mask is 0.0 nothing will get drawn to that pixel and where the mask is 1.0 the pixel will be drawn as normal.
She who travels light — forgot something.

Rogus
Posts: 12
Joined: Fri Nov 06, 2015 9:41 pm
Location: Warsaw, Poland

Re: alternative to vgClear

Tue Feb 28, 2017 3:32 pm

When you say you set the colour to all zeros do you include the alpha value in that
Yes. The problem is that when I change the alpha channel to 1.0 then the region is just black, but I want it to be transparent as with vgClear.
What do you mean by layers, do you have separate OpenVG windows?
Yes, sorry for the confusion. I'm using eglMakeCurrent to switch between window surfaces created with eglMakeWindowSurface. This is why it is important for me to erase the object in such a way that the region which it covers becomes transparent. Thanks to that I can e.g. draw a rectangle on one window and text on a window "above" it (to create a button), and when that rectangle is pressed I can change its colour without affecting the text. That was the main idea.
The mask layer is like drawing with a stencil over the top of the window. Values of 0.0 are the solid parts of the stencil and values of 1.0 are the holes in the stencil (and values in-between allow partial drawing, allows you to have soft edges rather than strict all-or-nothing). When used any pixels to draw will have their coverage values multiplied by the coverage value in the mask layer at that location first, so for pixels where the mask is 0.0 nothing will get drawn to that pixel and where the mask is 1.0 the pixel will be drawn as normal.
So that means that the clear mask is just a stencil with no "holes". When I try to draw over the clear mask nothing is affected. So its purpose is not to clear the area on the screen but to "defend" the area on the screen to prevent drawing on it. That's a shame :(

I'm guessing that vgClear is not affected by any masks - e.g. if I use a mask with "ones" on the circumference of my circle and "zeros" everywhere else so that I don't remove anything inside the cicle (which is on the same window as the rectangle) it wouldn't work, vgClear would erase the whole area anyway, right?

User avatar
Paeryn
Posts: 1950
Joined: Wed Nov 23, 2011 1:10 am
Location: Sheffield, England

Re: alternative to vgClear

Tue Feb 28, 2017 5:01 pm

Rogus wrote:
Paeryn wrote:When you say you set the colour to all zeros do you include the alpha value in that
Yes. The problem is that when I change the alpha channel to 1.0 then the region is just black, but I want it to be transparent as with vgClear.
You could try changing the blend mode before drawing your totally transparent rectangle so that the destination alpha value is ignored (so it should replace it with the new 0 alpha)

Code: Select all

  VGPaint black_with_full_alpha = vgCreatePaint();
  VGPaint black_with_no_alpha = vgCreatePaint();
  vgSetColor(black_with_full_alpha, 0x000000ff);
  vgSetColor(black_with_no_alpha, 0x00000000);

  // Draw rectangle in black with full alpha to clear the colour channels
  vgSetPaint(black_with_full_alpha, VG_FILL_PATH);
  vgDrawPath(your_rectangle_path, VG_FILL_PATH);

  vgSeti(VG_BLEND_MODE, VG_BLEND_SRC); // Blend mode overwriting

  // Draw again but with alpha set to 0, hopefully the destination alpha should be overwritten by this
  vgSetPaint(black_with_no_alpha, VG_FILL_PATH);
  vgDrawPath(your_rectangle_path, VG_FILL_PATH);

  vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER); // Put the default blend mode back
  vgDestroyPaint(black_with_full_alpha);
  vgDestroyPaint(black_with_no_alpha);
Thinking about it, the first part (drawing black with full alpha) might not be needed as writing with alpha set to 0 should set the colour channels to 0 too.
Rogus wrote:
Paeryn wrote:The mask layer is like drawing with a stencil over the top of the window. Values of 0.0 are the solid parts of the stencil and values of 1.0 are the holes in the stencil (and values in-between allow partial drawing, allows you to have soft edges rather than strict all-or-nothing). When used any pixels to draw will have their coverage values multiplied by the coverage value in the mask layer at that location first, so for pixels where the mask is 0.0 nothing will get drawn to that pixel and where the mask is 1.0 the pixel will be drawn as normal.
So that means that the clear mask is just a stencil with no "holes". When I try to draw over the clear mask nothing is affected. So its purpose is not to clear the area on the screen but to "defend" the area on the screen to prevent drawing on it. That's a shame :(

I'm guessing that vgClear is not affected by any masks - e.g. if I use a mask with "ones" on the circumference of my circle and "zeros" everywhere else so that I don't remove anything inside the cicle (which is on the same window as the rectangle) it wouldn't work, vgClear would erase the whole area anyway, right?
The mask layer is exactly what it says it is, it's a mask for the drawing operations.
vgClear() ignores the mask layer but it does honour the clipping rectangles. It's meant as a fast way of clearing the window (and applying the mask would slow it down).
She who travels light — forgot something.

Rogus
Posts: 12
Joined: Fri Nov 06, 2015 9:41 pm
Location: Warsaw, Poland

[SOLVED] alternative to vgClear

Tue Feb 28, 2017 9:44 pm

Paeryn wrote: You could try changing the blend mode before drawing your totally transparent rectangle so that the destination alpha value is ignored (so it should replace it with the new 0 alpha)

Code: Select all

  VGPaint black_with_full_alpha = vgCreatePaint();
  VGPaint black_with_no_alpha = vgCreatePaint();
  vgSetColor(black_with_full_alpha, 0x000000ff);
  vgSetColor(black_with_no_alpha, 0x00000000);

  // Draw rectangle in black with full alpha to clear the colour channels
  vgSetPaint(black_with_full_alpha, VG_FILL_PATH);
  vgDrawPath(your_rectangle_path, VG_FILL_PATH);

  vgSeti(VG_BLEND_MODE, VG_BLEND_SRC); // Blend mode overwriting

  // Draw again but with alpha set to 0, hopefully the destination alpha should be overwritten by this
  vgSetPaint(black_with_no_alpha, VG_FILL_PATH);
  vgDrawPath(your_rectangle_path, VG_FILL_PATH);

  vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER); // Put the default blend mode back
  vgDestroyPaint(black_with_full_alpha);
  vgDestroyPaint(black_with_no_alpha);
That worked! Thank you so much for your help :) Like you mentioned in your first reply, some artefacts remain probably due to anti-aliasing. I added stroke and it fixed the issue.
Paeryn wrote: Thinking about it, the first part (drawing black with full alpha) might not be needed as writing with alpha set to 0 should set the colour channels to 0 too.
Removing the full alpha part worked too, so the additional drawing is not necessary. The final code might look like the following:

Code: Select all

  VGPaint black_with_no_alpha = vgCreatePaint();
  vgSetColor(black_with_no_alpha, 0x00000000);
  // Increasing the stroke width to make sure everything gets removed from the screen
  vgSetf(VG_STROKE_LINE_WIDTH, 2.0f);

  vgSeti(VG_BLEND_MODE, VG_BLEND_SRC); // Blend mode overwriting

  // Draw rectangle with alpha set to 0, the destination alpha gets overwritten by this
  vgSetPaint(black_with_no_alpha, VG_FILL_PATH | VG_STROKE_PATH);
  vgDrawPath(your_rectangle_path, VG_FILL_PATH | VG_STROKE_PATH);

  vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER); // Put the default blend mode back
  vgSetf(VG_STROKE_LINE_WIDTH, 1.0f); // Put the default stroke width back
  vgDestroyPaint(black_with_no_alpha);
Marking as solved. Thanks again for your help :)

[edit] wanted to mark as solved, but probably an admin can only change the topic

User avatar
Paeryn
Posts: 1950
Joined: Wed Nov 23, 2011 1:10 am
Location: Sheffield, England

Re: [SOLVED] alternative to vgClear

Tue Feb 28, 2017 10:05 pm

Rogus wrote:That worked! Thank you so much for your help :) Like you mentioned in your first reply, some artefacts remain probably due to anti-aliasing. I added stroke and it fixed the issue.
Paeryn wrote: Thinking about it, the first part (drawing black with full alpha) might not be needed as writing with alpha set to 0 should set the colour channels to 0 too.
Removing the full alpha part worked too, so the additional drawing is not necessary.
Marking as solved. Thanks again for your help :)

[edit] wanted to mark as solved, but probably an admin can only change the topic
I thought it might not need the explicit drawing black after I wrote out the fuller version. I was initially thinking having the source alpha as zero wouldn't draw, but that is only under the normal blending mode. I didn't have time to check if it worked or not, glad you've got it sorted.

As to marking the thread solved, you should be able to edit the initial post and change the subject there, I think that the forum uses the subject of the first post when listing threads.
She who travels light — forgot something.

Return to “OpenVG”

Who is online

Users browsing this forum: No registered users and 1 guest