[Bf-blender-cvs] [e0edac4cb27] blender2.8: Eevee: Support for extension type in the Node Image Texture

Clément Foucault noreply at git.blender.org
Wed Nov 7 22:16:18 CET 2018


Commit: e0edac4cb27ddacc22bcbf7a628d58bb0eb9e9bf
Author: Clément Foucault
Date:   Wed Nov 7 19:40:24 2018 +0100
Branches: blender2.8
https://developer.blender.org/rBe0edac4cb27ddacc22bcbf7a628d58bb0eb9e9bf

Eevee: Support for extension type in the Node Image Texture

This does not work with the box projection mode. Implementing for box
projection mode would be difficult, slow, and produce a lot of code
duplication. Also i'm not sure this is worth it, as it's not a common use
case.

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

M	source/blender/gpu/shaders/gpu_shader_material.glsl
M	source/blender/nodes/shader/nodes/node_shader_tex_image.c

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

diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index eebc19328b2..3983a8c3f32 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -207,6 +207,12 @@ void point_texco_remap_square(vec3 vin, out vec3 vout)
 	vout = vec3(vin - vec3(0.5, 0.5, 0.5)) * 2.0;
 }
 
+void point_texco_clamp(vec3 vin, sampler2D ima, out vec3 vout)
+{
+	vec2 half_texel_size = 0.5 / vec2(textureSize(ima, 0).xy);
+	vout = clamp(vin, half_texel_size.xyy, 1.0 - half_texel_size.xyy);
+}
+
 void point_map_to_sphere(vec3 vin, out vec3 vout)
 {
 	float len = length(vin);
@@ -2020,21 +2026,27 @@ void node_tex_image_nearest(vec3 co, sampler2D ima, out vec4 color, out float al
 	alpha = color.a;
 }
 
-void node_tex_image_cubic(vec3 co, sampler2D ima, out vec4 color, out float alpha)
+/* @arg f: signed distance to texel center. */
+void cubic_bspline_coefs(vec2 f, out vec2 w0, out vec2 w1, out vec2 w2, out vec2 w3)
+{
+	vec2 f2 = f * f;
+	vec2 f3 = f2 * f;
+	/* Bspline coefs (optimized) */
+	w3 =  f3 / 6.0;
+	w0 = -w3       + f2 * 0.5 - f * 0.5 + 1.0 / 6.0;
+	w1 =  f3 * 0.5 - f2 * 1.0           + 2.0 / 3.0;
+	w2 = 1.0 - w0 - w1 - w3;
+}
+
+void node_tex_image_cubic_ex(vec3 co, sampler2D ima, float do_extend, out vec4 color, out float alpha)
 {
 	vec2 tex_size = vec2(textureSize(ima, 0).xy);
 
 	co.xy *= tex_size;
 	/* texel center */
 	vec2 tc = floor(co.xy - 0.5) + 0.5;
-	vec2 f = co.xy - tc;
-	vec2 f2 = f * f;
-	vec2 f3 = f2 * f;
-	/* Bspline coefs (optimized) */
-	vec2 w3 =  f3 / 6.0;
-	vec2 w0 = -w3       + f2 * 0.5 - f * 0.5 + 1.0 / 6.0;
-	vec2 w1 =  f3 * 0.5 - f2 * 1.0           + 2.0 / 3.0;
-	vec2 w2 = 1.0 - w0 - w1 - w3;
+	vec2 w0, w1, w2, w3;
+	cubic_bspline_coefs(co.xy - tc, w0, w1, w2, w3);
 
 #if 1 /* Optimized version using 4 filtered tap. */
 	vec2 s0 = w0 + w1;
@@ -2047,12 +2059,15 @@ void node_tex_image_cubic(vec3 co, sampler2D ima, out vec4 color, out float alph
 	final_co.xy = tc - 1.0 + f0;
 	final_co.zw = tc + 1.0 + f1;
 
+	if (do_extend == 1.0) {
+		final_co = clamp(final_co, vec4(0.5), tex_size.xyxy - 0.5);
+	}
 	final_co /= tex_size.xyxy;
 
-	color  = texture(ima, final_co.xy) * s0.x * s0.y;
-	color += texture(ima, final_co.zy) * s1.x * s0.y;
-	color += texture(ima, final_co.xw) * s0.x * s1.y;
-	color += texture(ima, final_co.zw) * s1.x * s1.y;
+	color  = textureLod(ima, final_co.xy, 0.0) * s0.x * s0.y;
+	color += textureLod(ima, final_co.zy, 0.0) * s1.x * s0.y;
+	color += textureLod(ima, final_co.xw, 0.0) * s0.x * s1.y;
+	color += textureLod(ima, final_co.zw, 0.0) * s1.x * s1.y;
 
 #else /* Reference bruteforce 16 tap. */
 	color  = texelFetch(ima, ivec2(tc + vec2(-1.0, -1.0)), 0) * w0.x * w0.y;
@@ -2079,10 +2094,20 @@ void node_tex_image_cubic(vec3 co, sampler2D ima, out vec4 color, out float alph
 	alpha = color.a;
 }
 
+void node_tex_image_cubic(vec3 co, sampler2D ima, out vec4 color, out float alpha)
+{
+	node_tex_image_cubic_ex(co, ima, 0.0, color, alpha);
+}
+
+void node_tex_image_cubic_extend(vec3 co, sampler2D ima, out vec4 color, out float alpha)
+{
+	node_tex_image_cubic_ex(co, ima, 1.0, color, alpha);
+}
+
 void node_tex_image_smart(vec3 co, sampler2D ima, out vec4 color, out float alpha)
 {
 	/* use cubic for now */
-	node_tex_image_cubic(co, ima, color, alpha);
+	node_tex_image_cubic_ex(co, ima, 0.0, color, alpha);
 }
 
 void tex_box_sample_linear(vec3 texco,
@@ -2155,19 +2180,19 @@ void tex_box_sample_cubic(vec3 texco,
 	if (N.x < 0.0) {
 		uv.x = 1.0 - uv.x;
 	}
-	node_tex_image_cubic(uv.xyy, ima, color1, alpha);
+	node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color1, alpha);
 	/* Y projection */
 	uv = texco.xz;
 	if (N.y > 0.0) {
 		uv.x = 1.0 - uv.x;
 	}
-	node_tex_image_cubic(uv.xyy, ima, color2, alpha);
+	node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color2, alpha);
 	/* Z projection */
 	uv = texco.yx;
 	if (N.z > 0.0) {
 		uv.x = 1.0 - uv.x;
 	}
-	node_tex_image_cubic(uv.xyy, ima, color3, alpha);
+	node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color3, alpha);
 }
 
 void tex_box_sample_smart(vec3 texco,
@@ -2235,6 +2260,69 @@ void node_tex_image_box(vec3 texco,
 	alpha = color.a;
 }
 
+void tex_clip_linear(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha)
+{
+	vec2 tex_size = vec2(textureSize(ima, 0).xy);
+	vec2 minco = min(co.xy, 1.0 - co.xy);
+	minco = clamp(minco * tex_size + 0.5, 0.0, 1.0);
+	float fac = minco.x * minco.y;
+
+	color = mix(vec4(0.0), icolor, fac);
+	alpha = color.a;
+}
+
+void tex_clip_nearest(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha)
+{
+	vec4 minco = vec4(co.xy, 1.0 - co.xy);
+	color = (any(lessThan(minco, vec4(0.0)))) ? vec4(0.0) : icolor;
+	alpha = color.a;
+}
+
+void tex_clip_cubic(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha)
+{
+	vec2 tex_size = vec2(textureSize(ima, 0).xy);
+
+	co.xy *= tex_size;
+	/* texel center */
+	vec2 tc = floor(co.xy - 0.5) + 0.5;
+	vec2 w0, w1, w2, w3;
+	cubic_bspline_coefs(co.xy - tc, w0, w1, w2, w3);
+
+	/* TODO Optimize this part. I'm sure there is a smarter way to do that.
+	 * Could do that when sampling? */
+#define CLIP_CUBIC_SAMPLE(samp, size) (float(all(greaterThan(samp, vec2(-0.5)))) * float(all(lessThan(ivec2(samp), itex_size))))
+	ivec2 itex_size = textureSize(ima, 0).xy;
+	float fac;
+	fac  = CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, -1.0), itex_size) * w0.x * w0.y;
+	fac += CLIP_CUBIC_SAMPLE(tc + vec2( 0.0, -1.0), itex_size) * w1.x * w0.y;
+	fac += CLIP_CUBIC_SAMPLE(tc + vec2( 1.0, -1.0), itex_size) * w2.x * w0.y;
+	fac += CLIP_CUBIC_SAMPLE(tc + vec2( 2.0, -1.0), itex_size) * w3.x * w0.y;
+
+	fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0,  0.0), itex_size) * w0.x * w1.y;
+	fac += CLIP_CUBIC_SAMPLE(tc + vec2( 0.0,  0.0), itex_size) * w1.x * w1.y;
+	fac += CLIP_CUBIC_SAMPLE(tc + vec2( 1.0,  0.0), itex_size) * w2.x * w1.y;
+	fac += CLIP_CUBIC_SAMPLE(tc + vec2( 2.0,  0.0), itex_size) * w3.x * w1.y;
+
+	fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0,  1.0), itex_size) * w0.x * w2.y;
+	fac += CLIP_CUBIC_SAMPLE(tc + vec2( 0.0,  1.0), itex_size) * w1.x * w2.y;
+	fac += CLIP_CUBIC_SAMPLE(tc + vec2( 1.0,  1.0), itex_size) * w2.x * w2.y;
+	fac += CLIP_CUBIC_SAMPLE(tc + vec2( 2.0,  1.0), itex_size) * w3.x * w2.y;
+
+	fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0,  2.0), itex_size) * w0.x * w3.y;
+	fac += CLIP_CUBIC_SAMPLE(tc + vec2( 0.0,  2.0), itex_size) * w1.x * w3.y;
+	fac += CLIP_CUBIC_SAMPLE(tc + vec2( 1.0,  2.0), itex_size) * w2.x * w3.y;
+	fac += CLIP_CUBIC_SAMPLE(tc + vec2( 2.0,  2.0), itex_size) * w3.x * w3.y;
+#undef CLIP_CUBIC_SAMPLE
+
+	color = mix(vec4(0.0), icolor, fac);
+	alpha = color.a;
+}
+
+void tex_clip_smart(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha)
+{
+	tex_clip_cubic(co, ima, icolor, color, alpha);
+}
+
 void node_tex_image_empty(vec3 co, out vec4 color, out float alpha)
 {
 	color = vec4(0.0);
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
index 9782df2638f..24ad28289c1 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
@@ -67,6 +67,12 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecDat
 	    "tex_box_sample_cubic",
 	    "tex_box_sample_smart"
 	};
