[Bf-blender-cvs] [2e42014] cycles_panorama_experiments: Cycles: Experiment with using Lambert cylindrical equal-area projection

Sergey Sharybin noreply at git.blender.org
Mon Mar 28 18:14:03 CEST 2016


Commit: 2e420144c5b4bc339dcde22585167bfd4b3cd62a
Author: Sergey Sharybin
Date:   Thu Mar 24 22:33:48 2016 +0500
Branches: cycles_panorama_experiments
https://developer.blender.org/rB2e420144c5b4bc339dcde22585167bfd4b3cd62a

Cycles: Experiment with using Lambert cylindrical equal-area projection

This commit implements new panorama and environment texture projection
which is called after a dude named Lambert:

  https://en.wikipedia.org/wiki/Lambert_cylindrical_equal-area_projection

Advantage of this projection is that it doesn't waste sampling time next
to the poles (which is a huge issue for the equirectangular projection).

Disadvantage of this model is that there'll be some distortion on the
poles when mapping it back to the sphere.

This is partially worked around by using scaling magic so there'll be
a bit more samples added on the top/bottom of the image (which makes it
technically a Roosendaal-Sharybin mapping since that's what we've been
discussing in the studio).

Maybe we should be more aggressive here with clamping of the sine, but
let's start doing some real-world tests first.

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

M	intern/cycles/app/cycles_xml.cpp
M	intern/cycles/blender/addon/properties.py
M	intern/cycles/kernel/kernel_projection.h
M	intern/cycles/kernel/kernel_types.h
M	intern/cycles/kernel/svm/svm_image.h
M	intern/cycles/render/nodes.cpp
M	source/blender/makesdna/DNA_node_types.h
M	source/blender/makesrna/intern/rna_nodetree.c

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

diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp
index 7fcc669..7e672c5 100644
--- a/intern/cycles/app/cycles_xml.cpp
+++ b/intern/cycles/app/cycles_xml.cpp
@@ -357,6 +357,8 @@ static void xml_read_camera(const XMLReadState& state, pugi::xml_node node)
 		cam->panorama_type = PANORAMA_FISHEYE_EQUISOLID;
 	else if(xml_equal_string(node, "panorama_type", "cubemap"))
 		cam->panorama_type = PANORAMA_CUBEMAP;
+	else if(xml_equal_string(node, "panorama_type", "lambert"))
+		cam->panorama_type = PANORAMA_LAMBERT;
 
 	xml_read_float(&cam->fisheye_fov, node, "fisheye_fov");
 	xml_read_float(&cam->fisheye_lens, node, "fisheye_lens");
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index d8d4157..3a83e2c 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -69,6 +69,7 @@ enum_panorama_types = (
                           "Similar to most fisheye modern lens, takes sensor dimensions into consideration"),
     ('MIRRORBALL', "Mirror Ball", "Uses the mirror ball mapping"),
     ('CUBEMAP', "Cubemap", "Render the scene using cube map projection"),
+    ('LAMBERT', "Lambert", "Render the scene with a spherical camera, having more precision in the center"),
     )
 
 enum_curve_primitives = (
diff --git a/intern/cycles/kernel/kernel_projection.h b/intern/cycles/kernel/kernel_projection.h
index 88cd507..6f96042 100644
--- a/intern/cycles/kernel/kernel_projection.h
+++ b/intern/cycles/kernel/kernel_projection.h
@@ -83,6 +83,38 @@ ccl_device float3 equirectangular_to_direction(float u, float v)
 	return equirectangular_range_to_direction(u, v, make_float4(-M_2PI_F, M_PI_F, -M_PI_F, M_PI_F));
 }
 
+/* Lambert coordinates <-> Cartesian direction */
+
+#define LAMBERT_CLAMP (1.0f - 0.01f)
+#define LAMBERT_SCALE (1.0990301169315693f)
+
+ccl_device_inline float lambert_asinf_clamped(float x)
+{
+	return asinf(x * LAMBERT_CLAMP) * LAMBERT_SCALE;
+}
+
+ccl_device_inline float lambert_sinf_clamped(float x)
+{
+	return sinf(x / LAMBERT_SCALE) / LAMBERT_CLAMP;
+}
+
+ccl_device float2 direction_to_lambert(float3 dir)
+{
+	float u = -atan2f(dir.y, dir.x) / (M_2PI_F) + 0.5f;
+	float v = lambert_sinf_clamped(atan2f(dir.z, hypotf(dir.x, dir.y))) * 0.5f + 0.5f;
+
+	return make_float2(u, v);
+}
+
+ccl_device float3 lambert_to_direction(float u, float v)
+{
+	const float phi = M_PI_F*(1.0f - 2.0f*u);
+	const float theta = lambert_asinf_clamped(1.0f - 2.0f*v) + M_PI_2_F;
+	return make_float3(sinf(theta)*cosf(phi),
+	                   sinf(theta)*sinf(phi),
+	                   cosf(theta));
+}
+
 /* Fisheye <-> Cartesian direction */
 
 ccl_device float2 direction_to_fisheye(float3 dir, float fov)
