[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [48822] branches/soc-2011-tomato: Cycles: blended box mapping support for image texture node.

Brecht Van Lommel brechtvanlommel at pandora.be
Wed Jul 11 02:08:44 CEST 2012


Revision: 48822
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=48822
Author:   blendix
Date:     2012-07-11 00:08:42 +0000 (Wed, 11 Jul 2012)
Log Message:
-----------
Cycles: blended box mapping support for image texture node. This enabled by
selecting Box instead of Flat as projection, and then setting the blend value.
Blend 0.0 will not do any blending between box sides, higher values will give
a smooth transition between the sides

This is useful for mapping image texture without too obvious patterns in a
way that looks seamless, without the need for UV mapping. This works basically
the same as the mango node setup that was posted, just a bit faster:

http://mango.blender.org/production/blended_box/

Modified Paths:
--------------
    branches/soc-2011-tomato/intern/cycles/blender/blender_shader.cpp
    branches/soc-2011-tomato/intern/cycles/kernel/svm/svm.h
    branches/soc-2011-tomato/intern/cycles/kernel/svm/svm_image.h
    branches/soc-2011-tomato/intern/cycles/kernel/svm/svm_types.h
    branches/soc-2011-tomato/intern/cycles/render/nodes.cpp
    branches/soc-2011-tomato/intern/cycles/render/nodes.h
    branches/soc-2011-tomato/source/blender/editors/space_node/drawnode.c
    branches/soc-2011-tomato/source/blender/makesdna/DNA_node_types.h
    branches/soc-2011-tomato/source/blender/makesrna/intern/rna_nodetree.c

Modified: branches/soc-2011-tomato/intern/cycles/blender/blender_shader.cpp
===================================================================
--- branches/soc-2011-tomato/intern/cycles/blender/blender_shader.cpp	2012-07-10 21:45:15 UTC (rev 48821)
+++ branches/soc-2011-tomato/intern/cycles/blender/blender_shader.cpp	2012-07-11 00:08:42 UTC (rev 48822)
@@ -404,6 +404,8 @@
 			if(b_image)
 				image->filename = image_user_file_path(b_image_node.image_user(), b_image, b_scene.frame_current());
 			image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()];
+			image->projection = ImageTextureNode::projection_enum[(int)b_image_node.projection()];
+			image->projection_blend = b_image_node.projection_blend();
 			get_tex_mapping(&image->tex_mapping, b_image_node.texture_mapping());
 			node = image;
 			break;

Modified: branches/soc-2011-tomato/intern/cycles/kernel/svm/svm.h
===================================================================
--- branches/soc-2011-tomato/intern/cycles/kernel/svm/svm.h	2012-07-10 21:45:15 UTC (rev 48821)
+++ branches/soc-2011-tomato/intern/cycles/kernel/svm/svm.h	2012-07-11 00:08:42 UTC (rev 48822)
@@ -220,6 +220,9 @@
 			case NODE_TEX_IMAGE:
 				svm_node_tex_image(kg, sd, stack, node);
 				break;
+			case NODE_TEX_IMAGE_BOX:
+				svm_node_tex_image_box(kg, sd, stack, node);
+				break;
 			case NODE_TEX_ENVIRONMENT:
 				svm_node_tex_environment(kg, sd, stack, node);
 				break;

Modified: branches/soc-2011-tomato/intern/cycles/kernel/svm/svm_image.h
===================================================================
--- branches/soc-2011-tomato/intern/cycles/kernel/svm/svm_image.h	2012-07-10 21:45:15 UTC (rev 48821)
+++ branches/soc-2011-tomato/intern/cycles/kernel/svm/svm_image.h	2012-07-11 00:08:42 UTC (rev 48822)
@@ -50,7 +50,7 @@
 	return x - (float)i;
 }
 
-__device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y)
+__device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, uint srgb)
 {
 	uint4 info = kernel_tex_fetch(__tex_image_packed_info, id);
 	uint width = info.x;
@@ -82,12 +82,18 @@
 	r += ty*(1.0f - tx)*svm_image_texture_read(kg, offset + ix + niy*width);
 	r += ty*tx*svm_image_texture_read(kg, offset + nix + niy*width);
 
+	if(srgb) {
+		r.x = color_srgb_to_scene_linear(r.x);
+		r.y = color_srgb_to_scene_linear(r.y);
+		r.z = color_srgb_to_scene_linear(r.z);
+	}
+
 	return r;
 }
 
 #else
 
-__device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y)
+__device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, uint srgb)
 {
 	float4 r;
 
@@ -206,6 +212,12 @@
 			return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
 	}
 
+	if(srgb) {
+		r.x = color_srgb_to_scene_linear(r.x);
+		r.y = color_srgb_to_scene_linear(r.y);
+		r.z = color_srgb_to_scene_linear(r.z);
+	}
+
 	return r;
 }
 
@@ -219,21 +231,102 @@
 	decode_node_uchar4(node.z, &co_offset, &out_offset, &alpha_offset, &srgb);
 
 	float3 co = stack_load_float3(stack, co_offset);
