Material representation back
Board: Board index ‹ Ray tracing ‹ !Real time ‹ Off-line
(L) [2008/09/11] [Thammuz] [Material representation] Wayback!Hi,
I'm currently doing a complete overhaul to my renderer, and I'm a bit stuck now. The problem is that I'm not quite sure on how to design the material (or well, surface properties) portion of it. I'd like materials to be represented in a somewhat realistic and general way , and also, I'd like to be able to do the path integration irrespective of the material properties.. i.e, the material properties "decide" the course of events (diffuse scattering, reflection, refraction, absorption etc), and the integrator gets the new direction, the pdf for it and happily continues. The way I represent my materials now is that a material has a color, a brdf/btdf, and a specular and a diffuse coefficient (basically to be able to decide whether to randomly scatter, reflect or absorb it). However, this model feels limited and I'm just not happy with it. Any ideas, or is there a "state of the art" way of going about this?
(L) [2008/09/11] [greenhybrid] [Material representation] Wayback!I do not know if there is an state of the art, so anyone from the Academic Alliance?
Anyways, I have had a similar question once: [LINK http://ompf.org/forum/viewtopic.php?f=10&t=899 viewtopic.php?f=10&t=899]
(L) [2008/09/11] [dr_eck] [Material representation] Wayback!>> a material has a color, a brdf/bsdf, and a specular and a diffuse coefficient (basically to be able to decide whether to randomly scatter, reflect or absorb it)
Huh? What does your bsdf do if it doesn't tell you how to reflect/scatter the light?  My BSDF class has methods for reflection and transmission to give three things: hemispherical reflectance(transmittance), directional reflectance(transmittance) and output ray direction (transmitted or reflected).  It's a lot like the one in Pharr & Humphreys' "Physically Based Rendering", but I have not included their texture capabilities because all of my surfaces wil have only a single color/bsdf.  The advantage is that I can skip all of the ray differential apparatus.
Here's my class:
Code: [LINK # Select all] class BSDF
{
public:
BSDF(void);
~BSDF(void);
// Is this BSDF specular?
virtual bool IsSpecular() const = 0;
// Return the average reflectance
real AvgRefl() const {return R.Avg(); }
// Return the average transmittance
real AvgTrans() const {return T.Avg(); }
// calculate the reflectance at a given angle of incidence, given by its cosine
virtual Spectrum CalcR(const real cosT, const real mu=1) const = 0;
// calculate the transmittance at a given angle of incidence, given by its cosine
virtual Spectrum CalcT(const real cosT, const real mu=1) const = 0;
// return a sample reflected ray, given the incoming ray & the normal
virtual Ray SampleR(const Ray& wi, const Vec3& n, real mu=1) const = 0;
// return a sample transmitted ray, given the incoming ray, the normal
virtual Ray SampleT(const Ray& wi, const Vec3& n, real mu=1) const = 0;
// return the BRDF for this (incoming, normal, outgoing) triplet
virtual Spectrum BRDF(const Vec3& vi, const Vec3& n, const Vec3& vo, real mu=1) const = 0;
// return the BTDF for this (incoming, normal, outgoing) triplet
virtual Spectrum BTDF(const Vec3& vi, const Vec3& n, const Vec3& vo, real mu=1) const = 0;
// data members
public:
BSDFType bt;
Spectrum R; // spectral reflectance of surface
Spectrum T; // spectral transmittance of surface
};
(L) [2008/09/12] [Thammuz] [Material representation] Wayback!Thanks for your swift answers! I had a look through the thread you posted, and it gave me quite a few new ideas on how to go about this, thanks. Also, it really (really) seems as though I need to get myself the PBRT-book, as I've seen it mentioned on these forums tons of times. Up until now, I've been working a lot off of the  "Advanced Global Illumination" book and papers online.
dr_eck: Thanks for the code you posted, neat design (I might do something along those lines)! And as for you question, well, the problem is that I don't have a bsdf-class per se, the functionality is smeared out all over the code base...hence the re-design and consolidation of the material handling. It really sucks as it is now, but that's what happens when you  shoe-horn an MC path tracer into old (really old) ray tracing code [SMILEY :wink:]
(L) [2008/09/23] [derethor] [Material representation] Wayback!i believe that working with realistic materials must be stadistical.. something like "20% lambert, 30% specular, etc"
probabilities, sampling, etc must be included in the simplest material description
(L) [2008/09/23] [dr_eck] [Material representation] Wayback!I suspect that what you mean is that every surface has some amount of specular reflection and some diffuse scattering.  If my suspicion is correct, then we agree.  However, it is sometimes important that one be precise about how the amounts are calculated and how the transition from specular to diffuse is handled.  If you want to learn the details about this, read Chapter 2 of Jill Ogilvy's "Theory of Wave Scattering from Random Rough Surfaces".  In short, the BSDF of a surface is proportional to the power spectral density distribution, which is the Fourier transform of the surface autocorrelation function, which is  (obviously  [SMILEY :roll:] ) the autocorrelation of the surface height distribution function.  Ogilvy does a reasonably good job of explaining this, but it doesn't hurt to have some background in linear systems theory.
The cool thing (at least to a physicist) is that every surface that I have measurements for behaves like a fractal when you are far from specular.  This is neat because it provides confirmation regarding the applicability of fractals to a wide variety of surfaces.  It also means BSDF functions like Blinn, Torrance-Sparrow, and Owen-Nayar are all wrong because they assume a Gaussian autocorrelation function rather than power-law which is associated with fractals.  Phong is, of course, also wrong.  This is not to say that any of the aforementioned functions is useless, they just do not provide close correlation with measurements.  (Note: for completeness I should mention that O’Donnell & Mendez did fabricate a surface with Gaussian autocorrelation by illuminating photoresist with laser speckle and then processing it - definitely not a natural surface.)
One can approximate natural surfaces with fractals, but this also runs into problems in the near-specular regime.  As it turns out, fractals posit self-similarity at all scales while nature tends to fall away from this behavior at sufficiently small scales.  Think, for example, of rounded mountain peaks due to weathering or snowfall.  Palasantzas, in his "Roughness spectrum and surface width of self-affine fractal surfaces via the K-correlation model", gives a good theoretical underpinning to a function that matches my experimental data very well.  The function is BSDF(x) = A / (1 + (B sin(x))^2 )^C, where x is the angle between the observation angle and the specular one.  You can vary C from 0 (Lambertian) to ~4 for surfaces with a very steep falloff.  You can also vary B to locate the transition from specular to diffuse.  Finally, A is determined by the hemispherical reflectance of the surface.
I may write a paper on this and provide sample code and tabulated coefficients for measured materials sometime in the next few months.
(L) [2008/09/23] [ypoissant] [Material representation] Wayback!I'm also into material representation lately. My take right now, is that I need to be able to represent multiple layer material because there are just too many material types that are multilayer in the real world. One paper I found interesting regarding this is "[LINK http://www.cg.tuwien.ac.at/research/publications/2007/weidlich_2007_almfs/weidlich_2007_almfs-paper.pdf Arbitrarily Layered Micro-Facet Surfaces]". It is not physically correct but physically plausible. But it surely shows that even using empirical BRDF models, when they are arranged in multilayers, one can get very believable surfaces.
(L) [2008/09/24] [cignox1] [Material representation] Wayback!I've also spent a few days thinking about it. I liked the elegance of the pbrt method, but it restricted too much to phisical based rendering ad was not suitable for more 'artisitc' materials. In addition it require the allocation of new object and I'm too lazy to spend days for a CMM where I still have to implement a spatial subdivision scheme [SMILEY :-(]
Currently I'm simlpy calling Evaluate(REFLECTION_TYPE), but I don't know how this would work with SSS or GI... I will reconsider my current design later, when I will have at least a model loader and a BIH working!
Edit. I've given a look to the layered paper posted above and it looks indeed very nice. What other models are aou there (I've already a couple of papers) and wich ones do you use?
(L) [2008/09/24] [greenhybrid] [Material representation] Wayback!>> cignox1 wrote:spend days for a CMM
not too hard. basic:
Code: [LINK # Select all]T = <your type>;
char bytes [<requested number of elements> * sizeof (T)];
T *my_array = reinterpret_cast <T> (bytes);
// then: placement new
T *brdf_a = new (my_array+0) T;
T *brdf_b = new (my_array+1) T;
// or:
T *brdf_c = new (bytes + index * sizeof (T)) T;
// or:
T *brdf_array = new (my_array) T [666];
// etc.
This means you can alloc (nearly) everything on the stack. You don't have to call the destructor if you know what you do, but if you want to you have to do it explicitly:
Code: [LINK # Select all]brdf_a->~T();
// or
for (int i=0; i<666; ++i) {
brdf_array [i].~T();
}
DO NOT USE c++-delete on placement-new'ed data (of course you can new/delete the memory in which you want to place your instances)
(just as a sidenote: CMM is not an official abbreviation, I just used it in that context [SMILEY ;)])
(L) [2008/09/24] [cignox1] [Material representation] Wayback!Thank you greenhybrid, but I don't really get how should this solve the problem: I cant return this pointer to the caller, because a subsequent call to a function would overwrite that memory, or am I missing something?
I suppose that I would need a memory pool or something, but there are issues with multitasking and so on, so I'll stick with this for now.
By the way, I already heard CMM applied to this contex, so you're not the only one to use it [SMILEY :-)]
Thank you!
(L) [2008/09/24] [ypoissant] [Material representation] Wayback!>> cignox1 wrote:Edit. I've given a look to the layered paper posted above and it looks indeed very nice. What other models are aou there (I've already a couple of papers) and wich ones do you use?
I don't use any in particular but my current implementation uses layered Schlick practical BRDF except that the "merging" of the top layer with the bottom layer is controled by the Fresnel term which is more realistic than a simple a priori weighting as suggested by Schlick.
Other papers along the same vein are:
"Distribution Based BRDFs" by Ashikhmin, Premoze, 2007;
"Real-Time Rendering of Objects Coated with Multilayer Thin Film" by Iwasaki, Ueda, Omoya, Takagi, 2007;
"A Simple Layered RGB BRDF Model" by Granier, Heidrich, 2003;
"A Microfacet Based Coupled Specular-Matte BRDF Model with Importance Sampling" by Kelemen, Szirmay-Kalos.
Then, if you follow the references from these papers, you are on a very good start.
A very good discussion of material appearance is the latest SIGGRAPH course notes "Advanced material appearance modeling" by Dorsey et al. It is one thing to get the BRDF(s) representation right but it is another to understand what makes BRDF(s) look the way they look in the real world.
(L) [2008/09/25] [greenhybrid] [Material representation] Wayback!>> cignox1 wrote:I cant return this pointer to the caller, because a subsequent call to a function would overwrite that memory, or am I missing something?
Depends on what you do. You could allocate some bytes on the *heap* by using some malloc(), then placement new something in, and return thy instance. Just an example. But yes, if you have a char-array on the *stack* that you use for the placement new, then any access to that space after leaving the scope of the char-array, you are doomed [SMILEY :)]
 >> I suppose that I would need a memory pool or something, but there are issues with multitasking and so on, so I'll stick with this for now.
Indeed. The good thing *would* be that you could optimize it on your usage pattern (linear growth to some known limit, e.g. -> no need to keep an 'acceleration structure' in the pool to bookkeep free and allocated memory; such a pool would be very compact wrt LoC, btw (at least for a non-threaded environment, but that should not be a big problem when you are in read-only mode)).
 >> By the way, I already heard CMM applied to this contex, so you're not the only one to use it
Thank you!
Ah, okay, I didn't know. And of course: Immer gerne [SMILEY :)]
(L) [2008/09/25] [cignox1] [Material representation] Wayback!@ypoissant: Thank you very much. I'll give a look to those papers
@greenhybrid: Danke shön, ietzt muss ich einen BIH schreiben (ich habe noch nicht begonnen), dann werde ich über MM denken  [SMILEY :-)]
(L) [2008/09/25] [toxie] [Material representation] Wayback!BIH for teh win!  [SMILEY :)] [SMILEY :)]
back