@@ -376,6 +408,8 @@ ccl_device float3 panorama_to_direction(KernelGlobals *kg,
 			return fisheye_to_direction(u, v, kernel_data.cam.fisheye_fov);
 		case PANORAMA_CUBEMAP:
 			return cubemap_to_direction(x, y, raster_width, raster_height, u, v);
+		case PANORAMA_LAMBERT:
+			return lambert_to_direction(u, v);
 		case PANORAMA_FISHEYE_EQUISOLID:
 		default:
 			return fisheye_equisolid_to_direction(u, v, kernel_data.cam.fisheye_lens,
@@ -403,6 +437,8 @@ ccl_device float2 direction_to_panorama(KernelGlobals *kg, float3 dir)
 			return direction_to_cubemap(dir,
 			                            kernel_data.cam.width,
 			                            kernel_data.cam.height);
+		case PANORAMA_LAMBERT:
+			return direction_to_lambert(dir);
 		case PANORAMA_FISHEYE_EQUISOLID:
 		default:
 			return direction_to_fisheye_equisolid(dir, kernel_data.cam.fisheye_lens,
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 9935ab2..6fd741d 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -489,6 +489,7 @@ enum PanoramaType {
 	PANORAMA_FISHEYE_EQUISOLID = 2,
 	PANORAMA_MIRRORBALL = 3,
 	PANORAMA_CUBEMAP = 4,
+	PANORAMA_LAMBERT = 5,
 
 	PANORAMA_NUM_TYPES,
 };
diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h
index 13e0e52..f67de9b 100644
--- a/intern/cycles/kernel/svm/svm_image.h
+++ b/intern/cycles/kernel/svm/svm_image.h
@@ -502,12 +502,15 @@ ccl_device void svm_node_tex_environment(KernelGlobals *kg,
 		uv = direction_to_equirectangular(co);
 	else if(projection == 1)
 		uv = direction_to_mirrorball(co);
-	else {
+	else if(projection == 2) {
 		uint4 node = read_node(kg, offset);
 		float raster_width = (float)(node.y);
 		float raster_height = (float)(node.z);
 		uv = direction_to_cubemap(co, raster_width, raster_height);
 	}
+	else {
+		uv = direction_to_lambert(co);
+	}
 
 	uint use_alpha = stack_valid(alpha_offset);
 	float4 f = svm_image_texture(kg, id, uv.x, uv.y, srgb, use_alpha);
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index b79a9ab..ddf85b8 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -406,6 +406,7 @@ static ShaderEnum env_projection_init()
 	enm.insert("Equirectangular", 0);
 	enm.insert("Mirror Ball", 1);
 	enm.insert("Cubemap", 2);
+	enm.insert("Lambert", 3);
 
 	return enm;
 }
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 8a94376..fcd6435 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -989,6 +989,7 @@ typedef struct NodeSunBeams {
 #define SHD_PROJ_EQUIRECTANGULAR	0
 #define SHD_PROJ_MIRROR_BALL		1
 #define SHD_PROJ_CUBEMAP		2
+#define SHD_PROJ_LAMBERT		3
 
 #define SHD_IMAGE_EXTENSION_REPEAT	0
 #define SHD_IMAGE_EXTENSION_EXTEND	1
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 789e0ad..c9bf53d 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -3665,6 +3665,8 @@ static void def_sh_tex_environment(StructRNA *srna)
 		                       "Projection from an orthographic photo of a mirror ball"},
 		{SHD_PROJ_CUBEMAP, "CUBEMAP", 0, "Cubemap",
 		                   "Projection onto a cube map"},
+		{SHD_PROJ_LAMBERT, "LAMBERT", 0, "Lambert",
+		                   "Lambert or cylindrical equal-area projection"},
 		{0, NULL, 0, NULL, NULL}
 	};




More information about the Bf-blender-cvs mailing list