New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

smooth(), noSmooth() behavior #3357

Closed
benfry opened this Issue Jun 6, 2015 · 12 comments

Comments

Projects
None yet
4 participants
@benfry
Member

benfry commented Jun 6, 2015

Dearest @REAS, @shiffman, and @codeanticode,

I'm working through the smooth() changes described here.

It's a little gross because if it's the primary drawing surface, everything happens in PApplet, but if offscreen, it needs to happen in PGraphics. This means that both need a smooth variable that is set to 0 (no smoothing), 1 (default for the renderer), 2+ (specified by the user, behavior depends on the renderer).

When the primary surface is created, the setting is retrieved from the sketch via sketchSmooth() (in line with sketchWidth() and others, which are now the public accessors for settings like this). When an offscreen surface is created, it's queried the same way, but can be overridden by calling g.noSmooth() (or whichever of the three) before the first beginDraw().

Essentially the behavior is very different, and I feel like it makes the internals a little confusing. Especially because in the past, the PGraphics version was just called by PApplet. But the tradeoff is:

  1. We could change how this works, and add a setSmooth() method (that takes, 0, 1, 2+) to PGraphics to handle the createGraphics() usage. This would make it more apparent that things are a little different.
  2. We could do this as-is, which would be less confusing for people updating their code.
  3. We could add more parameters to createGraphics(), but that seems like a mess. We already have several createGraphics() variants (with/without renderer, with/without filename) and this would multiply things and be awkward:
createGraphics(500, 300, "TiffFileRenderer", "output.tif", NO_SMOOTH);  // this sucks
createGraphics(500, 300, "TiffFileRenderer", "output.tif", "smooth=0");  // this is yuck

I'm moving forward with the second option (fewer changes to the behavior, but makes the internals a little awkward), but was hoping you three could confirm or shoot holes in this (or that I'd figure it out by having to write it out...)

@codeanticode boolean smooth and int quality in PGraphics are being replaced by int smooth, but I'm open to better ideas here.

@processing processing locked and limited conversation to collaborators Jun 6, 2015

@REAS

This comment has been minimized.

Show comment
Hide comment
@REAS

REAS Jun 6, 2015

Member

I think the good news with all scenarios is that if you're not changing the smooth() defaults, the code will remain as it has been since the default change to smooth() with 2.0. I'm working through the rest.

Member

REAS commented Jun 6, 2015

I think the good news with all scenarios is that if you're not changing the smooth() defaults, the code will remain as it has been since the default change to smooth() with 2.0. I'm working through the rest.

@shiffman

This comment has been minimized.

Show comment
Hide comment
@shiffman

shiffman Jun 6, 2015

Member

I am not entirely sure I follow completely. . is the following understanding correct?

This used to be valid:

void setup() {
  size(200, 200);
  PGraphics canvas = createGraphics(200, 200);
  canvas.beginDraw();
  canvas.smooth();  // or noSmooth() or smooth(4)
  canvas.rect(0, 0, 100, 100);
  canvas.endDraw();
  image(canvas, 0, 0);
}

But now it has to be:

void setup() {
  size(200, 200);
  PGraphics canvas = createGraphics(200, 200);
  canvas.smooth();  // any smooth()/noSmooth() stuff now has to be before beginDraw()!
  canvas.beginDraw();
  canvas.rect(0, 0, 100, 100);
  canvas.endDraw();
  image(canvas, 0, 0);
}

But this makes it very awkward for you to implement behind the scenes so you are thinking of changing it?

Or you cannot do any of the options above anymore all b/c you need to know what the smoothing should be the moment createGraphics() is called?

Member

shiffman commented Jun 6, 2015

I am not entirely sure I follow completely. . is the following understanding correct?

This used to be valid:

void setup() {
  size(200, 200);
  PGraphics canvas = createGraphics(200, 200);
  canvas.beginDraw();
  canvas.smooth();  // or noSmooth() or smooth(4)
  canvas.rect(0, 0, 100, 100);
  canvas.endDraw();
  image(canvas, 0, 0);
}

But now it has to be:

void setup() {
  size(200, 200);
  PGraphics canvas = createGraphics(200, 200);
  canvas.smooth();  // any smooth()/noSmooth() stuff now has to be before beginDraw()!
  canvas.beginDraw();
  canvas.rect(0, 0, 100, 100);
  canvas.endDraw();
  image(canvas, 0, 0);
}

But this makes it very awkward for you to implement behind the scenes so you are thinking of changing it?

