Welcome to mirror list, hosted at ThFree Co, Russian Federation.

magic.h « svm « kernel « cycles « intern - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: cdd73a7829ac3dfe1d062c5dc72f88e9d42fbd4d (plain)
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
 * Copyright 2011-2013 Blender Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

CCL_NAMESPACE_BEGIN

/* Magic */

ccl_device_noinline_cpu float3 svm_magic(float3 p, float scale, int n, float distortion)
{
  /*
   * Prevent NaNs due to input p
   * Sin and Cosine are periodic about [0 2*PI) so the following
   * will yield a more accurate result. As it stops the input values
   * going out of range for floats which caused a NaN. The
   * calculation of (px + py + pz)*5 can cause an Inf when one or more
   * values are very large the cos or sin of this results in a NaN
   * It also addresses the case where one dimension is large relative
   * to another which caused banding due to the loss of precision in the
   * smaller value. This is due to the value in the -2*PI to 2*PI range
   * effectively being lost due to floating point precision.
   */
  float px = fmodf(p.x, M_2PI_F);
  float py = fmodf(p.y, M_2PI_F);
  float pz = fmodf(p.z, M_2PI_F);

  float x = sinf((px + py + pz) * 5.0f * scale);
  float y = cosf((-px + py - pz) * 5.0f * scale);
  float z = -cosf((-px - py + pz) * 5.0f * scale);

  if (n > 0) {
    x *= distortion;
    y *= distortion;
    z *= distortion;
    y = -cosf(x - y + z);
    y *= distortion;

    if (n > 1) {
      x = cosf(x - y - z);
      x *= distortion;

      if (n > 2) {
        z = sinf(-x - y - z);
        z *= distortion;

        if (n > 3) {
          x = -cosf(-x + y - z);
          x *= distortion;

          if (n > 4) {
            y = -sinf(-x + y + z);
            y *= distortion;

            if (n > 5) {
              y = -cosf(-x + y + z);
              y *= distortion;

              if (n > 6) {
                x = cosf(x + y + z);
                x *= distortion;

                if (n > 7) {
                  z = sinf(x + y - z);
                  z *= distortion;

                  if (n > 8) {
                    x = -cosf(-x - y + z);
                    x *= distortion;

                    if (n > 9) {
                      y = -sinf(x - y + z);
                      y *= distortion;
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }

  if (distortion != 0.0f) {
    distortion *= 2.0f;
    x /= distortion;
    y /= distortion;
    z /= distortion;
  }

  return make_float3(0.5f - x, 0.5f - y, 0.5f - z);
}

ccl_device_noinline int svm_node_tex_magic(
    KernelGlobals kg, ccl_private ShaderData *sd, ccl_private float *stack, uint4 node, int offset)
{
  uint depth;
  uint scale_offset, distortion_offset, co_offset, fac_offset, color_offset;

  svm_unpack_node_uchar3(node.y, &depth, &color_offset, &fac_offset);
  svm_unpack_node_uchar3(node.z, &co_offset, &scale_offset, &distortion_offset);

  uint4 node2 = read_node(kg, &offset);
  float3 co = stack_load_float3(stack, co_offset);
  float scale = stack_load_float_default(stack, scale_offset, node2.x);
  float distortion = stack_load_float_default(stack, distortion_offset, node2.y);

  float3 color = svm_magic(co, scale, depth, distortion);

  if (stack_valid(fac_offset))
    stack_store_float(stack, fac_offset, average(color));
  if (stack_valid(color_offset))
    stack_store_float3(stack, color_offset, color);
  return offset;
}

CCL_NAMESPACE_END