1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
|
// Copyright 2009 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "Noise.ih"
#include "render/bsdfs/BeckmannDistribution.ih"
OSPRAY_BEGIN_ISPC_NAMESPACE
struct Flakes
{
float scale;
float density;
float spread;
float jitter;
};
inline vec3f Flakes_eval(const Flakes &self, vec3f P, int &mask)
{
vec3f N = make_vec3f(0.f, 0.f, 1.f);
mask = 0;
if (self.density <= 0.f || self.spread <= 0.f)
return N;
const BeckmannDistribution flakeDistribution =
make_BeckmannDistribution(roughnessToAlpha(self.spread));
P = P * self.scale;
// Simple Worley cellular noise with jittered feature points
// [Apodaca and Gritz, 1999, "Advanced RenderMan: Creating CGI for Motion
// Pictures", pp. 255-261]
const vec3f thisCell = floor(P) + 0.5f;
float f1 = 1000.f;
unsigned int cellRnd;
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
for (int k = -1; k <= 1; k++) {
const vec3f testCell = thisCell + make_vec3f(i, j, k);
// generate a random ID for the test cell
unsigned int rnd = cellNoise1ui(testCell);
// generate the position of the feature point in the test cell
const vec3f pos = testCell + self.jitter * (LCG_getFloat3(rnd) - 0.5f);
// distance test
const vec3f offset = pos - P;
const float dist = dot(offset, offset); // actually dist^2
if (dist < f1) {
f1 = dist;
cellRnd = rnd;
}
}
}
}
// test whether the flake exists
if (LCG_getFloat(cellRnd) <= self.density) {
// generate a random normal for the flake
float pdf;
N = sample(flakeDistribution, pdf, LCG_getFloat2(cellRnd));
mask = 1;
}
return normalize(N);
}
OSPRAY_END_ISPC_NAMESPACE
|