|
|
|
|
|
|
| |
| |
|
|
|
|
| |
| |
|
|
William F Pokorny <ano### [at] anonymousorg> wrote:
> Kenneth wrote:
> >
> > When image pixels go over <1,1,1> in brightness (regardless of how),
> > antialiasing starts to fail, both in the on-screen preview
> > and in the saved image file.
>
> ...At the time AA is done it knows about the color channel values and
> > nothing more. With color values >>1 there simply is a massive difference
> > between adjacent pixels.
You have given me an idea for what might be a useful feature (and feature
request!): A way to visually determine which pixels in a render have gone over a
certain brightness limit (to see where AA might fail, among other uses). This
would be for typical low-dynamic-range renders, not HDR where the idea may not
work as intended(?)
Let's say that I create a scene with many different light sources (spotlights,
fill lights, radiosity, etc.), and lots of objects with complex textures and
colors. With all of this stuff going on and interacting, it is sometimes
difficult to know exactly where the lighting of a scene is creating pixels that
are too bright, or where the colors have unintentionally washed out. Of course,
some of this effect may BE intentional; but let's assume that it isn't. (For
simplicity' sake, assume the pixel brightness limit to be anything greater than
<1,1,1> or <0.3,0.6,1.0> -- any vector component that exceeds 1.0)
It would be useful to have an optional 'switch' during render tests to actually
SEE which pixels are the problem ones. The idea would be to render the scene as
a pixel-by-pixel 'histogram' of sorts-- instead of the usual colorful render--
showing exactly where the lighting has gone over-limit. (For example, to pick
out a pixel that somehow ends up as <1.7,1.7,1.7>, or <0.3,0.5,1.9> or
whatever). To save on render time, this would be done before any final AA is
applied.
Once we can see where the lighting problems are, we can then go back and re-work
the lighting/textures to try and fix them.
For my example render, I've simply pumped up the lighting of the single
light_source, to mimic what multiple light sources might do when they interact
unintentionally. The 'histograms' are just Photoshop mock-ups of what I envsion
to be the result-- either in color, or equally useful as grayscale.
I don't know how this feature would be implemented within POV-ray, but it seems
possible(?)
Post a reply to this message
Attachments:
Download 'histogram_idea.jpg' (156 KB)
Preview of image 'histogram_idea.jpg'
|
|
| |
| |
|
|
|
|
| |
| |
|
|
Functions.
Render your scene, then paste the filename into the provided spot.
Render this scene.
I think it _ought_ to do what you want.
#version 3.8;
global_settings {assumed_gamma 1.0}
#declare Zoom = 60; // 15
camera {
orthographic
right x*image_width/Zoom
up y*image_height/Zoom
location <0, 0, -20> // x = 5
look_at <0, 0, 0>
//rotate -y*1
}
light_source { <0, 0, -20> color rgb <1, 1, 1>}
sky_sphere {pigment {rgb 1}}
//=====================================================================================================================
==
#declare Filename = "/home/oem/Documents/POV-Ray-3.8/PovLogo.png";
#declare ImageMap = pigment {image_map {Filename}}
#declare Pattern2 = function {pigment {image_map {Filename}}}
#declare f_red = function {max(Pattern2 (x, y, z).red, 1)-1}
#declare f_grn = function {max(Pattern2 (x, y, z).green, 1)-1}
#declare f_blu = function {max(Pattern2 (x, y, z).blue, 1)-1}
#declare OverOne = function {max(f_red (x,y,z), f_grn (x,y,z), f_blu (x,y,z))}
#declare Pigment2 =
pigment {
function {OverOne (x, y, z)}
color_map {
[ 0 rgb 0 ]
[ 1 rgb 1 ]
}
}
#declare Resolution = max_extent (ImageMap);
#declare Resolution = Resolution + <0, 0, 1>;
box {0, 1
pigment {Pigment2}
translate <-0.5, -0.5, -0.5>
scale Resolution*(1/Resolution.x)
}
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
"Bald Eagle" <cre### [at] netscapenet> wrote:
> Functions.
>
> Render your scene, then paste the filename into the provided spot.
>
> Render this scene.
> I think it _ought_ to do what you want.
> [code]
>
That's a valiant effort, and a clever use of functions! Especially with the use
of max(...)
[Btw, I couldn't get my own version of your
#declare Filename = ... file path ...
to work in Windows, despite multiple tries and guesses; obviously some kind of
arcane syntax problem at my end that I haven't yet solved]
As far as I can tell, the intention of your code is to take a *pre-rendered*
image and find the brightest pixels => 1.0 (or more specifically, which color
component goes over that limit.) The three functions...
#declare f_red = function {max(Pattern2 (x, y, z).red, 1)-1}
etc.
.......look like they expect to see values *over* 1.0, and to give the result as
the additional amount.
Unfortunately, what I see is a totally black render when I plug in a typical LDR
image. That's to be expected, though-- unless I'm wrong about your intention--
since an already-rendered LDR image has all of its pixels at or below 1.0, as
the image file (and monitor) can only reproduce colors in the 0-1 range.
(Maybe you had HDR images in mind instead?)
I re-worked a few things in the code to get your intended(?) result (re: using a
pre-rendered LDR image), and it works quite nicely: Pixels *approaching* 1.0 are
picked out. Cool!
But trying to determine which pixels are too bright *while* rendering involves
POV-ray's inner workings; as William alluded to, the scene's pixel values
(*prior* to being written to a file or to the preview screen) can easily exceed
1.0... hence the 'failed AA' effect, for example. I guess that they are clipped
to that maximum only when the file is written, or when the preview can't
reproduce them as-is.
In any case, here's my minor re-working of your code for LDR images...which
looks to be useful in and of itself. No light_source needed. Thanks for the
brain-boost ;-)
------------
#version 3.8;
global_settings {assumed_gamma 1.0}
background{rgb <.2,.2,.25>}
camera {
perspective
location <0, 0, -1>
look_at <0, 0, 0>
right x*image_width/image_height // aspect
}
#declare Pattern2 = function {pigment {image_map {png "my_image.png"}}}
#declare f_red = function {max(Pattern2 (x, y, z).red, .9999) - 1}
#declare f_grn = function {max(Pattern2 (x, y, z).green, .9999) -1}
#declare f_blu = function {max(Pattern2 (x, y, z).blue, .9999)-1}
#declare OverOne = function {max(f_red (x,y,z), f_grn (x,y,z), f_blu (x,y,z))}
#declare Pigment2 =
pigment {
function {OverOne (x, y, z)}
color_map {
// I reversed the color order here, to get a 'positive' image,
// so the brightest pixels show up white instead of black
[ 0 rgb 1 ]
[ 1 rgb 0 ]
}
}
#declare Resolution = max_extent (ImageMap);
#declare Resolution = Resolution + <0, 0, 1>;
box {0, 1
texture{
pigment {Pigment2}
finish{ambient 1 emission 0 diffuse 0}
}
translate <-0.5, -0.5, -0.5>
scale Resolution*(1/Resolution.x)
}
Post a reply to this message
Attachments:
Download 'brightest_pixels_test_1.jpg' (77 KB)
Preview of image 'brightest_pixels_test_1.jpg'
|
|
| |
| |
|
|
|
|
| |
| |
|
|
"Kenneth" <kdw### [at] gmailcom> wrote:
> "Bald Eagle" <cre### [at] netscapenet> wrote:
> [Btw, I couldn't get my own version of your
> #declare Filename = ... file path ...
> to work in Windows, despite multiple tries and guesses; obviously some kind of
> arcane syntax problem at my end that I haven't yet solved]
I know there's the thing with the forward/backward slashes in paths...
> As far as I can tell, the intention of your code is to take a *pre-rendered*
> image and find the brightest pixels => 1.0 (or more specifically, which color
> component goes over that limit.) The three functions...
> #declare f_red = function {max(Pattern2 (x, y, z).red, 1)-1}
> etc.
> .......look like they expect to see values *over* 1.0, and to give the result as
> the additional amount.
Right-o. Anything with a component over 1 is the only part that would show up.
> Unfortunately, what I see is a totally black render when I plug in a typical LDR
> image. That's to be expected, though-- unless I'm wrong about your intention--
> since an already-rendered LDR image has all of its pixels at or below 1.0, as
> the image file (and monitor) can only reproduce colors in the 0-1 range.
Hmmm. I thought POV-Ray could write color values to a file that were over 1.
I certainly know from all my reading and poking around in the source code and
working with the gamma and color values that the industry algorithms have sanity
checks for values over 1...
> (Maybe you had HDR images in mind instead?)
>
> I re-worked a few things in the code to get your intended(?) result (re: using a
> pre-rendered LDR image), and it works quite nicely: Pixels *approaching* 1.0 are
> picked out. Cool!
Define a multiplier for the function right before the 1 is subtracted.
I faked an HDR image by using >1 on the blue channel. Take your multiplier and
use a variable so you don't have to change all 3 when you want to tweak it.
> But trying to determine which pixels are too bright *while* rendering involves
> POV-ray's inner workings; as William alluded to, the scene's pixel values
> (*prior* to being written to a file or to the preview screen) can easily exceed
> 1.0... hence the 'failed AA' effect, for example. I guess that they are clipped
> to that maximum only when the file is written, or when the preview can't
> reproduce them as-is.
Is there a way to render it as "HDR" and without any antialiasing first, and
then re-render /post-process it WITH aa?
Maybe along the lines of what I'm doing here, or an image convolution kernel or
something.
#declare M = 0.9999;
> #declare f_red = function {max(Pattern2 (x, y, z).red, 1)*M - 1}
> #declare f_grn = function {max(Pattern2 (x, y, z).green, 1)*M - 1}
> #declare f_blu = function {max(Pattern2 (x, y, z).blue, 1)*M - 1}
> // I reversed the color order here, to get a 'positive' image,
> // so the brightest pixels show up white instead of black
> [ 0 rgb 1 ]
> [ 1 rgb 0 ]
> }
> }
Odd, since the result of the function should provide 0 for LDR images, and white
for anything over 1 - the fractional component.
It seemed to work that way for me with my version, but it was a last-minute
late-night hack, so maybe I double-reversed something....
Set M to 1.1 and see what happens... oh, I see now.
When you use your subtraction method inside the function, your max is now less
than 1. Then you subtract 1 and get a _negative_ value. That dips into the
color map from the top, not the bottom, which is why you get backwards results.
Use the *M version that I posted an the original color map, and all should be
well.
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
"Bald Eagle" <cre### [at] netscapenet> wrote:
> "Kenneth" <kdw### [at] gmailcom> wrote:
> > "Bald Eagle" <cre### [at] netscapenet> wrote:
>
> > [Btw, I couldn't get my own version of your
> > #declare Filename = ... file path ...
> > to work in Windows, despite multiple tries and guesses...]
>
> I know there's the thing with the forward/backward slashes in paths...
I finally got it to work (which is a major accomplishment for me, ha):
using DOUBLE backward slashes in Windows-- which is actualy mentioned in the
docs...
#declare Filename =
"C:\\Users\\Computer\\Documents\\Kens new POV-Ray scenes\\A1.png"
Double FORWARD slashes work too.
>
> Hmmm. I thought POV-Ray could write color values to a file that were over 1.
As far as *I* know (which isn't saying a lot), typical LDR image files like JPEG
and PNG top out at 255/255. Which makes sense, as to their final presentation on
a typical monitor.
> > But trying to determine which pixels are too bright *while* rendering
> > involves POV-ray's inner workings; as William alluded to, the scene's
> > pixel values (*prior* to being written to a file or to the preview screen)
> > can easily exceed 1.0... hence the 'failed AA' effect, for example. I guess
> > that they are clipped to that maximum only when the file is written, or
> > when the preview can't reproduce them as-is.
I've been rolling that seeming caveat around in my head since I posted it-- and
I now think I'm wrong: Once the too-bright pixels ARE eventually clipped to 1.0
maximum for the image file (and/or preview), the end result is just fine for
post-processing with the re-worked code here-- to find the brightest pixels. I
can't visualize any difference between that, and doing the same thing
'internally' in POV-ray like I initially imagined. The only difference I see is
that the code picks out pixels *at* 1.0 brightness, rather than > 1.0. But that
doesn't seem to be a deal-breaker, as to the code's intended use. As I reflect
more on the subtleties, I may turn out to be mistaken-- but the code seems to do
exactly what I envisioned... albeit *as* a post-processing step. But that's not
too painful a compromise ;-)
> > // I reversed the color order here, to get a 'positive' image,
> > // so the brightest pixels show up white instead of black
> > [ 0 rgb 1 ]
> > [ 1 rgb 0 ]
> > }
> > }
>
> Odd, since the result of the function should provide 0 for LDR images,
> and white for anything over 1... oh, I see now.
> When you use your subtraction method inside the function, your max is now less
> than 1. Then you subtract 1 and get a _negative_ value. That dips into the
> color map from the top, not the bottom, which is why you get backwards
> results...
Ha, I'm glad you figured that out; for me, it was just mucking around with
things until I got what looked like a good result! :-O
> Use the *M version that I posted an the original color map, and all should be
> well.
I'll give that a try.
BTW, I noticed something about my image results that makes me wonder about how
the max(...) function operates on other *functions*...
#declare OverOne = function{max(f_red (x,y,z), f_grn (x,y,z), f_blu (x,y,z))}
It seems that if every entry in max(...) is actually EQUAL, the overall function
returns all THREE values (combined? added?), not just one. I'm out of my depth
here, though; maybe that's how max always treats equal values(?), even if
they're just floats. But that's not a problem with the *code's* use; it works as
planned.
I've attached an image to illustrate this.
Post a reply to this message
Attachments:
Download 'max_result_with_functions.jpg' (93 KB)
Preview of image 'max_result_with_functions.jpg'
|
|
| |
| |
|
|
|
|
| |
| |
|
|
"Kenneth" <kdw### [at] gmailcom> wrote:
> > Hmmm. I thought POV-Ray could write color values to a file that were over 1.
>
> As far as *I* know (which isn't saying a lot), typical LDR image files like JPEG
> and PNG top out at 255/255. Which makes sense, as to their final presentation on
> a typical monitor.
>
> > > But trying to determine which pixels are too bright *while* rendering
> > > involves POV-ray's inner workings; as William alluded to, the scene's
> > > pixel values (*prior* to being written to a file or to the preview screen)
> > > can easily exceed 1.0... hence the 'failed AA' effect, for example. I guess
> > > that they are clipped to that maximum only when the file is written, or
> > > when the preview can't reproduce them as-is.
Yes - this was bouncing around in my head today, in the insufficiently
caffeinated fog of fatigue, and I think you'd have to define a special
antialiasing mode to use something like my functions in the antialiasing
convolution matrix.
http://cs.trinity.edu/~jhowland/class.files.cs357.html/pov-new/Docs/pov155.htm
I quickly skimmed over some aa/convolution websites, and using a 7x7 matrix with
jittering seemed to give very nice results.
> BTW, I noticed something about my image results that makes me wonder about how
> the max(...) function operates on other *functions*...
>
> #declare OverOne = function{max(f_red (x,y,z), f_grn (x,y,z), f_blu (x,y,z))}
>
> It seems that if every entry in max(...) is actually EQUAL, the overall function
> returns all THREE values (combined? added?), not just one. I'm out of my depth
> here, though; maybe that's how max always treats equal values(?), even if
> they're just floats. But that's not a problem with the *code's* use; it works as
> planned.
>
> I've attached an image to illustrate this.
Yes. Because OverOne is a function that acts more like a flag - because you
wanted to look at pixels with ANY component of the rgb color vector over one.
I have a mantra that I repeat to myself: "FUNCTIONS RETURN SCALAR VALUES".
So max returns the maximum value of all the arguments it is given.
1 is 1 is 1 is 1 is 1.
Or as Ayn Rand would admonish, "A is A."
So, if ANY one of the three components triggers the "bright pixel switch", the
value of its component function returns 1. So OverOne acts as a sort of Boolean
indicator to show which pixels have at least one_component satisfying your
criteria.
So interpreting your visual results logically,
Are there pixels in the red channel that are > M? Yes.
Are there pixels in the grn channel that are > M? Yes.
Are there pixels in the blu channel that are > M? Yes.
Which of those pixels meet your criteria? ALL of them.
So OverOne shows ALL of those channels. Because they way you wrote your inquiry
was to detect those brighter pixels. And AFAIK, POV-Ray's aa mechanism doesn't
function through individual color channels, it just interpolates the whole rgb
color vector.
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
"Bald Eagle" <cre### [at] netscapenet> wrote:
> "Kenneth" <kdw### [at] gmailcom> wrote:
> >
> > It seems that if every entry in max(...) is actually EQUAL, the overall
> > function returns all THREE values (combined? added?), not just one.
> Yes. Because OverOne is a function that acts more like a flag - because you
> wanted to look at pixels with ANY component of the rgb color vector over one.
> [snip]
Clear and concise; thanks a bunch. The docs for max(...) don't touch on any of
this, although I guess it's 2nd-nature knowledge to programmers. Parts of your
explanation should be included there, in my humble opinion...for poor folks like
me.
BTW, there are seemingly simple and straightforward parts of your code that
fascinate me... because I would not have expected them to work:
[using my own example...]
#declare Filename =
"C:\\Users\\Computer\\Documents\\Kens new POV-Ray scenes\\A1.png"
then yours...
#declare ImageMap = pigment {image_map {Filename}}
I've actually never done this kind of thing before(!)-- mainly because I
couldn't get the initial file path syntax to work until now. But I digress...
In essence,
Filename =
"A1.png" -- or maybe just A1.png with no quotes ?
One is an 'image string' (which is understandable as a #declared string), the
other is just... naked. In any case,
#declare ImageMap = pigment {image_map {Filename}}
looks like it would end up as
#declare ImageMap = pigment {image_map {"A1.png"}}
or just
#declare ImageMap = pigment {image_map {A1.png}}
.... neither with the usually-required prefix png "A1.png", although AFAIU,
maybe the prefix isn't absolutely required anyway.
Yet it works. I suspect that at least the double-quote version of A1.png is
correctly being recognized, although I'm not sure as to where the double quotes
arise from. Is it because the entire file-path name is itself in double quotes?
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
"Kenneth" <kdw### [at] gmailcom> wrote:
> Yet it works. I suspect that at least the double-quote version of A1.png is
> correctly being recognized, although I'm not sure as to where the double quotes
> arise from. Is it because the entire file-path name is itself in double quotes?
It's because the variable Filename is declared with a string value, so using
Filename is just like using that same string value as the image map filename
parameter - they are equivalent to the SDL parser.
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
"Robert McGregor" <rob### [at] mcgregorfineartcom> wrote:
> "Kenneth" <kdw### [at] gmailcom> wrote:
> ...I'm not sure as to where the double quotes
> > arise from. Is it because the entire file-path name is itself in
> > double quotes?
>
> It's because the variable Filename is declared with a string value, so using
> Filename is just like using that same string value as the image map filename
> parameter - they are equivalent to the SDL parser.
Thanks. Sometimes, I probably think too literally about this kind of stuff (out
of ignorance)-- when the parser already 'knows' what to do.
Btw, the OverOne function in the re-worked code should probably be re-named as
AtOne or LimitOne
to more accurately describe its changed result ;-)
Post a reply to this message
|
|
| |
| |
|
|
From: Cousin Ricky
Subject: Re: antialiasing fails with very bright objects
Date: 29 Aug 2021 12:09:46
Message: <612bb14a$1@news.povray.org>
|
|
|
| |
| |
|
|
On 2021-02-11 7:56 PM (-4), Cousin Ricky wrote:
>
> trade-off between good hyper-white effects and good anti-aliasing, and
> on balance, I'd have to say I prefer the latter.
*former
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
|
|