diff options
author | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2017-10-08 03:36:05 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2017-10-08 03:55:44 +0300 |
commit | f61c340bc15ef1573dc48f65fc7c71fce0a47a07 (patch) | |
tree | e528f0faafd466a780471ae5b8029e9f102128f3 /intern | |
parent | c040dedc124a413c13c62677f7d6aee0fd15668f (diff) |
Cycles: OpenCL bicubic and tricubic texture interpolation support.
Diffstat (limited to 'intern')
-rw-r--r-- | intern/cycles/blender/addon/ui.py | 8 | ||||
-rw-r--r-- | intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h | 166 | ||||
-rw-r--r-- | intern/cycles/util/util_texture.h | 12 |
3 files changed, 147 insertions, 39 deletions
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index baf1b9c31ee..7d19bccae4e 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -1208,9 +1208,7 @@ class CYCLES_WORLD_PT_settings(CyclesButtonsPanel, Panel): sub = col.column() sub.active = use_cpu(context) sub.prop(cworld, "volume_sampling", text="") - sub = col.column() - sub.active = not use_opencl(context) - sub.prop(cworld, "volume_interpolation", text="") + col.prop(cworld, "volume_interpolation", text="") col.prop(cworld, "homogeneous_volume", text="Homogeneous") @@ -1309,9 +1307,7 @@ class CYCLES_MATERIAL_PT_settings(CyclesButtonsPanel, Panel): sub = col.column() sub.active = use_cpu(context) sub.prop(cmat, "volume_sampling", text="") - sub = col.column() - sub.active = not use_opencl(context) - sub.prop(cmat, "volume_interpolation", text="") + col.prop(cmat, "volume_interpolation", text="") col.prop(cmat, "homogeneous_volume", text="Homogeneous") layout.separator() diff --git a/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h b/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h index 20ec36aa9eb..d908af78c7a 100644 --- a/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h +++ b/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h @@ -75,20 +75,26 @@ ccl_device_inline float svm_image_texture_frac(float x, int *ix) return x - (float)i; } +#define SET_CUBIC_SPLINE_WEIGHTS(u, t) \ + { \ + u[0] = (((-1.0f/6.0f)* t + 0.5f) * t - 0.5f) * t + (1.0f/6.0f); \ + u[1] = (( 0.5f * t - 1.0f) * t ) * t + (2.0f/3.0f); \ + u[2] = (( -0.5f * t + 0.5f) * t + 0.5f) * t + (1.0f/6.0f); \ + u[3] = (1.0f / 6.0f) * t * t * t; \ + } (void)0 + ccl_device float4 kernel_tex_image_interp(KernelGlobals *kg, int id, float x, float y) { const ccl_global TextureInfo *info = kernel_tex_info(kg, id); uint width = info->width; uint height = info->height; - uint offset = 0; uint interpolation = info->interpolation; uint extension = info->extension; /* Actual sampling. */ - float4 r; - int ix, iy, nix, niy; if(interpolation == INTERPOLATION_CLOSEST) { + int ix, iy; svm_image_texture_frac(x*width, &ix); svm_image_texture_frac(y*height, &iy); @@ -108,16 +114,17 @@ ccl_device float4 kernel_tex_image_interp(KernelGlobals *kg, int id, float x, fl iy = svm_image_texture_wrap_clamp(iy, height); } - r = svm_image_texture_read(kg, id, offset + ix + iy*width); + return svm_image_texture_read(kg, id, ix + iy*width); } - else { /* INTERPOLATION_LINEAR */ + else { + /* Bilinear or bicubic interpolation. */ + int ix, iy, nix, niy; float tx = svm_image_texture_frac(x*width - 0.5f, &ix); float ty = svm_image_texture_frac(y*height - 0.5f, &iy); if(extension == EXTENSION_REPEAT) { ix = svm_image_texture_wrap_periodic(ix, width); iy = svm_image_texture_wrap_periodic(iy, height); - nix = svm_image_texture_wrap_periodic(ix+1, width); niy = svm_image_texture_wrap_periodic(iy+1, height); } @@ -127,18 +134,61 @@ ccl_device float4 kernel_tex_image_interp(KernelGlobals *kg, int id, float x, fl return make_float4(0.0f, 0.0f, 0.0f, 0.0f); } } - nix = svm_image_texture_wrap_clamp(ix+1, width); - niy = svm_image_texture_wrap_clamp(iy+1, height); ix = svm_image_texture_wrap_clamp(ix, width); iy = svm_image_texture_wrap_clamp(iy, height); + nix = svm_image_texture_wrap_clamp(ix+1, width); + niy = svm_image_texture_wrap_clamp(iy+1, height); } - r = (1.0f - ty)*(1.0f - tx)*svm_image_texture_read(kg, id, offset + ix + iy*width); - r += (1.0f - ty)*tx*svm_image_texture_read(kg, id, offset + nix + iy*width); - r += ty*(1.0f - tx)*svm_image_texture_read(kg, id, offset + ix + niy*width); - r += ty*tx*svm_image_texture_read(kg, id, offset + nix + niy*width); + if(interpolation == INTERPOLATION_LINEAR) { + /* Bilinear interpolation. */ + float4 r; + r = (1.0f - ty)*(1.0f - tx)*svm_image_texture_read(kg, id, ix + iy*width); + r += (1.0f - ty)*tx*svm_image_texture_read(kg, id, nix + iy*width); + r += ty*(1.0f - tx)*svm_image_texture_read(kg, id, ix + niy*width); + r += ty*tx*svm_image_texture_read(kg, id, nix + niy*width); + return r; + } + + /* Bicubic interpolation. */ + int pix, piy, nnix, nniy; + if(extension == EXTENSION_REPEAT) { + pix = svm_image_texture_wrap_periodic(ix-1, width); + piy = svm_image_texture_wrap_periodic(iy-1, height); + nnix = svm_image_texture_wrap_periodic(ix+2, width); + nniy = svm_image_texture_wrap_periodic(iy+2, height); + } + else { + pix = svm_image_texture_wrap_clamp(ix-1, width); + piy = svm_image_texture_wrap_clamp(iy-1, height); + nnix = svm_image_texture_wrap_clamp(ix+2, width); + nniy = svm_image_texture_wrap_clamp(iy+2, height); + } + + const int xc[4] = {pix, ix, nix, nnix}; + const int yc[4] = {width * piy, + width * iy, + width * niy, + width * nniy}; + float u[4], v[4]; + /* Some helper macro to keep code reasonable size, + * let compiler to inline all the matrix multiplications. + */ +#define DATA(x, y) (svm_image_texture_read(kg, id, xc[x] + yc[y])) +#define TERM(col) \ + (v[col] * (u[0] * DATA(0, col) + \ + u[1] * DATA(1, col) + \ + u[2] * DATA(2, col) + \ + u[3] * DATA(3, col))) + + SET_CUBIC_SPLINE_WEIGHTS(u, tx); + SET_CUBIC_SPLINE_WEIGHTS(v, ty); + + /* Actual interpolation. */ + return TERM(0) + TERM(1) + TERM(2) + TERM(3); +#undef TERM +#undef DATA } - return r; } @@ -148,15 +198,13 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals *kg, int id, float x, uint width = info->width; uint height = info->height; - uint offset = 0; uint depth = info->depth; uint interpolation = (interp == INTERPOLATION_NONE)? info->interpolation: interp; uint extension = info->extension; /* Actual sampling. */ - float4 r; - int ix, iy, iz, nix, niy, niz; if(interpolation == INTERPOLATION_CLOSEST) { + int ix, iy, iz; svm_image_texture_frac(x*width, &ix); svm_image_texture_frac(y*height, &iy); svm_image_texture_frac(z*depth, &iz); @@ -180,9 +228,11 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals *kg, int id, float x, iy = svm_image_texture_wrap_clamp(iy, height); iz = svm_image_texture_wrap_clamp(iz, depth); } - r = svm_image_texture_read(kg, id, offset + ix + iy*width + iz*width*height); + return svm_image_texture_read(kg, id, ix + iy*width + iz*width*height); } - else { /* INTERPOLATION_LINEAR */ + else { + /* Bilinear or bicubic interpolation. */ + int ix, iy, iz, nix, niy, niz; float tx = svm_image_texture_frac(x*(float)width - 0.5f, &ix); float ty = svm_image_texture_frac(y*(float)height - 0.5f, &iy); float tz = svm_image_texture_frac(z*(float)depth - 0.5f, &iz); @@ -215,15 +265,77 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals *kg, int id, float x, iz = svm_image_texture_wrap_clamp(iz, depth); } - r = (1.0f - tz)*(1.0f - ty)*(1.0f - tx)*svm_image_texture_read(kg, id, offset + ix + iy*width + iz*width*height); - r += (1.0f - tz)*(1.0f - ty)*tx*svm_image_texture_read(kg, id, offset + nix + iy*width + iz*width*height); - r += (1.0f - tz)*ty*(1.0f - tx)*svm_image_texture_read(kg, id, offset + ix + niy*width + iz*width*height); - r += (1.0f - tz)*ty*tx*svm_image_texture_read(kg, id, offset + nix + niy*width + iz*width*height); + if(interpolation == INTERPOLATION_LINEAR) { + /* Bilinear interpolation. */ + float4 r; + r = (1.0f - tz)*(1.0f - ty)*(1.0f - tx)*svm_image_texture_read(kg, id, ix + iy*width + iz*width*height); + r += (1.0f - tz)*(1.0f - ty)*tx*svm_image_texture_read(kg, id, nix + iy*width + iz*width*height); + r += (1.0f - tz)*ty*(1.0f - tx)*svm_image_texture_read(kg, id, ix + niy*width + iz*width*height); + r += (1.0f - tz)*ty*tx*svm_image_texture_read(kg, id, nix + niy*width + iz*width*height); + + r += tz*(1.0f - ty)*(1.0f - tx)*svm_image_texture_read(kg, id, ix + iy*width + niz*width*height); + r += tz*(1.0f - ty)*tx*svm_image_texture_read(kg, id, nix + iy*width + niz*width*height); + r += tz*ty*(1.0f - tx)*svm_image_texture_read(kg, id, ix + niy*width + niz*width*height); + r += tz*ty*tx*svm_image_texture_read(kg, id, nix + niy*width + niz*width*height); + return r; + } + + /* Bicubic interpolation. */ + int pix, piy, piz, nnix, nniy, nniz; + if(extension == EXTENSION_REPEAT) { + pix = svm_image_texture_wrap_periodic(ix-1, width); + piy = svm_image_texture_wrap_periodic(iy-1, height); + piz = svm_image_texture_wrap_periodic(iz-1, depth); + nnix = svm_image_texture_wrap_periodic(ix+2, width); + nniy = svm_image_texture_wrap_periodic(iy+2, height); + nniz = svm_image_texture_wrap_periodic(iz+2, depth); + } + else { + pix = svm_image_texture_wrap_clamp(ix-1, width); + piy = svm_image_texture_wrap_clamp(iy-1, height); + piz = svm_image_texture_wrap_clamp(iz-1, depth); + nnix = svm_image_texture_wrap_clamp(ix+2, width); + nniy = svm_image_texture_wrap_clamp(iy+2, height); + nniz = svm_image_texture_wrap_clamp(iz+2, depth); + } + + const int xc[4] = {pix, ix, nix, nnix}; + const int yc[4] = {width * piy, + width * iy, + width * niy, + width * nniy}; + const int zc[4] = {width * height * piz, + width * height * iz, + width * height * niz, + width * height * nniz}; + float u[4], v[4], w[4]; + + /* Some helper macro to keep code reasonable size, + * let compiler to inline all the matrix multiplications. + */ +#define DATA(x, y, z) (svm_image_texture_read(kg, id, xc[x] + yc[y] + zc[z])) +#define COL_TERM(col, row) \ + (v[col] * (u[0] * DATA(0, col, row) + \ + u[1] * DATA(1, col, row) + \ + u[2] * DATA(2, col, row) + \ + u[3] * DATA(3, col, row))) +#define ROW_TERM(row) \ + (w[row] * (COL_TERM(0, row) + \ + COL_TERM(1, row) + \ + COL_TERM(2, row) + \ + COL_TERM(3, row))) - r += tz*(1.0f - ty)*(1.0f - tx)*svm_image_texture_read(kg, id, offset + ix + iy*width + niz*width*height); - r += tz*(1.0f - ty)*tx*svm_image_texture_read(kg, id, offset + nix + iy*width + niz*width*height); - r += tz*ty*(1.0f - tx)*svm_image_texture_read(kg, id, offset + ix + niy*width + niz*width*height); - r += tz*ty*tx*svm_image_texture_read(kg, id, offset + nix + niy*width + niz*width*height); + SET_CUBIC_SPLINE_WEIGHTS(u, tx); + SET_CUBIC_SPLINE_WEIGHTS(v, ty); + SET_CUBIC_SPLINE_WEIGHTS(w, tz); + + /* Actual interpolation. */ + return ROW_TERM(0) + ROW_TERM(1) + ROW_TERM(2) + ROW_TERM(3); + +#undef COL_TERM +#undef ROW_TERM +#undef DATA } - return r; } + +#undef SET_CUBIC_SPLINE_WEIGHTS diff --git a/intern/cycles/util/util_texture.h b/intern/cycles/util/util_texture.h index f22948d9bcd..cec03dc5e6e 100644 --- a/intern/cycles/util/util_texture.h +++ b/intern/cycles/util/util_texture.h @@ -52,7 +52,7 @@ CCL_NAMESPACE_BEGIN /* Interpolation types for textures * cuda also use texture space to store other objects */ -enum InterpolationType { +typedef enum InterpolationType { INTERPOLATION_NONE = -1, INTERPOLATION_LINEAR = 0, INTERPOLATION_CLOSEST = 1, @@ -60,12 +60,12 @@ enum InterpolationType { INTERPOLATION_SMART = 3, INTERPOLATION_NUM_TYPES, -}; +} InterpolationType; /* Texture types * Since we store the type in the lower bits of a flat index, * the shift and bit mask constant below need to be kept in sync. */ -enum ImageDataType { +typedef enum ImageDataType { IMAGE_DATA_TYPE_FLOAT4 = 0, IMAGE_DATA_TYPE_BYTE4 = 1, IMAGE_DATA_TYPE_HALF4 = 2, @@ -74,7 +74,7 @@ enum ImageDataType { IMAGE_DATA_TYPE_HALF = 5, IMAGE_DATA_NUM_TYPES -}; +} ImageDataType; #define IMAGE_DATA_TYPE_SHIFT 3 #define IMAGE_DATA_TYPE_MASK 0x7 @@ -82,7 +82,7 @@ enum ImageDataType { /* Extension types for textures. * * Defines how the image is extrapolated past its original bounds. */ -enum ExtensionType { +typedef enum ExtensionType { /* Cause the image to repeat horizontally and vertically. */ EXTENSION_REPEAT = 0, /* Extend by repeating edge pixels of the image. */ @@ -91,7 +91,7 @@ enum ExtensionType { EXTENSION_CLIP = 2, EXTENSION_NUM_TYPES, -}; +} ExtensionType; typedef struct TextureInfo { /* Pointer, offset or texture depending on device. */ |