DRW: use clipping for depth buffer

Object selection now supports clipping.
This commit is contained in:
Campbell Barton 2019-01-24 17:12:06 +11:00
parent 4d29312c66
commit 11428e0b7f
Notes: blender-bot 2023-02-14 03:59:42 +01:00
Referenced by issue #60779, 3D Viewport clipping support
6 changed files with 60 additions and 24 deletions

View File

@ -66,11 +66,15 @@ typedef struct BASIC_Data {
BASIC_StorageList *stl;
} BASIC_Data;
typedef struct BASIC_Shaders {
/* Depth Pre Pass */
struct GPUShader *depth;
} BASIC_Shaders;
/* *********** STATIC *********** */
static struct {
/* Depth Pre Pass */
struct GPUShader *depth_sh;
BASIC_Shaders sh_data[DRW_SHADER_SLOT_LEN];
} e_data = {NULL}; /* Engine data */
typedef struct BASIC_PrivateData {
@ -83,9 +87,12 @@ typedef struct BASIC_PrivateData {
static void basic_engine_init(void *UNUSED(vedata))
{
const DRWContextState *draw_ctx = DRW_context_state_get();
BASIC_Shaders *sh_data = &e_data.sh_data[draw_ctx->shader_slot];
/* Depth prepass */
if (!e_data.depth_sh) {
e_data.depth_sh = DRW_shader_create_3D_depth_only();
if (!sh_data->depth) {
sh_data->depth = DRW_shader_create_3D_depth_only(draw_ctx->shader_slot);
}
}
@ -94,6 +101,15 @@ static void basic_cache_init(void *vedata)
BASIC_PassList *psl = ((BASIC_Data *)vedata)->psl;
BASIC_StorageList *stl = ((BASIC_Data *)vedata)->stl;
const DRWContextState *draw_ctx = DRW_context_state_get();
BASIC_Shaders *sh_data = &e_data.sh_data[draw_ctx->shader_slot];
const RegionView3D *rv3d = draw_ctx->rv3d;
const bool is_clip = (rv3d->rflag & RV3D_CLIPPING) != 0;
if (is_clip) {
DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d);
}
if (!stl->g_data) {
/* Alloc transient pointers */
stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
@ -102,12 +118,18 @@ static void basic_cache_init(void *vedata)
{
psl->depth_pass = DRW_pass_create(
"Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE);
stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass);
stl->g_data->depth_shgrp = DRW_shgroup_create(sh_data->depth, psl->depth_pass);
if (rv3d->rflag & RV3D_CLIPPING) {
DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->depth_shgrp, rv3d);
}
psl->depth_pass_cull = DRW_pass_create(
"Depth Pass Cull",
DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK);
stl->g_data->depth_shgrp_cull = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass_cull);
stl->g_data->depth_shgrp_cull = DRW_shgroup_create(sh_data->depth, psl->depth_pass_cull);
if (rv3d->rflag & RV3D_CLIPPING) {
DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->depth_shgrp_cull, rv3d);
}
}
}

View File

@ -103,7 +103,7 @@ static void external_engine_init(void *UNUSED(vedata))
{
/* Depth prepass */
if (!e_data.depth_sh) {
e_data.depth_sh = DRW_shader_create_3D_depth_only();
e_data.depth_sh = DRW_shader_create_3D_depth_only(DRW_SHADER_SLOT_DEFAULT);
}
}

View File

