Blender V4.5
workbench_private.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BKE_context.hh"
6
7#include "DNA_camera_types.h"
8#include "DRW_render.hh"
9#include "GPU_shader.hh"
10#include "draw_manager.hh"
11#include "draw_pass.hh"
12
13#include "workbench_defines.hh"
14#include "workbench_enums.hh"
16
17#include "GPU_capabilities.hh"
18
19namespace blender::workbench {
20
21using namespace draw;
23
25 private:
27 [2 /*clip*/];
28 StaticShader resolve_[lighting_type_len][2 /*cavity*/][2 /*curvature*/][2 /*shadow*/];
29
30 StaticShader shadow_[2 /*depth_pass*/][2 /*manifold*/][2 /*cap*/];
31
32 StaticShader volume_[2 /*smoke*/][3 /*interpolation*/][2 /*coba*/][2 /*slice*/];
33
34 static gpu::StaticShaderCache<ShaderCache> &get_static_cache()
35 {
36 static gpu::StaticShaderCache<ShaderCache> static_cache;
37 return static_cache;
38 }
39
40 public:
41 static ShaderCache &get()
42 {
43 return get_static_cache().get();
44 }
45 static void release()
46 {
47 get_static_cache().release();
48 }
49
51
52 GPUShader *prepass_get(eGeometryType geometry_type,
53 ePipelineType pipeline_type,
54 eLightingType lighting_type,
55 eShaderType shader_type,
56 bool clip)
57 {
58 return prepass_[int(geometry_type)][int(pipeline_type)][int(lighting_type)][int(shader_type)]
59 [clip]
60 .get();
61 }
62
63 GPUShader *resolve_get(eLightingType lighting_type,
64 bool cavity = false,
65 bool curvature = false,
66 bool shadow = false)
67 {
68 return resolve_[int(lighting_type)][cavity][curvature][shadow].get();
69 }
70
71 GPUShader *shadow_get(bool depth_pass, bool manifold, bool cap = false)
72 {
73 return shadow_[depth_pass][manifold][cap].get();
74 }
75
76 GPUShader *volume_get(bool smoke, int interpolation, bool coba, bool slice)
77 {
78 return volume_[smoke][interpolation][coba][slice].get();
79 }
80
81 /* Transparency */
82 StaticShader transparent_resolve = {"workbench_transparent_resolve"};
83 StaticShader merge_depth = {"workbench_merge_depth"};
84
85 /* ShadowView */
87 "workbench_shadow_visibility_compute_dynamic_pass_type"};
88 StaticShader shadow_visibility_static = {"workbench_shadow_visibility_compute_static_pass_type"};
89
90 /* Outline */
91 StaticShader outline = {"workbench_effect_outline"};
92
93 /* Dof */
94 StaticShader dof_prepare = {"workbench_effect_dof_prepare"};
95 StaticShader dof_downsample = {"workbench_effect_dof_downsample"};
96 StaticShader dof_blur1 = {"workbench_effect_dof_blur1"};
97 StaticShader dof_blur2 = {"workbench_effect_dof_blur2"};
98 StaticShader dof_resolve = {"workbench_effect_dof_resolve"};
99
100 /* AA */
101 StaticShader taa_accumulation = {"workbench_taa"};
102 StaticShader smaa_edge_detect = {"workbench_smaa_stage_0"};
103 StaticShader smaa_aa_weight = {"workbench_smaa_stage_1"};
104 StaticShader smaa_resolve = {"workbench_smaa_stage_2"};
105 StaticShader overlay_depth = {"workbench_overlay_depth"};
106};
107
108struct Material {
110 /* Packed data into a int. Decoded in the shader. */
112
115 Material(::Object &ob, bool random = false);
116 Material(::Material &mat);
117
118 static uint32_t pack_data(float metallic, float roughness, float alpha);
119
120 bool is_transparent();
121};
122
124
126 Scene *scene = nullptr;
127
129 Camera *camera = nullptr;
132
134
137 bool xray_mode = false;
138
141
143
144 bool draw_cavity = false;
145 bool draw_curvature = false;
146 bool draw_shadows = false;
147 bool draw_outline = false;
148 bool draw_dof = false;
149 bool draw_aa = false;
150
151 bool draw_object_id = false;
152
153 int sample = 0;
154 int samples_len = 0;
156 bool render_finished = false;
157
158 /* Used when material_type == eMaterialType::SINGLE */
160 /* When r == -1.0 the shader uses the vertex color */
162
163 void init(const DRWContext *context, bool scene_updated, Object *camera_ob = nullptr);
164};
165
167 const char *name = nullptr;
170 bool premultiplied = false;
171 bool alpha_cutoff = false;
172
173 MaterialTexture() = default;
174 MaterialTexture(Object *ob, int material_index);
175 MaterialTexture(::Image *image, ImageUser *user = nullptr);
176};
177
178struct SceneResources;
179
184 bool draw_shadow = false;
186 bool sculpt_pbvh = false;
187
188 ObjectState(const DRWContext *draw_ctx,
189 const SceneState &scene_state,
190 const SceneResources &resources,
191 Object *ob);
192};
193
195 private:
196 /* This value must be kept in sync with the one declared at
197 * workbench_composite_info.hh (cavity_samples) */
198 static const int max_samples_ = 512;
199
201
202 int sample_ = 0;
203 int sample_count_ = 0;
204 bool curvature_enabled_ = false;
205 bool cavity_enabled_ = false;
206
207 public:
208 void init(const SceneState &scene_state, SceneResources &resources);
209 void setup_resolve_pass(PassSimple &pass, SceneResources &resources);
210
211 private:
212 void load_samples_buf(int ssao_samples);
213};
214
216 static const int jitter_tx_size = 64;
217
219 Texture matcap_tx = "matcap_tx";
220
221 TextureFromPool object_id_tx = "wb_object_id_tx";
222
226
227 Framebuffer clear_fb = {"Clear Main"};
229 Framebuffer clear_in_front_fb = {"Clear In Front"};
230
234
235 Texture jitter_tx = "wb_jitter_tx";
236
238
239 Texture missing_tx = "missing_tx";
241
242 Texture dummy_texture_tx = {"dummy_texture"};
243 Texture dummy_tile_data_tx = {"dummy_tile_data"};
244 Texture dummy_tile_array_tx = {"dummy_tile_array"};
245
246 gpu::Batch *volume_cube_batch = nullptr;
247
249 {
250 /* TODO(fclem): Auto destruction. */
252 }
253
254 void init(const SceneState &scene_state, const DRWContext *ctx);
255 void load_jitter_tx(int total_samples);
256};
257
258class MeshPass : public PassMain {
259 private:
260 using TextureSubPassKey = std::pair<GPUTexture *, eGeometryType>;
261
262 Map<TextureSubPassKey, PassMain::Sub *> texture_subpass_map_;
263
264 PassMain::Sub *passes_[geometry_type_len][shader_type_len] = {{nullptr}};
265
266 ePipelineType pipeline_;
267 eLightingType lighting_;
268 bool clip_;
269
270 bool is_empty_ = false;
271
272 PassMain::Sub &get_subpass(eGeometryType geometry_type, eShaderType shader_type);
273
274 public:
275 MeshPass(const char *name);
276
277 /* TODO: Move to draw::Pass */
278 bool is_empty() const;
279
280 void init_pass(SceneResources &resources, DRWState state, int clip_planes);
281 void init_subpasses(ePipelineType pipeline, eLightingType lighting, bool clip);
282
283 PassMain::Sub &get_subpass(eGeometryType geometry_type,
284 const MaterialTexture *texture = nullptr);
285};
286
287enum class StencilBits : uint8_t {
289 OBJECT = 1u << 0,
291};
292
294 public:
295 TextureFromPool gbuffer_normal_tx = {"gbuffer_normal_tx"};
296 TextureFromPool gbuffer_material_tx = {"gbuffer_material_tx"};
297
298 Texture shadow_depth_stencil_tx = {"shadow_depth_stencil_tx"};
299 GPUTexture *deferred_ps_stencil_tx = nullptr;
300
301 MeshPass gbuffer_ps_ = {"Opaque.Gbuffer"};
302 MeshPass gbuffer_in_front_ps_ = {"Opaque.GbufferInFront"};
303 PassSimple deferred_ps_ = {"Opaque.Deferred"};
304
305 Framebuffer gbuffer_fb = {"Opaque.Gbuffer"};
306 Framebuffer gbuffer_in_front_fb = {"Opaque.GbufferInFront"};
307 Framebuffer deferred_fb = {"Opaque.Deferred"};
308 Framebuffer clear_fb = {"Opaque.Clear"};
309
310 void sync(const SceneState &scene_state, SceneResources &resources);
311 void draw(Manager &manager,
312 View &view,
313 SceneResources &resources,
314 int2 resolution,
315 class ShadowPass *shadow_pass);
316 bool is_empty() const;
317};
318
320 public:
321 TextureFromPool accumulation_tx = {"accumulation_accumulation_tx"};
322 TextureFromPool reveal_tx = {"accumulation_reveal_tx"};
324
325 MeshPass accumulation_ps_ = {"Transparent.Accumulation"};
326 MeshPass accumulation_in_front_ps_ = {"Transparent.AccumulationInFront"};
327 PassSimple resolve_ps_ = {"Transparent.Resolve"};
329
330 void sync(const SceneState &scene_state, SceneResources &resources);
331 void draw(Manager &manager, View &view, SceneResources &resources, int2 resolution);
332 bool is_empty() const;
333};
334
336 public:
337 MeshPass main_ps_ = {"TransparentDepth.Main"};
338 Framebuffer main_fb = {"TransparentDepth.Main"};
339 MeshPass in_front_ps_ = {"TransparentDepth.InFront"};
340 Framebuffer in_front_fb = {"TransparentDepth.InFront"};
341 PassSimple merge_ps_ = {"TransparentDepth.Merge"};
342 Framebuffer merge_fb = {"TransparentDepth.Merge"};
343
344 void sync(const SceneState &scene_state, SceneResources &resources);
345 void draw(Manager &manager, View &view, SceneResources &resources);
346 bool is_empty() const;
347};
348
349#define DEBUG_SHADOW_VOLUME 0
350
352 private:
353 enum PassType { PASS = 0, FAIL, FORCED_FAIL, MAX };
354
355 class ShadowView : public View {
356 bool force_fail_method_ = false;
357 float3 light_direction_ = float3(0);
358 UniformBuffer<ExtrudedFrustum> extruded_frustum_ = {};
359 ShadowPass::PassType current_pass_type_ = PASS;
360
361 VisibilityBuf pass_visibility_buf_ = {};
362 VisibilityBuf fail_visibility_buf_ = {};
363
364 public:
365 ShadowView() : View("ShadowPass.View"){};
366
367 void setup(View &view, float3 light_direction, bool force_fail_method);
368 bool debug_object_culling(Object *ob);
369 void set_mode(PassType type);
370
371 protected:
372 virtual void compute_visibility(ObjectBoundsBuf &bounds,
373 ObjectInfosBuf &infos,
374 uint resource_len,
375 bool debug_freeze) override;
376 virtual VisibilityBuf &get_visibility_buffer() override;
377 } view_ = {};
378
379 bool enabled_;
380
381 UniformBuffer<ShadowPassData> pass_data_ = {};
382
383 /* Draws are added to both passes and the visibly compute shader selects one of them */
384 PassMain pass_ps_ = {"Shadow.Pass"};
385 PassMain fail_ps_ = {"Shadow.Fail"};
386
387 /* In some cases, we know beforehand that we need to use the fail technique */
388 PassMain forced_fail_ps_ = {"Shadow.ForcedFail"};
389
390 /* [PassType][Is Manifold][Is Cap] */
391 PassMain::Sub *passes_[PassType::MAX][2][2] = {{{nullptr}}};
392 PassMain::Sub *&get_pass_ptr(PassType type, bool manifold, bool cap = false);
393
394 TextureFromPool depth_tx_ = {};
395 Framebuffer fb_ = {};
396
397 public:
398 void init(const SceneState &scene_state, SceneResources &resources);
399 void update();
400 void sync();
401 void object_sync(SceneState &scene_state,
402 ObjectRef &ob_ref,
403 ResourceHandle handle,
404 const bool has_transp_mat);
405 void draw(Manager &manager,
406 View &view,
407 SceneResources &resources,
408 GPUTexture &depth_stencil_tx,
409 /* Needed when there are opaque "In Front" objects in the scene */
410 bool force_fail_method);
411
412 bool is_debug();
413};
414
416 bool active_ = true;
417
418 PassMain ps_ = {"Volume"};
419 Framebuffer fb_ = {"Volume"};
420
421 Texture dummy_shadow_tx_ = {"Volume.Dummy Shadow Tx"};
422 Texture dummy_volume_tx_ = {"Volume.Dummy Volume Tx"};
423 Texture dummy_coba_tx_ = {"Volume.Dummy Coba Tx"};
424
425 GPUTexture *stencil_tx_ = nullptr;
426
427 public:
428 void sync(SceneResources &resources);
429
430 void object_sync_volume(Manager &manager,
431 SceneResources &resources,
432 const SceneState &scene_state,
433 ObjectRef &ob_ref,
434 float3 color);
435
436 void object_sync_modifier(Manager &manager,
437 SceneResources &resources,
438 const SceneState &scene_state,
439 ObjectRef &ob_ref,
440 ModifierData *md);
441
442 void draw(Manager &manager, View &view, SceneResources &resources);
443
444 private:
445 void draw_slice_ps(Manager &manager,
446 SceneResources &resources,
447 PassMain::Sub &ps,
448 ObjectRef &ob_ref,
449 int slice_axis_enum,
450 float slice_depth);
451
452 void draw_volume_ps(Manager &manager,
453 SceneResources &resources,
454 PassMain::Sub &ps,
455 ObjectRef &ob_ref,
456 int taa_sample,
457 float3 slice_count,
458 float3 world_size);
459};
460
462 private:
463 bool enabled_ = false;
464
465 PassSimple ps_ = PassSimple("Workbench.Outline");
466 Framebuffer fb_ = Framebuffer("Workbench.Outline");
467
468 public:
469 void init(const SceneState &scene_state);
470 void sync(SceneResources &resources);
471 void draw(Manager &manager, SceneResources &resources);
472};
473
474class DofPass {
475 private:
476 static const int kernel_radius_ = 3;
477 static const int samples_len_ = (kernel_radius_ * 2 + 1) * (kernel_radius_ * 2 + 1);
478
479 bool enabled_ = false;
480
481 float offset_ = 0;
482
484
485 Texture source_tx_ = {};
486 Texture coc_halfres_tx_ = {};
487 TextureFromPool blur_tx_ = {};
488
489 Framebuffer downsample_fb_ = {};
490 Framebuffer blur1_fb_ = {};
491 Framebuffer blur2_fb_ = {};
492 Framebuffer resolve_fb_ = {};
493
494 PassSimple down_ps_ = {"Workbench.DoF.DownSample"};
495 PassSimple down2_ps_ = {"Workbench.DoF.DownSample2"};
496 PassSimple blur_ps_ = {"Workbench.DoF.Blur"};
497 PassSimple blur2_ps_ = {"Workbench.DoF.Blur2"};
498 PassSimple resolve_ps_ = {"Workbench.DoF.Resolve"};
499
500 float aperture_size_ = 0;
501 float distance_ = 0;
502 float invsensor_size_ = 0;
503 float near_ = 0;
504 float far_ = 0;
505 float blades_ = 0;
506 float rotation_ = 0;
507 float ratio_ = 0;
508
509 public:
510 void init(const SceneState &scene_state, const DRWContext *draw_ctx);
511 void sync(SceneResources &resources, const DRWContext *draw_ctx);
512 void draw(Manager &manager, View &view, SceneResources &resources, int2 resolution);
513 bool is_enabled();
514
515 private:
516 void setup_samples();
517};
518
520 private:
521 bool enabled_ = false;
522 /* Weight accumulated. */
523 float weight_accum_ = 0;
524 /* Samples weight for this iteration. */
525 float weights_[9] = {0};
526 /* Sum of weights. */
527 float weights_sum_ = 0;
528
529 Texture sample0_depth_tx_ = {"sample0_depth_tx"};
530 Texture sample0_depth_in_front_tx_ = {"sample0_depth_in_front_tx"};
531
532 Texture taa_accumulation_tx_ = {"taa_accumulation_tx"};
533 Texture smaa_search_tx_ = {"smaa_search_tx"};
534 Texture smaa_area_tx_ = {"smaa_area_tx"};
535 TextureFromPool smaa_edge_tx_ = {"smaa_edge_tx"};
536 TextureFromPool smaa_weight_tx_ = {"smaa_weight_tx"};
537
538 Framebuffer taa_accumulation_fb_ = {"taa_accumulation_fb"};
539 Framebuffer smaa_edge_fb_ = {"smaa_edge_fb"};
540 Framebuffer smaa_weight_fb_ = {"smaa_weight_fb"};
541 Framebuffer smaa_resolve_fb_ = {"smaa_resolve_fb"};
542 Framebuffer overlay_depth_fb_ = {"overlay_depth_fb"};
543
544 float4 smaa_viewport_metrics_ = float4(0);
545 float smaa_mix_factor_ = 0;
546
547 PassSimple taa_accumulation_ps_ = {"TAA.Accumulation"};
548 PassSimple smaa_edge_detect_ps_ = {"SMAA.EdgeDetect"};
549 PassSimple smaa_aa_weight_ps_ = {"SMAA.BlendWeights"};
550 PassSimple smaa_resolve_ps_ = {"SMAA.Resolve"};
551 PassSimple overlay_depth_ps_ = {"Overlay Depth"};
552
553 public:
555
556 void init(const SceneState &scene_state);
557 void sync(const SceneState &scene_state, SceneResources &resources);
558 void setup_view(View &view, const SceneState &scene_state);
559 void draw(
560 const DRWContext *draw_ctx,
561 Manager &manager,
562 View &view,
563 const SceneState &scene_state,
564 SceneResources &resources,
567 GPUTexture *depth_in_front_tx);
568};
569
570} // namespace blender::workbench
eContextObjectMode
@ CTX_MODE_OBJECT
unsigned int uint
struct Material Material
eV3DShadingColorType
@ V3D_SHADING_SINGLE_COLOR
static AppView * view
#define GPU_BATCH_DISCARD_SAFE(batch)
Definition GPU_batch.hh:204
void init()
View(const char *name, int view_len=1, bool procedural=false)
Definition draw_view.hh:70
virtual VisibilityBuf & get_visibility_buffer()
Definition draw_view.cc:312
detail::PassBase< command::DrawMultiBuf > Sub
Definition draw_pass.hh:490
void setup_view(View &view, const SceneState &scene_state)
void draw(const DRWContext *draw_ctx, Manager &manager, View &view, const SceneState &scene_state, SceneResources &resources, GPUTexture *depth_in_front_tx)
void sync(const SceneState &scene_state, SceneResources &resources)
void setup_resolve_pass(PassSimple &pass, SceneResources &resources)
void sync(SceneResources &resources, const DRWContext *draw_ctx)
void draw(Manager &manager, View &view, SceneResources &resources, int2 resolution)
void init_pass(SceneResources &resources, DRWState state, int clip_planes)
void init_subpasses(ePipelineType pipeline, eLightingType lighting, bool clip)
void sync(const SceneState &scene_state, SceneResources &resources)
void draw(Manager &manager, SceneResources &resources)
void sync(SceneResources &resources)
GPUShader * volume_get(bool smoke, int interpolation, bool coba, bool slice)
GPUShader * resolve_get(eLightingType lighting_type, bool cavity=false, bool curvature=false, bool shadow=false)
GPUShader * shadow_get(bool depth_pass, bool manifold, bool cap=false)
GPUShader * prepass_get(eGeometryType geometry_type, ePipelineType pipeline_type, eLightingType lighting_type, eShaderType shader_type, bool clip)
void draw(Manager &manager, View &view, SceneResources &resources, GPUTexture &depth_stencil_tx, bool force_fail_method)
void object_sync(SceneState &scene_state, ObjectRef &ob_ref, ResourceHandle handle, const bool has_transp_mat)
void sync(const SceneState &scene_state, SceneResources &resources)
void sync(const SceneState &scene_state, SceneResources &resources)
void sync(SceneResources &resources)
void object_sync_volume(Manager &manager, SceneResources &resources, const SceneState &scene_state, ObjectRef &ob_ref, float3 color)
void draw(Manager &manager, View &view, SceneResources &resources)
void object_sync_modifier(Manager &manager, SceneResources &resources, const SceneState &scene_state, ObjectRef &ob_ref, ModifierData *md)
DRWState
Definition draw_state.hh:25
@ DRW_STATE_NO_DRAW
Definition draw_state.hh:27
IMETHOD void random(Vector &a)
addDelta operator for displacement rotational velocity.
Definition frames.inl:1282
TEX_TEMPLATE DataVec texture(T, FltCoord, float=0.0f) RET
static ulong state[N]
detail::Pass< command::DrawCommandBuf > PassSimple
detail::Pass< command::DrawMultiBuf > PassMain
StorageArrayBuffer< ObjectBounds, 128 > ObjectBoundsBuf
Definition draw_view.hh:33
StorageArrayBuffer< ObjectInfos, 128 > ObjectInfosBuf
Definition draw_view.hh:34
StorageArrayBuffer< uint, 4, true > VisibilityBuf
Definition draw_view.hh:35
gpu::StaticShader StaticShader
ImageGPUTextures get_material_texture(GPUSamplerState &sampler_state)
static constexpr int geometry_type_len
static constexpr int lighting_type_len
static constexpr int shader_type_len
static constexpr int pipeline_type_len
MatBase< float, 4, 4 > float4x4
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 3 > float3
static constexpr GPUSamplerState default_sampler()
static uint32_t pack_data(float metallic, float roughness, float alpha)
ObjectState(const DRWContext *draw_ctx, const SceneState &scene_state, const SceneResources &resources, Object *ob)
UniformBuffer< WorldData > world_buf
StorageVectorBuffer< Material > material_buf
UniformArrayBuffer< float4, 6 > clip_planes_buf