[Bf-blender-cvs] [1f6d1213d27] master: Workbench: Use eGPUSamplerState to change texture sampling behavior

Clément Foucault noreply at git.blender.org
Mon Jun 8 10:58:56 CEST 2020


Commit: 1f6d1213d27cbe3e50460aa6da54e0c7606f2216
Author: Clément Foucault
Date:   Mon Jun 8 10:58:45 2020 +0200
Branches: master
https://developer.blender.org/rB1f6d1213d27cbe3e50460aa6da54e0c7606f2216

Workbench: Use eGPUSamplerState to change texture sampling behavior

This removes some fragment shader hacks and improve the support of
different repeat & filtering modes.

This fix T77453 Image texture not repeating in viewport

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

M	source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl
M	source/blender/draw/engines/workbench/workbench_engine.c
M	source/blender/draw/engines/workbench/workbench_materials.c
M	source/blender/draw/engines/workbench/workbench_private.h
M	source/blender/draw/intern/DRW_render.h
M	source/blender/draw/intern/draw_manager_data.c

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

diff --git a/source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl
index e45f7a7b9e3..c5ad48191d1 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl
@@ -4,17 +4,20 @@ bool node_tex_tile_lookup(inout vec3 co, sampler2DArray ima, sampler1DArray map)
 {
   vec2 tile_pos = floor(co.xy);
 
-  if (tile_pos.x < 0 || tile_pos.y < 0 || tile_pos.x >= 10)
+  if (tile_pos.x < 0 || tile_pos.y < 0 || tile_pos.x >= 10) {
     return false;
+  }
 
   float tile = 10.0 * tile_pos.y + tile_pos.x;
-  if (tile >= textureSize(map, 0).x)
+  if (tile >= textureSize(map, 0).x) {
     return false;
+  }
 
   /* Fetch tile information. */
   float tile_layer = texelFetch(map, ivec2(tile, 0), 0).x;
-  if (tile_layer < 0.0)
+  if (tile_layer < 0.0) {
     return false;
+  }
 
   vec4 tile_info = texelFetch(map, ivec2(tile, 1), 0);
 
@@ -22,59 +25,29 @@ bool node_tex_tile_lookup(inout vec3 co, sampler2DArray ima, sampler1DArray map)
   return true;
 }
 
-vec4 workbench_sample_texture(sampler2D image, vec2 coord, bool nearest_sampling)
-{
-  /* TODO(fclem) We could do the same with sampler objects.
-   * But this is a quick workaround instead of messing with the GPUTexture itself. */
-  if (nearest_sampling) {
-    /* Use texelFetch for nearest_sampling to reduce glitches. See: T73726 */
-    vec2 tex_size = vec2(textureSize(image, 0).xy);
-    ivec2 uv = ivec2(floor(coord * tex_size) + 0.5);
-    return texelFetch(image, uv, 0);
-  }
-  else {
-    return texture(image, coord);
-  }
-}
-
-vec4 workbench_sample_texture_array(sampler2DArray tile_array,
-                                    sampler1DArray tile_data,
-                                    vec2 coord,
-                                    bool nearest_sampling)
-{
-
-  vec3 uv = vec3(coord, 0);
-  if (!node_tex_tile_lookup(uv, tile_array, tile_data))
-    return vec4(1.0, 0.0, 1.0, 1.0);
-
-  /* TODO(fclem) We could do the same with sampler objects.
-   * But this is a quick workaround instead of messing with the GPUTexture itself. */
-  if (nearest_sampling) {
-    /* Use texelFetch for nearest_sampling to reduce glitches. See: T73726 */
-    vec3 tex_size = vec3(textureSize(tile_array, 0));
-    uv.xy = floor(uv.xy * tex_size.xy) + 0.5;
-    return texelFetch(tile_array, ivec3(uv), 0);
-  }
-  else {
-    return texture(tile_array, uv);
-  }
-}
-
 uniform sampler2DArray imageTileArray;
 uniform sampler1DArray imageTileData;
 uniform sampler2D imageTexture;
 
 uniform float imageTransparencyCutoff = 0.1;
