node_musgrave_texture.osl 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /*
  2. * Copyright 2011-2013 Blender Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "stdosl.h"
  17. #include "node_texture.h"
  18. /* Musgrave fBm
  19. *
  20. * H: fractal increment parameter
  21. * lacunarity: gap between successive frequencies
  22. * octaves: number of frequencies in the fBm
  23. *
  24. * from "Texturing and Modelling: A procedural approach"
  25. */
  26. float noise_musgrave_fBm(point ip, float H, float lacunarity, float octaves)
  27. {
  28. float rmd;
  29. float value = 0.0;
  30. float pwr = 1.0;
  31. float pwHL = pow(lacunarity, -H);
  32. int i;
  33. point p = ip;
  34. for (i = 0; i < (int)octaves; i++) {
  35. value += safe_noise(p, "signed") * pwr;
  36. pwr *= pwHL;
  37. p *= lacunarity;
  38. }
  39. rmd = octaves - floor(octaves);
  40. if (rmd != 0.0)
  41. value += rmd * safe_noise(p, "signed") * pwr;
  42. return value;
  43. }
  44. /* Musgrave Multifractal
  45. *
  46. * H: highest fractal dimension
  47. * lacunarity: gap between successive frequencies
  48. * octaves: number of frequencies in the fBm
  49. */
  50. float noise_musgrave_multi_fractal(point ip, float H, float lacunarity, float octaves)
  51. {
  52. float rmd;
  53. float value = 1.0;
  54. float pwr = 1.0;
  55. float pwHL = pow(lacunarity, -H);
  56. int i;
  57. point p = ip;
  58. for (i = 0; i < (int)octaves; i++) {
  59. value *= (pwr * safe_noise(p, "signed") + 1.0);
  60. pwr *= pwHL;
  61. p *= lacunarity;
  62. }
  63. rmd = octaves - floor(octaves);
  64. if (rmd != 0.0)
  65. value *= (rmd * pwr * safe_noise(p, "signed") + 1.0); /* correct? */
  66. return value;
  67. }
  68. /* Musgrave Heterogeneous Terrain
  69. *
  70. * H: fractal dimension of the roughest area
  71. * lacunarity: gap between successive frequencies
  72. * octaves: number of frequencies in the fBm
  73. * offset: raises the terrain from `sea level'
  74. */
  75. float noise_musgrave_hetero_terrain(
  76. point ip, float H, float lacunarity, float octaves, float offset)
  77. {
  78. float value, increment, rmd;
  79. float pwHL = pow(lacunarity, -H);
  80. float pwr = pwHL;
  81. int i;
  82. point p = ip;
  83. /* first unscaled octave of function; later octaves are scaled */
  84. value = offset + safe_noise(p, "signed");
  85. p *= lacunarity;
  86. for (i = 1; i < (int)octaves; i++) {
  87. increment = (safe_noise(p, "signed") + offset) * pwr * value;
  88. value += increment;
  89. pwr *= pwHL;
  90. p *= lacunarity;
  91. }
  92. rmd = octaves - floor(octaves);
  93. if (rmd != 0.0) {
  94. increment = (safe_noise(p, "signed") + offset) * pwr * value;
  95. value += rmd * increment;
  96. }
  97. return value;
  98. }
  99. /* Hybrid Additive/Multiplicative Multifractal Terrain
  100. *
  101. * H: fractal dimension of the roughest area
  102. * lacunarity: gap between successive frequencies
  103. * octaves: number of frequencies in the fBm
  104. * offset: raises the terrain from `sea level'
  105. */
  106. float noise_musgrave_hybrid_multi_fractal(
  107. point ip, float H, float lacunarity, float octaves, float offset, float gain)
  108. {
  109. float result, signal, weight, rmd;
  110. float pwHL = pow(lacunarity, -H);
  111. float pwr = pwHL;
  112. int i;
  113. point p = ip;
  114. result = safe_noise(p, "signed") + offset;
  115. weight = gain * result;
  116. p *= lacunarity;
  117. for (i = 1; (weight > 0.001) && (i < (int)octaves); i++) {
  118. if (weight > 1.0)
  119. weight = 1.0;
  120. signal = (safe_noise(p, "signed") + offset) * pwr;
  121. pwr *= pwHL;
  122. result += weight * signal;
  123. weight *= gain * signal;
  124. p *= lacunarity;
  125. }
  126. rmd = octaves - floor(octaves);
  127. if (rmd != 0.0)
  128. result += rmd * ((safe_noise(p, "signed") + offset) * pwr);
  129. return result;
  130. }
  131. /* Ridged Multifractal Terrain
  132. *
  133. * H: fractal dimension of the roughest area
  134. * lacunarity: gap between successive frequencies
  135. * octaves: number of frequencies in the fBm
  136. * offset: raises the terrain from `sea level'
  137. */
  138. float noise_musgrave_ridged_multi_fractal(
  139. point ip, float H, float lacunarity, float octaves, float offset, float gain)
  140. {
  141. float result, signal, weight;
  142. float pwHL = pow(lacunarity, -H);
  143. float pwr = pwHL;
  144. int i;
  145. point p = ip;
  146. signal = offset - fabs(safe_noise(p, "signed"));
  147. signal *= signal;
  148. result = signal;
  149. weight = 1.0;
  150. for (i = 1; i < (int)octaves; i++) {
  151. p *= lacunarity;
  152. weight = clamp(signal * gain, 0.0, 1.0);
  153. signal = offset - fabs(safe_noise(p, "signed"));
  154. signal *= signal;
  155. signal *= weight;
  156. result += signal * pwr;
  157. pwr *= pwHL;
  158. }
  159. return result;
  160. }
  161. /* Shader */
  162. shader node_musgrave_texture(
  163. int use_mapping = 0,
  164. matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
  165. string type = "fBM",
  166. float Dimension = 2.0,
  167. float Lacunarity = 1.0,
  168. float Detail = 2.0,
  169. float Offset = 0.0,
  170. float Gain = 1.0,
  171. float Scale = 5.0,
  172. point Vector = P,
  173. output float Fac = 0.0,
  174. output color Color = 0.0)
  175. {
  176. float dimension = max(Dimension, 1e-5);
  177. float octaves = clamp(Detail, 0.0, 16.0);
  178. float lacunarity = max(Lacunarity, 1e-5);
  179. float intensity = 1.0;
  180. point p = Vector;
  181. if (use_mapping)
  182. p = transform(mapping, p);
  183. p = p * Scale;
  184. if (type == "multifractal")
  185. Fac = intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves);
  186. else if (type == "fBM")
  187. Fac = intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves);
  188. else if (type == "hybrid_multifractal")
  189. Fac = intensity *
  190. noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, Offset, Gain);
  191. else if (type == "ridged_multifractal")
  192. Fac = intensity *
  193. noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, Offset, Gain);
  194. else if (type == "hetero_terrain")
  195. Fac = intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, Offset);
  196. Color = color(Fac, Fac, Fac);
  197. }