Water drop 3b – Physically based wet surfaces

Version : 1.3 – Living blog – First version was 15 avril 2013

This is the third post of a series about simulating rain and its effect on the world in game. As it is a pretty big post, I split it in two parts A and B:

Water drop 1 – Observe rainy world
Water drop 2a – Dynamic rain and its effects
Water drop 2b – Dynamic rain and its effects
Water drop 3a – Physically based wet surfaces
Water drop 3b – Physically based wet surfaces
Water drop 4a – Reflecting wet world
Water drop 4b – Reflecting wet world

Directly following the part A let’s continue with other rain effects:

Approximation for game

We have begun this post by studying the influence of water on lighting for wet surfaces. Then we have seen two real time implementations with analytic light for both optical phenomena which were inherited directly from the observation. They have some drawbacks, they miss an image based lighting implementation and their cost for in-game usage still a problem for XBOX360/PS3 game. In computer graphic there is a different path available to simulate optical phenomena other than changing the lighting model. We could simply create/edit/capture both wet and dry surfaces BRDF parameters (diffuse, specular, specular power…) with the same lighting model. This is not really a “simulation” as we know the final wet state of the surface but we are now able to render wet surfaces and to dynamically wet our game world. Simply interpolating between dry and  wet BRDF parameters without changing the lighting model do the effect. Nevertheless this approach is stuck to the subsurface scattering events inside the wet material and its top, i.e the diffuse and specular of the wet surface itself. It will not allow to simulate the dual layering lighting we have study in part A when there is a thin layer of water on the top of the wet surface. I will discuss this point later.

The benefit is the simplicity of the process and we still compatible with any kind of lights: image based lighting and analytic. The drawback of requiring a dry and a wet set of BRDF parameters by surfaces is the time to author and store them. The wet lighting model approach required more instructions whereas this one require only few extra instructions (but this still two textures fetch for the blending). However in game development, doubling the storage in memory/disc space and the number of textures to author is prohibited. Hopefully we now know that’s we can express both wet and dry surfaces with the same lighting model, so maybe we can find a way to tweak the dry BRDF parameters to get an approximation of the wet’s one and thus avoid the inconvenient of storing and authoring new textures.

Almost all games I know chose to follow this  BRDF parameters’ tweaking path : Stalker [12], Uncharted 2/3 (on the main character), Assassin’s creed 3 [13], Crysis 2/3, Metal Gear Solid V [15] etc… This is not surprising as the method seems simple and it fit very well with a deferred shading renderer: You can tweak dry BRDF parameters in the G-buffer without complicating the lighting systems. However the wet BRDF parameters generated by these games are either coarse or wrong approximation (in a physical sense, I am agree that’s visually the look can be Ok). Most use the same eye-calibrated factors to attenuate diffuse and boost specular (old fashion) on every wet surfaces of the scene regardless of material properties (roughness/smoothness, porosity, metalic/dielectric…). Assassin’s creed 3 even does an additional wrong step by changing the strength of the factor based on the type of rain. Remember from part A that under any type of rains a porous surface can be water saturated. This only depends on  water precipitation volume and exposition time. A bit differently Tomb Raider : A survivor is born [14] use “dark light” to attenuate the light receive by the diffuse part of the wetted surfaces, the specular part is modified as other games. As they use lights to produce rain with a light prepass renderer, I think they intent to make up the missing of a diffuse parameter in the small G-Buffer with this method. Which again apply wrongly the same modification factors on all dry surfaces.

One of the purposes of the remainder of this section is to improve the BRDF wet parameters generation from the dry one. I want to highlight the benefit of PBR for this parameters generation. I will begin by talking about the tweaking of the diffuse (or subsurface scattering part) and the specular parameters for porous dielectric material then for other kind of materials. I will end with the effect of the thin layer of water which can accumulate above surfaces and the case of thick accumulated water like puddles.

Porous dielectric material

Disclaimer all color values I will talk about are in RGB linear space, not sRGB space. All graph show here are available in a Mathematica file at the end of this section.

We aim to found a factor which can be applied on a dry diffuse parameter to get a wet diffuse parameter and equivalent for the glossiness parameter. I will begin by an overview of previous works, they are all focus on rough dielectric material.

For asphalt in driving simulator, Nakamae et al [2] use a factor between 0.1 and 0.3 to attenuate the diffuse albedo and a factor of 5 to 10 to boost the specular (not PBR). As many other, they perform an empirical calibration for this coefficient without taking into account the properties of the surfaces.

