虽然Octane有flakes的OSL预设,不过默认的不能控制flakes贴图的投射模式。
新建一个OSL节点,并把以下代码复制替换进去,然后点击上方的Compile按钮即可。
shader flakes
(
point position = P,
float scale = 1 [[ float min = 1e-4, float max = 1e3, float sliderexponent = 4 ]],
float flake_size = 0.5 [[ string description = "Relative size of the flakes",
float min = 0, float max = 10 ]],
float flake_size_variance = 0.0 [[ string description = "0.0 makes all flakes the same size, 1.0 assigns random size between 0 and the given flake size",
float min = 0, float max = 1 ]],
float strength = 0.3 [[ string description = "The strength of the normal map",
float min = 0, float max = .5 ]],
output color cOut = color(0.5, 0.5, 1.0)
)
{
point uvw = position / scale;
float safe_flake_size_variance = clamp(flake_size_variance, 0, 1.0);
point base = floor(uvw);
point nearestFlakePos = point(0.0, 0.0, 1.0);
float bestDistance = 99;
for (float cellx = -1.5; cellx < 1; cellx += 1.0)
{
for (float celly = -1.5; celly < 1; celly += 1.0)
{
for (float cellz = -1.5; cellz < 1; cellz += 1.0)
{
point cellCenter = base + point(cellx, celly, cellz);
cellCenter += (vector) cellnoise(cellCenter);
float cellDistance = distance(uvw, cellCenter);
float maxDistance = flake_size;
if (cellDistance < maxDistance)
{
float uSize = cellnoise(cellCenter + vector(-600, 600, 600));
maxDistance -= flake_size_variance * uSize * flake_size;
if (cellDistance < maxDistance)
{
if (cellDistance < flake_size && cellDistance < bestDistance)
{
bestDistance = cellDistance;
nearestFlakePos = cellCenter;
}
}
}
}
}
}
if (bestDistance != 99)
{
vector random = cellnoise(nearestFlakePos);
float ang = random[0] * M_PI * 2;
// sample disk, non-uniform: more densely near the origin
vector distortion = vector(sin(ang), cos(ang), 0)
* sqrt(-2 * log(1 - .999 * random[1]));
cOut = normalize(vector(0, 0, 1) + distortion * strength) * .5 + .5;
}
}
参考:
https://render.otoy.com/forum/viewtopic.php?f=9&t=75761&p=389476&hilit=osl#p389476
https://docs.chaosgroup.com/display/OSLShaders/Flakes+normal+map