diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 551866f7fce..30417e85441 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -335,7 +335,7 @@ static void attr_create_vertex_color(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, continue; Attribute *attr = mesh->subd_attributes.add( - ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE); + ustring(l->name().c_str()), TypeRGBA, ATTR_ELEMENT_CORNER_BYTE); BL::Mesh::polygons_iterator p; uchar4 *cdata = attr->data_uchar4(); @@ -343,9 +343,9 @@ static void attr_create_vertex_color(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, for (b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) { int n = p->loop_total(); for (int i = 0; i < n; i++) { - float3 color = get_float3(l->data[p->loop_start() + i].color()); + float4 color = get_float4(l->data[p->loop_start() + i].color()); /* Compress/encode vertex color using the sRGB curve. */ - *(cdata++) = color_float_to_byte(color_srgb_to_linear_v3(color)); + *(cdata++) = color_float4_to_uchar4(color_srgb_to_linear_v4(color)); } } } @@ -357,21 +357,21 @@ static void attr_create_vertex_color(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, continue; Attribute *attr = mesh->attributes.add( - ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE); + ustring(l->name().c_str()), TypeRGBA, ATTR_ELEMENT_CORNER_BYTE); BL::Mesh::loop_triangles_iterator t; uchar4 *cdata = attr->data_uchar4(); for (b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) { int3 li = get_int3(t->loops()); - float3 c1 = get_float3(l->data[li[0]].color()); - float3 c2 = get_float3(l->data[li[1]].color()); - float3 c3 = get_float3(l->data[li[2]].color()); + float4 c1 = get_float4(l->data[li[0]].color()); + float4 c2 = get_float4(l->data[li[1]].color()); + float4 c3 = get_float4(l->data[li[2]].color()); /* Compress/encode vertex color using the sRGB curve. */ - cdata[0] = color_float_to_byte(color_srgb_to_linear_v3(c1)); - cdata[1] = color_float_to_byte(color_srgb_to_linear_v3(c2)); - cdata[2] = color_float_to_byte(color_srgb_to_linear_v3(c3)); + cdata[0] = color_float4_to_uchar4(color_srgb_to_linear_v4(c1)); + cdata[1] = color_float4_to_uchar4(color_srgb_to_linear_v4(c2)); + cdata[2] = color_float4_to_uchar4(color_srgb_to_linear_v4(c3)); cdata += 3; } } diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 257c799a3e0..362155f22ac 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -590,6 +590,12 @@ static ShaderNode *add_node(Scene *scene, else if (b_node.is_a(&RNA_ShaderNodeVolumeInfo)) { node = new VolumeInfoNode(); } + else if (b_node.is_a(&RNA_ShaderNodeVertexColor)) { + BL::ShaderNodeVertexColor b_vertex_color_node(b_node); + VertexColorNode *vertex_color_node = new VertexColorNode(); + vertex_color_node->layer_name = b_vertex_color_node.layer_name(); + node = vertex_color_node; + } else if (b_node.is_a(&RNA_ShaderNodeBump)) { BL::ShaderNodeBump b_bump_node(b_node); BumpNode *bump = new BumpNode(); diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 04df49aa058..41e57bb3e43 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -223,6 +223,7 @@ set(SRC_SVM_HEADERS svm/svm_voxel.h svm/svm_wave.h svm/svm_white_noise.h + svm/svm_vertex_color.h ) set(SRC_GEOM_HEADERS diff --git a/intern/cycles/kernel/geom/geom_patch.h b/intern/cycles/kernel/geom/geom_patch.h index df19199f68e..8b4b91b96c8 100644 --- a/intern/cycles/kernel/geom/geom_patch.h +++ b/intern/cycles/kernel/geom/geom_patch.h @@ -380,15 +380,15 @@ ccl_device float3 patch_eval_float3(KernelGlobals *kg, return val; } -ccl_device float3 patch_eval_uchar4(KernelGlobals *kg, +ccl_device float4 patch_eval_uchar4(KernelGlobals *kg, const ShaderData *sd, int offset, int patch, float u, float v, int channel, - float3 *du, - float3 *dv) + float4 *du, + float4 *dv) { int indices[PATCH_MAX_CONTROL_VERTS]; float weights[PATCH_MAX_CONTROL_VERTS]; @@ -398,14 +398,14 @@ ccl_device float3 patch_eval_uchar4(KernelGlobals *kg, int num_control = patch_eval_control_verts( kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv); - float3 val = make_float3(0.0f, 0.0f, 0.0f); + float4 val = make_float4(0.0f, 0.0f, 0.0f, 0.0f); if (du) - *du = make_float3(0.0f, 0.0f, 0.0f); + *du = make_float4(0.0f, 0.0f, 0.0f, 0.0f); if (dv) - *dv = make_float3(0.0f, 0.0f, 0.0f); + *dv = make_float4(0.0f, 0.0f, 0.0f, 0.0f); for (int i = 0; i < num_control; i++) { - float3 v = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, offset + indices[i])); + float4 v = color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, offset + indices[i])); val += v * weights[i]; if (du) diff --git a/intern/cycles/kernel/geom/geom_primitive.h b/intern/cycles/kernel/geom/geom_primitive.h index 7f2b52a24c4..9a91da79f58 100644 --- a/intern/cycles/kernel/geom/geom_primitive.h +++ b/intern/cycles/kernel/geom/geom_primitive.h @@ -162,6 +162,27 @@ ccl_device_inline float3 primitive_attribute_float3(KernelGlobals *kg, } } +ccl_device_inline float4 primitive_attribute_float4(KernelGlobals *kg, + const ShaderData *sd, + const AttributeDescriptor desc, + float4 *dx, + float4 *dy) +{ + if (sd->type & PRIMITIVE_ALL_TRIANGLE) { + if (subd_triangle_patch(kg, sd) == ~0) + return triangle_attribute_float4(kg, sd, desc, dx, dy); + else + return subd_triangle_attribute_float4(kg, sd, desc, dx, dy); + } + else { + if (dx) + *dx = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + if (dy) + *dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + return make_float4(0.0f, 0.0f, 0.0f, 0.0f); + } +} + ccl_device_inline float2 primitive_surface_attribute_float2(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, diff --git a/intern/cycles/kernel/geom/geom_subd_triangle.h b/intern/cycles/kernel/geom/geom_subd_triangle.h index 8d5b3c12833..81bac6e6ee1 100644 --- a/intern/cycles/kernel/geom/geom_subd_triangle.h +++ b/intern/cycles/kernel/geom/geom_subd_triangle.h @@ -382,13 +382,7 @@ ccl_device_noinline float3 subd_triangle_attribute_float3(KernelGlobals *kg, float2 p = dpdu * sd->u + dpdv * sd->v + uv[2]; float3 a, dads, dadt; - - if (desc.element == ATTR_ELEMENT_CORNER_BYTE) { - a = patch_eval_uchar4(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt); - } - else { - a = patch_eval_float3(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt); - } + a = patch_eval_float3(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt); # ifdef __RAY_DIFFERENTIALS__ if (dx || dy) { @@ -460,7 +454,7 @@ ccl_device_noinline float3 subd_triangle_attribute_float3(KernelGlobals *kg, return sd->u * a + sd->v * b + (1.0f - sd->u - sd->v) * c; } - else if (desc.element == ATTR_ELEMENT_CORNER || desc.element == ATTR_ELEMENT_CORNER_BYTE) { + else if (desc.element == ATTR_ELEMENT_CORNER) { float2 uv[3]; subd_triangle_patch_uv(kg, sd, uv); @@ -469,18 +463,10 @@ ccl_device_noinline float3 subd_triangle_attribute_float3(KernelGlobals *kg, float3 f0, f1, f2, f3; - if (desc.element == ATTR_ELEMENT_CORNER) { - f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[0] + desc.offset)); - f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[1] + desc.offset)); - f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[2] + desc.offset)); - f3 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[3] + desc.offset)); - } - else { - f0 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[0] + desc.offset)); - f1 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[1] + desc.offset)); - f2 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[2] + desc.offset)); - f3 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[3] + desc.offset)); - } + f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[0] + desc.offset)); + f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[1] + desc.offset)); + f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[2] + desc.offset)); + f3 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[3] + desc.offset)); if (subd_triangle_patch_num_corners(kg, patch) != 4) { f1 = (f1 + f0) * 0.5f; @@ -510,4 +496,102 @@ ccl_device_noinline float3 subd_triangle_attribute_float3(KernelGlobals *kg, } } +ccl_device_noinline float4 subd_triangle_attribute_float4(KernelGlobals *kg, + const ShaderData *sd, + const AttributeDescriptor desc, + float4 *dx, + float4 *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]; + + float4 dads, dadt; + + float4 a = patch_eval_uchar4(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_CORNER_BYTE) { + float2 uv[3]; + subd_triangle_patch_uv(kg, sd, uv); + + int corners[4]; + subd_triangle_patch_corners(kg, patch, corners); + + float4 f0 = color_uchar4_to_float4( + kernel_tex_fetch(__attributes_uchar4, corners[0] + desc.offset)); + float4 f1 = color_uchar4_to_float4( + kernel_tex_fetch(__attributes_uchar4, corners[1] + desc.offset)); + float4 f2 = color_uchar4_to_float4( + kernel_tex_fetch(__attributes_uchar4, corners[2] + desc.offset)); + float4 f3 = color_uchar4_to_float4( + kernel_tex_fetch(__attributes_uchar4, corners[3] + desc.offset)); + + if (subd_triangle_patch_num_corners(kg, patch) != 4) { + f1 = (f1 + f0) * 0.5f; + f3 = (f3 + f0) * 0.5f; + } + + float4 a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y); + float4 b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y); + float4 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_float4(0.0f, 0.0f, 0.0f, 0.0f); + if (dy) + *dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + + return make_float4(0.0f, 0.0f, 0.0f, 0.0f); + } +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/geom/geom_triangle.h b/intern/cycles/kernel/geom/geom_triangle.h index 9938c0ba2c3..fdb7f655f64 100644 --- a/intern/cycles/kernel/geom/geom_triangle.h +++ b/intern/cycles/kernel/geom/geom_triangle.h @@ -255,20 +255,13 @@ ccl_device float3 triangle_attribute_float3(KernelGlobals *kg, return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2; } - else if (desc.element == ATTR_ELEMENT_CORNER || desc.element == ATTR_ELEMENT_CORNER_BYTE) { + else if (desc.element == ATTR_ELEMENT_CORNER) { int tri = desc.offset + sd->prim * 3; float3 f0, f1, f2; - if (desc.element == ATTR_ELEMENT_CORNER) { - f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0)); - f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1)); - f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2)); - } - else { - f0 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, tri + 0)); - f1 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, tri + 1)); - f2 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, tri + 2)); - } + f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0)); + f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1)); + f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2)); #ifdef __RAY_DIFFERENTIALS__ if (dx) @@ -289,4 +282,36 @@ ccl_device float3 triangle_attribute_float3(KernelGlobals *kg, } } +ccl_device float4 triangle_attribute_float4(KernelGlobals *kg, + const ShaderData *sd, + const AttributeDescriptor desc, + float4 *dx, + float4 *dy) +{ + if (desc.element == ATTR_ELEMENT_CORNER_BYTE) { + int tri = desc.offset + sd->prim * 3; + + float4 f0 = color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, tri + 0)); + float4 f1 = color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, tri + 1)); + float4 f2 = color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, 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_float4(0.0f, 0.0f, 0.0f, 0.0f); + if (dy) + *dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + + return make_float4(0.0f, 0.0f, 0.0f, 0.0f); + } +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index 415de9cd66b..2698ed59e64 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -483,6 +483,65 @@ static bool set_attribute_float3(float3 f, TypeDesc type, bool derivatives, void return set_attribute_float3(fv, type, derivatives, val); } +/* Attributes with the TypeRGBA type descriptor should be retrived and stored + * in a float array of size 4 (e.g. node_vertex_color.osl), this array have + * a type descriptor TypeFloatArray4. If the storage is not a TypeFloatArray4, + * we either store the first three components in a vector, store the average of + * the components in a float, or fail the retrival and do nothing. We allow + * this for the correct operation of the Attribute node. + */ + +static bool set_attribute_float4(float4 f[3], TypeDesc type, bool derivatives, void *val) +{ + float *fval = (float *)val; + if (type == TypeFloatArray4) { + fval[0] = f[0].x; + fval[1] = f[0].y; + fval[2] = f[0].z; + fval[3] = f[0].w; + + if (derivatives) { + fval[4] = f[1].x; + fval[5] = f[1].y; + fval[6] = f[1].z; + fval[7] = f[1].w; + + fval[8] = f[2].x; + fval[9] = f[2].y; + fval[10] = f[2].z; + fval[11] = f[2].w; + } + return true; + } + else if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || + type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) { + fval[0] = f[0].x; + fval[1] = f[0].y; + fval[2] = f[0].z; + + if (derivatives) { + fval[3] = f[1].x; + fval[4] = f[1].y; + fval[5] = f[1].z; + + fval[6] = f[2].x; + fval[7] = f[2].y; + fval[8] = f[2].z; + } + return true; + } + else if (type == TypeDesc::TypeFloat) { + fval[0] = average(float4_to_float3(f[0])); + + if (derivatives) { + fval[1] = average(float4_to_float3(f[1])); + fval[2] = average(float4_to_float3(f[2])); + } + return true; + } + return false; +} + static bool set_attribute_float(float f[3], TypeDesc type, bool derivatives, void *val) { if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || @@ -629,6 +688,12 @@ static bool get_primitive_attribute(KernelGlobals *kg, kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); return set_attribute_float(fval, type, derivatives, val); } + else if (attr.type == TypeRGBA) { + float4 fval[3]; + fval[0] = primitive_attribute_float4( + kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); + return set_attribute_float4(fval, type, derivatives, val); + } else { return false; } diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt index 38ba113a184..f4258da70d3 100644 --- a/intern/cycles/kernel/shaders/CMakeLists.txt +++ b/intern/cycles/kernel/shaders/CMakeLists.txt @@ -80,6 +80,7 @@ set(SRC_OSL node_vector_math.osl node_vector_transform.osl node_velvet_bsdf.osl + node_vertex_color.osl node_voronoi_texture.osl node_voxel_texture.osl node_wavelength.osl diff --git a/intern/cycles/kernel/shaders/node_vertex_color.osl b/intern/cycles/kernel/shaders/node_vertex_color.osl new file mode 100644 index 00000000000..1997a690181 --- /dev/null +++ b/intern/cycles/kernel/shaders/node_vertex_color.osl @@ -0,0 +1,40 @@ +/* + * Copyright 2011-2013 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "stdosl.h" + +shader node_vertex_color(string bump_offset = "center", + string layer_name = "", + output color Color = 0.0, + output float Alpha = 0.0) +{ + float vertex_color[4]; + if (getattribute(layer_name, vertex_color)) { + Color = color(vertex_color[0], vertex_color[1], vertex_color[2]); + Alpha = vertex_color[3]; + + if (bump_offset == "dx") { + Color += Dx(Color); + Alpha += Dx(Alpha); + } + else if (bump_offset == "dy") { + Color += Dy(Color); + Alpha += Dy(Alpha); + } + } else { + warning("%s", "Invalid attribute."); + } +} diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index 8de66a04963..4fc5e633e3b 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -205,6 +205,7 @@ CCL_NAMESPACE_END #include "kernel/svm/svm_map_range.h" #include "kernel/svm/svm_clamp.h" #include "kernel/svm/svm_white_noise.h" +#include "kernel/svm/svm_vertex_color.h" #ifdef __SHADER_RAYTRACE__ # include "kernel/svm/svm_ao.h" @@ -289,6 +290,9 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, case NODE_ATTR: svm_node_attr(kg, sd, stack, node); break; + case NODE_VERTEX_COLOR: + svm_node_vertex_color(kg, sd, stack, node.y, node.z, node.w); + break; # if NODES_FEATURE(NODE_FEATURE_BUMP) case NODE_GEOMETRY_BUMP_DX: svm_node_geometry_bump_dx(kg, sd, stack, node.y, node.z); @@ -328,6 +332,12 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, case NODE_ATTR_BUMP_DY: svm_node_attr_bump_dy(kg, sd, stack, node); break; + case NODE_VERTEX_COLOR_BUMP_DX: + svm_node_vertex_color_bump_dx(kg, sd, stack, node.y, node.z, node.w); + break; + case NODE_VERTEX_COLOR_BUMP_DY: + svm_node_vertex_color_bump_dy(kg, sd, stack, node.y, node.z, node.w); + break; case NODE_TEX_COORD_BUMP_DX: svm_node_tex_coord_bump_dx(kg, sd, path_flag, stack, node, &offset); break; diff --git a/intern/cycles/kernel/svm/svm_attribute.h b/intern/cycles/kernel/svm/svm_attribute.h index eaee0f9e4ee..fc7a3ba3f5a 100644 --- a/intern/cycles/kernel/svm/svm_attribute.h +++ b/intern/cycles/kernel/svm/svm_attribute.h @@ -69,6 +69,15 @@ ccl_device void svm_node_attr(KernelGlobals *kg, ShaderData *sd, float *stack, u stack_store_float3(stack, out_offset, make_float3(f.x, f.y, 0.0f)); } } + else if (desc.type == NODE_ATTR_RGBA) { + float4 f = primitive_attribute_float4(kg, sd, desc, NULL, NULL); + if (type == NODE_ATTR_FLOAT) { + stack_store_float(stack, out_offset, average(float4_to_float3(f))); + } + else { + stack_store_float3(stack, out_offset, float4_to_float3(f)); + } + } else { float3 f = primitive_attribute_float3(kg, sd, desc, NULL, NULL); if (type == NODE_ATTR_FLOAT) { @@ -107,6 +116,16 @@ ccl_device void svm_node_attr_bump_dx(KernelGlobals *kg, ShaderData *sd, float * stack_store_float3(stack, out_offset, make_float3(f.x + dx.x, f.y + dx.y, 0.0f)); } } + else if (desc.type == NODE_ATTR_RGBA) { + float4 dx; + float4 f = primitive_attribute_float4(kg, sd, desc, &dx, NULL); + if (type == NODE_ATTR_FLOAT) { + stack_store_float(stack, out_offset, average(float4_to_float3(f + dx))); + } + else { + stack_store_float3(stack, out_offset, float4_to_float3(f + dx)); + } + } else { float3 dx; float3 f = primitive_surface_attribute_float3(kg, sd, desc, &dx, NULL); @@ -146,6 +165,16 @@ ccl_device void svm_node_attr_bump_dy(KernelGlobals *kg, ShaderData *sd, float * stack_store_float3(stack, out_offset, make_float3(f.x + dy.x, f.y + dy.y, 0.0f)); } } + else if (desc.type == NODE_ATTR_RGBA) { + float4 dy; + float4 f = primitive_attribute_float4(kg, sd, desc, NULL, &dy); + if (type == NODE_ATTR_FLOAT) { + stack_store_float(stack, out_offset, average(float4_to_float3(f + dy))); + } + else { + stack_store_float3(stack, out_offset, float4_to_float3(f + dy)); + } + } else { float3 dy; float3 f = primitive_surface_attribute_float3(kg, sd, desc, NULL, &dy); diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 65e2dacedae..a6f2327dada 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -142,12 +142,16 @@ typedef enum ShaderNodeType { NODE_CLAMP, NODE_TEXTURE_MAPPING, NODE_TEX_WHITE_NOISE, + NODE_VERTEX_COLOR, + NODE_VERTEX_COLOR_BUMP_DX, + NODE_VERTEX_COLOR_BUMP_DY, } ShaderNodeType; typedef enum NodeAttributeType { NODE_ATTR_FLOAT = 0, NODE_ATTR_FLOAT2, NODE_ATTR_FLOAT3, + NODE_ATTR_RGBA, NODE_ATTR_MATRIX } NodeAttributeType; diff --git a/intern/cycles/kernel/svm/svm_vertex_color.h b/intern/cycles/kernel/svm/svm_vertex_color.h new file mode 100644 index 00000000000..3c105b1cbfa --- /dev/null +++ b/intern/cycles/kernel/svm/svm_vertex_color.h @@ -0,0 +1,92 @@ +/* + * Copyright 2011-2013 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +CCL_NAMESPACE_BEGIN + +ccl_device void svm_node_vertex_color(KernelGlobals *kg, + ShaderData *sd, + float *stack, + uint layer_id, + uint color_offset, + uint alpha_offset) +{ + AttributeDescriptor descriptor = find_attribute(kg, sd, layer_id); + if (descriptor.offset != ATTR_STD_NOT_FOUND) { + float4 vertex_color = primitive_attribute_float4(kg, sd, descriptor, NULL, NULL); + stack_store_float3(stack, color_offset, float4_to_float3(vertex_color)); + stack_store_float(stack, alpha_offset, vertex_color.w); + } + else { + stack_store_float3(stack, color_offset, make_float3(0.0f, 0.0f, 0.0f)); + stack_store_float(stack, alpha_offset, 0.0f); + } +} + +#ifndef __KERNEL_CUDA__ +ccl_device +#else +ccl_device_noinline +#endif + void + svm_node_vertex_color_bump_dx(KernelGlobals *kg, + ShaderData *sd, + float *stack, + uint layer_id, + uint color_offset, + uint alpha_offset) +{ + AttributeDescriptor descriptor = find_attribute(kg, sd, layer_id); + if (descriptor.offset != ATTR_STD_NOT_FOUND) { + float4 dx; + float4 vertex_color = primitive_attribute_float4(kg, sd, descriptor, &dx, NULL); + vertex_color += dx; + stack_store_float3(stack, color_offset, float4_to_float3(vertex_color)); + stack_store_float(stack, alpha_offset, vertex_color.w); + } + else { + stack_store_float3(stack, color_offset, make_float3(0.0f, 0.0f, 0.0f)); + stack_store_float(stack, alpha_offset, 0.0f); + } +} + +#ifndef __KERNEL_CUDA__ +ccl_device +#else +ccl_device_noinline +#endif + void + svm_node_vertex_color_bump_dy(KernelGlobals *kg, + ShaderData *sd, + float *stack, + uint layer_id, + uint color_offset, + uint alpha_offset) +{ + AttributeDescriptor descriptor = find_attribute(kg, sd, layer_id); + if (descriptor.offset != ATTR_STD_NOT_FOUND) { + float4 dy; + float4 vertex_color = primitive_attribute_float4(kg, sd, descriptor, NULL, &dy); + vertex_color += dy; + stack_store_float3(stack, color_offset, float4_to_float3(vertex_color)); + stack_store_float(stack, alpha_offset, vertex_color.w); + } + else { + stack_store_float3(stack, color_offset, make_float3(0.0f, 0.0f, 0.0f)); + stack_store_float(stack, alpha_offset, 0.0f); + } +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index f1341d50b9d..0fa1142f354 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -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 == TypeFloat2); + type == TypeDesc::TypeNormal || type == TypeDesc::TypeMatrix || type == TypeFloat2 || + type == TypeRGBA); } void Attribute::resize(Mesh *mesh, AttributePrimitive prim, bool reserve_only) diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 3d2cc98d38b..9be078b6fca 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -1223,6 +1223,8 @@ void MeshManager::update_osl_attributes(Device *device, osl_attr.type = TypeDesc::TypeMatrix; else if (req.triangle_type == TypeFloat2) osl_attr.type = TypeFloat2; + else if (req.triangle_type == TypeRGBA) + osl_attr.type = TypeRGBA; else osl_attr.type = TypeDesc::TypeColor; @@ -1246,6 +1248,8 @@ void MeshManager::update_osl_attributes(Device *device, osl_attr.type = TypeDesc::TypeMatrix; else if (req.curve_type == TypeFloat2) osl_attr.type = TypeFloat2; + else if (req.curve_type == TypeRGBA) + osl_attr.type = TypeRGBA; else osl_attr.type = TypeDesc::TypeColor; @@ -1269,6 +1273,8 @@ void MeshManager::update_osl_attributes(Device *device, osl_attr.type = TypeDesc::TypeMatrix; else if (req.subd_type == TypeFloat2) osl_attr.type = TypeFloat2; + else if (req.subd_type == TypeRGBA) + osl_attr.type = TypeRGBA; else osl_attr.type = TypeDesc::TypeColor; @@ -1341,6 +1347,8 @@ void MeshManager::update_svm_attributes(Device *, attr_map[index].w = NODE_ATTR_MATRIX; else if (req.triangle_type == TypeFloat2) attr_map[index].w = NODE_ATTR_FLOAT2; + else if (req.triangle_type == TypeRGBA) + attr_map[index].w = NODE_ATTR_RGBA; else attr_map[index].w = NODE_ATTR_FLOAT3; @@ -1379,6 +1387,8 @@ void MeshManager::update_svm_attributes(Device *, attr_map[index].w = NODE_ATTR_MATRIX; else if (req.subd_type == TypeFloat2) attr_map[index].w = NODE_ATTR_FLOAT2; + else if (req.triangle_type == TypeRGBA) + attr_map[index].w = NODE_ATTR_RGBA; else attr_map[index].w = NODE_ATTR_FLOAT3; diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 1d98fabbc9f..71f1863ea49 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -4342,6 +4342,64 @@ void VolumeInfoNode::compile(OSLCompiler &) { } +NODE_DEFINE(VertexColorNode) +{ + NodeType *type = NodeType::add("vertex_color", create, NodeType::SHADER); + + SOCKET_STRING(layer_name, "Layer Name", ustring()); + SOCKET_OUT_COLOR(color, "Color"); + SOCKET_OUT_FLOAT(alpha, "Alpha"); + + return type; +} + +VertexColorNode::VertexColorNode() : ShaderNode(node_type) +{ +} + +void VertexColorNode::attributes(Shader *shader, AttributeRequestSet *attributes) +{ + if (!(output("Color")->links.empty() && output("Alpha")->links.empty())) { + attributes->add_standard(layer_name); + } + ShaderNode::attributes(shader, attributes); +} + +void VertexColorNode::compile(SVMCompiler &compiler) +{ + ShaderOutput *color_out = output("Color"); + ShaderOutput *alpha_out = output("Alpha"); + int layer_id = compiler.attribute(layer_name); + + ShaderNodeType node; + + if (bump == SHADER_BUMP_DX) + node = NODE_VERTEX_COLOR_BUMP_DX; + else if (bump == SHADER_BUMP_DY) + node = NODE_VERTEX_COLOR_BUMP_DY; + else { + node = NODE_VERTEX_COLOR; + } + + compiler.add_node( + node, layer_id, compiler.stack_assign(color_out), compiler.stack_assign(alpha_out)); +} + +void VertexColorNode::compile(OSLCompiler &compiler) +{ + if (bump == SHADER_BUMP_DX) { + compiler.parameter("bump_offset", "dx"); + } + else if (bump == SHADER_BUMP_DY) { + compiler.parameter("bump_offset", "dy"); + } + else { + compiler.parameter("bump_offset", "center"); + } + compiler.parameter("layer_name", layer_name.c_str()); + compiler.add(this, "node_vertex_color"); +} + /* Value */ NODE_DEFINE(ValueNode) diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 171568644fb..13e9b65fa07 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -979,6 +979,22 @@ class VolumeInfoNode : public ShaderNode { void expand(ShaderGraph *graph); }; +class VertexColorNode : public ShaderNode { + public: + SHADER_NODE_CLASS(VertexColorNode) + void attributes(Shader *shader, AttributeRequestSet *attributes); + bool has_attribute_dependency() + { + return true; + } + bool has_spatial_varying() + { + return true; + } + + ustring layer_name; +}; + class ValueNode : public ShaderNode { public: SHADER_NODE_CLASS(ValueNode) diff --git a/intern/cycles/util/util_color.h b/intern/cycles/util/util_color.h index 6e61190de6b..c6937ca78fe 100644 --- a/intern/cycles/util/util_color.h +++ b/intern/cycles/util/util_color.h @@ -43,11 +43,29 @@ ccl_device uchar4 color_float_to_byte(float3 c) return make_uchar4(r, g, b, 0); } +ccl_device uchar4 color_float4_to_uchar4(float4 c) +{ + uchar r, g, b, a; + + r = float_to_byte(c.x); + g = float_to_byte(c.y); + b = float_to_byte(c.z); + a = float_to_byte(c.w); + + return make_uchar4(r, g, b, a); +} + ccl_device_inline float3 color_byte_to_float(uchar4 c) { return make_float3(c.x * (1.0f / 255.0f), c.y * (1.0f / 255.0f), c.z * (1.0f / 255.0f)); } +ccl_device_inline float4 color_uchar4_to_float4(uchar4 c) +{ + return make_float4( + c.x * (1.0f / 255.0f), c.y * (1.0f / 255.0f), c.z * (1.0f / 255.0f), c.w * (1.0f / 255.0f)); +} + ccl_device float color_srgb_to_linear(float c) { if (c < 0.04045f) diff --git a/intern/cycles/util/util_param.h b/intern/cycles/util/util_param.h index cfbe416aba1..3f8e2d6d700 100644 --- a/intern/cycles/util/util_param.h +++ b/intern/cycles/util/util_param.h @@ -29,6 +29,11 @@ CCL_NAMESPACE_BEGIN OIIO_NAMESPACE_USING static constexpr TypeDesc TypeFloat2(TypeDesc::FLOAT, TypeDesc::VEC2); +static constexpr TypeDesc TypeRGBA(TypeDesc::FLOAT, TypeDesc::VEC4, TypeDesc::COLOR); +static constexpr TypeDesc TypeFloatArray4(TypeDesc::FLOAT, + TypeDesc::SCALAR, + TypeDesc::NOSEMANTICS, + 4); CCL_NAMESPACE_END diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py index 5dc2cf8d106..f0f1baba642 100644 --- a/release/scripts/startup/nodeitems_builtins.py +++ b/release/scripts/startup/nodeitems_builtins.py @@ -190,6 +190,7 @@ shader_node_categories = [ NodeItem("ShaderNodeParticleInfo"), NodeItem("ShaderNodeCameraData"), NodeItem("ShaderNodeUVMap"), + NodeItem("ShaderNodeVertexColor"), NodeItem("ShaderNodeUVAlongStroke", poll=line_style_shader_nodes_poll), NodeItem("NodeGroupInput", poll=group_input_output_item_poll), ]), diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 98710394079..f88aebd312c 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -978,6 +978,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, #define SH_NODE_CLAMP 703 #define SH_NODE_TEX_WHITE_NOISE 704 #define SH_NODE_VOLUME_INFO 705 +#define SH_NODE_VERTEX_COLOR 706 /* custom defines options for Material node */ #define SH_NODE_MAT_DIFF 1 diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index c5e16b2d3cd..6e45130ce44 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -3914,6 +3914,7 @@ static void registerShaderNodes(void) register_node_type_sh_tex_coord(); register_node_type_sh_particle_info(); register_node_type_sh_bump(); + register_node_type_sh_vertex_color(); register_node_type_sh_background(); register_node_type_sh_bsdf_anisotropic(); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 6055a503b7b..8a4cbb3c71a 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -998,6 +998,18 @@ static void node_shader_buts_uvmap(uiLayout *layout, bContext *C, PointerRNA *pt } } +static void node_shader_buts_vertex_color(uiLayout *layout, bContext *C, PointerRNA *ptr) +{ + PointerRNA obptr = CTX_data_pointer_get(C, "active_object"); + if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) { + PointerRNA dataptr = RNA_pointer_get(&obptr, "data"); + uiItemPointerR(layout, ptr, "layer_name", &dataptr, "vertex_colors", "", ICON_GROUP_VCOL); + } + else { + uiItemL(layout, "No mesh in active object.", ICON_ERROR); + } +} + static void node_shader_buts_uvalongstroke(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiItemR(layout, ptr, "use_tips", 0, NULL, 0); @@ -1299,6 +1311,9 @@ static void node_shader_set_butfunc(bNodeType *ntype) case SH_NODE_UVMAP: ntype->draw_buttons = node_shader_buts_uvmap; break; + case SH_NODE_VERTEX_COLOR: + ntype->draw_buttons = node_shader_buts_vertex_color; + break; case SH_NODE_UVALONGSTROKE: ntype->draw_buttons = node_shader_buts_uvalongstroke; break; diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index aea96dac2e3..8d2355ff5ac 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -313,6 +313,7 @@ data_to_c_simple(shaders/material/gpu_shader_material_vector_curves.glsl SRC) data_to_c_simple(shaders/material/gpu_shader_material_vector_displacement.glsl SRC) data_to_c_simple(shaders/material/gpu_shader_material_vector_math.glsl SRC) data_to_c_simple(shaders/material/gpu_shader_material_velvet.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_vertex_color.glsl SRC) data_to_c_simple(shaders/material/gpu_shader_material_volume_absorption.glsl SRC) data_to_c_simple(shaders/material/gpu_shader_material_volume_info.glsl SRC) data_to_c_simple(shaders/material/gpu_shader_material_volume_principled.glsl SRC) diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 8b68bcd5889..242b0ed2e31 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -1080,6 +1080,15 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u "\treturn mix(c1, c2, step(vec3(0.04045), c));\n" "}\n\n"); + BLI_dynstr_append(ds, + "vec4 srgba_to_linear_attr(vec4 c) {\n" + "\tc = max(c, vec4(0.0));\n" + "\tvec4 c1 = c * (1.0 / 12.92);\n" + "\tvec4 c2 = pow((c + 0.055) * (1.0 / 1.055), vec4(2.4));\n" + "\tvec4 final = mix(c1, c2, step(vec4(0.04045), c));" + "\treturn vec4(final.xyz, c.a);\n" + "}\n\n"); + /* Prototype because defined later. */ BLI_dynstr_append(ds, "vec2 hair_get_customdata_vec2(const samplerBuffer);\n" @@ -1184,7 +1193,7 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u } else if (input->attr_type == CD_MCOL) { BLI_dynstr_appendf(ds, - "\tvar%d%s = srgb_to_linear_attr(att%d);\n", + "\tvar%d%s = srgba_to_linear_attr(att%d);\n", input->attr_id, use_geom ? "g" : "", input->attr_id); diff --git a/source/blender/gpu/intern/gpu_material_library.h b/source/blender/gpu/intern/gpu_material_library.h index 06544d27af9..3a38eb5c600 100644 --- a/source/blender/gpu/intern/gpu_material_library.h +++ b/source/blender/gpu/intern/gpu_material_library.h @@ -114,6 +114,7 @@ extern char datatoc_gpu_shader_material_vector_curves_glsl[]; extern char datatoc_gpu_shader_material_vector_displacement_glsl[]; extern char datatoc_gpu_shader_material_vector_math_glsl[]; extern char datatoc_gpu_shader_material_velvet_glsl[]; +extern char datatoc_gpu_shader_material_vertex_color_glsl[]; extern char datatoc_gpu_shader_material_volume_absorption_glsl[]; extern char datatoc_gpu_shader_material_volume_info_glsl[]; extern char datatoc_gpu_shader_material_volume_principled_glsl[]; @@ -527,6 +528,11 @@ static GPUMaterialLibrary gpu_shader_material_velvet_library = { .dependencies = {&gpu_shader_material_diffuse_library, NULL}, }; +static GPUMaterialLibrary gpu_shader_material_vertex_color_library = { + .code = datatoc_gpu_shader_material_vertex_color_glsl, + .dependencies = {NULL}, +}; + static GPUMaterialLibrary gpu_shader_material_volume_absorption_library = { .code = datatoc_gpu_shader_material_volume_absorption_glsl, .dependencies = {NULL}, @@ -638,6 +644,7 @@ static GPUMaterialLibrary *gpu_material_libraries[] = { &gpu_shader_material_vector_displacement_library, &gpu_shader_material_vector_math_library, &gpu_shader_material_velvet_library, + &gpu_shader_material_vertex_color_library, &gpu_shader_material_volume_absorption_library, &gpu_shader_material_volume_info_library, &gpu_shader_material_volume_principled_library, diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_vertex_color.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_vertex_color.glsl new file mode 100644 index 00000000000..551b838daf8 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_vertex_color.glsl @@ -0,0 +1,5 @@ +void node_vertex_color(vec4 vertexColor, out vec4 outColor, out float outAlpha) +{ + outColor = vertexColor; + outAlpha = vertexColor.a; +} diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 6b46c5887b4..0287a1510fe 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -997,6 +997,10 @@ typedef struct NodeShaderUVMap { char uv_map[64]; } NodeShaderUVMap; +typedef struct NodeShaderVertexColor { + char layer_name[64]; +} NodeShaderVertexColor; + typedef struct NodeShaderTexIES { int mode; diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 3d90d566315..913324e4997 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -4867,6 +4867,19 @@ static void def_sh_uvmap(StructRNA *srna) RNA_def_struct_sdna_from(srna, "bNode", NULL); } +static void def_sh_vertex_color(StructRNA *srna) +{ + PropertyRNA *prop; + + RNA_def_struct_sdna_from(srna, "NodeShaderVertexColor", "storage"); + + prop = RNA_def_property(srna, "layer_name", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "Vertex Color", "Vertex Color"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + + RNA_def_struct_sdna_from(srna, "bNode", NULL); +} + static void def_sh_uvalongstroke(StructRNA *srna) { PropertyRNA *prop; diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index ea2968f4917..57a4ace997c 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -206,6 +206,7 @@ set(SRC shader/nodes/node_shader_valToRgb.c shader/nodes/node_shader_value.c shader/nodes/node_shader_vectTransform.c + shader/nodes/node_shader_vertex_color.c shader/nodes/node_shader_vector_displacement.c shader/nodes/node_shader_vector_math.c shader/nodes/node_shader_volume_absorption.c diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index 30673e7cd31..a004090d03d 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -86,6 +86,7 @@ void register_node_type_sh_script(void); void register_node_type_sh_normal_map(void); void register_node_type_sh_tangent(void); void register_node_type_sh_vect_transform(void); +void register_node_type_sh_vertex_color(void); void register_node_type_sh_ambient_occlusion(void); void register_node_type_sh_background(void); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index d14511504f0..f3bc5a0cafa 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -121,6 +121,7 @@ DefNode(ShaderNode, SH_NODE_VECT_TRANSFORM, def_sh_vect_transform, "VEC DefNode(ShaderNode, SH_NODE_SEPHSV, 0, "SEPHSV", SeparateHSV, "Separate HSV", "" ) DefNode(ShaderNode, SH_NODE_COMBHSV, 0, "COMBHSV", CombineHSV, "Combine HSV", "" ) DefNode(ShaderNode, SH_NODE_UVMAP, def_sh_uvmap, "UVMAP", UVMap, "UV Map", "" ) +DefNode(ShaderNode, SH_NODE_VERTEX_COLOR, def_sh_vertex_color, "VERTEX_COLOR", VertexColor, "Vertex Color", "" ) DefNode(ShaderNode, SH_NODE_UVALONGSTROKE, def_sh_uvalongstroke, "UVALONGSTROKE", UVAlongStroke, "UV Along Stroke", "" ) DefNode(ShaderNode, SH_NODE_SEPXYZ, 0, "SEPXYZ", SeparateXYZ, "Separate XYZ", "" ) DefNode(ShaderNode, SH_NODE_COMBXYZ, 0, "COMBXYZ", CombineXYZ, "Combine XYZ", "" ) diff --git a/source/blender/nodes/shader/nodes/node_shader_vertex_color.c b/source/blender/nodes/shader/nodes/node_shader_vertex_color.c new file mode 100644 index 00000000000..8848fc37c66 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_vertex_color.c @@ -0,0 +1,58 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + */ + +#include "../node_shader_util.h" + +static bNodeSocketTemplate sh_node_vertex_color_out[] = { + {SOCK_RGBA, 0, N_("Color")}, + {SOCK_FLOAT, 0, N_("Alpha")}, + {-1, 0, ""}, +}; + +static void node_shader_init_vertex_color(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeShaderVertexColor *vertexColor = MEM_callocN(sizeof(NodeShaderVertexColor), + "NodeShaderVertexColor"); + node->storage = vertexColor; +} + +static int node_shader_gpu_vertex_color(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + NodeShaderVertexColor *vertexColor = (NodeShaderVertexColor *)node->storage; + GPUNodeLink *vertexColorLink = GPU_attribute(CD_MCOL, vertexColor->layer_name); + return GPU_stack_link(mat, node, "node_vertex_color", in, out, vertexColorLink); +} + +void register_node_type_sh_vertex_color(void) +{ + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_VERTEX_COLOR, "Vertex Color", NODE_CLASS_INPUT, 0); + node_type_socket_templates(&ntype, NULL, sh_node_vertex_color_out); + node_type_init(&ntype, node_shader_init_vertex_color); + node_type_storage( + &ntype, "NodeShaderVertexColor", node_free_standard_storage, node_copy_standard_storage); + node_type_gpu(&ntype, node_shader_gpu_vertex_color); + + nodeRegisterType(&ntype); +}