[3] and [16] details the two optical theories that’s we see in this post (part A)  which aim to explain the darkening of the albedo. We will call the model of [3] LD and the model of [16] TBM. I would advice that’s the albedo mention in this paper don’t match the diffuse albedo definition we use in computer graphic (i.e the diffuse color of a perfect lambertian surface), it contain some specular reflection. Both papers purpose a relationship between wet and dry albedo. They explain that’s the highest differences between wet and dry albedo occurs for surface in the middle range of dry albedo. Dark surfaces will tend to absorb more light on first contact with the surface, the contribution of internal reflections will be less important  decreasing the effect of wetting. Bright surfaces will tend to reflect much more light than is absorbed by internal reflection also decreasing the effect of wetting. In both case the relationship between dry and wet albedo depends only on the  index of refraction (IOR) of the surface, the IOR of the water and the dry albedo. The following graph is the wet albedo function of the dry albedo from the optical phenomena of [3] for an IOR of 1.5 for surface (common value for rough dielectric surface) and 1.33 for water. The red line is the dry albedo for comparison:

WetDryAlbedo2

I found more readable to transform this graph to the fraction of wet / dry albedo function of albedo. This means the factor to apply to dry albedo to retrieve wet albedo:

WetDryAlbedo3
A good comment about these graphs is done in [6]:

They further show that the wet albedo is a non-linear function of dry albedo, with low albedos reduced more by wetting than high albedos. A consequence of this result (not explicitly stated in their paper) is that wet surface color is more saturated than dry surface color, because the wetting further exaggerates the differences in albedo for different wavelengths.
Source [6]


If we take the example of a dry worn asphalt surface of 0.12 albedo, using the second graph we get the factor of 0.68 allowing retrieving the wet value of 0.08. (In Photoshop sRGB this transforms 97 to 81).
For very low albedo ( < 0.039), the curve goes above 1.0 (Not show on the graph). This is probably because water albedo (pure water is 0.02 at normal incidence, but orientation and impurity should increase it) is greater than these low albedo values causing a brightening of the dark surface.
Remark instead of converting from dry albedo to wet albedo, it is possible to go the other way and use wet albedo to get dry albedo like detailed by [4].

End of the story ? Well not. I have few remarks regarding the wet and dry relationship in LD and TBM. There are really few measurements taken into account in their works. Even if the two models are close (that’s why I don’t show [16]), both works focus on different materials: [3] seem to apply best to rough solid surfaces, such as blackboards, asphalt, or concrete; [16]  seem to apply best to finely divided media, such as sand. My main concern is that be based solely on albedo and IOR properties of a surface is not enough. We see previously that’s porosity is an important factor and the roughness is certainly involve. Other work seems to go in this way. In [17] it is show that’s individually both previous model cannot simply describe all the measurements done. Here is a dry/wet relationship graph of 6 natural sediments. The prediction of the LD model is the solid black line, the TMB model is the dashed line. The different shape plots are the individual measurements:

WetDryAlbedo4

Source [17]

The paper in [17] highlight that’s both model should be taken into account (In fact, that’s what we have describe in part A of this post) and two parameters should be added: fraction of translucent particles (quartzlike particles with a low absorption coefficient and low internal scattering) and microscopic roughness. The difference between dry and wet albedo increases with increasing translucent particle concentration. And a rough surface will scatter light more diffusely than a smooth surface, if a thin layer of water is present on top of it, there will be more hits of the water air interface at larger angles causing more internal reflection and increasing the darkening effect. So the LD and TBM model aren’t sufficient. We also require to have a separate factor for diffuse and specular part but the albedo here contain both, suggesting that’s the diffuse factor could be more than the minimum 0.68 of LD model.

Other works have gathered a set of real world measurement of dry and wet materials available publicly [5][8]. In [8] Gu et al. have measured the drying process of several materials. They have registered images at different time interval for different views and lightings configuration. To be able to transfer and control the captured drying process in rendering applications, they have fitted measured BRDF to parameters of a Torrance-Sparrow BRDF (A microfacet BRDF). To be clear, they have been able to generate a diffuse component (exactly what we are looking for) and a specular component (roughness + specular reflectance) to simulate the drying process with one physically based lighting model as used in game.

I have downloaded part of the database provide with [8]. The textures of the database name Kd are the diffuse textures in a game engine. Ks and roughness sigma are the specular part which match old game lighting equation (i.e specular is not normalized and intensity and shape side are not coupled. Sigma can be convert to specular power with formula see in part A of this post). I extract many info from this database that’s I show on the figure below. There is the fitted Kd textures fully dry (left picture) and fully wet (right picture) captured during the drying process. Then there are two relationship graphs: wet function of dry albedo (First graph) and wet/dry albedo function of dry albedo (second graph) for each RGB channel. Black line is the dry reference line. I also plotted a histogram of the image for albedo (Third graph) and for the roughness sigma (Fourth graph). Texel’s albedo is taken into account only when there is at least 10 occurence of it inside the texture to reduce noisy data. To draw the wet/dry albedo I take the mean of every pixel with the same dry albedo. Number in the material name refer to the sample number in the database, textures are in sRGB (graph values are in RGB):

