Cycles: Added Float2 attribute type.
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Tue, 5 Mar 2019 13:54:54 +0000 (14:54 +0100)
committerStefan Werner <stefan.werner@tangent-animation.com>
Tue, 5 Mar 2019 13:55:21 +0000 (14:55 +0100)
Float2 are now a new type for attributes in Cycles. Before, the choices
for attribute storage were float and float3, the latter padded to
float4. This meant that UV maps were inflated to twice the size
necessary.

Reviewers: brecht, sergey

Reviewed By: brecht

Subscribers: #cycles

Tags: #cycles

Differential Revision: https://developer.blender.org/D4409

20 files changed:
intern/cycles/blender/blender_mesh.cpp
intern/cycles/kernel/geom/geom_curve.h
intern/cycles/kernel/geom/geom_patch.h
intern/cycles/kernel/geom/geom_primitive.h
intern/cycles/kernel/geom/geom_subd_triangle.h
intern/cycles/kernel/geom/geom_triangle.h
intern/cycles/kernel/kernel_textures.h
intern/cycles/kernel/osl/osl_services.cpp
intern/cycles/kernel/svm/svm_attribute.h
intern/cycles/kernel/svm/svm_tex_coord.h
intern/cycles/kernel/svm/svm_types.h
intern/cycles/render/attribute.cpp
intern/cycles/render/attribute.h
intern/cycles/render/mesh.cpp
intern/cycles/render/mesh_subdivision.cpp
intern/cycles/render/nodes.cpp
intern/cycles/render/scene.cpp
intern/cycles/render/scene.h
intern/cycles/util/util_math_float2.h
intern/cycles/util/util_param.h

index 8d2ade1e30b5defbcf1dccb3306620220e4e6f07..cb9d23e121c86827094c6e5ff709dc95b63f476d 100644 (file)
@@ -106,7 +106,7 @@ struct MikkUserData {
                else {
                        Attribute *attr_uv = attributes.find(ustring(layer_name));
                        if(attr_uv != NULL) {
-                               texface = attr_uv->data_float3();
+                               texface = attr_uv->data_float2();
                        }
                }
        }
