Cycles: Cleanup, split 2D interpolation function
This commit is contained in:
@@ -83,145 +83,160 @@ template<typename T> struct TextureInterpolator {
|
|||||||
return x - (float)i;
|
return x - (float)i;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ccl_always_inline float4 interp(const TextureInfo& info, float x, float y)
|
/* ******** 2D interpolation ******** */
|
||||||
|
|
||||||
|
static ccl_always_inline float4 interp_closest(const TextureInfo& info,
|
||||||
|
float x, float y)
|
||||||
{
|
{
|
||||||
if(UNLIKELY(!info.data))
|
|
||||||
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
|
||||||
|
|
||||||
const T *data = (const T*)info.data;
|
const T *data = (const T*)info.data;
|
||||||
int width = info.width;
|
const int width = info.width;
|
||||||
int height = info.height;
|
const int height = info.height;
|
||||||
|
int ix, iy;
|
||||||
|
frac(x*(float)width, &ix);
|
||||||
|
frac(y*(float)height, &iy);
|
||||||
|
switch(info.extension) {
|
||||||
|
case EXTENSION_REPEAT:
|
||||||
|
ix = wrap_periodic(ix, width);
|
||||||
|
iy = wrap_periodic(iy, 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;
|
||||||
|
case EXTENSION_EXTEND:
|
||||||
|
ix = wrap_clamp(ix, width);
|
||||||
|
iy = wrap_clamp(iy, height);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
kernel_assert(0);
|
||||||
|
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
return read(data[ix + iy*width]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ccl_always_inline float4 interp_linear(const TextureInfo& info,
|
||||||
|
float x, float y)
|
||||||
|
{
|
||||||
|
const T *data = (const T*)info.data;
|
||||||
|
const int width = info.width;
|
||||||
|
const int height = info.height;
|
||||||
int ix, iy, nix, niy;
|
int ix, iy, nix, niy;
|
||||||
|
const float tx = frac(x*(float)width - 0.5f, &ix);
|
||||||
if(info.interpolation == INTERPOLATION_CLOSEST) {
|
const float ty = frac(y*(float)height - 0.5f, &iy);
|
||||||
frac(x*(float)width, &ix);
|
switch(info.extension) {
|
||||||
frac(y*(float)height, &iy);
|
case EXTENSION_REPEAT:
|
||||||
switch(info.extension) {
|
ix = wrap_periodic(ix, width);
|
||||||
case EXTENSION_REPEAT:
|
iy = wrap_periodic(iy, height);
|
||||||
ix = wrap_periodic(ix, width);
|
nix = wrap_periodic(ix+1, width);
|
||||||
iy = wrap_periodic(iy, height);
|
niy = wrap_periodic(iy+1, height);
|
||||||
break;
|
break;
|
||||||
case EXTENSION_CLIP:
|
case EXTENSION_CLIP:
|
||||||
if(x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f) {
|
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;
|
|
||||||
case EXTENSION_EXTEND:
|
|
||||||
ix = wrap_clamp(ix, width);
|
|
||||||
iy = wrap_clamp(iy, height);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
kernel_assert(0);
|
|
||||||
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
return read(data[ix + iy*width]);
|
ATTR_FALLTHROUGH;
|
||||||
|
case EXTENSION_EXTEND:
|
||||||
|
nix = wrap_clamp(ix+1, width);
|
||||||
|
niy = wrap_clamp(iy+1, height);
|
||||||
|
ix = wrap_clamp(ix, width);
|
||||||
|
iy = wrap_clamp(iy, height);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
kernel_assert(0);
|
||||||
|
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
else if(info.interpolation == INTERPOLATION_LINEAR) {
|
float4 r = (1.0f - ty)*(1.0f - tx)*read(data[ix + iy*width]);
|
||||||
float tx = frac(x*(float)width - 0.5f, &ix);
|
r += (1.0f - ty)*tx*read(data[nix + iy*width]);
|
||||||
float ty = frac(y*(float)height - 0.5f, &iy);
|
r += ty*(1.0f - tx)*read(data[ix + niy*width]);
|
||||||
|
r += ty*tx*read(data[nix + niy*width]);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
switch(info.extension) {
|
static ccl_always_inline float4 interp_cubic(const TextureInfo& info,
|
||||||
case EXTENSION_REPEAT:
|
float x, float y)
|
||||||
ix = wrap_periodic(ix, width);
|
{
|
||||||
iy = wrap_periodic(iy, height);
|
const T *data = (const T*)info.data;
|
||||||
|
const int width = info.width;
|
||||||
nix = wrap_periodic(ix+1, width);
|
const int height = info.height;
|
||||||
niy = wrap_periodic(iy+1, height);
|
int ix, iy, nix, niy;
|
||||||
break;
|
const float tx = frac(x*(float)width - 0.5f, &ix);
|
||||||
case EXTENSION_CLIP:
|
const float ty = frac(y*(float)height - 0.5f, &iy);
|
||||||
if(x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f) {
|
int pix, piy, nnix, nniy;
|
||||||
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
switch(info.extension) {
|
||||||
}
|
case EXTENSION_REPEAT:
|
||||||
ATTR_FALLTHROUGH;
|
ix = wrap_periodic(ix, width);
|
||||||
case EXTENSION_EXTEND:
|
iy = wrap_periodic(iy, height);
|
||||||
nix = wrap_clamp(ix+1, width);
|
pix = wrap_periodic(ix-1, width);
|
||||||
niy = wrap_clamp(iy+1, height);
|
piy = wrap_periodic(iy-1, height);
|
||||||
|
nix = wrap_periodic(ix+1, width);
|
||||||
ix = wrap_clamp(ix, width);
|
niy = wrap_periodic(iy+1, height);
|
||||||
iy = wrap_clamp(iy, height);
|
nnix = wrap_periodic(ix+2, width);
|
||||||
break;
|
nniy = wrap_periodic(iy+2, height);
|
||||||
default:
|
break;
|
||||||
kernel_assert(0);
|
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);
|
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
ATTR_FALLTHROUGH;
|
||||||
float4 r = (1.0f - ty)*(1.0f - tx)*read(data[ix + iy*width]);
|
case EXTENSION_EXTEND:
|
||||||
r += (1.0f - ty)*tx*read(data[nix + iy*width]);
|
pix = wrap_clamp(ix-1, width);
|
||||||
r += ty*(1.0f - tx)*read(data[ix + niy*width]);
|
piy = wrap_clamp(iy-1, height);
|
||||||
r += ty*tx*read(data[nix + niy*width]);
|
nix = wrap_clamp(ix+1, width);
|
||||||
|
niy = wrap_clamp(iy+1, height);
|
||||||
return r;
|
nnix = wrap_clamp(ix+2, width);
|
||||||
|
nniy = wrap_clamp(iy+2, height);
|
||||||
|
ix = wrap_clamp(ix, width);
|
||||||
|
iy = wrap_clamp(iy, height);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
kernel_assert(0);
|
||||||
|
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
else {
|
const int xc[4] = {pix, ix, nix, nnix};
|
||||||
/* Bicubic b-spline interpolation. */
|
const int yc[4] = {width * piy,
|
||||||
float tx = frac(x*(float)width - 0.5f, &ix);
|
width * iy,
|
||||||
float ty = frac(y*(float)height - 0.5f, &iy);
|
width * niy,
|
||||||
int pix, piy, nnix, nniy;
|
width * nniy};
|
||||||
switch(info.extension) {
|
float u[4], v[4];
|
||||||
case EXTENSION_REPEAT:
|
/* Some helper macro to keep code reasonable size,
|
||||||
ix = wrap_periodic(ix, width);
|
* let compiler to inline all the matrix multiplications.
|
||||||
iy = wrap_periodic(iy, height);
|
*/
|
||||||
|
|
||||||
pix = wrap_periodic(ix-1, width);
|
|
||||||
piy = wrap_periodic(iy-1, height);
|
|
||||||
|
|
||||||
nix = wrap_periodic(ix+1, width);
|
|
||||||
niy = wrap_periodic(iy+1, height);
|
|
||||||
|
|
||||||
nnix = wrap_periodic(ix+2, width);
|
|
||||||
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;
|
|
||||||
case EXTENSION_EXTEND:
|
|
||||||
pix = wrap_clamp(ix-1, width);
|
|
||||||
piy = wrap_clamp(iy-1, height);
|
|
||||||
|
|
||||||
nix = wrap_clamp(ix+1, width);
|
|
||||||
niy = wrap_clamp(iy+1, height);
|
|
||||||
|
|
||||||
nnix = wrap_clamp(ix+2, width);
|
|
||||||
nniy = wrap_clamp(iy+2, height);
|
|
||||||
|
|
||||||
ix = wrap_clamp(ix, width);
|
|
||||||
iy = wrap_clamp(iy, height);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
kernel_assert(0);
|
|
||||||
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};
|
|
||||||
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]]))
|
||||||
#define TERM(col) \
|
#define TERM(col) \
|
||||||
(v[col] * (u[0] * DATA(0, col) + \
|
(v[col] * (u[0] * DATA(0, col) + \
|
||||||
u[1] * DATA(1, col) + \
|
u[1] * DATA(1, col) + \
|
||||||
u[2] * DATA(2, col) + \
|
u[2] * DATA(2, col) + \
|
||||||
u[3] * DATA(3, col)))
|
u[3] * DATA(3, col)))
|
||||||
|
|
||||||
SET_CUBIC_SPLINE_WEIGHTS(u, tx);
|
SET_CUBIC_SPLINE_WEIGHTS(u, tx);
|
||||||
SET_CUBIC_SPLINE_WEIGHTS(v, ty);
|
SET_CUBIC_SPLINE_WEIGHTS(v, ty);
|
||||||
|
|
||||||
/* Actual interpolation. */
|
|
||||||
return TERM(0) + TERM(1) + TERM(2) + TERM(3);
|
|
||||||
|
|
||||||
|
/* Actual interpolation. */
|
||||||
|
return TERM(0) + TERM(1) + TERM(2) + TERM(3);
|
||||||
#undef TERM
|
#undef TERM
|
||||||
#undef DATA
|
#undef DATA
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
switch(info.interpolation) {
|
||||||
|
case INTERPOLATION_CLOSEST:
|
||||||
|
return interp_closest(info, x, y);
|
||||||
|
case INTERPOLATION_LINEAR:
|
||||||
|
return interp_linear(info, x, y);
|
||||||
|
default:
|
||||||
|
return interp_cubic(info, x, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static ccl_always_inline float4 interp_3d_closest(const TextureInfo& info, float x, float y, float z)
|
/* ******** 3D interpolation ******** */
|
||||||
|
|
||||||
|
static ccl_always_inline float4 interp_3d_closest(const TextureInfo& info,
|
||||||
|
float x, float y, float z)
|
||||||
{
|
{
|
||||||
int width = info.width;
|
int width = info.width;
|
||||||
int height = info.height;
|
int height = info.height;
|
||||||
@@ -259,7 +274,8 @@ template<typename T> struct TextureInterpolator {
|
|||||||
return read(data[ix + iy*width + iz*width*height]);
|
return read(data[ix + iy*width + iz*width*height]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ccl_always_inline float4 interp_3d_linear(const TextureInfo& info, float x, float y, float z)
|
static ccl_always_inline float4 interp_3d_linear(const TextureInfo& info,
|
||||||
|
float x, float y, float z)
|
||||||
{
|
{
|
||||||
int width = info.width;
|
int width = info.width;
|
||||||
int height = info.height;
|
int height = info.height;
|
||||||
|
Reference in New Issue
Block a user