[Bf-blender-cvs] [0347abee2d7] gsoc-2018-many-light-sampling: Cycles: Add Support for IES files as textures for light strength

Lukas Stockner noreply at git.blender.org
Fri Jun 1 16:17:50 CEST 2018


Commit: 0347abee2d7645bd9de07b5f0520bc6676cdd222
Author: Lukas Stockner
Date:   Sun May 27 00:46:37 2018 +0200
Branches: gsoc-2018-many-light-sampling
https://developer.blender.org/rB0347abee2d7645bd9de07b5f0520bc6676cdd222

Cycles: Add Support for IES files as textures for light strength

This patch adds support for IES files, a file format that is commonly used to store the directional intensity distribution of light sources.
The new IES node is supposed to be plugged into the Strength input of the Emission node of the lamp.

Since people generating IES files do not really seem to care about the standard, the parser is flexible enough to accept all test files I have tried.
Some common weirdnesses are distributing values over multiple lines that should go into one line, using commas instead of spaces as delimiters and adding various useless stuff at the end of the file.

The user interface of the node is similar to the script node, the user can either select an internal Text or load a file.
Internally, IES files are handled similar to Image textures: They are stored in slots by the LightManager and each unique IES is assigned to one slot.

The local coordinate system of the lamp is used, so that the direction of the light can be changed. For UI reasons, it's usually best to add an area light,
rotate it and then change its type, since especially the point light does not immediately show its local coordinate system in the viewport.

Reviewers: #cycles, dingto, sergey, brecht

Reviewed By: #cycles, dingto, brecht

Subscribers: OgDEV, crazyrobinhood, secundar, cardboard, pisuke, intrah, swerner, micah_denn, harvester, gottfried, disnel, campbellbarton, duarteframos, Lapineige, brecht, juicyfruit, dingto, marek, rickyblender, bliblubli, lockal, sergey

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

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

M	intern/cycles/blender/blender_shader.cpp
M	intern/cycles/blender/blender_util.h
M	intern/cycles/graph/node_type.h
M	intern/cycles/kernel/CMakeLists.txt
M	intern/cycles/kernel/kernel_light.h
M	intern/cycles/kernel/kernel_textures.h
M	intern/cycles/kernel/osl/osl_services.cpp
M	intern/cycles/kernel/shaders/CMakeLists.txt
A	intern/cycles/kernel/shaders/node_ies_light.osl
M	intern/cycles/kernel/svm/svm.h
A	intern/cycles/kernel/svm/svm_ies.h
M	intern/cycles/kernel/svm/svm_types.h
M	intern/cycles/render/graph.cpp
M	intern/cycles/render/light.cpp
M	intern/cycles/render/light.h
M	intern/cycles/render/nodes.cpp
M	intern/cycles/render/nodes.h
M	intern/cycles/render/osl.cpp
M	intern/cycles/render/osl.h
M	intern/cycles/render/scene.cpp
M	intern/cycles/render/scene.h
M	intern/cycles/render/svm.cpp
M	intern/cycles/render/svm.h
M	intern/cycles/util/CMakeLists.txt
A	intern/cycles/util/util_ies.cpp
A	intern/cycles/util/util_ies.h
M	intern/cycles/util/util_math.h
M	release/scripts/startup/nodeitems_builtins.py
M	source/blender/blenkernel/BKE_node.h
M	source/blender/blenkernel/intern/bpath.c
M	source/blender/blenkernel/intern/node.c
M	source/blender/editors/space_node/drawnode.c
M	source/blender/makesdna/DNA_node_types.h
M	source/blender/makesrna/RNA_access.h
M	source/blender/makesrna/intern/rna_nodetree.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_ies_light.c

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

diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index eb9968a85c2..c6144cef1bf 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -818,6 +818,19 @@ static ShaderNode *add_node(Scene *scene,
 		get_tex_mapping(&sky->tex_mapping, b_texture_mapping);
 		node = sky;
 	}
