[Bf-blender-cvs] [0aec2dcd3ae] master: Cycles: add Principled Volume shader.

Brecht Van Lommel noreply at git.blender.org
Fri Feb 23 19:02:23 CET 2018


Commit: 0aec2dcd3ae0ed382ffe7b3311a4e30fc88398e4
Author: Brecht Van Lommel
Date:   Tue Jan 30 15:05:19 2018 +0100
Branches: master
https://developer.blender.org/rB0aec2dcd3ae0ed382ffe7b3311a4e30fc88398e4

Cycles: add Principled Volume shader.

Similar to the Principled BSDF, this should make it easier to set up volume
materials. Smoke and fire can be rendererd with just a single principled
volume node, the appropriate attributes will be used when available. The node
also works for simpler homogeneous volumes like water or mist.

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

===================================================================

M	intern/cycles/blender/blender_shader.cpp
M	intern/cycles/kernel/shaders/CMakeLists.txt
A	intern/cycles/kernel/shaders/node_principled_volume.osl
M	intern/cycles/kernel/svm/svm.h
M	intern/cycles/kernel/svm/svm_closure.h
M	intern/cycles/kernel/svm/svm_types.h
M	intern/cycles/render/nodes.cpp
M	intern/cycles/render/nodes.h
M	release/scripts/startup/bl_operators/object_quick_effects.py
M	release/scripts/startup/nodeitems_builtins.py
M	source/blender/blenkernel/BKE_node.h
M	source/blender/blenkernel/intern/node.c
M	source/blender/nodes/CMakeLists.txt
M	source/blender/nodes/NOD_shader.h
M	source/blender/nodes/NOD_static_types.h
A	source/blender/nodes/shader/nodes/node_shader_volume_principled.c
M	source/blender/nodes/shader/nodes/node_shader_volume_scatter.c

===================================================================

diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 33384709947..eb9968a85c2 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -566,6 +566,10 @@ static ShaderNode *add_node(Scene *scene,
 	else if(b_node.is_a(&RNA_ShaderNodeVolumeAbsorption)) {
 		node = new AbsorptionVolumeNode();
 	}
+	else if(b_node.is_a(&RNA_ShaderNodeVolumePrincipled)) {
+		PrincipledVolumeNode *principled = new PrincipledVolumeNode();
+		node = principled;
+	}
 	else if(b_node.is_a(&RNA_ShaderNodeNewGeometry)) {
 		node = new GeometryNode();
 	}
@@ -1024,6 +1028,10 @@ static void add_nodes(Scene *scene,
 			for(b_node->internal_links.begin(b_link); b_link != b_node->internal_links.end(); ++b_link) {
 				BL::NodeSocket to_socket(b_link->to_socket());
 				SocketType::Type to_socket_type = convert_socket_type(to_socket);
+				if (to_socket_type == SocketType::UNDEFINED) {
+					continue;
+				}
+
 				ConvertNode *proxy = new ConvertNode(to_socket_type, to_socket_type, true);
 
 				input_map[b_link->from_socket().ptr.data] = proxy->inputs[0];
@@ -1047,6 +1055,10 @@ static void add_nodes(Scene *scene,
 			 */
 			for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
 				SocketType::Type input_type = convert_socket_type(*b_input);
+				if (input_type == SocketType::UNDEFINED) {
+					continue;
+				}
+
 				ConvertNode *proxy = new ConvertNode(input_type, input_type, true);
 				graph->add(proxy);
 
@@ -1059,6 +1071,10 @@ static void add_nodes(Scene *scene,
 			}
 			for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
 				SocketType::Type output_type = convert_socket_type(*b_output);
+				if (output_type == SocketType::UNDEFINED) {
+					continue;
+				}
+
 				ConvertNode *proxy = new ConvertNode(output_type, output_type, true);
 				graph->add(proxy);
 
diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt
index 19b7769200e..6ec651a96d8 100644
--- a/intern/cycles/kernel/shaders/CMakeLists.txt
+++ b/intern/cycles/kernel/shaders/CMakeLists.txt
@@ -36,6 +36,7 @@ set(SRC_OSL
 	node_hair_info.osl
 	node_scatter_volume.osl
 	node_absorption_volume.osl
+	node_principled_volume.osl
 	node_holdout.osl
 	node_hsv.osl
 	node_image_texture.osl
diff --git a/intern/cycles/kernel/shaders/node_principled_volume.osl b/intern/cycles/kernel/shaders/node_principled_volume.osl
new file mode 100644
index 00000000000..609fb95866d
--- /dev/null
+++ b/intern/cycles/kernel/shaders/node_principled_volume.osl
@@ -0,0 +1,94 @@
+/*
+ * 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_principled_volume(
+	color Color = color(0.5, 0.5, 0.5),
+	float Density = 1.0,
+	float Anisotropy = 0.0,
+	color AbsorptionColor = color(0.0, 0.0, 0.0),
+	float EmissionStrength = 0.0,
+	color EmissionColor = color(1.0, 1.0, 1.0),
+	float BlackbodyIntensity = 0.0,
+	color BlackbodyTint = color(1.0, 1.0, 1.0),
+	float Temperature = 1500.0,
+	string DensityAttribute = "geom:density",
+	string ColorAttribute = "geom:color",
+	string TemperatureAttribute = "geom:temperature",
+	output closure color Volume = 0)
+{
+	/* Compute density. */
+	float primitive_density = 1.0;
+	float density = max(Density, 0.0);
+
+	if(density > 1e-5) {
+		if(getattribute(DensityAttribute, primitive_density)) {
+			density = max(density * primitive_density, 0.0);
+		}
+	}
+
+	if(density > 1e-5) {
+		/* Compute scattering color. */
+		color scatter_color = Color;
+		color primitive_color;
+		if(getattribute(ColorAttribute, primitive_color)) {
+			scatter_color *= primitive_color;
+		}
+
+		/* Add scattering and absorption closures. */
+		color scatter_coeff = scatter_color;
+		color absorption_coeff = max(1.0 - scatter_color, 0.0) * max(1.0 - AbsorptionColor, 0.0);
+		Volume = scatter_coeff * density * henyey_greenstein(Anisotropy) +
+		         absorption_coeff * density * absorption();
+	}
+
+	/* Compute emission. */
+	float emission_strength = max(EmissionStrength, 0.0);
+	float blackbody_intensity = BlackbodyIntensity;
+
+	if(emission_strength > 1e-5) {
+		Volume += emission_strength * EmissionColor * emission();
+	}
+
+	if(blackbody_intensity > 1e-3) {
+		float T = Temperature;
+
+		/* Add temperature from attribute if available. */
+		float temperature;
+		if(getattribute(TemperatureAttribute, temperature)) {
+			T *= max(temperature, 0.0);
+		}
+
+		T = max(T, 0.0);
+
+		/* Stefan-Boltzman law. */
+		float T4 = (T * T) * (T * T);
+		float sigma = 5.670373e-8 * 1e-6 / M_PI;
+		float intensity = sigma * mix(1.0, T4, blackbody_intensity);
+
+		if(intensity > 1e-5) {
+			color bb = blackbody(T);
+			float l = luminance(bb);
+
+			if(l != 0.0) {
+				bb *= BlackbodyTint * intensity / l;
+				Volume += bb * emission();
+			}
+		}
+	}
+}
+
diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h
index fae9f783483..39cd5da7b12 100644
--- a/intern/cycles/kernel/svm/svm.h
+++ b/intern/cycles/kernel/svm/svm.h
@@ -334,7 +334,10 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ccl_a
 				break;
 #  if NODES_FEATURE(NODE_FEATURE_VOLUME)
 			case NODE_CLOSURE_VOLUME:
-				svm_node_closure_volume(kg, sd, stack, node, type, path_flag);
+				svm_node_closure_volume(kg, sd, stack, node, type);
+				break;
+			case NODE_PRINCIPLED_VOLUME:
+				svm_node_principled_volume(kg, sd, stack, node, type, path_flag, &offset);
 				break;
 #  endif  /* NODES_FEATURE(NODE_FEATURE_VOLUME) */
 #  ifdef __EXTRA_NODES__
diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h
index 24452c81fe0..819b256bde0 100644
--- a/intern/cycles/kernel/svm/svm_closure.h
+++ b/intern/cycles/kernel/svm/svm_closure.h
@@ -794,7 +794,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
 	}
 }
 
-ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, ShaderType shader_type, int path_flag)
+ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, ShaderType shader_type)
 {
 #ifdef __VOLUME__
 	/* Only sum extinction for volumes, variable is shared with surface transparency. */
@@ -802,19 +802,20 @@ ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float
 		return;
 	}
 