+	static const char *names_clip[] = {
+	    "tex_clip_linear",
+	    "tex_clip_nearest",
+	    "tex_clip_cubic",
+	    "tex_clip_smart"
+	};
 
 	Image *ima = (Image *)node->id;
 	ImageUser *iuser = NULL;
@@ -75,8 +81,18 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecDat
 	                             ? names_box[tex->interpolation]
 	                             : names[tex->interpolation];
 	bool do_color_correction = false;
+	bool do_texco_extend = (tex->extension != SHD_IMAGE_EXTENSION_REPEAT);
+	const bool do_texco_clip = (tex->extension == SHD_IMAGE_EXTENSION_CLIP);
+
+	if (do_texco_extend && (tex->projection != SHD_PROJ_BOX) &&
+		ELEM(tex->interpolation, SHD_INTERP_CUBIC, SHD_INTERP_SMART))
+	{
+		gpu_node_name = "node_tex_image_cubic_extend";
+		/* We do it inside the sampling function */
+		do_texco_extend = false;
+	}
 
-	GPUNodeLink *norm, *col1, *col2, *col3;
+	GPUNodeLink *norm, *col1, *col2, *col3, *input_coords;
 
 	int isdata = tex->color_space == SHD_COLORSPACE_NONE;
 	float blend = tex->projection_blend;
