Changeset View
Changeset View
Standalone View
Standalone View
source/blender/nodes/geometry/nodes/node_geo_image_texture.cc
| /* SPDX-License-Identifier: GPL-2.0-or-later | /* SPDX-License-Identifier: GPL-2.0-or-later | ||||
| * Copyright 2005 Blender Foundation. All rights reserved. */ | * Copyright 2005 Blender Foundation. All rights reserved. */ | ||||
| #include "node_geometry_util.hh" | #include "node_geometry_util.hh" | ||||
| #include "BKE_image.h" | #include "BKE_image.h" | ||||
| #include "BLI_math_vec_types.hh" | #include "BLI_math_vec_types.hh" | ||||
| #include "BLI_threads.h" | #include "BLI_threads.h" | ||||
| #include "BLI_timeit.hh" | #include "BLI_timeit.hh" | ||||
| #include "DNA_texture_types.h" | |||||
| #include "IMB_colormanagement.h" | #include "IMB_colormanagement.h" | ||||
| #include "IMB_imbuf.h" | #include "IMB_imbuf.h" | ||||
| #include "IMB_imbuf_types.h" | #include "IMB_imbuf_types.h" | ||||
| #include "UI_interface.h" | #include "UI_interface.h" | ||||
| #include "UI_resources.h" | #include "UI_resources.h" | ||||
| namespace blender::nodes::node_geo_image_texture_cc { | namespace blender::nodes::node_geo_image_texture_cc { | ||||
| ▲ Show 20 Lines • Show All 102 Lines • ▼ Show 20 Lines | public: | ||||
| static float frac(const float x, int *ix) | static float frac(const float x, int *ix) | ||||
| { | { | ||||
| const int i = (int)x - ((x < 0.0f) ? 1 : 0); | const int i = (int)x - ((x < 0.0f) ? 1 : 0); | ||||
| *ix = i; | *ix = i; | ||||
| return x - (float)i; | return x - (float)i; | ||||
| } | } | ||||
| #define ERROR_COLOR float4(0.0f, 0.0f, 0.0f, 0.0f) | |||||
| static float4 image_cubic_texture_lookup(const ImBuf *ibuf, | static float4 image_cubic_texture_lookup(const ImBuf *ibuf, | ||||
| const float px, | const float px, | ||||
| const float py, | const float py, | ||||
| const int extension) | const int extension) | ||||
| { | { | ||||
| const int width = ibuf->x; | const int width = ibuf->x; | ||||
| const int height = ibuf->y; | const int height = ibuf->y; | ||||
| int pix, piy, nix, niy; | int pix, piy, nix, niy; | ||||
| const float tx = frac(px * (float)width - 0.5f, &pix); | const float tx = frac(px * (float)width - 0.5f, &pix); | ||||
| const float ty = frac(py * (float)height - 0.5f, &piy); | const float ty = frac(py * (float)height - 0.5f, &piy); | ||||
| int ppix, ppiy, nnix, nniy; | int ppix, ppiy, nnix, nniy; | ||||
| switch (extension) { | switch (extension) { | ||||
| case SHD_IMAGE_EXTENSION_REPEAT: { | case IMAGE_TEX_EXT_REPEAT: | ||||
| pix = wrap_periodic(pix, width); | |||||
| piy = wrap_periodic(piy, height); | |||||
| ppix = wrap_periodic(pix - 1, width); | ppix = wrap_periodic(pix - 1, width); | ||||
| ppiy = wrap_periodic(piy - 1, height); | |||||
| nix = wrap_periodic(pix + 1, width); | nix = wrap_periodic(pix + 1, width); | ||||
| niy = wrap_periodic(piy + 1, height); | |||||
| nnix = wrap_periodic(pix + 2, width); | nnix = wrap_periodic(pix + 2, width); | ||||
| pix = wrap_periodic(pix, width); | |||||
| ppiy = wrap_periodic(piy - 1, height); | |||||
| niy = wrap_periodic(piy + 1, height); | |||||
| nniy = wrap_periodic(piy + 2, height); | nniy = wrap_periodic(piy + 2, height); | ||||
| piy = wrap_periodic(piy, height); | |||||
| break; | break; | ||||
| } | case IMAGE_TEX_EXT_CLIP: | ||||
| case SHD_IMAGE_EXTENSION_CLIP: { | |||||
| ppix = pix - 1; | ppix = pix - 1; | ||||
| ppiy = piy - 1; | |||||
| nix = pix + 1; | nix = pix + 1; | ||||
| niy = piy + 1; | |||||
| nnix = pix + 2; | nnix = pix + 2; | ||||
| ppiy = piy - 1; | |||||
| niy = piy + 1; | |||||
| nniy = piy + 2; | nniy = piy + 2; | ||||
| break; | break; | ||||
| } | case IMAGE_TEX_EXT_EXTEND: | ||||
| case SHD_IMAGE_EXTENSION_EXTEND: { | |||||
| ppix = wrap_clamp(pix - 1, width); | ppix = wrap_clamp(pix - 1, width); | ||||
| ppiy = wrap_clamp(piy - 1, height); | |||||
| nix = wrap_clamp(pix + 1, width); | nix = wrap_clamp(pix + 1, width); | ||||
| niy = wrap_clamp(piy + 1, height); | |||||
| nnix = wrap_clamp(pix + 2, width); | nnix = wrap_clamp(pix + 2, width); | ||||
| nniy = wrap_clamp(piy + 2, height); | |||||
| pix = wrap_clamp(pix, width); | pix = wrap_clamp(pix, width); | ||||
| ppiy = wrap_clamp(piy - 1, height); | |||||
| niy = wrap_clamp(piy + 1, height); | |||||
| nniy = wrap_clamp(piy + 2, height); | |||||
| piy = wrap_clamp(piy, height); | piy = wrap_clamp(piy, height); | ||||
| break; | break; | ||||
| } | |||||
| default: | default: | ||||
| return float4(0.0f, 0.0f, 0.0f, 0.0f); | BLI_assert_unreachable(); | ||||
| return ERROR_COLOR; | |||||
| } | } | ||||
| const int xc[4] = {ppix, pix, nix, nnix}; | const int xc[4] = {ppix, pix, nix, nnix}; | ||||
| const int yc[4] = {ppiy, piy, niy, nniy}; | const int yc[4] = {ppiy, piy, niy, nniy}; | ||||
| float u[4], v[4]; | float u[4], v[4]; | ||||
| u[0] = (((-1.0f / 6.0f) * tx + 0.5f) * tx - 0.5f) * tx + (1.0f / 6.0f); | u[0] = (((-1.0f / 6.0f) * tx + 0.5f) * tx - 0.5f) * tx + (1.0f / 6.0f); | ||||
| u[1] = ((0.5f * tx - 1.0f) * tx) * tx + (2.0f / 3.0f); | u[1] = ((0.5f * tx - 1.0f) * tx) * tx + (2.0f / 3.0f); | ||||
| Show All 30 Lines | #define ERROR_COLOR float4(0.0f, 0.0f, 0.0f, 0.0f) | ||||
| { | { | ||||
| const int width = ibuf->x; | const int width = ibuf->x; | ||||
| const int height = ibuf->y; | const int height = ibuf->y; | ||||
| int pix, piy, nix, niy; | int pix, piy, nix, niy; | ||||
| const float nfx = frac(px * (float)width - 0.5f, &pix); | const float nfx = frac(px * (float)width - 0.5f, &pix); | ||||
| const float nfy = frac(py * (float)height - 0.5f, &piy); | const float nfy = frac(py * (float)height - 0.5f, &piy); | ||||
| switch (extension) { | switch (extension) { | ||||
| case SHD_IMAGE_EXTENSION_CLIP: { | case IMAGE_TEX_EXT_REPEAT: | ||||
| nix = wrap_periodic(pix + 1, width); | |||||
| pix = wrap_periodic(pix, width); | |||||
| niy = wrap_periodic(piy + 1, height); | |||||
| piy = wrap_periodic(piy, height); | |||||
| break; | |||||
| case IMAGE_TEX_EXT_CLIP: | |||||
| nix = pix + 1; | nix = pix + 1; | ||||
| niy = piy + 1; | niy = piy + 1; | ||||
| break; | break; | ||||
| } | case IMAGE_TEX_EXT_EXTEND: | ||||
| case SHD_IMAGE_EXTENSION_EXTEND: { | |||||
| nix = wrap_clamp(pix + 1, width); | nix = wrap_clamp(pix + 1, width); | ||||
| niy = wrap_clamp(piy + 1, height); | |||||
| pix = wrap_clamp(pix, width); | pix = wrap_clamp(pix, width); | ||||
| niy = wrap_clamp(piy + 1, height); | |||||
| piy = wrap_clamp(piy, height); | piy = wrap_clamp(piy, height); | ||||
| break; | break; | ||||
| } | |||||
| default: | default: | ||||
| case SHD_IMAGE_EXTENSION_REPEAT: | BLI_assert_unreachable(); | ||||
| pix = wrap_periodic(pix, width); | return ERROR_COLOR; | ||||
| piy = wrap_periodic(piy, height); | |||||
| nix = wrap_periodic(pix + 1, width); | |||||
| niy = wrap_periodic(piy + 1, height); | |||||
| break; | |||||
| } | } | ||||
| const float ptx = 1.0f - nfx; | const float ptx = 1.0f - nfx; | ||||
| const float pty = 1.0f - nfy; | const float pty = 1.0f - nfy; | ||||
| return image_pixel_lookup(ibuf, pix, piy) * ptx * pty + | return image_pixel_lookup(ibuf, pix, piy) * ptx * pty + | ||||
| image_pixel_lookup(ibuf, nix, piy) * nfx * pty + | image_pixel_lookup(ibuf, nix, piy) * nfx * pty + | ||||
| image_pixel_lookup(ibuf, pix, niy) * ptx * nfy + | image_pixel_lookup(ibuf, pix, niy) * ptx * nfy + | ||||
| image_pixel_lookup(ibuf, nix, niy) * nfx * nfy; | image_pixel_lookup(ibuf, nix, niy) * nfx * nfy; | ||||
| } | } | ||||
| static float4 image_closest_texture_lookup(const ImBuf *ibuf, | static float4 image_closest_texture_lookup(const ImBuf *ibuf, | ||||
| const float px, | const float px, | ||||
| const float py, | const float py, | ||||
| const int extension) | const int extension) | ||||
| { | { | ||||
| const int width = ibuf->x; | const int width = ibuf->x; | ||||
| const int height = ibuf->y; | const int height = ibuf->y; | ||||
| int ix, iy; | int ix, iy; | ||||
| const float tx = frac(px * (float)width - 0.5f, &ix); | const float tx = frac(px * (float)width, &ix); | ||||
| const float ty = frac(py * (float)height - 0.5f, &iy); | const float ty = frac(py * (float)height, &iy); | ||||
| switch (extension) { | switch (extension) { | ||||
| case SHD_IMAGE_EXTENSION_REPEAT: { | case IMAGE_TEX_EXT_REPEAT: | ||||
| ix = wrap_periodic(ix, width); | ix = wrap_periodic(ix, width); | ||||
| iy = wrap_periodic(iy, height); | iy = wrap_periodic(iy, height); | ||||
| return image_pixel_lookup(ibuf, ix, iy); | break; | ||||
| } | case IMAGE_TEX_EXT_CLIP: | ||||
| case SHD_IMAGE_EXTENSION_CLIP: { | if (px < 0.0f || px > 1.0f || py < 0.0f || py > 1.0f) { | ||||
| if (tx < 0.0f || ty < 0.0f || tx > 1.0f || ty > 1.0f) { | |||||
| return float4(0.0f, 0.0f, 0.0f, 0.0f); | |||||
| } | |||||
| if (ix < 0 || iy < 0 || ix > width || iy > height) { | |||||
| return float4(0.0f, 0.0f, 0.0f, 0.0f); | return float4(0.0f, 0.0f, 0.0f, 0.0f); | ||||
| } | } | ||||
| ATTR_FALLTHROUGH; | break; | ||||
| } | case IMAGE_TEX_EXT_EXTEND: | ||||
| case SHD_IMAGE_EXTENSION_EXTEND: { | |||||
| ix = wrap_clamp(ix, width); | ix = wrap_clamp(ix, width); | ||||
| iy = wrap_clamp(iy, height); | iy = wrap_clamp(iy, height); | ||||
| return image_pixel_lookup(ibuf, ix, iy); | break; | ||||
| } | |||||
| default: | default: | ||||
| return float4(0.0f, 0.0f, 0.0f, 0.0f); | BLI_assert_unreachable(); | ||||
| return ERROR_COLOR; | |||||
| } | } | ||||
| return image_pixel_lookup(ibuf, ix, iy); | |||||
| } | } | ||||
| void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override | void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override | ||||
| { | { | ||||
| const VArray<float3> &vectors = params.readonly_single_input<float3>(0, "Vector"); | const VArray<float3> &vectors = params.readonly_single_input<float3>(0, "Vector"); | ||||
| MutableSpan<ColorGeometry4f> r_color = params.uninitialized_single_output<ColorGeometry4f>( | MutableSpan<ColorGeometry4f> r_color = params.uninitialized_single_output<ColorGeometry4f>( | ||||
| 1, "Color"); | 1, "Color"); | ||||
| MutableSpan<float> r_alpha = params.uninitialized_single_output_if_required<float>(2, "Alpha"); | MutableSpan<float> r_alpha = params.uninitialized_single_output_if_required<float>(2, "Alpha"); | ||||
| MutableSpan<float4> color_data{(float4 *)r_color.data(), r_color.size()}; | MutableSpan<float4> color_data{(float4 *)r_color.data(), r_color.size()}; | ||||
| /* Sample image texture. */ | /* Sample image texture. */ | ||||
| switch (interpolation_) { | switch (interpolation_) { | ||||
| case SHD_INTERP_LINEAR: | case IMAGE_TEX_INTERP_LINEAR: | ||||
| for (const int64_t i : mask) { | for (const int64_t i : mask) { | ||||
| const float3 p = vectors[i]; | const float3 p = vectors[i]; | ||||
| color_data[i] = image_linear_texture_lookup(image_buffer_, p.x, p.y, extension_); | color_data[i] = image_linear_texture_lookup(image_buffer_, p.x, p.y, extension_); | ||||
| } | } | ||||
| break; | break; | ||||
| case SHD_INTERP_CLOSEST: | case IMAGE_TEX_INTERP_CLOSEST: | ||||
| for (const int64_t i : mask) { | for (const int64_t i : mask) { | ||||
| const float3 p = vectors[i]; | const float3 p = vectors[i]; | ||||
| color_data[i] = image_closest_texture_lookup(image_buffer_, p.x, p.y, extension_); | color_data[i] = image_closest_texture_lookup(image_buffer_, p.x, p.y, extension_); | ||||
| } | } | ||||
| break; | break; | ||||
| case SHD_INTERP_CUBIC: | case IMAGE_TEX_INTERP_CUBIC: | ||||
| case SHD_INTERP_SMART: | case IMAGE_TEX_INTERP_SMART: | ||||
| for (const int64_t i : mask) { | for (const int64_t i : mask) { | ||||
| const float3 p = vectors[i]; | const float3 p = vectors[i]; | ||||
| color_data[i] = image_cubic_texture_lookup(image_buffer_, p.x, p.y, extension_); | color_data[i] = image_cubic_texture_lookup(image_buffer_, p.x, p.y, extension_); | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| int alpha_mode = image_.alpha_mode; | int alpha_mode = image_.alpha_mode; | ||||
| ▲ Show 20 Lines • Show All 92 Lines • Show Last 20 Lines | |||||