Cycles: Support tube projection for images
authorSergey Sharybin <sergey.vfx@gmail.com>
Wed, 21 Jan 2015 19:37:09 +0000 (00:37 +0500)
committerSergey Sharybin <sergey.vfx@gmail.com>
Wed, 21 Jan 2015 19:41:42 +0000 (00:41 +0500)
This way Cycles finally becomes feature-full on image projections
compared to Blender Internal and Gooseberry Project Team could
finally finish the movie.

intern/cycles/kernel/shaders/node_image_texture.osl
intern/cycles/kernel/svm/svm_image.h
intern/cycles/kernel/svm/svm_types.h
intern/cycles/render/nodes.cpp
intern/cycles/util/util_math.h
source/blender/makesdna/DNA_node_types.h
source/blender/makesrna/intern/rna_nodetree.c

index c63ad179060083a122d8a61e5636e799fd5887f3..526a87525cd2995cbc6fd6e9d87b2374af6e00c5 100644 (file)
 #include "stdosl.h"
 #include "node_color.h"
 
+point texco_remap_square(point co)
+{
+       return (co - point(0.5, 0.5, 0.5)) * 2.0;
+}
+
+point map_to_tube(vector dir)
+{
+       float u, v;
+       v = (dir[2] + 1.0) * 0.5;
+       float len = sqrt(dir[0]*dir[0] + dir[1]*dir[1]);
+       if (len > 0.0) {
+               u = (1.0 - (atan2(dir[0] / len, dir[1] / len) / M_PI)) * 0.5;
+       }
+       else {
+               v = u = 0.0; /* To avoid un-initialized variables. */
+       }
+       return point(u, v, 0.0);
+}
+
 point map_to_sphere(vector dir)
 {
        float len = length(dir);
        float v, u;
        if(len > 0.0) {
                if(dir[0] == 0.0 && dir[1] == 0.0) {
-                       u = 0.0;  /* othwise domain error */
+                       u = 0.0;  /* Othwise domain error. */
                }
                else {
                        u = (1.0 - atan2(dir[0], dir[1]) / M_PI) / 2.0;
@@ -31,7 +50,7 @@ point map_to_sphere(vector dir)
                v = 1.0 - acos(dir[2] / len) / M_PI;
        }
        else {
-               v = u = 0.0; /* to avoid un-initialized variables */
+               v = u = 0.0;  /* To avoid un-initialized variables. */
        }
        return point(u, v, 0.0);
 }
@@ -156,7 +175,13 @@ shader node_image_texture(
                }
        }
        else if (projection == "Sphere") {
-               point projected = map_to_sphere((p - vector(0.5, 0.5, 0.5)) * 2.0);
+               point projected = map_to_sphere(texco_remap_square(p));
+               Color = image_texture_lookup(filename, color_space,
+                                            projected[0], projected[1],
+                                            Alpha, use_alpha, is_float, interpolation);
+       }
+       else if (projection == "Tube") {
+               point projected = map_to_tube(texco_remap_square(p));
                Color = image_texture_lookup(filename, color_space,
                                             projected[0], projected[1],
                                             Alpha, use_alpha, is_float, interpolation);
index 44d15e185cbd32562e5664f05a5c68ba861baa12..e667fc2033d4df7660a392510b5e63ad8a9ebcbd 100644 (file)
@@ -354,6 +354,12 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y,
 
 #endif
 
+/* Remap coordnate from 0..1 box to -1..-1 */
+ccl_device_inline float3 texco_remap_square(float3 co)
+{
+       return (co - make_float3(0.5f, 0.5f, 0.5f)) * 2.0f;
+}
+
 ccl_device void svm_node_tex_image(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
 {
        uint id = node.y;
@@ -364,9 +370,13 @@ ccl_device void svm_node_tex_image(KernelGlobals *kg, ShaderData *sd, float *sta
        float3 co = stack_load_float3(stack, co_offset);
        uint use_alpha = stack_valid(alpha_offset);
        if(node.w == NODE_IMAGE_PROJ_SPHERE) {
-               co = (co - make_float3(0.5f, 0.5f, 0.5f)) * 2.0f;
+               co = texco_remap_square(co);
                map_to_sphere(&co.x, &co.y, co.x, co.y, co.z);
        }
+       else if(node.w == NODE_IMAGE_PROJ_TUBE) {
+               co = texco_remap_square(co);
+               map_to_tube(&co.x, &co.y, co.x, co.y, co.z);
+       }
        float4 f = svm_image_texture(kg, id, co.x, co.y, srgb, use_alpha);
 
        if(stack_valid(out_offset))
index d5c3cebe1af37d98645c0bc16d264e8886ad8abf..a8d0da6ff393fafddeb23949dc4479f7992da5be 100644 (file)
@@ -338,6 +338,7 @@ typedef enum NodeImageProjection {
        NODE_IMAGE_PROJ_FLAT   = 0,
        NODE_IMAGE_PROJ_BOX    = 1,
        NODE_IMAGE_PROJ_SPHERE = 2,
+       NODE_IMAGE_PROJ_TUBE   = 3,
 } NodeImageProjection;
 
 typedef enum ShaderType {
index 05ead55ca2d1060ab5be812d545397159ea997ba..ed0be4d7b418cfb5624e22728e296dc046bd2642 100644 (file)
@@ -177,6 +177,7 @@ static ShaderEnum image_projection_init()
        enm.insert("Flat", NODE_IMAGE_PROJ_FLAT);
        enm.insert("Box", NODE_IMAGE_PROJ_BOX);
        enm.insert("Sphere", NODE_IMAGE_PROJ_SPHERE);
+       enm.insert("Tube", NODE_IMAGE_PROJ_TUBE);
 
        return enm;
 }
index 177a72bc1c91603c45a4893c8f0d4cdce6dd1aa8..623849ea7c738298663e7d7a2f79a2e052df2bb9 100644 (file)
@@ -1450,6 +1450,20 @@ ccl_device bool ray_quad_intersect(
 }
 
 /* projections */
+ccl_device void map_to_tube(float *r_u, float *r_v,
+                            const float x, const float y, const float z)
+{
+       float len;
+       *r_v = (z + 1.0f) * 0.5f;
+       len = sqrtf(x * x + y * y);
+       if (len > 0.0f) {
+               *r_u = (1.0f - (atan2f(x / len, y / len) / (float)M_PI)) * 0.5f;
+       }
+       else {
+               *r_v = *r_u = 0.0f; /* To avoid un-initialized variables. */
+       }
+}
+
 ccl_device bool map_to_sphere(float *r_u, float *r_v,
                               const float x, const float y, const float z)
 {
index 5cd4e0d223b82b3c7809f6829ed59ea516fef044..5d1793e479aef8da412fdb6a45af270bea0f83ac 100644 (file)
@@ -963,6 +963,7 @@ typedef struct NodeSunBeams {
 #define SHD_PROJ_FLAT                          0
 #define SHD_PROJ_BOX                           1
 #define SHD_PROJ_SPHERE                                2
+#define SHD_PROJ_TUBE                          3
 
 /* image texture interpolation */
 #define SHD_INTERP_LINEAR              0
index 48e56e28f52c4f7a6b6429e72dd436e00d80c259..32a844c3fd0a16becd132d490033c8753fb17732 100644 (file)
@@ -3437,6 +3437,8 @@ static void def_sh_tex_image(StructRNA *srna)
                                  "Image is projected using different components for each side of the object space bounding box"},
                {SHD_PROJ_SPHERE, "SPHERE", 0, "Sphere",
                                  "Image is projected spherically using the Z axis as central"},
+               {SHD_PROJ_TUBE,   "TUBE", 0, "Tube",
+                                 "Image is projected from the tube using the Z axis as central"},
                {0, NULL, 0, NULL, NULL}
        };