@@ -100,6 +116,12 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecDat
 
 	switch (tex->projection) {
 		case SHD_PROJ_FLAT:
+			if (do_texco_clip) {
+				GPU_link(mat, "set_rgb", in[0].link, &input_coords);
+			}
+			if (do_texco_extend) {
+				GPU_link(mat, "point_texco_clamp", in[0].link, GPU_image(ima, iuser, isdata), &in[0].link);
+			}
 			GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser, isdata));
 			break;
 		case SHD_PROJ_BOX:
@@ -131,15 +153,33 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecDat
 		case SHD_PROJ_SPHERE:
 			GPU_link(mat, "point_texco_remap_square", in[0].link, &in[0].link);
 			GPU_link(mat, "point_map_to_sphere", in[0].link, &in[0].link);
+			if (do_texco_clip) {
+				GPU_link(mat, "set_rgb", in[0].link, &input_coords);
+			}
+			if (do_texco_extend) {
+				GPU_link(mat, "point_texco_clamp", in[0].link, GPU_image(ima, iuser, isdata), &in[0].link);
+			}
 			GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser, isdata));
 			break;
 		case SHD_PROJ_TUBE:
 			GPU_link(mat, "point_texco_remap_square", in[0].link, &in[0].link);
 			GPU_link(mat, "point_map_to_tube", in[0].link, &in[0].link);
+			if (do_texco_clip) {
+				GPU_link(mat, "set_rgb", in[0].link, &input_coords);
+			}
+			if (do_texco_extend) {
+				GPU_link(mat, "point_texco_clamp", in[0].link, GPU_image(ima, iuser, isdata), &in[0].link);
+			}
 			GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser, isdata));
 			break;
 	}
 
+	if (do_texco_clip && (tex->projection != SHD_PROJ_BOX)) {
+		GPU_link(mat, names_clip[tex->interpolation],
+		         input_coords, GPU_image(ima, iuser, isdata), out[0].link,
+		         &out[0].link, &out[1].link);
+	}
+
 	if (do_color_c

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list