From 04d18b117c2f95b0b28df12c9ddac06b018d6236 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 24 Jan 2019 15:02:40 +1100 Subject: DRW: API for own versions of builtin GPU shaders DRW_shader_get_builtin_shader can replace GPU_shader_get_builtin_shader when we need to support clipping. Use this for loose point & wire drawing in object mode, clips edges in lattice edit mode. --- source/blender/draw/CMakeLists.txt | 4 + source/blender/draw/intern/draw_builtin_shader.c | 131 +++++++++++++++++++++ source/blender/draw/intern/draw_builtin_shader.h | 34 ++++++ source/blender/draw/intern/draw_manager.c | 2 + source/blender/draw/modes/edit_lattice_mode.c | 6 +- source/blender/draw/modes/object_mode.c | 48 +++++--- .../shaders/drw_shader_3D_smooth_color_vert.glsl | 17 +++ .../draw/modes/shaders/drw_shader_3D_vert.glsl | 13 ++ 8 files changed, 238 insertions(+), 17 deletions(-) create mode 100644 source/blender/draw/intern/draw_builtin_shader.c create mode 100644 source/blender/draw/intern/draw_builtin_shader.h create mode 100644 source/blender/draw/modes/shaders/drw_shader_3D_smooth_color_vert.glsl create mode 100644 source/blender/draw/modes/shaders/drw_shader_3D_vert.glsl (limited to 'source') diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index a305d18a592..c25d5564b21 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -55,6 +55,7 @@ set(INC_SYS set(SRC intern/draw_anim_viz.c intern/draw_armature.c + intern/draw_builtin_shader.c intern/draw_cache.c intern/draw_cache_impl_curve.c intern/draw_cache_impl_displist.c @@ -133,6 +134,7 @@ set(SRC DRW_engine.h intern/DRW_render.h + intern/draw_builtin_shader.h intern/draw_cache.h intern/draw_cache_impl.h intern/draw_common.h @@ -323,6 +325,8 @@ data_to_c_simple(modes/shaders/particle_strand_frag.glsl SRC) data_to_c_simple(modes/shaders/particle_strand_vert.glsl SRC) data_to_c_simple(modes/shaders/sculpt_mask_vert.glsl SRC) data_to_c_simple(modes/shaders/volume_velocity_vert.glsl SRC) +data_to_c_simple(modes/shaders/drw_shader_3D_vert.glsl SRC) +data_to_c_simple(modes/shaders/drw_shader_3D_smooth_color_vert.glsl SRC) data_to_c_simple(engines/gpencil/shaders/gpencil_fill_vert.glsl SRC) data_to_c_simple(engines/gpencil/shaders/gpencil_fill_frag.glsl SRC) diff --git a/source/blender/draw/intern/draw_builtin_shader.c b/source/blender/draw/intern/draw_builtin_shader.c new file mode 100644 index 00000000000..3f49f9d2731 --- /dev/null +++ b/source/blender/draw/intern/draw_builtin_shader.c @@ -0,0 +1,131 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +/** \file draw_armature.c + * \ingroup draw + * Draw manager versions of #eGPUBuiltinShader, see #GPU_shader_get_builtin_shader. + * + * Allows for modifications to shaders (currently only clipping support). + * Follow GPU_shader.h conventions to avoid annoyance. + */ + +#include "BLI_utildefines.h" + +#include "GPU_shader.h" + +#include "DRW_render.h" + +#include "draw_builtin_shader.h" /* own include */ + + +extern char datatoc_common_world_clip_lib_glsl[]; + +extern char datatoc_drw_shader_3D_vert_glsl[]; +extern char datatoc_drw_shader_3D_smooth_color_vert_glsl[]; + +extern char datatoc_gpu_shader_uniform_color_frag_glsl[]; +extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[]; + + +/* cache of built-in shaders (each is created on first use) */ +static struct { + GPUShader *builtin_shaders[GPU_NUM_BUILTIN_SHADERS]; +} g_sh_data[DRW_SHADER_SLOT_LEN - 1] = {{{NULL}}}; + +static GPUShader *drw_shader_get_builtin_shader_clipped(eGPUBuiltinShader shader_id, bool *r_test_only) +{ + const char *world_clip_lib = datatoc_common_world_clip_lib_glsl; + const char *world_clip_def = "#define USE_WORLD_CLIP_PLANES\n"; + + if (r_test_only) { + *r_test_only = true; + } + + GPUShader *shader = NULL; + switch (shader_id) { + case GPU_SHADER_3D_UNIFORM_COLOR: + if (r_test_only) { + break; + } + shader = DRW_shader_create_from_arrays({ + .vert = (const char *[]){world_clip_lib, datatoc_drw_shader_3D_vert_glsl, NULL}, + .frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL}, + .defs = (const char *[]){world_clip_def, NULL}}); + break; + case GPU_SHADER_3D_SMOOTH_COLOR: + if (r_test_only) { + break; + } + shader = DRW_shader_create_from_arrays({ + .vert = (const char *[]){world_clip_lib, datatoc_drw_shader_3D_smooth_color_vert_glsl, NULL}, + .frag = (const char *[]){datatoc_gpu_shader_3D_smooth_color_frag_glsl, NULL}, + .defs = (const char *[]){world_clip_def, NULL}}); + break; + default: + /* Unsupported, caller asserts. */ + if (r_test_only) { + *r_test_only = false; + } + } + return shader; +} + +static bool drw_shader_get_builtin_shader_test_all(eGPUBuiltinShader shader_id) +{ + bool test = false; + drw_shader_get_builtin_shader_clipped(shader_id, &test); + return test; +} + +GPUShader *DRW_shader_get_builtin_shader(eGPUBuiltinShader shader_id, eDRW_ShaderSlot slot) +{ + BLI_assert(drw_shader_get_builtin_shader_test_all(shader_id)); + if (slot == DRW_SHADER_SLOT_DEFAULT) { + return GPU_shader_get_builtin_shader(shader_id); + } + + GPUShader **builtin_shaders = g_sh_data[slot - 1].builtin_shaders; + + if (builtin_shaders[shader_id] != NULL) { + return builtin_shaders[shader_id]; + } + + if (slot == DRW_SHADER_SLOT_CLIPPED) { + builtin_shaders[shader_id] = drw_shader_get_builtin_shader_clipped(shader_id, NULL); + return builtin_shaders[shader_id]; + } + else { + BLI_assert(0); + } +} + +void DRW_shader_free_builtin_shaders(void) +{ + for (int j = 0; j < (DRW_SHADER_SLOT_LEN - 1); j++) { + GPUShader **builtin_shaders = g_sh_data[j].builtin_shaders; + for (int i = 0; i < GPU_NUM_BUILTIN_SHADERS; i++) { + if (builtin_shaders[i]) { + GPU_shader_free(builtin_shaders[i]); + builtin_shaders[i] = NULL; + } + } + } +} diff --git a/source/blender/draw/intern/draw_builtin_shader.h b/source/blender/draw/intern/draw_builtin_shader.h new file mode 100644 index 00000000000..f9eb42a7026 --- /dev/null +++ b/source/blender/draw/intern/draw_builtin_shader.h @@ -0,0 +1,34 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +/** \file draw_builtin_shader.h + * \ingroup draw + */ + +#ifndef __DRAW_BUILTIN_SHADER_H__ +#define __DRAW_BUILTIN_SHADER_H__ + +struct GPUShader; + +struct GPUShader *DRW_shader_get_builtin_shader(eGPUBuiltinShader shader_id, eDRW_ShaderSlot slot); +void DRW_shader_free_builtin_shaders(void); + +#endif /* __DRAW_BUILTIN_SHADER_H__ */ diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index c47ab00c841..d311b3e8156 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -82,6 +82,7 @@ #include "draw_cache_impl.h" #include "draw_mode_engines.h" +#include "draw_builtin_shader.h" #include "engines/eevee/eevee_engine.h" #include "engines/basic/basic_engine.h" #include "engines/workbench/workbench_engine.h" @@ -2610,6 +2611,7 @@ void DRW_engines_free(void) DRW_shape_cache_free(); DRW_stats_free(); DRW_globals_free(); + DRW_shader_free_builtin_shaders(); DrawEngineType *next; for (DrawEngineType *type = DRW_engines.first; type; type = next) { diff --git a/source/blender/draw/modes/edit_lattice_mode.c b/source/blender/draw/modes/edit_lattice_mode.c index c98a68f13b2..e484b359b9e 100644 --- a/source/blender/draw/modes/edit_lattice_mode.c +++ b/source/blender/draw/modes/edit_lattice_mode.c @@ -37,6 +37,7 @@ #include "draw_common.h" #include "draw_mode_engines.h" +#include "draw_builtin_shader.h" extern char datatoc_common_world_clip_lib_glsl[]; extern char datatoc_common_globals_lib_glsl[]; @@ -154,7 +155,7 @@ static void EDIT_LATTICE_engine_init(void *vedata) const char *world_clip_def_or_empty = is_clip ? "#define USE_WORLD_CLIP_PLANES\n" : ""; if (!sh_data->wire) { - sh_data->wire = GPU_shader_get_builtin_shader(GPU_SHADER_3D_SMOOTH_COLOR); + sh_data->wire = DRW_shader_get_builtin_shader(GPU_SHADER_3D_SMOOTH_COLOR, draw_ctx->shader_slot); } if (!sh_data->overlay_vert) { @@ -194,6 +195,9 @@ static void EDIT_LATTICE_cache_init(void *vedata) "Lattice Wire", DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE); stl->g_data->wire_shgrp = DRW_shgroup_create(sh_data->wire, psl->wire_pass); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->wire_shgrp, rv3d); + } psl->vert_pass = DRW_pass_create( "Lattice Verts", diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c index 7a10763c1b7..1f0bb4738db 100644 --- a/source/blender/draw/modes/object_mode.c +++ b/source/blender/draw/modes/object_mode.c @@ -79,9 +79,11 @@ #include "draw_mode_engines.h" #include "draw_manager_text.h" #include "draw_common.h" +#include "draw_builtin_shader.h" #include "DEG_depsgraph_query.h" +extern char datatoc_common_world_clip_lib_glsl[]; extern char datatoc_object_outline_prepass_vert_glsl[]; extern char datatoc_object_outline_prepass_geom_glsl[]; extern char datatoc_object_outline_prepass_frag_glsl[]; @@ -103,6 +105,7 @@ extern char datatoc_gpu_shader_flat_color_frag_glsl[]; extern char datatoc_gpu_shader_flat_id_frag_glsl[]; extern char datatoc_common_fullscreen_vert_glsl[]; extern char datatoc_gpu_shader_uniform_color_frag_glsl[]; +extern char datatoc_drw_shader_3D_vert_glsl[]; /* *********** LISTS *********** */ typedef struct OBJECT_PassList { @@ -409,6 +412,10 @@ static void OBJECT_engine_init(void *vedata) const DRWContextState *draw_ctx = DRW_context_state_get(); OBJECT_Shaders *sh_data = &e_data.sh_data[draw_ctx->shader_slot]; + const bool is_clip = (draw_ctx->rv3d->rflag & RV3D_CLIPPING) != 0; + const char *world_clip_lib_or_empty = is_clip ? datatoc_common_world_clip_lib_glsl : ""; + const char *world_clip_def_or_empty = is_clip ? "#define USE_WORLD_CLIP_PLANES\n" : ""; + if (!sh_data->outline_resolve) { /* Outline */ sh_data->outline_prepass = DRW_shader_create_3D(datatoc_object_outline_prepass_frag_glsl, NULL); @@ -484,7 +491,10 @@ static void OBJECT_engine_init(void *vedata) datatoc_object_lightprobe_grid_vert_glsl, NULL, datatoc_gpu_shader_flat_id_frag_glsl, NULL); /* Loose Points */ - sh_data->loose_points = DRW_shader_create_3D(datatoc_object_loose_points_frag_glsl, NULL); + sh_data->loose_points = DRW_shader_create_from_arrays({ + .vert = (const char *[]){world_clip_lib_or_empty, datatoc_drw_shader_3D_vert_glsl, NULL}, + .frag = (const char *[]){datatoc_object_loose_points_frag_glsl, NULL}, + .defs = (const char *[]){world_clip_def_or_empty, NULL}}); } { @@ -664,21 +674,27 @@ static DRWShadingGroup *shgroup_outline(DRWPass *pass, const int *ofs, GPUShader } /* currently same as 'shgroup_outline', new function to avoid confustion */ -static DRWShadingGroup *shgroup_wire(DRWPass *pass, const float col[4], GPUShader *sh) +static DRWShadingGroup *shgroup_wire(DRWPass *pass, const float col[4], GPUShader *sh, eDRW_ShaderSlot shader_slot) { DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); DRW_shgroup_uniform_vec4(grp, "color", col, 1); + if (shader_slot == DRW_SHADER_SLOT_CLIPPED) { + DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); + } return grp; } /* currently same as 'shgroup_outline', new function to avoid confustion */ -static DRWShadingGroup *shgroup_points(DRWPass *pass, const float col[4], GPUShader *sh) +static DRWShadingGroup *shgroup_points(DRWPass *pass, const float col[4], GPUShader *sh, eDRW_ShaderSlot shader_slot) { DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); DRW_shgroup_uniform_vec4(grp, "color", col, 1); DRW_shgroup_uniform_vec4(grp, "innerColor", G_draw.block.colorEditMeshMiddle, 1); + if (shader_slot == DRW_SHADER_SLOT_CLIPPED) { + DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); + } return grp; } @@ -1252,24 +1268,24 @@ static void OBJECT_cache_init(void *vedata) sgl->texspace = shgroup_instance(sgl->non_meshes, geom); /* Wires (for loose edges) */ - sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); - sgl->wire = shgroup_wire(sgl->non_meshes, gb->colorWire, sh); - sgl->wire_select = shgroup_wire(sgl->non_meshes, gb->colorSelect, sh); - sgl->wire_transform = shgroup_wire(sgl->non_meshes, gb->colorTransform, sh); - sgl->wire_active = shgroup_wire(sgl->non_meshes, gb->colorActive, sh); + sh = DRW_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR, draw_ctx->shader_slot); + sgl->wire = shgroup_wire(sgl->non_meshes, gb->colorWire, sh, draw_ctx->shader_slot); + sgl->wire_select = shgroup_wire(sgl->non_meshes, gb->colorSelect, sh, draw_ctx->shader_slot); + sgl->wire_transform = shgroup_wire(sgl->non_meshes, gb->colorTransform, sh, draw_ctx->shader_slot); + sgl->wire_active = shgroup_wire(sgl->non_meshes, gb->colorActive, sh, draw_ctx->shader_slot); /* Wire (duplicator) */ - sgl->wire_dupli = shgroup_wire(sgl->non_meshes, gb->colorDupli, sh); - sgl->wire_dupli_select = shgroup_wire(sgl->non_meshes, gb->colorDupliSelect, sh); + sgl->wire_dupli = shgroup_wire(sgl->non_meshes, gb->colorDupli, sh, draw_ctx->shader_slot); + sgl->wire_dupli_select = shgroup_wire(sgl->non_meshes, gb->colorDupliSelect, sh, draw_ctx->shader_slot); /* Points (loose points) */ sh = sh_data->loose_points; - sgl->points = shgroup_points(sgl->non_meshes, gb->colorWire, sh); - sgl->points_select = shgroup_points(sgl->non_meshes, gb->colorSelect, sh); - sgl->points_transform = shgroup_points(sgl->non_meshes, gb->colorTransform, sh); - sgl->points_active = shgroup_points(sgl->non_meshes, gb->colorActive, sh); + sgl->points = shgroup_points(sgl->non_meshes, gb->colorWire, sh, draw_ctx->shader_slot); + sgl->points_select = shgroup_points(sgl->non_meshes, gb->colorSelect, sh, draw_ctx->shader_slot); + sgl->points_transform = shgroup_points(sgl->non_meshes, gb->colorTransform, sh, draw_ctx->shader_slot); + sgl->points_active = shgroup_points(sgl->non_meshes, gb->colorActive, sh, draw_ctx->shader_slot); /* Points (duplicator) */ - sgl->points_dupli = shgroup_points(sgl->non_meshes, gb->colorDupli, sh); - sgl->points_dupli_select = shgroup_points(sgl->non_meshes, gb->colorDupliSelect, sh); + sgl->points_dupli = shgroup_points(sgl->non_meshes, gb->colorDupli, sh, draw_ctx->shader_slot); + sgl->points_dupli_select = shgroup_points(sgl->non_meshes, gb->colorDupliSelect, sh, draw_ctx->shader_slot); DRW_shgroup_state_disable(sgl->points, DRW_STATE_BLEND); DRW_shgroup_state_disable(sgl->points_select, DRW_STATE_BLEND); DRW_shgroup_state_disable(sgl->points_transform, DRW_STATE_BLEND); diff --git a/source/blender/draw/modes/shaders/drw_shader_3D_smooth_color_vert.glsl b/source/blender/draw/modes/shaders/drw_shader_3D_smooth_color_vert.glsl new file mode 100644 index 00000000000..05f9618a7f7 --- /dev/null +++ b/source/blender/draw/modes/shaders/drw_shader_3D_smooth_color_vert.glsl @@ -0,0 +1,17 @@ +/* Keep 'gpu_shader_3D_smooth_color_vert.glsl' compatible. */ +uniform mat4 ModelViewProjectionMatrix; +uniform mat4 ModelMatrix; + +in vec3 pos; +in vec4 color; + +out vec4 finalColor; + +void main() +{ + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + finalColor = color; +#ifdef USE_WORLD_CLIP_PLANES + world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); +#endif +} diff --git a/source/blender/draw/modes/shaders/drw_shader_3D_vert.glsl b/source/blender/draw/modes/shaders/drw_shader_3D_vert.glsl new file mode 100644 index 00000000000..f0d477527ce --- /dev/null +++ b/source/blender/draw/modes/shaders/drw_shader_3D_vert.glsl @@ -0,0 +1,13 @@ +/* Keep 'gpu_shader_3D_vert.glsl' compatible. */ +uniform mat4 ModelViewProjectionMatrix; +uniform mat4 ModelMatrix; + +in vec3 pos; + +void main() +{ + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); +#ifdef USE_WORLD_CLIP_PLANES + world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); +#endif +} -- cgit v1.2.3