Changeset View
Changeset View
Standalone View
Standalone View
source/blender/nodes/geometry/nodes/node_geo_image_texture.cc
| Show All 34 Lines | |||||
| { | { | ||||
| uiItemR(layout, ptr, "interpolation", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); | uiItemR(layout, ptr, "interpolation", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); | ||||
| uiItemR(layout, ptr, "extension", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); | uiItemR(layout, ptr, "extension", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); | ||||
| } | } | ||||
| static void node_init(bNodeTree * /*tree*/, bNode *node) | static void node_init(bNodeTree * /*tree*/, bNode *node) | ||||
| { | { | ||||
| NodeGeometryImageTexture *tex = MEM_cnew<NodeGeometryImageTexture>(__func__); | NodeGeometryImageTexture *tex = MEM_cnew<NodeGeometryImageTexture>(__func__); | ||||
| tex->interpolation = SHD_INTERP_LINEAR; | |||||
| tex->extension = SHD_IMAGE_EXTENSION_REPEAT; | |||||
| node->storage = tex; | node->storage = tex; | ||||
| } | } | ||||
| class ImageFieldsFunction : public fn::MultiFunction { | class ImageFieldsFunction : public fn::MultiFunction { | ||||
| private: | private: | ||||
| const int interpolation_; | const uint8_t interpolation_; | ||||
| const int extension_; | const uint8_t extension_; | ||||
| Image &image_; | Image &image_; | ||||
| ImageUser image_user_; | ImageUser image_user_; | ||||
| void *image_lock_; | void *image_lock_; | ||||
| ImBuf *image_buffer_; | ImBuf *image_buffer_; | ||||
| public: | public: | ||||
| ImageFieldsFunction(const int interpolation, | ImageFieldsFunction(const uint8_t interpolation, | ||||
| const int extension, | const uint8_t extension, | ||||
HooglyBoogly: `uint8_t` -> `int8_t` | |||||
| Image &image, | Image &image, | ||||
| ImageUser image_user) | ImageUser image_user) | ||||
| : interpolation_(interpolation), | : interpolation_(interpolation), | ||||
| extension_(extension), | extension_(extension), | ||||
| image_(image), | image_(image), | ||||
| image_user_(image_user) | image_user_(image_user) | ||||
| { | { | ||||
| static fn::MFSignature signature = create_signature(); | static fn::MFSignature signature = create_signature(); | ||||
| ▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | static int wrap_periodic(int x, const int width) | ||||
| return x; | return x; | ||||
| } | } | ||||
| static int wrap_clamp(const int x, const int width) | static int wrap_clamp(const int x, const int width) | ||||
| { | { | ||||
| return std::clamp(x, 0, width - 1); | return std::clamp(x, 0, width - 1); | ||||
| } | } | ||||
| static float4 image_pixel_lookup(const ImBuf *ibuf, const int px, const int py) | static float4 image_pixel_lookup(const ImBuf &ibuf, const int px, const int py) | ||||
| { | { | ||||
| if (px < 0 || py < 0 || px >= ibuf->x || py >= ibuf->y) { | if (px < 0 || py < 0 || px >= ibuf.x || py >= ibuf.y) { | ||||
| return float4(0.0f, 0.0f, 0.0f, 0.0f); | return float4(0.0f, 0.0f, 0.0f, 0.0f); | ||||
| } | } | ||||
| return ((const float4 *)ibuf->rect_float)[px + py * ibuf->x]; | return ((const float4 *)ibuf.rect_float)[px + py * ibuf.x]; | ||||
| } | } | ||||
| 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); | ||||
| } | } | ||||
| 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 SHD_IMAGE_EXTENSION_REPEAT: { | ||||
| pix = wrap_periodic(pix, width); | pix = wrap_periodic(pix, width); | ||||
| ▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | return (v[0] * (u[0] * image_pixel_lookup(ibuf, xc[0], yc[0]) + | ||||
| u[2] * image_pixel_lookup(ibuf, xc[2], yc[2]) + | u[2] * image_pixel_lookup(ibuf, xc[2], yc[2]) + | ||||
| u[3] * image_pixel_lookup(ibuf, xc[3], yc[2]))) + | u[3] * image_pixel_lookup(ibuf, xc[3], yc[2]))) + | ||||
| (v[3] * (u[0] * image_pixel_lookup(ibuf, xc[0], yc[3]) + | (v[3] * (u[0] * image_pixel_lookup(ibuf, xc[0], yc[3]) + | ||||
| u[1] * image_pixel_lookup(ibuf, xc[1], yc[3]) + | u[1] * image_pixel_lookup(ibuf, xc[1], yc[3]) + | ||||
| u[2] * image_pixel_lookup(ibuf, xc[2], yc[3]) + | u[2] * image_pixel_lookup(ibuf, xc[2], yc[3]) + | ||||
| u[3] * image_pixel_lookup(ibuf, xc[3], yc[3]))); | u[3] * image_pixel_lookup(ibuf, xc[3], yc[3]))); | ||||
| } | } | ||||
| static float4 image_linear_texture_lookup(const ImBuf *ibuf, | static float4 image_linear_texture_lookup(const ImBuf &ibuf, | ||||
| const float px, | const float px, | ||||
| const float py, | const float py, | ||||
| const int extension) | const uint8_t 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 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 SHD_IMAGE_EXTENSION_CLIP: { | ||||
| nix = pix + 1; | nix = pix + 1; | ||||
| niy = piy + 1; | niy = piy + 1; | ||||
| Show All 19 Lines | static float4 image_linear_texture_lookup(const ImBuf &ibuf, | ||||
| 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), &ix); | const float tx = frac(px * float(width), &ix); | ||||
| const float ty = frac(py * float(height), &iy); | const float ty = frac(py * float(height), &iy); | ||||
| switch (extension) { | switch (extension) { | ||||
| case SHD_IMAGE_EXTENSION_REPEAT: { | case SHD_IMAGE_EXTENSION_REPEAT: { | ||||
| ix = wrap_periodic(ix, width); | ix = wrap_periodic(ix, width); | ||||
| iy = wrap_periodic(iy, height); | iy = wrap_periodic(iy, height); | ||||
| Show All 27 Lines | void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override | ||||
| MutableSpan<float4> color_data{reinterpret_cast<float4 *>(r_color.data()), r_color.size()}; | MutableSpan<float4> color_data{reinterpret_cast<float4 *>(r_color.data()), r_color.size()}; | ||||
| /* Sample image texture. */ | /* Sample image texture. */ | ||||
| switch (interpolation_) { | switch (interpolation_) { | ||||
| case SHD_INTERP_LINEAR: | case SHD_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 SHD_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 SHD_INTERP_CUBIC: | ||||
| case SHD_INTERP_SMART: | case SHD_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; | ||||
| if (IMB_colormanagement_space_name_is_data(image_.colorspace_settings.name)) { | if (IMB_colormanagement_space_name_is_data(image_.colorspace_settings.name)) { | ||||
| alpha_mode = IMA_ALPHA_CHANNEL_PACKED; | alpha_mode = IMA_ALPHA_CHANNEL_PACKED; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | try { | ||||
| image_fn = std::make_unique<ImageFieldsFunction>( | image_fn = std::make_unique<ImageFieldsFunction>( | ||||
| storage.interpolation, storage.extension, *image, image_user); | storage.interpolation, storage.extension, *image, image_user); | ||||
| } | } | ||||
| catch (const std::runtime_error &) { | catch (const std::runtime_error &) { | ||||
| params.set_default_remaining_outputs(); | params.set_default_remaining_outputs(); | ||||
| return; | return; | ||||
| } | } | ||||
| Field<float3> vector_field = params.extract_input<Field<float3>>("Vector"); | const Field<float3> vector_field = params.extract_input<Field<float3>>("Vector"); | ||||
| auto image_op = std::make_shared<FieldOperation>( | auto image_op = std::make_shared<FieldOperation>( | ||||
| FieldOperation(std::move(image_fn), {std::move(vector_field)})); | FieldOperation(std::move(image_fn), {std::move(vector_field)})); | ||||
HooglyBooglyUnsubmitted Done Inline Actionsvector_field wasn't const because we use std::move on it. I think that will give an error on some compilers HooglyBoogly: `vector_field` wasn't const because we use `std::move` on it. I think that will give an error… | |||||
ModerAuthorUnsubmitted Done Inline ActionsAh, so here's the thing. Yes, I do not have an error, but it sounds logical, since the transfer of rights takes ownership and the fact of having. I didn't think about it. Moder: Ah, so here's the thing. Yes, I do not have an error, but it sounds logical, since the transfer… | |||||
| params.set_output("Color", Field<ColorGeometry4f>(image_op, 0)); | params.set_output("Color", Field<ColorGeometry4f>(image_op, 0)); | ||||
| params.set_output("Alpha", Field<float>(image_op, 1)); | params.set_output("Alpha", Field<float>(image_op, 1)); | ||||
| } | } | ||||
| } // namespace blender::nodes::node_geo_image_texture_cc | } // namespace blender::nodes::node_geo_image_texture_cc | ||||
| void register_node_type_geo_image_texture() | void register_node_type_geo_image_texture() | ||||
| Show All 16 Lines | |||||
uint8_t -> int8_t