-	float4 f = svm_image_texture(kg, id, co.x, co.y);
-	float3 r = make_float3(f.x, f.y, f.z);
+	float4 f = svm_image_texture(kg, id, co.x, co.y, srgb);
 
-	if(srgb) {
-		r.x = color_srgb_to_scene_linear(r.x);
-		r.y = color_srgb_to_scene_linear(r.y);
-		r.z = color_srgb_to_scene_linear(r.z);
+	if(stack_valid(out_offset))
+		stack_store_float3(stack, out_offset, make_float3(f.x, f.y, f.z));
+	if(stack_valid(alpha_offset))
+		stack_store_float(stack, alpha_offset, f.w);
+}
+
+__device void svm_node_tex_image_box(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
+{
+	/* get object space normal */
+	float3 N = sd->N;
+
+	N = sd->N;
+	if(sd->object != ~0)
+		object_inverse_normal_transform(kg, sd, &N);
+
+	/* project from direction vector to barycentric coordinates in triangles */
+	N.x = fabsf(N.x);
+	N.y = fabsf(N.y);
+	N.z = fabsf(N.z);
+
+	N /= (N.x + N.y + N.z);
+
+	/* basic idea is to think of this as a triangle, each corner representing
+	 * one of the 3 faces of the cube. in the corners we have single textures,
+	 * in between we blend between two textures, and in the middle we a blend
+	 * between three textures.
+	 *
+	 * the Nxyz values are the barycentric coordinates in an equilateral
+	 * triangle, which in case of blending in the middle has a smaller
+	 * equilateral triangle where 3 textures blend. this divides things into
+	 * 7 zones, with an if() test for each zone */
+
+	float3 weight = make_float3(0.0f, 0.0f, 0.0f);
+	float blend = __int_as_float(node.w);
+	float limit = 0.5f*(1.0f + blend);
+
+	/* first test for corners with single texture */
+	if(N.x > limit*(N.x + N.y) && N.x > limit*(N.x + N.z)) {
+		weight.x = 1.0f;
 	}
+	else if(N.y > limit*(N.x + N.y) && N.y > limit*(N.y + N.z)) {
+		weight.y = 1.0f;
+	}
+	else if(N.z > limit*(N.x + N.z) && N.z > limit*(N.y + N.z)) {
+		weight.z = 1.0f;
+	}
+	else if(blend > 0.0f) {
+		/* in case of blending, test for mixes between two textures */
+		if(N.z < (1.0f - limit)*(N.y + N.x)) {
+			weight.x = N.x/(N.x + N.y);
+			weight.x = clamp((weight.x - 0.5f*(1.0f - blend))/blend, 0.0f, 1.0f);
+			weight.y = 1.0f - weight.x;
+		}
+		else if(N.x < (1.0f - limit)*(N.y + N.z)) {
+			weight.y = N.y/(N.y + N.z);
+			weight.y = clamp((weight.y - 0.5f*(1.0f - blend))/blend, 0.0f, 1.0f);
+			weight.z = 1.0f - weight.y;
+		}
+		else if(N.y < (1.0f - limit)*(N.x + N.z)) {
+			weight.x = N.x/(N.x + N.z);
+			weight.x = clamp((weight.x - 0.5f*(1.0f - blend))/blend, 0.0f, 1.0f);
+			weight.z = 1.0f - weight.x;
+		}
+		else {
+			/* last case, we have a mix between three */
+			weight.x = ((2.0f - limit)*N.x + (limit - 1.0f))/(2.0f*limit - 1.0f);
+			weight.y = ((2.0f - limit)*N.y + (limit - 1.0f))/(2.0f*limit - 1.0f);
+			weight.z = ((2.0f - limit)*N.z + (limit - 1.0f))/(2.0f*limit - 1.0f);
+		}
+	}
 
+	/* now fetch textures */
+	uint co_offset, out_offset, alpha_offset, srgb;
+	decode_node_uchar4(node.z, &co_offset, &out_offset, &alpha_offset, &srgb);
+
+	float3 co = stack_load_float3(stack, co_offset);
+	uint id = node.y;
+
+	float4 f = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+
+	if(weight.x > 0.0f)
+		f += weight.x*svm_image_texture(kg, id, co.y, co.z, srgb);
+	if(weight.y > 0.0f)
+		f += weight.y*svm_image_texture(kg, id, co.x, co.z, srgb);
+	if(weight.z > 0.0f)
+		f += weight.z*svm_image_texture(kg, id, co.y, co.x, srgb);
+
 	if(stack_valid(out_offset))
-		stack_store_float3(stack, out_offset, r);
+		stack_store_float3(stack, out_offset, make_float3(f.x, f.y, f.z));
 	if(stack_valid(alpha_offset))
 		stack_store_float(stack, alpha_offset, f.w);
 }
 
+
 __device void svm_node_tex_environment(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
 {
 	uint id = node.y;
@@ -252,17 +345,10 @@
 	else
 		uv = direction_to_mirrorball(co);
 
-	float4 f = svm_image_texture(kg, id, uv.x, uv.y);
-	float3 r = make_float3(f.x, f.y, f.z);
+	float4 f = svm_image_texture(kg, id, uv.x, uv.y, srgb);
 
-	if(srgb) {
-		r.x = color_srgb_to_scene_linear(r.x);
-		r.y = color_srgb_to_scene_linear(r.y);
-		r.z = color_srgb_to_scene_linear(r.z);
-	}
-
 	if(stack_valid(out_offset))
-		stack_store_float3(stack, out_offset, r);
+		stack_store_float3(stack, out_offset, make_float3(f.x, f.y, f.z));
 	if(stack_valid(alpha_offset))
 		stack_store_float(stack, alpha_offset, f.w);
 }

Modified: branches/soc-2011-tomato/intern/cycles/kernel/svm/svm_types.h
===================================================================
--- branches/soc-2011-tomato/intern/cycles/kernel/svm/svm_types.h	2012-07-10 21:45:15 UTC (rev 48821)
+++ branches/soc-2011-tomato/intern/cycles/kernel/svm/svm_types.h	2012-07-11 00:08:42 UTC (rev 48822)
@@ -40,6 +40,7 @@
 	NODE_MIX_CLOSURE,
 	NODE_JUMP,
 	NODE_TEX_IMAGE,
+	NODE_TEX_IMAGE_BOX,
 	NODE_TEX_SKY,
 	NODE_GEOMETRY,
 	NODE_LIGHT_PATH,

Modified: branches/soc-2011-tomato/intern/cycles/render/nodes.cpp
===================================================================
--- branches/soc-2011-tomato/intern/cycles/render/nodes.cpp	2012-07-10 21:45:15 UTC (rev 48821)
+++ branches/soc-2011-tomato/intern/cycles/render/nodes.cpp	2012-07-11 00:08:42 UTC (rev 48822)
@@ -112,7 +112,18 @@
 	return enm;
 }
 
+static ShaderEnum image_projection_init()
+{
+	ShaderEnum enm;
+
+	enm.insert("Flat", 0);
+	enm.insert("Box", 1);
+
+	return enm;
+}
+
 ShaderEnum ImageTextureNode::color_space_enum = color_space_init();
+ShaderEnum ImageTextureNode::projection_enum = image_projection_init();
 
 ImageTextureNode::ImageTextureNode()
 : TextureNode("image_texture")
@@ -122,6 +133,8 @@
 	is_float = false;
 	filename = "";
 	color_space = ustring("Color");
+	projection = ustring("Flat");;
+	projection_blend = 0.0f;
 
 	add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_UV);
 	add_output("Color", SHADER_SOCKET_COLOR);
