Files
test2/intern/cycles/kernel/svm/fractal_noise.h
2024-01-08 11:31:43 +11:00

534 lines
13 KiB
C

/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
#pragma once
#include "kernel/svm/noise.h"
CCL_NAMESPACE_BEGIN
/* Fractal Brownian motion. */
ccl_device_noinline float noise_fbm(
float p, float detail, float roughness, float lacunarity, bool normalize)
{
float fscale = 1.0f;
float amp = 1.0f;
float maxamp = 0.0f;
float sum = 0.0f;
for (int i = 0; i <= float_to_int(detail); i++) {
float t = snoise_1d(fscale * p);
sum += t * amp;
maxamp += amp;
amp *= roughness;
fscale *= lacunarity;
}
float rmd = detail - floorf(detail);
if (rmd != 0.0f) {
float t = snoise_1d(fscale * p);
float sum2 = sum + t * amp;
return normalize ? mix(0.5f * sum / maxamp + 0.5f, 0.5f * sum2 / (maxamp + amp) + 0.5f, rmd) :
mix(sum, sum2, rmd);
}
else {
return normalize ? 0.5f * sum / maxamp + 0.5f : sum;
}
}
ccl_device_noinline float noise_fbm(
float2 p, float detail, float roughness, float lacunarity, bool normalize)
{
float fscale = 1.0f;
float amp = 1.0f;
float maxamp = 0.0f;
float sum = 0.0f;
for (int i = 0; i <= float_to_int(detail); i++) {
float t = snoise_2d(fscale * p);
sum += t * amp;
maxamp += amp;
amp *= roughness;
fscale *= lacunarity;
}
float rmd = detail - floorf(detail);
if (rmd != 0.0f) {
float t = snoise_2d(fscale * p);
float sum2 = sum + t * amp;
return normalize ? mix(0.5f * sum / maxamp + 0.5f, 0.5f * sum2 / (maxamp + amp) + 0.5f, rmd) :
mix(sum, sum2, rmd);
}
else {
return normalize ? 0.5f * sum / maxamp + 0.5f : sum;
}
}
ccl_device_noinline float noise_fbm(
float3 p, float detail, float roughness, float lacunarity, bool normalize)
{
float fscale = 1.0f;
float amp = 1.0f;
float maxamp = 0.0f;
float sum = 0.0f;
for (int i = 0; i <= float_to_int(detail); i++) {
float t = snoise_3d(fscale * p);
sum += t * amp;
maxamp += amp;
amp *= roughness;
fscale *= lacunarity;
}
float rmd = detail - floorf(detail);
if (rmd != 0.0f) {
float t = snoise_3d(fscale * p);
float sum2 = sum + t * amp;
return normalize ? mix(0.5f * sum / maxamp + 0.5f, 0.5f * sum2 / (maxamp + amp) + 0.5f, rmd) :
mix(sum, sum2, rmd);
}
else {
return normalize ? 0.5f * sum / maxamp + 0.5f : sum;
}
}
ccl_device_noinline float noise_fbm(
float4 p, float detail, float roughness, float lacunarity, bool normalize)
{
float fscale = 1.0f;
float amp = 1.0f;
float maxamp = 0.0f;
float sum = 0.0f;
for (int i = 0; i <= float_to_int(detail); i++) {
float t = snoise_4d(fscale * p);
sum += t * amp;
maxamp += amp;
amp *= roughness;
fscale *= lacunarity;
}
float rmd = detail - floorf(detail);
if (rmd != 0.0f) {
float t = snoise_4d(fscale * p);
float sum2 = sum + t * amp;
return normalize ? mix(0.5f * sum / maxamp + 0.5f, 0.5f * sum2 / (maxamp + amp) + 0.5f, rmd) :
mix(sum, sum2, rmd);
}
else {
return normalize ? 0.5f * sum / maxamp + 0.5f : sum;
}
}
/* Multifractal */
ccl_device_noinline float noise_multi_fractal(float p,
float detail,
float roughness,
float lacunarity)
{
float value = 1.0f;
float pwr = 1.0f;
for (int i = 0; i <= float_to_int(detail); i++) {
value *= (pwr * snoise_1d(p) + 1.0f);
pwr *= roughness;
p *= lacunarity;
}
float rmd = detail - floorf(detail);
if (rmd != 0.0f) {
value *= (rmd * pwr * snoise_1d(p) + 1.0f); /* correct? */
}
return value;
}
ccl_device_noinline float noise_multi_fractal(float2 p,
float detail,
float roughness,
float lacunarity)
{
float value = 1.0f;
float pwr = 1.0f;
for (int i = 0; i <= float_to_int(detail); i++) {
value *= (pwr * snoise_2d(p) + 1.0f);
pwr *= roughness;
p *= lacunarity;
}
float rmd = detail - floorf(detail);
if (rmd != 0.0f) {
value *= (rmd * pwr * snoise_2d(p) + 1.0f); /* correct? */
}
return value;
}
ccl_device_noinline float noise_multi_fractal(float3 p,
float detail,
float roughness,
float lacunarity)
{
float value = 1.0f;
float pwr = 1.0f;
for (int i = 0; i <= float_to_int(detail); i++) {
value *= (pwr * snoise_3d(p) + 1.0f);
pwr *= roughness;
p *= lacunarity;
}
float rmd = detail - floorf(detail);
if (rmd != 0.0f) {
value *= (rmd * pwr * snoise_3d(p) + 1.0f); /* correct? */
}
return value;
}
ccl_device_noinline float noise_multi_fractal(float4 p,
float detail,
float roughness,
float lacunarity)
{
float value = 1.0f;
float pwr = 1.0f;
for (int i = 0; i <= float_to_int(detail); i++) {
value *= (pwr * snoise_4d(p) + 1.0f);
pwr *= roughness;
p *= lacunarity;
}
float rmd = detail - floorf(detail);
if (rmd != 0.0f) {
value *= (rmd * pwr * snoise_4d(p) + 1.0f); /* correct? */
}
return value;
}
/* Heterogeneous Terrain */
ccl_device_noinline float noise_hetero_terrain(
float p, float detail, float roughness, float lacunarity, float offset)
{
float pwr = roughness;
/* first unscaled octave of function; later octaves are scaled */
float value = offset + snoise_1d(p);
p *= lacunarity;
for (int i = 1; i <= float_to_int(detail); i++) {
float increment = (snoise_1d(p) + offset) * pwr * value;
value += increment;
pwr *= roughness;
p *= lacunarity;
}
float rmd = detail - floorf(detail);
if (rmd != 0.0f) {
float increment = (snoise_1d(p) + offset) * pwr * value;
value += rmd * increment;
}
return value;
}
ccl_device_noinline float noise_hetero_terrain(
float2 p, float detail, float roughness, float lacunarity, float offset)
{
float pwr = roughness;
/* first unscaled octave of function; later octaves are scaled */
float value = offset + snoise_2d(p);
p *= lacunarity;
for (int i = 1; i <= float_to_int(detail); i++) {
float increment = (snoise_2d(p) + offset) * pwr * value;
value += increment;
pwr *= roughness;
p *= lacunarity;
}
float rmd = detail - floorf(detail);
if (rmd != 0.0f) {
float increment = (snoise_2d(p) + offset) * pwr * value;
value += rmd * increment;
}
return value;
}
ccl_device_noinline float noise_hetero_terrain(
float3 p, float detail, float roughness, float lacunarity, float offset)
{
float pwr = roughness;
/* first unscaled octave of function; later octaves are scaled */
float value = offset + snoise_3d(p);
p *= lacunarity;
for (int i = 1; i <= float_to_int(detail); i++) {
float increment = (snoise_3d(p) + offset) * pwr * value;
value += increment;
pwr *= roughness;
p *= lacunarity;
}
float rmd = detail - floorf(detail);
if (rmd != 0.0f) {
float increment = (snoise_3d(p) + offset) * pwr * value;
value += rmd * increment;
}
return value;
}
ccl_device_noinline float noise_hetero_terrain(
float4 p, float detail, float roughness, float lacunarity, float offset)
{
float pwr = roughness;
/* first unscaled octave of function; later octaves are scaled */
float value = offset + snoise_4d(p);
p *= lacunarity;
for (int i = 1; i <= float_to_int(detail); i++) {
float increment = (snoise_4d(p) + offset) * pwr * value;
value += increment;
pwr *= roughness;
p *= lacunarity;
}
float rmd = detail - floorf(detail);
if (rmd != 0.0f) {
float increment = (snoise_4d(p) + offset) * pwr * value;
value += rmd * increment;
}
return value;
}
/* Hybrid Additive/Multiplicative Multifractal Terrain */
ccl_device_noinline float noise_hybrid_multi_fractal(
float p, float detail, float roughness, float lacunarity, float offset, float gain)
{
float pwr = 1.0f;
float value = 0.0f;
float weight = 1.0f;
for (int i = 0; (weight > 0.001f) && (i <= float_to_int(detail)); i++) {
if (weight > 1.0f) {
weight = 1.0f;
}
float signal = (snoise_1d(p) + offset) * pwr;
pwr *= roughness;
value += weight * signal;
weight *= gain * signal;
p *= lacunarity;
}
float rmd = detail - floorf(detail);
if ((rmd != 0.0f) && (weight > 0.001f)) {
if (weight > 1.0f) {
weight = 1.0f;
}
float signal = (snoise_1d(p) + offset) * pwr;
value += rmd * weight * signal;
}
return value;
}
ccl_device_noinline float noise_hybrid_multi_fractal(
float2 p, float detail, float roughness, float lacunarity, float offset, float gain)
{
float pwr = 1.0f;
float value = 0.0f;
float weight = 1.0f;
for (int i = 0; (weight > 0.001f) && (i <= float_to_int(detail)); i++) {
if (weight > 1.0f) {
weight = 1.0f;
}
float signal = (snoise_2d(p) + offset) * pwr;
pwr *= roughness;
value += weight * signal;
weight *= gain * signal;
p *= lacunarity;
}
float rmd = detail - floorf(detail);
if ((rmd != 0.0f) && (weight > 0.001f)) {
if (weight > 1.0f) {
weight = 1.0f;
}
float signal = (snoise_2d(p) + offset) * pwr;
value += rmd * weight * signal;
}
return value;
}
ccl_device_noinline float noise_hybrid_multi_fractal(
float3 p, float detail, float roughness, float lacunarity, float offset, float gain)
{
float pwr = 1.0f;
float value = 0.0f;
float weight = 1.0f;
for (int i = 0; (weight > 0.001f) && (i <= float_to_int(detail)); i++) {
if (weight > 1.0f) {
weight = 1.0f;
}
float signal = (snoise_3d(p) + offset) * pwr;
pwr *= roughness;
value += weight * signal;
weight *= gain * signal;
p *= lacunarity;
}
float rmd = detail - floorf(detail);
if ((rmd != 0.0f) && (weight > 0.001f)) {
if (weight > 1.0f) {
weight = 1.0f;
}
float signal = (snoise_3d(p) + offset) * pwr;
value += rmd * weight * signal;
}
return value;
}
ccl_device_noinline float noise_hybrid_multi_fractal(
float4 p, float detail, float roughness, float lacunarity, float offset, float gain)
{
float pwr = 1.0f;
float value = 0.0f;
float weight = 1.0f;
for (int i = 0; (weight > 0.001f) && (i <= float_to_int(detail)); i++) {
if (weight > 1.0f) {
weight = 1.0f;
}
float signal = (snoise_4d(p) + offset) * pwr;
pwr *= roughness;
value += weight * signal;
weight *= gain * signal;
p *= lacunarity;
}
float rmd = detail - floorf(detail);
if ((rmd != 0.0f) && (weight > 0.001f)) {
if (weight > 1.0f) {
weight = 1.0f;
}
float signal = (snoise_4d(p) + offset) * pwr;
value += rmd * weight * signal;
}
return value;
}
/* Ridged Multifractal Terrain */
ccl_device_noinline float noise_ridged_multi_fractal(
float p, float detail, float roughness, float lacunarity, float offset, float gain)
{
float pwr = roughness;
float signal = offset - fabsf(snoise_1d(p));
signal *= signal;
float value = signal;
float weight = 1.0f;
for (int i = 1; i <= float_to_int(detail); i++) {
p *= lacunarity;
weight = saturatef(signal * gain);
signal = offset - fabsf(snoise_1d(p));
signal *= signal;
signal *= weight;
value += signal * pwr;
pwr *= roughness;
}
return value;
}
ccl_device_noinline float noise_ridged_multi_fractal(
float2 p, float detail, float roughness, float lacunarity, float offset, float gain)
{
float pwr = roughness;
float signal = offset - fabsf(snoise_2d(p));
signal *= signal;
float value = signal;
float weight = 1.0f;
for (int i = 1; i <= float_to_int(detail); i++) {
p *= lacunarity;
weight = saturatef(signal * gain);
signal = offset - fabsf(snoise_2d(p));
signal *= signal;
signal *= weight;
value += signal * pwr;
pwr *= roughness;
}
return value;
}
ccl_device_noinline float noise_ridged_multi_fractal(
float3 p, float detail, float roughness, float lacunarity, float offset, float gain)
{
float pwr = roughness;
float signal = offset - fabsf(snoise_3d(p));
signal *= signal;
float value = signal;
float weight = 1.0f;
for (int i = 1; i <= float_to_int(detail); i++) {
p *= lacunarity;
weight = saturatef(signal * gain);
signal = offset - fabsf(snoise_3d(p));
signal *= signal;
signal *= weight;
value += signal * pwr;
pwr *= roughness;
}
return value;
}
ccl_device_noinline float noise_ridged_multi_fractal(
float4 p, float detail, float roughness, float lacunarity, float offset, float gain)
{
float pwr = roughness;
float signal = offset - fabsf(snoise_4d(p));
signal *= signal;
float value = signal;
float weight = 1.0f;
for (int i = 1; i <= float_to_int(detail); i++) {
p *= lacunarity;
weight = saturatef(signal * gain);
signal = offset - fabsf(snoise_4d(p));
signal *= signal;
signal *= weight;
value += signal * pwr;
pwr *= roughness;
}
return value;
}
CCL_NAMESPACE_END