July 15, 2016

Inverse Sine Distribution and Seeding (And Sparkling Materials)

The Perfect Tile System is a fairly mature system, but there's always room for improvement. One example is how to handle random seeding with features like tile tilting and roughness, to give each tile a unique tilt in the normals or shift in the roughness. This method can be used to give a nice sparkling finish to a granular material. I noticed that the old distribution (sine waves), while cheap, favored extreme angles to a more centered distribution: a sine wave rounds out on the ends, not in the middle. The distribution I needed was the opposite: an inverse sine, where the center values are more typical along the distribution path, with sharper falloffs into the extreme.

In HLSL:
asin (x)

Inverse sine calculations, unfortunately, are very expensive (10 instructions by itself), and requires the input to be bound between [-1:1]. But I needed the input to be unbound so the distribution can be used to completely randomize and seed values. If you want a purely coded distribution method, you need to use the oscillation BEFORE the function, at which point, why bother doing this seeding calculation 3 times? All being said, the coded inverse sine was NOT going to be efficient at ALL.

So in my research, I found two alternate methods to make this type of distribution much cheaper: the texture/data table method, and the smooth curve method. The cheapest and most flexible technique was the Texture Seeding/Data Table Method. It is 3-5 times cheaper than the coded method.


Coded Seeding Method (Bottom Asine is 2-vector)


Texture Seeding Method (Asine is embedded as gradient texture)

Random Map > multiply by constant seed value > Mask and offset UVs of Asine/Sine/Linear gradient texture > Interpolate and/or bias to final values.

The texture method is similar to a data table: use the seed values to randomize the UVs of a texture containing a single sine distribution. This method is really cheap, and costs only 5 instructions to seed (from random values to [0:1] asine distribution). I used a 1x512 texture to map out the values from 0-255 along an inverse sine wave, and the whole thing wraps around. The values themselves were figured out using a formula in Excel.

This Excel function plots one arc of the inverse sine from 0-1 using 256 steps:

=(ASIN((ROW(A1)-2)/255))/(PI()/2)*256

Note: This single arc must be manipulated into a corrected asine distribution. I made a corrected Excel data table below of the raw numbers.


From those values, it just takes a lot of manual labor in Photoshop to color a texture 512 pixels long. There are only 256 values that can be plotted in a single pixel on a texture. That being said, trilinear filtering DOES smooth out the resolution of the data set, giving you an effectively accurate inverse sine distribution for no more cost than any other data set in the texture seeding method. The texture must be imported with sRGB checked OFF with the Linear Grayscale compression settings (uncompressed, one channel). This method costs only 5 instructions for the seeding, 7 total for including interpolating. Using the same method for a linear gradient will give you a linear distribution. Sine gradient, a sine distribution.

Download raw Excel data table
Download Asine.tga 512-pixel gradient