Blender V4.3
overlay_grid.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2019 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "BLI_math_color.h"
10
11#include "DRW_render.hh"
12
13#include "DNA_camera_types.h"
14#include "DNA_screen_types.h"
15
17
18#include "ED_image.hh"
19#include "ED_view3d.hh"
20
21#include "UI_resources.hh"
22
24#include "overlay_private.hh"
25
26using namespace blender::draw;
27
29
31
33{
34 OVERLAY_PrivateData *pd = vedata->stl->pd;
35 OVERLAY_GridData *grid = &pd->grid_data;
36 const DRWContextState *draw_ctx = DRW_context_state_get();
37
38 float *grid_axes = pd->grid.grid_axes;
39 float *zplane_axes = pd->grid.zplane_axes;
40 float grid_steps[SI_GRID_STEPS_LEN] = {
41 0.001f, 0.01f, 0.1f, 1.0f, 10.0f, 100.0f, 1000.0f, 10000.0f};
42 float grid_steps_y[SI_GRID_STEPS_LEN] = {0.0f}; /* When zero, use value from grid_steps. */
43 OVERLAY_GridBits grid_flag = OVERLAY_GridBits(0), zneg_flag = OVERLAY_GridBits(0),
44 zpos_flag = OVERLAY_GridBits(0);
45 grid->line_size = max_ff(0.0f, U.pixelsize - 1.0f) * 0.5f;
46 /* Default, nothing is drawn. */
48
49 if (pd->space_type == SPACE_IMAGE) {
50 SpaceImage *sima = (SpaceImage *)draw_ctx->space_data;
51 View2D *v2d = &draw_ctx->region->v2d;
52
53 /* Only UV Edit mode has the various Overlay options for now. */
54 const bool is_uv_edit = sima->mode == SI_MODE_UV;
55
56 const bool background_enabled = is_uv_edit ? (!pd->hide_overlays &&
57 (sima->overlay.flag &
59 true;
60 if (background_enabled) {
61 grid_flag = GRID_BACK | PLANE_IMAGE;
62 if (sima->flag & SI_GRID_OVER_IMAGE) {
63 grid_flag = PLANE_IMAGE;
64 }
65 }
66
67 const bool draw_grid = is_uv_edit || !ED_space_image_has_buffer(sima);
68 if (background_enabled && draw_grid) {
69 grid_flag |= SHOW_GRID;
70 if (is_uv_edit) {
72 grid_flag |= CUSTOM_GRID;
73 }
74 }
75 }
76
77 grid->distance = 1.0f;
78 copy_v3_fl3(grid->size, 1.0f, 1.0f, 1.0f);
79 if (is_uv_edit) {
80 grid->size[0] = float(sima->tile_grid_shape[0]);
81 grid->size[1] = float(sima->tile_grid_shape[1]);
82 }
83
84 grid->zoom_factor = ED_space_image_zoom_level(v2d, SI_GRID_STEPS_LEN);
85 ED_space_image_grid_steps(sima, grid_steps, grid_steps_y, SI_GRID_STEPS_LEN);
86 }
87 else {
88 /* SPACE_VIEW3D */
89 View3D *v3d = draw_ctx->v3d;
90 Scene *scene = draw_ctx->scene;
91 RegionView3D *rv3d = draw_ctx->rv3d;
92
93 const bool show_axis_x = (pd->v3d_gridflag & V3D_SHOW_X) != 0;
94 const bool show_axis_y = (pd->v3d_gridflag & V3D_SHOW_Y) != 0;
95 const bool show_axis_z = (pd->v3d_gridflag & V3D_SHOW_Z) != 0;
96 const bool show_floor = (pd->v3d_gridflag & V3D_SHOW_FLOOR) != 0;
97 const bool show_ortho_grid = (pd->v3d_gridflag & V3D_SHOW_ORTHO_GRID) != 0;
98
101 {
102 return;
103 }
104
105 float viewinv[4][4], wininv[4][4];
106 float viewmat[4][4], winmat[4][4];
107 DRW_view_winmat_get(nullptr, winmat, false);
108 DRW_view_winmat_get(nullptr, wininv, true);
109 DRW_view_viewmat_get(nullptr, viewmat, false);
110 DRW_view_viewmat_get(nullptr, viewinv, true);
111
112 /* If perspective view or non-axis aligned view. */
113 if (winmat[3][3] == 0.0f || rv3d->view == RV3D_VIEW_USER) {
114 if (show_axis_x) {
115 grid_flag |= PLANE_XY | SHOW_AXIS_X;
116 }
117 if (show_axis_y) {
118 grid_flag |= PLANE_XY | SHOW_AXIS_Y;
119 }
120 if (show_floor) {
121 grid_flag |= PLANE_XY | SHOW_GRID;
122 }
123 }
124 else {
125 if (show_ortho_grid && ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT)) {
127 }
128 else if (show_ortho_grid && ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) {
130 }
131 else if (show_ortho_grid && ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) {
133 }
134 }
135
136 grid_axes[0] = float((grid_flag & (PLANE_XZ | PLANE_XY)) != 0);
137 grid_axes[1] = float((grid_flag & (PLANE_YZ | PLANE_XY)) != 0);
138 grid_axes[2] = float((grid_flag & (PLANE_YZ | PLANE_XZ)) != 0);
139
140 /* Z axis if needed */
141 if (((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) && show_axis_z) {
142 zpos_flag = SHOW_AXIS_Z;
143
144 float zvec[3], campos[3];
145 negate_v3_v3(zvec, viewinv[2]);
146 copy_v3_v3(campos, viewinv[3]);
147
148 /* z axis : chose the most facing plane */
149 if (fabsf(zvec[0]) < fabsf(zvec[1])) {
150 zpos_flag |= PLANE_XZ;
151 }
152 else {
153 zpos_flag |= PLANE_YZ;
154 }
155
156 zneg_flag = zpos_flag;
157
158 /* Perspective: If camera is below floor plane, we switch clipping.
159 * Orthographic: If eye vector is looking up, we switch clipping. */
160 if (((winmat[3][3] == 0.0f) && (campos[2] > 0.0f)) ||
161 ((winmat[3][3] != 0.0f) && (zvec[2] < 0.0f)))
162 {
163 zpos_flag |= CLIP_ZPOS;
164 zneg_flag |= CLIP_ZNEG;
165 }
166 else {
167 zpos_flag |= CLIP_ZNEG;
168 zneg_flag |= CLIP_ZPOS;
169 }
170
171 zplane_axes[0] = float((zpos_flag & (PLANE_XZ | PLANE_XY)) != 0);
172 zplane_axes[1] = float((zpos_flag & (PLANE_YZ | PLANE_XY)) != 0);
173 zplane_axes[2] = float((zpos_flag & (PLANE_YZ | PLANE_XZ)) != 0);
174 }
175 else {
176 zneg_flag = zpos_flag = CLIP_ZNEG | CLIP_ZPOS;
177 }
178
179 float dist;
180 if (rv3d->persp == RV3D_CAMOB && v3d->camera && v3d->camera->type == OB_CAMERA) {
181 Object *camera_object = DEG_get_evaluated_object(draw_ctx->depsgraph, v3d->camera);
182 dist = ((Camera *)(camera_object->data))->clip_end;
183 grid_flag |= GRID_CAMERA;
184 zneg_flag |= GRID_CAMERA;
185 zpos_flag |= GRID_CAMERA;
186 }
187 else {
188 dist = v3d->clip_end;
189 }
190
191 if (winmat[3][3] == 0.0f) {
192 copy_v3_fl(grid->size, dist);
193 }
194 else {
195 float viewdist = 1.0f / min_ff(fabsf(winmat[0][0]), fabsf(winmat[1][1]));
196 copy_v3_fl(grid->size, viewdist * dist);
197 }
198
199 grid->distance = dist / 2.0f;
200
201 ED_view3d_grid_steps(scene, v3d, rv3d, grid_steps);
202
203 if ((v3d->flag & (V3D_XR_SESSION_SURFACE | V3D_XR_SESSION_MIRROR)) != 0) {
204 /* The calculations for the grid parameters assume that the view matrix has no scale
205 * component, which may not be correct if the user is "shrunk" or "enlarged" by zooming in or
206 * out. Therefore, we need to compensate the values here. */
207 /* Assumption is uniform scaling (all column vectors are of same length). */
208 float viewinvscale = len_v3(viewinv[0]);
209 grid->distance *= viewinvscale;
210 }
211 }
212
213 /* Convert to UBO alignment. */
214 for (int i = 0; i < SI_GRID_STEPS_LEN; i++) {
215 grid->steps[i][0] = grid_steps[i];
216 grid->steps[i][1] = (grid_steps_y[i] != 0.0f) ? grid_steps_y[i] : grid_steps[i];
217 }
218 pd->grid.grid_flag = grid_flag;
219 pd->grid.zneg_flag = zneg_flag;
220 pd->grid.zpos_flag = zpos_flag;
221}
222
224{
225 OVERLAY_StorageList *stl = vedata->stl;
226 OVERLAY_PrivateData *pd = stl->pd;
227 OVERLAY_GridData *grid = &pd->grid_data;
228
229 OVERLAY_PassList *psl = vedata->psl;
231
232 psl->grid_ps = nullptr;
233
234 if ((pd->grid.grid_flag == 0 && pd->grid.zpos_flag == 0) || !DRW_state_is_fbo()) {
235 return;
236 }
237
238 GPUUniformBuf *&grid_ubo = reinterpret_cast<Instance *>(vedata->instance)->grid_ubo;
239 if (grid_ubo == nullptr) {
240 grid_ubo = GPU_uniformbuf_create(sizeof(OVERLAY_GridData));
241 }
242 GPU_uniformbuf_update(grid_ubo, &pd->grid_data);
243
246
247 if (pd->space_type == SPACE_IMAGE) {
248 float mat[4][4];
249
250 /* Add quad background. */
253 float color_back[4];
255 DRW_shgroup_uniform_vec4_copy(grp, "ucolor", color_back);
256 DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
257 unit_m4(mat);
258 mat[0][0] = grid->size[0];
259 mat[1][1] = grid->size[1];
260 mat[2][2] = grid->size[2];
262 }
263
264 {
265 DRWShadingGroup *grp;
266 blender::gpu::Batch *geom = DRW_cache_grid_get();
267
269
270 /* Create 3 quads to render ordered transparency Z axis */
271 grp = DRW_shgroup_create(sh, psl->grid_ps);
272 DRW_shgroup_uniform_block(grp, "grid_buf", grid_ubo);
273 DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
274 DRW_shgroup_uniform_texture_ref(grp, "depth_tx", &dtxl->depth);
275
276 DRW_shgroup_uniform_int_copy(grp, "grid_flag", pd->grid.zneg_flag);
277 DRW_shgroup_uniform_vec3_copy(grp, "plane_axes", pd->grid.zplane_axes);
278 if (pd->grid.zneg_flag & SHOW_AXIS_Z) {
279 DRW_shgroup_call(grp, geom, nullptr);
280 }
281
282 grp = DRW_shgroup_create_sub(grp);
283 DRW_shgroup_uniform_int_copy(grp, "grid_flag", pd->grid.grid_flag);
284 DRW_shgroup_uniform_vec3_copy(grp, "plane_axes", pd->grid.grid_axes);
285 if (pd->grid.grid_flag) {
286 DRW_shgroup_call(grp, geom, nullptr);
287 }
288
289 grp = DRW_shgroup_create_sub(grp);
290 DRW_shgroup_uniform_int_copy(grp, "grid_flag", pd->grid.zpos_flag);
291 DRW_shgroup_uniform_vec3_copy(grp, "plane_axes", pd->grid.zplane_axes);
292 if (pd->grid.zpos_flag & SHOW_AXIS_Z) {
293 DRW_shgroup_call(grp, geom, nullptr);
294 }
295 }
296
297 if (pd->space_type == SPACE_IMAGE) {
298 float theme_color[4];
299 UI_GetThemeColorShade4fv(TH_BACK, 60, theme_color);
300 srgb_to_linearrgb_v4(theme_color, theme_color);
301
302 float mat[4][4];
303 /* add wire border */
306 DRW_shgroup_uniform_vec4_copy(grp, "ucolor", theme_color);
307 unit_m4(mat);
308 for (int x = 0; x < grid->size[0]; x++) {
309 mat[3][0] = x;
310 for (int y = 0; y < grid->size[1]; y++) {
311 mat[3][1] = y;
313 }
314 }
315 }
316}
317
319{
320 OVERLAY_PassList *psl = vedata->psl;
321
322 if (psl->grid_ps) {
324 }
325}
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
MINLINE void srgb_to_linearrgb_v4(float linear[4], const float srgb[4])
void unit_m4(float m[4][4])
Definition rct.c:1127
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_v3_v3(float r[3], const float a[3])
void interp_v4_v4v4(float r[4], const float a[4], const float b[4], float t)
Definition math_vector.c:45
MINLINE void copy_v3_fl3(float v[3], float x, float y, float z)
MINLINE void copy_v3_fl(float r[3], float f)
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
#define ELEM(...)
Object * DEG_get_evaluated_object(const Depsgraph *depsgraph, Object *object)
@ OB_CAMERA
@ SI_GRID_OVER_IMAGE
@ SI_OVERLAY_SHOW_GRID_BACKGROUND
@ SPACE_IMAGE
#define SI_GRID_STEPS_LEN
@ SI_GRID_SHAPE_DYNAMIC
@ SI_MODE_UV
@ V3D_SHOW_FLOOR
@ V3D_SHOW_Z
@ V3D_SHOW_X
@ V3D_SHOW_Y
@ V3D_SHOW_ORTHO_GRID
@ RV3D_CAMOB
@ RV3D_ORTHO
@ V3D_XR_SESSION_SURFACE
@ V3D_XR_SESSION_MIRROR
@ RV3D_VIEW_FRONT
@ RV3D_VIEW_BOTTOM
@ RV3D_VIEW_LEFT
@ RV3D_VIEW_RIGHT
@ RV3D_VIEW_TOP
@ RV3D_VIEW_BACK
@ RV3D_VIEW_USER
#define DRW_PASS_CREATE(pass, state)
#define DRW_shgroup_uniform_block(shgroup, name, ubo)
#define DRW_shgroup_call_obmat(shgroup, geom, obmat)
#define DRW_shgroup_call(shgroup, geom, ob)
float ED_space_image_zoom_level(const View2D *v2d, int grid_dimension)
bool ED_space_image_has_buffer(SpaceImage *sima)
void ED_space_image_grid_steps(SpaceImage *sima, float grid_steps_x[SI_GRID_STEPS_LEN], float grid_steps_y[SI_GRID_STEPS_LEN], int grid_dimension)
void ED_view3d_grid_steps(const Scene *scene, const View3D *v3d, const RegionView3D *rv3d, float r_grid_steps[8])
#define GPU_uniformbuf_create(size)
void GPU_uniformbuf_update(GPUUniformBuf *ubo, const void *data)
@ TH_BACK
void UI_GetThemeColorShade4fv(int colorid, int offset, float col[4])
struct GPUShader GPUShader
unsigned int U
Definition btGjkEpa3.h:78
A running instance of the engine.
#define fabsf(x)
blender::gpu::Batch * DRW_cache_quad_get()
blender::gpu::Batch * DRW_cache_quad_wires_get()
blender::gpu::Batch * DRW_cache_grid_get()
DRW_Global G_draw
DefaultTextureList * DRW_viewport_texture_list_get()
const DRWContextState * DRW_context_state_get()
bool DRW_state_is_fbo()
DRWShadingGroup * DRW_shgroup_create(GPUShader *shader, DRWPass *pass)
void DRW_shgroup_uniform_vec3_copy(DRWShadingGroup *shgroup, const char *name, const float *value)
DRWShadingGroup * DRW_shgroup_create_sub(DRWShadingGroup *shgroup)
void DRW_view_winmat_get(const DRWView *view, float mat[4][4], bool inverse)
void DRW_shgroup_uniform_int_copy(DRWShadingGroup *shgroup, const char *name, const int value)
void DRW_shgroup_uniform_vec4_copy(DRWShadingGroup *shgroup, const char *name, const float *value)
void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex)
void DRW_view_viewmat_get(const DRWView *view, float mat[4][4], bool inverse)
void DRW_draw_pass(DRWPass *pass)
DRWState
Definition draw_state.hh:25
@ DRW_STATE_BLEND_ALPHA
Definition draw_state.hh:55
@ DRW_STATE_WRITE_COLOR
Definition draw_state.hh:30
draw_view in_light_buf[] float
static ulong state[N]
BLI_STATIC_ASSERT(MBC_BATCH_LEN< 32, "Number of batches exceeded the limit of bit fields")
void OVERLAY_grid_draw(OVERLAY_Data *vedata)
void OVERLAY_grid_cache_init(OVERLAY_Data *vedata)
void OVERLAY_grid_init(OVERLAY_Data *vedata)
GPUShader * OVERLAY_shader_grid_background()
GPUShader * OVERLAY_shader_grid()
GPUShader * OVERLAY_shader_grid_image()
#define OVERLAY_GRID_STEPS_LEN
Depsgraph * depsgraph
ARegion * region
RegionView3D * rv3d
SpaceLink * space_data
GlobalsUboStorage block
GPUUniformBuf * block_ubo
OVERLAY_PassList * psl
OVERLAY_StorageList * stl
OVERLAY_GridBits grid_flag
OVERLAY_GridBits zneg_flag
struct OVERLAY_PrivateData::@226 grid
OVERLAY_GridData grid_data
OVERLAY_GridBits zpos_flag
OVERLAY_PrivateData * pd
int tile_grid_shape[2]
SpaceImageOverlay overlay
struct Object * camera