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 2018-01-22 12:20:51 +01:00
parent b90f3928a3
commit a50c381fac
1 changed files with 27 additions and 17 deletions

View File

@ -156,6 +156,16 @@ template<typename T> struct texture_image {
return make_float4(f, f, f, 1.0f);
}
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]);
}
ccl_always_inline int wrap_periodic(int x, int width)
{
x %= width;
@ -219,10 +229,9 @@ template<typename T> struct texture_image {
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);
@ -235,10 +244,10 @@ template<typename T> struct texture_image {
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]);
float4 r = (1.0f - ty) * (1.0f - tx) * read(data, ix, iy, width, height);
r += (1.0f - ty) * tx * read(data, nix, iy, width, height);
r += ty * (1.0f - tx) * read(data, ix, niy, width, height);
r += ty * tx * read(data, nix, niy, width, height);
return r;
}
@ -262,10 +271,13 @@ template<typename T> struct texture_image {
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);
@ -285,15 +297,13 @@ template<typename T> struct texture_image {
}
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) + \