+	else if(b_node.is_a(&RNA_ShaderNodeTexIES)) {
+		BL::ShaderNodeTexIES b_ies_node(b_node);
+		IESLightNode *ies = new IESLightNode();
+		switch(b_ies_node.mode()) {
+			case BL::ShaderNodeTexIES::mode_EXTERNAL:
+				ies->filename = blender_absolute_path(b_data, b_ntree, b_ies_node.filepath());
+				break;
+			case BL::ShaderNodeTexIES::mode_INTERNAL:
+				ies->ies = get_text_datablock_content(b_ies_node.ies().ptr);
+				break;
+		}
+		node = ies;
+	}
 	else if(b_node.is_a(&RNA_ShaderNodeNormalMap)) {
 		BL::ShaderNodeNormalMap b_normal_map_node(b_node);
 		NormalMapNode *nmap = new NormalMapNode();
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index c418b19a637..87d6c7eba8a 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -468,6 +468,21 @@ static inline string blender_absolute_path(BL::BlendData& b_data,
 	return path;
 }
 
+static inline string get_text_datablock_content(const PointerRNA&& ptr)
+{
+	if(ptr.data == NULL) {
+		return "";
+	}
+
+	string content;
+	BL::Text::lines_iterator iter;
+	for(iter.begin(ptr); iter; ++iter) {
+		content += iter->body() + "\n";
+	}
+
+	return content;
+}
+
 /* Texture Space */
 
 static inline void mesh_texture_space(BL::Mesh& b_mesh,
diff --git a/intern/cycles/graph/node_type.h b/intern/cycles/graph/node_type.h
index 7d46e31ce24..15d34a79bb8 100644
--- a/intern/cycles/graph/node_type.h
+++ b/intern/cycles/graph/node_type.h
@@ -73,12 +73,13 @@ struct SocketType
 		INTERNAL               = (1 << 2) | (1 << 3),
 
 		LINK_TEXTURE_GENERATED = (1 << 4),
-		LINK_TEXTURE_UV        = (1 << 5),
-		LINK_INCOMING          = (1 << 6),
-		LINK_NORMAL            = (1 << 7),
-		LINK_POSITION          = (1 << 8),
-		LINK_TANGENT           = (1 << 9),
-		DEFAULT_LINK_MASK      = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9)
+		LINK_TEXTURE_NORMAL    = (1 << 5),
+		LINK_TEXTURE_UV        = (1 << 6),
+		LINK_INCOMING          = (1 << 7),
+		LINK_NORMAL            = (1 << 8),
+		LINK_POSITION          = (1 << 9),
+		LINK_TANGENT           = (1 << 10),
+		DEFAULT_LINK_MASK      = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10)
 	};
 
 	ustring name;
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index 9b7f4e00084..457602ae4e7 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -178,6 +178,7 @@ set(SRC_SVM_HEADERS
 	svm/svm_geometry.h
 	svm/svm_gradient.h
 	svm/svm_hsv.h
+	svm/svm_ies.h
 	svm/svm_image.h
 	svm/svm_invert.h
 	svm/svm_light_path.h
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index efab69ee37d..ec7203d36eb 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -170,7 +170,7 @@ float3 background_map_sample(KernelGlobals *kg, float randu, float randv, float
 	float2 cdf_last_v = kernel_tex_fetch(__light_background_marginal_cdf, res);
 
 	/* importance-sampled V direction */
-	float dv = (randv - cdf_v.y) / (cdf_next_v.y - cdf_v.y);
+	float dv = inverse_lerp(cdf_v.y, cdf_next_v.y, randv);
 	float v = (index_v + dv) / res;
 
 	/* this is basically std::lower_bound as used by pbrt */
@@ -196,7 +196,7 @@ float3 background_map_sample(KernelGlobals *kg, float randu, float randv, float
 	float2 cdf_last_u = kernel_tex_fetch(__light_background_conditional_cdf, index_v * cdf_count + res);
 
 	/* importance-sampled U direction */
-	float du = (randu - cdf_u.y) / (cdf_next_u.y - cdf_u.y);
+	float du = inverse_lerp(cdf_u.y, cdf_next_u.y, randu);
 	float u = (index_u + du) / res;
 
 	/* compute pdf */
diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h
index 9047b93a0b2..a7b8c492ee9 100644
--- a/intern/cycles/kernel/kernel_textures.h
+++ b/intern/cycles/kernel/kernel_textures.h
@@ -81,5 +81,8 @@ KERNEL_TEX(uint, __sobol_directions)
 /* image textures */
 KERNEL_TEX(TextureInfo, __texture_info)
 
+/* ies lights */
+KERNEL_TEX(float, __ies)
+
 #undef KERNEL_TEX
 
diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp
index 0c5e5e30e47..32d86b7192a 100644
--- a/intern/cycles/kernel/osl/osl_services.cpp
+++ b/intern/cycles/kernel/osl/osl_services.cpp
@@ -956,9 +956,15 @@ bool OSLRenderServices::texture(ustring filename,
 				status = true;
 			}
 		}
+		else if(filename[1] == 'l') {
+			/* IES light. */
+			int slot = atoi(filename.c_str() + 2);
+			result[0] = kernel_ies_interp(kg, slot, s, t);
+			status = true;
+		}
 		else {
 			/* Packed texture. */
-			int slot = atoi(filename.c_str() + 1);
+			int slot = atoi(filename.c_str() + 2);
 			float4 rgba = kernel_tex_image_interp(kg, slot, s, 1.0f - t);
 
 			result[0] = rgba[0];
diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt
index 6ec651a96d8..b28d017c1c2 100644
--- a/intern/cycles/kernel/shaders/CMakeLists.txt
+++ b/intern/cycles/kernel/shaders/CMakeLists.txt
@@ -39,6 +39,7 @@ set(SRC_OSL
 	node_principled_volume.osl
 	node_holdout.osl
 	node_hsv.osl
+	node_ies_light.osl
 	node_image_texture.osl
 	node_invert.osl
 	node_layer_weight.osl
diff --git a/intern/cycles/kernel/shaders/node_ies_light.osl b/intern/cycles/kernel/shaders/node_ies_light.osl
new file mode 100644
index 00000000000..a0954e3a444
--- /dev/null
+++ b/intern/cycles/kernel/shaders/node_ies_light.osl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2011-2015 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"
+#include "node_texture.h"
+
+/* IES Light */
+
+shader node_ies_light(
+	int use_mapping = 0,
+	matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+	int slot = 0,
+	float Strength = 1.0,
+	point Vector = I,
+	output float Fac = 0.0)
+{
+	point p = Vector;
+
+	if (use_mapping) {
+		p = transform(mapping, p);
+	}
+
+	p = normalize(p);
+
+	float v_angle = acos(-p[2]);
+	float h_angle = atan2(p[0], p[1]) + M_PI;
+
+	Fac = Strength * texture(format("@l%d", slot), h_angle, v_angle);
+}
diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h
index 39cd5da7b12..bfa146f2d93 100644
--- a/intern/cycles/kernel/svm/svm.h
+++ b/intern/cycles/kernel/svm/svm.h
@@ -157,6 +157,7 @@ CCL_NAMESPACE_END
 #include "kernel/svm/svm_camera.h"
 #include "kernel/svm/svm_geometry.h"
 #include "kernel/svm/svm_hsv.h"
+#include "kernel/svm/svm_ies.h"
 #include "kernel/svm/svm_image.h"
 #include "kernel/svm/svm_gamma.h"
 #include "kernel/svm/svm_brightness.h"
@@ -421,6 +422,9 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ccl_a
 			case NODE_LIGHT_FALLOFF:
 				svm_node_light_falloff(sd, stack, node);
 				break;
+			case NODE_IES:
+				svm_node_ies(kg, sd, stack, node, &offset);
+				break;
 #  endif  /* __EXTRA_NODES__ */
 #endif  /* NODES_GROUP(NODE_GROUP_LEVEL_2) */
 
diff --git a/intern/cycles/kernel/svm/svm_ies.h b/intern/cycles/kernel/svm/svm_ies.h
new file mode 100644
index 00000000000..6130c3348b0
--- /dev/null
+++ b/intern/cycles/kernel/svm/svm_ies.h
@@ -0,0 +1,110 @@
+/*
+ * 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
+
+/* IES Light */
+
+ccl_device_inline float interpolate_ies_vertical(KernelGlobals *kg, int ofs, int v, int v_num, float v_frac, int h)
+{
+	/* Since lookups are performed in spherical coordinates, clamping the coordinates at the low end of v
+	 * (corresponding to the north pole) would result in artifacts.
+	 * The proper way of dealing with this would be to lookup the corresponding value on the other side of the pole,
+	 * but since the horizontal coordinates might be nonuniform, this would require yet another interpolation.
+	 * Therefore, the assumtion is made that the light is going to be symmetrical, which means that we can just take
+	 * the corresponding value at the current horizontal coordinate. */
+
+#define IES_LOOKUP(v) kernel_tex_fetch(__ies, ofs+h*v_num+(v))
+	/* If v is zero, assume symmetry and read at v=1 instead of v=-1. */
+	float a = IES_LOOKUP((v == 0)? 1 : v-1);
+	float b = IES_LOOKUP(v);
+	float c = IES_LOOKUP(v+1);
+	float d = IES_LOOKUP(min(v+2, v_num-1));
+#undef IES_LOOKUP
+
+	return cubic_interp(a, b, c, d, v_frac);
+}
+
+ccl_device_inline float kernel_ies_interp(KernelGlobals *kg, int slot, float h_angle, float v_angle)
+{
+	/* Find offset of the IES data in the table. */
+	int ofs = __float_as_int(kernel_tex_fetch(__ies, slot));
+	if(ofs == -1) {
+		return 100.0f;
+	}
+
+	int h_num = __float_as_int(kernel_tex_fetch(__ies, ofs++));
+	int v_num = __float_as_int(kernel_tex_fetch(__ies, ofs++));
+
+#define IES_LOOKUP_ANGLE_H(h) kernel_tex_fetch(__ies, ofs+(h))
+#define IES_LOOKUP_ANGLE_V(v) kernel_tex_fetch(__ie

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list