@ -94,6 +94,16 @@ typedef struct BoundSphere {
float center[3], radius;
} BoundSphere;
/**
* Support selecting shaders with different options compiled in.
* Needed for clipping support because it means using a separate set of shaders.
*/
typedef enum eDRW_ShaderSlot {
DRW_SHADER_SLOT_DEFAULT = 0,
DRW_SHADER_SLOT_CLIPPED = 1,
} eDRW_ShaderSlot;
#define DRW_SHADER_SLOT_LEN 2
/* declare members as empty (unused) */
typedef char DRWViewportEmptyList;
@ -259,7 +269,7 @@ struct GPUShader *DRW_shader_create_with_transform_feedback(
struct GPUShader *DRW_shader_create_2D(const char *frag, const char *defines);
struct GPUShader *DRW_shader_create_3D(const char *frag, const char *defines);
struct GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *defines);
struct GPUShader *DRW_shader_create_3D_depth_only(void);
struct GPUShader *DRW_shader_create_3D_depth_only(eDRW_ShaderSlot slot);
struct GPUMaterial *DRW_shader_find_from_world(struct World *wo, const void *engine_type, int options, bool deferred);
struct GPUMaterial *DRW_shader_find_from_material(struct Material *ma, const void *engine_type, int options, bool deferred);
struct GPUMaterial *DRW_shader_create_from_world(
@ -571,16 +581,6 @@ bool DRW_state_show_text(void);
bool DRW_state_draw_support(void);
bool DRW_state_draw_background(void);
/**
* Support selecting shaders with different options compiled in.
* Needed for clipping support because it means using a separate set of shaders.
*/
typedef enum eDRW_ShaderSlot {
DRW_SHADER_SLOT_DEFAULT = 0,
DRW_SHADER_SLOT_CLIPPED = 1,
} eDRW_ShaderSlot;
#define DRW_SHADER_SLOT_LEN 2
/* Avoid too many lookups while drawing */
typedef struct DRWContextState {

View File

@ -43,7 +43,7 @@ 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[];
extern char datatoc_gpu_shader_depth_only_frag_glsl[];
/* cache of built-in shaders (each is created on first use) */
static struct {
@ -79,6 +79,15 @@ static GPUShader *drw_shader_get_builtin_shader_clipped(eGPUBuiltinShader shader
.frag = (const char *[]){datatoc_gpu_shader_3D_smooth_color_frag_glsl, NULL},
.defs = (const char *[]){world_clip_def, NULL}});
break;
case GPU_SHADER_3D_DEPTH_ONLY:
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_depth_only_frag_glsl, NULL},
.defs = (const char *[]){world_clip_def, NULL}});
break;
default:
/* Unsupported, caller asserts. */
if (r_test_only) {

View File

@ -26,8 +26,7 @@
* \ingroup draw
*/
#include "draw_manager.h"
#include "DNA_object_types.h"
#include "DNA_world_types.h"
#include "DNA_material_types.h"
@ -48,6 +47,9 @@
#include "WM_api.h"
#include "WM_types.h"
#include "draw_manager.h"
#include "draw_builtin_shader.h"
extern char datatoc_gpu_shader_2D_vert_glsl[];
extern char datatoc_gpu_shader_3D_vert_glsl[];
extern char datatoc_gpu_shader_depth_only_frag_glsl[];
@ -386,9 +388,9 @@ GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *defines)
return GPU_shader_create(datatoc_common_fullscreen_vert_glsl, frag, NULL, NULL, defines, __func__);
}
GPUShader *DRW_shader_create_3D_depth_only(void)
GPUShader *DRW_shader_create_3D_depth_only(eDRW_ShaderSlot slot)
{
return GPU_shader_get_builtin_shader(GPU_SHADER_3D_DEPTH_ONLY);
return DRW_shader_get_builtin_shader(GPU_SHADER_3D_DEPTH_ONLY, slot);
}
GPUMaterial *DRW_shader_find_from_world(World *wo, const void *engine_type, int options, bool deferred)

View File

@ -334,7 +334,7 @@ static void EDIT_MESH_engine_init(void *vedata)
.defs = (const char *[]){world_clip_def_or_empty, NULL}});
}
if (!sh_data->depth) {
sh_data->depth = DRW_shader_create_3D_depth_only();
sh_data->depth = DRW_shader_create_3D_depth_only(draw_ctx->shader_slot);
}
if (!sh_data->ghost_clear_depth) {
sh_data->ghost_clear_depth = DRW_shader_create_fullscreen(datatoc_gpu_shader_depth_only_frag_glsl, NULL);
@ -525,6 +525,9 @@ static void EDIT_MESH_cache_init(void *vedata)
"Depth Pass Hidden Wire",
DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK);
stl->g_data->depth_shgrp_hidden_wire = DRW_shgroup_create(sh_data->depth, psl->depth_hidden_wire);
if (rv3d->rflag & RV3D_CLIPPING) {
DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->fweights_shgrp, rv3d);
}
}
{