(Click for high res)

CompareDryWet

All materials of the database are rough dielectrics. The first thing we remark is that there is no real pattern and the darkening is color channel dependents. The diffuse albedo values are high compare to the one present in LD and TBM works because they are not normalized (divide by PI) (see Torrance-Sparrow BRDF section 4.2 of [8]). The range of the diffuse factors (second graph) is also higher than for LD and TBM: From 0.2 to 1.0. The reasons for this may lie in the fitting process, the absence of specular (LD and TBM albedo include specular),  the calibration of the capture devices… For low albedo (if we divide by PI, around 0.02), we have value going above 1 (clip on the graph here) showing a similar behavior of LD and TBM model. We note that’s some wet materials can be simulated by simple RGB uniform scaling, for example Wood Drying 29 wet albedo can be get by applying (0.82, 0.58, 0.38) on the dry albedo, but most materials have variation. I should advice that’s the method I use to compare materials make sense only if most of wet / dry ratio are equals, but there is a large standard deviation around the mean for the rock and the brick material so result must be taken with care. Other materials have a standard deviation < 0.1. So we don’t see clear pattern as in LD and TBM model but as said the albedo definition here is different.

We see before that’s the darkening effect is linked to roughness of the surface and other properties, that’s why I include the roughness histogram. You may remark that’s a material with similar histogram of roughness and albedo like rock drying 20 and granite drying 37 still have different factors. This may suggest that’s they have different porosity which are not included in this study. In order to see if we can link specular and diffuse factors I plot the graph of the ratio Ks wet/ Ks dry function of Kd dry (second graph) and sigma wet / sigma dry function of Kd dry (third graph). Ks and roughness sigma are decoupled in this model (compare to modern normalized specular). For roughness, less roughness mean more specular. What we expect here is to have value ratio Ks above 1.0 and value for ratio roughness sigma below 1.0 (as smaller roughness mean more concentrated reflection, so smoother) but on these measurements, this is not always the case :

(Click for high res)

CompareDryWet3

We have materials here which behave as expected: see granite drying 37, rock drying 20 or wood drying 29. Wood drying 29 is the one show in [8] for most of examples. But strange enough, some materials seems wrong, like light wood 2 23 and green cloth 30 which are less specular when wet than when dry. I can’t explain the reason of this… Regarding the shape of the curve of Ks or sigma, it seems that there is often one of them which are similar to the shape of the curve Kd. This remind the wet porous material BRDF (Part A of this post) which suggest that’s the diffuse porous part should be change to a specular water lighting contribution when wet. From this observation, I suggest to reuse the factor use to darken the diffuse to modify the specular.

Let’s see if we can get other information from the database [5]. In this database the data are similar except they are no spatially varying (mean you don’t have textures but a single value instead). Here I download the data, then write the name of the material, the dry diffuse color of the material, the wet diffuse color, the ratio wet / dry and the roughness sigma (similar to database [8]). The two color squares are the color of Dry and Wet. A roughness of “-” mean no data available:

CompareDryWet2

The database is fitted with Oran-Nayar instead of perfect lambertian BRDF for the diffuse but I am not showing the diffuse roughness here. Again the data show the channel dependant factor and the large range of the factor (0.38-1). There is also value of diffuse color which goes above one and sigma value not available, this may related to the method of analytic BRDF fitting employed in this paper.

To conclude with these databases, my point of view is that’s they miss important information to better understand the relationship between dry and wet material properties: the nature of the surface. Having the measured porosity and roughness of the surface would have been useful information. The deduced roughness resulting of data fitting is not really accurate. Moreover, this should be fit to normalized specular term to be more meaningful. If interested here the Mathematica file pdf containing all the graph above : TimeVaryingAppearance.pdf and here is a package containing the C++ program (visual studio 2008 runtime) allowing to extract all information from exr image of the databases with some batch and the Mathematica notebook:ExtractInfoExr.pdf (As WordPress do not support zip file you must right click, save as… then rename the .pdf as .zip).