-uniform bool imageNearest;
 uniform bool imagePremult;
 
 vec3 workbench_image_color(vec2 uvs)
 {
 #ifdef V3D_SHADING_TEXTURE_COLOR
+  vec4 color;
+
 #  ifdef TEXTURE_IMAGE_ARRAY
-  vec4 color = workbench_sample_texture_array(imageTileArray, imageTileData, uvs, imageNearest);
+  vec3 co = vec3(uvs, 0.0);
+  if (node_tex_tile_lookup(co, imageTileArray, imageTileData)) {
+    color = texture(imageTileArray, co);
+  }
+  else {
+    color = vec4(1.0, 0.0, 1.0, 1.0);
+  }
 #  else
-  vec4 color = workbench_sample_texture(imageTexture, uvs, imageNearest);
+
+  color = texture(imageTexture, uvs);
 #  endif
 
   /* Unpremultiply if stored multiplied, since straight alpha is expected by shaders. */
@@ -90,6 +63,7 @@ vec3 workbench_image_color(vec2 uvs)
 
   return color.rgb;
 #else
+
   return vec3(1.0);
 #endif
 }
diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c
index 511dd563b46..bc5a2c14538 100644
--- a/source/blender/draw/engines/workbench/workbench_engine.c
+++ b/source/blender/draw/engines/workbench/workbench_engine.c
@@ -141,10 +141,10 @@ static void workbench_cache_texpaint_populate(WORKBENCH_PrivateData *wpd, Object
     struct GPUBatch *geom = DRW_cache_mesh_surface_texpaint_single_get(ob);
     if (geom) {
       Image *ima = imapaint->canvas;
-      int interp = (imapaint->interp == IMAGEPAINT_INTERP_LINEAR) ? SHD_INTERP_LINEAR :
-                                                                    SHD_INTERP_CLOSEST;
+      eGPUSamplerState state = GPU_SAMPLER_REPEAT;
+      SET_FLAG_FROM_TEST(state, imapaint->interp == IMAGEPAINT_INTERP_LINEAR, GPU_SAMPLER_FILTER);
 
-      DRWShadingGroup *grp = workbench_image_setup(wpd, ob, 0, ima, NULL, interp);
+      DRWShadingGroup *grp = workbench_image_setup(wpd, ob, 0, ima, NULL, state);
       DRW_shgroup_call(grp, geom, ob);
     }
   }
@@ -210,10 +210,10 @@ static void workbench_cache_hair_populate(WORKBENCH_PrivateData *wpd,
 
   const ImagePaintSettings *imapaint = use_texpaint_mode ? &scene->toolsettings->imapaint : NULL;
   Image *ima = (imapaint && imapaint->mode == IMAGEPAINT_MODE_IMAGE) ? imapaint->canvas : NULL;
-  int interp = (imapaint && imapaint->interp == IMAGEPAINT_INTERP_LINEAR) ? SHD_INTERP_LINEAR :
-                                                                            SHD_INTERP_CLOSEST;
+  eGPUSamplerState state = 0;
+  SET_FLAG_FROM_TEST(state, imapaint->interp == IMAGEPAINT_INTERP_LINEAR, GPU_SAMPLER_FILTER);
   DRWShadingGroup *grp = (use_texpaint_mode) ?
-                             workbench_image_hair_setup(wpd, ob, matnr, ima, NULL, interp) :
+                             workbench_image_hair_setup(wpd, ob, matnr, ima, NULL, state) :
                              workbench_material_hair_setup(wpd, ob, matnr, color_type);
 
   DRW_shgroup_hair_create_sub(ob, psys, md, grp);
diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c
index b36a4a3a494..0b2d508fee5 100644
--- a/source/blender/draw/engines/workbench/workbench_materials.c
+++ b/source/blender/draw/engines/workbench/workbench_materials.c
@@ -101,31 +101,34 @@ BLI_INLINE Material *workbench_object_material_get(Object *ob, int mat_nr)
 }
 
 BLI_INLINE void workbench_material_get_image(
-    Object *ob, int mat_nr, Image **r_image, ImageUser **r_iuser, int *r_interp)
+    Object *ob, int mat_nr, Image **r_image, ImageUser **r_iuser, eGPUSamplerState *r_sampler)
 {
   bNode *node;
+  *r_sampler = 0;
 
   ED_object_get_active_image(ob, mat_nr, r_image, r_iuser, &node, NULL);
   if (node && *r_image) {
     switch (node->type) {
       case SH_NODE_TEX_IMAGE: {
         NodeTexImage *storage = node->storage;
-        *r_interp = storage->interpolation;
+        const bool use_filter = (storage->interpolation != SHD_INTERP_CLOSEST);
+        const bool use_repeat = (storage->extension == SHD_IMAGE_EXTENSION_REPEAT);
+        const bool use_clip = (storage->extension == SHD_IMAGE_EXTENSION_CLIP);
+        SET_FLAG_FROM_TEST(*r_sampler, use_filter, GPU_SAMPLER_FILTER);
+        SET_FLAG_FROM_TEST(*r_sampler, use_repeat, GPU_SAMPLER_REPEAT);
+        SET_FLAG_FROM_TEST(*r_sampler, use_clip, GPU_SAMPLER_CLAMP_BORDER);
         break;
       }
       case SH_NODE_TEX_ENVIRONMENT: {
         NodeTexEnvironment *storage = node->storage;
-        *r_interp = storage->interpolation;
+        const bool use_filter = (storage->interpolation != SHD_INTERP_CLOSEST);
+        SET_FLAG_FROM_TEST(*r_sampler, use_filter, GPU_SAMPLER_FILTER);
         break;
       }
       default:
         BLI_assert(!"Node type not supported by workbench");
-        *r_interp = 0;
     }
   }
-  else {
-    *r_interp = 0;
-  }
 }
 
 /* Return true if the current material ubo has changed and needs to be rebind. */
