Cycles: Fix difference in image Clip extension method between CPU and GPU

Our own implementation was behaving different comparing to OSL and GPU,
namely on the border pixels OSL and CUDA was doing interpolation with
black, but we were clamping coordinate.

This partially fixes issue reported in T53452.

Similar change should also be done for 3D interpolation perhaps, but this
is to be investigated separately.
This commit is contained in:
Sergey Sharybin 2017-12-08 11:20:12 +01:00
parent f31fb4a014
commit 2e8914549b
Notes: blender-bot 2023-02-14 06:17:19 +01:00
Referenced by issue #53683, 2.79a release
1 changed files with 28 additions and 19 deletions

View File

@ -63,6 +63,16 @@ template<typename T> struct TextureInterpolator {
return make_float4(f, f, f, 1.0f);
}
static ccl_always_inline float4 read(const T *data,
int x, int y,
int width, int height)
{
if(x < 0 || y < 0 || x >= width || y >= height) {
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
}
return read(data[y * width + x]);
}
static ccl_always_inline int wrap_periodic(int x, int width)
{
x %= width;
@ -132,10 +142,9 @@ template<typename T> struct TextureInterpolator {
niy = wrap_periodic(iy+1, height);
break;
case EXTENSION_CLIP:
if(x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f) {
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
}
ATTR_FALLTHROUGH;
nix = ix + 1;
niy = iy + 1;
break;
case EXTENSION_EXTEND:
nix = wrap_clamp(ix+1, width);
niy = wrap_clamp(iy+1, height);
@ -146,11 +155,10 @@ template<typename T> struct TextureInterpolator {
kernel_assert(0);
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
}
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;
return (1.0f - ty) * (1.0f - tx) * read(data, ix, iy, width, height) +
(1.0f - ty) * tx * read(data, nix, iy, width, height) +
ty * (1.0f - tx) * read(data, ix, niy, width, height) +
ty * tx * read(data, nix, niy, width, height);
}
static ccl_always_inline float4 interp_cubic(const TextureInfo& info,
@ -175,10 +183,13 @@ template<typename T> struct TextureInterpolator {
nniy = wrap_periodic(iy+2, height);
break;
case EXTENSION_CLIP:
if(x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f) {
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
}
ATTR_FALLTHROUGH;
pix = ix - 1;
piy = iy - 1;
nix = ix + 1;
niy = iy + 1;
nnix = ix + 2;
nniy = iy + 2;
break;
case EXTENSION_EXTEND:
pix = wrap_clamp(ix-1, width);
piy = wrap_clamp(iy-1, height);
@ -194,15 +205,12 @@ template<typename T> struct TextureInterpolator {
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
}
const int xc[4] = {pix, ix, nix, nnix};
const int yc[4] = {width * piy,
width * iy,
width * niy,
width * nniy};
const int yc[4] = {piy, iy, niy, 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) (read(data[xc[x] + yc[y]]))
#define DATA(x, y) (read(data, xc[x], yc[y], width, height))
#define TERM(col) \
(v[col] * (u[0] * DATA(0, col) + \
u[1] * DATA(1, col) + \
@ -218,7 +226,8 @@ template<typename T> struct TextureInterpolator {
#undef DATA
}
static ccl_always_inline float4 interp(const TextureInfo& info, float x, float y)
static ccl_always_inline float4 interp(const TextureInfo& info,
float x, float y)
{
if(UNLIKELY(!info.data)) {
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);