Coming back to game development, what can be done ? We now know that’s low albedo, rough and porous materials tend to have larger wetting effect. We also know that’s high albedo, smooth material or no porous tend to be less affected by water. The handling of different varying factor by channel color with a curve similar to LD or TBM could be a little costly. We will stuck to monochromatic factor here to reduce the storage cost (and in several case it is sufficient) and we also won’t use albedo dependent factor because the curves handling even simplified add too many instructions. Anyway, if you use physical albedo value for your physically based lighting model, you should rarely have extreme albedo, remember that’s darkest material is 0.04 (charcoal) and brightness is 0.9 (snow). It is simpler to just rely on roughness and porosity.
As explain in part A, roughness and porosity should be considered as two invisible micro-geometric features. But roughness and porosity for some material seems correlated. In [19] it seems that’s in the specific case of rock there is a linear relationship but we can’t generalize, other paper demonstrate a non linear relationship. But sometime rough surfaces can be not porous (Vinyl, leather, textured surface, fired ceramic (porcelain…), some kinf of glass, rough metal…). In the abscence of enough work on this part, for our context of game development with the material we usually used, we will just rely on this intuition that’s we can link porosity and roughness when we can’t afford a dedicated porosity parameter. I suggest few options compatible with performance and artists control to get an approximation of a wet material from a dry material:

1. With a porosity scalar
In this case we have a porosity textures which go from 0 for no porosity to 1 for “full” porosity. The porosity is a grey texture which can be include in a free channel of any texture at low resolution. The meaning of the porosity parameter here is not really physical as we are not using any porous BRDF. This is instead the strenght of the factor we want to apply to the dry albedo. The texture should be authored by artist, best could be to take calibrated albedo texture [18] from the wet and dry surface, then use the ratio as porosity but in this case we come back to our original problem of authoring time. Another prefered way for production could be to start from the gloss texture and then removing all smooth values then blurring and tweaking. Smooth part can’t be porous by definition. Note that’s porosity can vary in a noise-like pattern between location [11], similar to glossiness. If more physical porosity is required for other aging or weathering effects, a simple remaping from 0 .. 1 to 0 .. 0.5 (50% porosity) could be sufficient.
For our calculation, we will use a diffuse darkening factor on the dry diffuse and as suggested we will reused this factor for the specular boost. About the specular boost, with a physically based lighting model we only require to tweak the glossiness. The normalized specular automatically handle the increase of reflection with the reduced shape of the highlight. The use of a preconvolved cubemap chain indexed by glossiness allows to automatically adjusting the water reflection. The change in specular color (i.e the index of refraction) induce by the water saturation is not visible enough in game to be take into account (we go from 0.04 for common dielectric to 0.02 for water).

Taking the DoWetProcess() function of the RenderMonkey application of Water drop 2b – Dynamic rain and its effects we get:

void DoWetProcess(inout float3 Diffuse, inout float Gloss, float WetLevel, float2 uv)
{
   float Porosity = tex2D(GreyTextures, uv).g;
   // Calc diffuse factor
   float factor = lerp(1, 0.2, Porosity);

   // Water influence on material BRDF
   Diffuse    *= lerp(1.0, factor, WetLevel); // Attenuate diffuse
   Gloss      = lerp(1.0, Gloss, lerp(1, factor, 0.5 * WetLevel));
}

We begin by first determine a diffuse attenuation factor. We lerp between no attenuation (1.0) and full attenuation (0.2) based on porosity. The glossiness is indirectly taken into account as its effect has been merge in the porosity texture at author time. The 0.2 is chosen base on the range found in the database [8] and on the choice of 0.3 in [2]. Porosity have a direct influence on the darkening, allowing the artists to fine tune the result if needed.  Once we get the diffuse factor we apply it on the dry diffuse. The lerp with WetLevel allow a smooth transition. We then reuse this diffuse factor to get a blending weight between the material gloss and the water gloss. As water is smooth, we use 1.0. I use a factor of 0.5 on WetLevel to limit the specular boost. This is rather empirical as I couldn’t extract a good specular factor from the databases. Here is sample result with WetLevel set to 1, from left to right: Porosity 0, porosity 0.25, porosity 0.5, porosity 0.75, porosity 1.0, textured porosity (the texture is show below):

(Click for high res)

FactorWithPorous

TX_Porosity

2. With a porosity mask

Adding a new porosity texture may not always be possible and this require to author an additional texture. In this case I suggest a coarse approximation based on the correlation between roughness and porosity. By using a porosity texture mask, artist can control the wetting effects on materials. We modulate the porosity mask with the gloss texture to control the porosity intensity. For example in my case we store the porosity mask within the alpha channel of the specular (index of refraction) texture and compress in DXT1a. The specular don’t suffer from the more aggressive compression and is low resolution:

float Porosity = tex2D(specular_texture, uv).a * saturate(((1-Gloss) - 0.5)) / 0.4 );
// Calc diffuse factor
float factor = lerp(1, 0.2, Porosity);