@@ -164,11 +167,11 @@ DRWShadingGroup *workbench_material_setup_ex(WORKBENCH_PrivateData *wpd,
 {
   Image *ima = NULL;
   ImageUser *iuser = NULL;
-  int interp;
+  eGPUSamplerState sampler;
   const bool infront = (ob->dtx & OB_DRAWXRAY) != 0;
 
   if (color_type == V3D_SHADING_TEXTURE_COLOR) {
-    workbench_material_get_image(ob, mat_nr, &ima, &iuser, &interp);
+    workbench_material_get_image(ob, mat_nr, &ima, &iuser, &sampler);
     if (ima == NULL) {
       /* Fallback to material color. */
       color_type = V3D_SHADING_MATERIAL_COLOR;
@@ -177,7 +180,7 @@ DRWShadingGroup *workbench_material_setup_ex(WORKBENCH_PrivateData *wpd,
 
   switch (color_type) {
     case V3D_SHADING_TEXTURE_COLOR: {
-      return workbench_image_setup_ex(wpd, ob, mat_nr, ima, iuser, interp, hair);
+      return workbench_image_setup_ex(wpd, ob, mat_nr, ima, iuser, sampler, hair);
     }
     case V3D_SHADING_MATERIAL_COLOR: {
       /* For now, we use the same ubo for material and object coloring but with different indices.
@@ -247,13 +250,13 @@ DRWShadingGroup *workbench_image_setup_ex(WORKBENCH_PrivateData *wpd,
                                           int mat_nr,
                                           Image *ima,
                                           ImageUser *iuser,
-                                          int interp,
+                                          eGPUSamplerState sampler,
                                           bool hair)
 {
   GPUTexture *tex = NULL, *tex_tile_data = NULL;
 
   if (ima == NULL) {
-    workbench_material_get_image(ob, mat_nr, &ima, &iuser, &interp);
+    workbench_material_get_image(ob, mat_nr, &ima, &iuser, &sampler);
   }
 
   if (ima) {
@@ -284,13 +287,12 @@ DRWShadingGroup *workbench_image_setup_ex(WORKBENCH_PrivateData *wpd,
 
   *grp_tex = grp = DRW_shgroup_create_sub(grp);
   if (tex_tile_data) {
-    DRW_shgroup_uniform_texture(grp, "imageTileArray", tex);
+    DRW_shgroup_uniform_texture_ex(grp, "imageTileArray", tex, sampler);
     DRW_shgroup_uniform_texture(grp, "imageTileData", tex_tile_data);
   }
   else {
-    DRW_shgroup_uniform_texture(grp, "imageTexture", tex);
+    DRW_shgroup_uniform_texture_ex(grp, "imageTexture", tex, sampler);
   }
   DRW_shgroup_uniform_bool_copy(grp, "imagePremult", (ima && ima->alpha_mode == IMA_ALPHA_PREMUL));
-  DRW_shgroup_uniform_bool_copy(grp, "imageNearest", (interp == SHD_INTERP_CLOSEST));
   return grp;
 }
diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h
index 967bdf9bae0..20b6d368ac0 100644
--- a/source/blender/draw/engines/workbench/workbench_private.h
+++ b/source/blender/draw/eng

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list