Cycles: Add implementation of clip extension mode
authorSergey Sharybin <sergey.vfx@gmail.com>
Tue, 28 Jul 2015 12:36:08 +0000 (14:36 +0200)
committerSergey Sharybin <sergey.vfx@gmail.com>
Tue, 28 Jul 2015 12:36:08 +0000 (14:36 +0200)
For now there's no OpenCL support, it'll come later.

intern/cycles/device/device_cuda.cpp
intern/cycles/kernel/kernel_compat_cpu.h
intern/cycles/render/nodes.cpp
intern/cycles/util/util_types.h

index 9703b786289f8c5b1da55475c551089f85f5b618..a47d4edeb56877c56b6522af4c280e1a94b71b1a 100644 (file)
@@ -513,13 +513,19 @@ public:
                                cuda_assert(cuTexRefSetFlags(texref, CU_TRSF_READ_AS_INTEGER));
                        }
 
-                       if(extension == EXTENSION_REPEAT) {
-                               cuda_assert(cuTexRefSetAddressMode(texref, 0, CU_TR_ADDRESS_MODE_WRAP));
-                               cuda_assert(cuTexRefSetAddressMode(texref, 1, CU_TR_ADDRESS_MODE_WRAP));
-                       }
-                       else {
-                               cuda_assert(cuTexRefSetAddressMode(texref, 0, CU_TR_ADDRESS_MODE_CLAMP));
-                               cuda_assert(cuTexRefSetAddressMode(texref, 1, CU_TR_ADDRESS_MODE_CLAMP));
+                       switch(extension) {
+                               case EXTENSION_REPEAT:
+                                       cuda_assert(cuTexRefSetAddressMode(texref, 0, CU_TR_ADDRESS_MODE_WRAP));
+                                       cuda_assert(cuTexRefSetAddressMode(texref, 1, CU_TR_ADDRESS_MODE_WRAP));
+                                       break;
+                               case EXTENSION_EXTEND:
+                                       cuda_assert(cuTexRefSetAddressMode(texref, 0, CU_TR_ADDRESS_MODE_CLAMP));
+                                       cuda_assert(cuTexRefSetAddressMode(texref, 1, CU_TR_ADDRESS_MODE_CLAMP));
+                                       break;
+                               case EXTENSION_CLIP:
+                                       cuda_assert(cuTexRefSetAddressMode(texref, 0, CU_TR_ADDRESS_MODE_BORDER));
+                                       cuda_assert(cuTexRefSetAddressMode(texref, 1, CU_TR_ADDRESS_MODE_BORDER));
+                                       break;
                        }
                        cuda_assert(cuTexRefSetFormat(texref, format, mem.data_elements));
 
index be8e54b3d3de9ec17459e597e56ce34d183134b4..37387d7fa2544491aa88c8f1c1b65765ee767a33 100644 (file)
@@ -138,14 +138,20 @@ template<typename T> struct texture_image  {
                if(interpolation == INTERPOLATION_CLOSEST) {
                        frac(x*(float)width, &ix);
                        frac(y*(float)height, &iy);
-                       if(extension == EXTENSION_REPEAT) {
-                               ix = wrap_periodic(ix, width);
-                               iy = wrap_periodic(iy, height);
-
-                       }
-                       else {
-                               ix = wrap_clamp(ix, width);
-                               iy = wrap_clamp(iy, height);
+                       switch(extension) {
+                               case EXTENSION_REPEAT:
+                                       ix = wrap_periodic(ix, width);
+                                       iy = wrap_periodic(iy, height);
+                                       break;
+                               case EXTENSION_CLIP:
+                                       if (ix < 0 || iy < 0 || ix >= width || iy >= height) {
+                                               return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+                                       }
+                                       /* Fall through. */
+                               case EXTENSION_EXTEND:
+                                       ix = wrap_clamp(ix, width);
+                                       iy = wrap_clamp(iy, height);
+                                       break;
                        }
                        return read(data[ix + iy*width]);
                }
@@ -153,19 +159,26 @@ template<typename T> struct texture_image  {
                        float tx = frac(x*(float)width - 0.5f, &ix);
                        float ty = frac(y*(float)height - 0.5f, &iy);
 
-                       if(extension == EXTENSION_REPEAT) {
-                               ix = wrap_periodic(ix, width);
-                               iy = wrap_periodic(iy, height);
-
-                               nix = wrap_periodic(ix+1, width);
-                               niy = wrap_periodic(iy+1, height);
-                       }
-                       else {
-                               ix = wrap_clamp(ix, width);
-                               iy = wrap_clamp(iy, height);
-
-                               nix = wrap_clamp(ix+1, width);
-                               niy = wrap_clamp(iy+1, height);
+                       switch(extension) {
+                               case EXTENSION_REPEAT:
+                                       ix = wrap_periodic(ix, width);
+                                       iy = wrap_periodic(iy, height);
+
+                                       nix = wrap_periodic(ix+1, width);
+                                       niy = wrap_periodic(iy+1, height);
+                                       break;
+                               case EXTENSION_CLIP:
+                                       if (ix < 0 || iy < 0 || ix >= width || iy >= height) {
+                                               return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+                                       }
+                                       /* Fall through. */
+                               case EXTENSION_EXTEND:
+                                       ix = wrap_clamp(ix, width);
+                                       iy = wrap_clamp(iy, height);
+
+                                       nix = wrap_clamp(ix+1, width);
+                                       niy = wrap_clamp(iy+1, height);
+                                       break;
                        }
 
                        float4 r = (1.0f - ty)*(1.0f - tx)*read(data[ix + iy*width]);
@@ -176,36 +189,44 @@ template<typename T> struct texture_image  {
                        return r;
                }
                else {
-                       /* Tricubic b-spline interpolation. */
+                       /* Bicubic b-spline interpolation. */
                        const float tx = frac(x*(float)width - 0.5f, &ix);
                        const float ty = frac(y*(float)height - 0.5f, &iy);
                        int pix, piy, nnix, nniy;
-                       if(extension == EXTENSION_REPEAT) {
-                               ix = wrap_periodic(ix, width);
-                               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);
+                       switch(extension) {
+                               case EXTENSION_REPEAT:
+                                       ix = wrap_periodic(ix, width);
+                                       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 (ix < 0 || iy < 0 || ix >= width || iy >= height) {
+                                               return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+                                       }
+                                       /* Fall through. */
+                               case EXTENSION_EXTEND:
+                                       ix = wrap_clamp(ix, width);
+                                       iy = wrap_clamp(iy, height);
+
+                                       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);
+                                       break;
                        }
-                       else {
-                               ix = wrap_clamp(ix, width);
-                               iy = wrap_clamp(iy, height);
-
-                               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);
-                       }
                        const int xc[4] = {pix, ix, nix, nnix};
                        const int yc[4] = {width * piy,
                                           width * iy,
@@ -251,15 +272,22 @@ template<typename T> struct texture_image  {
                        frac(y*(float)height, &iy);
                        frac(z*(float)depth, &iz);
 
-                       if(extension == EXTENSION_REPEAT) {
-                               ix = wrap_periodic(ix, width);
-                               iy = wrap_periodic(iy, height);
-                               iz = wrap_periodic(iz, depth);
-                       }
-                       else {
-                               ix = wrap_clamp(ix, width);
-                               iy = wrap_clamp(iy, height);
-                               iz = wrap_clamp(iz, depth);
+                       switch(extension) {
+                               case EXTENSION_REPEAT:
+                                       ix = wrap_periodic(ix, width);
+                                       iy = wrap_periodic(iy, height);
+                                       iz = wrap_periodic(iz, depth);
+                                       break;
+                               case EXTENSION_CLIP:
+                                       if (ix < 0 || iy < 0 || ix >= width || iy >= height) {
+                                               return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+                                       }
+                                       /* Fall through. */
+                               case EXTENSION_EXTEND:
+                                       ix = wrap_clamp(ix, width);
+                                       iy = wrap_clamp(iy, height);
+                                       iz = wrap_clamp(iz, depth);
+                                       break;
                        }
 
                        return read(data[ix + iy*width + iz*width*height]);
@@ -269,23 +297,30 @@ template<typename T> struct texture_image  {
                        float ty = frac(y*(float)height - 0.5f, &iy);
                        float tz = frac(z*(float)depth - 0.5f, &iz);
 
-                       if(extension == EXTENSION_REPEAT) {
-                               ix = wrap_periodic(ix, width);
-                               iy = wrap_periodic(iy, height);
-                               iz = wrap_periodic(iz, depth);
-
-                               nix = wrap_periodic(ix+1, width);
-                               niy = wrap_periodic(iy+1, height);
-                               niz = wrap_periodic(iz+1, depth);
-                       }
-                       else {
-                               ix = wrap_clamp(ix, width);
-                               iy = wrap_clamp(iy, height);
-                               iz = wrap_clamp(iz, depth);
-
-                               nix = wrap_clamp(ix+1, width);
-                               niy = wrap_clamp(iy+1, height);
-                               niz = wrap_clamp(iz+1, depth);
+                       switch(extension) {
+                               case EXTENSION_REPEAT:
+                                       ix = wrap_periodic(ix, width);
+                                       iy = wrap_periodic(iy, height);
+                                       iz = wrap_periodic(iz, depth);
+
+                                       nix = wrap_periodic(ix+1, width);
+                                       niy = wrap_periodic(iy+1, height);
+                                       niz = wrap_periodic(iz+1, depth);
+                                       break;
+                               case EXTENSION_CLIP:
+                                       if (ix < 0 || iy < 0 || ix >= width || iy >= height) {
+                                               return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+                                       }
+                                       /* Fall through. */
+                               case EXTENSION_EXTEND:
+                                       ix = wrap_clamp(ix, width);
+                                       iy = wrap_clamp(iy, height);
+                                       iz = wrap_clamp(iz, depth);
+
+                                       nix = wrap_clamp(ix+1, width);
+                                       niy = wrap_clamp(iy+1, height);
+                                       niz = wrap_clamp(iz+1, depth);
+                                       break;
                        }
 
                        float4 r;
@@ -309,39 +344,46 @@ template<typename T> struct texture_image  {
                        const float tz = frac(z*(float)depth - 0.5f, &iz);
                        int pix, piy, piz, nnix, nniy, nniz;
 
-                       if(extension == EXTENSION_REPEAT) {
-                               ix = wrap_periodic(ix, width);
-                               iy = wrap_periodic(iy, height);
-                               iz = wrap_periodic(iz, depth);
-
-                               pix = wrap_periodic(ix-1, width);
-                               piy = wrap_periodic(iy-1, height);
-                               piz = wrap_periodic(iz-1, depth);
-
-                               nix = wrap_periodic(ix+1, width);
-                               niy = wrap_periodic(iy+1, height);
-                               niz = wrap_periodic(iz+1, depth);
-
-                               nnix = wrap_periodic(ix+2, width);
-                               nniy = wrap_periodic(iy+2, height);
-                               nniz = wrap_periodic(iz+2, depth);
-                       }
-                       else {
-                               ix = wrap_clamp(ix, width);
-                               iy = wrap_clamp(iy, height);
-                               iz = wrap_clamp(iz, depth);
-
-                               pix = wrap_clamp(ix-1, width);
-                               piy = wrap_clamp(iy-1, height);
-                               piz = wrap_clamp(iz-1, depth);
-
-                               nix = wrap_clamp(ix+1, width);
-                               niy = wrap_clamp(iy+1, height);
-                               niz = wrap_clamp(iz+1, depth);
-
-                               nnix = wrap_clamp(ix+2, width);
-                               nniy = wrap_clamp(iy+2, height);
-                               nniz = wrap_clamp(iz+2, depth);
+                       switch(extension) {
+                               case EXTENSION_REPEAT:
+                                       ix = wrap_periodic(ix, width);
+                                       iy = wrap_periodic(iy, height);
+                                       iz = wrap_periodic(iz, depth);
+
+                                       pix = wrap_periodic(ix-1, width);
+                                       piy = wrap_periodic(iy-1, height);
+                                       piz = wrap_periodic(iz-1, depth);
+
+                                       nix = wrap_periodic(ix+1, width);
+                                       niy = wrap_periodic(iy+1, height);
+                                       niz = wrap_periodic(iz+1, depth);
+
+                                       nnix = wrap_periodic(ix+2, width);
+                                       nniy = wrap_periodic(iy+2, height);
+                                       nniz = wrap_periodic(iz+2, depth);
+                                       break;
+                               case EXTENSION_CLIP:
+                                       if (ix < 0 || iy < 0 || ix >= width || iy >= height) {
+                                               return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+                                       }
+                                       /* Fall through. */
+                               case EXTENSION_EXTEND:
+                                       ix = wrap_clamp(ix, width);
+                                       iy = wrap_clamp(iy, height);
+                                       iz = wrap_clamp(iz, depth);
+
+                                       pix = wrap_clamp(ix-1, width);
+                                       piy = wrap_clamp(iy-1, height);
+                                       piz = wrap_clamp(iz-1, depth);
+
+                                       nix = wrap_clamp(ix+1, width);
+                                       niy = wrap_clamp(iy+1, height);
+                                       niz = wrap_clamp(iz+1, depth);
+
+                                       nnix = wrap_clamp(ix+2, width);
+                                       nniy = wrap_clamp(iy+2, height);
+                                       nniz = wrap_clamp(iz+2, depth);
+                                       break;
                        }
 
                        const int xc[4] = {pix, ix, nix, nnix};
index e766c0c20d6906727daf7927ae412fb5091a8fbf..7ed07ab64537021d5c3767797910ff7917e6892c 100644 (file)
@@ -379,11 +379,17 @@ void ImageTextureNode::compile(OSLCompiler& compiler)
                        break;
        }
 
-       if (extension == EXTENSION_REPEAT) {
-               compiler.parameter("wrap", "periodic");
-       }
-       else {
-               compiler.parameter("wrap", "clamp");
+       switch(extension) {
+               case EXTENSION_EXTEND:
+                       compiler.parameter("wrap", "clamp");
+                       break;
+               case EXTENSION_CLIP:
+                       compiler.parameter("wrap", "black");
+                       break;
+               case EXTENSION_REPEAT:
+               default:
+                       compiler.parameter("wrap", "periodic");
+                       break;
        }
 
        compiler.add(this, "node_image_texture");
index 5198194b652b4477976559ecd1d5d4a2ab0ea94b..6f474f873a60b1cd4db4b17cabf94f605319b597 100644 (file)
@@ -479,6 +479,8 @@ enum ExtensionType {
        EXTENSION_REPEAT = 0,
        /* Extend by repeating edge pixels of the image. */
        EXTENSION_EXTEND = 1,
+       /* Clip to image size and set exterior pixels as transparent. */
+       EXTENSION_CLIP = 2,
 };
 
 /* macros */