diff options
author | OmarSquircleArt <omar.squircleart@gmail.com> | 2019-09-12 18:42:13 +0300 |
---|---|---|
committer | OmarSquircleArt <omar.squircleart@gmail.com> | 2019-09-12 18:42:13 +0300 |
commit | 2ea82e86ca60c1c268c6074ecba10524cebd97ed (patch) | |
tree | bf355c2a930f584685f68a833ce620ad15e63a70 /intern/cycles | |
parent | f80018b5f7497d7ed0fe79783c4cd76f05ec1c7c (diff) |
Shading: Add Vertex Color node.
This patch adds a new Vertex Color node. The node also returns the alpha
of the vertex color layer as an output.
Reviewers: brecht
Differential Revision: https://developer.blender.org/D5767
Diffstat (limited to 'intern/cycles')
20 files changed, 535 insertions, 49 deletions
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 |