RandomBitmaps - 图1

    1. // Randomly place (and alpha-blend) bitmap on top of something else
    2. // RamdomBitmap.osl by Zap Andersson)
    3. // Modified: 2019-11-26
    4. // Modified: 2021-03-26 by Saul Espinosa for Redshift 3D
    5. // Copyright 2019 Autodesk Inc, All rights reserved. This file is licensed under Apache 2.0 license
    6. // https://github.com/ADN-DevTech/3dsMax-OSL-Shaders/blob/master/LICENSE.txt
    7. color TextureFetch(string filename, point lp, output float a)
    8. {
    9. color rgb = texture(filename, lp[0], 1.0-lp[1], "alpha", a, "wrap", "clamp");
    10. int channels = 3;
    11. gettextureinfo(filename, "channels", channels);
    12. if (channels <= 3) // If there is no alpha...
    13. a = 1.0; // ...use 1.0
    14. return rgb;
    15. }
    16. shader RandomBitmaps
    17. [[ string help = "Randomly place (and alpha blend) a set of<br>bitmaps on top of something else",
    18. string version = "2.0.0",
    19. string label = "Randomized Bitmaps", string page = "0 : General" ]]
    20. (
    21. int Layers = 1 [[ int min=1, int max=9, int connectable=0, string page = "0 : General" ]],
    22. vector UVW = vector(u,v,0) [[string page = "3 : Other"]],
    23. float Scale = 1.0 [[ float min = 0, float max = 2, string label = "Overall Scale", string page = "0 : General" ]],
    24. color Input = 0.0
    25. [[ string label = "Background RGB", string page = "0 : General",
    26. string help="The input color on top of which everything else is put. Thia allows cascading multiple RandomBitmap on top of each other easily..." ]],
    27. float InputAlpha = 1.0
    28. [[ float min = 0, float max = 1.0,
    29. string label = "Background Alpha", string page = "0 : General",
    30. string help="The input alpha on top of which everything else is put. Thia allows cascading multiple RandomBitmap on top of each other easily..." ]],
    31. #define LAYER(x) \
    32. string Filename##x = "" \
    33. [[ string widget="filename", \
    34. string label="File name " #x, \
    35. string help="The name of the bitmap to place randomly", string page = "1 : Textures" ]],
    36. LAYER(0)
    37. //====LAYER-BEGIN====
    38. LAYER(1)
    39. LAYER(2)
    40. LAYER(3)
    41. LAYER(4)
    42. LAYER(5)
    43. LAYER(6)
    44. LAYER(7)
    45. LAYER(8)
    46. LAYER(9)
    47. //====LAYER-END====
    48. #undef LAYER
    49. int NumFiles = 0
    50. [[ string label = "Limit to N Files",
    51. string help = "By default, all files are used, but for testing purpouses, "
    52. "one can choose to only use a few of them by setting this "
    53. "value greater than zero.",
    54. int min = 0, int max = 10, string page = "0 : General" ]],
    55. int Seed = 39
    56. [[ string help="The random seed", string page = "2 : Randomization", int min = 0, int max = 100 ]],
    57. vector Probability = vector(1.0, 0.0, 0.1)
    58. [[ string help="Three values: The probability a bitmap will show up, the randomness of the variation in the probability, and the scale of said randomness",
    59. float min = 0.0,
    60. float max = 1.0, string page = "2 : Randomization" ]],
    61. vector PosRandom = vector(0.5,0.5,0.0)
    62. [[ string page = "2 : Randomization", string help="Position randomness. For large numbers you may have to turn Overlap up, but impacts performance! Note: the Z value is not used." ]],
    63. vector ScaleMin = vector(1.0, 1.0, 0.0)
    64. [[ string help="The scale randomness. For large scales you may have to turn Overlap up, but impacts performance! Note: the Z value is not used." ,
    65. float min = 0.0,
    66. float max = 10.0, string page = "2 : Randomization" ]],
    67. vector ScaleMax = vector(1.0, 1.0, 0.0)
    68. [[ string help="The scale randomness. For large scales you may have to turn Overlap up, but impacts performance! Note: the Z value is not used." ,
    69. float min = 0.0,
    70. float max = 10.0, string page = "2 : Randomization" ]],
    71. int UniformScale = 1
    72. [[ string widget="checkBox",
    73. string help="If enabled, U and V scales in sync with each other, if off, they scale independently", string label = "Randomize Scale Proportionally", string page = "2 : Randomization" ]],
    74. float PixelScale = 0.0
    75. [[ float min = 0, float max = 8192, float sensitivity = 1, string page = "2 : Randomization", string help="Relates pixels to image size.<ul><li>If zero, each image is considered to be a 1.0 x 1.0 square in UV space.<li>If nonzero, maps that many pixels to a the size of 1.0, so that images are the same size w.r.t. to pixels <i>and</i> retains their aspect ratio.<br/><b>NOTE</b>: Sizes ending up larger than 1.0 will require turning up Overlap, which reduces performance!</li></ul>" ]],
    76. float RotMin = 0.0
    77. [[ string help="The Rotational randomness." ,
    78. float min = -180,
    79. float max = 0, string page = "2 : Randomization", float sensitivity = 1 ]],
    80. float RotMax = 0.0
    81. [[ string help="The Rotational randomness." ,
    82. float min = 0,
    83. float max = 180, string page = "2 : Randomization", float sensitivity = 1 ]],
    84. int RotSteps = 1
    85. [[ string help="Number of 'steps' of Rotational randomness. 1 means 'no steps'.<br><br>For example, to rotate something only 0, 90, 180 and 270 degrees, set min rotation to 0, max rotation to 270, and RotSteps to 4." ,
    86. int min = 1,
    87. int max = 10, string page = "2 : Randomization" ]],
    88. vector HSVMin = vector(0.0, 1.0, 1.0)
    89. [[ string help="Hue/Saturation/Value randomness. Start range of hue shift and saturation/value scaling" ,
    90. float min = -2.0,
    91. float max = 2.0, string page = "2 : Randomization" ]],
    92. vector HSVMax = vector(0.0, 1.0, 1.0)
    93. [[ string help="Hue/Saturation/Value randomness. End range of hue shift and saturation/value scaling" ,
    94. float min = -2.0,
    95. float max = 2.0, string page = "2 : Randomization" ]],
    96. float AlphaMin = 1.0
    97. [[ string help="The Alpha randomness. Minimum multiplier of alpha." ,
    98. float min = 0.0,
    99. float max = 1.0, string page = "2 : Randomization" ]],
    100. float AlphaMax = 1.0
    101. [[ string help="The Alpha randomness. Maximum multiplier of alpha." ,
    102. float min = 0.0,
    103. float max = 1.0, string page = "2 : Randomization" ]],
    104. float GammaMin = 0.0
    105. [[ string help="The Gamma randomness. Minimum offset of gamma value." ,
    106. float min = -5.0,
    107. float max = 5.0, string page = "2 : Randomization" ]],
    108. float GammaMax = 0.0
    109. [[ string help="The Gamma randomness. Maximum offset of gamma value." ,
    110. float min = -5.0,
    111. float max = 5.0, string page = "2 : Randomization" ]],
    112. int Clamp = 1
    113. [[ string widget = "checkBox", string page = "3 : Other",
    114. string help = "Large color tweaks can yield colors outside of the 0-1 range. It's a good idea to clamp those colors to the 0-1 range..." ]],
    115. float ManualGamma = 2.2
    116. [[ string label="Manual Gamma", string page = "3 : Other" ]],
    117. int OverLap = 1
    118. [[ string help="For very large scales or position shifts, you may see cut-off textures. This means the shader may need to look further into more neighbouring cells. Increasing this reduces performance A LOT so ONLY do this if absolutely necessary!",
    119. int min=0, int max=5, string page = "3 : Other" ]],
    120. output color Out = 0.0,
    121. output float Alpha = 1.0,
    122. )
    123. {
    124. // Adjust behaviour based on version
    125. int oslversion = 0;
    126. getattribute("osl:version", oslversion);
    127. point UVWs = UVW / Scale;
    128. int ix = int(floor(UVWs[0]));
    129. int iy = int(floor(UVWs[1]));
    130. float fx = UVWs[0] - ix;
    131. float fy = UVWs[1] - iy;
    132. float gamma = 1.0;
    133. gamma = ManualGamma;
    134. // Start with the output being the input
    135. Out = Input;
    136. Alpha = InputAlpha;
    137. // The modulo value is number of layers+1
    138. int modValue = Layers+1;
    139. // Has the user chosen to limit number of files?
    140. if (NumFiles > 0 && NumFiles <= Layers)
    141. modValue = NumFiles;
    142. for (int xx = -OverLap; xx <= OverLap; xx++)
    143. {
    144. for(int yy = -OverLap; yy <= OverLap; yy++)
    145. {
    146. // The point used for all the randomness
    147. point rndpoint = point(ix + xx, iy + yy, Seed);
    148. // Compensate for old cellnoise behaviour
    149. if (oslversion >= 11000)
    150. {
    151. rndpoint[0] = rndpoint[0] < 0 ? rndpoint[0]-1: rndpoint[0];
    152. rndpoint[1] = rndpoint[1] < 0 ? rndpoint[1]-1: rndpoint[1];
    153. rndpoint[2] = rndpoint[2] < 0 ? rndpoint[2]-1: rndpoint[2];
    154. }
    155. // Random pos data
    156. point pos = ((noise("cell", rndpoint, 0) - vector(0.5,0.5,0.0)) * vector(PosRandom[0], PosRandom[1], 1.0));
    157. // The actual lookup point
    158. point lp = point(fx-xx, fy-yy, 0) - pos;
    159. float prob = Probability[0] + noise("perlin", rndpoint * Probability[2]) * Probability[1];
    160. if (pos[2] < prob)
    161. {
    162. // Scale and rotation randomness
    163. point scr = noise("cell", rndpoint, 1);
    164. int pic = int((float)noise("cell", rndpoint, 15) * 100) % modValue;
    165. // XY scaling tweak
    166. float sx = 1.0, sy = 1.0;
    167. if (PixelScale > 0.0)
    168. {
    169. int res[2];
    170. if (pic == 0) gettextureinfo(Filename0, "resolution", res);
    171. #define LAYER(x) else if (pic == x) gettextureinfo(Filename##x, "resolution", res);
    172. //====LAYER-BEGIN====
    173. LAYER(0)
    174. LAYER(1)
    175. LAYER(2)
    176. LAYER(3)
    177. LAYER(4)
    178. LAYER(5)
    179. LAYER(6)
    180. LAYER(7)
    181. LAYER(8)
    182. LAYER(9)
    183. //====LAYER-END====
    184. #undef LAYER
    185. sx = res[0] / PixelScale;
    186. sy = res[1] / PixelScale;
    187. }
    188. float scaleX = sx * mix(ScaleMin[0], ScaleMax[0], scr[0]);
    189. float scaleY = sy * mix(ScaleMin[1], ScaleMax[1], scr[UniformScale?0:1]);
    190. if (RotSteps > 1)
    191. {
    192. scr[2] = floor(scr[2] * RotSteps) / (RotSteps - 1);
    193. }
    194. float rot = mix(RotMin, RotMax, scr[2]);
    195. lp -= 0.5;
    196. lp = rotate(lp, radians(rot), point(0,0,0), vector(0,0,1));
    197. lp /= vector(scaleX, scaleY, 1.0);
    198. lp += 0.5;
    199. if (lp[0] >= 0.0 && lp[0] < 1.0 &&
    200. lp[1] >= 0.0 && lp[1] < 1.0)
    201. {
    202. color rgb;
    203. float a = 1.0;
    204. if (pic == 0) rgb = TextureFetch(Filename0, lp, a);
    205. #define LAYER(x) else if (pic == x) rgb = TextureFetch(Filename##x, lp, a);
    206. //====LAYER-BEGIN====
    207. LAYER(0)
    208. LAYER(1)
    209. LAYER(2)
    210. LAYER(3)
    211. LAYER(4)
    212. LAYER(5)
    213. LAYER(6)
    214. LAYER(7)
    215. LAYER(8)
    216. LAYER(9)
    217. //====LAYER-END====
    218. #undef LAYER
    219. if (a > 0.0)
    220. {
    221. // Color randomness
    222. point clr = noise("cell", rndpoint, 2);
    223. // Alpha and Gamma randomness
    224. point arr = noise("cell", rndpoint, 3);
    225. float gr = mix(GammaMin, GammaMax, arr[1]);
    226. if (gamma + gr != 1.0)
    227. rgb = pow(rgb, gamma + gr);
    228. vector hsvTweak = mix(HSVMin, HSVMax, clr);
    229. float ar = mix(AlphaMin, AlphaMax, arr[0]);
    230. color hsv = transformc("rgb", "hsv", rgb);
    231. hsv[0] += hsvTweak[0]; // Offset the hue
    232. hsv[1] *= hsvTweak[1]; // Scale the saturation
    233. hsv[2] *= hsvTweak[2]; // Scale the value
    234. rgb = transformc("hsv", "rgb", hsv);
    235. // Apply alpha randomness
    236. rgb *= ar; a *= ar;
    237. if (Clamp)
    238. rgb = clamp(rgb, 0.0, 1.0);
    239. }
    240. Alpha = 1.0 - ((1.0-Alpha)*(1.0-a));
    241. Out = Out * (1.0-a) + rgb;
    242. }
    243. }
    244. }
    245. }
    246. }