forked from bartvdbraak/blender
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
This commit is contained in:
parent
ef51b69009
commit
dd2dca2f7e
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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());
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -117,14 +117,19 @@ template<typename T> 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<uchar4> 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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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<uchar4>& 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)
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -76,6 +76,7 @@ public:
|
||||
void *builtin_data;
|
||||
ustring color_space;
|
||||
ustring projection;
|
||||
InterpolationType interpolation;
|
||||
float projection_blend;
|
||||
bool animated;
|
||||
|
||||
|
@ -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__ */
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user