The glossiness should affect the factor only if rough and can have a linear decrease with lower roughness. I remap glossiness with equation ((1-Gloss) – Start) / (Start – End) to control this. Start and End depends on the glossiness convention and the glossiness range of your engine. Start should be the value where a surface can be considered to be too smooth for water to penetrate inside it and End the value where the surface is so rough that’s we consider it fully porous. In my case, gloss is 1 for smooth with a range of 1-2048. The above code gives the following left graph. The right graph shows the conversion from Glossiness to Specular Power as reference.

SimpleRemapingHere Start is equal to 0.5 mean a specular power of 45 (or a RMS slope of 0.2) and End is equal to 0.1 meaning 2. The remap can be written in a single mad_sat in all case, here I get: saturate(-2.5 * Gloss + 1.25).

3. Without porosity

In this case a simple coarse approximation is to use the glossiness parameter only as remaped above. Artists will not be allowed to control which surface are affect by the wettings effect (So rough non-porous material like leather will be affect even if it should not) but comparing to applying the same factor on everything (include metal see after) as most game do this is already an improvement:

float porosity = saturate(((1-Gloss) - 0.5)) / 0.4 );
// Calc diffuse factor
float factor = lerp(1, 0.2, Porosity);

Metallic and smooth material

As see in part A of this post, porous/rough materials have subsurface scattering event causing the darkening of the surface. Such event doesn’t happen with smooth or metal material. There is some hand crafted powdered metal material which are porous but we don’t care about them here. So the only work we need to do regarding the darkening effect is to ignore it. We already handle smooth material in previous paragraph as we use the glossiness to generate the porosity. Here we just need to have metalness in the equation:

float factor = lerp(1, 0.2, (1 - Metalness) * Porosity);

Metalness is a set to 1 for metal material and 0 otherwise. In the case of storing a grey porosity texture, the metalness can simply be merge in it. As we use physical values in our lighting model, if you don’t have a metalness parameter you can deduce it from specular value (index of refraction value). In fact we know that’s metal have high specular values ( > 0.5), so a simple formula can be use:

// dot, mad_sat
float Metalness = saturate((dot(specular, 0.33) * 1000 - 500) )

The dot instruction allows handling case like gold metal (1, 0.76, 0.33). Note that’s this will also cancel the specular boost which is what we want as the smooth specular in this case come from the thin layer of water.

Thin layer of water and puddles

When porous material is water saturated or when we have a smooth or metal material, a thin layer of water accumulates on the top of the surface. This layer could not be simulated by tweaking BRDF parameters and require a dual layer BRDF. But as we see, a dual layer lighting model is expensive. Jensen et al. in [1] have implemented a lighting model with the subsurface scattering and the thin layer of water linked to wet surfaces and they have found that’s the consideration of water inside material have the more dramatic effect. The subsurface scattering is the most significant reason why materials are darker when wet (And the subsurface scattering allow rendering the increased translucency of thin materials caused by the absorption of the water (like paper, cloth)). So for rough/porous material handling double layering is not really needed. And for metal/smooth material we have seen that’s the absorption of the water, the refraction and the total internal reflection have not an important impact for such a thin layer of water. This doesn’t mean we will do nothing.

In Water drop 2b – Dynamic rain and its effects I have describe a system to simulate puddles by smoothly blending normal map and vertex normal. We can reuse this system to get both the thin layer of water and the puddles. See this picture:

Dualpuddles

When we have a thin layer of water we still have a reflection corresponding to a disturbed normal from the underlying surface. For thick layer like the puddle on the manhole we have a perfect reflection coming from flat normal. Thus using a progressive blend between normal map and vertex normal can provide visually correct result for increasing height of the water layer.

I will not provide code for this post as the RenderMonkey application of Water drop 2b – Dynamic rain and its effects contain almost all the code we need. By replacing the code of the DoWetProcess() by the one of the previous paragraph we get our physically based wet surfaces rendering approximation. The AccumulatedWater variable of the code simulate both the thin layer of water and the puddles. By adjusting the heightmap/vertex colors values of the surface you may influence the size of the top water layer.

To sum up, reusing the region type give in [2] for this description:
– For wet region (type 2) we have the DoWetProcess() function which apply the PBR darkening of the diffuse and the specular boost.
– For the thin layer of water which can be considered as drenched region (type 3) we have a small amount of water in AccumulatedWater causing a slight smoothing of the normal and a slight boost in specular (smaller highlight, better reflection definition, increase in intensity).
– For puddles (type 4) we are totally flat and have blended to water properties.

The system describe here provide good results, is simple to implement and is suitable for XBOX360/PS3 games.