-	uint type, param1_offset, param2_offset;
+	uint type, density_offset, anisotropy_offset;
 
 	uint mix_weight_offset;
-	decode_node_uchar4(node.y, &type, &param1_offset, &param2_offset, &mix_weight_offset);
+	decode_node_uchar4(node.y, &type, &density_offset, &anisotropy_offset, &mix_weight_offset);
 	float mix_weight = (stack_valid(mix_weight_offset)? stack_load_float(stack, mix_weight_offset): 1.0f);
 
-	if(mix_weight == 0.0f)
+	if(mix_weight == 0.0f) {
 		return;
+	}
 
-	float param1 = (stack_valid(param1_offset))? stack_load_float(stack, param1_offset): __uint_as_float(node.z);
+	float density = (stack_valid(density_offset))? stack_load_float(stack, density_offset): __uint_as_float(node.z);
+	density = mix_weight * fmaxf(density, 0.0f);
 
 	/* Compute scattering coefficient. */
-	float density = mix_weight * fmaxf(param1, 0.0f);
 	float3 weight = sd->svm_closure_weight;
 
 	if(type == CLOSURE_VOLUME_ABSORPTION_ID) {
@@ -825,11 +826,11 @@ ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float
 
 	/* Add closure for volume scattering. */
 	if(type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID) {
-		float param2 = (stack_valid(param2_offset))? stack_load_float(stack, param2_offset): __uint_as_float(node.w);
 		HenyeyGreensteinVolume *volume = (HenyeyGreensteinVolume*)bsdf_alloc(sd, sizeof(HenyeyGreensteinVolume), weight);
 
 		if(volume) {
-			volume->g = param2; /* g */
+			float anisotropy = (stack_valid(anisotropy_offset))? stack_load_float(stack, anisotropy_offset): __uint_as_float(node.w);
+			volume->g = anisotropy; /* g */
 			sd->flag |= volume_henyey_greenstein_setup(volume);
 		}
 	}
@@ -839,6 +840,106 @@ ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float
 #endif
 }
 
+ccl_device void svm_node_principled_volume(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, ShaderType shader_type, int path_flag, int *offset)
+{
+#ifdef __VOLUME__
+	uint4 value_node = read_node(kg, offset);
+	uint4 attr_node = read_node(kg, offset);
+
+	/* Only sum extinction for volumes, variable is shared with surface transparency. */
+	if(shader_type != SHADER_TYPE_VOLUME) {
+		return;
+	}
+
+	uint density_offset, anisotropy_offset, absorption_color_offset, mix_weight_offset;
+	decode_node_uchar4(node.y, &density_offset, &anisotropy_offset, &absorption_color_offset, &mix_weight_offset);
+	float mix_weight = (stack_valid(mix_weight_offset)? stack_load_float(stack, mix_weight_offset): 1.0f);
+
+	if(mix_weight == 0.0f) {
+		return;
+	}
+
+	/* Compute density. */
+	float primitive_density = 1.0f;
+	float density = (stack_valid(density_offset))? stack_load_float(stack, density_offset): __uint_as_float(value_node.x);
+	density = mix_weight * fmaxf(density, 0.0f);
+
+	if(density > CLOSURE_WEIGHT_CUTOFF) {
+		/* Density and color attribute lookup if available. */
+		const AttributeDescriptor attr_density = find_attribute(kg, sd, attr_node.x);
+		if(attr_density.offset != ATTR_STD_NOT_FOUND) {
+			primitive_density = primitive_attribute_float(kg, sd, attr_density, NULL, NULL);
+			density = fmaxf(density * primitive_density, 0.0f);
+		}
+	}
+
+	if(density > CLOSURE_WEIGHT_CUTOFF) {
+		/* Compute scattering color. */
+		float3 color = sd->svm_closure_weight;
+
+		const

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list