Cycles: internal support for alpha output for attribute node

Not exposed in Blender yet.

Ref D2057
This commit is contained in:
Alexander Gavrilov 2020-10-26 18:32:48 +01:00 committed by Brecht Van Lommel
parent b7558e3c9c
commit 70040e7b0b
4 changed files with 121 additions and 50 deletions

@ -20,20 +20,26 @@ shader node_attribute(string bump_offset = "center",
string name = "",
output point Vector = point(0.0, 0.0, 0.0),
output color Color = 0.0,
output float Fac = 0.0)
output float Fac = 0.0,
output float Alpha = 0.0)
{
getattribute(name, Color);
float data[4];
getattribute(name, data);
Color = color(data[0], data[1], data[2]);
Vector = point(Color);
getattribute(name, Fac);
Alpha = data[3];
if (bump_offset == "dx") {
Color += Dx(Color);
Vector += Dx(Vector);
Fac += Dx(Fac);
Alpha += Dx(Alpha);
}
else if (bump_offset == "dy") {
Color += Dy(Color);
Vector += Dy(Vector);
Fac += Dy(Fac);
Alpha += Dy(Alpha);
}
}

@ -19,10 +19,10 @@ CCL_NAMESPACE_BEGIN
/* Attribute Node */
ccl_device AttributeDescriptor svm_node_attr_init(
KernelGlobals *kg, ShaderData *sd, uint4 node, NodeAttributeType *type, uint *out_offset)
KernelGlobals *kg, ShaderData *sd, uint4 node, NodeAttributeOutputType *type, uint *out_offset)
{
*out_offset = node.z;
*type = (NodeAttributeType)node.w;
*type = (NodeAttributeOutputType)node.w;
AttributeDescriptor desc;
@ -46,7 +46,7 @@ ccl_device AttributeDescriptor svm_node_attr_init(
ccl_device void svm_node_attr(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{
NodeAttributeType type = NODE_ATTR_FLOAT;
NodeAttributeOutputType type = NODE_ATTR_OUTPUT_FLOAT;
uint out_offset = 0;
AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
@ -56,72 +56,91 @@ ccl_device void svm_node_attr(KernelGlobals *kg, ShaderData *sd, float *stack, u
if (primitive_is_volume_attribute(sd, desc)) {
const float4 value = volume_attribute_float4(kg, sd, desc);
if (type == NODE_ATTR_FLOAT) {
if (type == NODE_ATTR_OUTPUT_FLOAT) {
const float f = volume_attribute_value_to_float(value);
stack_store_float(stack, out_offset, f);
}
else {
else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
const float3 f = volume_attribute_value_to_float3(value);
stack_store_float3(stack, out_offset, f);
}
else {
const float f = volume_attribute_value_to_alpha(value);
stack_store_float(stack, out_offset, f);
}
return;
}
#endif
/* Surface */
/* Surface. */
if (desc.type == NODE_ATTR_FLOAT) {
float f = primitive_surface_attribute_float(kg, sd, desc, NULL, NULL);
if (type == NODE_ATTR_FLOAT) {
if (type == NODE_ATTR_OUTPUT_FLOAT) {
stack_store_float(stack, out_offset, f);
}
else {
else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store_float3(stack, out_offset, make_float3(f, f, f));
}
else {
stack_store_float(stack, out_offset, 1.0f);
}
}
else if (desc.type == NODE_ATTR_FLOAT2) {
float2 f = primitive_surface_attribute_float2(kg, sd, desc, NULL, NULL);
if (type == NODE_ATTR_FLOAT) {
if (type == NODE_ATTR_OUTPUT_FLOAT) {
stack_store_float(stack, out_offset, f.x);
}
else {
else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store_float3(stack, out_offset, make_float3(f.x, f.y, 0.0f));
}
else {
stack_store_float(stack, out_offset, 1.0f);
}
}
else if (desc.type == NODE_ATTR_FLOAT4 || desc.type == NODE_ATTR_RGBA) {
float4 f = primitive_surface_attribute_float4(kg, sd, desc, NULL, NULL);
if (type == NODE_ATTR_FLOAT) {
if (type == NODE_ATTR_OUTPUT_FLOAT) {
stack_store_float(stack, out_offset, average(float4_to_float3(f)));
}
else {
else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store_float3(stack, out_offset, float4_to_float3(f));
}
else {
stack_store_float(stack, out_offset, f.w);
}
}
else {
float3 f = primitive_surface_attribute_float3(kg, sd, desc, NULL, NULL);
if (type == NODE_ATTR_FLOAT) {
if (type == NODE_ATTR_OUTPUT_FLOAT) {
stack_store_float(stack, out_offset, average(f));
}
else {
else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store_float3(stack, out_offset, f);
}
else {
stack_store_float(stack, out_offset, 1.0f);
}
}
}
ccl_device void svm_node_attr_bump_dx(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{
NodeAttributeType type = NODE_ATTR_FLOAT;
NodeAttributeOutputType type = NODE_ATTR_OUTPUT_FLOAT;
uint out_offset = 0;
AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
#ifdef __VOLUME__
/* Volume */
if (primitive_is_volume_attribute(sd, desc)) {
if (type == NODE_ATTR_FLOAT) {
if (type == NODE_ATTR_OUTPUT_FLOAT) {
stack_store_float(stack, out_offset, 0.0f);
}
else {
else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store_float3(stack, out_offset, make_float3(0.0f, 0.0f, 0.0f));
}
else {
stack_store_float(stack, out_offset, 1.0f);
}
return;
}
#endif
@ -130,60 +149,75 @@ ccl_device void svm_node_attr_bump_dx(KernelGlobals *kg, ShaderData *sd, 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_OUTPUT_FLOAT) {
stack_store_float(stack, out_offset, f + dx);
}
else {
else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store_float3(stack, out_offset, make_float3(f + dx, f + dx, f + dx));
}
else {
stack_store_float(stack, out_offset, 1.0f);
}
}
else if (desc.type == NODE_ATTR_FLOAT2) {
float2 dx;
float2 f = primitive_surface_attribute_float2(kg, sd, desc, &dx, NULL);
if (type == NODE_ATTR_FLOAT) {
if (type == NODE_ATTR_OUTPUT_FLOAT) {
stack_store_float(stack, out_offset, f.x + dx.x);
}
else {
else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store_float3(stack, out_offset, make_float3(f.x + dx.x, f.y + dx.y, 0.0f));
}
else {
stack_store_float(stack, out_offset, 1.0f);
}
}
else if (desc.type == NODE_ATTR_FLOAT4 || desc.type == NODE_ATTR_RGBA) {
float4 dx;
float4 f = primitive_surface_attribute_float4(kg, sd, desc, &dx, NULL);
if (type == NODE_ATTR_FLOAT) {
if (type == NODE_ATTR_OUTPUT_FLOAT) {
stack_store_float(stack, out_offset, average(float4_to_float3(f + dx)));
}
else {
else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store_float3(stack, out_offset, float4_to_float3(f + dx));
}
else {
stack_store_float(stack, out_offset, f.w + dx.w);
}
}
else {
float3 dx;
float3 f = primitive_surface_attribute_float3(kg, sd, desc, &dx, NULL);
if (type == NODE_ATTR_FLOAT) {
if (type == NODE_ATTR_OUTPUT_FLOAT) {
stack_store_float(stack, out_offset, average(f + dx));
}
else {
else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store_float3(stack, out_offset, f + dx);
}
else {
stack_store_float(stack, out_offset, 1.0f);
}
}
}
ccl_device void svm_node_attr_bump_dy(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{
NodeAttributeType type = NODE_ATTR_FLOAT;
NodeAttributeOutputType type = NODE_ATTR_OUTPUT_FLOAT;
uint out_offset = 0;
AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
#ifdef __VOLUME__
/* Volume */
if (primitive_is_volume_attribute(sd, desc)) {
if (type == NODE_ATTR_FLOAT) {
if (type == NODE_ATTR_OUTPUT_FLOAT) {
stack_store_float(stack, out_offset, 0.0f);
}
else {
else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store_float3(stack, out_offset, make_float3(0.0f, 0.0f, 0.0f));
}
else {
stack_store_float(stack, out_offset, 1.0f);
}
return;
}
#endif
@ -192,42 +226,54 @@ ccl_device void svm_node_attr_bump_dy(KernelGlobals *kg, ShaderData *sd, 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_OUTPUT_FLOAT) {
stack_store_float(stack, out_offset, f + dy);
}
else {
else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store_float3(stack, out_offset, make_float3(f + dy, f + dy, f + dy));
}
else {
stack_store_float(stack, out_offset, 1.0f);
}
}
else if (desc.type == NODE_ATTR_FLOAT2) {
float2 dy;
float2 f = primitive_surface_attribute_float2(kg, sd, desc, NULL, &dy);
if (type == NODE_ATTR_FLOAT) {
if (type == NODE_ATTR_OUTPUT_FLOAT) {
stack_store_float(stack, out_offset, f.x + dy.x);
}
else {
else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store_float3(stack, out_offset, make_float3(f.x + dy.x, f.y + dy.y, 0.0f));
}
else {
stack_store_float(stack, out_offset, 1.0f);
}
}
else if (desc.type == NODE_ATTR_FLOAT4 || desc.type == NODE_ATTR_RGBA) {
float4 dy;
float4 f = primitive_surface_attribute_float4(kg, sd, desc, NULL, &dy);
if (type == NODE_ATTR_FLOAT) {
if (type == NODE_ATTR_OUTPUT_FLOAT) {
stack_store_float(stack, out_offset, average(float4_to_float3(f + dy)));
}
else {
else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store_float3(stack, out_offset, float4_to_float3(f + dy));
}
else {
stack_store_float(stack, out_offset, f.w + dy.w);
}
}
else {
float3 dy;
float3 f = primitive_surface_attribute_float3(kg, sd, desc, NULL, &dy);
if (type == NODE_ATTR_FLOAT) {
if (type == NODE_ATTR_OUTPUT_FLOAT) {
stack_store_float(stack, out_offset, average(f + dy));
}
else {
else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store_float3(stack, out_offset, f + dy);
}
else {
stack_store_float(stack, out_offset, 1.0f);
}
}
}

@ -157,6 +157,12 @@ typedef enum ShaderNodeType {
* match the switch case order in svm.h. */
} ShaderNodeType;
typedef enum NodeAttributeOutputType {
NODE_ATTR_OUTPUT_FLOAT3 = 0,
NODE_ATTR_OUTPUT_FLOAT,
NODE_ATTR_OUTPUT_FLOAT_ALPHA,
} NodeAttributeOutputType;
typedef enum NodeAttributeType {
NODE_ATTR_FLOAT = 0,
NODE_ATTR_FLOAT2,

@ -3743,7 +3743,7 @@ void GeometryNode::compile(SVMCompiler &compiler)
if (!out->links.empty()) {
if (compiler.output_type() != SHADER_TYPE_VOLUME) {
compiler.add_node(
attr_node, ATTR_STD_POINTINESS, compiler.stack_assign(out), NODE_ATTR_FLOAT);
attr_node, ATTR_STD_POINTINESS, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT);
}
else {
compiler.add_node(NODE_VALUE_F, __float_as_int(0.0f), compiler.stack_assign(out));
@ -3753,8 +3753,10 @@ void GeometryNode::compile(SVMCompiler &compiler)
out = output("Random Per Island");
if (!out->links.empty()) {
if (compiler.output_type() != SHADER_TYPE_VOLUME) {
compiler.add_node(
attr_node, ATTR_STD_RANDOM_PER_ISLAND, compiler.stack_assign(out), NODE_ATTR_FLOAT);
compiler.add_node(attr_node,
ATTR_STD_RANDOM_PER_ISLAND,
compiler.stack_assign(out),
NODE_ATTR_OUTPUT_FLOAT);
}
else {
compiler.add_node(NODE_VALUE_F, __float_as_int(0.0f), compiler.stack_assign(out));
@ -3872,7 +3874,7 @@ void TextureCoordinateNode::compile(SVMCompiler &compiler)
}
else {
int attr = compiler.attribute(ATTR_STD_GENERATED);
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_OUTPUT_FLOAT3);
}
}
}
@ -3889,7 +3891,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_OUTPUT_FLOAT3);
}
}
@ -4007,7 +4009,7 @@ void UVMapNode::compile(SVMCompiler &compiler)
else
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_OUTPUT_FLOAT3);
}
}
}
@ -4403,7 +4405,7 @@ void HairInfoNode::compile(SVMCompiler &compiler)
out = output("Intercept");
if (!out->links.empty()) {
int attr = compiler.attribute(ATTR_STD_CURVE_INTERCEPT);
compiler.add_node(NODE_ATTR, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT);
compiler.add_node(NODE_ATTR, attr, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT);
}
out = output("Thickness");
@ -4424,7 +4426,7 @@ void HairInfoNode::compile(SVMCompiler &compiler)
out = output("Random");
if (!out->links.empty()) {
int attr = compiler.attribute(ATTR_STD_CURVE_RANDOM);
compiler.add_node(NODE_ATTR, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT);
compiler.add_node(NODE_ATTR, attr, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT);
}
}
@ -5386,6 +5388,7 @@ NODE_DEFINE(AttributeNode)
SOCKET_OUT_COLOR(color, "Color");
SOCKET_OUT_VECTOR(vector, "Vector");
SOCKET_OUT_FLOAT(fac, "Fac");
SOCKET_OUT_FLOAT(alpha, "Alpha");
return type;
}
@ -5399,8 +5402,10 @@ void AttributeNode::attributes(Shader *shader, AttributeRequestSet *attributes)
ShaderOutput *color_out = output("Color");
ShaderOutput *vector_out = output("Vector");
ShaderOutput *fac_out = output("Fac");
ShaderOutput *alpha_out = output("Alpha");
if (!color_out->links.empty() || !vector_out->links.empty() || !fac_out->links.empty()) {
if (!color_out->links.empty() || !vector_out->links.empty() || !fac_out->links.empty() ||
!alpha_out->links.empty()) {
attributes->add_standard(attribute);
}
@ -5416,6 +5421,7 @@ void AttributeNode::compile(SVMCompiler &compiler)
ShaderOutput *color_out = output("Color");
ShaderOutput *vector_out = output("Vector");
ShaderOutput *fac_out = output("Fac");
ShaderOutput *alpha_out = output("Alpha");
ShaderNodeType attr_node = NODE_ATTR;
int attr = compiler.attribute_standard(attribute);
@ -5426,15 +5432,22 @@ void AttributeNode::compile(SVMCompiler &compiler)
if (!color_out->links.empty() || !vector_out->links.empty()) {
if (!color_out->links.empty()) {
compiler.add_node(attr_node, attr, compiler.stack_assign(color_out), NODE_ATTR_FLOAT3);
compiler.add_node(
attr_node, attr, compiler.stack_assign(color_out), NODE_ATTR_OUTPUT_FLOAT3);
}
if (!vector_out->links.empty()) {
compiler.add_node(attr_node, attr, compiler.stack_assign(vector_out), NODE_ATTR_FLOAT3);
compiler.add_node(
attr_node, attr, compiler.stack_assign(vector_out), NODE_ATTR_OUTPUT_FLOAT3);
}
}
if (!fac_out->links.empty()) {
compiler.add_node(attr_node, attr, compiler.stack_assign(fac_out), NODE_ATTR_FLOAT);
compiler.add_node(attr_node, attr, compiler.stack_assign(fac_out), NODE_ATTR_OUTPUT_FLOAT);
}
if (!alpha_out->links.empty()) {
compiler.add_node(
attr_node, attr, compiler.stack_assign(alpha_out), NODE_ATTR_OUTPUT_FLOAT_ALPHA);
}
}