@@ -115,7 +115,7 @@ struct MikkUserData {
        int num_faces;
 
        float3 *vertex_normal;
-       float3 *texface;
+       float2 *texface;
        float3 *orco;
        float3 orco_loc, orco_size;
 
@@ -190,7 +190,7 @@ static void mikk_get_texture_coordinate(const SMikkTSpaceContext *context,
        const Mesh *mesh = userdata->mesh;
        if(userdata->texface != NULL) {
                const int corner_index = mikk_corner_index(mesh, face_num, vert_num);
-               float3 tfuv = userdata->texface[corner_index];
+               float2 tfuv = userdata->texface[corner_index];
                uv[0] = tfuv.x;
                uv[1] = tfuv.y;
        }
@@ -494,19 +494,19 @@ static void attr_create_uv_map(Scene *scene,
                                }
 
                                BL::MeshTextureFaceLayer::data_iterator t;
-                               float3 *fdata = uv_attr->data_float3();
+                               float2 *fdata = uv_attr->data_float2();
                                size_t i = 0;
 
                                for(l->data.begin(t); t != l->data.end(); ++t, ++i) {
                                        int tri_a[3], tri_b[3];
                                        face_split_tri_indices(face_flags[i], tri_a, tri_b);
 
-                                       float3 uvs[4];
-                                       uvs[0] = get_float3(t->uv1());
-                                       uvs[1] = get_float3(t->uv2());
-                                       uvs[2] = get_float3(t->uv3());
+                                       float2 uvs[4];
+                                       uvs[0] = get_float2(t->uv1());
+                                       uvs[1] = get_float2(t->uv2());
+                                       uvs[2] = get_float2(t->uv3());
                                        if(nverts[i] == 4) {
-                                               uvs[3] = get_float3(t->uv4());
+                                               uvs[3] = get_float2(t->uv4());
                                        }
 
                                        fdata[0] = uvs[tri_a[0]];
@@ -593,12 +593,12 @@ static void attr_create_subd_uv_map(Scene *scene,
                                }
 
                                BL::Mesh::polygons_iterator p;
-                               float3 *fdata = uv_attr->data_float3();
+                               float2 *fdata = uv_attr->data_float2();
 
                                for(b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
                                        int n = p->loop_total();
                                        for(int j = 0; j < n; j++) {
-                                               *(fdata++) = get_float3(l->data[p->loop_start() + j].uv());
+                                               *(fdata++) = get_float2(l->data[p->loop_start() + j].uv());
                                        }
                                }
                        }
index dea0c742ed75bb6a2cb45b55fa8979ee3ddf5417..9b60cf6d56b8b3d9b97fafca47a70573d3e82aa7 100644 (file)
@@ -87,6 +87,45 @@ ccl_device float curve_attribute_float(KernelGlobals *kg, const ShaderData *sd,
        }
 }
 
+ccl_device float2 curve_attribute_float2(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float2 *dx, float2 *dy)
+{
+       if(desc.element == ATTR_ELEMENT_CURVE) {
+               /* idea: we can't derive any useful differentials here, but for tiled
+                * mipmap image caching it would be useful to avoid reading the highest
+                * detail level always. maybe a derivative based on the hair density
+                * could be computed somehow? */
+#ifdef __RAY_DIFFERENTIALS__
+               if(dx) *dx = make_float2(0.0f, 0.0f);
+               if(dy) *dy = make_float2(0.0f, 0.0f);
+#endif
+
+               return kernel_tex_fetch(__attributes_float2, desc.offset + sd->prim);
+       }
+       else if(desc.element == ATTR_ELEMENT_CURVE_KEY || desc.element == ATTR_ELEMENT_CURVE_KEY_MOTION) {
+               float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
+               int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
+               int k1 = k0 + 1;
+
+               float2 f0 = kernel_tex_fetch(__attributes_float2, desc.offset + k0);
+               float2 f1 = kernel_tex_fetch(__attributes_float2, desc.offset + k1);
+
+#ifdef __RAY_DIFFERENTIALS__
+               if(dx) *dx = sd->du.dx*(f1 - f0);
+               if(dy) *dy = make_float2(0.0f, 0.0f);
+#endif
+
+               return (1.0f - sd->u)*f0 + sd->u*f1;
+       }
+       else {
+#ifdef __RAY_DIFFERENTIALS__
+               if(dx) *dx = make_float2(0.0f, 0.0f);
+               if(dy) *dy = make_float2(0.0f, 0.0f);
+#endif
+
+               return make_float2(0.0f, 0.0f);
+       }
+}
+
 ccl_device float3 curve_attribute_float3(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float3 *dx, float3 *dy)
 {
        if(desc.element == ATTR_ELEMENT_CURVE) {
index 0143b384aa2724412aba2a4c06a5049fa1464a0a..edb821729594b28c11c2d9a8283c3e68d6bf3051 100644 (file)
@@ -284,6 +284,33 @@ ccl_device float patch_eval_float(KernelGlobals *kg, const ShaderData *sd, int o
        return val;
 }
 
+ccl_device float2 patch_eval_float2(KernelGlobals *kg, const ShaderData *sd, int offset,
+                                    int patch, float u, float v, int channel,
+                                    float2 *du, float2 *dv)
+{
+       int indices[PATCH_MAX_CONTROL_VERTS];
+       float weights[PATCH_MAX_CONTROL_VERTS];
+       float weights_du[PATCH_MAX_CONTROL_VERTS];
+       float weights_dv[PATCH_MAX_CONTROL_VERTS];
+
+       int num_control = patch_eval_control_verts(kg, sd->object, patch, u, v, channel,
+                                                  indices, weights, weights_du, weights_dv);
+
+       float2 val = make_float2(0.0f, 0.0f);
+       if(du) *du = make_float2(0.0f, 0.0f);
+       if(dv) *dv = make_float2(0.0f, 0.0f);
+
+       for(int i = 0; i < num_control; i++) {
+               float2 v = kernel_tex_fetch(__attributes_float2, offset + indices[i]);
+
+               val += v * weights[i];
+               if(du) *du += v * weights_du[i];
+               if(dv) *dv += v * weights_dv[i];
+       }
+
+       return val;
+}
+
 ccl_device float3 patch_eval_float3(KernelGlobals *kg, const ShaderData *sd, int offset,
                                     int patch, float u, float v, int channel,
                                     float3 *du, float3 *dv)
index e3e2648e9eca55f42dc5abf9df430e7b8288c464..c9b1995ee05a636014b985e5fc61607ebfabb60e 100644 (file)
@@ -89,6 +89,37 @@ ccl_device_inline float primitive_volume_attribute_float(KernelGlobals *kg,
 }
 #endif
 
+ccl_device_inline float2 primitive_attribute_float2(KernelGlobals *kg,
+                                                    const ShaderData *sd,
+                                                    const AttributeDescriptor desc,
+                                                    float2 *dx, float2 *dy)
+{
+       if(sd->type & PRIMITIVE_ALL_TRIANGLE) {
+               if(subd_triangle_patch(kg, sd) == ~0)
+                       return triangle_attribute_float2(kg, sd, desc, dx, dy);
+               else
+                       return subd_triangle_attribute_float2(kg, sd, desc, dx, dy);
+       }
+#ifdef __HAIR__
+       else if(sd->type & PRIMITIVE_ALL_CURVE) {
+               return curve_attribute_float2(kg, sd, desc, dx, dy);
+       }
+#endif
+#ifdef __VOLUME__
+       else if(sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
+               kernel_assert(0);
+               if(dx) *dx = make_float2(0.0f, 0.0f);
+               if(dy) *dy = make_float2(0.0f, 0.0f);
+               return make_float2(0.0f, 0.0f);
+       }
+#endif
+       else {
+               if(dx) *dx = make_float2(0.0f, 0.0f);
+               if(dy) *dy = make_float2(0.0f, 0.0f);
+               return make_float2(0.0f, 0.0f);
+       }
+}
+
 ccl_device_inline float3 primitive_attribute_float3(KernelGlobals *kg,
                                                     const ShaderData *sd,
                                                     const AttributeDescriptor desc,
@@ -119,6 +150,29 @@ ccl_device_inline float3 primitive_attribute_float3(KernelGlobals *kg,
        }
 }
 
+ccl_device_inline float2 primitive_surface_attribute_float2(KernelGlobals *kg,
+                                                            const ShaderData *sd,
+                                                            const AttributeDescriptor desc,
+                                                            float2 *dx, float2 *dy)
+{
+       if(sd->type & PRIMITIVE_ALL_TRIANGLE) {
+               if(subd_triangle_patch(kg, sd) == ~0)
+                       return triangle_attribute_float2(kg, sd, desc, dx, dy);
+               else
+                       return subd_triangle_attribute_float2(kg, sd, desc, dx, dy);
+       }
+#ifdef __HAIR__
+       else if(sd->type & PRIMITIVE_ALL_CURVE) {
+               return curve_attribute_float2(kg, sd, desc, dx, dy);
+       }
+#endif
+       else {
+               if(dx) *dx = make_float2(0.0f, 0.0f);
+               if(dy) *dy = make_float2(0.0f, 0.0f);
+               return make_float2(0.0f, 0.0f);
+       }
+}
+
 ccl_device_inline float3 primitive_surface_attribute_float3(KernelGlobals *kg,
                                                             const ShaderData *sd,
                                                             const AttributeDescriptor desc,
index 8c0d0a9770eb0b2d119b0b5fc321d3e1ab9d30f9..251e070c21ff31b6091687396394ac918dc9d4a2 100644 (file)
@@ -216,6 +216,128 @@ ccl_device_noinline float subd_triangle_attribute_float(KernelGlobals *kg, const
        }
 }
 
+ccl_device_noinline float2 subd_triangle_attribute_float2(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float2 *dx, float2 *dy)
+{
+       int patch = subd_triangle_patch(kg, sd);
+
+#ifdef __PATCH_EVAL__
+       if(desc.flags & ATTR_SUBDIVIDED) {
+               float2 uv[3];
+               subd_triangle_patch_uv(kg, sd, uv);
+
+               float2 dpdu = uv[0] - uv[2];
+               float2 dpdv = uv[1] - uv[2];
+
+               /* p is [s, t] */
+               float2 p = dpdu * sd->u + dpdv * sd->v + uv[2];
+
+               float2 a, dads, dadt;
+
+               a = patch_eval_float2(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt);
+
+#ifdef __RAY_DIFFERENTIALS__
+               if(dx || dy) {
+                       float dsdu = dpdu.x;
+                       float dtdu = dpdu.y;
+                       float dsdv = dpdv.x;
+                       float dtdv = dpdv.y;
+
+                       if(dx) {
+                               float dudx = sd->du.dx;
+                               float dvdx = sd->dv.dx;
+
+                               float dsdx = dsdu*dudx + dsdv*dvdx;
+                               float dtdx = dtdu*dudx + dtdv*dvdx;
+
+                               *dx = dads*dsdx + dadt*dtdx;
+                       }
+                       if(dy) {
+                               float dudy = sd->du.dy;
+                               float dvdy = sd->dv.dy;
+
+                               float dsdy = dsdu*dudy + dsdv*dvdy;
+                               float dtdy = dtdu*dudy + dtdv*dvdy;
+
+                               *dy = dads*dsdy + dadt*dtdy;
+                       }
+               }
+#endif
+
+               return a;
+       }
+       else
+#endif  /* __PATCH_EVAL__ */
+               if(desc.element == ATTR_ELEMENT_FACE) {
+                       if(dx) *dx = make_float2(0.0f, 0.0f);
+                       if(dy) *dy = make_float2(0.0f, 0.0f);
+
+                       return kernel_tex_fetch(__attributes_float2, desc.offset + subd_triangle_patch_face(kg, patch));
+               }
+               else if(desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
+                       float2 uv[3];
+                       subd_triangle_patch_uv(kg, sd, uv);
+
+                       uint4 v = subd_triangle_patch_indices(kg, patch);
+
+                       float2 f0 = kernel_tex_fetch(__attributes_float2, desc.offset + v.x);
+                       float2 f1 = kernel_tex_fetch(__attributes_float2, desc.offset + v.y);
+                       float2 f2 = kernel_tex_fetch(__attributes_float2, desc.offset + v.z);
+                       float2 f3 = kernel_tex_fetch(__attributes_float2, desc.offset + v.w);
+
+                       if(subd_triangle_patch_num_corners(kg, patch) != 4) {
+                               f1 = (f1+f0)*0.5f;
+                               f3 = (f3+f0)*0.5f;
+                       }
+
+                       float2 a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y);
+                       float2 b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y);
+                       float2 c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y);
+
+#ifdef __RAY_DIFFERENTIALS__
+                       if(dx) *dx = sd->du.dx*a + sd->dv.dx*b - (sd->du.dx + sd->dv.dx)*c;
+                       if(dy) *dy = sd->du.dy*a + sd->dv.dy*b - (sd->du.dy + sd->dv.dy)*c;
+#endif
+
+                       return sd->u*a + sd->v*b + (1.0f - sd->u - sd->v)*c;
+               }
+               else if(desc.element == ATTR_ELEMENT_CORNER) {
+                       float2 uv[3];
+                       subd_triangle_patch_uv(kg, sd, uv);
+
+                       int corners[4];
+                       subd_triangle_patch_corners(kg, patch, corners);
+
+                       float2 f0, f1, f2, f3;
+
+                       f0 = kernel_tex_fetch(__attributes_float2, corners[0] + desc.offset);
+                       f1 = kernel_tex_fetch(__attributes_float2, corners[1] + desc.offset);
+                       f2 = kernel_tex_fetch(__attributes_float2, corners[2] + desc.offset);
+                       f3 = kernel_tex_fetch(__attributes_float2, corners[3] + desc.offset);
+
+                       if(subd_triangle_patch_num_corners(kg, patch) != 4) {
+                               f1 = (f1+f0)*0.5f;
+                               f3 = (f3+f0)*0.5f;
+                       }
+
+                       float2 a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y);
+                       float2 b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y);
+                       float2 c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y);
+
+#ifdef __RAY_DIFFERENTIALS__
+                       if(dx) *dx = sd->du.dx*a + sd->dv.dx*b - (sd->du.dx + sd->dv.dx)*c;
+                       if(dy) *dy = sd->du.dy*a + sd->dv.dy*b - (sd->du.dy + sd->dv.dy)*c;
+#endif
+
+                       return sd->u*a + sd->v*b + (1.0f - sd->u - sd->v)*c;
+               }
+               else {
+                       if(dx) *dx = make_float2(0.0f, 0.0f);
+                       if(dy) *dy = make_float2(0.0f, 0.0f);
+
+                       return make_float2(0.0f, 0.0f);
+               }
+}
+
 ccl_device_noinline float3 subd_triangle_attribute_float3(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float3 *dx, float3 *dy)
 {
        int patch = subd_triangle_patch(kg, sd);
index 105aee8da15f31d3f9a9ba17acf981dbe6fce617..300227c38e658a35011b7934beb3f45396bf69c5 100644 (file)
@@ -149,6 +149,53 @@ ccl_device float triangle_attribute_float(KernelGlobals *kg, const ShaderData *s
        }
 }
 