In Remember  Me as we ended with static weathering condition we have use only a small part of what was presented here. The rain being static we have created wet textures for everything. This is a gain in quality as artists have full control on the rendering and in performance. This is the morality of the story, fit your features to your game context.

Added note:

Additional nice picture of darkening of wet surface with highlight of the saturation are available in [7].

Angelo Pesce [20] already describes in one of this post a similar system for thin layer of water/puddle:

Water will have the same normals as the underlying asphalt if the water layer is thin, but it will “fill” asphalt discontinuities if it thick enough. That’s easy if the asphalt has a normalmap, we simply interpolate that with the original geometry normal proportionally with the water level.

During my research I have experimented the wetting process via the spectrum, here is some result. In [6] the spectral reflectance of a dry and wet stone has been measured and it has been show that’s the difference between the two is a simple shift (See part A of this post). I found two other papers comparing the spectrum of wet and dry surfaces [21][22]. In both paper the change could be seen as a mix of a shift and an interpolation with the water spectrum. Here is a spectrum of the drying process (each spectrum have an hour since wet) of a sediment of composite moderate carbonate:

SpectrumDrying

Source [21]

I have done a simple test to see if I can generate a good diffuse wet texture from a dry texture with spectrum manipulation. I use the Pbrt code from Matt Pharr [23] to convert from RGB to spectrum, apply a lerp or shift or both between the dry spectrum and a water spectrum (approximate as constant 0.02) then convert back to RGB. The weighting to apply is controllable. Here is a sample result with from top to bottom original texture, lerp with 0.4, shift with 0.1, shift with 0.05 with a lerp of 0.025

Spectrum-originalSpectrum-lerp04Spectrum-shift01Spectrum-shift005Lerp025
The lerp is too grayish, the shift a little strong but it bring the hue shift we are looking for. That’s why I try a mix between shifting and lerping. The last texture is not rather good. I have not push the test further but this could be an interesting way to quickly generate wet textures. However converting to spectrum still an unsolvable problem so result will never be correct.

If interested here is the application with the source code: SpectrumShift.pdf (As WordPress do not support zip file you must right click, save as… then rename the .pdf as .zip. C++ (visual studio 2010 runtime)). The application takes a factor for the shift, a factor for the lerp and any number of images in tga format. I add 4 textures above in the package.

Wetting/Drying

When managing dynamic rain, we also need to look at drying and wetting process.

The process of drying is more complex than it appears at first. In the observation post, we have seen some drying patterns. The drying process is non-homogenous :

Drying

Moreover the wet surface shows a spatially-varying reflection. When drying, the specular reflection disappears but the diffuse reflection still darker than the dry surface:

DryingSurface

A complete study of these phenomena have been done by Lu et al. [6]. The speed of drying differs between spatial location due to object geometry and shape of the wet surface. The drying is also linked to exposure to radiant energy source (Sun which imply a directional effect on drying, air temperature, exposure to fire…), air motion, gravity and gradients of the fluid within the porous material (the distance of any point on the surface from dry material has great influence). Lu et al. [6] have done an experiment by minimizing most of the above external factor to study the drying process. The first row is the drying surface and the second row show only the specular reflection:

DryingHistory2

Source [6]

Gu et al. [8] have also done a similar capturing process. Here is a drying piece of wood with time of capture (The light location on these shot move, the orientation is given above each step):

dryinghistory4Source[8]

Both experiment consider that’s there is no thick water layer on top of objects. We observe that’s specular reflection are initially strong then decrease in intensity as a function of the distance from the wet region boundary. The wet specular reflection goes away quicker than the wet diffuse reflection. Gu et al. [8] observe that’s specular decreases exponentially when drying. The wet regions boundaries also appear more blurry with time. Lu et al [6] use accessibility (convex parts dry faster than concave regions) and distance to the boundary as control parameters for simulate the drying. Different spatial locations evolve at different rate based on these parameters. In all case, the drying time function can be fit to a sigmoid function [6][8]. Here is a sample of fitting:

DryingHistory3

Source [6]

Gu et al. in [8] use measured data converted to two textures, a drying rate texture (left) and an offset texture controlling the start of the drying (right),  to simulate the non-homogenous drying speed. Here is an example for the piece of wood  from above:


DryingHistory5

Source [8]

Sun et al in [5] precise that’s the wet diffuse albedo is a more or less straight lines shifts in the color space of the dry diffuse albedo. And they provide the following formula to simulate wet material (which is the same formula used by [6] and [8]):

\rho_d(t) = \alpha(t).\rho_{d,dry} + (1 - \alpha(t)).\rho_{d,wet}

where \rho_{d,dry} and \rho_{d,wet} are the albedo of the material when fully dry and wet and \alpha(t) is the sigmoid function.

