From dd2dca2f7e77e7521d13b78e875ffa58a90846f2 Mon Sep 17 00:00:00 2001 From: Martijn Berger Date: Fri, 7 Mar 2014 23:16:09 +0100 Subject: Add support for multiple interpolation modes on cycles image textures All textures are sampled bi-linear currently with the exception of OSL there texture sampling is fixed and set to smart bi-cubic. This patch adds user control to this setting. Added: - bits to DNA / RNA in the form of an enum for supporting multiple interpolations types - changes to the image texture node drawing code ( add enum) - to ImageManager (this needs to know to allocate second texture when interpolation type is different) - to node compiler (pass on interpolation type) - to device tex_alloc this also needs to get the concept of multiple interpolation types - implementation for doing non interpolated lookup for cuda and cpu - implementation where we pass this along to osl ( this makes OSL also do linear untill I add smartcubic to the interface / DNA/ RNA) Reviewers: brecht, dingto Reviewed By: brecht CC: dingto, venomgfx Differential Revision: https://developer.blender.org/D317 --- intern/cycles/blender/blender_shader.cpp | 1 + intern/cycles/device/device.h | 2 +- intern/cycles/device/device_cpu.cpp | 4 +-- intern/cycles/device/device_cuda.cpp | 16 ++++++--- intern/cycles/device/device_multi.cpp | 2 +- intern/cycles/device/device_network.cpp | 4 +-- intern/cycles/device/device_opencl.cpp | 2 +- intern/cycles/kernel/kernel.cpp | 4 ++- intern/cycles/kernel/kernel.h | 2 +- intern/cycles/kernel/kernel_compat_cpu.h | 18 ++++++---- .../cycles/kernel/shaders/node_image_texture.osl | 13 +++---- intern/cycles/kernel/svm/svm_image.h | 17 ++++++--- intern/cycles/render/image.cpp | 41 ++++++++++++++++------ intern/cycles/render/image.h | 6 ++-- intern/cycles/render/nodes.cpp | 27 +++++++++++--- intern/cycles/render/nodes.h | 1 + intern/cycles/util/util_types.h | 10 ++++++ source/blender/editors/space_node/drawnode.c | 1 + source/blender/makesdna/DNA_node_types.h | 8 ++++- source/blender/makesrna/intern/rna_nodetree.c | 16 +++++++++ 20 files changed, 146 insertions(+), 49 deletions(-) diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 6175c8ea399..1559a96a3d3 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -549,6 +549,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen } image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()]; image->projection = ImageTextureNode::projection_enum[(int)b_image_node.projection()]; + image->interpolation = (InterpolationType)b_image_node.interpolation(); image->projection_blend = b_image_node.projection_blend(); get_tex_mapping(&image->tex_mapping, b_image_node.texture_mapping()); node = image; diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index bd309e35788..f94075f9aa5 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -100,7 +100,7 @@ public: /* texture memory */ virtual void tex_alloc(const char *name, device_memory& mem, - bool interpolation = false, bool periodic = false) {}; + InterpolationType interpolation = INTERPOLATION_NONE, bool periodic = false) {}; virtual void tex_free(device_memory& mem) {}; /* pixel memory */ diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index 76123fe44d2..de44feb2deb 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -103,9 +103,9 @@ public: kernel_const_copy(&kernel_globals, name, host, size); } - void tex_alloc(const char *name, device_memory& mem, bool interpolation, bool periodic) + void tex_alloc(const char *name, device_memory& mem, InterpolationType interpolation, bool periodic) { - kernel_tex_copy(&kernel_globals, name, mem.data_pointer, mem.data_width, mem.data_height); + kernel_tex_copy(&kernel_globals, name, mem.data_pointer, mem.data_width, mem.data_height, interpolation); mem.device_pointer = mem.data_pointer; stats.mem_alloc(mem.memory_size()); diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index 932fdc303a5..5133a5c9fea 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -451,7 +451,7 @@ public: cuda_pop_context(); } - void tex_alloc(const char *name, device_memory& mem, bool interpolation, bool periodic) + void tex_alloc(const char *name, device_memory& mem, InterpolationType interpolation, bool periodic) { /* determine format */ CUarray_format_enum format; @@ -479,7 +479,7 @@ public: return; } - if(interpolation) { + if(interpolation != INTERPOLATION_NONE) { CUarray handle = NULL; CUDA_ARRAY_DESCRIPTOR desc; @@ -513,7 +513,15 @@ public: cuda_assert(cuTexRefSetArray(texref, handle, CU_TRSA_OVERRIDE_FORMAT)) - cuda_assert(cuTexRefSetFilterMode(texref, CU_TR_FILTER_MODE_LINEAR)) + if(interpolation == INTERPOLATION_CLOSEST) { + cuda_assert(cuTexRefSetFilterMode(texref, CU_TR_FILTER_MODE_POINT)) + } + else if (interpolation == INTERPOLATION_LINEAR){ + cuda_assert(cuTexRefSetFilterMode(texref, CU_TR_FILTER_MODE_LINEAR)) + } + else {/* CUBIC and SMART are unsupported for CUDA */ + cuda_assert(cuTexRefSetFilterMode(texref, CU_TR_FILTER_MODE_LINEAR)) + } cuda_assert(cuTexRefSetFlags(texref, CU_TRSF_NORMALIZED_COORDINATES)) mem.device_pointer = (device_ptr)handle; @@ -570,7 +578,7 @@ public: cuda_pop_context(); } - tex_interp_map[mem.device_pointer] = interpolation; + tex_interp_map[mem.device_pointer] = (interpolation != INTERPOLATION_NONE); } void tex_free(device_memory& mem) diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp index 27b9de0769e..1e9367c845a 100644 --- a/intern/cycles/device/device_multi.cpp +++ b/intern/cycles/device/device_multi.cpp @@ -168,7 +168,7 @@ public: sub.device->const_copy_to(name, host, size); } - void tex_alloc(const char *name, device_memory& mem, bool interpolation, bool periodic) + void tex_alloc(const char *name, device_memory& mem, InterpolationType interpolation, bool periodic) { foreach(SubDevice& sub, devices) { mem.device_pointer = 0; diff --git a/intern/cycles/device/device_network.cpp b/intern/cycles/device/device_network.cpp index bffd993818f..8f00324c3e1 100644 --- a/intern/cycles/device/device_network.cpp +++ b/intern/cycles/device/device_network.cpp @@ -162,7 +162,7 @@ public: snd.write_buffer(host, size); } - void tex_alloc(const char *name, device_memory& mem, bool interpolation, bool periodic) + void tex_alloc(const char *name, device_memory& mem, InterpolationType interpolation, bool periodic) { thread_scoped_lock lock(rpc_lock); @@ -559,7 +559,7 @@ protected: else if(rcv.name == "tex_alloc") { network_device_memory mem; string name; - bool interpolation; + InterpolationType interpolation; bool periodic; device_ptr client_pointer; diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index 9117b70d749..33170e1230d 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -881,7 +881,7 @@ public: mem_copy_to(*i->second); } - void tex_alloc(const char *name, device_memory& mem, bool interpolation, bool periodic) + void tex_alloc(const char *name, device_memory& mem, InterpolationType interpolation, bool periodic) { mem_alloc(mem, MEM_READ_ONLY); mem_copy_to(mem); diff --git a/intern/cycles/kernel/kernel.cpp b/intern/cycles/kernel/kernel.cpp index 6cd14d3c51c..5d74feed9f4 100644 --- a/intern/cycles/kernel/kernel.cpp +++ b/intern/cycles/kernel/kernel.cpp @@ -37,7 +37,7 @@ void kernel_const_copy(KernelGlobals *kg, const char *name, void *host, size_t s assert(0); } -void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t width, size_t height) +void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t width, size_t height, InterpolationType interpolation) { if(0) { } @@ -63,6 +63,7 @@ void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t tex->data = (float4*)mem; tex->width = width; tex->height = height; + tex->interpolation = interpolation; } } else if(strstr(name, "__tex_image")) { @@ -78,6 +79,7 @@ void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t tex->data = (uchar4*)mem; tex->width = width; tex->height = height; + tex->interpolation = interpolation; } } else diff --git a/intern/cycles/kernel/kernel.h b/intern/cycles/kernel/kernel.h index 039dc791b08..a4f13e78006 100644 --- a/intern/cycles/kernel/kernel.h +++ b/intern/cycles/kernel/kernel.h @@ -32,7 +32,7 @@ void *kernel_osl_memory(KernelGlobals *kg); bool kernel_osl_use(KernelGlobals *kg); void kernel_const_copy(KernelGlobals *kg, const char *name, void *host, size_t size); -void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t width, size_t height); +void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t width, size_t height, InterpolationType interpolation=INTERPOLATION_LINEAR); void kernel_cpu_path_trace(KernelGlobals *kg, float *buffer, unsigned int *rng_state, int sample, int x, int y, int offset, int stride); diff --git a/intern/cycles/kernel/kernel_compat_cpu.h b/intern/cycles/kernel/kernel_compat_cpu.h index a9c66ec2d68..55f4484ba1f 100644 --- a/intern/cycles/kernel/kernel_compat_cpu.h +++ b/intern/cycles/kernel/kernel_compat_cpu.h @@ -117,14 +117,19 @@ template struct texture_image { niy = wrap_clamp(iy+1, height); } - float4 r = (1.0f - ty)*(1.0f - tx)*read(data[ix + iy*width]); - r += (1.0f - ty)*tx*read(data[nix + iy*width]); - r += ty*(1.0f - tx)*read(data[ix + niy*width]); - r += ty*tx*read(data[nix + niy*width]); - - return r; + if(interpolation == INTERPOLATION_CLOSEST) { + return read(data[ix + iy*width]); + } + else { + float4 r = (1.0f - ty)*(1.0f - tx)*read(data[ix + iy*width]); + r += (1.0f - ty)*tx*read(data[nix + iy*width]); + r += ty*(1.0f - tx)*read(data[ix + niy*width]); + r += ty*tx*read(data[nix + niy*width]); + return r; + } } + int interpolation; T *data; int width, height; }; @@ -146,7 +151,6 @@ typedef texture_image texture_image_uchar4; #define kernel_tex_fetch_m128i(tex, index) (kg->tex.fetch_m128i(index)) #define kernel_tex_lookup(tex, t, offset, size) (kg->tex.lookup(t, offset, size)) #define kernel_tex_image_interp(tex, x, y) ((tex < MAX_FLOAT_IMAGES) ? kg->texture_float_images[tex].interp(x, y) : kg->texture_byte_images[tex - MAX_FLOAT_IMAGES].interp(x, y)) - #define kernel_data (kg->__data) CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/shaders/node_image_texture.osl b/intern/cycles/kernel/shaders/node_image_texture.osl index caa755636b9..7238a1e8862 100644 --- a/intern/cycles/kernel/shaders/node_image_texture.osl +++ b/intern/cycles/kernel/shaders/node_image_texture.osl @@ -17,9 +17,9 @@ #include "stdosl.h" #include "node_color.h" -color image_texture_lookup(string filename, string color_space, float u, float v, output float Alpha, int use_alpha, int is_float) +color image_texture_lookup(string filename, string color_space, float u, float v, output float Alpha, int use_alpha, int is_float, string interpolation) { - color rgb = (color)texture(filename, u, 1.0 - v, "wrap", "periodic", "alpha", Alpha); + color rgb = (color)texture(filename, u, 1.0 - v, "wrap", "periodic", "interp", interpolation, "alpha", Alpha); if (use_alpha) { rgb = color_unpremultiply(rgb, Alpha); @@ -42,6 +42,7 @@ shader node_image_texture( string filename = "", string color_space = "sRGB", string projection = "Flat", + string interpolation = "smartcubic", float projection_blend = 0.0, int is_float = 1, int use_alpha = 1, @@ -54,7 +55,7 @@ shader node_image_texture( p = transform(mapping, p); if (projection == "Flat") { - Color = image_texture_lookup(filename, color_space, p[0], p[1], Alpha, use_alpha, is_float); + Color = image_texture_lookup(filename, color_space, p[0], p[1], Alpha, use_alpha, is_float, interpolation); } else if (projection == "Box") { /* object space normal */ @@ -119,15 +120,15 @@ shader node_image_texture( float tmp_alpha; if (weight[0] > 0.0) { - Color += weight[0] * image_texture_lookup(filename, color_space, p[1], p[2], tmp_alpha, use_alpha, is_float); + Color += weight[0] * image_texture_lookup(filename, color_space, p[1], p[2], tmp_alpha, use_alpha, is_float, interpolation); Alpha += weight[0] * tmp_alpha; } if (weight[1] > 0.0) { - Color += weight[1] * image_texture_lookup(filename, color_space, p[0], p[2], tmp_alpha, use_alpha, is_float); + Color += weight[1] * image_texture_lookup(filename, color_space, p[0], p[2], tmp_alpha, use_alpha, is_float, interpolation); Alpha += weight[1] * tmp_alpha; } if (weight[2] > 0.0) { - Color += weight[2] * image_texture_lookup(filename, color_space, p[1], p[0], tmp_alpha, use_alpha, is_float); + Color += weight[2] * image_texture_lookup(filename, color_space, p[1], p[0], tmp_alpha, use_alpha, is_float, interpolation); Alpha += weight[2] * tmp_alpha; } } diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h index bc76ea1e662..750af97150e 100644 --- a/intern/cycles/kernel/svm/svm_image.h +++ b/intern/cycles/kernel/svm/svm_image.h @@ -60,7 +60,8 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, uint width = info.x; uint height = info.y; uint offset = info.z; - uint periodic = info.w; + uint periodic = (info.w & 0x1); + uint interpolation = info.w >> 1; int ix, iy, nix, niy; float tx = svm_image_texture_frac(x*width, &ix); @@ -81,10 +82,16 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, niy = svm_image_texture_wrap_clamp(iy+1, height); } - float4 r = (1.0f - ty)*(1.0f - tx)*svm_image_texture_read(kg, offset + ix + iy*width); - r += (1.0f - ty)*tx*svm_image_texture_read(kg, offset + nix + iy*width); - r += ty*(1.0f - tx)*svm_image_texture_read(kg, offset + ix + niy*width); - r += ty*tx*svm_image_texture_read(kg, offset + nix + niy*width); + float4 r; + if (interpolation == INTERPOLATION_CLOSEST){ + r = svm_image_texture_read(kg, offset + ix + iy*width); + } + else { /* We default to linear interpolation if it is not closest */ + r = (1.0f - ty)*(1.0f - tx)*svm_image_texture_read(kg, offset + ix + iy*width); + r += (1.0f - ty)*tx*svm_image_texture_read(kg, offset + nix + iy*width); + r += ty*(1.0f - tx)*svm_image_texture_read(kg, offset + ix + niy*width); + r += ty*tx*svm_image_texture_read(kg, offset + nix + niy*width); + } if(use_alpha && r.w != 1.0f && r.w != 0.0f) { float invw = 1.0f/r.w; diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 91aae6f3ec3..b2559c8c824 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -145,7 +145,7 @@ bool ImageManager::is_float_image(const string& filename, void *builtin_data, bo return is_float; } -int ImageManager::add_image(const string& filename, void *builtin_data, bool animated, bool& is_float, bool& is_linear) +int ImageManager::add_image(const string& filename, void *builtin_data, bool animated, bool& is_float, bool& is_linear, InterpolationType interpolation) { Image *img; size_t slot; @@ -156,7 +156,7 @@ int ImageManager::add_image(const string& filename, void *builtin_data, bool ani if(is_float) { /* find existing image */ for(slot = 0; slot < float_images.size(); slot++) { - if(float_images[slot] && float_images[slot]->filename == filename) { + if(float_images[slot] && float_images[slot]->filename == filename && float_images[slot]->interpolation == interpolation) { float_images[slot]->users++; return slot; } @@ -185,13 +185,14 @@ int ImageManager::add_image(const string& filename, void *builtin_data, bool ani img->builtin_data = builtin_data; img->need_load = true; img->animated = animated; + img->interpolation = interpolation; img->users = 1; float_images[slot] = img; } else { for(slot = 0; slot < images.size(); slot++) { - if(images[slot] && images[slot]->filename == filename) { + if(images[slot] && images[slot]->filename == filename && images[slot]->interpolation == interpolation) { images[slot]->users++; return slot+tex_image_byte_start; } @@ -220,6 +221,7 @@ int ImageManager::add_image(const string& filename, void *builtin_data, bool ani img->builtin_data = builtin_data; img->need_load = true; img->animated = animated; + img->interpolation = interpolation; img->users = 1; images[slot] = img; @@ -231,12 +233,12 @@ int ImageManager::add_image(const string& filename, void *builtin_data, bool ani return slot; } -void ImageManager::remove_image(const string& filename, void *builtin_data) +void ImageManager::remove_image(const string& filename, void *builtin_data, InterpolationType interpolation) { size_t slot; for(slot = 0; slot < images.size(); slot++) { - if(images[slot] && images[slot]->filename == filename && images[slot]->builtin_data == builtin_data) { + if(images[slot] && images[slot]->filename == filename && images[slot]->interpolation == interpolation && images[slot]->builtin_data == builtin_data) { /* decrement user count */ images[slot]->users--; assert(images[slot]->users >= 0); @@ -254,7 +256,9 @@ void ImageManager::remove_image(const string& filename, void *builtin_data) if(slot == images.size()) { /* see if it's in a float texture slot */ for(slot = 0; slot < float_images.size(); slot++) { - if(float_images[slot] && float_images[slot]->filename == filename && float_images[slot]->builtin_data == builtin_data) { + if(float_images[slot] && float_images[slot]->filename == filename + && float_images[slot]->interpolation == interpolation + && float_images[slot]->builtin_data == builtin_data) { /* decrement user count */ float_images[slot]->users--; assert(float_images[slot]->users >= 0); @@ -499,7 +503,7 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, int sl if(!pack_images) { thread_scoped_lock device_lock(device_mutex); - device->tex_alloc(name.c_str(), tex_img, true, true); + device->tex_alloc(name.c_str(), tex_img, img->interpolation, true); } } else { @@ -530,7 +534,7 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, int sl if(!pack_images) { thread_scoped_lock device_lock(device_mutex); - device->tex_alloc(name.c_str(), tex_img, true, true); + device->tex_alloc(name.c_str(), tex_img, img->interpolation, true); } } @@ -653,16 +657,31 @@ void ImageManager::device_pack_images(Device *device, DeviceScene *dscene, Progr device_vector& tex_img = dscene->tex_image[slot]; - info[slot] = make_uint4(tex_img.data_width, tex_img.data_height, offset, 1); + + /* The image options are packed + bit 0 -> periodic + bit 1 + 2 -> interpolation type */ + u_int8_t interpolation = (images[slot]->interpolation << 1) + 1; + info[slot] = make_uint4(tex_img.data_width, tex_img.data_height, offset, interpolation); memcpy(pixels+offset, (void*)tex_img.data_pointer, tex_img.memory_size()); offset += tex_img.size(); } - if(dscene->tex_image_packed.size()) + if(dscene->tex_image_packed.size()) { + if(dscene->tex_image_packed.device_pointer) { + thread_scoped_lock device_lock(device_mutex); + device->tex_free(dscene->tex_image_packed); + } device->tex_alloc("__tex_image_packed", dscene->tex_image_packed); - if(dscene->tex_image_packed_info.size()) + } + if(dscene->tex_image_packed_info.size()) { + if(dscene->tex_image_packed_info.device_pointer) { + thread_scoped_lock device_lock(device_mutex); + device->tex_free(dscene->tex_image_packed_info); + } device->tex_alloc("__tex_image_packed_info", dscene->tex_image_packed_info); + } } void ImageManager::device_free(Device *device, DeviceScene *dscene) diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h index 187c5fd0f02..85b6b512bae 100644 --- a/intern/cycles/render/image.h +++ b/intern/cycles/render/image.h @@ -49,8 +49,8 @@ public: ImageManager(); ~ImageManager(); - int add_image(const string& filename, void *builtin_data, bool animated, bool& is_float, bool& is_linear); - void remove_image(const string& filename, void *builtin_data); + int add_image(const string& filename, void *builtin_data, bool animated, bool& is_float, bool& is_linear, InterpolationType interpolation); + void remove_image(const string& filename, void *builtin_data, InterpolationType interpolation); bool is_float_image(const string& filename, void *builtin_data, bool& is_linear); void device_update(Device *device, DeviceScene *dscene, Progress& progress); @@ -79,6 +79,8 @@ private: bool need_load; bool animated; + InterpolationType interpolation; + int users; }; diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index af6fca29ab0..e2ee3a949fd 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -193,6 +193,7 @@ ImageTextureNode::ImageTextureNode() builtin_data = NULL; color_space = ustring("Color"); projection = ustring("Flat"); + interpolation = INTERPOLATION_LINEAR; projection_blend = 0.0f; animated = false; @@ -204,7 +205,7 @@ ImageTextureNode::ImageTextureNode() ImageTextureNode::~ImageTextureNode() { if(image_manager) - image_manager->remove_image(filename, builtin_data); + image_manager->remove_image(filename, builtin_data, interpolation); } ShaderNode *ImageTextureNode::clone() const @@ -241,7 +242,7 @@ void ImageTextureNode::compile(SVMCompiler& compiler) image_manager = compiler.image_manager; if(is_float == -1) { bool is_float_bool; - slot = image_manager->add_image(filename, builtin_data, animated, is_float_bool, is_linear); + slot = image_manager->add_image(filename, builtin_data, animated, is_float_bool, is_linear, interpolation); is_float = (int)is_float_bool; } @@ -315,6 +316,24 @@ void ImageTextureNode::compile(OSLCompiler& compiler) compiler.parameter("projection_blend", projection_blend); compiler.parameter("is_float", is_float); compiler.parameter("use_alpha", !alpha_out->links.empty()); + + switch (interpolation){ + case INTERPOLATION_LINEAR: + compiler.parameter("interpolation", "linear"); + break; + case INTERPOLATION_CLOSEST: + compiler.parameter("interpolation", "closest"); + break; + case INTERPOLATION_CUBIC: + compiler.parameter("interpolation", "cubic"); + break; + case INTERPOLATION_SMART: + compiler.parameter("interpolation", "smart"); + break; + default: + compiler.parameter("interpolation", "linear"); + break; + } compiler.add(this, "node_image_texture"); } @@ -354,7 +373,7 @@ EnvironmentTextureNode::EnvironmentTextureNode() EnvironmentTextureNode::~EnvironmentTextureNode() { if(image_manager) - image_manager->remove_image(filename, builtin_data); + image_manager->remove_image(filename, builtin_data, INTERPOLATION_LINEAR); } ShaderNode *EnvironmentTextureNode::clone() const @@ -389,7 +408,7 @@ void EnvironmentTextureNode::compile(SVMCompiler& compiler) image_manager = compiler.image_manager; if(slot == -1) { bool is_float_bool; - slot = image_manager->add_image(filename, builtin_data, animated, is_float_bool, is_linear); + slot = image_manager->add_image(filename, builtin_data, animated, is_float_bool, is_linear, INTERPOLATION_LINEAR); is_float = (int)is_float_bool; } diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 86c4f490875..497a367a2a6 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -76,6 +76,7 @@ public: void *builtin_data; ustring color_space; ustring projection; + InterpolationType interpolation; float projection_blend; bool animated; diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h index 20d575e481c..5d2037960fc 100644 --- a/intern/cycles/util/util_types.h +++ b/intern/cycles/util/util_types.h @@ -450,6 +450,16 @@ ccl_device_inline int4 make_int4(const float3& f) #endif +/* Interpolation types for textures + * cuda also use texture space to store other objects */ +enum InterpolationType { + INTERPOLATION_NONE = -1, + INTERPOLATION_LINEAR = 0, + INTERPOLATION_CLOSEST = 1, + INTERPOLATION_CUBIC = 2, + INTERPOLATION_SMART = 3, +}; + CCL_NAMESPACE_END #endif /* __UTIL_TYPES_H__ */ diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index effb8eb7de5..0cdb17cb2d4 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -784,6 +784,7 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL); uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE); uiItemR(layout, ptr, "projection", 0, "", ICON_NONE); + uiItemR(layout, ptr, "interpolation", 0, "", ICON_NONE); if (RNA_enum_get(ptr, "projection") == SHD_PROJ_BOX) { uiItemR(layout, ptr, "projection_blend", 0, "Blend", ICON_NONE); diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index cd9595d8185..1ad713e64e0 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -724,7 +724,7 @@ typedef struct NodeTexImage { int color_space; int projection; float projection_blend; - int pad; + int interpolation; } NodeTexImage; typedef struct NodeTexChecker { @@ -951,6 +951,12 @@ typedef struct NodeShaderNormalMap { #define SHD_PROJ_FLAT 0 #define SHD_PROJ_BOX 1 +/* image texture interpolation */ +#define SHD_INTER_LINEAR 0 +#define SHD_INTER_CLOSEST 1 +#define SHD_INTER_CUBIC 2 +#define SHD_INTER_SMART 3 + /* tangent */ #define SHD_TANGENT_RADIAL 0 #define SHD_TANGENT_UVMAP 1 diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index d893a8c21f9..ae7dcdac423 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -3428,6 +3428,17 @@ static void def_sh_tex_image(StructRNA *srna) {0, NULL, 0, NULL, NULL} }; + static const EnumPropertyItem prop_interpolation_items[] = { + {SHD_INTER_LINEAR, "Linear", 0, "Linear", + "Linear interpolation"}, + {SHD_INTER_CLOSEST, "Closest", 0, "Closest", + "No interpolation (sample closest texel"}, + {SHD_INTER_CUBIC, "Cubic", 0, "Cubic", + "Cubic interpolation (OSL only)"}, + {SHD_INTER_SMART, "Smart", 0, "Smart", + "Bicubic when maxifying, else bilinear (OSL only)"}, + {0, NULL, 0, NULL, NULL} + }; PropertyRNA *prop; @@ -3451,6 +3462,11 @@ static void def_sh_tex_image(StructRNA *srna) RNA_def_property_ui_text(prop, "Projection", "Method to project 2D image on object with a 3D texture vector"); RNA_def_property_update(prop, 0, "rna_Node_update"); + prop = RNA_def_property(srna, "interpolation", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, prop_interpolation_items); + RNA_def_property_ui_text(prop, "Interpolation", "Texture interpolation"); + RNA_def_property_update(prop, 0, "rna_Node_update"); + prop = RNA_def_property(srna, "projection_blend", PROP_FLOAT, PROP_FACTOR); RNA_def_property_ui_text(prop, "Projection Blend", "For box projection, amount of blend to use between sides"); RNA_def_property_update(prop, 0, "rna_Node_update"); -- cgit v1.2.3