diff options
author | Lukas Stockner <lukasstockner97> | 2020-01-14 02:33:21 +0300 |
---|---|---|
committer | Lukas Stockner <lukas.stockner@freenet.de> | 2020-01-16 04:06:49 +0300 |
commit | 7d8a186335400cb7ad69d24aab89e7a215a70348 (patch) | |
tree | 0919c339e6f9a8a56fed8246af7f365473475784 /source/blender/draw | |
parent | 689a873029b9554a60ee1198344a29cd2f567659 (diff) |
Fix T73133: UDIM texture count in Eevee is limited by OpenGL
Based on @fclem's suggestion in D6421, this commit implements support for
storing all tiles of a UDIM texture in a single 2D array texture on the GPU.
Previously, Eevee was binding one OpenGL texture per tile, quickly running
into hardware limits with nontrivial UDIM texture sets.
Workbench meanwhile had no UDIM support at all, as reusing the per-tile
approach would require splitting the mesh by tile as well as texture.
With this commit, both Workbench as well as Eevee now support huge numbers
of tiles, with the eventual limits being GPU memory and ultimately
GL_MAX_ARRAY_TEXTURE_LAYERS, which tends to be in the 1000s on modern GPUs.
Initially my plan was to have one array texture per unique size, but managing
the different textures and keeping everything consistent ended up being way
too complex.
Therefore, we now use a simpler version that allocates a texture that
is large enough to fit the largest tile and then packs all tiles into as many
layers as necessary.
As a result, each UDIM texture only binds two textures (one for the actual
images, one for metadata) regardless of how many tiles are used.
Note that this rolls back per-tile GPUTextures, meaning that we again have
per-Image GPUTextures like we did before the original UDIM commit,
but now with four instead of two types.
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D6456
Diffstat (limited to 'source/blender/draw')
8 files changed, 146 insertions, 40 deletions
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl index 59a463f49c3..c0d7719180b 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl @@ -140,6 +140,28 @@ vec2 matcap_uv_compute(vec3 I, vec3 N, bool flipped) return matcap_uv * 0.496 + 0.5; } +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) + return false; + + float tile = 10.0 * tile_pos.y + tile_pos.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) + return false; + + vec4 tile_info = texelFetch(map, ivec2(tile, 1), 0); + + co = vec3(((co.xy - tile_pos) * tile_info.zw) + tile_info.xy, tile_layer); + return true; +} + vec4 workbench_sample_texture(sampler2D image, vec2 coord, bool nearest_sampling, @@ -158,3 +180,28 @@ vec4 workbench_sample_texture(sampler2D image, return color; } + +vec4 workbench_sample_texture_array(sampler2DArray tile_array, + sampler1DArray tile_data, + vec2 coord, + bool nearest_sampling, + bool premultiplied) +{ + vec2 tex_size = vec2(textureSize(tile_array, 0).xy); + + 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. */ + uv.xy = nearest_sampling ? (floor(uv.xy * tex_size) + 0.5) / tex_size : uv.xy; + vec4 color = texture(tile_array, uv); + + /* Unpremultiply if stored multiplied, since straight alpha is expected by shaders. */ + if (premultiplied && !(color.a == 0.0 || color.a == 1.0)) { + color.rgb = color.rgb / color.a; + } + + return color; +} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl index f799ce41cb2..559dc07c107 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl @@ -1,6 +1,11 @@ uniform float ImageTransparencyCutoff = 0.1; +#ifdef TEXTURE_IMAGE_ARRAY +uniform sampler2DArray image_tile_array; +uniform sampler1DArray image_tile_data; +#else uniform sampler2D image; +#endif uniform bool imageNearest; uniform bool imagePremultiplied; @@ -44,7 +49,12 @@ void main() vec4 base_color; #if defined(V3D_SHADING_TEXTURE_COLOR) +# ifdef TEXTURE_IMAGE_ARRAY + base_color = workbench_sample_texture_array( + image_tile_array, image_tile_data, uv_interp, imageNearest, imagePremultiplied); +# else base_color = workbench_sample_texture(image, uv_interp, imageNearest, imagePremultiplied); +# endif if (base_color.a < ImageTransparencyCutoff) { discard; } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl index b5f95f2dcf8..94e41b4bcd4 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl @@ -2,7 +2,12 @@ uniform vec4 materialColorAndMetal; uniform float materialRoughness; +#ifdef TEXTURE_IMAGE_ARRAY +uniform sampler2DArray image_tile_array; +uniform sampler1DArray image_tile_data; +#else uniform sampler2D image; +#endif uniform float ImageTransparencyCutoff = 0.1; uniform bool imageNearest; uniform bool imagePremultiplied; @@ -39,7 +44,12 @@ void main() vec4 color; # if defined(V3D_SHADING_TEXTURE_COLOR) +# ifdef TEXTURE_IMAGE_ARRAY + color = workbench_sample_texture_array( + image_tile_array, image_tile_data, uv_interp, imageNearest, imagePremultiplied); +# else color = workbench_sample_texture(image, uv_interp, imageNearest, imagePremultiplied); +# endif if (color.a < ImageTransparencyCutoff) { discard; } diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c index 8bc4ae2e101..1af9357e015 100644 --- a/source/blender/draw/engines/workbench/workbench_deferred.c +++ b/source/blender/draw/engines/workbench/workbench_deferred.c @@ -214,16 +214,17 @@ static GPUShader *workbench_cavity_shader_get(bool cavity, bool curvature) static GPUShader *ensure_deferred_prepass_shader(WORKBENCH_PrivateData *wpd, bool is_uniform_color, bool is_hair, + bool is_tiled, const WORKBENCH_ColorOverride color_override, eGPUShaderConfig sh_cfg) { WORKBENCH_DEFERRED_Shaders *sh_data = &e_data.sh_data[sh_cfg]; int index = workbench_material_get_prepass_shader_index( - wpd, is_uniform_color, is_hair, color_override); + wpd, is_uniform_color, is_hair, is_tiled, color_override); if (sh_data->prepass_sh_cache[index] == NULL) { const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg]; char *defines = workbench_material_build_defines( - wpd, is_uniform_color, is_hair, color_override); + wpd, is_uniform_color, is_hair, is_tiled, color_override); char *prepass_vert = workbench_build_prepass_vert(is_hair); char *prepass_frag = workbench_build_prepass_frag(); sh_data->prepass_sh_cache[index] = GPU_shader_create_from_arrays({ @@ -243,7 +244,7 @@ static GPUShader *ensure_deferred_composite_shader(WORKBENCH_PrivateData *wpd) int index = workbench_material_get_composite_shader_index(wpd); if (e_data.composite_sh_cache[index] == NULL) { char *defines = workbench_material_build_defines( - wpd, false, false, WORKBENCH_COLOR_OVERRIDE_OFF); + wpd, false, false, false, WORKBENCH_COLOR_OVERRIDE_OFF); char *composite_frag = workbench_build_composite_frag(wpd); e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines); MEM_freeN(composite_frag); @@ -271,17 +272,19 @@ static GPUShader *ensure_background_shader(WORKBENCH_PrivateData *wpd) static void select_deferred_shaders(WORKBENCH_PrivateData *wpd, eGPUShaderConfig sh_cfg) { wpd->prepass_sh = ensure_deferred_prepass_shader( - wpd, false, false, WORKBENCH_COLOR_OVERRIDE_OFF, sh_cfg); + wpd, false, false, false, WORKBENCH_COLOR_OVERRIDE_OFF, sh_cfg); wpd->prepass_hair_sh = ensure_deferred_prepass_shader( - wpd, false, true, WORKBENCH_COLOR_OVERRIDE_OFF, sh_cfg); + wpd, false, true, false, WORKBENCH_COLOR_OVERRIDE_OFF, sh_cfg); wpd->prepass_uniform_sh = ensure_deferred_prepass_shader( - wpd, true, false, WORKBENCH_COLOR_OVERRIDE_OFF, sh_cfg); + wpd, true, false, false, WORKBENCH_COLOR_OVERRIDE_OFF, sh_cfg); wpd->prepass_uniform_hair_sh = ensure_deferred_prepass_shader( - wpd, true, true, WORKBENCH_COLOR_OVERRIDE_OFF, sh_cfg); + wpd, true, true, false, WORKBENCH_COLOR_OVERRIDE_OFF, sh_cfg); wpd->prepass_textured_sh = ensure_deferred_prepass_shader( - wpd, false, false, WORKBENCH_COLOR_OVERRIDE_TEXTURE, sh_cfg); + wpd, false, false, false, WORKBENCH_COLOR_OVERRIDE_TEXTURE, sh_cfg); + wpd->prepass_textured_array_sh = ensure_deferred_prepass_shader( + wpd, false, false, true, WORKBENCH_COLOR_OVERRIDE_TEXTURE, sh_cfg); wpd->prepass_vertex_sh = ensure_deferred_prepass_shader( - wpd, false, false, WORKBENCH_COLOR_OVERRIDE_VERTEX, sh_cfg); + wpd, false, false, false, WORKBENCH_COLOR_OVERRIDE_VERTEX, sh_cfg); wpd->composite_sh = ensure_deferred_composite_shader(wpd); wpd->background_sh = ensure_background_shader(wpd); } @@ -873,8 +876,9 @@ static WORKBENCH_MaterialData *get_or_create_material_data(WORKBENCH_Data *vedat /* select the correct prepass shader */ GPUShader *shader = (wpd->shading.color_type == color_type) ? wpd->prepass_sh : wpd->prepass_uniform_sh; + const bool is_tiled = (ima && ima->source == IMA_SRC_TILED); if (color_type == V3D_SHADING_TEXTURE_COLOR) { - shader = wpd->prepass_textured_sh; + shader = is_tiled ? wpd->prepass_textured_array_sh : wpd->prepass_textured_sh; } if (color_type == V3D_SHADING_VERTEX_COLOR) { shader = wpd->prepass_vertex_sh; @@ -883,7 +887,7 @@ static WORKBENCH_MaterialData *get_or_create_material_data(WORKBENCH_Data *vedat shader, (ob->dtx & OB_DRAWXRAY) ? psl->ghost_prepass_pass : psl->prepass_pass); workbench_material_copy(material, &material_template); DRW_shgroup_stencil_mask(material->shgrp, (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF); - workbench_material_shgroup_uniform(wpd, material->shgrp, material, ob, true, interp); + workbench_material_shgroup_uniform(wpd, material->shgrp, material, ob, true, is_tiled, interp); BLI_ghash_insert(wpd->material_hash, POINTER_FROM_UINT(hash), material); } return material; @@ -926,7 +930,7 @@ static void workbench_cache_populate_particles(WORKBENCH_Data *vedata, Object *o (ob->dtx & OB_DRAWXRAY) ? psl->ghost_prepass_hair_pass : psl->prepass_hair_pass, shader); DRW_shgroup_stencil_mask(shgrp, (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF); - workbench_material_shgroup_uniform(wpd, shgrp, material, ob, true, interp); + workbench_material_shgroup_uniform(wpd, shgrp, material, ob, true, false, interp); } } } diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c index 44f43fc7d09..ae001f8d10c 100644 --- a/source/blender/draw/engines/workbench/workbench_forward.c +++ b/source/blender/draw/engines/workbench/workbench_forward.c @@ -172,8 +172,10 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_ GPUShader *shader = (wpd->shading.color_type == color_type) ? wpd->transparent_accum_sh : wpd->transparent_accum_uniform_sh; + const bool is_tiled = (ima && ima->source == IMA_SRC_TILED); if (color_type == V3D_SHADING_TEXTURE_COLOR) { - shader = wpd->transparent_accum_textured_sh; + shader = is_tiled ? wpd->transparent_accum_textured_array_sh : + wpd->transparent_accum_textured_sh; } grp = DRW_shgroup_create(shader, psl->transparent_accum_pass); @@ -201,7 +203,7 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_ DRW_shgroup_uniform_float_copy(grp, "shadowFocus", wpd->shadow_focus); } - workbench_material_shgroup_uniform(wpd, grp, material, ob, false, interp); + workbench_material_shgroup_uniform(wpd, grp, material, ob, false, is_tiled, interp); material->shgrp = grp; /* Depth */ @@ -226,16 +228,17 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_ static GPUShader *ensure_forward_accum_shaders(WORKBENCH_PrivateData *wpd, bool is_uniform_color, bool is_hair, + bool is_tiled, const WORKBENCH_ColorOverride color_override, eGPUShaderConfig sh_cfg) { WORKBENCH_FORWARD_Shaders *sh_data = &e_data.sh_data[sh_cfg]; int index = workbench_material_get_accum_shader_index( - wpd, is_uniform_color, is_hair, color_override); + wpd, is_uniform_color, is_hair, is_tiled, color_override); if (sh_data->transparent_accum_sh_cache[index] == NULL) { const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg]; char *defines = workbench_material_build_defines( - wpd, is_uniform_color, is_hair, color_override); + wpd, is_uniform_color, is_hair, is_tiled, color_override); char *transparent_accum_vert = workbench_build_forward_vert(is_hair); char *transparent_accum_frag = workbench_build_forward_transparent_accum_frag(); sh_data->transparent_accum_sh_cache[index] = GPU_shader_create_from_arrays({ @@ -255,7 +258,7 @@ static GPUShader *ensure_forward_composite_shaders(WORKBENCH_PrivateData *wpd) int index = OBJECT_OUTLINE_ENABLED(wpd) ? 1 : 0; if (e_data.composite_sh_cache[index] == NULL) { char *defines = workbench_material_build_defines( - wpd, false, false, WORKBENCH_COLOR_OVERRIDE_OFF); + wpd, false, false, false, WORKBENCH_COLOR_OVERRIDE_OFF); char *composite_frag = workbench_build_forward_composite_frag(); e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines); MEM_freeN(composite_frag); @@ -268,17 +271,19 @@ void workbench_forward_choose_shaders(WORKBENCH_PrivateData *wpd, eGPUShaderConf { wpd->composite_sh = ensure_forward_composite_shaders(wpd); wpd->transparent_accum_sh = ensure_forward_accum_shaders( - wpd, false, false, WORKBENCH_COLOR_OVERRIDE_OFF, sh_cfg); + wpd, false, false, false, WORKBENCH_COLOR_OVERRIDE_OFF, sh_cfg); wpd->transparent_accum_hair_sh = ensure_forward_accum_shaders( - wpd, false, true, WORKBENCH_COLOR_OVERRIDE_OFF, sh_cfg); + wpd, false, true, false, WORKBENCH_COLOR_OVERRIDE_OFF, sh_cfg); wpd->transparent_accum_uniform_sh = ensure_forward_accum_shaders( - wpd, true, false, WORKBENCH_COLOR_OVERRIDE_OFF, sh_cfg); + wpd, true, false, false, WORKBENCH_COLOR_OVERRIDE_OFF, sh_cfg); wpd->transparent_accum_uniform_hair_sh = ensure_forward_accum_shaders( - wpd, true, true, WORKBENCH_COLOR_OVERRIDE_OFF, sh_cfg); + wpd, true, true, false, WORKBENCH_COLOR_OVERRIDE_OFF, sh_cfg); wpd->transparent_accum_textured_sh = ensure_forward_accum_shaders( - wpd, false, false, WORKBENCH_COLOR_OVERRIDE_TEXTURE, sh_cfg); + wpd, false, false, false, WORKBENCH_COLOR_OVERRIDE_TEXTURE, sh_cfg); + wpd->transparent_accum_textured_array_sh = ensure_forward_accum_shaders( + wpd, false, false, true, WORKBENCH_COLOR_OVERRIDE_TEXTURE, sh_cfg); wpd->transparent_accum_vertex_sh = ensure_forward_accum_shaders( - wpd, false, false, WORKBENCH_COLOR_OVERRIDE_VERTEX, sh_cfg); + wpd, false, false, false, WORKBENCH_COLOR_OVERRIDE_VERTEX, sh_cfg); } void workbench_forward_outline_shaders_ensure(WORKBENCH_PrivateData *wpd, eGPUShaderConfig sh_cfg) @@ -288,11 +293,11 @@ void workbench_forward_outline_shaders_ensure(WORKBENCH_PrivateData *wpd, eGPUSh if (sh_data->object_outline_sh == NULL) { const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg]; char *defines = workbench_material_build_defines( - wpd, false, false, WORKBENCH_COLOR_OVERRIDE_OFF); + wpd, false, false, false, WORKBENCH_COLOR_OVERRIDE_OFF); char *defines_texture = workbench_material_build_defines( - wpd, true, false, WORKBENCH_COLOR_OVERRIDE_OFF); + wpd, true, false, false, WORKBENCH_COLOR_OVERRIDE_OFF); char *defines_hair = workbench_material_build_defines( - wpd, false, true, WORKBENCH_COLOR_OVERRIDE_OFF); + wpd, false, true, false, WORKBENCH_COLOR_OVERRIDE_OFF); char *forward_vert = workbench_build_forward_vert(false); char *forward_frag = workbench_build_forward_outline_frag(); char *forward_hair_vert = workbench_build_forward_vert(true); @@ -533,7 +538,7 @@ static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, O DRWShadingGroup *shgrp = DRW_shgroup_hair_create( ob, psys, md, psl->transparent_accum_pass, shader); DRW_shgroup_uniform_block(shgrp, "world_block", wpd->world_ubo); - workbench_material_shgroup_uniform(wpd, shgrp, material, ob, false, interp); + workbench_material_shgroup_uniform(wpd, shgrp, material, ob, false, false, interp); DRW_shgroup_uniform_vec4(shgrp, "viewvecs[0]", (float *)wpd->viewvecs, 3); /* Hairs have lots of layer and can rapidly become the most prominent surface. * So lower their alpha artificially. */ diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c index 16fcda54253..2219f5cf2dd 100644 --- a/source/blender/draw/engines/workbench/workbench_materials.c +++ b/source/blender/draw/engines/workbench/workbench_materials.c @@ -85,6 +85,7 @@ void workbench_material_update_data(WORKBENCH_PrivateData *wpd, char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, bool is_uniform_color, bool is_hair, + bool is_tiled, const WORKBENCH_ColorOverride color_override) { char *str = NULL; @@ -102,6 +103,7 @@ char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, use_textures = false; use_vertex_colors = true; is_hair = false; + is_tiled = false; break; case WORKBENCH_COLOR_OVERRIDE_OFF: break; @@ -151,6 +153,9 @@ char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, if (is_hair) { BLI_dynstr_append(ds, "#define HAIR_SHADER\n"); } + if (use_textures && is_tiled) { + BLI_dynstr_append(ds, "#define TEXTURE_IMAGE_ARRAY\n"); + } str = BLI_dynstr_get_cstring(ds); BLI_dynstr_free(ds); @@ -211,6 +216,7 @@ int workbench_material_get_composite_shader_index(WORKBENCH_PrivateData *wpd) int workbench_material_get_prepass_shader_index(WORKBENCH_PrivateData *wpd, bool is_uniform_color, bool is_hair, + bool is_tiled, const WORKBENCH_ColorOverride color_override) { bool use_textures = (wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR) && !is_uniform_color; @@ -225,6 +231,7 @@ int workbench_material_get_prepass_shader_index(WORKBENCH_PrivateData *wpd, case WORKBENCH_COLOR_OVERRIDE_VERTEX: use_textures = false; use_vertex_colors = true; + is_tiled = false; break; case WORKBENCH_COLOR_OVERRIDE_OFF: break; @@ -239,6 +246,7 @@ int workbench_material_get_prepass_shader_index(WORKBENCH_PrivateData *wpd, SET_FLAG_FROM_TEST(index, MATCAP_ENABLED(wpd), 1 << 4); SET_FLAG_FROM_TEST(index, use_textures, 1 << 5); SET_FLAG_FROM_TEST(index, use_vertex_colors, 1 << 6); + SET_FLAG_FROM_TEST(index, is_tiled && use_textures, 1 << 7); BLI_assert(index < MAX_PREPASS_SHADERS); return index; } @@ -246,6 +254,7 @@ int workbench_material_get_prepass_shader_index(WORKBENCH_PrivateData *wpd, int workbench_material_get_accum_shader_index(WORKBENCH_PrivateData *wpd, bool is_uniform_color, bool is_hair, + bool is_tiled, const WORKBENCH_ColorOverride color_override) { bool use_textures = (wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR) && !is_uniform_color; @@ -262,6 +271,7 @@ int workbench_material_get_accum_shader_index(WORKBENCH_PrivateData *wpd, use_textures = false; use_vertex_colors = true; is_hair = false; + is_tiled = false; break; case WORKBENCH_COLOR_OVERRIDE_OFF: break; @@ -277,6 +287,7 @@ int workbench_material_get_accum_shader_index(WORKBENCH_PrivateData *wpd, /* 1 bits SHADOWS (only facing factor) */ SET_FLAG_FROM_TEST(index, SHADOW_ENABLED(wpd), 1 << 5); SET_FLAG_FROM_TEST(index, workbench_is_specular_highlight_enabled(wpd), 1 << 6); + SET_FLAG_FROM_TEST(index, is_tiled && use_textures, 1 << 7); BLI_assert(index < MAX_ACCUM_SHADERS); return index; } @@ -352,6 +363,7 @@ void workbench_material_shgroup_uniform(WORKBENCH_PrivateData *wpd, WORKBENCH_MaterialData *material, Object *ob, const bool deferred, + const bool is_tiled, const int interp) { if (deferred && !workbench_is_matdata_pass_enabled(wpd)) { @@ -362,8 +374,18 @@ void workbench_material_shgroup_uniform(WORKBENCH_PrivateData *wpd, const bool use_texture = (V3D_SHADING_TEXTURE_COLOR == workbench_material_determine_color_type( wpd, material->ima, ob, false)); if (use_texture) { - GPUTexture *tex = GPU_texture_from_blender(material->ima, material->iuser, GL_TEXTURE_2D); - DRW_shgroup_uniform_texture(grp, "image", tex); + if (is_tiled) { + GPUTexture *array_tex = GPU_texture_from_blender( + material->ima, material->iuser, GL_TEXTURE_2D_ARRAY); + GPUTexture *data_tex = GPU_texture_from_blender( + material->ima, material->iuser, GL_TEXTURE_1D_ARRAY); + DRW_shgroup_uniform_texture(grp, "image_tile_array", array_tex); + DRW_shgroup_uniform_texture(grp, "image_tile_data", data_tex); + } + else { + GPUTexture *tex = GPU_texture_from_blender(material->ima, material->iuser, GL_TEXTURE_2D); + DRW_shgroup_uniform_texture(grp, "image", tex); + } DRW_shgroup_uniform_bool_copy( grp, "imagePremultiplied", (material->ima->alpha_mode == IMA_ALPHA_PREMUL)); DRW_shgroup_uniform_bool_copy(grp, "imageNearest", (interp == SHD_INTERP_CLOSEST)); diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index 7c774ca7490..e100f6e875c 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -37,8 +37,8 @@ #define WORKBENCH_ENGINE "BLENDER_WORKBENCH" #define M_GOLDEN_RATION_CONJUGATE 0.618033988749895 #define MAX_COMPOSITE_SHADERS (1 << 7) -#define MAX_PREPASS_SHADERS (1 << 7) -#define MAX_ACCUM_SHADERS (1 << 7) +#define MAX_PREPASS_SHADERS (1 << 8) +#define MAX_ACCUM_SHADERS (1 << 8) #define MAX_CAVITY_SHADERS (1 << 3) #define TEXTURE_DRAWING_ENABLED(wpd) (wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR) @@ -207,6 +207,7 @@ typedef struct WORKBENCH_PrivateData { struct GPUShader *prepass_uniform_sh; struct GPUShader *prepass_uniform_hair_sh; struct GPUShader *prepass_textured_sh; + struct GPUShader *prepass_textured_array_sh; struct GPUShader *prepass_vertex_sh; struct GPUShader *composite_sh; struct GPUShader *background_sh; @@ -215,6 +216,7 @@ typedef struct WORKBENCH_PrivateData { struct GPUShader *transparent_accum_uniform_sh; struct GPUShader *transparent_accum_uniform_hair_sh; struct GPUShader *transparent_accum_textured_sh; + struct GPUShader *transparent_accum_textured_array_sh; struct GPUShader *transparent_accum_vertex_sh; View3DShading shading; StudioLight *studio_light; @@ -516,6 +518,7 @@ void workbench_material_get_image_and_mat( char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, bool is_uniform_color, bool is_hair, + bool is_tiled, const WORKBENCH_ColorOverride color_override); void workbench_material_update_data(WORKBENCH_PrivateData *wpd, Object *ob, @@ -527,16 +530,19 @@ int workbench_material_get_composite_shader_index(WORKBENCH_PrivateData *wpd); int workbench_material_get_prepass_shader_index(WORKBENCH_PrivateData *wpd, bool is_uniform_color, bool is_hair, + bool is_tiled, const WORKBENCH_ColorOverride color_override); int workbench_material_get_accum_shader_index(WORKBENCH_PrivateData *wpd, bool is_uniform_color, bool is_hair, + bool is_tiled, const WORKBENCH_ColorOverride color_override); void workbench_material_shgroup_uniform(WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp, WORKBENCH_MaterialData *material, Object *ob, const bool deferred, + const bool is_tiled, const int interp); void workbench_material_copy(WORKBENCH_MaterialData *dest_material, const WORKBENCH_MaterialData *source_material); diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index 98474c81209..c6fc244121c 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -1214,17 +1214,19 @@ static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp, GPUTexture *tex = NULL; if (input->ima) { - /* If there's no specified iuser but we need a different tile, create a temporary one. */ - ImageUser local_iuser; - BKE_imageuser_default(&local_iuser); - local_iuser.tile = input->image_tile; - - ImageUser *iuser = input->iuser ? input->iuser : &local_iuser; - iuser->tile = input->image_tile; - GPUTexture **tex_ref = BLI_memblock_alloc(DST.vmempool->images); - *tex_ref = tex = GPU_texture_from_blender(input->ima, iuser, GL_TEXTURE_2D); + int textarget; + if (input->type == GPU_TEX2D_ARRAY) { + textarget = GL_TEXTURE_2D_ARRAY; + } + else if (input->type == GPU_TEX1D_ARRAY) { + textarget = GL_TEXTURE_1D_ARRAY; + } + else { + textarget = GL_TEXTURE_2D; + } + *tex_ref = tex = GPU_texture_from_blender(input->ima, input->iuser, textarget); GPU_texture_ref(tex); } |