Commit: e7d8908f1405bbe54df2b5b51b4c1078200e5020
Author: Clément Foucault
Date:   Fri Jul 20 15:25:20 2018 +0200
Branches: blender2.8
https://developer.blender.org/rBe7d8908f1405bbe54df2b5b51b4c1078200e5020

GPUMaterial: Optimize and fix blending in box mapping

Blending was done in srgb space and was not matching cycles.

Optimized by using less branches and more vector operations.

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

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 d1183c792f5..4b376160105 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -1804,18 +1804,46 @@ void node_tex_image(vec3 co, sampler2D ima, out vec4 
color, out float alpha)
        alpha = color.a;
 }
 
+void tex_box_sample(vec3 texco,
+                    vec3 N,
+                    sampler2D ima,
+                    out vec4 color1,
+                    out vec4 color2,
+                    out vec4 color3)
+{
+       /* X projection */
+       vec2 uv = texco.yz;
+       if (N.x < 0.0) {
+               uv.x = 1.0 - uv.x;
+       }
+       color1 = texture(ima, uv);
+       /* Y projection */
+       uv = texco.xz;
+       if (N.y > 0.0) {
+               uv.x = 1.0 - uv.x;
+       }
+       color2 = texture(ima, uv);
+       /* Z projection */
+       uv = texco.yx;
+       if (N.z > 0.0) {
+               uv.x = 1.0 - uv.x;
+       }
+       color3 = texture(ima, uv);
+}
+
 void node_tex_image_box(vec3 texco,
                         vec3 N,
+                        vec4 color1,
+                        vec4 color2,
+                        vec4 color3,
                         sampler2D ima,
                         float blend,
                         out vec4 color,
                         out float alpha)
 {
-       vec3 signed_N = N;
-
        /* project from direction vector to barycentric coordinates in 
triangles */
-       N = vec3(abs(N.x), abs(N.y), abs(N.z));
-       N /= (N.x + N.y + N.z);
+       N = abs(N);
+       N /= dot(N, vec3(1.0));
 
        /* 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,
@@ -1825,72 +1853,36 @@ void node_tex_image_box(vec3 texco,
         * 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 */
+        * 7 zones, with an if () test for each zone
+        * EDIT: Now there is only 4 if's. */
 
-       vec3 weight = vec3(0.0, 0.0, 0.0);
-       float limit = 0.5 * (1.0 + blend);
+       float limit = 0.5 + 0.5 * 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.0;
-       }
-       else if (N.y > limit * (N.x + N.y) && N.y > limit * (N.y + N.z)) {
-               weight.y = 1.0;
+       vec3 weight;
+       weight.x = N.x / (N.x + N.y);
+       weight.y = N.y / (N.y + N.z);
+       weight.z = N.z / (N.x + N.z);
+       weight = clamp((weight - 0.5 * (1.0 - blend)) / max(1e-8, blend), 0.0, 
1.0);
+
+       /* test for mixes between two textures */
+       if (N.z < (1.0 - limit) * (N.y + N.x)) {
+               weight.z = 0.0;
+               weight.y = 1.0 - weight.x;
        }
-       else if (N.z > limit * (N.x + N.z) && N.z > limit * (N.y + N.z)) {
-               weight.z = 1.0;
+       else if (N.x < (1.0 - limit) * (N.y + N.z)) {
+               weight.x = 0.0;
+               weight.z = 1.0 - weight.y;
        }
-       else if (blend > 0.0) {
-               /* in case of blending, test for mixes between two textures */
-               if (N.z < (1.0 - limit) * (N.y + N.x)) {
-                       weight.x = N.x / (N.x + N.y);
-                       weight.x = clamp((weight.x - 0.5 * (1.0 - blend)) / 
blend, 0.0, 1.0);
-                       weight.y = 1.0 - weight.x;
-               }
-               else if (N.x < (1.0 - limit) * (N.y + N.z)) {
-                       weight.y = N.y / (N.y + N.z);
-                       weight.y = clamp((weight.y - 0.5 * (1.0 - blend)) / 
blend, 0.0, 1.0);
-                       weight.z = 1.0 - weight.y;
-               }
-               else if (N.y < (1.0 - limit) * (N.x + N.z)) {
-                       weight.x = N.x / (N.x + N.z);
-                       weight.x = clamp((weight.x - 0.5 * (1.0 - blend)) / 
blend, 0.0, 1.0);
-                       weight.z = 1.0 - weight.x;
-               }
-               else {
-                       /* last case, we have a mix between three */
-                       weight.x = ((2.0 - limit) * N.x + (limit - 1.0)) / (2.0 
* limit - 1.0);
-                       weight.y = ((2.0 - limit) * N.y + (limit - 1.0)) / (2.0 
* limit - 1.0);
-                       weight.z = ((2.0 - limit) * N.z + (limit - 1.0)) / (2.0 
* limit - 1.0);
-               }
+       else if (N.y < (1.0 - limit) * (N.x + N.z)) {
+               weight.y = 0.0;
+               weight.x = 1.0 - weight.z;
        }
        else {
-               /* Desperate mode, no valid choice anyway, fallback to one 
side.*/
-               weight.x = 1.0;
-       }
-       color = vec4(0);
-       if (weight.x > 0.0) {
-               vec2 uv = texco.yz;
-               if(signed_N.x < 0.0) {
-                       uv.x = 1.0 - uv.x;
-               }
-               color += weight.x * texture(ima, uv);
-       }
-       if (weight.y > 0.0) {
-               vec2 uv = texco.xz;
-               if(signed_N.y > 0.0) {
-                       uv.x = 1.0 - uv.x;
-               }
-               color += weight.y * texture(ima, uv);
-       }
-       if (weight.z > 0.0) {
-               vec2 uv = texco.yx;
-               if(signed_N.z > 0.0) {
-                       uv.x = 1.0 - uv.x;
-               }
-               color += weight.z * texture(ima, uv);
+               /* last case, we have a mix between three */
+               weight = ((2.0 - limit) * N + (limit - 1.0)) / max(1e-8, 2.0 * 
limit - 1.0);
        }
 
+       color = weight.x * color1 + weight.y * color2 + weight.z * color3;
        alpha = color.a;
 }
 
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 2bbe3617bee..20753445aa6 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
@@ -58,8 +58,9 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode 
*node, bNodeExecDat
        Image *ima = (Image *)node->id;
        ImageUser *iuser = NULL;
        NodeTexImage *tex = node->storage;
+       bool do_color_correction = false;
 
-       GPUNodeLink *norm;
+       GPUNodeLink *norm, *col1, *col2, *col3;
 
        int isdata = tex->color_space == SHD_COLORSPACE_NONE;
        float blend = tex->projection_blend;
@@ -67,6 +68,15 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode 
*node, bNodeExecDat
        if (!ima)
                return GPU_stack_link(mat, node, "node_tex_image_empty", in, 
out);
 
+       ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
+       if ((tex->color_space == SHD_COLORSPACE_COLOR) &&
+           ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 &&
+           GPU_material_do_color_management(mat))
+       {
+               do_color_correction = true;
+       }
+       BKE_image_release_ibuf(ima, ibuf, NULL);
+
        if (!in[0].link)
                in[0].link = GPU_attribute(CD_MTFACE, "");
 
@@ -83,8 +93,20 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode 
*node, bNodeExecDat
                        GPU_link(mat, "direction_transform_m4v3", norm,
                                                                  
GPU_builtin(GPU_INVERSE_OBJECT_MATRIX),
                                                                  &norm);
+                       GPU_link(mat, "tex_box_sample", in[0].link,
+                                                       norm,
+                                                       GPU_image(ima, iuser, 
isdata),
+                                                       &col1,
+                                                       &col2,
+                                                       &col3);
+                       if (do_color_correction) {
+                               GPU_link(mat, "srgb_to_linearrgb", col1, &col1);
+                               GPU_link(mat, "srgb_to_linearrgb", col2, &col2);
+                               GPU_link(mat, "srgb_to_linearrgb", col3, &col3);
+                       }
                        GPU_link(mat, "node_tex_image_box", in[0].link,
                                                            norm,
+                                                           col1, col2, col3,
                                                            GPU_image(ima, 
iuser, isdata),
                                                            GPU_uniform(&blend),
                                                            &out[0].link,
@@ -102,14 +124,9 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, 
bNode *node, bNodeExecDat
                        break;
        }
 
-       ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
-       if ((tex->color_space == SHD_COLORSPACE_COLOR) &&
-           ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 &&
-           GPU_material_do_color_management(mat))
-       {
+       if (do_color_correction && (tex->projection != SHD_PROJ_BOX)) {
                GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link);
        }
-       BKE_image_release_ibuf(ima, ibuf, NULL);
 
        return true;
 }

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to