Blender V4.3
texture_procedural.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cmath>
10#include <cstdio>
11#include <cstdlib>
12#include <cstring>
13
14#include "BLI_math_geom.h"
15#include "BLI_noise.h"
16#include "BLI_rand.h"
17#include "BLI_utildefines.h"
18
19#include "DNA_image_types.h"
20#include "DNA_material_types.h"
21#include "DNA_node_types.h"
22#include "DNA_texture_types.h"
23
25#include "IMB_imbuf_types.hh"
26
27#include "BKE_colorband.hh"
28#include "BKE_image.hh"
29
30#include "NOD_texture.h"
31
32#include "MEM_guardedalloc.h"
33
34#include "texture_common.h"
35
36#include "RE_texture.h"
37
39
44
46{
47 if (random_tex_array == nullptr) {
48 return;
49 }
51 random_tex_array = nullptr;
52}
53
54/* ------------------------------------------------------------------------- */
55
56static int blend(const Tex *tex, const float texvec[3], TexResult *texres)
57{
58 float x, y, t;
59
60 if (tex->flag & TEX_FLIPBLEND) {
61 x = texvec[1];
62 y = texvec[0];
63 }
64 else {
65 x = texvec[0];
66 y = texvec[1];
67 }
68
69 if (tex->stype == TEX_LIN) { /* Linear. */
70 texres->tin = (1.0f + x) / 2.0f;
71 }
72 else if (tex->stype == TEX_QUAD) { /* Quadratic. */
73 texres->tin = (1.0f + x) / 2.0f;
74 if (texres->tin < 0.0f) {
75 texres->tin = 0.0f;
76 }
77 else {
78 texres->tin *= texres->tin;
79 }
80 }
81 else if (tex->stype == TEX_EASE) { /* Ease. */
82 texres->tin = (1.0f + x) / 2.0f;
83 if (texres->tin <= 0.0f) {
84 texres->tin = 0.0f;
85 }
86 else if (texres->tin >= 1.0f) {
87 texres->tin = 1.0f;
88 }
89 else {
90 t = texres->tin * texres->tin;
91 texres->tin = (3.0f * t - 2.0f * t * texres->tin);
92 }
93 }
94 else if (tex->stype == TEX_DIAG) { /* Diagonal. */
95 texres->tin = (2.0f + x + y) / 4.0f;
96 }
97 else if (tex->stype == TEX_RAD) { /* Radial. */
98 texres->tin = (atan2f(y, x) / float(2 * M_PI) + 0.5f);
99 }
100 else { /* sphere TEX_SPHERE */
101 texres->tin = 1.0f - sqrtf(x * x + y * y + texvec[2] * texvec[2]);
102 if (texres->tin < 0.0f) {
103 texres->tin = 0.0f;
104 }
105 if (tex->stype == TEX_HALO) {
106 texres->tin *= texres->tin; /* Halo. */
107 }
108 }
109
110 BRICONT;
111
112 return TEX_INT;
113}
114
115/* ------------------------------------------------------------------------- */
116/* ************************************************************************* */
117
118/* newnoise: all noise-based types now have different noise-bases to choose from. */
119
120static int clouds(const Tex *tex, const float texvec[3], TexResult *texres)
121{
122 int rv = TEX_INT;
123
125 texvec[0],
126 texvec[1],
127 texvec[2],
130 tex->noisebasis);
131
132 if (tex->stype == TEX_COLOR) {
133 texres->trgba[0] = texres->tin;
135 texvec[1],
136 texvec[0],
137 texvec[2],
140 tex->noisebasis);
142 texvec[1],
143 texvec[2],
144 texvec[0],
147 tex->noisebasis);
149 texres->trgba[3] = 1.0;
150 return (rv | TEX_RGB);
151 }
152
153 BRICONT;
154
155 return rv;
156}
157
158/* creates a sine wave */
159static float tex_sin(float a)
160{
161 a = 0.5f + 0.5f * sinf(a);
162
163 return a;
164}
165
166/* creates a saw wave */
167static float tex_saw(float a)
168{
169 const float b = 2 * M_PI;
170
171 int n = int(a / b);
172 a -= n * b;
173 if (a < 0) {
174 a += b;
175 }
176 return a / b;
177}
178
179/* creates a triangle wave */
180static float tex_tri(float a)
181{
182 const float b = 2 * M_PI;
183 const float rmax = 1.0;
184
185 a = rmax - 2.0f * fabsf(floorf((a * (1.0f / b)) + 0.5f) - (a * (1.0f / b)));
186
187 return a;
188}
189
190/* computes basic wood intensity value at x,y,z */
191static float wood_int(const Tex *tex, float x, float y, float z)
192{
193 float wi = 0;
194 /* wave form: TEX_SIN=0, TEX_SAW=1, TEX_TRI=2. */
195 short wf = tex->noisebasis2;
196 /* wood type: TEX_BAND=0, TEX_RING=1, TEX_BANDNOISE=2, TEX_RINGNOISE=3. */
197 short wt = tex->stype;
198
199 float (*waveform[3])(float); /* create array of pointers to waveform functions */
200 waveform[0] = tex_sin; /* assign address of tex_sin() function to pointer array */
201 waveform[1] = tex_saw;
202 waveform[2] = tex_tri;
203
204 if ((wf > TEX_TRI) || (wf < TEX_SIN)) {
205 wf = 0; /* check to be sure noisebasis2 is initialized ahead of time */
206 }
207
208 if (wt == TEX_BAND) {
209 wi = waveform[wf]((x + y + z) * 10.0f);
210 }
211 else if (wt == TEX_RING) {
212 wi = waveform[wf](sqrtf(x * x + y * y + z * z) * 20.0f);
213 }
214 else if (wt == TEX_BANDNOISE) {
215 wi = tex->turbul *
218 wi = waveform[wf]((x + y + z) * 10.0f + wi);
219 }
220 else if (wt == TEX_RINGNOISE) {
221 wi = tex->turbul *
224 wi = waveform[wf](sqrtf(x * x + y * y + z * z) * 20.0f + wi);
225 }
226
227 return wi;
228}
229
230static int wood(const Tex *tex, const float texvec[3], TexResult *texres)
231{
232 int rv = TEX_INT;
233
234 texres->tin = wood_int(tex, texvec[0], texvec[1], texvec[2]);
235
236 BRICONT;
237
238 return rv;
239}
240
241/* computes basic marble intensity at x,y,z */
242static float marble_int(const Tex *tex, float x, float y, float z)
243{
244 float n, mi;
245 short wf = tex->noisebasis2; /* wave form: TEX_SIN=0, TEX_SAW=1, TEX_TRI=2 */
246 short mt = tex->stype; /* marble type: TEX_SOFT=0, TEX_SHARP=1, TEX_SHAPER=2 */
247
248 float (*waveform[3])(float); /* create array of pointers to waveform functions */
249 waveform[0] = tex_sin; /* assign address of tex_sin() function to pointer array */
250 waveform[1] = tex_saw;
251 waveform[2] = tex_tri;
252
253 if ((wf > TEX_TRI) || (wf < TEX_SIN)) {
254 wf = 0; /* check to be sure noisebasis2 isn't initialized ahead of time */
255 }
256
257 n = 5.0f * (x + y + z);
258
260 x,
261 y,
262 z,
265 tex->noisebasis);
266
267 if (mt >= TEX_SOFT) { /* TEX_SOFT always true */
268 mi = waveform[wf](mi);
269 if (mt == TEX_SHARP) {
270 mi = sqrtf(mi);
271 }
272 else if (mt == TEX_SHARPER) {
273 mi = sqrtf(sqrtf(mi));
274 }
275 }
276
277 return mi;
278}
279
280static int marble(const Tex *tex, const float texvec[3], TexResult *texres)
281{
282 int rv = TEX_INT;
283
284 texres->tin = marble_int(tex, texvec[0], texvec[1], texvec[2]);
285
286 BRICONT;
287
288 return rv;
289}
290
291/* ------------------------------------------------------------------------- */
292
293static int magic(const Tex *tex, const float texvec[3], TexResult *texres)
294{
295 float x, y, z, turb;
296 int n;
297
298 n = tex->noisedepth;
299 turb = tex->turbul / 5.0f;
300
301 x = sinf((texvec[0] + texvec[1] + texvec[2]) * 5.0f);
302 y = cosf((-texvec[0] + texvec[1] - texvec[2]) * 5.0f);
303 z = -cosf((-texvec[0] - texvec[1] + texvec[2]) * 5.0f);
304 if (n > 0) {
305 x *= turb;
306 y *= turb;
307 z *= turb;
308 y = -cosf(x - y + z);
309 y *= turb;
310 if (n > 1) {
311 x = cosf(x - y - z);
312 x *= turb;
313 if (n > 2) {
314 z = sinf(-x - y - z);
315 z *= turb;
316 if (n > 3) {
317 x = -cosf(-x + y - z);
318 x *= turb;
319 if (n > 4) {
320 y = -sinf(-x + y + z);
321 y *= turb;
322 if (n > 5) {
323 y = -cosf(-x + y + z);
324 y *= turb;
325 if (n > 6) {
326 x = cosf(x + y + z);
327 x *= turb;
328 if (n > 7) {
329 z = sinf(x + y - z);
330 z *= turb;
331 if (n > 8) {
332 x = -cosf(-x - y + z);
333 x *= turb;
334 if (n > 9) {
335 y = -sinf(x - y + z);
336 y *= turb;
337 }
338 }
339 }
340 }
341 }
342 }
343 }
344 }
345 }
346 }
347
348 if (turb != 0.0f) {
349 turb *= 2.0f;
350 x /= turb;
351 y /= turb;
352 z /= turb;
353 }
354 texres->trgba[0] = 0.5f - x;
355 texres->trgba[1] = 0.5f - y;
356 texres->trgba[2] = 0.5f - z;
357
358 texres->tin = (1.0f / 3.0f) * (texres->trgba[0] + texres->trgba[1] + texres->trgba[2]);
359
361 texres->trgba[3] = 1.0f;
362
363 return TEX_RGB;
364}
365
366/* ------------------------------------------------------------------------- */
367
368/* newnoise: stucci also modified to use different noisebasis */
369static int stucci(const Tex *tex, const float texvec[3], TexResult *texres)
370{
371 float b2, ofs;
372 int retval = TEX_INT;
373
375 texvec[0],
376 texvec[1],
377 texvec[2],
379 tex->noisebasis);
380
381 ofs = tex->turbul / 200.0f;
382
383 if (tex->stype) {
384 ofs *= (b2 * b2);
385 }
386
388 texvec[0],
389 texvec[1],
390 texvec[2] + ofs,
392 tex->noisebasis);
393
394 if (tex->stype == TEX_WALLOUT) {
395 texres->tin = 1.0f - texres->tin;
396 }
397
398 if (texres->tin < 0.0f) {
399 texres->tin = 0.0f;
400 }
401
402 return retval;
403}
404
405/* ------------------------------------------------------------------------- */
406/* newnoise: musgrave terrain noise types */
407
408static int mg_mFractalOrfBmTex(const Tex *tex, const float texvec[3], TexResult *texres)
409{
410 int rv = TEX_INT;
411 float (*mgravefunc)(float, float, float, float, float, float, int);
412
413 if (tex->stype == TEX_MFRACTAL) {
414 mgravefunc = BLI_noise_mg_multi_fractal;
415 }
416 else {
417 mgravefunc = BLI_noise_mg_fbm;
418 }
419
420 texres->tin = tex->ns_outscale * mgravefunc(texvec[0],
421 texvec[1],
422 texvec[2],
423 tex->mg_H,
426 tex->noisebasis);
427
428 BRICONT;
429
430 return rv;
431}
432
433static int mg_ridgedOrHybridMFTex(const Tex *tex, const float texvec[3], TexResult *texres)
434{
435 int rv = TEX_INT;
436 float (*mgravefunc)(float, float, float, float, float, float, float, float, int);
437
438 if (tex->stype == TEX_RIDGEDMF) {
440 }
441 else {
443 }
444
445 texres->tin = tex->ns_outscale * mgravefunc(texvec[0],
446 texvec[1],
447 texvec[2],
448 tex->mg_H,
451 tex->mg_offset,
452 tex->mg_gain,
453 tex->noisebasis);
454
455 BRICONT;
456
457 return rv;
458}
459
460static int mg_HTerrainTex(const Tex *tex, const float texvec[3], TexResult *texres)
461{
462 int rv = TEX_INT;
463
464 texres->tin = tex->ns_outscale * BLI_noise_mg_hetero_terrain(texvec[0],
465 texvec[1],
466 texvec[2],
467 tex->mg_H,
470 tex->mg_offset,
471 tex->noisebasis);
472
473 BRICONT;
474
475 return rv;
476}
477
478static int mg_distNoiseTex(const Tex *tex, const float texvec[3], TexResult *texres)
479{
480 int rv = TEX_INT;
481
483 texvec[0], texvec[1], texvec[2], tex->dist_amount, tex->noisebasis, tex->noisebasis2);
484
485 BRICONT;
486
487 return rv;
488}
489
490/* ------------------------------------------------------------------------- */
491/* newnoise: Voronoi texture type
492 *
493 * probably the slowest, especially with minkovsky, bump-mapping, could be done another way.
494 */
495
496static int voronoiTex(const Tex *tex, const float texvec[3], TexResult *texres)
497{
498 int rv = TEX_INT;
499 float da[4], pa[12]; /* distance and point coordinate arrays of 4 nearest neighbors */
500 float aw1 = fabsf(tex->vn_w1);
501 float aw2 = fabsf(tex->vn_w2);
502 float aw3 = fabsf(tex->vn_w3);
503 float aw4 = fabsf(tex->vn_w4);
504 float sc = (aw1 + aw2 + aw3 + aw4);
505 if (sc != 0.0f) {
506 sc = tex->ns_outscale / sc;
507 }
508
509 BLI_noise_voronoi(texvec[0], texvec[1], texvec[2], da, pa, tex->vn_mexp, tex->vn_distm);
510 texres->tin = sc * fabsf(dot_v4v4(&tex->vn_w1, da));
511
512 const bool is_color = ELEM(tex->vn_coltype, TEX_COL1, TEX_COL2, TEX_COL3);
513 if (is_color) {
514 float ca[3]; /* cell color */
515 BLI_noise_cell_v3(pa[0], pa[1], pa[2], ca);
516 texres->trgba[0] = aw1 * ca[0];
517 texres->trgba[1] = aw1 * ca[1];
518 texres->trgba[2] = aw1 * ca[2];
519 BLI_noise_cell_v3(pa[3], pa[4], pa[5], ca);
520 texres->trgba[0] += aw2 * ca[0];
521 texres->trgba[1] += aw2 * ca[1];
522 texres->trgba[2] += aw2 * ca[2];
523 BLI_noise_cell_v3(pa[6], pa[7], pa[8], ca);
524 texres->trgba[0] += aw3 * ca[0];
525 texres->trgba[1] += aw3 * ca[1];
526 texres->trgba[2] += aw3 * ca[2];
527 BLI_noise_cell_v3(pa[9], pa[10], pa[11], ca);
528 texres->trgba[0] += aw4 * ca[0];
529 texres->trgba[1] += aw4 * ca[1];
530 texres->trgba[2] += aw4 * ca[2];
532 float t1 = (da[1] - da[0]) * 10;
533 if (t1 > 1) {
534 t1 = 1;
535 }
536 if (tex->vn_coltype == TEX_COL3) {
537 t1 *= texres->tin;
538 }
539 else {
540 t1 *= sc;
541 }
542 texres->trgba[0] *= t1;
543 texres->trgba[1] *= t1;
544 texres->trgba[2] *= t1;
545 }
546 else {
547 texres->trgba[0] *= sc;
548 texres->trgba[1] *= sc;
549 texres->trgba[2] *= sc;
550 }
551 }
552
553 if (is_color) {
555 texres->trgba[3] = 1.0;
556 return (rv | TEX_RGB);
557 }
558
559 BRICONT;
560
561 return rv;
562}
563
564/* ------------------------------------------------------------------------- */
565
566static int texnoise(const Tex *tex, TexResult *texres, int thread)
567{
568 float div = 3.0;
569 int val, ran, loop, shift = 29;
570
572
573 loop = tex->noisedepth;
574
575 /* start from top bits since they have more variance */
576 val = ((ran >> shift) & 3);
577
578 while (loop--) {
579 shift -= 2;
580 val *= ((ran >> shift) & 3);
581 div *= 3.0f;
582 }
583
584 texres->tin = float(val) / div;
585
586 BRICONT;
587 return TEX_INT;
588}
589
590/* ------------------------------------------------------------------------- */
591
592static int cubemap_glob(const float n[3], float x, float y, float z, float *adr1, float *adr2)
593{
594 float x1, y1, z1, nor[3];
595 int ret;
596
597 if (n == nullptr) {
598 nor[0] = x;
599 nor[1] = y;
600 nor[2] = z; /* use local render coord */
601 }
602 else {
603 copy_v3_v3(nor, n);
604 }
605
606 x1 = fabsf(nor[0]);
607 y1 = fabsf(nor[1]);
608 z1 = fabsf(nor[2]);
609
610 if (z1 >= x1 && z1 >= y1) {
611 *adr1 = (x + 1.0f) / 2.0f;
612 *adr2 = (y + 1.0f) / 2.0f;
613 ret = 0;
614 }
615 else if (y1 >= x1 && y1 >= z1) {
616 *adr1 = (x + 1.0f) / 2.0f;
617 *adr2 = (z + 1.0f) / 2.0f;
618 ret = 1;
619 }
620 else {
621 *adr1 = (y + 1.0f) / 2.0f;
622 *adr2 = (z + 1.0f) / 2.0f;
623 ret = 2;
624 }
625 return ret;
626}
627
628/* ------------------------------------------------------------------------- */
629
630static void do_2d_mapping(
631 const MTex *mtex, float texvec[3], const float n[3], float dxt[3], float dyt[3])
632{
633 Tex *tex;
634 float fx, fy, fac1, area[8];
635 int ok, proj, areaflag = 0, wrap;
636
637 /* #MTex variables localized, only cube-map doesn't cooperate yet. */
638 wrap = mtex->mapping;
639 tex = mtex->tex;
640
641 if (!(dxt && dyt)) {
642
643 if (wrap == MTEX_FLAT) {
644 fx = (texvec[0] + 1.0f) / 2.0f;
645 fy = (texvec[1] + 1.0f) / 2.0f;
646 }
647 else if (wrap == MTEX_TUBE) {
648 map_to_tube(&fx, &fy, texvec[0], texvec[1], texvec[2]);
649 }
650 else if (wrap == MTEX_SPHERE) {
651 map_to_sphere(&fx, &fy, texvec[0], texvec[1], texvec[2]);
652 }
653 else {
654 cubemap_glob(n, texvec[0], texvec[1], texvec[2], &fx, &fy);
655 }
656
657 /* repeat */
658 if (tex->extend == TEX_REPEAT) {
659 if (tex->xrepeat > 1) {
660 float origf = fx *= tex->xrepeat;
661
662 if (fx > 1.0f) {
663 fx -= int(fx);
664 }
665 else if (fx < 0.0f) {
666 fx += 1 - int(fx);
667 }
668
669 if (tex->flag & TEX_REPEAT_XMIR) {
670 int orig = int(floor(origf));
671 if (orig & 1) {
672 fx = 1.0f - fx;
673 }
674 }
675 }
676 if (tex->yrepeat > 1) {
677 float origf = fy *= tex->yrepeat;
678
679 if (fy > 1.0f) {
680 fy -= int(fy);
681 }
682 else if (fy < 0.0f) {
683 fy += 1 - int(fy);
684 }
685
686 if (tex->flag & TEX_REPEAT_YMIR) {
687 int orig = int(floor(origf));
688 if (orig & 1) {
689 fy = 1.0f - fy;
690 }
691 }
692 }
693 }
694 /* crop */
695 if (tex->cropxmin != 0.0f || tex->cropxmax != 1.0f) {
696 fac1 = tex->cropxmax - tex->cropxmin;
697 fx = tex->cropxmin + fx * fac1;
698 }
699 if (tex->cropymin != 0.0f || tex->cropymax != 1.0f) {
700 fac1 = tex->cropymax - tex->cropymin;
701 fy = tex->cropymin + fy * fac1;
702 }
703
704 texvec[0] = fx;
705 texvec[1] = fy;
706 }
707 else {
708
709 if (wrap == MTEX_FLAT) {
710 fx = (texvec[0] + 1.0f) / 2.0f;
711 fy = (texvec[1] + 1.0f) / 2.0f;
712 dxt[0] /= 2.0f;
713 dxt[1] /= 2.0f;
714 dxt[2] /= 2.0f;
715 dyt[0] /= 2.0f;
716 dyt[1] /= 2.0f;
717 dyt[2] /= 2.0f;
718 }
719 else if (ELEM(wrap, MTEX_TUBE, MTEX_SPHERE)) {
720 /* exception: the seam behind (y<0.0) */
721 ok = 1;
722 if (texvec[1] <= 0.0f) {
723 fx = texvec[0] + dxt[0];
724 fy = texvec[0] + dyt[0];
725 if (fx >= 0.0f && fy >= 0.0f && texvec[0] >= 0.0f) {
726 /* pass */
727 }
728 else if (fx <= 0.0f && fy <= 0.0f && texvec[0] <= 0.0f) {
729 /* pass */
730 }
731 else {
732 ok = 0;
733 }
734 }
735
736 if (ok) {
737 if (wrap == MTEX_TUBE) {
738 map_to_tube(area, area + 1, texvec[0], texvec[1], texvec[2]);
740 area + 2, area + 3, texvec[0] + dxt[0], texvec[1] + dxt[1], texvec[2] + dxt[2]);
742 area + 4, area + 5, texvec[0] + dyt[0], texvec[1] + dyt[1], texvec[2] + dyt[2]);
743 }
744 else {
745 map_to_sphere(area, area + 1, texvec[0], texvec[1], texvec[2]);
747 area + 2, area + 3, texvec[0] + dxt[0], texvec[1] + dxt[1], texvec[2] + dxt[2]);
749 area + 4, area + 5, texvec[0] + dyt[0], texvec[1] + dyt[1], texvec[2] + dyt[2]);
750 }
751 areaflag = 1;
752 }
753 else {
754 if (wrap == MTEX_TUBE) {
755 map_to_tube(&fx, &fy, texvec[0], texvec[1], texvec[2]);
756 }
757 else {
758 map_to_sphere(&fx, &fy, texvec[0], texvec[1], texvec[2]);
759 }
760 dxt[0] /= 2.0f;
761 dxt[1] /= 2.0f;
762 dyt[0] /= 2.0f;
763 dyt[1] /= 2.0f;
764 }
765 }
766 else {
767
768 proj = cubemap_glob(n, texvec[0], texvec[1], texvec[2], &fx, &fy);
769
770 if (proj == 1) {
771 std::swap(dxt[1], dxt[2]);
772 std::swap(dyt[1], dyt[2]);
773 }
774 else if (proj == 2) {
775 float f1 = dxt[0], f2 = dyt[0];
776 dxt[0] = dxt[1];
777 dyt[0] = dyt[1];
778 dxt[1] = dxt[2];
779 dyt[1] = dyt[2];
780 dxt[2] = f1;
781 dyt[2] = f2;
782 }
783
784 dxt[0] *= 0.5f;
785 dxt[1] *= 0.5f;
786 dxt[2] *= 0.5f;
787
788 dyt[0] *= 0.5f;
789 dyt[1] *= 0.5f;
790 dyt[2] *= 0.5f;
791 }
792
793 /* If area, then recalculate `dxt[]` and `dyt[]` */
794 if (areaflag) {
795 fx = area[0];
796 fy = area[1];
797 dxt[0] = area[2] - fx;
798 dxt[1] = area[3] - fy;
799 dyt[0] = area[4] - fx;
800 dyt[1] = area[5] - fy;
801 }
802
803 /* repeat */
804 if (tex->extend == TEX_REPEAT) {
805 float max = 1.0f;
806 if (tex->xrepeat > 1) {
807 float origf = fx *= tex->xrepeat;
808
809 /* TXF: omit mirror here, see comments in do_material_tex() after do_2d_mapping() call */
810 if (tex->texfilter == TXF_BOX) {
811 if (fx > 1.0f) {
812 fx -= int(fx);
813 }
814 else if (fx < 0.0f) {
815 fx += 1 - int(fx);
816 }
817
818 if (tex->flag & TEX_REPEAT_XMIR) {
819 int orig = int(floor(origf));
820 if (orig & 1) {
821 fx = 1.0f - fx;
822 }
823 }
824 }
825
826 max = tex->xrepeat;
827
828 dxt[0] *= tex->xrepeat;
829 dyt[0] *= tex->xrepeat;
830 }
831 if (tex->yrepeat > 1) {
832 float origf = fy *= tex->yrepeat;
833
834 /* TXF: omit mirror here, see comments in do_material_tex() after do_2d_mapping() call */
835 if (tex->texfilter == TXF_BOX) {
836 if (fy > 1.0f) {
837 fy -= int(fy);
838 }
839 else if (fy < 0.0f) {
840 fy += 1 - int(fy);
841 }
842
843 if (tex->flag & TEX_REPEAT_YMIR) {
844 int orig = int(floor(origf));
845 if (orig & 1) {
846 fy = 1.0f - fy;
847 }
848 }
849 }
850
851 if (max < tex->yrepeat) {
852 max = tex->yrepeat;
853 }
854
855 dxt[1] *= tex->yrepeat;
856 dyt[1] *= tex->yrepeat;
857 }
858 if (max != 1.0f) {
859 dxt[2] *= max;
860 dyt[2] *= max;
861 }
862 }
863 /* crop */
864 if (tex->cropxmin != 0.0f || tex->cropxmax != 1.0f) {
865 fac1 = tex->cropxmax - tex->cropxmin;
866 fx = tex->cropxmin + fx * fac1;
867 dxt[0] *= fac1;
868 dyt[0] *= fac1;
869 }
870 if (tex->cropymin != 0.0f || tex->cropymax != 1.0f) {
871 fac1 = tex->cropymax - tex->cropymin;
872 fy = tex->cropymin + fy * fac1;
873 dxt[1] *= fac1;
874 dyt[1] *= fac1;
875 }
876
877 texvec[0] = fx;
878 texvec[1] = fy;
879 }
880}
881
882/* ************************************** */
883
884static int multitex(Tex *tex,
885 const float texvec[3],
886 float dxt[3],
887 float dyt[3],
888 int osatex,
889 TexResult *texres,
890 const short thread,
891 const short which_output,
892 ImagePool *pool,
893 const bool skip_load_image,
894 const bool texnode_preview,
895 const bool use_nodes)
896{
897 float tmpvec[3];
898 int retval = 0; /* return value, TEX_INT or TEX_RGB. */
899
900 texres->talpha = false; /* Is set when image texture returns alpha (considered pre-multiplied) */
901
902 if (use_nodes && tex->use_nodes && tex->nodetree) {
903 const float cfra = 1.0f; /* This was only set for Blender Internal render before. */
904 retval = ntreeTexExecTree(tex->nodetree,
905 texres,
906 texvec,
907 dxt,
908 dyt,
909 osatex,
910 thread,
911 tex,
912 which_output,
913 cfra,
914 texnode_preview,
915 nullptr);
916 }
917 else {
918 switch (tex->type) {
919 case 0:
920 texres->tin = 0.0f;
921 return 0;
922 case TEX_CLOUDS:
923 retval = clouds(tex, texvec, texres);
924 break;
925 case TEX_WOOD:
926 retval = wood(tex, texvec, texres);
927 break;
928 case TEX_MARBLE:
929 retval = marble(tex, texvec, texres);
930 break;
931 case TEX_MAGIC:
932 retval = magic(tex, texvec, texres);
933 break;
934 case TEX_BLEND:
935 retval = blend(tex, texvec, texres);
936 break;
937 case TEX_STUCCI:
938 retval = stucci(tex, texvec, texres);
939 break;
940 case TEX_NOISE:
941 retval = texnoise(tex, texres, thread);
942 break;
943 case TEX_IMAGE:
944 if (osatex) {
945 retval = imagewraposa(
946 tex, tex->ima, nullptr, texvec, dxt, dyt, texres, pool, skip_load_image);
947 }
948 else {
949 retval = imagewrap(tex, tex->ima, texvec, texres, pool, skip_load_image);
950 }
951 if (tex->ima) {
953 }
954 break;
955 case TEX_MUSGRAVE:
956 /* newnoise: musgrave types */
957
958 /* NOTE(@ton): added this, for Blender convention reason.
959 * NOTE(@artificer): added the use of tmpvec to avoid scaling texvec. */
960 copy_v3_v3(tmpvec, texvec);
961 mul_v3_fl(tmpvec, 1.0f / tex->noisesize);
962
963 switch (tex->stype) {
964 case TEX_MFRACTAL:
965 case TEX_FBM:
966 retval = mg_mFractalOrfBmTex(tex, tmpvec, texres);
967 break;
968 case TEX_RIDGEDMF:
969 case TEX_HYBRIDMF:
970 retval = mg_ridgedOrHybridMFTex(tex, tmpvec, texres);
971 break;
972 case TEX_HTERRAIN:
973 retval = mg_HTerrainTex(tex, tmpvec, texres);
974 break;
975 }
976 break;
977 /* newnoise: voronoi type */
978 case TEX_VORONOI:
979 /* NOTE(@ton): added this, for Blender convention reason.
980 * NOTE(@artificer): added the use of tmpvec to avoid scaling texvec. */
981 copy_v3_v3(tmpvec, texvec);
982 mul_v3_fl(tmpvec, 1.0f / tex->noisesize);
983
984 retval = voronoiTex(tex, tmpvec, texres);
985 break;
986 case TEX_DISTNOISE:
987 /* NOTE(@ton): added this, for Blender convention reason.
988 * NOTE(@artificer): added the use of tmpvec to avoid scaling texvec. */
989 copy_v3_v3(tmpvec, texvec);
990 mul_v3_fl(tmpvec, 1.0f / tex->noisesize);
991
992 retval = mg_distNoiseTex(tex, tmpvec, texres);
993 break;
994 }
995 }
996
997 if (tex->flag & TEX_COLORBAND) {
998 float col[4];
999 if (BKE_colorband_evaluate(tex->coba, texres->tin, col)) {
1000 texres->talpha = true;
1001 copy_v4_v4(texres->trgba, col);
1002 retval |= TEX_RGB;
1003 }
1004 }
1005 return retval;
1006}
1007
1009 const float texvec[3],
1010 float dxt[3],
1011 float dyt[3],
1012 int osatex,
1013 TexResult *texres,
1014 const short thread,
1015 short which_output,
1016 const MTex *mtex,
1017 ImagePool *pool,
1018 const bool scene_color_manage,
1019 const bool skip_load_image,
1020 const bool texnode_preview,
1021 const bool use_nodes)
1022{
1023 if (tex == nullptr) {
1024 memset(texres, 0, sizeof(TexResult));
1025 return 0;
1026 }
1027
1028 if (mtex) {
1029 which_output = mtex->which_output;
1030 }
1031
1032 if (tex->type == TEX_IMAGE) {
1033 int retval;
1034
1035 if (mtex) {
1036 float texvec_l[3];
1037 copy_v3_v3(texvec_l, texvec);
1038 /* we have mtex, use it for 2d mapping images only */
1039 do_2d_mapping(mtex, texvec_l, nullptr, dxt, dyt);
1040 retval = multitex(tex,
1041 texvec_l,
1042 dxt,
1043 dyt,
1044 osatex,
1045 texres,
1046 thread,
1047 which_output,
1048 pool,
1049 skip_load_image,
1050 texnode_preview,
1051 use_nodes);
1052
1053 if (mtex->mapto & MAP_COL) {
1054 ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
1055
1056 /* don't linearize float buffers, assumed to be linear */
1057 if (ibuf != nullptr && ibuf->float_buffer.data == nullptr && (retval & TEX_RGB) &&
1058 scene_color_manage)
1059 {
1061 ibuf->byte_buffer.colorspace);
1062 }
1063
1064 BKE_image_pool_release_ibuf(tex->ima, ibuf, pool);
1065 }
1066 }
1067 else {
1068 /* we don't have mtex, do default flat 2d projection */
1069 MTex localmtex;
1070 float texvec_l[3], dxt_l[3], dyt_l[3];
1071
1072 localmtex.mapping = MTEX_FLAT;
1073 localmtex.tex = tex;
1074 localmtex.object = nullptr;
1075 localmtex.texco = TEXCO_ORCO;
1076
1077 copy_v3_v3(texvec_l, texvec);
1078 if (dxt && dyt) {
1079 copy_v3_v3(dxt_l, dxt);
1080 copy_v3_v3(dyt_l, dyt);
1081 }
1082 else {
1083 zero_v3(dxt_l);
1084 zero_v3(dyt_l);
1085 }
1086
1087 do_2d_mapping(&localmtex, texvec_l, nullptr, dxt_l, dyt_l);
1088 retval = multitex(tex,
1089 texvec_l,
1090 dxt_l,
1091 dyt_l,
1092 osatex,
1093 texres,
1094 thread,
1095 which_output,
1096 pool,
1097 skip_load_image,
1098 texnode_preview,
1099 use_nodes);
1100
1101 {
1102 ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
1103
1104 /* don't linearize float buffers, assumed to be linear */
1105 if (ibuf != nullptr && ibuf->float_buffer.data == nullptr && (retval & TEX_RGB) &&
1106 scene_color_manage)
1107 {
1109 ibuf->byte_buffer.colorspace);
1110 }
1111
1112 BKE_image_pool_release_ibuf(tex->ima, ibuf, pool);
1113 }
1114 }
1115
1116 return retval;
1117 }
1118
1119 return multitex(tex,
1120 texvec,
1121 dxt,
1122 dyt,
1123 osatex,
1124 texres,
1125 thread,
1126 which_output,
1127 pool,
1128 skip_load_image,
1129 texnode_preview,
1130 use_nodes);
1131}
1132
1134 const float texvec[3],
1135 float dxt[3],
1136 float dyt[3],
1137 int osatex,
1138 TexResult *texres,
1139 const short thread,
1140 short which_output,
1141 const MTex *mtex,
1142 ImagePool *pool)
1143{
1145 texvec,
1146 dxt,
1147 dyt,
1148 osatex,
1149 texres,
1150 thread,
1151 which_output,
1152 mtex,
1153 pool,
1154 true,
1155 false,
1156 false,
1157 true);
1158}
1159
1161 const float texvec[3],
1162 float dxt[3],
1163 float dyt[3],
1164 int osatex,
1165 TexResult *texres,
1166 const short thread,
1167 ImagePool *pool,
1168 bool scene_color_manage,
1169 const bool skip_load_image)
1170{
1172 texvec,
1173 dxt,
1174 dyt,
1175 osatex,
1176 texres,
1177 thread,
1178 0,
1179 nullptr,
1180 pool,
1181 scene_color_manage,
1182 skip_load_image,
1183 false,
1184 true);
1185}
1186
1188 const float texvec[3],
1189 TexResult *texres,
1190 ImagePool *pool,
1191 bool scene_color_manage,
1192 const bool skip_load_image)
1193{
1195 texvec,
1196 nullptr,
1197 nullptr,
1198 0,
1199 texres,
1200 0,
1201 0,
1202 nullptr,
1203 pool,
1204 scene_color_manage,
1205 skip_load_image,
1206 false,
1207 false);
1208}
1209
1210/* ------------------------------------------------------------------------- */
1211
1212float texture_value_blend(float tex, float out, float fact, float facg, int blendtype)
1213{
1214 float in = 0.0, facm, col, scf;
1215 int flip = (facg < 0.0f);
1216
1217 facg = fabsf(facg);
1218
1219 fact *= facg;
1220 facm = 1.0f - fact;
1221 if (flip) {
1222 std::swap(fact, facm);
1223 }
1224
1225 switch (blendtype) {
1226 case MTEX_BLEND:
1227 in = fact * tex + facm * out;
1228 break;
1229
1230 case MTEX_MUL:
1231 facm = 1.0f - facg;
1232 in = (facm + fact * tex) * out;
1233 break;
1234
1235 case MTEX_SCREEN:
1236 facm = 1.0f - facg;
1237 in = 1.0f - (facm + fact * (1.0f - tex)) * (1.0f - out);
1238 break;
1239
1240 case MTEX_OVERLAY:
1241 facm = 1.0f - facg;
1242 if (out < 0.5f) {
1243 in = out * (facm + 2.0f * fact * tex);
1244 }
1245 else {
1246 in = 1.0f - (facm + 2.0f * fact * (1.0f - tex)) * (1.0f - out);
1247 }
1248 break;
1249
1250 case MTEX_SUB:
1251 fact = -fact;
1253 case MTEX_ADD:
1254 in = fact * tex + out;
1255 break;
1256
1257 case MTEX_DIV:
1258 if (tex != 0.0f) {
1259 in = facm * out + fact * out / tex;
1260 }
1261 break;
1262
1263 case MTEX_DIFF:
1264 in = facm * out + fact * fabsf(tex - out);
1265 break;
1266
1267 case MTEX_DARK:
1268 in = min_ff(out, tex) * fact + out * facm;
1269 break;
1270
1271 case MTEX_LIGHT:
1272 col = fact * tex;
1273 if (col > out) {
1274 in = col;
1275 }
1276 else {
1277 in = out;
1278 }
1279 break;
1280
1281 case MTEX_SOFT_LIGHT:
1282 scf = 1.0f - (1.0f - tex) * (1.0f - out);
1283 in = facm * out + fact * ((1.0f - out) * tex * out) + (out * scf);
1284 break;
1285
1286 case MTEX_LIN_LIGHT:
1287 if (tex > 0.5f) {
1288 in = out + fact * (2.0f * (tex - 0.5f));
1289 }
1290 else {
1291 in = out + fact * (2.0f * tex - 1.0f);
1292 }
1293 break;
1294 }
1295
1296 return in;
1297}
1298
1299/* ------------------------------------------------------------------------- */
1300
1301bool RE_texture_evaluate(const MTex *mtex,
1302 const float vec[3],
1303 const int thread,
1304 ImagePool *pool,
1305 const bool skip_load_image,
1306 const bool texnode_preview,
1307 /* Return arguments. */
1308 float *r_intensity,
1309 float r_rgba[4])
1310{
1311 Tex *tex;
1312 TexResult texr;
1313 float dxt[3], dyt[3], texvec[3];
1314 int rgb;
1315
1316 tex = mtex->tex;
1317 if (tex == nullptr) {
1318 return false;
1319 }
1320
1321 /* placement */
1322 if (mtex->projx) {
1323 texvec[0] = mtex->size[0] * (vec[mtex->projx - 1] + mtex->ofs[0]);
1324 }
1325 else {
1326 texvec[0] = mtex->size[0] * (mtex->ofs[0]);
1327 }
1328
1329 if (mtex->projy) {
1330 texvec[1] = mtex->size[1] * (vec[mtex->projy - 1] + mtex->ofs[1]);
1331 }
1332 else {
1333 texvec[1] = mtex->size[1] * (mtex->ofs[1]);
1334 }
1335
1336 if (mtex->projz) {
1337 texvec[2] = mtex->size[2] * (vec[mtex->projz - 1] + mtex->ofs[2]);
1338 }
1339 else {
1340 texvec[2] = mtex->size[2] * (mtex->ofs[2]);
1341 }
1342
1343 /* texture */
1344 if (tex->type == TEX_IMAGE) {
1345 do_2d_mapping(mtex, texvec, nullptr, dxt, dyt);
1346 }
1347
1348 rgb = multitex(tex,
1349 texvec,
1350 dxt,
1351 dyt,
1352 0,
1353 &texr,
1354 thread,
1355 mtex->which_output,
1356 pool,
1357 skip_load_image,
1358 texnode_preview,
1359 true);
1360
1361 if (rgb) {
1363 }
1364 else {
1365 copy_v3_fl3(texr.trgba, mtex->r, mtex->g, mtex->b);
1366 }
1367
1368 *r_intensity = texr.tin;
1369 copy_v4_v4(r_rgba, texr.trgba);
1370
1371 return (rgb != 0);
1372}
bool BKE_colorband_evaluate(const ColorBand *coba, float in, float out[4])
Definition colorband.cc:396
void BKE_image_tag_time(Image *ima)
ImBuf * BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool)
void BKE_image_pool_release_ibuf(Image *ima, ImBuf *ibuf, ImagePool *pool)
#define ATTR_FALLTHROUGH
MINLINE float min_ff(float a, float b)
#define M_PI
bool map_to_sphere(float *r_u, float *r_v, float x, float y, float z)
bool map_to_tube(float *r_u, float *r_v, float x, float y, float z)
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE float dot_v4v4(const float a[4], const float b[4]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v3_fl3(float v[3], float x, float y, float z)
MINLINE void zero_v3(float r[3])
float BLI_noise_mg_hetero_terrain(float x, float y, float z, float H, float lacunarity, float octaves, float offset, int noisebasis)
Definition noise.c:1391
float BLI_noise_mg_multi_fractal(float x, float y, float z, float H, float lacunarity, float octaves, int noisebasis)
Definition noise.c:1332
float BLI_noise_mg_ridged_multi_fractal(float x, float y, float z, float H, float lacunarity, float octaves, float offset, float gain, int noisebasis)
Definition noise.c:1537
float BLI_noise_mg_variable_lacunarity(float x, float y, float z, float distortion, int nbas1, int nbas2)
Definition noise.c:1608
float BLI_noise_generic_noise(float noisesize, float x, float y, float z, bool hard, int noisebasis)
Definition noise.c:1153
void BLI_noise_voronoi(float x, float y, float z, float *da, float *pa, float me, int dtype)
Definition noise.c:915
float BLI_noise_mg_fbm(float x, float y, float z, float H, float lacunarity, float octaves, int noisebasis)
Definition noise.c:1272
void BLI_noise_cell_v3(float x, float y, float z, float r_ca[3])
Definition noise.c:1131
float BLI_noise_mg_hybrid_multi_fractal(float x, float y, float z, float H, float lacunarity, float octaves, float offset, float gain, int noisebasis)
Definition noise.c:1461
float BLI_noise_generic_turbulence(float noisesize, float x, float y, float z, int oct, bool hard, int noisebasis)
Definition noise.c:1210
Random number functions.
void BLI_rng_threaded_free(struct RNG_THREAD_ARRAY *rngarr) ATTR_NONNULL(1)
Definition rand.cc:248
RNG_THREAD_ARRAY * BLI_rng_threaded_new(void)
Definition rand.cc:235
int BLI_rng_thread_rand(RNG_THREAD_ARRAY *rngarr, int thread) ATTR_WARN_UNUSED_RESULT
Definition rand.cc:253
#define ELEM(...)
@ TEXCO_ORCO
@ TEX_BLEND
@ TEX_MARBLE
@ TEX_NOISE
@ TEX_IMAGE
@ TEX_WOOD
@ TEX_CLOUDS
@ TEX_DISTNOISE
@ TEX_VORONOI
@ TEX_STUCCI
@ TEX_MAGIC
@ TEX_MUSGRAVE
@ TEX_COL2
@ TEX_COL1
@ TEX_COL3
@ MTEX_FLAT
@ MTEX_SPHERE
@ MTEX_TUBE
@ TEX_SHARPER
@ TEX_SOFT
@ TEX_SHARP
@ TEX_INT
@ TEX_RGB
@ MTEX_DIFF
@ MTEX_DIV
@ MTEX_MUL
@ MTEX_DARK
@ MTEX_LIGHT
@ MTEX_BLEND
@ MTEX_SOFT_LIGHT
@ MTEX_LIN_LIGHT
@ MTEX_SUB
@ MTEX_ADD
@ MTEX_OVERLAY
@ MTEX_SCREEN
@ TEX_SIN
@ TEX_TRI
@ TEX_BANDNOISE
@ TEX_RINGNOISE
@ TEX_RING
@ TEX_BAND
@ TEX_DIAG
@ TEX_EASE
@ TEX_HALO
@ TEX_QUAD
@ TEX_RAD
@ TEX_LIN
@ TEX_REPEAT_YMIR
@ TEX_FLIPBLEND
@ TEX_COLORBAND
@ TEX_REPEAT_XMIR
@ TEX_HYBRIDMF
@ TEX_MFRACTAL
@ TEX_HTERRAIN
@ TEX_FBM
@ TEX_RIDGEDMF
@ TEX_COLOR
@ TEX_WALLOUT
@ TEX_NOISESOFT
@ TXF_BOX
@ TEX_REPEAT
void IMB_colormanagement_colorspace_to_scene_linear_v3(float pixel[3], ColorSpace *colorspace)
BLI_INLINE float IMB_colormanagement_get_luminance(const float rgb[3])
Contains defines and structs used throughout the imbuf module.
Read Guarded memory(de)allocation.
int ntreeTexExecTree(struct bNodeTree *ntree, struct TexResult *target, const float co[3], float dxt[3], float dyt[3], int osatex, short thread, const struct Tex *tex, short which_output, int cfra, int preview, struct MTex *mtex)
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
local_group_size(16, 16) .push_constant(Type b
#define sinf(x)
#define cosf(x)
#define atan2f(x, y)
#define floorf(x)
#define fabsf(x)
#define sqrtf(x)
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
uint col
ccl_device_inline float2 floor(const float2 a)
static float turb(float x, float y, float z, int oct, int hard, int nb, float ampscale, float freqscale)
float wrap(float value, float max, float min)
Definition node_math.h:71
Frequency::GEOMETRY nor[]
return ret
ColorSpace * colorspace
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer
short texco
short which_output
float ofs[3]
short mapto
struct Object * object
float size[3]
struct Tex * tex
float tin
Definition RE_texture.h:87
float trgba[4]
Definition RE_texture.h:88
float cropymin
float dist_amount
float noisesize
short xrepeat
float vn_w4
short noisedepth
float ns_outscale
short noisetype
float vn_w2
float cropxmax
float cropymax
float mg_lacunarity
float mg_offset
char use_nodes
float vn_mexp
float mg_gain
short noisebasis2
short vn_coltype
short stype
float mg_octaves
struct ImageUser iuser
struct ColorBand * coba
short vn_distm
float cropxmin
float vn_w3
struct bNodeTree * nodetree
short noisebasis
float vn_w1
struct Image * ima
short extend
short yrepeat
float turbul
#define BRICONT
#define BRICONTRGB
int imagewrap(struct Tex *tex, struct Image *ima, const float texvec[3], struct TexResult *texres, struct ImagePool *pool, bool skip_load_image)
int imagewraposa(struct Tex *tex, struct Image *ima, struct ImBuf *ibuf, const float texvec[3], const float DXT[2], const float DYT[2], struct TexResult *texres, struct ImagePool *pool, bool skip_load_image)
static float tex_sin(float a)
int multitex_nodes(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, const short thread, short which_output, const MTex *mtex, ImagePool *pool)
static int mg_mFractalOrfBmTex(const Tex *tex, const float texvec[3], TexResult *texres)
static int stucci(const Tex *tex, const float texvec[3], TexResult *texres)
static void do_2d_mapping(const MTex *mtex, float texvec[3], const float n[3], float dxt[3], float dyt[3])
static int voronoiTex(const Tex *tex, const float texvec[3], TexResult *texres)
static RNG_THREAD_ARRAY * random_tex_array
static int multitex_nodes_intern(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, const short thread, short which_output, const MTex *mtex, ImagePool *pool, const bool scene_color_manage, const bool skip_load_image, const bool texnode_preview, const bool use_nodes)
static float tex_saw(float a)
static int mg_distNoiseTex(const Tex *tex, const float texvec[3], TexResult *texres)
static float wood_int(const Tex *tex, float x, float y, float z)
static int mg_ridgedOrHybridMFTex(const Tex *tex, const float texvec[3], TexResult *texres)
void RE_texture_rng_init()
static int mg_HTerrainTex(const Tex *tex, const float texvec[3], TexResult *texres)
bool RE_texture_evaluate(const MTex *mtex, const float vec[3], const int thread, ImagePool *pool, const bool skip_load_image, const bool texnode_preview, float *r_intensity, float r_rgba[4])
static int multitex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, const short thread, const short which_output, ImagePool *pool, const bool skip_load_image, const bool texnode_preview, const bool use_nodes)
static int cubemap_glob(const float n[3], float x, float y, float z, float *adr1, float *adr2)
static int magic(const Tex *tex, const float texvec[3], TexResult *texres)
int multitex_ext(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, const short thread, ImagePool *pool, bool scene_color_manage, const bool skip_load_image)
static float marble_int(const Tex *tex, float x, float y, float z)
static int texnoise(const Tex *tex, TexResult *texres, int thread)
void RE_texture_rng_exit()
int multitex_ext_safe(Tex *tex, const float texvec[3], TexResult *texres, ImagePool *pool, bool scene_color_manage, const bool skip_load_image)
float texture_value_blend(float tex, float out, float fact, float facg, int blendtype)
static float tex_tri(float a)
static int clouds(const Tex *tex, const float texvec[3], TexResult *texres)
float max