Blender V4.3
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 "DNA_camera_types.h"
6#include "DRW_render.hh"
7#include "draw_manager.hh"
8#include "draw_pass.hh"
9
10#include "workbench_defines.hh"
11#include "workbench_enums.hh"
13
14#include "GPU_capabilities.hh"
15
17
18namespace blender::workbench {
19
20using namespace draw;
21
23 private:
24 std::string info_name_;
25 GPUShader *shader_ = nullptr;
26
27 public:
28 StaticShader(std::string info_name) : info_name_(info_name) {}
29
30 StaticShader() = default;
31 StaticShader(StaticShader &&other) = default;
32 StaticShader &operator=(StaticShader &&other) = default;
33
35 {
36 DRW_SHADER_FREE_SAFE(shader_);
37 }
38
40 {
41 if (!shader_) {
42 BLI_assert(!info_name_.empty());
43 shader_ = GPU_shader_create_from_info_name(info_name_.c_str());
44 }
45 return shader_;
46 }
47};
48
50 private:
51 static ShaderCache *static_cache;
52
54 [2 /*clip*/];
55 StaticShader resolve_[lighting_type_len][2 /*cavity*/][2 /*curvature*/][2 /*shadow*/];
56
57 StaticShader shadow_[2 /*depth_pass*/][2 /*manifold*/][2 /*cap*/];
58
59 StaticShader volume_[2 /*smoke*/][3 /*interpolation*/][2 /*coba*/][2 /*slice*/];
60
61 public:
62 static ShaderCache &get();
63 static void release();
64
66
68 ePipelineType pipeline_type,
69 eLightingType lighting_type,
70 eShaderType shader_type,
71 bool clip)
72 {
73 return prepass_[int(geometry_type)][int(pipeline_type)][int(lighting_type)][int(shader_type)]
74 [clip]
75 .get();
76 }
77
79 bool cavity = false,
80 bool curvature = false,
81 bool shadow = false)
82 {
83 return resolve_[int(lighting_type)][cavity][curvature][shadow].get();
84 }
85
86 GPUShader *shadow_get(bool depth_pass, bool manifold, bool cap = false)
87 {
88 return shadow_[depth_pass][manifold][cap].get();
89 }
90
91 GPUShader *volume_get(bool smoke, int interpolation, bool coba, bool slice)
92 {
93 return volume_[smoke][interpolation][coba][slice].get();
94 }
95
96 StaticShader extract_stencil = {"workbench_extract_stencil"};
97
98 /* Transparency */
99 StaticShader transparent_resolve = {"workbench_transparent_resolve"};
100 StaticShader merge_depth = {"workbench_merge_depth"};
101
102 /* ShadowView */
104 "workbench_shadow_visibility_compute_dynamic_pass_type"};
105 StaticShader shadow_visibility_static = {"workbench_shadow_visibility_compute_static_pass_type"};
106
107 /* Outline */
108 StaticShader outline = {"workbench_effect_outline"};
109
110 /* Dof */
111 StaticShader dof_prepare = {"workbench_effect_dof_prepare"};
112 StaticShader dof_downsample = {"workbench_effect_dof_downsample"};
113 StaticShader dof_blur1 = {"workbench_effect_dof_blur1"};
114 StaticShader dof_blur2 = {"workbench_effect_dof_blur2"};
115 StaticShader dof_resolve = {"workbench_effect_dof_resolve"};
116
117 /* AA */
118 StaticShader taa_accumulation = {"workbench_taa"};
119 StaticShader smaa_edge_detect = {"workbench_smaa_stage_0"};
120 StaticShader smaa_aa_weight = {"workbench_smaa_stage_1"};
121 StaticShader smaa_resolve = {"workbench_smaa_stage_2"};
122 StaticShader overlay_depth = {"workbench_overlay_depth"};
123};
124
125struct Material {
127 /* Packed data into a int. Decoded in the shader. */
129
131 Material(float3 color);
132 Material(::Object &ob, bool random = false);
133 Material(::Material &mat);
134
135 static uint32_t pack_data(float metallic, float roughness, float alpha);
136
137 bool is_transparent();
138};
139
141
143 Scene *scene = nullptr;
144
146 Camera *camera = nullptr;
149
151
152 View3DShading shading = {};
154 bool xray_mode = false;
155
158
160
161 bool draw_cavity = false;
162 bool draw_curvature = false;
163 bool draw_shadows = false;
164 bool draw_outline = false;
165 bool draw_dof = false;
166 bool draw_aa = false;
167
168 bool draw_object_id = false;
169
170 int sample = 0;
171 int samples_len = 0;
173 bool render_finished = false;
174
175 /* Used when material_type == eMaterialType::SINGLE */
177 /* When r == -1.0 the shader uses the vertex color */
179
180 void init(Object *camera_ob = nullptr);
181};
182
184 const char *name = nullptr;
187 bool premultiplied = false;
188 bool alpha_cutoff = false;
189
190 MaterialTexture() = default;
191 MaterialTexture(Object *ob, int material_index);
192 MaterialTexture(::Image *image, ImageUser *user = nullptr);
193};
194
195struct SceneResources;
196
207
209 private:
210 /* This value must be kept in sync with the one declared at
211 * workbench_composite_info.hh (cavity_samples) */
212 static const int max_samples_ = 512;
213
215
216 int sample_ = 0;
217 int sample_count_ = 0;
218 bool curvature_enabled_ = false;
219 bool cavity_enabled_ = false;
220
221 public:
222 void init(const SceneState &scene_state, SceneResources &resources);
223 void setup_resolve_pass(PassSimple &pass, SceneResources &resources);
224
225 private:
226 void load_samples_buf(int ssao_samples);
227};
228
229/* Used as a temporary workaround for the lack of texture views support on Windows ARM. */
231 private:
232 Texture stencil_copy_tx_ = "stencil_copy_tx";
233
234 public:
241 GPUTexture *extract(Manager &manager, Texture &stencil_src)
242 {
244 return stencil_src.stencil_view();
245 }
246
247 int2 extent = int2(stencil_src.width(), stencil_src.height());
248 stencil_copy_tx_.ensure_2d(
250
251 PassSimple ps("Stencil View Workaround");
252 ps.init();
253 ps.clear_color(float4(0));
255 ps.state_stencil(0x00, 0x00, 0xFF);
256 ps.shader_set(ShaderCache::get().extract_stencil.get());
258
260 fb.ensure(GPU_ATTACHMENT_TEXTURE(stencil_src), GPU_ATTACHMENT_TEXTURE(stencil_copy_tx_));
261 fb.bind();
262
263 manager.submit(ps);
264
265 return stencil_copy_tx_;
266 }
267};
268
305
306class MeshPass : public PassMain {
307 private:
308 using TextureSubPassKey = std::pair<GPUTexture *, eGeometryType>;
309
310 Map<TextureSubPassKey, PassMain::Sub *> texture_subpass_map_;
311
312 PassMain::Sub *passes_[geometry_type_len][shader_type_len] = {{nullptr}};
313
314 bool is_empty_ = false;
315
316 public:
317 MeshPass(const char *name);
318
319 /* TODO: Move to draw::Pass */
320 bool is_empty() const;
321
322 void init_pass(SceneResources &resources, DRWState state, int clip_planes);
323 void init_subpasses(ePipelineType pipeline, eLightingType lighting, bool clip);
324
326 const MaterialTexture *texture = nullptr);
327};
328
329enum class StencilBits : uint8_t {
330 BACKGROUND = 0,
331 OBJECT = 1u << 0,
332 OBJECT_IN_FRONT = 1u << 1,
333};
334
336 public:
337 TextureFromPool gbuffer_normal_tx = {"gbuffer_normal_tx"};
338 TextureFromPool gbuffer_material_tx = {"gbuffer_material_tx"};
339
340 Texture shadow_depth_stencil_tx = {"shadow_depth_stencil_tx"};
341 GPUTexture *deferred_ps_stencil_tx = nullptr;
342
343 MeshPass gbuffer_ps_ = {"Opaque.Gbuffer"};
344 MeshPass gbuffer_in_front_ps_ = {"Opaque.GbufferInFront"};
345 PassSimple deferred_ps_ = {"Opaque.Deferred"};
346
347 Framebuffer gbuffer_fb = {"Opaque.Gbuffer"};
348 Framebuffer gbuffer_in_front_fb = {"Opaque.GbufferInFront"};
349 Framebuffer deferred_fb = {"Opaque.Deferred"};
350 Framebuffer clear_fb = {"Opaque.Clear"};
351
352 void sync(const SceneState &scene_state, SceneResources &resources);
353 void draw(Manager &manager,
354 View &view,
355 SceneResources &resources,
356 int2 resolution,
357 class ShadowPass *shadow_pass);
358 bool is_empty() const;
359};
360
362 public:
363 TextureFromPool accumulation_tx = {"accumulation_accumulation_tx"};
364 TextureFromPool reveal_tx = {"accumulation_reveal_tx"};
366
367 MeshPass accumulation_ps_ = {"Transparent.Accumulation"};
368 MeshPass accumulation_in_front_ps_ = {"Transparent.AccumulationInFront"};
369 PassSimple resolve_ps_ = {"Transparent.Resolve"};
371
372 void sync(const SceneState &scene_state, SceneResources &resources);
373 void draw(Manager &manager, View &view, SceneResources &resources, int2 resolution);
374 bool is_empty() const;
375};
376
378 public:
379 MeshPass main_ps_ = {"TransparentDepth.Main"};
380 Framebuffer main_fb = {"TransparentDepth.Main"};
381 MeshPass in_front_ps_ = {"TransparentDepth.InFront"};
382 Framebuffer in_front_fb = {"TransparentDepth.InFront"};
383 PassSimple merge_ps_ = {"TransparentDepth.Merge"};
384 Framebuffer merge_fb = {"TransparentDepth.Merge"};
385
386 void sync(const SceneState &scene_state, SceneResources &resources);
387 void draw(Manager &manager, View &view, SceneResources &resources);
388 bool is_empty() const;
389};
390
391#define DEBUG_SHADOW_VOLUME 0
392
394 private:
395 enum PassType { PASS = 0, FAIL, FORCED_FAIL, MAX };
396
397 class ShadowView : public View {
398 bool force_fail_method_ = false;
399 float3 light_direction_ = float3(0);
400 UniformBuffer<ExtrudedFrustum> extruded_frustum_ = {};
401 ShadowPass::PassType current_pass_type_ = PASS;
402
403 VisibilityBuf pass_visibility_buf_ = {};
404 VisibilityBuf fail_visibility_buf_ = {};
405
406 public:
407 ShadowView() : View("ShadowPass.View"){};
408
409 void setup(View &view, float3 light_direction, bool force_fail_method);
410 bool debug_object_culling(Object *ob);
411 void set_mode(PassType type);
412
413 protected:
414 virtual void compute_visibility(ObjectBoundsBuf &bounds,
415 ObjectInfosBuf &infos,
416 uint resource_len,
417 bool debug_freeze) override;
418 virtual VisibilityBuf &get_visibility_buffer() override;
419 } view_ = {};
420
421 bool enabled_;
422
423 UniformBuffer<ShadowPassData> pass_data_ = {};
424
425 /* Draws are added to both passes and the visibly compute shader selects one of them */
426 PassMain pass_ps_ = {"Shadow.Pass"};
427 PassMain fail_ps_ = {"Shadow.Fail"};
428
429 /* In some cases, we know beforehand that we need to use the fail technique */
430 PassMain forced_fail_ps_ = {"Shadow.ForcedFail"};
431
432 /* [PassType][Is Manifold][Is Cap] */
433 PassMain::Sub *passes_[PassType::MAX][2][2] = {{{nullptr}}};
434 PassMain::Sub *&get_pass_ptr(PassType type, bool manifold, bool cap = false);
435
436 TextureFromPool depth_tx_ = {};
437 Framebuffer fb_ = {};
438
439 public:
440 void init(const SceneState &scene_state, SceneResources &resources);
441 void update();
442 void sync();
443 void object_sync(SceneState &scene_state,
444 ObjectRef &ob_ref,
445 ResourceHandle handle,
446 const bool has_transp_mat);
447 void draw(Manager &manager,
448 View &view,
449 SceneResources &resources,
450 GPUTexture &depth_stencil_tx,
451 /* Needed when there are opaque "In Front" objects in the scene */
452 bool force_fail_method);
453
454 bool is_debug();
455};
456
458 bool active_ = true;
459
460 PassMain ps_ = {"Volume"};
461 Framebuffer fb_ = {"Volume"};
462
463 Texture dummy_shadow_tx_ = {"Volume.Dummy Shadow Tx"};
464 Texture dummy_volume_tx_ = {"Volume.Dummy Volume Tx"};
465 Texture dummy_coba_tx_ = {"Volume.Dummy Coba Tx"};
466
467 GPUTexture *stencil_tx_ = nullptr;
468
469 public:
470 void sync(SceneResources &resources);
471
472 void object_sync_volume(Manager &manager,
473 SceneResources &resources,
474 const SceneState &scene_state,
475 ObjectRef &ob_ref,
476 float3 color);
477
478 void object_sync_modifier(Manager &manager,
479 SceneResources &resources,
480 const SceneState &scene_state,
481 ObjectRef &ob_ref,
482 ModifierData *md);
483
484 void draw(Manager &manager, View &view, SceneResources &resources);
485
486 private:
487 void draw_slice_ps(Manager &manager,
488 PassMain::Sub &ps,
489 ObjectRef &ob_ref,
490 int slice_axis_enum,
491 float slice_depth);
492
493 void draw_volume_ps(Manager &manager,
494 PassMain::Sub &ps,
495 ObjectRef &ob_ref,
496 int taa_sample,
497 float3 slice_count,
498 float3 world_size);
499};
500
502 private:
503 bool enabled_ = false;
504
505 PassSimple ps_ = PassSimple("Workbench.Outline");
506 Framebuffer fb_ = Framebuffer("Workbench.Outline");
507
508 public:
509 void init(const SceneState &scene_state);
510 void sync(SceneResources &resources);
511 void draw(Manager &manager, SceneResources &resources);
512};
513
514class DofPass {
515 private:
516 static const int kernel_radius_ = 3;
517 static const int samples_len_ = (kernel_radius_ * 2 + 1) * (kernel_radius_ * 2 + 1);
518
519 bool enabled_ = false;
520
521 float offset_ = 0;
522
524
525 Texture source_tx_ = {};
526 Texture coc_halfres_tx_ = {};
527 TextureFromPool blur_tx_ = {};
528
529 Framebuffer downsample_fb_ = {};
530 Framebuffer blur1_fb_ = {};
531 Framebuffer blur2_fb_ = {};
532 Framebuffer resolve_fb_ = {};
533
534 PassSimple down_ps_ = {"Workbench.DoF.DownSample"};
535 PassSimple down2_ps_ = {"Workbench.DoF.DownSample2"};
536 PassSimple blur_ps_ = {"Workbench.DoF.Blur"};
537 PassSimple blur2_ps_ = {"Workbench.DoF.Blur2"};
538 PassSimple resolve_ps_ = {"Workbench.DoF.Resolve"};
539
540 float aperture_size_ = 0;
541 float distance_ = 0;
542 float invsensor_size_ = 0;
543 float near_ = 0;
544 float far_ = 0;
545 float blades_ = 0;
546 float rotation_ = 0;
547 float ratio_ = 0;
548
549 public:
550 void init(const SceneState &scene_state);
551 void sync(SceneResources &resources);
552 void draw(Manager &manager, View &view, SceneResources &resources, int2 resolution);
553 bool is_enabled();
554
555 private:
556 void setup_samples();
557};
558
560 private:
561 bool enabled_ = false;
562 /* Weight accumulated. */
563 float weight_accum_ = 0;
564 /* Samples weight for this iteration. */
565 float weights_[9] = {0};
566 /* Sum of weights. */
567 float weights_sum_ = 0;
568
569 Texture sample0_depth_tx_ = {"sample0_depth_tx"};
570 Texture sample0_depth_in_front_tx_ = {"sample0_depth_in_front_tx"};
571
572 Texture taa_accumulation_tx_ = {"taa_accumulation_tx"};
573 Texture smaa_search_tx_ = {"smaa_search_tx"};
574 Texture smaa_area_tx_ = {"smaa_area_tx"};
575 TextureFromPool smaa_edge_tx_ = {"smaa_edge_tx"};
576 TextureFromPool smaa_weight_tx_ = {"smaa_weight_tx"};
577
578 Framebuffer taa_accumulation_fb_ = {"taa_accumulation_fb"};
579 Framebuffer smaa_edge_fb_ = {"smaa_edge_fb"};
580 Framebuffer smaa_weight_fb_ = {"smaa_weight_fb"};
581 Framebuffer smaa_resolve_fb_ = {"smaa_resolve_fb"};
582 Framebuffer overlay_depth_fb_ = {"overlay_depth_fb"};
583
584 float4 smaa_viewport_metrics_ = float4(0);
585 float smaa_mix_factor_ = 0;
586
587 PassSimple taa_accumulation_ps_ = {"TAA.Accumulation"};
588 PassSimple smaa_edge_detect_ps_ = {"SMAA.EdgeDetect"};
589 PassSimple smaa_aa_weight_ps_ = {"SMAA.BlendWeights"};
590 PassSimple smaa_resolve_ps_ = {"SMAA.Resolve"};
591 PassSimple overlay_depth_ps_ = {"Overlay Depth"};
592
593 public:
595
596 void init(const SceneState &scene_state);
597 void sync(const SceneState &scene_state, SceneResources &resources);
598 void setup_view(View &view, const SceneState &scene_state);
599 void draw(
600 Manager &manager,
601 View &view,
602 const SceneState &scene_state,
603 SceneResources &resources,
606 GPUTexture *depth_in_front_tx);
607};
608
609} // namespace blender::workbench
eContextObjectMode
@ CTX_MODE_OBJECT
#define BLI_assert(a)
Definition BLI_assert.h:50
unsigned int uint
struct Material Material
eV3DShadingColorType
@ V3D_SHADING_SINGLE_COLOR
#define DRW_SHADER_FREE_SAFE(shader)
bool GPU_texture_view_support()
#define GPU_ATTACHMENT_TEXTURE(_texture)
@ GPU_PRIM_TRIS
GPUShader * GPU_shader_create_from_info_name(const char *info_name)
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_ATTACHMENT
@ GPU_R8UI
struct GPUShader GPUShader
void init()
void ensure(GPUAttachment depth=GPU_ATTACHMENT_NONE, GPUAttachment color1=GPU_ATTACHMENT_NONE, GPUAttachment color2=GPU_ATTACHMENT_NONE, GPUAttachment color3=GPU_ATTACHMENT_NONE, GPUAttachment color4=GPU_ATTACHMENT_NONE, GPUAttachment color5=GPU_ATTACHMENT_NONE, GPUAttachment color6=GPU_ATTACHMENT_NONE, GPUAttachment color7=GPU_ATTACHMENT_NONE, GPUAttachment color8=GPU_ATTACHMENT_NONE)
void submit(PassSimple &pass, View &view)
bool ensure_2d(eGPUTextureFormat format, int2 extent, eGPUTextureUsage usage=GPU_TEXTURE_USAGE_GENERAL, const float *data=nullptr, int mip_len=1)
GPUTexture * stencil_view(bool cube_as_array=false)
View(const char *name, int view_len=1, bool procedural=false)
Definition draw_view.hh:59
void clear_color(float4 color)
Definition draw_pass.hh:911
void draw_procedural(GPUPrimType primitive, uint instance_len, uint vertex_len, uint vertex_first=-1, ResourceHandle handle={0}, uint custom_id=0)
Definition draw_pass.hh:833
void state_set(DRWState state, int clip_plane_count=0)
Definition draw_pass.hh:954
void state_stencil(uint8_t write_mask, uint8_t reference, uint8_t compare_mask)
Definition draw_pass.hh:966
void shader_set(GPUShader *shader)
Definition draw_pass.hh:971
detail::PassBase< command::DrawMultiBuf > Sub
Definition draw_pass.hh:462
void setup_view(View &view, const SceneState &scene_state)
void draw(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)
void draw(Manager &manager, View &view, SceneResources &resources, int2 resolution)
PassMain::Sub & get_subpass(eGeometryType geometry_type, const MaterialTexture *texture=nullptr)
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)
StaticShader(StaticShader &&other)=default
StaticShader(std::string info_name)
StaticShader & operator=(StaticShader &&other)=default
GPUTexture * extract(Manager &manager, Texture &stencil_src)
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
@ DRW_STATE_WRITE_COLOR
Definition draw_state.hh:30
@ DRW_STATE_STENCIL_NEQUAL
Definition draw_state.hh:48
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
BLI_INLINE float fb(float length, float L)
static ulong state[N]
detail::Pass< command::DrawCommandBuf > PassSimple
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
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 3 > float3
unsigned int uint32_t
Definition stdint.h:80
unsigned char uint8_t
Definition stdint.h:78
static constexpr GPUSamplerState default_sampler()
static uint32_t pack_data(float metallic, float roughness, float alpha)
ObjectState(const SceneState &scene_state, const SceneResources &resources, Object *ob)
UniformBuffer< WorldData > world_buf
StorageVectorBuffer< Material > material_buf
UniformArrayBuffer< float4, 6 > clip_planes_buf
DrawEngineType draw_engine_workbench