In game, it is obvious that’s we won’t go so far in the detail. A simple generic noise mask texture could be use with a sigmoïdale function or even a simple lerp to attenuate differently the wetness.

As stated in previous post, if the player can’t notice it there is no need to implement the effect. Using real world time values for drying process is useless (> 30 min). Basing the drying speed on weather condition (heat, wind..) has almost no chance to be noticed. Game could simply lerp quickly (1 min) to dry surface state without taking into account the specular exponential decrease. Special care need to be taken for thick layer of water on top of wet surface like puddle which should not dry as quickly as the other area. The RenderMonkey application of Water drop 2b – Dynamic rain and its effects implements such a drying with puddles.
Note that’s there is no real drying process for no porous material. The thin layer of water will simply evaporate.

The process of wetting is a little different as surfaces are almost instantaneously wet when they are hit by water. The main process which occur here depends on the water quantity receive by the surface which will determine the saturation of the porous material and the creation of a thin layer of water. I don’t find any computer graphic research on this topic.

Added note:

An interesting technique to generate wetting or drying effect is the “dynamic paint” tools from Blender. This can be use to generate dynamic wet map [9] or a start of a rain as show in this youtube video or this one.

There is an interesting paper on flow simulation going through a porous material [10].

In [5] there is a database of data fitted to a Torrance-Sparrow and Oren-Nayar BRDF (As in previous section but not spatially varying). Here is a plot of the data from this database allowing seeing the progress of the different parameter with time. Disclaimer, the x axis here doesn’t represent the time but the sample, so the real time dependent curve may be a bit warped:

(Click for high res)

DryingProcessDatabaseThis graph is available in the Mathematica file of the previous section. The roughness data are a bit odd so not all material have data.

Conclusion

We see many thing in this post helping to understand the physical process involve in the darkening and brightening of wet surfaces. Wet surfaces are really complex to get right and the complexity involve is difficult to master in the context of game development (dual layering, porosity, subsurface interaction…). I myself still don’t get all. Hopefully we see that’s we are not forced to construct a complex lighting model to get good wet surface feelings, simply tweaking BRDF parameters from dry material do the job. The main point I want to highlight is the great benefit of using a physically based lighting model with physically based values. From physical parameters you are able to identify the nature of surfaces. Useful information when you deal with procedural effect based on aging and weathering.

The takeaways of this post are:

– Darkening and specular are due to two optical phenomena
– The change due to water induce an increase saturation, a hue shift and a brightness decrease of the diffuse part and an increase smoothing of specular part
– Only porous material are affected by rain
– Example of complex lighting model to handle wet surfaces with dual layer/porous BRDF
– Few simple ways to handle wet surfaces by tweaking BRDF
– Using a physical lighting model with physical values allow to identify the nature of material
– Porosity is a parameter to consider for dynamic aging and weathering effect
– Drying process is a sigmoidale function, drying is non homogenous and wet specular vanish quickly compare to we diffuse

To conclude, this post has show me that’s current measured material miss important information like measured roughness and porosity. We need better acquisition process. Moreover, too few study have focus on the specular boost of wet surfaces. There still other subjects which have not be taken into account here. The translucency of material when wet (cloth, paper…) and more complex lighting for dual layering like rough coating.

Reference

