Information on albedo and fresnel use. v3.7/v3.8/v4.0. (First thought a wiki contribution, then re-written like a newsgroup posting but complicated, and never seemed really done so never posted to a forum. Here as my current understanding of the finish features tangle and why the povr branch is trying some alternatives) The update of documentation for the v3.8 radiosity brilliance boolean keyword months back inspired me to try again to understand, and perhaps more extensively document, the v3.8 albedo and fresnel keywords. In previous attempts to adopt "albedo/fresnel," I've ended confused. In digging anew, I better understand and I've developed some views. In the hopes I can help others, I'm going to write for while. I consider myself a naive user of the full set of finish features. If I've gotten something wrong, perhaps clipka, Cousin Ricky or others will step in to correct and clarify. My usual raft of footnotes (--) are all at the bottom. My recommendations given the current state and my understanding of it --------------------------------------------------------------------- If using v3.7, don't use albedo with highlights(ii). If using v3.8, use albedo with highlights only where also using finish block fresnel and an interior IOR > 1.0. If using v3.8, never use finish block 'fresnel on' with non-albedo highlighting. Avoid using albedo highlights if the underlying surface / perturbed surface normal is not smooth. In other words, if you are already modeling micro surface effects(pp). Use diffuse albedo only when brilliance is not the default of 1.0. Likewise, the radiosity brilliance boolean is active only without albedo and brilliance not 1.0. Never use a brilliance value of -1.0(aa). The diffuse fresnel behavior (IOR > 1) essentially forces a finish reflection block for realistic results(oo). With transparency, use interior_textures to create finishes which adjust finish features generating unwanted effects on second surfaces. Some of what happens internally ------------------------------- With non-radiosity diffuse, 'albedo' generates an internal adjustment factor applied to both the diffuse and diffuse backside values. In v3.8, if using the new radiosity brilliance boolean, another adjustment is used for diffuse values with radiosity rays - when albedo is not specified. No matter the application details or the POV-Ray version, these adjustments only happen if the finish brilliance is other than the default of value of 1.0. If other than 1.0(aa), the adjustment factor(s) and resulting internal diffuse values are changed(qq). With phong and specular highlights, albedo creates huge internal values based upon the values specified. Two different formulas are used for phong and specular. These internal values appear to be set so as to generate, roughly, a non-albedo, equivalent highlight at an IOR of 1.5 and a local light intensity of 1.0. In v3.7 it looks to me like work not finished and that this is what v3.8 addresses with the finish block fresnel keyword. There is too a promise that albedo can be used "to specify that the parameter is to be taken as the total diffuse/specular reflectance, rather than peak reflectance." (b1)(b2)(b3)(b4)(b5)(b6)(b7) Performance considerations -------------------------- On the newsgroups we've talked about how >1.0 values in highlights, reflections or source representations cause very jagged results even with Anti-aliasing(AA). What's not been stressed enough is that AA performance is dreadful over the entire highlight region though we only notice the jagged edges in the result. The common output formats clamp output channel values to a maximum of 1.0, so it's easy to forget AA is thrashing in these >>1 intensity regions. Any adaptive AA tends to exhaust itself trying to do something - and it's pointless. Where intensities are well over 1.0, scene render performances can be many times worse than a scene where values are all in the 0-1 range. Physically based rendering techniques - to the extent they encourage internal working values outside the usual 0-1 color channel range - are at odds with POV-Ray's AA(jj). Rendering large(rr) and using methods to scale down to a finished image size is one method to avoid the AA penalty with a gain for the look of the final result too. Rendering larger, of course, carries its own cost. Albedo highlight results are different -------------------------------------- Using a scene with a sphere lit by a single light. In v3.8 with finish fresnel on and an IOR of 1.5, with both phong and specular highlights (0.5), the albedo versions return >1 highlight values at a light intensity of about 2.47(kk) instead of this happening at just over 2.0 with non-albedo highlights(kk). The intensity change between albedo versions of highlights and regular ones are different over all light intensities. To be expected, when the v3.8 finish fresnel is on, changes in IOR affect the highlight intensity(ff). If you turn on the finish block fresnel boolean and specify phong/specular highlights without changing the default IOR from 1.0, you get no visible highlights at all - poof(gg). Plus, that poof is much more likely if 'fresnel on' where we have non-albedo highlighting. The latter, of course, come out much dimmer not having the huge internal values of the albedo form. Negative light results with highlights look to differ much more between traditional highlights and v3.8 albedo finish fresnel on highlights than do normal positive lights differ(ll). I've not run down why, my guess is this is related to the highlight response being different for the v3.8 fresnel form - more so at local light intensities not near 1.0. Diffuse fresnel results are different ------------------------------------- Here ignoring any albedo driven differences and taking the brilliance as always 1.0. In v3.8, if you set up a diffuse object with an interior IOR > 1.0, and have fresnel on, the object dims as you move toward portions of the surface where the normal is perpendicular to the incoming rays. In v3.8, setting diffuse at 0.5, the IOR at 1.5 and turning fresnel on in the finish block for a sphere lit by a single light. You get a returned diffuse intensity over 1.0 at a local light intensity of around 2.178. When the finish block fresnel is turned off the returned diffuse intensity goes over 1.0 at just over 2.0 as one would expect. The fresnel diffuse going over 1.0 at 2.178 and the albedo-fresnel highlights at 2.47 is - unfortunate for our intuition. If the IOR is < 1.0 and fresnel is on, the internal FresnelR() calculation see a total reflection for portions of the object inward from the, "ray to surface normal perpendicular," parts and in proportion to the IOR value as it moves toward 0.0. These regions turn completely black for the diffuse contribution - the lit parts shrink relative to any given "view." Where the IOR > 1.0, fresnel on, I believe the effect correct - but one not realistic if there is no compensating fresnel reflective component in the finish(oo). What to do if one doesn't want this compensation, but otherwise needs the interior to have an IOR > 1.0? Emission fresnel results are different -------------------------------------- In v3.8, if you set up an emissive object with an interior IOR > 1.0, and have fresnel on, the object dims as you move toward portions of the surface where surface normals are perpendicular to the incoming rays. In other words, if you have an emissive sphere with an IOR of 1.5 you get a dark outline on the sphere and a darker sphere. Further, emission dims - in total - the higher the IOR value. If the IOR is < 1.0 and fresnel is on, the internal FresnelR() calculation see a total reflection for portions of the object inward from the, "ray to surface normal perpendicular," parts in proportion to the IOR value as it moves toward 0.0. These regions turn completely black for emission. The emissive parts shrink relative to any given "view." One can set the emissive object IOR's to 1.0, if these fresnel / 'aoi' dimming effects are unwanted. How often applying fresnel effects to emission makes sense, is a question in my mind. If after highlights or fresnel reflection on the emissive object's surface, I suppose. Where the emission is relatively dim compared to reflected or highlight intensities? In such cases - glass bounding something emissive I'd guess - wondering if modeling the emissive part apart from the containing / bounding surface would be better. Maybe, this is harder for mesh representations. Reflection fresnel results -------------------------- As far as I know, results here long stable and relatively solid. A potential point of confusion; If you have coded the common shorthand of: reflection { 1 fresnel on } and the internal IOR is at 1.0, you get a completely black reflection response. You'd need to code a minimum value too to avoid this - or have an IOR > 1.0. At IORs <1.0 the response is similar to that of diffuse and emission excepting, rather than seeing an intensity of 0.0 creeping in from the ray glancing portions, you get a complete reflection of the environment - where the max reflection value >= 1.0. The IOR setting doesn't matter, if the reflection fresnel is off. The finish block fresnel setting is tangled with the reflection block fresnel setting depending upon the ordering of statements as described in the documentation. I suspect the implementation is trying to encourage full finish block fresnel turning on the reflection block fresnel as this most accurate - but the set up makes it easier for users to trip. Of note the maximum reflection value is not clamped, but the minimum effectively is for the reflectivity. You can of course reflect color channels at any value so long as there is some reflection. As long recommended, where one has any transparency, use the conserve_energy keyword for more accurate results. What's probably less understood is the conserve_energy implementation is 'gray weighted'. Meaning it's less accurate as one moves away from grey / roughly equivalent color channels for the reflection color and reflected / transmitted colors. Correctness where transparency ------------------------------ I have a number of concerns and questions as to correctness, especially with respect to highlights. To some degree this true whether the v3.8 albedo / fresnel type or not. First, background. The IOR getting used internally isn't the one specified, but rather a "relativeIOR." An internal function calculates this value using both the IOR where the ray started and the IOR at the surface intersection was just found. There is an internal atmospheric IOR of 1.0 (air) used for regions outside a shape or surface. For the purposes of thinking about things; Suppose one, partly transparent, shape/surface with an IOR of 1.5. At the initial air surface intersection the relativeIOR is determined to be 1.5 - and the expected stuff happens. At the next shape/surface intersection we have instead an interior to air transition and the relativeIOR is determined to be 0.667. Where the second surface of the same solid shape(mm) I believe the reflection and refraction calculations to be render-correct with respect to the relativeIOR and direction (excepting treatments with perturbed normal textures as discussed below). But... We are today doing phong and specular highlight calculations at that second surface. However, these can only be correct, if we account for the refracted ray direction given a >1.0 IOR. Seems to me this can only be done while tracing in a forward direction from the lights - when using photons. Let's now make the shape hollow so that we have more of a membrane, shell or bubble of material enclosing 'air' - though we often, at a given working scale, cannot resolve both surfaces, there are two. In such cases it seems to me we want to mostly ignore the interior and any refraction effects and worry only about reflection / specular reflection effects. I think we need in many cases an IOR for the surface glaze. We need one too for the interior when that shape interior is not hollow (gg)(mm). This idea of a surface lacquer or oxidation or whatever surface material over an interior material pushes us toward breaking the common IOR apart for the purposes of rendering. Further, we could again not carry around an interior for opaque objects - should we want to go that route. There's something to be said too for the simplicity - code wise - in only having one. On the second surface, what things are happening with the fresnel diffusion and emission fading based upon IOR? I believe, often, the wrong sorts things given the < 1.0 relativeIOR on that surface. An option to suppress effects we do not want on that second surface is to create a interior_texture without highlights and with fresnel off (brightness??) - as needed. An interior_texture option doesn't work should we want highlights on both interior and exterior surfaces. Suppressing interior_textures would make the photon result less accurate, but there I suppose one could add a photon switch and save photons, two interior textures, maybe... Lastly, I'll add using custom interiors adds another potential point of confusion for shapes that flip inside out depending upon how they are specified. On plastic exponents. Phong 40. Specular 20 (1/20) -------------------------------------------------- Internally both highlight types use exponents to pow(). The phong exponent is specified directly and the specular value as 1/exponent. It's basically a falloff exponent internally. The documentation's phong and specular have default good plastic values, but at much different highlight sizes. To my eye phong's is closer to truth. I believe the default plastic roughness(cc) value for specular should originally have been 1/160 and not the 1/20 it is(dd) for the kinds of lighting and camera positions most commonly used. The highlights should be of very similar size at the 'plastic' setting for most scenes; the exact value matters less. Beyond this issue, the highlight setting is messy once the light position starts to oppose the camera to surface vector - when the object starts to become back lit. With specular highlights the highlight size stays the same as the lighting becomes more back lit. Further, specular's 'imprint', on a locally spherical surface, stays round. The phong highlight however elongates in a direction perpendicular to the most back lit vector for the incoming light once beyond about 90 degrees from the surface to camera vector. At a phong_size of 40 / 'plastic' for a sphere where the light is 135 degrees rotation +y, creates a substantially elongated / 'scaled up in y' phong highlight. When I think about a rough surface as the cause for the highlight, an elongation with such lighting relative to the eye makes sense to me. Our documentation, however, claims the specular highlight is more accurate: "[specular]... more closely resembles real specular reflection and provides a more credible spreading of the highlights occurring near the object horizons." I see no spreading at all at the horizon with specular highlights, but rather with phong highlights? Given camera opposing lighting, if one wanted to roughly match the phong highlight in height, 1/20 is a roughness value you might use. This is my best guess for why the 1/20 value was chosen for specular. The 1/20 value however is large for a highlight and it forces larger specular values to have reasonably visible highlights for the more common scene configurations; scenes where the light is actually lighting most of the object's surface. With specular and more back lit lighting, things get ugly because the highlight is always round. At the 1/20 kind of roughness, the highlight, 'visually,' and variously: crashes into the shadow line, pushes the shadow line itself or pushes the highlight past the apparent shadow line. With the phong highlights and more back lit lighting, things get ugly because the size of the highlights substantially increases in a way I believe too vigorous to be realistic, but it better handles the highlights with respect to the shadow lines. Both highlight types can 'abut' and/or push the shadow line if large enough. To step back, both highlight methods are compute efficient approximations for light scattering caused by the roughness of the surface. The general take away is the highlight behavior is less controlled with more back lit lighting situations - especially if one 'normalizes' the desired specular highlight for back lit situations. Other stuff ----------- In v3.8, it's too easy to forget 'albedo' in the highlight specification - or re-specifications - while the finish block fresnel is on. You get, suddenly, very dim or no visible highlight. A complicating factor is you might be expecting some dimming - due the constant albedo reflectance promise - but if not careful you're getting in fact another kind of dimming, by accident, because you forgot the albedo keyword(ee). I think most know, these days (v3.7+), an interior block is attached to all shapes and surfaces whether they can support a defined interior or not(mm). This, I'm guessing, is due needing an IOR for the albdeo and fresnel features(hh). One cannot default interior settings; there is an open github issue regarding this (#319). With highlights, IORs < 1.0 continue to generate the same sort of highlight on the surface as >=1.0 values do. Meaning we get the same highlight for an IOR of 1.5 as (1.0/1.5). Is this render-correct? Seems wrong to me especially with fresnel results. The highlight response staying at black for working IORs of <=1.0 would tend to help with second surfaces where transparency and maybe be more accurate on the whole? On highlight and other intensities >1 with radiosity. Ignoring interior and media to a first order and supposing physically based point light intensities where we've set up distance based light fading due spatial spreading (or localized focusing). We can get very bright surface regions which do not 'forward' (or calculate anew) distance attenuation. The only related controls of which I'm aware are the radiosity block's max_sample keyword and the ability to set the radiosity importance with very bright 'objects'. Neither control ideal, but what else could be done? Negative IOR values, with which folks sometimes play, are always treated as positive values where fresnel calculations come into play. Cousin Ricky has mentioned not using albedo with finish blocks aimed at metallic surfaces. I doubt I understand all the reasons for his statement. Is it that we are already modeling micro effects? On color responses turning white. Clamping happens where the image presentation mechanism cannot represent the spectral color / energy. Clamping happens in viewing where the viewing mechanism cannot completely digest the spectral color / energy. We often get / see white-ish clamping, but what happens is more complicated. It is a distortion toward 'white' - toward the primary components of representation or digestion. We could use additional mechanisms for avoiding - color indigestion / distortion(ss). Take note the default pigment changed from black to white moving v3.7 to v3.8 via setting the version in the SDL. Intended to be a help where someone forgets to add a pigment and has a default black background. The change can be confusing if one happens to have picked up an older scene or texture where the coder took advantage of the default pigment being black - where they wanted black but didn't code it. The lesson is set the pigment black if you need black. Even putting the v3.8 change aside, it's always been possible to set a default pigment in the global settings block to other than black, or white. On seeing odd results with povr's new normal { micro } pattern, it was discovered that there has long been code which modifies perturbed normals where they are non-projecting in a dot product sense. As a rule this happens when the bump_size is larger than about 0.5, but with no_bump_scale all bets are off as to when inversion happens are particular to the set up. Further, since v3.6 (1998) there has been 'bugfix' code which starts to modify perturbed normals in two different ways from the moment the bump_size is other than zero. The effect of this bugfix is muted until the bump_size gets beyond roughly 0.5, but that's somewhat situation and pattern dependent. Practically, this means the reflection response is normal { ... bump_size } dependent. The povr branch has added a new keyword in 'inv_pnormal_cure ' allowing more control of what perturbed normal modifications happen and making it clear 'other' stuff is going on with reflections whenever a normal block is used for a texture / material. Conclusion ---------- There's more banging around in my head, but... Certainly v3.8's default behavior is much better than v3.7s for albedo / fresnel. To the degree we are able to upgrade parsing and control mechanisms to keep folks from incorrectly using features, it's worth pursuing (in v4.0)(nn). Describing and modeling finish components is complicated. I've likely, gotten some wrong in what I've written. Footnotes pertaining to issues and bugs --------------------------------------- (aa) - In v3.8 the adjustments where not hard set to 1.0 I believe should be: New->BrillianceAdjust = (std::abs(New->Brilliance) + 1.0) / 2.0; and New->BrillianceAdjustRad = 2.0 / (std::abs(New->Brilliance) + 1.0); The povr branch has adopted these changes. (b1) - The internal values are calculated only where the full albedo are specified. Updating only the phong_size/roughness of a previously defined finish has always been allowed. It's convenient. Further, it continues to 'work/do something' whether the passed finish had albedo specified or not. This is a problem in that it breaks the constant reflectance aspect promised by highlight albedo use(b1a). (b1a) - Even remembering to specify the full, with albedo, highlight phrase when passing previously defined finishes, one must remember - or otherwise set external to all finish blocks - the phong/specular value from which to calculate the huge value. In other words, we must somehow explicitly specify the phong/specular value 'about which' we want constant value reflectance. (b2) Supposing a correctly defined finish in v3.8 using albedo highlights with fresnel on in the finish block. Further, that a user uses that finish ID to set most of a modified one - and then for reason or accident he turns the fresnel block boolean off. #declare Finish13 = finish { Finish12 ... fresnel off } Boom! The user gets an unadjusted, huge, but hidden from view, internal phong/specular value highlight. (b3) - Better albedo highlight mechanisms are needed. Perhaps always remembering the users original specified value and calculating anew the huge internal values where a user specifies say just 'albedo roughness 0.00123' when passing a previously defined finish to a derived one(v4.0). In the povr branch, I've been playing with options in this direction and for non-fresnel albedo highlights too. (b4) The internal highlight values without the v3.8 fresnel keyword are huge unless the input phong/specular values are 'unnaturally' small. I feel albedo highlights should be illegal unless the fresnel block keyword is present and on(v4.0). We've always been able to use huge values for highlighting tricks in radiosity targeted scenes. This is accomplished with 'very' dim lights and an example of this trick can be seen in the shipped finish_fresnel.pov scene. (b5) - The albedo constant reflection comment in our documentation is only true / meaningful in v3.8, if, the fresnel block boolean is on. (b6) - Both phong and specular documentation have the statements: "If specular is not specified roughness has no effect." This a statement only conditionally true based upon use of the albedo keyword. (b7) - Related to (b1), something I've done a couple times while playing around with albedo in v3.8 is specify 'specular' in the original full finish id definition and then 'phong' albedo ... in the variant of the passed finish id. When you do this you, of course, get both highlights at once. (cc) - It's unfortunate phong and specular went with different keywords and methods to specify the internal exponential falloff. One highlight 'falloff' keyword would be better in v4.0 replacing phong_size and roughness. Maybe 'hardness', 'polish', or ? (dd) - Internally, the phong and specular calculations are different. To get an equivalent size involves a factor of 4 over the majority of a +-90 degree quadrant centered a vector directly to the camera. (ee) - Should the finish block fresnel be legal where users have not specified albedo to get the huge internal values? If not, documenting all that can happen gets tricky I think - and certainly less clear. (ff) - At phong/specular albedo 0.5 at a local light intensity of 1.0 at the highlight, it looks like any IOR above roughly 1.9, generates highlight values of more than 1.0 (which is bad for AA). If the original phong/specular albedo value is 1.0, we get highlight values larger than 1.0 back at an IOR of roughly 1.58. This behavior seems off, given the light value is at 1.0. In other words, why is the highlight 'amplifying' the incoming light above certain IOR values? (gg) One of a couple reasons why in povr I've been working on adding a surface only IOR to the finish block which will have a default of 1.5. (Yes, due ever backwards compatibility, you can already do this, but as only a back door way to set the interior IOR and the method sets/defaults other finish parameters). Another flavor of this idea creates a refraction IOR and reflection IOR. Not sure how these ideas will work out as I don't yet have working implementations with which to play. (hh) In the code there remains a significant number of conditional checks as to whether the interior is present ahead of running code for various features. Further, documentation / code comments are floating around suggesting interior blocks are optional - which is confusing. (ii) - You of course can, but, complicated games must be played. Knowing how the internal albedo 'big' phong and specular values are calculated you can get them into a more workable 0-1 range about a particular root, phong & phong_size / specular and roughness, setting about which you might twiddle. For example, supposing we want a baseline phong highlight of roughly: phong 0.5 phong_size 100 where we can scale phong_size via 'albedo' from 0+ to 200 with, with close to constant light in the highlight, we'd could use: phong albedo 1/100 phong_size <0+ to 200> A similar set up for specular : specular 0.5 roughness 1/100 would be: specular albedo 1/25 roughness <0+ to 1/200> (jj) IIRC. More recent PBR offerings have a special AA implementation specifically for highlights and, of course, smoothing of jaggies often happens in tooling via post-processing. Sizing, blurring, etc. (kk) - FWIW. The phong highlight hits a >1.0 response 2-3% earlier with respect to light intensity than specular highlights. (ll) - This true for negative phong and specular values too, but these are supported only in the povr branch as far as I know. (mm) - Every shape / surface having - and defining - an interior is problematic and why in povr I've been thinking about some kind of stand alone interior only set of shapes - ideally with it's own search hierarchy. For example, today, the interior fade related calculations are only correct where the interior regions are clean. Clean, meaning, clearly defined inside and rays traveling completely through the interior without any intervening surfaces. Aside: media handles intervening surfaces better so long as work ends up done with cleanly paired sets of intersections. (nn) - Ideas. Make albedo highlights without finish block fresnel a warning or error. Start generating warnings on dual use of phong and specular. Using both is useful for certain effects (especially, if allowing negative highlight values as in povr), but it's not common. Using both accidentally happens more often with v3.8's albedo re-specification for size due having to repeat the whole phong or specular specification with the new size. Related, some easier way to respecify just size would be welcome. In povr this can be done with just 'albedo roughness ' or 'albedo phong_size '. If the parser sees a finish block fresnel on and the IOR is 1.0, perhaps a warning. (oo) - Even with reflection in the finish, there are situations likely to cause trouble. For example, if one is using any alpha transparency (+ua) with the background/sky_sphere. A scene containing sphere with no_image, but still reflection? I don't know - we cannot reflect what isn't yet there. Maybe an aoi pattern increasing transparency at the edges... I don't know. (pp) - Thinking here where modeled surface effects are already accounting for the roughness/phong_size - size of any highlights. I see this is a complication with highlights in general, but, in particular I cannot see how constant light intensity aspect of the albedo highlights works in a consistent manner with other than very smooth surfaces. (qq) - This of course changes the diffuse contribution underneath, say, highlights. The aim I take to be more a more consistent overall 'brilliance' effect and this I believe it achieves at some cost to understandability of other finish effects. (rr) - Highlights, extreme brilliance effects, more extreme fresnel effects - many finish block elements, are very sensitive to the effective render size. The ray sampling size. The problem is not dissimilar to issues around rendering fine details at distance - the aliasing effects caused by how rays miss or hit certain features. This a reason in povr why AA jitter for methods 1 and 2 are again truly random. Further that povr supports big jitter values (>1 jitter values) so the randomness covers the entire pixel size and not an ever shrinking sub grid. To a degree we cannot model certain localized finish effects well, unless, we shoot a lot of somewhat random rays. It's just how it is. There are reasons Norbert Kern renders large; getting better finish effects is one of them. (ss) - Spectral rendering fits here, but our current high dynamic range file formats - as used by Ive's spectral rendering demo technique - or as we need for other image file defined, high dynamic ranges are not 'bit-deep' enough. -----------------------