48 float4 encoded_structure_tensor =
float4(inputs[2]->get_elem(it.x, it.y));
49 float dxdx = encoded_structure_tensor.x;
50 float dxdy = encoded_structure_tensor.y;
51 float dydy = encoded_structure_tensor.w;
55 float eigenvalue_first_term = (dxdx + dydy) / 2.0f;
56 float eigenvalue_square_root_term =
sqrt(square(dxdx - dydy) + 4.0f * square(dxdy)) / 2.0f;
57 float first_eigenvalue = eigenvalue_first_term + eigenvalue_square_root_term;
58 float second_eigenvalue = eigenvalue_first_term - eigenvalue_square_root_term;
63 float2 eigenvector =
float2(first_eigenvalue - dxdx, -dxdy);
64 float eigenvector_length =
length(eigenvector);
65 float2 unit_eigenvector = eigenvector_length != 0.0f ? eigenvector / eigenvector_length :
71 float eigenvalue_sum = first_eigenvalue + second_eigenvalue;
72 float eigenvalue_difference = first_eigenvalue - second_eigenvalue;
73 float anisotropy = eigenvalue_sum > 0.0f ? eigenvalue_difference / eigenvalue_sum : 0.0f;
75 float radius =
max(0.0f, *inputs[1]->get_elem(it.x, it.y));
77 copy_v4_v4(it.out, inputs[0]->get_elem(it.x, it.y));
87 float ellipse_width = ellipse_width_factor * radius;
88 float ellipse_height = radius / ellipse_width_factor;
93 float cosine = unit_eigenvector.x;
94 float sine = unit_eigenvector.y;
100 float2(cosine / ellipse_width, -sine / ellipse_height),
101 float2(sine / ellipse_width, cosine / ellipse_height));
111 float2 ellipse_major_axis = ellipse_width * unit_eigenvector;
112 float2 ellipse_minor_axis = ellipse_height *
float2(unit_eigenvector.y, unit_eigenvector.x) *
115 ceil(
sqrt(square(ellipse_major_axis) + square(ellipse_minor_axis))));
120 int number_of_sectors = 8;
121 float sector_center_overlap_parameter = 2.0f / radius;
122 float sector_envelope_angle = ((3.0f / 2.0f) *
M_PI) / number_of_sectors;
123 float cross_sector_overlap_parameter = (sector_center_overlap_parameter +
124 cos(sector_envelope_angle)) /
125 square(sin(sector_envelope_angle));
130 float4 weighted_mean_of_squared_color_of_sectors[8];
131 float4 weighted_mean_of_color_of_sectors[8];
132 float sum_of_weights_of_sectors[8];
139 float4 center_color =
float4(inputs[0]->get_elem(it.x, it.y));
140 float4 center_color_squared = center_color * center_color;
141 float center_weight = 1.0f / number_of_sectors;
142 float4 weighted_center_color = center_color * center_weight;
143 float4 weighted_center_color_squared = center_color_squared * center_weight;
144 for (
int i = 0; i < number_of_sectors; i++) {
145 weighted_mean_of_squared_color_of_sectors[i] = weighted_center_color_squared;
146 weighted_mean_of_color_of_sectors[i] = weighted_center_color;
147 sum_of_weights_of_sectors[i] = center_weight;
154 for (
int j = 0; j <= ellipse_bounds.y; j++) {
155 for (
int i = -ellipse_bounds.x; i <= ellipse_bounds.x; i++) {
163 if (j == 0 && i <= 0) {
169 float2 disk_point = inverse_ellipse_matrix *
float2(i, j);
170 float disk_point_length_squared =
dot(disk_point, disk_point);
171 if (disk_point_length_squared > 1.0f) {
179 float sector_weights[8];
188 float2 polynomial = sector_center_overlap_parameter -
189 cross_sector_overlap_parameter * square(disk_point);
190 sector_weights[0] = square(
max(0.0f, disk_point.y + polynomial.x));
191 sector_weights[2] = square(
max(0.0f, -disk_point.x + polynomial.y));
192 sector_weights[4] = square(
max(0.0f, -disk_point.y + polynomial.x));
193 sector_weights[6] = square(
max(0.0f, disk_point.x + polynomial.y));
198 disk_point.x + disk_point.y);
202 float2 rotated_polynomial = sector_center_overlap_parameter -
203 cross_sector_overlap_parameter * square(rotated_disk_point);
204 sector_weights[1] = square(
max(0.0f, rotated_disk_point.y + rotated_polynomial.x));
205 sector_weights[3] = square(
max(0.0f, -rotated_disk_point.x + rotated_polynomial.y));
206 sector_weights[5] = square(
max(0.0f, -rotated_disk_point.y + rotated_polynomial.x));
207 sector_weights[7] = square(
max(0.0f, rotated_disk_point.x + rotated_polynomial.y));
213 float sector_weights_sum = sector_weights[0] + sector_weights[1] + sector_weights[2] +
214 sector_weights[3] + sector_weights[4] + sector_weights[5] +
215 sector_weights[6] + sector_weights[7];
216 float radial_gaussian_weight =
exp(-
M_PI * disk_point_length_squared) / sector_weights_sum;
220 inputs[0]->get_elem(
clamp(it.x + i, 0, inputs[0]->get_width() - 1),
221 clamp(it.y + j, 0, inputs[0]->get_height() - 1)));
223 inputs[0]->get_elem(
clamp(it.x - i, 0, inputs[0]->get_width() - 1),
224 clamp(it.y - j, 0, inputs[0]->get_height() - 1)));
225 float4 upper_color_squared = upper_color * upper_color;
226 float4 lower_color_squared = lower_color * lower_color;
228 for (
int k = 0; k < number_of_sectors; k++) {
229 float weight = sector_weights[k] * radial_gaussian_weight;
233 sum_of_weights_of_sectors[upper_index] += weight;
234 weighted_mean_of_color_of_sectors[upper_index] += upper_color * weight;
235 weighted_mean_of_squared_color_of_sectors[upper_index] += upper_color_squared * weight;
239 int lower_index = (k + number_of_sectors / 2) % number_of_sectors;
240 sum_of_weights_of_sectors[lower_index] += weight;
241 weighted_mean_of_color_of_sectors[lower_index] += lower_color * weight;
242 weighted_mean_of_squared_color_of_sectors[lower_index] += lower_color_squared * weight;
249 float sum_of_weights = 0.0f;
251 for (
int i = 0; i < number_of_sectors; i++) {
252 weighted_mean_of_color_of_sectors[i] /= sum_of_weights_of_sectors[i];
253 weighted_mean_of_squared_color_of_sectors[i] /= sum_of_weights_of_sectors[i];
255 float4 color_mean = weighted_mean_of_color_of_sectors[i];
256 float4 squared_color_mean = weighted_mean_of_squared_color_of_sectors[i];
257 float4 color_variance =
abs(squared_color_mean - color_mean * color_mean);
266 sum_of_weights += weight;
267 weighted_sum += color_mean * weight;
272 if (sum_of_weights == 0.0f) {
273 weighted_sum = center_color;
276 weighted_sum /= sum_of_weights;