Or you cannot do any of the options above anymore all b/c you need to know what the smoothing should be the moment createGraphics() is called?

@shiffman

This comment has been minimized.

Show comment
Hide comment
@shiffman

shiffman Jun 6, 2015

Member

Oh oh, sorry I should have clicked through your link where more is explained. I think you are right, to keep as is and now that smooth() is something more of a global thing that cannot be changed through out a sketch it makes sense that createGraphics() would inherit it. If there's some workaround for those who need a different smoothness for PGraphics vs PSurface that might be nice, but I think that's something of an edge case and doesn't need to be featured prominently in the documentation.

Member

shiffman commented Jun 6, 2015

Oh oh, sorry I should have clicked through your link where more is explained. I think you are right, to keep as is and now that smooth() is something more of a global thing that cannot be changed through out a sketch it makes sense that createGraphics() would inherit it. If there's some workaround for those who need a different smoothness for PGraphics vs PSurface that might be nice, but I think that's something of an edge case and doesn't need to be featured prominently in the documentation.

@benfry

This comment has been minimized.

Show comment
Hide comment
@benfry

benfry Jun 6, 2015

Member

Thanks guys... I'll continue in this vein and see how it goes, and let me know if you think of anything in the meantime.

@codeanticode I'm also going to rename the primarySurface variable to primaryGraphics since that's what it is, to avoid confusion because we have something else actually called "surface" in the API now.

Member

benfry commented Jun 6, 2015

Thanks guys... I'll continue in this vein and see how it goes, and let me know if you think of anything in the meantime.

@codeanticode I'm also going to rename the primarySurface variable to primaryGraphics since that's what it is, to avoid confusion because we have something else actually called "surface" in the API now.

@codeanticode

This comment has been minimized.

Show comment
Hide comment
@codeanticode

codeanticode Jun 7, 2015

Member

jumping late into the discussion... @benfry I agree with the direction you are taking, constraining the use of smooth/noSmooth to a single call before beginDraw() seems like a good solution to me.

However, just want to make one observation: the smooth() used to correspond to smooth(2), right? In fact, a quality level of 1 in openGL represents the aliased setting with 1 sample, in other words no smoothing. Should the OpenGL renderer set 2 samples for smooth(1)?

Member

codeanticode commented Jun 7, 2015

jumping late into the discussion... @benfry I agree with the direction you are taking, constraining the use of smooth/noSmooth to a single call before beginDraw() seems like a good solution to me.

However, just want to make one observation: the smooth() used to correspond to smooth(2), right? In fact, a quality level of 1 in openGL represents the aliased setting with 1 sample, in other words no smoothing. Should the OpenGL renderer set 2 samples for smooth(1)?

@benfry

This comment has been minimized.

Show comment
Hide comment
@benfry

benfry Jun 7, 2015

Member

Yes, that's correct, smooth(1) should be the appropriate default for the renderer (equivalent to smooth() with no args)... in Java2D, the default (bicubic) is 4, though you can drop it to 2 (bilinear) if you want. Even though OpenGL technically would see smooth(1) as noSmooth(), that's just too weird to foist on people, so you should override that.

Member

benfry commented Jun 7, 2015

Yes, that's correct, smooth(1) should be the appropriate default for the renderer (equivalent to smooth() with no args)... in Java2D, the default (bicubic) is 4, though you can drop it to 2 (bilinear) if you want. Even though OpenGL technically would see smooth(1) as noSmooth(), that's just too weird to foist on people, so you should override that.

@REAS

This comment has been minimized.

Show comment
Hide comment
@REAS

REAS Jun 7, 2015

Member

Please check this out:
https://beta.processing.org/reference/smooth_.html

I think that I should mention the defaults, to confirm, that's smooth(4) for the default and JAVA2D_2X and smooth(2) for the OpenGL renderers. Or are you saying smooth(1) for OpenGL should be "2X" under the hood?

Member

REAS commented Jun 7, 2015

Please check this out:
https://beta.processing.org/reference/smooth_.html

I think that I should mention the defaults, to confirm, that's smooth(4) for the default and JAVA2D_2X and smooth(2) for the OpenGL renderers. Or are you saying smooth(1) for OpenGL should be "2X" under the hood?

@codeanticode

This comment has been minimized.

Show comment
Hide comment
@codeanticode

codeanticode Jun 7, 2015

Member

Ok, but now the current smooth levels -0, 1, 2, 4, 8- don't make much sense. For example in OpenGL:

0 -> no smooth
1 -> default smoothing (2 samples)
2 -> 4 samples (?)
...

with some hardware supporting up to 16 samples, or even 32. Shouldn't be simply consecutive 0, 1, 2, 3, 4... with the appropriate interpretation depending on the renderer?

Member

codeanticode commented Jun 7, 2015

Ok, but now the current smooth levels -0, 1, 2, 4, 8- don't make much sense. For example in OpenGL:

0 -> no smooth
1 -> default smoothing (2 samples)
2 -> 4 samples (?)
...

with some hardware supporting up to 16 samples, or even 32. Shouldn't be simply consecutive 0, 1, 2, 3, 4... with the appropriate interpretation depending on the renderer?

@benfry

This comment has been minimized.

Show comment
Hide comment
@benfry

benfry Jun 7, 2015

Member

The only smoothing levels that users will see is 2, 4, or 8 (or whatever the renderer uses). 0 and 1 are only used internally.

The numbers are specific to the renderer, so if you want 2 to mean "2x" and 4 to mean "4x", for OpenGL, then great. For Java2D, it's bilinear or bicubic, so those might be 2 and 3. There's no 2x or 4x or 8x, so it has to be renderer-specific, so consecutive levels really don't make any sense. In addition, in Java2D, you can set the smoothing lower than the default, so using consecutive numbers presents a problem there too.

Member

benfry commented Jun 7, 2015

The only smoothing levels that users will see is 2, 4, or 8 (or whatever the renderer uses). 0 and 1 are only used internally.

The numbers are specific to the renderer, so if you want 2 to mean "2x" and 4 to mean "4x", for OpenGL, then great. For Java2D, it's bilinear or bicubic, so those might be 2 and 3. There's no 2x or 4x or 8x, so it has to be renderer-specific, so consecutive levels really don't make any sense. In addition, in Java2D, you can set the smoothing lower than the default, so using consecutive numbers presents a problem there too.

@benfry

This comment has been minimized.

Show comment
Hide comment
@benfry

benfry Jun 7, 2015

Member

@REAS please leave smooth(0) out of the reference. It's not useful and confuses things further. Also, you should mention that it's dependent on your machine's graphics capabilities (the card and the drivers) whether it supports 4x or 8x or whatever. Many won't be able to do that.

Should we make smooth(2) bilinear and smooth(3) bicubic for Java2D? (And therefore, smooth(3) will be the default.) Numbers-wise that seems to make more sense (bilinear = 2d degree, cubic = 3rd degree).

Member

benfry commented Jun 7, 2015

@REAS please leave smooth(0) out of the reference. It's not useful and confuses things further. Also, you should mention that it's dependent on your machine's graphics capabilities (the card and the drivers) whether it supports 4x or 8x or whatever. Many won't be able to do that.

Should we make smooth(2) bilinear and smooth(3) bicubic for Java2D? (And therefore, smooth(3) will be the default.) Numbers-wise that seems to make more sense (bilinear = 2d degree, cubic = 3rd degree).

@benfry

This comment has been minimized.

Show comment
Hide comment
@benfry

benfry Jun 8, 2015

Member

Alright, this is wrapped... smooth(3) is bicubic in Java2D (the default) and smooth(2) sets it lower to bilinear. On OpenGL, the smoothing level refers to the oversampling/multisampling/fsaa or whatever it's using these days, so it'll be 2 (the default), 4, 8, 16 depending on how your card works.

But for 95% of users (and 99.99% of the time), the smooth() command can be all but ignored since it's on by default. The other 5% might want noSmooth() or smooth(N) sometime.

Member

benfry commented Jun 8, 2015

Alright, this is wrapped... smooth(3) is bicubic in Java2D (the default) and smooth(2) sets it lower to bilinear. On OpenGL, the smoothing level refers to the oversampling/multisampling/fsaa or whatever it's using these days, so it'll be 2 (the default), 4, 8, 16 depending on how your card works.

But for 95% of users (and 99.99% of the time), the smooth() command can be all but ignored since it's on by default. The other 5% might want noSmooth() or smooth(N) sometime.

@benfry benfry closed this Jun 8, 2015

@benfry benfry self-assigned this Jun 8, 2015

@REAS

This comment has been minimized.

Show comment
Hide comment
@REAS

REAS Jun 8, 2015

Member

I will referencify these decisions.

Member

REAS commented Jun 8, 2015

I will referencify these decisions.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.