POV-Ray / povray

The Persistence of Vision Raytracer: http://www.povray.org/
GNU Affero General Public License v3.0
1.35k stars 282 forks source link

Delta to same region of full image on +sc +ec +sr +er use. #377

Closed wfpokorny closed 7 months ago

wfpokorny commented 5 years ago

Summary

The differences show up only with anit-aliasing options on. With +am1 the differences seen have been almost invisible at < 3/255 per color channel affecting only a few pixels and sometimes differences might not appear. With +am2 I've not seen a differences, but suspect that just chance and susceptibility. With the new to v38 +am3, using +ss for reproducibility, the differences is apparent and always present. The +am3 option brings out detail - including defect related detail like this.

Suspect with the partial rendering options there is some sub-pixel offset relative to the full size render. A guess.

Recommend this issue be looked at should either of the issues #279 or #312 be taken up. Those issues are also related to partial rendering and this issue would likely need to be fixed should the feature of #279 be implemented.

For additional detail see the newsgroup thread at:

http://news.povray.org/povray.binaries.images/thread/%3Cweb.5d07acb1d24138982bedecc40%40news.povray.org%3E/

Environment

My initial debug of newsgroup report with Ubuntu 18.04, but the problem seen in various releases and environments.

Steps to Reproduce

With the following set of renders creating netpbm ppm output images. Later using the pamarith command from that package of image utilities to create comparison images.

povray test.pov +am3 +a0.1 +r4 +ss1234 -j +wt1 -D +w400 +h400 +fp +oFullA.ppm
povray test.pov +am3 +a0.1 +r4 +ss1234 -j +wt1 -D +w400 +h400 +fp +oFullB.ppm

povray test.pov +am3 +a0.1 +r4 +ss1234 -j +wt1 +sc1 +sr1 +ec200 +er200 \
  -d +w400 +h400 +fp -oUpperLeft.ppm

Full compare is always OK:

pamarith -difference FullA.ppm FullB.ppm >FullCompare.ppm

Any full to partial is not (see attached FullToULCompare.png):

pamarith -difference FullA.ppm UpperLeft.ppm >FullToULCompare.ppm

Expected Behavior

Partial image render output should match full render output exactly and does not with AA options +am1 and +am3. Issue not seen with +am2, but strongly suspect we've just not seen it there given how hard it is to pick up with +am1.

Render Settings

See too details above on reproducing. I used master branch (v38) at commit 74b3ebe used to create the image and probably most useful for debug as +am3 exists only in that branch (or the uberpov branch). The issue exists back to v3.6 with +am1 at least, however it might be difficult or impossible to see on comparison to the full image.

Scene

//--- testPov.pov

#version 3.7;
global_settings { assumed_gamma 1 }
camera {
  location 3
  look_at 0
}

light_source { 10 color rgb 1 }

background { color rgb 0.4 }

sphere { 0 1 texture { pigment { color rgb <1,0,0.5> } } }

//--- end of testPov.pov

Output

Using +am3 +a0.1 +r4 +ss1234 -j +wt1 for full and partial images compared. See above.

FullToULCompare

Workaround

Given the issue not seen with +am2 that practically might be an AA option. Turning jitter off has helped some with +am1 differences, but all my testing had it off so that doesn't work universally.

c-lipka commented 3 years ago

Anti-aliasing makes use of pseudo-random sequences which are seeded based on the render thread block coordinates to make sure the results are repeatable regardless of the order of render thread blocks; but (to the best of my knowledge) no attempt is made to re-seed these sequences on a per-pixel basis. As a result, if these pseudo-random numbers are "used up" in a different pattern during the render of a block, different numbers are "pulled" for any given pixel.

"Cutting off" part of a ender block using the partial render parameters will cause some of the block's pixels to not be rendered, thus no pseudo-random numbers will be "used up" by these cut-off pixels, modifying the numbers "pulled" for the other pixels.

Those pseudo-random numbers will primarily affect anti-aliasing jitter, but might also affect other pseudo-random render effects, such as subsurface light transport computations.

These effects may go away if you "cut" the image at render thread block boundaries, but I'm not 100% sure. (Render blocks in the center of the rendered area will re-sample strips of pixels outside its boundary to obtain the information needed for anti-aliasing; I'm not sure off the top of my head whether this also happens if those pixels aren't part of the image to be rendered.)

Also, note the documentation claiming:

Note: The jittering noise is random and non-repeatable so you should avoid using jitter in animation sequences as the anti-aliased pixels will vary and flicker annoyingly from frame to frame.

So essentially, POV-Ray is not even guaranteeing that re-rendering a full scene with the same settings will produce the same result, if you are using anti-aliasing with jitter.

c-lipka commented 3 years ago

For the records: I'm filing this under "let's not put this on our plate for the v3.8.0 release", because it is presumably behavior carried over from v3.7, and certainly not trivial to fix.

wfpokorny commented 7 months ago

For an improved understanding of this issue see:

https://news.povray.org/povray.pov4.discussion.general/message/%3C65b28310%241%40news.povray.org%3E/#%3C65b28310%241%40news.povray.org%3E

Basically these differences are related the use of anti-aliasing (AA) and pseudo random number streams being different at any given pixel between a full render and a partial render. There are mitigations, but no complete fix when running AA (*).

(*) - In other than a way which always forces the maximum number of AA samples.

wfpokorny commented 7 months ago

What was seen here is a side effect of how anti-aliasing works given different pixel orderings between a partial render and a full render.

Above statement suggests normalizing the random stream seeds to pixel positions would likely work, but this looks ugly to implement and use when compared to the benefit.