@@ -169,13 +182,25 @@
 			tex_mapping.compile(compiler, vector_in->stack_offset, vector_offset);
 		}
 
-		compiler.add_node(NODE_TEX_IMAGE,
-			slot,
-			compiler.encode_uchar4(
-				vector_offset,
-				color_out->stack_offset,
-				alpha_out->stack_offset,
-				srgb));
+		if(projection == "Flat") {
+			compiler.add_node(NODE_TEX_IMAGE,
+				slot,
+				compiler.encode_uchar4(
+					vector_offset,
+					color_out->stack_offset,
+					alpha_out->stack_offset,
+					srgb));
+		}
+		else {
+			compiler.add_node(NODE_TEX_IMAGE_BOX,
+				slot,
+				compiler.encode_uchar4(
+					vector_offset,
+					color_out->stack_offset,
+					alpha_out->stack_offset,
+					srgb),
+				__float_as_int(projection_blend));
+		}
 	
 		if(vector_offset != vector_in->stack_offset)
 			compiler.stack_clear_offset(vector_in->type, vector_offset);
@@ -205,7 +230,7 @@
 
 /* Environment Texture */
 
-static ShaderEnum projection_init()
+static ShaderEnum env_projection_init()
 {
 	ShaderEnum enm;
 
@@ -216,7 +241,7 @@
 }
 
 ShaderEnum EnvironmentTextureNode::color_space_enum = color_space_init();
-ShaderEnum EnvironmentTextureNode::projection_enum = projection_init();
+ShaderEnum EnvironmentTextureNode::projection_enum = env_projection_init();
 
 EnvironmentTextureNode::EnvironmentTextureNode()
 : TextureNode("environment_texture")

Modified: branches/soc-2011-tomato/intern/cycles/render/nodes.h
===================================================================
--- branches/soc-2011-tomato/intern/cycles/render/nodes.h	2012-07-10 21:45:15 UTC (rev 48821)
+++ branches/soc-2011-tomato/intern/cycles/render/nodes.h	2012-07-11 00:08:42 UTC (rev 48822)
@@ -70,8 +70,11 @@
 	bool is_float;
 	string filename;
 	ustring color_space;
+	ustring projection;

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list