[1] Jensen, Legakis, Dorsey, “Rendering of Wet Materials”, http://graphics.cs.yale.edu/julie/pubs/Wet.pdf
[2] Nakamae, Kaneda, Okamoto, Nishita, “A Lighting Model Aiming at Drive Simulators”, http://dl.acm.org/citation.cfm?id=97922
[3] Lekner, Dorf, “Why some things are darker when wet”, https://www.victoria.ac.nz/scps/about/staff/pdf/darkerwhenwet.pdf
[4] Mall, Lobo, “Determining wet surfaces from dry”, http://www.vision.eecs.ucf.edu/papers/wet_dry_iccv.pdf
[5] Sun, Sunkavalli, Ramamoorthi, Belhumeur, Nayar, “Time-Varying BRDFs”, http://www.cs.columbia.edu/~belhumeur/journal/tbrdf-tvcg07.pdf
[6] Lu, Georghiades, Rushmeier, Dorsey, Xu, “Synthesis of Material Drying History: Phenomenon Modeling, Transferring and Rendering”, http://graphics.cs.yale.edu/julie/pubs/Drying.pdf
[7] Blevins, “Wet Looking Materials “, http://www.neilblevins.com/cg_education/wet_materials/wet_materials.htm
[8] Gu, Tu, Ramamoorthi, Belhumeur, Matusik, Nayar, “Time-Varying Surface Appearance: Acquisition, Modeling and Rendering”, http://www.cs.berkeley.edu/~ravir/papers/tsvbrdf/
[9] Hämäläinen, “Blender dynamic paint guide”, http://www.miikahweb.com/en/articles/dynamic-paint-guide
[10] Lenaerts, Adams, Dutré, “Porous Flow in Particle-Based Fluid Simulations”, http://graphics.cs.kuleuven.be/publications/PFPBFS/PorousFlow.pdf
[11] Mérillou, Mérillou, Ghazanfarpour, Dischler, Galin, “Simulating Atmospheric Pollution Weathering on Buildings”, http://liris.cnrs.fr/~egalin/Pdf/2010-atmospheric-weathering.pdf
[12] Lobanchikov, Gruen, “GSC Game World‘s S.T.A.L.K.E.R : Clear Sky –a showcase for Direct3D 10.0/1″ http://developer.amd.com/gpu_assets/01GDC09AD3DDStalkerClearSky210309.ppt
[13] St-Amour, “Rendering Assassin’s Creed 3”
[14] Lacroix, “Casting a new light on a familiar face”, https://drive.google.com/folderview?id=0B2iEzxzGlkkZWXNrOURDcFJXbzg&usp=sharing
[15] Kojima, “Metal Gear Solid V: The Phantom Pain”, http://www.gamespot.com/metal-gear-solid-v-the-phantom-pain/videos/hideo-kojima-gdc-2013-panel-6406092/
[16] Twomey, Bohren, Mergenthaler, “Reflectance and albedo differences between wet and dry surfaces”, Applied Optics
[17] Zhang, J.Voss, “Bidirectional reflectance study on dry, wet, and submerged particulate layers: effects of pore liquid refractive index and translucent particle concentrations”, http://www.opticsinfobase.org/ao/abstract.cfm?uri=ao-45-34-8753
[18] McCauley, “Calibrating lighting and materials in far cry 3”, http://blog.stevemcauley.com/2012/09/09/calibrating-lighting-and-materials-in-far-cry-3/
[19] Rebollo, Hogert, Albano, Raffo, Gaggioli, “Correlation between roughness and porosity in rocks”, http://www.sciencedirect.com/science/article/pii/0030399295000518
[20] Pesce,”impossible is approximately possible”, http://c0de517e.blogspot.fr/2008/10/impossible-is-approximatively-possible.html
[21] Balsam, Deaton, Damuth, “The effects of water content on diffuse reflectance spectrophotometry studies of deep-sea sediment cores”, http://www.ig.utexas.edu/people/staff/damuth/reprints/spectrastudy_watercontent.pdf
[22] Philpot, “Spectral reflectance of wetted soils”, http://www.asdi.com/getmedia/eeeb7ad1-c964-44fd-9404-d4870657e738/Spectral-Reflectance-of-Wetted-Soils.pdf.aspx
[23] http://www.pbrt.org/

6 Responses to Water drop 3b – Physically based wet surfaces

  1. Closed says:

    You are The God! Impressive, thanks a lot.

  2. seblagarde says:

    v1.1 Minor rewrite for better explanation of several sentences.

  3. seblagarde says:

    V1.2 : Rewrite of part “1. With a porosity scalar” “2. with porosity mask” “3. without poristy” and “Metallic and smooth material” which were incorrect.

  4. seblagarde says:

    V1.3: Add a figure from source [21] for the spectrum manipulation and add some sample of rough non-porous surface (vinyl, leather, textured surfaced…) in the text. This illustrate the need of at least a porosity mask to be more correct instead of simply relying on roughness for the darkening.

  5. Simon says:

    I’ve a question about the chapter “1. with porosity scalar”. As far as I understand line 3…

    float factor = lerp(1, 0.2, Porosity);

    …the diffuse-factor can never be < 0.2 but this also means, that…

    lerp(1, factor, 0.5 * WetLevel)

    …can't be < 0.2 which again means that…

    Gloss = lerp(1.0, Gloss, lerp(1, factor, 0.5 * WetLevel));

    …never reaches the original gloss-values, right? Even setting the wetLevel to 0.0 would result in min. factor of 0.2 and therefore the minimum lerp-value would neve be 0.0. Or did I oversee something?

    Here's the complete code:

    {
    float Porosity = tex2D(GreyTextures, uv).g;
    // Calc diffuse factor
    float factor = lerp(1, 0.2, Porosity);

    // Water influence on material BRDF
    Diffuse *= lerp(1.0, factor, WetLevel); // Attenuate diffuse
    Gloss = lerp(1.0, Gloss, lerp(1, factor, 0.5 * WetLevel));
    }

  6. Pingback: Welcome ! – HardTop's Vanillaccurate Pack

Leave a comment