+ccl_device float2 triangle_attribute_float2(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float2 *dx, float2 *dy)
+{
+       if(desc.element == ATTR_ELEMENT_FACE) {
+               if(dx) *dx = make_float2(0.0f, 0.0f);
+               if(dy) *dy = make_float2(0.0f, 0.0f);
+
+               return kernel_tex_fetch(__attributes_float2, desc.offset + sd->prim);
+       }
+       else if(desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
+               uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
+
+               float2 f0 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.x);
+               float2 f1 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.y);
+               float2 f2 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.z);
+
+#ifdef __RAY_DIFFERENTIALS__
+               if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
+               if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
+#endif
+
+               return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
+       }
+       else if(desc.element == ATTR_ELEMENT_CORNER) {
+               int tri = desc.offset + sd->prim*3;
+               float2 f0, f1, f2;
+
+               if(desc.element == ATTR_ELEMENT_CORNER) {
+                       f0 = kernel_tex_fetch(__attributes_float2, tri + 0);
+                       f1 = kernel_tex_fetch(__attributes_float2, tri + 1);
+                       f2 = kernel_tex_fetch(__attributes_float2, tri + 2);
+               }
+
+#ifdef __RAY_DIFFERENTIALS__
+               if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
+               if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
+#endif
+
+               return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
+       }
+       else {
+               if(dx) *dx = make_float2(0.0f, 0.0f);
+               if(dy) *dy = make_float2(0.0f, 0.0f);
+
+               return make_float2(0.0f, 0.0f);
+       }
+}
+
 ccl_device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float3 *dx, float3 *dy)
 {
        if(desc.element == ATTR_ELEMENT_FACE) {
index e83727ec64e9e4bf609c84c93a6d7feb5fef8a68..9eaa6b5516e9850f69954833974bfff28e196c2c 100644 (file)
@@ -56,6 +56,7 @@ KERNEL_TEX(uint, __patches)
 /* attributes */
 KERNEL_TEX(uint4, __attributes_map)
 KERNEL_TEX(float, __attributes_float)
+KERNEL_TEX(float2, __attributes_float2)
 KERNEL_TEX(float4, __attributes_float3)
 KERNEL_TEX(uchar4, __attributes_uchar4)
 
index 5436a66c9d463e35035b4628032941c54d26fac3..6464d382634f9366f789cd6c6e9798b3cabcc457 100644 (file)
@@ -392,6 +392,44 @@ bool OSLRenderServices::get_array_attribute(OSL::ShaderGlobals *sg, bool derivat
        return false;
 }
 
+static bool set_attribute_float2(float2 f[3], TypeDesc type, bool derivatives, void *val)
+{
+       if(type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
+          type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor)
+       {
+               float *fval = (float *)val;
+
+               fval[0] = f[0].x;
+               fval[1] = f[0].y;
+               fval[2] = 0.0f;
+
+               if(derivatives) {
+                       fval[3] = f[1].x;
+                       fval[4] = f[1].y;
+                       fval[5] = 0.0f;
+
+                       fval[6] = f[2].x;
+                       fval[7] = f[2].y;
+                       fval[8] = 0.0f;
+               }
+
+               return true;
+       }
+       else if(type == TypeDesc::TypeFloat) {
+               float *fval = (float *)val;
+               fval[0] = average(f[0]);
+
+               if(derivatives) {
+                       fval[1] = average(f[1]);
+                       fval[2] = average(f[2]);
+               }
+
+               return true;
+       }
+
+       return false;
+}
+
 static bool set_attribute_float3(float3 f[3], TypeDesc type, bool derivatives, void *val)
 {
        if(type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
@@ -572,6 +610,12 @@ static bool get_primitive_attribute(KernelGlobals *kg, const ShaderData *sd, con
                                                     (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
                return set_attribute_float3(fval, type, derivatives, val);
        }
+       else if(attr.type == TypeFloat2) {
+               float2 fval[2];
+               fval[0] = primitive_attribute_float2(kg, sd, attr.desc,
+                                                     (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
+               return set_attribute_float2(fval, type, derivatives, val);
+       }
        else if(attr.type == TypeDesc::TypeFloat) {
                float fval[3];
                fval[0] = primitive_attribute_float(kg, sd, attr.desc,
index ef6f7d7cbb5cfa5e81e20365d10ada0654e27796..c2366df71d0553a410abd67ce830e79133084724 100644 (file)
@@ -52,18 +52,27 @@ ccl_device void svm_node_attr(KernelGlobals *kg, ShaderData *sd, float *stack, u
        AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
 
        /* fetch and store attribute */
-       if (desc.type == NODE_ATTR_FLOAT) {
+       if(desc.type == NODE_ATTR_FLOAT) {
                float f = primitive_attribute_float(kg, sd, desc, NULL, NULL);
-               if (type == NODE_ATTR_FLOAT) {
+               if(type == NODE_ATTR_FLOAT) {
                        stack_store_float(stack, out_offset, f);
                }
                else {
                        stack_store_float3(stack, out_offset, make_float3(f, f, f));
                }
        }
+       else if(desc.type == NODE_ATTR_FLOAT2) {
+               float2 f = primitive_attribute_float2(kg, sd, desc, NULL, NULL);
+               if(type == NODE_ATTR_FLOAT) {
+                       stack_store_float(stack, out_offset, f.x);
+               }
+               else {
+                       stack_store_float3(stack, out_offset, make_float3(f.x, f.y, 0.0f));
+               }
+       }
        else {
                float3 f = primitive_attribute_float3(kg, sd, desc, NULL, NULL);
-               if (type == NODE_ATTR_FLOAT) {
+               if(type == NODE_ATTR_FLOAT) {
                        stack_store_float(stack, out_offset, average(f));
                }
                else {
@@ -84,20 +93,30 @@ void svm_node_attr_bump_dx(KernelGlobals *kg, ShaderData *sd, float *stack, uint
        AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
 
        /* fetch and store attribute */
-       if (desc.type == NODE_ATTR_FLOAT) {
+       if(desc.type == NODE_ATTR_FLOAT) {
                float dx;
                float f = primitive_surface_attribute_float(kg, sd, desc, &dx, NULL);
-               if (type == NODE_ATTR_FLOAT) {
+               if(type == NODE_ATTR_FLOAT) {
                        stack_store_float(stack, out_offset, f+dx);
                }
                else {
                        stack_store_float3(stack, out_offset, make_float3(f+dx, f+dx, f+dx));
                }
        }
+       else if(desc.type == NODE_ATTR_FLOAT2) {
+               float2 dx;
+               float2 f = primitive_attribute_float2(kg, sd, desc, &dx, NULL);
+               if (type == NODE_ATTR_FLOAT) {
+                       stack_store_float(stack, out_offset, f.x + dx.x);
+               }
+               else {
+                       stack_store_float3(stack, out_offset, make_float3(f.x+dx.x, f.y+dx.y, 0.0f));
+               }
+       }
        else {
                float3 dx;
                float3 f = primitive_surface_attribute_float3(kg, sd, desc, &dx, NULL);
-               if (type == NODE_ATTR_FLOAT) {
+               if(type == NODE_ATTR_FLOAT) {
                        stack_store_float(stack, out_offset, average(f+dx));
                }
                else {
@@ -121,20 +140,30 @@ void svm_node_attr_bump_dy(KernelGlobals *kg,
        AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
 
        /* fetch and store attribute */
-               if (desc.type == NODE_ATTR_FLOAT) {
+       if(desc.type == NODE_ATTR_FLOAT) {
                float dy;
                float f = primitive_surface_attribute_float(kg, sd, desc, NULL, &dy);
-               if (type == NODE_ATTR_FLOAT) {
+               if(type == NODE_ATTR_FLOAT) {
                        stack_store_float(stack, out_offset, f+dy);
                }
                else {
                        stack_store_float3(stack, out_offset, make_float3(f+dy, f+dy, f+dy));
                }
        }
+       else if(desc.type == NODE_ATTR_FLOAT2) {
+               float2 dy;
+               float2 f = primitive_attribute_float2(kg, sd, desc, NULL, &dy);
+               if(type == NODE_ATTR_FLOAT) {
+                       stack_store_float(stack, out_offset, f.x + dy.x);
+               }
+               else {
+                       stack_store_float3(stack, out_offset, make_float3(f.x+dy.x, f.y+dy.y, 0.0f));
+               }
+       }
        else {
                float3 dy;
                float3 f = primitive_surface_attribute_float3(kg, sd, desc, NULL, &dy);
-               if (type == NODE_ATTR_FLOAT) {
+               if(type == NODE_ATTR_FLOAT) {
                        stack_store_float(stack, out_offset, average(f+dy));
                }
                else {
index 72871254f0d78ba634d5ba56193ed45cc043b7d1..fe61292d0b0d45a5f5cdaf4a750a2096e26e4d9f 100644 (file)
@@ -363,7 +363,15 @@ ccl_device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack
        float3 attribute_value;
        const AttributeDescriptor desc = find_attribute(kg, sd, node.z);
        if (desc.offset != ATTR_STD_NOT_FOUND) {
-               attribute_value = primitive_surface_attribute_float3(kg, sd, desc, NULL, NULL);
+               if(desc.type == NODE_ATTR_FLOAT2) {
+                       float2 value = primitive_surface_attribute_float2(kg, sd, desc, NULL, NULL);
+                       attribute_value.x = value.x;
+                       attribute_value.y = value.y;
+                       attribute_value.z = 0.0f;
+               }
+               else {
+                       attribute_value = primitive_surface_attribute_float3(kg, sd, desc, NULL, NULL);
+               }
        }
 
 
index 0f1dfa4936b92c280aacd2efc43e838b5f06896e..8b15d7bf9f4be3c404ffef69263cea8e012287c1 100644 (file)
@@ -141,6 +141,7 @@ typedef enum ShaderNodeType {
 
 typedef enum NodeAttributeType {
        NODE_ATTR_FLOAT = 0,
+       NODE_ATTR_FLOAT2,
        NODE_ATTR_FLOAT3,
        NODE_ATTR_MATRIX
 } NodeAttributeType;
index ca167a7c7221717a7f092f202f12f3eb5c72786b..70f75a4b573e6d2a16c70a37484416b9f52648f0 100644 (file)
@@ -48,7 +48,8 @@ void Attribute::set(ustring name_, TypeDesc type_, AttributeElement element_)
        /* string and matrix not supported! */
        assert(type == TypeDesc::TypeFloat || type == TypeDesc::TypeColor ||
                type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
-               type == TypeDesc::TypeNormal || type == TypeDesc::TypeMatrix);
+               type == TypeDesc::TypeNormal || type == TypeDesc::TypeMatrix ||
+               type == TypeFloat2);
 }
 
 void Attribute::resize(Mesh *mesh, AttributePrimitive prim, bool reserve_only)
@@ -400,7 +401,7 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
                                attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_FACE);
                                break;
                        case ATTR_STD_UV:
-                               attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);
+                               attr = add(name, TypeFloat2, ATTR_ELEMENT_CORNER);
                                break;
                        case ATTR_STD_UV_TANGENT:
                                attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER);
index e7438f4513d14e69f66049699886e844839b70f3..9a92d98b713f1419cfe8aec21e80ecd1f71efb8c 100644 (file)
@@ -67,6 +67,7 @@ public:
        size_t buffer_size(Mesh *mesh, AttributePrimitive prim) const;
 
        char *data() { return (buffer.size())? &buffer[0]: NULL; };
+       float2 *data_float2() { return (float2*)data(); }
        float3 *data_float3() { return (float3*)data(); }
        float4 *data_float4() { return (float4*)data(); }
        float *data_float() { return (float*)data(); }
@@ -75,6 +76,7 @@ public:
        VoxelAttribute *data_voxel()  { return ( VoxelAttribute*)data(); }
 
        const char *data() const { return (buffer.size())? &buffer[0]: NULL; }
+       const float2 *data_float2() const { return (const float2*)data(); }
        const float3 *data_float3() const { return (const float3*)data(); }
        const float4 *data_float4() const { return (const float4*)data(); }
        const float *data_float() const { return (const float*)data(); }
@@ -85,6 +87,7 @@ public:
        void add_with_weight(void* dst, void* src, float weight);
 
        void add(const float& f);
+       void add(const float2& f);
        void add(const float3& f);
        void add(const uchar4& f);
        void add(const Transform& f);
index 5f884a3f871e19a6add55c73ad567fd60ad99969..753224de1aa9c38eb611f338f36109d12b7848b8 100644 (file)
@@ -1233,6 +1233,8 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att
                                        osl_attr.type = TypeDesc::TypeFloat;
                                else if(req.triangle_type == TypeDesc::TypeMatrix)
                                        osl_attr.type = TypeDesc::TypeMatrix;
+                               else if(req.triangle_type == TypeFloat2)
+                                       osl_attr.type = TypeFloat2;
                                else
                                        osl_attr.type = TypeDesc::TypeColor;
 
@@ -1342,6 +1344,8 @@ void MeshManager::update_svm_attributes(Device *, DeviceScene *dscene, Scene *sc
                                        attr_map[index].w = NODE_ATTR_FLOAT;
                                else if(req.triangle_type == TypeDesc::TypeMatrix)
                                        attr_map[index].w = NODE_ATTR_MATRIX;
+                               else if(req.triangle_type == TypeFloat2)
+                                       attr_map[index].w = NODE_ATTR_FLOAT2;
                                else
                                        attr_map[index].w = NODE_ATTR_FLOAT3;
 
@@ -1359,6 +1363,8 @@ void MeshManager::update_svm_attributes(Device *, DeviceScene *dscene, Scene *sc
                                        attr_map[index].w = NODE_ATTR_FLOAT;
                                else if(req.curve_type == TypeDesc::TypeMatrix)
                                        attr_map[index].w = NODE_ATTR_MATRIX;
+                               else if(req.curve_type == TypeFloat2)
+                                       attr_map[index].w = NODE_ATTR_FLOAT2;
                                else
                                        attr_map[index].w = NODE_ATTR_FLOAT3;
 
@@ -1376,6 +1382,8 @@ void MeshManager::update_svm_attributes(Device *, DeviceScene *dscene, Scene *sc
                                        attr_map[index].w = NODE_ATTR_FLOAT;
                                else if(req.subd_type == TypeDesc::TypeMatrix)
                                        attr_map[index].w = NODE_ATTR_MATRIX;
+                               else if(req.subd_type == TypeFloat2)
+                                       attr_map[index].w = NODE_ATTR_FLOAT2;
                                else
                                        attr_map[index].w = NODE_ATTR_FLOAT3;
 
@@ -1404,6 +1412,7 @@ static void update_attribute_element_size(Mesh *mesh,
                                           Attribute *mattr,
                                           AttributePrimitive prim,
                                           size_t *attr_float_size,
+                                                                                 size_t *attr_float2_size,
                                           size_t *attr_float3_size,
                                           size_t *attr_uchar4_size)
 {
@@ -1419,6 +1428,9 @@ static void update_attribute_element_size(Mesh *mesh,
                else if(mattr->type == TypeDesc::TypeFloat) {
                        *attr_float_size += size;
                }
+               else if(mattr->type == TypeFloat2) {
+                       *attr_float2_size += size;
+               }
                else if(mattr->type == TypeDesc::TypeMatrix) {
                        *attr_float3_size += size * 4;
                }
@@ -1431,6 +1443,8 @@ static void update_attribute_element_size(Mesh *mesh,
 static void update_attribute_element_offset(Mesh *mesh,
                                             device_vector<float>& attr_float,
                                             size_t& attr_float_offset,
+                                                                                       device_vector<float2>& attr_float2,
+                                                                                       size_t& attr_float2_offset,
                                             device_vector<float4>& attr_float3,
                                             size_t& attr_float3_offset,
                                             device_vector<uchar4>& attr_uchar4,
@@ -1477,6 +1491,16 @@ static void update_attribute_element_offset(Mesh *mesh,
                        }
                        attr_float_offset += size;
                }
+               else if(mattr->type == TypeFloat2) {
+                       float2 *data = mattr->data_float2();
+                       offset = attr_float2_offset;
+
+                       assert(attr_float2.size() >= offset + size);
+                       for(size_t k = 0; k < size; k++) {
+                               attr_float2[offset+k] = data[k];
+                       }
+                       attr_float2_offset += size;
+               }
                else if(mattr->type == TypeDesc::TypeMatrix) {
                        Transform *tfm = mattr->data_transform();
                        offset = attr_float3_offset;
@@ -1561,6 +1585,7 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
         * take 2x of overall attribute memory usage.
         */
        size_t attr_float_size = 0;
+       size_t attr_float2_size = 0;
        size_t attr_float3_size = 0;
        size_t attr_uchar4_size = 0;
        for(size_t i = 0; i < scene->meshes.size(); i++) {
@@ -1575,28 +1600,33 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
                                                      triangle_mattr,
                                                      ATTR_PRIM_TRIANGLE,
                                                      &attr_float_size,
+                                                                                 &attr_float2_size,
                                                      &attr_float3_size,
                                                      &attr_uchar4_size);
                        update_attribute_element_size(mesh,
                                                      curve_mattr,
                                                      ATTR_PRIM_CURVE,
                                                      &attr_float_size,
+                                                                                 &attr_float2_size,
                                                      &attr_float3_size,
                                                      &attr_uchar4_size);
                        update_attribute_element_size(mesh,
                                                      subd_mattr,
                                                      ATTR_PRIM_SUBD,
                                                      &attr_float_size,
+                                                                                 &attr_float2_size,
                                                      &attr_float3_size,
                                                      &attr_uchar4_size);
                }
        }
 
        dscene->attributes_float.alloc(attr_float_size);
+       dscene->attributes_float2.alloc(attr_float2_size);
        dscene->attributes_float3.alloc(attr_float3_size);
        dscene->attributes_uchar4.alloc(attr_uchar4_size);
 
        size_t attr_float_offset = 0;
+       size_t attr_float2_offset = 0;
        size_t attr_float3_offset = 0;
        size_t attr_uchar4_offset = 0;
 
@@ -1614,6 +1644,7 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
 
                        update_attribute_element_offset(mesh,
                                                        dscene->attributes_float, attr_float_offset,
+                                                                                       dscene->attributes_float2, attr_float2_offset,
                                                        dscene->attributes_float3, attr_float3_offset,
                                                        dscene->attributes_uchar4, attr_uchar4_offset,
                                                        triangle_mattr,
@@ -1623,6 +1654,7 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
 
                        update_attribute_element_offset(mesh,
                                                        dscene->attributes_float, attr_float_offset,
+                                                                                       dscene->attributes_float2, attr_float2_offset,
                                                        dscene->attributes_float3, attr_float3_offset,
                                                        dscene->attributes_uchar4, attr_uchar4_offset,
                                                        curve_mattr,
@@ -1632,6 +1664,7 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
 
                        update_attribute_element_offset(mesh,
                                                        dscene->attributes_float, attr_float_offset,
+                                                                                       dscene->attributes_float2, attr_float2_offset,
                                                        dscene->attributes_float3, attr_float3_offset,
                                                        dscene->attributes_uchar4, attr_uchar4_offset,
                                                        subd_mattr,
@@ -1657,6 +1690,9 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
        if(dscene->attributes_float.size()) {
                dscene->attributes_float.copy_to_device();
        }
+       if(dscene->attributes_float2.size()) {
+               dscene->attributes_float2.copy_to_device();
+       }
        if(dscene->attributes_float3.size()) {
                dscene->attributes_float3.copy_to_device();
        }
@@ -2289,6 +2325,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
        dscene->patches.free();
        dscene->attributes_map.free();
        dscene->attributes_float.free();
+       dscene->attributes_float2.free();
        dscene->attributes_float3.free();
        dscene->attributes_uchar4.free();
 
index 13fda99e9cca00411299fa38c4744755187e10e9..95cc6f1fca15da1841c078c0be54690d2159d4b7 100644 (file)
@@ -231,6 +231,9 @@ public:
                                if(attr.same_storage(attr.type, TypeDesc::TypeFloat)) {
                                        primvar_refiner.Interpolate(i+1, (OsdValue<float>*)src, (OsdValue<float>*&)dest);
                                }
+                               else if(attr.same_storage(attr.type, TypeFloat2)) {
+                                       primvar_refiner.Interpolate(i+1, (OsdValue<float2>*)src, (OsdValue<float2>*&)dest);
+                               }
                                else {
                                        primvar_refiner.Interpolate(i+1, (OsdValue<float4>*)src, (OsdValue<float4>*&)dest);
                                }
@@ -243,6 +246,10 @@ public:
                                        patch_table->ComputeLocalPointValues((OsdValue<float>*)&attr.buffer[0],
                                                                                     (OsdValue<float>*)&attr.buffer[num_refiner_verts * attr.data_sizeof()]);
                                }
+                               else if(attr.same_storage(attr.type, TypeFloat2)) {
+                                       patch_table->ComputeLocalPointValues((OsdValue<float2>*)&attr.buffer[0],
+                                                                                                                (OsdValue<float2>*)&attr.buffer[num_refiner_verts * attr.data_sizeof()]);
+                               }
                                else {
                                        patch_table->ComputeLocalPointValues((OsdValue<float4>*)&attr.buffer[0],
                                                                                     (OsdValue<float4>*)&attr.buffer[num_refiner_verts * attr.data_sizeof()]);
index d32b1513e42402743fccccb430730685355bf860..dc015b871e5da6cb77d311f7b5ef5838ecf8a53f 100644 (file)
@@ -3483,7 +3483,7 @@ void TextureCoordinateNode::compile(SVMCompiler& compiler)
                }
                else {
                        int attr = compiler.attribute(ATTR_STD_UV);
-                       compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT3);
+                       compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT2);
                }
        }
 
index c96a1b785376cee10d2217a24da36b4f07161c88..59c4f5fccb86154ee483576e22e6082e060b7e5f 100644 (file)
@@ -66,6 +66,7 @@ DeviceScene::DeviceScene(Device *device)
   camera_motion(device, "__camera_motion", MEM_TEXTURE),
   attributes_map(device, "__attributes_map", MEM_TEXTURE),
   attributes_float(device, "__attributes_float", MEM_TEXTURE),
+  attributes_float2(device, "__attributes_float2", MEM_TEXTURE),
   attributes_float3(device, "__attributes_float3", MEM_TEXTURE),
   attributes_uchar4(device, "__attributes_uchar4", MEM_TEXTURE),
   light_distribution(device, "__light_distribution", MEM_TEXTURE),
index 57ea1d471e8598574afb0410d146073df037ce93..22b2a61743d2f7ce259c355a087c92c6021277c8 100644 (file)
@@ -98,6 +98,7 @@ public:
        /* attributes */
        device_vector<uint4> attributes_map;
        device_vector<float> attributes_float;
+       device_vector<float2> attributes_float2;
        device_vector<float4> attributes_float3;
        device_vector<uchar4> attributes_uchar4;
 
index e937509367f0c45459307f7e2e9decde9203d74f..6fe8e3b4115759fe1fb9a451f00ab5e9d8459874 100644 (file)
@@ -220,6 +220,12 @@ ccl_device_inline float2 interp(const float2& a, const float2& b, float t)
 {
        return a + t*(b - a);
 }
+
+ccl_device_inline float2 mix(const float2& a, const float2& b, float t)
+{
+       return a + t*(b - a);
+}
+
 #endif  /* !__KERNEL_OPENCL__ */
 
 CCL_NAMESPACE_END
index 4453c66aae2ec628f34540203714a992892354a9..0381548642958479b5b866328c15b2129f68b050 100644 (file)
@@ -28,6 +28,8 @@ CCL_NAMESPACE_BEGIN
 
 OIIO_NAMESPACE_USING
 
+static constexpr TypeDesc TypeFloat2(TypeDesc::FLOAT, TypeDesc::VEC2);
+
 CCL_NAMESPACE_END
 
 #endif  /* __UTIL_PARAM_H__ */