Blender V5.0
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"
9#include "DRW_render.hh"
10#include "GPU_shader.hh"
11#include "draw_manager.hh"
12#include "draw_pass.hh"
13
14#include "workbench_defines.hh"
15#include "workbench_enums.hh"
17
18#include "GPU_capabilities.hh"
19
20namespace blender::workbench {
21
22using namespace draw;
24
26 private:
28 [2 /*clip*/];
29 StaticShader resolve_[lighting_type_len][2 /*cavity*/][2 /*curvature*/][2 /*shadow*/];
30
31 StaticShader shadow_[2 /*depth_pass*/][2 /*manifold*/][2 /*cap*/];
32
33 StaticShader volume_[2 /*smoke*/][3 /*interpolation*/][2 /*coba*/][2 /*slice*/];
34
35 static gpu::StaticShaderCache<ShaderCache> &get_static_cache()
36 {
37 static gpu::StaticShaderCache<ShaderCache> static_cache;
38 return static_cache;
39 }
40
41 public:
42 static ShaderCache &get()
43 {
44 return get_static_cache().get();
45 }
46 static void release()
47 {
48 get_static_cache().release();
49 }
50
52
54 ePipelineType pipeline_type,
55 eLightingType lighting_type,
56 eShaderType shader_type,
57 bool clip)
58 {
59 return prepass_[int(geometry_type)][int(pipeline_type)][int(lighting_type)][int(shader_type)]
60 [clip]
61 .get();
62 }
63
65 bool cavity = false,
66 bool curvature = false,
67 bool shadow = false)
68 {
69 return resolve_[int(lighting_type)][cavity][curvature][shadow].get();
70 }
71
72 gpu::Shader *shadow_get(bool depth_pass, bool manifold, bool cap = false)
73 {
74 return shadow_[depth_pass][manifold][cap].get();
75 }
76
77 gpu::Shader *volume_get(bool smoke, int interpolation, bool coba, bool slice)
78 {
79 return volume_[smoke][interpolation][coba][slice].get();
80 }
81
82 /* Transparency */
83 StaticShader transparent_resolve = {"workbench_transparent_resolve"};
84 StaticShader merge_depth = {"workbench_merge_depth"};
85
86 /* ShadowView */
88 "workbench_shadow_visibility_compute_dynamic_pass_type"};
89 StaticShader shadow_visibility_static = {"workbench_shadow_visibility_compute_static_pass_type"};
90
91 /* Outline */
92 StaticShader outline = {"workbench_effect_outline"};
93
94 /* Dof */
95 StaticShader dof_prepare = {"workbench_effect_dof_prepare"};
96 StaticShader dof_downsample = {"workbench_effect_dof_downsample"};
97 StaticShader dof_blur1 = {"workbench_effect_dof_blur1"};
98 StaticShader dof_blur2 = {"workbench_effect_dof_blur2"};
99 StaticShader dof_resolve = {"workbench_effect_dof_resolve"};
100
101 /* AA */
102 StaticShader taa_accumulation = {"workbench_taa"};
103 StaticShader smaa_edge_detect = {"workbench_smaa_stage_0"};
104 StaticShader smaa_aa_weight = {"workbench_smaa_stage_1"};
105 StaticShader smaa_resolve = {"workbench_smaa_stage_2"};
106 StaticShader overlay_depth = {"workbench_overlay_depth"};
107};
108
109struct Material {
111 /* Packed data into a int. Decoded in the shader. */
113
114 Material() = default;
116
117 Material(::Object &ob, bool random = false);
119 : base_color(&mat.r), packed_data(Material::pack_data(mat.metallic, mat.roughness, mat.a))
120 {
121 }
122
123 static uint32_t pack_data(float metallic, float roughness, float alpha);
124
125 bool is_transparent();
126};
127
128inline bool Material::is_transparent()
129{
130 uint32_t full_alpha_ref = 0x00ff0000;
131 return (packed_data & full_alpha_ref) != full_alpha_ref;
132}
133
134inline uint32_t Material::pack_data(float metallic, float roughness, float alpha)
135{
136 /* Remap to Disney roughness. */
137 roughness = sqrtf(roughness);
138 uint32_t packed_roughness = unit_float_to_uchar_clamp(roughness);
139 uint32_t packed_metallic = unit_float_to_uchar_clamp(metallic);
140 uint32_t packed_alpha = unit_float_to_uchar_clamp(alpha);
141 return (packed_alpha << 16u) | (packed_roughness << 8u) | packed_metallic;
142}
143
145
147 Scene *scene = nullptr;
148
150 Camera *camera = nullptr;
153
155
158 bool xray_mode = false;
159
162
164
165 bool draw_cavity = false;
166 bool draw_curvature = false;
167 bool draw_shadows = false;
168 bool draw_outline = false;
169 bool draw_dof = false;
170 bool draw_aa = false;
171
172 bool draw_object_id = false;
173
174 int sample = 0;
175 int samples_len = 0;
177 bool render_finished = false;
178
179 /* Used when material_type == eMaterialType::SINGLE */
181 /* When r == -1.0 the shader uses the vertex color */
183
184 void init(const DRWContext *context, bool scene_updated, Object *camera_ob = nullptr);
185};
186
188 const char *name = nullptr;
191 bool premultiplied = false;
192 bool alpha_cutoff = false;
193
194 MaterialTexture() = default;
195 MaterialTexture(Object *ob, int material_index);
196 MaterialTexture(::Image *image, ImageUser *user = nullptr);
197};
198
199struct SceneResources;
200
205 bool draw_shadow = false;
207 bool sculpt_pbvh = false;
208
209 ObjectState(const DRWContext *draw_ctx,
210 const SceneState &scene_state,
211 const SceneResources &resources,
212 Object *ob);
213};
214
216 private:
217 /* This value must be kept in sync with the one declared at
218 * workbench_composite_info.hh (cavity_samples) */
219 static const int max_samples_ = 512;
220
222
223 int sample_ = 0;
224 int sample_count_ = 0;
225 bool curvature_enabled_ = false;
226 bool cavity_enabled_ = false;
227
228 public:
229 void init(const SceneState &scene_state, SceneResources &resources);
230 void setup_resolve_pass(PassSimple &pass, SceneResources &resources);
231
232 private:
233 void load_samples_buf(int ssao_samples);
234};
235
237 static const int jitter_tx_size = 64;
238
240 Texture matcap_tx = "matcap_tx";
241
242 TextureFromPool object_id_tx = "wb_object_id_tx";
243
247
248 Framebuffer clear_fb = {"Clear Main"};
250 Framebuffer clear_in_front_fb = {"Clear In Front"};
251
255
256 Texture jitter_tx = "wb_jitter_tx";
257
259
260 Texture missing_tx = "missing_tx";
262
263 Texture dummy_texture_tx = {"dummy_texture"};
264 Texture dummy_tile_data_tx = {"dummy_tile_data"};
265 Texture dummy_tile_array_tx = {"dummy_tile_array"};
266
267 gpu::Batch *volume_cube_batch = nullptr;
268
270 {
271 /* TODO(fclem): Auto destruction. */
273 }
274
275 void init(const SceneState &scene_state, const DRWContext *ctx);
276 void load_jitter_tx(int total_samples);
277};
278
279class MeshPass : public PassMain {
280 private:
281 struct TextureSubPassKey {
283 GPUSamplerState sampler_state;
284 eGeometryType geom_type;
285
286 uint64_t hash() const
287 {
288 return get_default_hash(texture, sampler_state.as_uint(), geom_type);
289 }
290
291 bool operator==(TextureSubPassKey const &rhs) const
292 {
293 return this->texture == rhs.texture && this->sampler_state == rhs.sampler_state &&
294 this->geom_type == rhs.geom_type;
295 }
296 };
297
298 Map<TextureSubPassKey, PassMain::Sub *> texture_subpass_map_;
299
300 PassMain::Sub *passes_[geometry_type_len][shader_type_len] = {{nullptr}};
301
302 ePipelineType pipeline_;
303 eLightingType lighting_;
304 bool clip_;
305
306 bool is_empty_ = false;
307
308 PassMain::Sub &get_subpass(eGeometryType geometry_type, eShaderType shader_type);
309
310 public:
311 MeshPass(const char *name);
312
313 /* TODO: Move to draw::Pass */
314 bool is_empty() const;
315
316 void init_pass(SceneResources &resources, DRWState state, int clip_planes);
317 void init_subpasses(ePipelineType pipeline, eLightingType lighting, bool clip);
318
319 PassMain::Sub &get_subpass(eGeometryType geometry_type,
320 const MaterialTexture *texture = nullptr);
321};
322
323enum class StencilBits : uint8_t {
325 OBJECT = 1u << 0,
327};
328
330 public:
331 TextureFromPool gbuffer_normal_tx = {"gbuffer_normal_tx"};
332 TextureFromPool gbuffer_material_tx = {"gbuffer_material_tx"};
333
334 Texture shadow_depth_stencil_tx = {"shadow_depth_stencil_tx"};
336
337 MeshPass gbuffer_ps_ = {"Opaque.Gbuffer"};
338 MeshPass gbuffer_in_front_ps_ = {"Opaque.GbufferInFront"};
339 PassSimple deferred_ps_ = {"Opaque.Deferred"};
340
341 Framebuffer gbuffer_fb = {"Opaque.Gbuffer"};
342 Framebuffer gbuffer_in_front_fb = {"Opaque.GbufferInFront"};
343 Framebuffer deferred_fb = {"Opaque.Deferred"};
344 Framebuffer clear_fb = {"Opaque.Clear"};
345
346 void sync(const SceneState &scene_state, SceneResources &resources);
347 void draw(Manager &manager,
348 View &view,
349 SceneResources &resources,
350 int2 resolution,
351 class ShadowPass *shadow_pass);
352 bool is_empty() const;
353};
354
356 public:
357 TextureFromPool accumulation_tx = {"accumulation_accumulation_tx"};
358 TextureFromPool reveal_tx = {"accumulation_reveal_tx"};
360
361 MeshPass accumulation_ps_ = {"Transparent.Accumulation"};
362 MeshPass accumulation_in_front_ps_ = {"Transparent.AccumulationInFront"};
363 PassSimple resolve_ps_ = {"Transparent.Resolve"};
365
366 void sync(const SceneState &scene_state, SceneResources &resources);
367 void draw(Manager &manager, View &view, SceneResources &resources, int2 resolution);
368 bool is_empty() const;
369};
370
372 public:
373 MeshPass main_ps_ = {"TransparentDepth.Main"};
374 Framebuffer main_fb = {"TransparentDepth.Main"};
375 MeshPass in_front_ps_ = {"TransparentDepth.InFront"};
376 Framebuffer in_front_fb = {"TransparentDepth.InFront"};
377 PassSimple merge_ps_ = {"TransparentDepth.Merge"};
378 Framebuffer merge_fb = {"TransparentDepth.Merge"};
379
380 void sync(const SceneState &scene_state, SceneResources &resources);
381 void draw(Manager &manager, View &view, SceneResources &resources);
382 bool is_empty() const;
383};
384
385#define DEBUG_SHADOW_VOLUME 0
386
388 private:
389 enum PassType { PASS = 0, FAIL, FORCED_FAIL, MAX };
390
391 class ShadowView : public View {
392 bool force_fail_method_ = false;
393 float3 light_direction_ = float3(0);
394 UniformBuffer<ExtrudedFrustum> extruded_frustum_ = {};
395 ShadowPass::PassType current_pass_type_ = PASS;
396
397 VisibilityBuf pass_visibility_buf_ = {};
398 VisibilityBuf fail_visibility_buf_ = {};
399
400 public:
401 ShadowView() : View("ShadowPass.View") {};
402
403 void setup(View &view, float3 light_direction, bool force_fail_method);
404 bool debug_object_culling(Object *ob);
405 void set_mode(PassType type);
406
407 protected:
408 virtual void compute_visibility(ObjectBoundsBuf &bounds,
409 ObjectInfosBuf &infos,
410 uint resource_len,
411 bool debug_freeze) override;
412 virtual VisibilityBuf &get_visibility_buffer() override;
413 } view_ = {};
414
415 bool enabled_;
416
417 UniformBuffer<ShadowPassData> pass_data_ = {};
418
419 /* Draws are added to both passes and the visibly compute shader selects one of them */
420 PassMain pass_ps_ = {"Shadow.Pass"};
421 PassMain fail_ps_ = {"Shadow.Fail"};
422
423 /* In some cases, we know beforehand that we need to use the fail technique */
424 PassMain forced_fail_ps_ = {"Shadow.ForcedFail"};
425
426 /* [PassType][Is Manifold][Is Cap] */
427 PassMain::Sub *passes_[PassType::MAX][2][2] = {{{nullptr}}};
428 PassMain::Sub *&get_pass_ptr(PassType type, bool manifold, bool cap = false);
429
430 TextureFromPool depth_tx_ = {};
431 Framebuffer fb_ = {};
432
433 public:
434 void init(const SceneState &scene_state, SceneResources &resources);
435 void update();
436 void sync();
437 void object_sync(SceneState &scene_state,
438 ObjectRef &ob_ref,
439 ResourceHandleRange handle,
440 const bool has_transp_mat);
441 void draw(Manager &manager,
442 View &view,
443 SceneResources &resources,
444 gpu::Texture &depth_stencil_tx,
445 /* Needed when there are opaque "In Front" objects in the scene */
446 bool force_fail_method);
447
448 bool is_debug();
449};
450
452 bool active_ = true;
453
454 PassMain ps_ = {"Volume"};
455 Framebuffer fb_ = {"Volume"};
456
457 Texture dummy_shadow_tx_ = {"Volume.Dummy Shadow Tx"};
458 Texture dummy_volume_tx_ = {"Volume.Dummy Volume Tx"};
459 Texture dummy_coba_tx_ = {"Volume.Dummy Coba Tx"};
460
461 gpu::Texture *stencil_tx_ = nullptr;
462
463 public:
464 void sync(SceneResources &resources);
465
466 void object_sync_volume(Manager &manager,
467 SceneResources &resources,
468 const SceneState &scene_state,
469 ObjectRef &ob_ref,
470 float3 color);
471
472 void object_sync_modifier(Manager &manager,
473 SceneResources &resources,
474 const SceneState &scene_state,
475 ObjectRef &ob_ref,
476 ModifierData *md);
477
478 void draw(Manager &manager, View &view, SceneResources &resources);
479
480 private:
481 void draw_slice_ps(Manager &manager,
482 SceneResources &resources,
483 PassMain::Sub &ps,
484 ObjectRef &ob_ref,
485 int slice_axis_enum,
486 float slice_depth);
487
488 void draw_volume_ps(Manager &manager,
489 SceneResources &resources,
490 PassMain::Sub &ps,
491 ObjectRef &ob_ref,
492 int taa_sample,
493 float3 slice_count,
494 float3 world_size);
495};
496
498 private:
499 bool enabled_ = false;
500
501 PassSimple ps_ = PassSimple("Workbench.Outline");
502 Framebuffer fb_ = Framebuffer("Workbench.Outline");
503
504 public:
505 void init(const SceneState &scene_state);
506 void sync(SceneResources &resources);
507 void draw(Manager &manager, SceneResources &resources);
508};
509
510class DofPass {
511 private:
512 static const int kernel_radius_ = 3;
513 static const int samples_len_ = (kernel_radius_ * 2 + 1) * (kernel_radius_ * 2 + 1);
514
515 bool enabled_ = false;
516
517 float offset_ = 0;
518
520
521 Texture source_tx_ = {};
522 Texture coc_halfres_tx_ = {};
523 TextureFromPool blur_tx_ = {};
524
525 Framebuffer downsample_fb_ = {};
526 Framebuffer blur1_fb_ = {};
527 Framebuffer blur2_fb_ = {};
528 Framebuffer resolve_fb_ = {};
529
530 PassSimple down_ps_ = {"Workbench.DoF.DownSample"};
531 PassSimple down2_ps_ = {"Workbench.DoF.DownSample2"};
532 PassSimple down3_ps_ = {"Workbench.DoF.DownSample3"};
533 PassSimple blur_ps_ = {"Workbench.DoF.Blur"};
534 PassSimple blur2_ps_ = {"Workbench.DoF.Blur2"};
535 PassSimple resolve_ps_ = {"Workbench.DoF.Resolve"};
536
537 float aperture_size_ = 0;
538 float distance_ = 0;
539 float invsensor_size_ = 0;
540 float near_ = 0;
541 float far_ = 0;
542 float blades_ = 0;
543 float rotation_ = 0;
544 float ratio_ = 0;
545
546 public:
547 void init(const SceneState &scene_state, const DRWContext *draw_ctx);
548 void sync(SceneResources &resources, const DRWContext *draw_ctx);
549 void draw(Manager &manager, View &view, SceneResources &resources, int2 resolution);
550 bool is_enabled();
551
552 private:
553 void setup_samples();
554};
555
557 private:
558 bool enabled_ = false;
559 /* Weight accumulated. */
560 float weight_accum_ = 0;
561 /* Samples weight for this iteration. */
562 float weights_[9] = {0};
563 /* Sum of weights. */
564 float weights_sum_ = 0;
565
566 Texture sample0_depth_tx_ = {"sample0_depth_tx"};
567 Texture sample0_depth_in_front_tx_ = {"sample0_depth_in_front_tx"};
568
569 Texture taa_accumulation_tx_ = {"taa_accumulation_tx"};
570 Texture smaa_search_tx_ = {"smaa_search_tx"};
571 Texture smaa_area_tx_ = {"smaa_area_tx"};
572 TextureFromPool smaa_edge_tx_ = {"smaa_edge_tx"};
573 TextureFromPool smaa_weight_tx_ = {"smaa_weight_tx"};
574
575 Framebuffer taa_accumulation_fb_ = {"taa_accumulation_fb"};
576 Framebuffer smaa_edge_fb_ = {"smaa_edge_fb"};
577 Framebuffer smaa_weight_fb_ = {"smaa_weight_fb"};
578 Framebuffer smaa_resolve_fb_ = {"smaa_resolve_fb"};
579 Framebuffer overlay_depth_fb_ = {"overlay_depth_fb"};
580
581 float4 smaa_viewport_metrics_ = float4(0);
582 float smaa_mix_factor_ = 0;
583
584 PassSimple taa_accumulation_ps_ = {"TAA.Accumulation"};
585 PassSimple smaa_edge_detect_ps_ = {"SMAA.EdgeDetect"};
586 PassSimple smaa_aa_weight_ps_ = {"SMAA.BlendWeights"};
587 PassSimple smaa_resolve_ps_ = {"SMAA.Resolve"};
588 PassSimple overlay_depth_ps_ = {"Overlay Depth"};
589
590 public:
592
593 void init(const SceneState &scene_state);
594 void sync(const SceneState &scene_state, SceneResources &resources);
595 void setup_view(View &view, const SceneState &scene_state);
596 void draw(
597 const DRWContext *draw_ctx,
598 Manager &manager,
599 View &view,
600 const SceneState &scene_state,
601 SceneResources &resources,
604 gpu::Texture *depth_in_front_tx);
605};
606
607} // namespace blender::workbench
eContextObjectMode
@ CTX_MODE_OBJECT
unsigned int uint
struct Material Material
eV3DShadingColorType
@ V3D_SHADING_SINGLE_COLOR
static AppView * view
static void View(GHOST_IWindow *window, bool stereo, int eye=0)
#define GPU_BATCH_DISCARD_SAFE(batch)
Definition GPU_batch.hh:197
bool operator==(const AssetWeakReference &a, const AssetWeakReference &b)
void init()
unsigned long long int uint64_t
detail::PassBase< command::DrawMultiBuf > Sub
Definition draw_pass.hh:499
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, gpu::Texture *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 draw(Manager &manager, SceneResources &resources)
void sync(SceneResources &resources)
gpu::Shader * resolve_get(eLightingType lighting_type, bool cavity=false, bool curvature=false, bool shadow=false)
gpu::Shader * prepass_get(eGeometryType geometry_type, ePipelineType pipeline_type, eLightingType lighting_type, eShaderType shader_type, bool clip)
gpu::Shader * volume_get(bool smoke, int interpolation, bool coba, bool slice)
gpu::Shader * shadow_get(bool depth_pass, bool manifold, bool cap=false)
void object_sync(SceneState &scene_state, ObjectRef &ob_ref, ResourceHandleRange handle, const bool has_transp_mat)
void draw(Manager &manager, View &view, SceneResources &resources, gpu::Texture &depth_stencil_tx, bool force_fail_method)
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
MINLINE unsigned char unit_float_to_uchar_clamp(float val)
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
uint64_t get_default_hash(const T &v, const Args &...args)
Definition BLI_hash.hh:233
VecBase< int32_t, 2 > int2
VecBase< float, 3 > float3
#define hash
Definition noise_c.cc:154
const char * name
#define sqrtf
static constexpr GPUSamplerState default_sampler()
uint32_t as_uint() const
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