Since real fabrics are not perfect a bit of variation can add a lot of realism to the apperance of the material.

I implemented a variation factor that uses some of the coordinates discussed in the pervious post to generate a random a factor that varies the intensity of the specular highlights. With this a “fineness” parmater is used to adjust the density of varaition. The existing irawan implementation included in mitsuba was used as a reference. It took a lot of fiddeling with the coordinates and variables in order to get the numbers used to generate the random variables in a correct fashion. Also, since the built in mitsuba implementation treates the pattern representation a bit differently from how we do it some changes had to be made.

New variables had to be defined. The absolute x and y positions in pattern scale.

uint32_t total_x = its.uv.x*m_uscale*m_pattern_width;
uint32_t total_y = its.uv.y*m_vscale*m_pattern_height;

With this the variation can be calculated, where sampleTEAFloat is a built in mitsuba function which will need to be replaced with something else or reimplemented in order for this work to be used in another rendering enegine. Looking ahead this is something i will have to investigate.

float intensityVariation(PatternData pattern_data) const {
  //absolute position for start of yarn segment
  float startx = total_x_ - pattern_data.x*pattern_data.width;
  float starty = total_y - pattern_data.y*pattern_data.length;

  //absolute position for center of yarn segment
  float centerx = startx + pattern_data.width/2.0;
  float centery = starty + pattern_data.length/2.0;

  uint32_t r1 = (uint32_t) ((centerx + pattern_data.total_x) 
          * m_intensity_fineness);
  uint32_t r2 = (uint32_t) ((centery + pattern_data.total_y) 
          * m_intensity_fineness);
        
  float xi = sampleTEAFloat(r1, r2, 8);
  return std::min(-math::fastlog(xi), (Float) 10.0f);
}       

Results:

Close-up of pattern with and without noise.

It looks a bit rough and the values used are quite arbitrary.

But since the average of the noise should be 0, this only has an cosmetic effect and should not effect any physical correcteness of the underlying model.

UPDATE (2016-03-30): Sorry, previous sentence is wrong and not true. New attempt… The random numbers xi are between 0 and 1, thus values from -math::fastlog(xi) can range from 0 to inf. \(X = xi \) is a uniformly distributed random variable on the interval [0,1].

The expected value is given by \begin{equation} E[-log(X)] = \int_{-\infty}^{\infty} -log(x) f_X(x) dx = \int_{0}^{1} -log(x) dx = 1 \end{equation}

The expected value will be 1. In the code std::min(-math::fastlog(xi), (Float) 10.0f) we limit the value to be below 10. But the distribution remains the same and does not affect the expected value.

A quick test in matlab demonstrates this,

values = min(-log(rand(10000,1)), 10);
mean_res = sum(values)/length(values)

> mean_res =
      1.0100

Therfore on average the intensity will remain and this noise variation should not effect any physical correcteness of the underlying model.

Example of cloth with and without noise.