Blender V5.0
workbench_state.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
6
7#include "DNA_userdef_types.h"
8
9#include "BKE_camera.h"
10#include "BKE_customdata.hh"
11#include "BKE_editmesh.hh"
12#include "BKE_mesh_types.hh"
13#include "BKE_paint.hh"
14#include "BKE_paint_bvh.hh"
15
17
18#include "DNA_world_types.h"
19
20#include "ED_paint.hh"
21#include "ED_view3d.hh"
22
23#include "GPU_capabilities.hh"
24
25namespace blender::workbench {
26
27/* Used for update detection on the render settings. */
28static bool operator!=(const View3DShading &a, const View3DShading &b)
29{
30 /* Only checks the properties that are actually used by workbench. */
31 if (a.type != b.type) {
32 return true;
33 }
34 if (a.color_type != b.color_type) {
35 return true;
36 }
37 if (a.flag != b.flag) {
38 return true;
39 }
40 if (a.light != b.light) {
41 return true;
42 }
43 if (a.background_type != b.background_type) {
44 return true;
45 }
46 if (a.cavity_type != b.cavity_type) {
47 return true;
48 }
49 if (a.wire_color_type != b.wire_color_type) {
50 return true;
51 }
52 if (StringRefNull(a.studio_light) != StringRefNull(b.studio_light)) {
53 return true;
54 }
55 if (StringRefNull(a.matcap) != StringRefNull(b.matcap)) {
56 return true;
57 }
58 if (a.shadow_intensity != b.shadow_intensity) {
59 return true;
60 }
61 if (float3(a.single_color) != float3(b.single_color)) {
62 return true;
63 }
64 if (a.studiolight_rot_z != b.studiolight_rot_z) {
65 return true;
66 }
67 if (float3(a.object_outline_color) != float3(b.object_outline_color)) {
68 return true;
69 }
70 if (a.xray_alpha != b.xray_alpha) {
71 return true;
72 }
73 if (a.xray_alpha_wire != b.xray_alpha_wire) {
74 return true;
75 }
76 if (a.cavity_valley_factor != b.cavity_valley_factor) {
77 return true;
78 }
79 if (a.cavity_ridge_factor != b.cavity_ridge_factor) {
80 return true;
81 }
82 if (float3(a.background_color) != float3(b.background_color)) {
83 return true;
84 }
85 if (a.curvature_ridge_factor != b.curvature_ridge_factor) {
86 return true;
87 }
88 if (a.curvature_valley_factor != b.curvature_valley_factor) {
89 return true;
90 }
91 return false;
92}
93
94void SceneState::init(const DRWContext *context,
95 bool scene_updated,
96 Object *camera_ob /*=nullptr*/)
97{
98 bool reset_taa = reset_taa_next_sample || scene_updated;
100
101 View3D *v3d = context->v3d;
102 RegionView3D *rv3d = context->rv3d;
103
104 scene = DEG_get_evaluated_scene(context->depsgraph);
105
106 if (assign_if_different(resolution, int2(context->viewport_size_get()))) {
107 /* In some cases, the viewport can change resolution without a call to `workbench_view_update`.
108 * This is the case when dragging a window between two screen with different DPI settings.
109 * (See #128712) */
110 reset_taa = true;
111 }
112
113 camera_object = camera_ob;
114 if (camera_object == nullptr && v3d && rv3d) {
115 camera_object = (rv3d->persp == RV3D_CAMOB) ? v3d->camera : nullptr;
116 }
119 nullptr;
120
121 object_mode = CTX_data_mode_enum_ex(context->object_edit, context->obact, context->object_mode);
122
123 /* TODO(@pragma37):
124 * Check why Workbench Next exposes OB_MATERIAL, and Workbench exposes OB_RENDER */
125 bool is_render_mode = !v3d || ELEM(v3d->shading.type, OB_RENDER, OB_MATERIAL);
126
127 const View3DShading previous_shading = shading;
128 shading = is_render_mode ? scene->display.shading : v3d->shading;
129
132
133 /* FIXME: This reproduce old behavior when workbench was separated in 2 engines.
134 * But this is a workaround for a missing update tagging. */
135 DRWState new_clip_state = RV3D_CLIPPING_ENABLED(v3d, rv3d) ? DRW_STATE_CLIP_PLANES :
137 DRWState old_clip_state = clip_planes.size() > 0 ? DRW_STATE_CLIP_PLANES : DRW_STATE_NO_DRAW;
138 if (new_clip_state != old_clip_state) {
139 reset_taa = true;
140 }
141 clip_planes.clear();
142 if (new_clip_state & DRW_STATE_CLIP_PLANES) {
143 int plane_len = (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXCLIP) ? 4 : 6;
144 for (auto i : IndexRange(plane_len)) {
145 clip_planes.append(rv3d->clip[i]);
146 }
147 }
148
149 if (shading.type < OB_SOLID) {
152 shading.xray_alpha = 0.0f;
153 }
154 else if (SHADING_XRAY_ENABLED(shading)) {
155 shading.xray_alpha = SHADING_XRAY_ALPHA(shading);
156 }
157 else {
158 shading.xray_alpha = 1.0f;
159 }
160 xray_mode = shading.xray_alpha != 1.0f;
161
162 if (xray_mode) {
163 /* Disable shading options that aren't supported in transparency mode. */
165 }
166
167 if (shading != previous_shading) {
168 reset_taa = true;
169 }
170
172 material_override = Material(shading.single_color);
173
174 background_color = float4(0.0f);
175 if (is_render_mode && scene->r.alphamode != R_ALPHAPREMUL) {
176 if (World *w = scene->world) {
177 background_color = float4(w->horr, w->horg, w->horb, 1.0f);
178 }
179 }
180
181 if (rv3d && rv3d->rflag & RV3D_GPULIGHT_UPDATE) {
182 reset_taa = true;
183 /* FIXME: This reproduce old behavior when workbench was separated in 2 engines.
184 * But this is a workaround for a missing update tagging. */
186 }
187
189 if (matrix != view_projection_matrix) {
190 view_projection_matrix = matrix;
191 reset_taa = true;
192 }
193
194 bool is_playback = context->is_playback();
195 bool is_navigating = context->is_navigating();
196
197 /* Reset complete drawing when navigating or during viewport playback or when
198 * leaving one of those states. In case of multires modifier the navigation
199 * mesh differs from the viewport mesh, so we need to be sure to restart. */
200 if (is_playback || is_navigating) {
201 reset_taa = true;
203 }
204
205 int _samples_len = U.viewport_aa;
206 if (v3d && ELEM(v3d->shading.type, OB_RENDER, OB_MATERIAL)) {
207 _samples_len = scene->display.viewport_aa;
208 }
209 else if (context->is_scene_render()) {
210 _samples_len = scene->display.render_aa;
211 }
212 if (is_navigating || is_playback) {
213 /* Only draw using SMAA or no AA when navigating. */
214 _samples_len = min_ii(_samples_len, 1);
215 }
216 /* 0 samples means no AA */
217 draw_aa = _samples_len > 0;
218 _samples_len = max_ii(_samples_len, 1);
219
220 /* Reset the TAA when we have already draw a sample, but the sample count differs from previous
221 * time. This removes render artifacts when the viewport anti-aliasing in the user preferences
222 * is set to a lower value. */
223 if (samples_len != _samples_len) {
224 samples_len = _samples_len;
225 reset_taa = true;
226 }
227
228 if (reset_taa || samples_len <= 1) {
229 sample = 0;
230 }
231 else {
232 sample++;
233 }
235
236 /* TODO(@pragma37): volumes_do */
237
240 draw_curvature = shading.flag & V3D_SHADING_CAVITY && ELEM(shading.cavity_type,
245 draw_dof = camera && camera->dof.flag & CAM_DOF_ENABLED &&
247
249};
250
251static const CustomData *get_loop_custom_data(const Mesh *mesh)
252{
253 if (mesh->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH) {
254 BLI_assert(mesh->runtime->edit_mesh != nullptr);
255 BLI_assert(mesh->runtime->edit_mesh->bm != nullptr);
256 return &mesh->runtime->edit_mesh->bm->ldata;
257 }
258 return &mesh->corner_data;
259}
260
261static const CustomData *get_vert_custom_data(const Mesh *mesh)
262{
263 if (mesh->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH) {
264 BLI_assert(mesh->runtime->edit_mesh != nullptr);
265 BLI_assert(mesh->runtime->edit_mesh->bm != nullptr);
266 return &mesh->runtime->edit_mesh->bm->vdata;
267 }
268 return &mesh->vert_data;
269}
270
272 const SceneState &scene_state,
273 const SceneResources &resources,
274 Object *ob)
275{
276 const bool is_active = (ob == draw_ctx->obact);
277
279 !draw_ctx->is_image_render();
280 draw_shadow = scene_state.draw_shadows && (ob->dtx & OB_DRAW_NO_SHADOW_CAST) == 0 &&
281 !sculpt_pbvh && !(is_active && DRW_object_use_hide_faces(ob));
282
284
285 /* Don't perform CustomData lookup unless it's really necessary, since it's quite expensive. */
286 const auto has_color = [&]() {
287 if (ob->type != OB_MESH) {
288 return false;
289 }
291 const CustomData *cd_vdata = get_vert_custom_data(&mesh);
292 const CustomData *cd_ldata = get_loop_custom_data(&mesh);
293 return CustomData_has_layer(cd_vdata, CD_PROP_COLOR) ||
297 };
298
299 const auto has_uv = [&]() {
300 if (ob->type != OB_MESH) {
301 return false;
302 }
304 const CustomData *cd_ldata = get_loop_custom_data(&mesh);
305 return CustomData_has_layer(cd_ldata, CD_PROP_FLOAT2);
306 };
307
308 if (color_type == V3D_SHADING_TEXTURE_COLOR && (!has_uv() || ob->dt < OB_TEXTURE)) {
310 }
311 else if (color_type == V3D_SHADING_VERTEX_COLOR && !has_color()) {
313 }
314
315 if (sculpt_pbvh) {
318 {
319 /* Force use of material color for sculpt. */
321 }
322
323 /* Bad call C is required to access the tool system that is context aware. Cast to non-const
324 * due to current API. */
325 bContext *C = (bContext *)draw_ctx->evil_C;
326 if (C != nullptr) {
328 C, &scene_state.scene->toolsettings->paint_mode, *ob, color_type);
329 }
330 }
331 else if (ob->type == OB_MESH && !draw_ctx->is_scene_render()) {
332 /* Force texture or vertex mode if object is in paint mode. */
333 const bool is_vertpaint_mode = is_active && (scene_state.object_mode == CTX_MODE_PAINT_VERTEX);
334 const bool is_texpaint_mode = is_active && (scene_state.object_mode == CTX_MODE_PAINT_TEXTURE);
335 if (is_vertpaint_mode && has_color()) {
337 }
338 else if (is_texpaint_mode && has_uv()) {
341 const ImagePaintSettings *imapaint = &scene_state.scene->toolsettings->imapaint;
342 if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) {
343 if (imapaint->canvas) {
347 const bool use_linear_filter = imapaint->interp == IMAGEPAINT_INTERP_LINEAR;
348 image_paint_override.sampler_state.set_filtering_flag_from_test(
349 GPU_SAMPLER_FILTERING_LINEAR, use_linear_filter);
350 }
351 else {
353 }
354 }
355 }
356 }
357
358 use_per_material_batches = image_paint_override.gpu.texture == nullptr &&
362}
363
364} // namespace blender::workbench
Camera data-block and utility functions.
@ CTX_MODE_PAINT_TEXTURE
@ CTX_MODE_PAINT_VERTEX
enum eContextObjectMode CTX_data_mode_enum_ex(const Object *obedit, const Object *ob, eObjectMode object_mode)
CustomData interface, see also DNA_customdata_types.h.
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
@ ME_WRAPPER_TYPE_BMESH
bool BKE_sculptsession_use_pbvh_draw(const Object *ob, const RegionView3D *rv3d)
Definition paint.cc:3068
A BVH for high poly meshes.
#define BLI_assert(a)
Definition BLI_assert.h:46
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
#define ELEM(...)
Scene * DEG_get_evaluated_scene(const Depsgraph *graph)
@ CAM_DOF_ENABLED
@ CD_PROP_BYTE_COLOR
@ CD_PROP_COLOR
@ CD_PROP_FLOAT2
struct Material Material
@ OB_TEXTURE
@ OB_SOLID
@ OB_RENDER
@ OB_MATERIAL
@ OB_DRAW_NO_SHADOW_CAST
@ OB_CAMERA
@ OB_MESH
#define IMAGEPAINT_MODE_IMAGE
@ R_ALPHAPREMUL
@ IMAGEPAINT_INTERP_LINEAR
eV3DShadingColorType
@ V3D_SHADING_TEXTURE_COLOR
@ V3D_SHADING_VERTEX_COLOR
@ V3D_SHADING_MATERIAL_COLOR
@ V3D_SHADING_OBJECT_COLOR
@ V3D_LIGHTING_FLAT
@ V3D_SHADING_SHADOW
@ V3D_SHADING_DEPTH_OF_FIELD
@ V3D_SHADING_OBJECT_OUTLINE
@ V3D_SHADING_CAVITY
@ V3D_SHADING_BACKFACE_CULLING
#define RV3D_LOCK_FLAGS(rv3d)
@ V3D_SHADING_CAVITY_BOTH
@ V3D_SHADING_CAVITY_SSAO
@ V3D_SHADING_CAVITY_CURVATURE
@ RV3D_GPULIGHT_UPDATE
#define RV3D_CLIPPING_ENABLED(v3d, rv3d)
@ RV3D_CAMOB
@ RV3D_BOXCLIP
T & DRW_object_get_data_for_drawing(const Object &object)
eV3DShadingColorType ED_paint_shading_color_override(bContext *C, const PaintModeSettings *settings, Object &ob, eV3DShadingColorType orig_color_type)
#define SHADING_XRAY_ALPHA(shading)
#define SHADING_XRAY_ENABLED(shading)
@ GPU_SAMPLER_EXTEND_MODE_REPEAT
@ GPU_SAMPLER_FILTERING_LINEAR
#define C
Definition RandGen.cpp:29
#define U
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
const float4x4 persmat(int view_id=0) const
Definition draw_view.hh:161
static View & default_get()
Definition draw_view.cc:317
bool DRW_object_use_hide_faces(const Object *ob)
DRWState
Definition draw_state.hh:25
@ DRW_STATE_CLIP_PLANES
Definition draw_state.hh:71
@ DRW_STATE_NO_DRAW
Definition draw_state.hh:27
@ DRW_STATE_CULL_BACK
Definition draw_state.hh:43
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:3052
bool operator!=(const CameraData &a, const CameraData &b)
static const CustomData * get_loop_custom_data(const Mesh *mesh)
static const CustomData * get_vert_custom_data(const Mesh *mesh)
static eLightingType lighting_type_from_v3d_lighting(char lighting)
bool assign_if_different(T &old_value, T new_value)
MatBase< float, 4, 4 > float4x4
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 3 > float3
bool is_image_render() const
bool is_scene_render() const
RegionView3D * rv3d
Object * obact
const bContext * evil_C
struct Image * canvas
MeshRuntimeHandle * runtime
CustomData corner_data
CustomData vert_data
float clip[6][4]
struct ToolSettings * toolsettings
struct ImagePaintSettings imapaint
struct PaintModeSettings paint_mode
float background_color[3]
float object_outline_color[3]
float curvature_valley_factor
char studio_light[256]
struct Object * camera
View3DShading shading
ObjectState(const DRWContext *draw_ctx, const SceneState &scene_state, const SceneResources &resources, Object *ob)
void init(const DRWContext *context, bool scene_updated, Object *camera_ob=nullptr)
i
Definition text_draw.cc:230