Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2020-06-03 17:18:28 +0300
committerClément Foucault <foucault.clem@gmail.com>2020-06-03 17:18:50 +0300
commitb2dcff4c21a645fa16ca39484d206a38944168d2 (patch)
treeda30f1d9208033668478fa872029d1f7743c0a6d /source/blender/nodes/shader/nodes/node_shader_tex_image.c
parent054923c8607c804a717cb5bb8ef15c0d4b151df3 (diff)
GPUMaterial: Rework/simplify image texture filtering
This use the latest GPUTexture change to use the sampler state to avoid the pole issues instead of using GLSL hacks. This should fix T73942: Eevee mipmaps not respecting border mode. Note that this also fix some discrepencies between cycles and eevee (like boxmapping + clip).
Diffstat (limited to 'source/blender/nodes/shader/nodes/node_shader_tex_image.c')
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_image.c183
1 files changed, 55 insertions, 128 deletions
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 87114fe23b5..b349555efe8 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
@@ -19,6 +19,8 @@
#include "../node_shader_util.h"
+#include "GPU_draw.h"
+
/* **************** OUTPUT ******************** */
static bNodeSocketTemplate sh_node_tex_image_in[] = {
@@ -57,31 +59,6 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
GPUNodeStack *in,
GPUNodeStack *out)
{
- static const char *names[] = {
- "node_tex_image_linear",
- "node_tex_image_nearest",
- "node_tex_image_cubic",
- "node_tex_image_smart",
- };
- static const char *names_tiled[] = {
- "node_tex_tile_linear",
- "node_tex_tile_nearest",
- "node_tex_tile_cubic",
- "node_tex_tile_smart",
- };
- static const char *names_box[] = {
- "tex_box_sample_linear",
- "tex_box_sample_nearest",
- "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;
NodeTexImage *tex = node->storage;
@@ -91,26 +68,11 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
NodeTexImage *tex_original = node_original->storage;
ImageUser *iuser = &tex_original->iuser;
- const char *gpu_node_name = (tex->projection == SHD_PROJ_BOX) ? names_box[tex->interpolation] :
- names[tex->interpolation];
- 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, *input_coords, *gpu_image;
- GPUNodeLink *vnor, *ob_mat, *blend;
- GPUNodeLink **texco = &in[0].link;
-
if (!ima) {
return GPU_stack_link(mat, node, "node_tex_image_empty", in, out);
}
+ GPUNodeLink **texco = &in[0].link;
if (!*texco) {
*texco = GPU_attribute(mat, CD_MTFACE, "");
node_shader_gpu_bump_tex_coord(mat, node, texco);
@@ -118,108 +80,73 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
node_shader_gpu_tex_mapping(mat, node, in, out);
- eGPUSamplerState sampler_state = GPU_SAMPLER_MAX;
+ eGPUSamplerState sampler_state = 0;
+
+ switch (tex->extension) {
+ case SHD_IMAGE_EXTENSION_REPEAT:
+ sampler_state |= GPU_SAMPLER_REPEAT;
+ break;
+ case SHD_IMAGE_EXTENSION_CLIP:
+ sampler_state |= GPU_SAMPLER_CLAMP_BORDER;
+ break;
+ default:
+ break;
+ }
+
+ if (tex->interpolation != SHD_INTERP_CLOSEST) {
+ sampler_state |= GPU_SAMPLER_ANISO | GPU_SAMPLER_FILTER;
+ sampler_state |= GPU_get_mipmap() ? GPU_SAMPLER_MIPMAP : 0;
+ }
+ const bool use_cubic = ELEM(tex->interpolation, SHD_INTERP_CUBIC, SHD_INTERP_SMART);
if (ima->source == IMA_SRC_TILED) {
+ const char *gpu_node_name = use_cubic ? "node_tex_tile_cubic" : "node_tex_tile_linear";
+ GPUNodeLink *gpu_image = GPU_image(mat, ima, iuser, sampler_state);
+ GPUNodeLink *gpu_image_tile_mapping = GPU_image_tiled_mapping(mat, ima, iuser);
/* UDIM tiles needs a samper2DArray and sampler1DArray for tile mapping. */
- GPU_stack_link(mat,
- node,
- names_tiled[tex->interpolation],
- in,
- out,
- GPU_image_tiled(mat, ima, iuser, sampler_state),
- GPU_image_tiled_mapping(mat, ima, iuser));
+ GPU_stack_link(mat, node, gpu_node_name, in, out, gpu_image, gpu_image_tile_mapping);
}
else {
+ const char *gpu_node_name = use_cubic ? "node_tex_image_cubic" : "node_tex_image_linear";
+
switch (tex->projection) {
- case SHD_PROJ_FLAT:
- if (do_texco_clip) {
- /* This seems redundant, but is required to ensure the texco link
- * is not freed by GPU_link, as it is still needed for GPU_stack_link.
- * Intermediate links like this can only be used once and are then
- * freed immediately, but if we make it the output link of a set_rgb
- * node it will be kept and can be used multiple times. */
- GPU_link(mat, "set_rgb", *texco, texco);
- GPU_link(mat, "set_rgb", *texco, &input_coords);
- }
- if (do_texco_extend) {
- GPU_link(
- mat, "point_texco_clamp", *texco, GPU_image(mat, ima, iuser, sampler_state), texco);
- }
- GPU_stack_link(
- mat, node, gpu_node_name, in, out, GPU_image(mat, ima, iuser, sampler_state));
+ case SHD_PROJ_FLAT: {
+ GPUNodeLink *gpu_image = GPU_image(mat, ima, iuser, sampler_state);
+ GPU_stack_link(mat, node, gpu_node_name, in, out, gpu_image);
break;
-
- case SHD_PROJ_BOX:
- vnor = GPU_builtin(GPU_WORLD_NORMAL);
- ob_mat = GPU_builtin(GPU_OBJECT_MATRIX);
- blend = GPU_uniform(&tex->projection_blend);
- gpu_image = GPU_image(mat, ima, iuser, sampler_state);
-
+ }
+ case SHD_PROJ_BOX: {
+ gpu_node_name = use_cubic ? "tex_box_sample_cubic" : "tex_box_sample_linear";
+ GPUNodeLink *wnor, *col1, *col2, *col3;
+ GPUNodeLink *vnor = GPU_builtin(GPU_WORLD_NORMAL);
+ GPUNodeLink *ob_mat = GPU_builtin(GPU_OBJECT_MATRIX);
+ GPUNodeLink *blend = GPU_uniform(&tex->projection_blend);
+ GPUNodeLink *gpu_image = GPU_image(mat, ima, iuser, sampler_state);
/* equivalent to normal_world_to_object */
- GPU_link(mat, "normal_transform_transposed_m4v3", vnor, ob_mat, &norm);
- {
- /* See SHD_PROJ_FLAT for explanation. */
- GPU_link(mat, "set_rgb", *texco, texco);
- GPU_link(mat, "set_rgb", *texco, &input_coords);
- in[0].link = input_coords;
- }
- GPU_link(mat,
- gpu_node_name,
- *texco,
- norm,
- GPU_image(mat, ima, iuser, sampler_state),
- &col1,
- &col2,
- &col3);
- GPU_stack_link(
- mat, node, "node_tex_image_box", in, out, norm, col1, col2, col3, gpu_image, blend);
+ GPU_link(mat, "normal_transform_transposed_m4v3", vnor, ob_mat, &wnor);
+ GPU_link(mat, gpu_node_name, in[0].link, wnor, gpu_image, &col1, &col2, &col3);
+ GPU_link(mat, "tex_box_blend", wnor, col1, col2, col3, blend, &out[0].link, &out[1].link);
break;
-
- case SHD_PROJ_SPHERE:
+ }
+ case SHD_PROJ_SPHERE: {
+ /* This projection is known to have a derivative discontinuity.
+ * Hide it by turning off mipmapping. */
+ sampler_state &= ~GPU_SAMPLER_MIPMAP;
+ GPUNodeLink *gpu_image = GPU_image(mat, ima, iuser, sampler_state);
GPU_link(mat, "point_texco_remap_square", *texco, texco);
GPU_link(mat, "point_map_to_sphere", *texco, texco);
- if (do_texco_clip) {
- /* See SHD_PROJ_FLAT for explanation. */
- GPU_link(mat, "set_rgb", *texco, texco);
- GPU_link(mat, "set_rgb", *texco, &input_coords);
- }
- if (do_texco_extend) {
- GPU_link(
- mat, "point_texco_clamp", *texco, GPU_image(mat, ima, iuser, sampler_state), texco);
- }
- GPU_stack_link(
- mat, node, gpu_node_name, in, out, GPU_image(mat, ima, iuser, sampler_state));
+ GPU_stack_link(mat, node, gpu_node_name, in, out, gpu_image);
break;
-
- case SHD_PROJ_TUBE:
+ }
+ case SHD_PROJ_TUBE: {
+ /* This projection is known to have a derivative discontinuity.
+ * Hide it by turning off mipmapping. */
+ sampler_state &= ~GPU_SAMPLER_MIPMAP;
+ GPUNodeLink *gpu_image = GPU_image(mat, ima, iuser, sampler_state);
GPU_link(mat, "point_texco_remap_square", *texco, texco);
GPU_link(mat, "point_map_to_tube", *texco, texco);
- if (do_texco_clip) {
- /* See SHD_PROJ_FLAT for explanation. */
- GPU_link(mat, "set_rgb", *texco, texco);
- GPU_link(mat, "set_rgb", *texco, &input_coords);
- }
- if (do_texco_extend) {
- GPU_link(
- mat, "point_texco_clamp", *texco, GPU_image(mat, ima, iuser, sampler_state), texco);
- }
- GPU_stack_link(
- mat, node, gpu_node_name, in, out, GPU_image(mat, ima, iuser, sampler_state));
+ GPU_stack_link(mat, node, gpu_node_name, in, out, gpu_image);
break;
- }
-
- if (tex->projection != SHD_PROJ_BOX) {
- if (do_texco_clip) {
- gpu_node_name = names_clip[tex->interpolation];
- in[0].link = input_coords;
- GPU_stack_link(mat,
- node,
- gpu_node_name,
- in,
- out,
- GPU_image(mat, ima, iuser, sampler_state),
- out[0].link);
}
}
}