Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/space_view3d/view3d_draw.c
| Show First 20 Lines • Show All 826 Lines • ▼ Show 20 Lines | imm_draw_box_wire_2d(shdr_pos, | ||||
| v3d->render_border.xmin * region->winx, | v3d->render_border.xmin * region->winx, | ||||
| v3d->render_border.ymin * region->winy, | v3d->render_border.ymin * region->winy, | ||||
| v3d->render_border.xmax * region->winx, | v3d->render_border.xmax * region->winx, | ||||
| v3d->render_border.ymax * region->winy); | v3d->render_border.ymax * region->winy); | ||||
| immUnbindProgram(); | immUnbindProgram(); | ||||
| } | } | ||||
| void ED_view3d_draw_depth(Depsgraph *depsgraph, ARegion *region, View3D *v3d, bool alphaoverride) | |||||
| { | |||||
| struct bThemeState theme_state; | |||||
| Scene *scene = DEG_get_evaluated_scene(depsgraph); | |||||
| RegionView3D *rv3d = region->regiondata; | |||||
| short flag = v3d->flag; | |||||
| float glalphaclip = U.glalphaclip; | |||||
| /* temp set drawtype to solid */ | |||||
| /* Setting these temporarily is not nice */ | |||||
| v3d->flag &= ~V3D_SELECT_OUTLINE; | |||||
| /* not that nice but means we wont zoom into billboards */ | |||||
| U.glalphaclip = alphaoverride ? 0.5f : glalphaclip; | |||||
| /* Tools may request depth outside of regular drawing code. */ | |||||
| UI_Theme_Store(&theme_state); | |||||
| UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW); | |||||
| ED_view3d_draw_setup_view( | |||||
| G_MAIN->wm.first, NULL, depsgraph, scene, region, v3d, NULL, NULL, NULL); | |||||
| /* get surface depth without bias */ | |||||
| rv3d->rflag |= RV3D_ZOFFSET_DISABLED; | |||||
| /* Needed in cases the 3D Viewport isn't already setup. */ | |||||
| WM_draw_region_viewport_ensure(region, SPACE_VIEW3D); | |||||
| WM_draw_region_viewport_bind(region); | |||||
| GPUViewport *viewport = WM_draw_region_get_viewport(region); | |||||
| /* When Blender is starting, a click event can trigger a depth test while the viewport is not | |||||
| * yet available. */ | |||||
| if (viewport != NULL) { | |||||
| DRW_draw_depth_loop(depsgraph, region, v3d, viewport, false); | |||||
| } | |||||
| WM_draw_region_viewport_unbind(region); | |||||
| rv3d->rflag &= ~RV3D_ZOFFSET_DISABLED; | |||||
| U.glalphaclip = glalphaclip; | |||||
| v3d->flag = flag; | |||||
| UI_Theme_Restore(&theme_state); | |||||
| } | |||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Other Elements | /** \name Other Elements | ||||
| * \{ */ | * \{ */ | ||||
| /** could move this elsewhere, but tied into #ED_view3d_grid_scale */ | /** could move this elsewhere, but tied into #ED_view3d_grid_scale */ | ||||
| float ED_scene_grid_scale(const Scene *scene, const char **r_grid_unit) | float ED_scene_grid_scale(const Scene *scene, const char **r_grid_unit) | ||||
| ▲ Show 20 Lines • Show All 740 Lines • ▼ Show 20 Lines | void view3d_main_region_draw(const bContext *C, ARegion *region) | ||||
| DRW_cache_free_old_batches(bmain); | DRW_cache_free_old_batches(bmain); | ||||
| BKE_image_free_old_gputextures(bmain); | BKE_image_free_old_gputextures(bmain); | ||||
| GPU_pass_cache_garbage_collect(); | GPU_pass_cache_garbage_collect(); | ||||
| /* No depth test for drawing action zones afterwards. */ | /* No depth test for drawing action zones afterwards. */ | ||||
| GPU_depth_test(GPU_DEPTH_NONE); | GPU_depth_test(GPU_DEPTH_NONE); | ||||
| v3d->flag |= V3D_INVALID_BACKBUF; | v3d->runtime.flag &= ~V3D_RUNTIME_DEPTHBUF_OVERRIDDEN; | ||||
| /* TODO: Clear cache? */ | |||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Offscreen Drawing | /** \name Offscreen Drawing | ||||
| * \{ */ | * \{ */ | ||||
| ▲ Show 20 Lines • Show All 517 Lines • ▼ Show 20 Lines | |||||
| * \note Only use in object mode. | * \note Only use in object mode. | ||||
| */ | */ | ||||
| static void validate_object_select_id(struct Depsgraph *depsgraph, | static void validate_object_select_id(struct Depsgraph *depsgraph, | ||||
| ViewLayer *view_layer, | ViewLayer *view_layer, | ||||
| ARegion *region, | ARegion *region, | ||||
| View3D *v3d, | View3D *v3d, | ||||
| Object *obact) | Object *obact) | ||||
| { | { | ||||
| /* TODO: Use a flag in the selection engine itself. */ | |||||
| if (v3d->runtime.flag & V3D_RUNTIME_DEPTHBUF_OVERRIDDEN) { | |||||
| return; | |||||
| } | |||||
| Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact); | Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact); | ||||
| BLI_assert(region->regiontype == RGN_TYPE_WINDOW); | BLI_assert(region->regiontype == RGN_TYPE_WINDOW); | ||||
| UNUSED_VARS_NDEBUG(region); | UNUSED_VARS_NDEBUG(region); | ||||
| if (obact_eval && (obact_eval->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) || | if (obact_eval && (obact_eval->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) || | ||||
| BKE_paint_select_face_test(obact_eval))) { | BKE_paint_select_face_test(obact_eval))) { | ||||
| /* do nothing */ | /* do nothing */ | ||||
| } | } | ||||
| /* texture paint mode sampling */ | /* texture paint mode sampling */ | ||||
| else if (obact_eval && (obact_eval->mode & OB_MODE_TEXTURE_PAINT) && | else if (obact_eval && (obact_eval->mode & OB_MODE_TEXTURE_PAINT) && | ||||
| (v3d->shading.type > OB_WIRE)) { | (v3d->shading.type > OB_WIRE)) { | ||||
| /* do nothing */ | /* do nothing */ | ||||
| } | } | ||||
| else if ((obact_eval && (obact_eval->mode & OB_MODE_PARTICLE_EDIT)) && !XRAY_ENABLED(v3d)) { | else if ((obact_eval && (obact_eval->mode & OB_MODE_PARTICLE_EDIT)) && !XRAY_ENABLED(v3d)) { | ||||
| /* do nothing */ | /* do nothing */ | ||||
| } | } | ||||
| else { | else { | ||||
| v3d->flag &= ~V3D_INVALID_BACKBUF; | v3d->runtime.flag |= V3D_RUNTIME_DEPTHBUF_OVERRIDDEN; | ||||
| return; | |||||
| } | |||||
| if (!(v3d->flag & V3D_INVALID_BACKBUF)) { | |||||
| return; | return; | ||||
| } | } | ||||
| if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0)) { | if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0)) { | ||||
| Base *base = BKE_view_layer_base_find(view_layer, obact); | Base *base = BKE_view_layer_base_find(view_layer, obact); | ||||
| DRW_select_buffer_context_create(&base, 1, -1); | DRW_select_buffer_context_create(&base, 1, -1); | ||||
| } | } | ||||
| /* TODO: Create a flag in `DRW_manager` because the drawing is no longer | v3d->runtime.flag |= V3D_RUNTIME_DEPTHBUF_OVERRIDDEN; | ||||
| * made on the back-buffer in this case. */ | |||||
| v3d->flag &= ~V3D_INVALID_BACKBUF; | |||||
| } | } | ||||
| /* TODO: Creating, attaching texture, and destroying a framebuffer is quite slow. | /* TODO: Creating, attaching texture, and destroying a framebuffer is quite slow. | ||||
| * Calling this function should be avoided during interactive drawing. */ | * Calling this function should be avoided during interactive drawing. */ | ||||
| static void view3d_opengl_read_Z_pixels(GPUViewport *viewport, rcti *rect, void *data) | static void view3d_opengl_read_Z_pixels(GPUViewport *viewport, rcti *rect, void *data) | ||||
| { | { | ||||
| DefaultTextureList *dtxl = (DefaultTextureList *)GPU_viewport_texture_list_get(viewport); | DefaultTextureList *dtxl = (DefaultTextureList *)GPU_viewport_texture_list_get(viewport); | ||||
| Show All 10 Lines | GPU_framebuffer_read_depth(tmp_fb, | ||||
| data); | data); | ||||
| GPU_framebuffer_restore(); | GPU_framebuffer_restore(); | ||||
| GPU_framebuffer_free(tmp_fb); | GPU_framebuffer_free(tmp_fb); | ||||
| } | } | ||||
| void ED_view3d_select_id_validate(ViewContext *vc) | void ED_view3d_select_id_validate(ViewContext *vc) | ||||
| { | { | ||||
| /* TODO: Create a flag in `DRW_manager` because the drawing is no longer | |||||
| * made on the back-buffer in this case. */ | |||||
| if (vc->v3d->flag & V3D_INVALID_BACKBUF) { | |||||
| validate_object_select_id(vc->depsgraph, vc->view_layer, vc->region, vc->v3d, vc->obact); | validate_object_select_id(vc->depsgraph, vc->view_layer, vc->region, vc->v3d, vc->obact); | ||||
| } | } | ||||
| } | |||||
| void ED_view3d_backbuf_depth_validate(ViewContext *vc) | |||||
| { | |||||
| if (vc->v3d->flag & V3D_INVALID_BACKBUF) { | |||||
| ARegion *region = vc->region; | |||||
| Object *obact_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact); | |||||
| if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0)) { | |||||
| GPUViewport *viewport = WM_draw_region_get_viewport(region); | |||||
| DRW_draw_depth_object(vc->scene, vc->region, vc->v3d, viewport, obact_eval); | |||||
| } | |||||
| vc->v3d->flag &= ~V3D_INVALID_BACKBUF; | |||||
| } | |||||
| } | |||||
| /** | /** | ||||
| * allow for small values [0.5 - 2.5], | * allow for small values [0.5 - 2.5], | ||||
| * and large values, FLT_MAX by clamping by the area size | * and large values, FLT_MAX by clamping by the area size | ||||
| */ | */ | ||||
| int ED_view3d_backbuf_sample_size_clamp(ARegion *region, const float dist) | int ED_view3d_backbuf_sample_size_clamp(ARegion *region, const float dist) | ||||
| { | { | ||||
| return (int)min_ff(ceilf(dist), (float)max_ii(region->winx, region->winx)); | return (int)min_ff(ceilf(dist), (float)max_ii(region->winx, region->winx)); | ||||
| ▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | if (d->damaged) { | ||||
| /* Range is assumed to be this as they are never changed. */ | /* Range is assumed to be this as they are never changed. */ | ||||
| d->depth_range[0] = 0.0; | d->depth_range[0] = 0.0; | ||||
| d->depth_range[1] = 1.0; | d->depth_range[1] = 1.0; | ||||
| d->damaged = false; | d->damaged = false; | ||||
| } | } | ||||
| } | } | ||||
| /* Note, with nouveau drivers the glReadPixels() is very slow. T24339. */ | /* Note, with nouveau drivers the glReadPixels() is very slow. T24339. */ | ||||
| void ED_view3d_depth_update(ARegion *region) | static void view3d_depth_cache_update(ARegion *region) | ||||
| { | { | ||||
| RegionView3D *rv3d = region->regiondata; | RegionView3D *rv3d = region->regiondata; | ||||
| /* Create storage for, and, if necessary, copy depth buffer. */ | /* Create storage for, and, if necessary, copy depth buffer. */ | ||||
| if (!rv3d->depths) { | if (!rv3d->depths) { | ||||
| rv3d->depths = MEM_callocN(sizeof(ViewDepths), "ViewDepths"); | rv3d->depths = MEM_callocN(sizeof(ViewDepths), "ViewDepths"); | ||||
| } | } | ||||
| if (rv3d->depths) { | if (rv3d->depths) { | ||||
| ViewDepths *d = rv3d->depths; | ViewDepths *d = rv3d->depths; | ||||
| if (d->w != region->winx || d->h != region->winy || !d->depths) { | if (d->w != region->winx || d->h != region->winy || !d->depths) { | ||||
| d->w = region->winx; | d->w = region->winx; | ||||
| d->h = region->winy; | d->h = region->winy; | ||||
| if (d->depths) { | if (d->depths) { | ||||
| MEM_freeN(d->depths); | MEM_freeN(d->depths); | ||||
| } | } | ||||
| d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths"); | d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths"); | ||||
| d->damaged = true; | d->damaged = true; | ||||
| } | } | ||||
| if (d->damaged) { | if (d->damaged) { | ||||
| GPUViewport *viewport = WM_draw_region_get_viewport(region); | GPUViewport *viewport = WM_draw_region_get_viewport(region); | ||||
| rcti r = { | DefaultFramebufferList *fbl = GPU_viewport_framebuffer_list_get(viewport); | ||||
| .xmin = 0, | GPU_framebuffer_read_depth(fbl->depth_only_fb, 0, 0, d->w, d->h, GPU_DATA_FLOAT, d->depths); | ||||
| .xmax = d->w, | |||||
| .ymin = 0, | |||||
| .ymax = d->h, | |||||
| }; | |||||
| view3d_opengl_read_Z_pixels(viewport, &r, d->depths); | |||||
| /* Assumed to be this as they are never changed. */ | /* Assumed to be this as they are never changed. */ | ||||
| d->depth_range[0] = 0.0; | d->depth_range[0] = 0.0; | ||||
| d->depth_range[1] = 1.0; | d->depth_range[1] = 1.0; | ||||
| d->damaged = false; | d->damaged = false; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| Show All 16 Lines | while (i--) { | ||||
| if ((depth < far) && (depth > near)) { | if ((depth < far) && (depth > near)) { | ||||
| far = depth; | far = depth; | ||||
| } | } | ||||
| } | } | ||||
| return far == far_real ? FLT_MAX : far; | return far == far_real ? FLT_MAX : far; | ||||
| } | } | ||||
| void ED_view3d_draw_depth_gpencil(Depsgraph *depsgraph, Scene *scene, ARegion *region, View3D *v3d) | /** | ||||
| * Redraw the viewport depth buffer. | |||||
| * | |||||
| * \param mode: V3D_DEPTH_NO_GPENCIL - Redraw viewport without Grease Pencil and Annotations. | |||||
| * V3D_DEPTH_GPENCIL_ONLY - Redraw viewport with Grease Pencil and Annotations only. | |||||
| * V3D_DEPTH_OBJECT_ONLY - Redraw viewport with active object only. | |||||
| * \param update_cache: If true, store the entire depth buffer in #rv3d->depths. | |||||
| */ | |||||
| void ED_view3d_depth_override(Depsgraph *depsgraph, | |||||
| ARegion *region, | |||||
| View3D *v3d, | |||||
| Object *obact, | |||||
| eV3DDepthOverrideMode mode, | |||||
| bool update_cache) | |||||
| { | { | ||||
| /* Setup view matrix. */ | if (v3d->runtime.flag & V3D_RUNTIME_DEPTHBUF_OVERRIDDEN) { | ||||
| ED_view3d_draw_setup_view(NULL, NULL, depsgraph, scene, region, v3d, NULL, NULL, NULL); | return; | ||||
| } | |||||
| struct bThemeState theme_state; | |||||
| Scene *scene = DEG_get_evaluated_scene(depsgraph); | |||||
| RegionView3D *rv3d = region->regiondata; | |||||
| GPU_clear_depth(1.0f); | short flag = v3d->flag; | ||||
| /* temp set drawtype to solid */ | |||||
| /* Setting these temporarily is not nice */ | |||||
| v3d->flag &= ~V3D_SELECT_OUTLINE; | |||||
| GPU_depth_test(GPU_DEPTH_LESS_EQUAL); | /* Tools may request depth outside of regular drawing code. */ | ||||
| UI_Theme_Store(&theme_state); | |||||
| UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW); | |||||
| ED_view3d_draw_setup_view( | |||||
| G_MAIN->wm.first, NULL, depsgraph, scene, region, v3d, NULL, NULL, NULL); | |||||
| /* get surface depth without bias */ | |||||
| rv3d->rflag |= RV3D_ZOFFSET_DISABLED; | |||||
| /* Needed in cases the 3D Viewport isn't already setup. */ | |||||
| WM_draw_region_viewport_ensure(region, SPACE_VIEW3D); | |||||
| WM_draw_region_viewport_bind(region); | |||||
| GPUViewport *viewport = WM_draw_region_get_viewport(region); | GPUViewport *viewport = WM_draw_region_get_viewport(region); | ||||
| /* When Blender is starting, a click event can trigger a depth test while the viewport is not | |||||
| * yet available. */ | |||||
| if (viewport != NULL) { | |||||
| switch (mode) { | |||||
| case V3D_DEPTH_NO_GPENCIL: | |||||
| DRW_draw_depth_loop(depsgraph, region, v3d, viewport); | |||||
| break; | |||||
| case V3D_DEPTH_GPENCIL_ONLY: | |||||
| DRW_draw_depth_loop_gpencil(depsgraph, region, v3d, viewport); | DRW_draw_depth_loop_gpencil(depsgraph, region, v3d, viewport); | ||||
| break; | |||||
| case V3D_DEPTH_OBJECT_ONLY: | |||||
| DRW_draw_depth_object( | |||||
| scene, region, v3d, viewport, DEG_get_evaluated_object(depsgraph, obact)); | |||||
| break; | |||||
| } | |||||
| GPU_depth_test(GPU_DEPTH_NONE); | if (rv3d->depths != NULL) { | ||||
| rv3d->depths->damaged = true; | |||||
| /* TODO: Clear cache? */ | |||||
| } | |||||
| if (update_cache) { | |||||
| view3d_depth_cache_update(region); | |||||
| } | |||||
| } | |||||
| WM_draw_region_viewport_unbind(region); | |||||
| rv3d->rflag &= ~RV3D_ZOFFSET_DISABLED; | |||||
| v3d->flag = flag; | |||||
| v3d->runtime.flag |= V3D_RUNTIME_DEPTHBUF_OVERRIDDEN; | |||||
| UI_Theme_Restore(&theme_state); | |||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Custom-data Utilities | /** \name Custom-data Utilities | ||||
| * \{ */ | * \{ */ | ||||
| ▲ Show 20 Lines • Show All 217 Lines • Show Last 20 Lines | |||||