Blender V4.3
workbench_mesh_passes.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
7namespace blender::workbench {
8
9/* -------------------------------------------------------------------- */
12
13MeshPass::MeshPass(const char *name) : PassMain(name){};
14
16{
17 /* TODO: Move to #draw::Pass. */
18
19 return is_empty_;
20}
21
22void MeshPass::init_pass(SceneResources &resources, DRWState state, int clip_planes)
23{
24 use_custom_ids = true;
25 is_empty_ = true;
27 state_set(state, clip_planes);
34 if (clip_planes > 0) {
36 }
37}
38
39void MeshPass::init_subpasses(ePipelineType pipeline, eLightingType lighting, bool clip)
40{
41 texture_subpass_map_.clear();
42
43 static std::string pass_names[geometry_type_len][shader_type_len] = {};
44
45 for (auto geom : IndexRange(geometry_type_len)) {
46 for (auto shader : IndexRange(shader_type_len)) {
47 eGeometryType geom_type = static_cast<eGeometryType>(geom);
48 eShaderType shader_type = static_cast<eShaderType>(shader);
49 if (pass_names[geom][shader].empty()) {
50 pass_names[geom][shader] = std::string(get_name(geom_type)) +
51 std::string(get_name(shader_type));
52 }
53 PassMain::Sub *pass = &sub(pass_names[geom][shader].c_str());
54 pass->shader_set(
55 ShaderCache::get().prepass_get(geom_type, pipeline, lighting, shader_type, clip));
56 passes_[geom][shader] = pass;
57 }
58 }
59}
60
62 const MaterialTexture *texture /* = nullptr */)
63{
64 is_empty_ = false;
65
66 if (texture && texture->gpu.texture) {
67 auto add_cb = [&] {
68 PassMain::Sub *sub_pass = passes_[int(geometry_type)][int(eShaderType::TEXTURE)];
69 sub_pass = &sub_pass->sub(texture->name);
70 if (texture->gpu.tile_mapping) {
71 sub_pass->bind_texture(WB_TILE_ARRAY_SLOT, texture->gpu.texture, texture->sampler_state);
72 sub_pass->bind_texture(WB_TILE_DATA_SLOT, texture->gpu.tile_mapping);
73 }
74 else {
75 sub_pass->bind_texture(WB_TEXTURE_SLOT, texture->gpu.texture, texture->sampler_state);
76 }
77 sub_pass->push_constant("isImageTile", texture->gpu.tile_mapping != nullptr);
78 sub_pass->push_constant("imagePremult", texture->premultiplied);
79 /* TODO(@pragma37): This setting should be exposed on the user side,
80 * either as a global parameter (and set it here)
81 * or by reading the Material Clipping Threshold (and set it per material) */
82 float alpha_cutoff = texture->alpha_cutoff ? 0.1f : -FLT_MAX;
83 sub_pass->push_constant("imageTransparencyCutoff", alpha_cutoff);
84 return sub_pass;
85 };
86
87 return *texture_subpass_map_.lookup_or_add_cb(
88 TextureSubPassKey(texture->gpu.texture, geometry_type), add_cb);
89 }
90
91 return *passes_[int(geometry_type)][int(eShaderType::MATERIAL)];
92}
93
95
96/* -------------------------------------------------------------------- */
99
100void OpaquePass::sync(const SceneState &scene_state, SceneResources &resources)
101{
104
105 bool clip = scene_state.clip_planes.size() > 0;
106
107 DRWState in_front_state = state | DRW_STATE_STENCIL_ALWAYS;
108 gbuffer_in_front_ps_.init_pass(resources, in_front_state, scene_state.clip_planes.size());
110 gbuffer_in_front_ps_.init_subpasses(ePipelineType::OPAQUE, scene_state.lighting_type, clip);
111
113 gbuffer_ps_.init_pass(resources, state, scene_state.clip_planes.size());
114 gbuffer_ps_.state_stencil(
116 gbuffer_ps_.init_subpasses(ePipelineType::OPAQUE, scene_state.lighting_type, clip);
117
118 deferred_ps_.init();
120 deferred_ps_.shader_set(ShaderCache::get().resolve_get(scene_state.lighting_type,
121 scene_state.draw_cavity,
122 scene_state.draw_curvature,
123 scene_state.draw_shadows));
124 deferred_ps_.push_constant("forceShadowing", false);
125 deferred_ps_.bind_ubo(WB_WORLD_SLOT, resources.world_buf);
126 deferred_ps_.bind_texture(WB_MATCAP_SLOT, resources.matcap_tx);
127 deferred_ps_.bind_texture("normal_tx", &gbuffer_normal_tx);
128 deferred_ps_.bind_texture("material_tx", &gbuffer_material_tx);
129 deferred_ps_.bind_texture("depth_tx", &resources.depth_tx);
130 deferred_ps_.bind_texture("stencil_tx", &deferred_ps_stencil_tx);
131 resources.cavity.setup_resolve_pass(deferred_ps_, resources);
132 deferred_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
133}
134
136 View &view,
137 SceneResources &resources,
138 int2 resolution,
139 ShadowPass *shadow_pass)
140{
141 if (is_empty()) {
142 return;
143 }
144 gbuffer_material_tx.acquire(
146 gbuffer_normal_tx.acquire(
148
149 GPUAttachment object_id_attachment = GPU_ATTACHMENT_NONE;
150 if (resources.object_id_tx.is_valid()) {
151 object_id_attachment = GPU_ATTACHMENT_TEXTURE(resources.object_id_tx);
152 }
153
154 if (!gbuffer_in_front_ps_.is_empty()) {
158 object_id_attachment);
159 gbuffer_in_front_fb.bind();
160
162
163 if (resources.depth_in_front_tx.is_valid()) {
164 GPU_texture_copy(resources.depth_in_front_tx, resources.depth_tx);
165 }
166 }
167
168 if (!gbuffer_ps_.is_empty()) {
172 object_id_attachment);
173 gbuffer_fb.bind();
174
175 manager.submit(gbuffer_ps_, view);
176 }
177
178 if (shadow_pass) {
180 resolution,
184
187 clear_fb.bind();
189
190 shadow_pass->draw(
191 manager, view, resources, **&shadow_depth_stencil_tx, !gbuffer_in_front_ps_.is_empty());
193 }
194 else {
196 deferred_ps_stencil_tx = nullptr;
197 }
198
199 if (!shadow_pass || !shadow_pass->is_debug()) {
202 deferred_fb.bind();
203 manager.submit(deferred_ps_, view);
204 }
205
206 gbuffer_normal_tx.release();
207 gbuffer_material_tx.release();
208}
209
211{
212 return gbuffer_ps_.is_empty() && gbuffer_in_front_ps_.is_empty();
213}
214
216
217/* -------------------------------------------------------------------- */
220
221void TransparentPass::sync(const SceneState &scene_state, SceneResources &resources)
222{
224 scene_state.cull_state;
225
226 bool clip = scene_state.clip_planes.size() > 0;
227
228 accumulation_ps_.init_pass(
229 resources, state | DRW_STATE_STENCIL_NEQUAL, scene_state.clip_planes.size());
230 accumulation_ps_.state_stencil(
232 accumulation_ps_.clear_color(float4(0.0f, 0.0f, 0.0f, 1.0f));
233 accumulation_ps_.init_subpasses(ePipelineType::TRANSPARENT, scene_state.lighting_type, clip);
234
235 accumulation_in_front_ps_.init_pass(resources, state, scene_state.clip_planes.size());
236 accumulation_in_front_ps_.clear_color(float4(0.0f, 0.0f, 0.0f, 1.0f));
237 accumulation_in_front_ps_.init_subpasses(
238 ePipelineType::TRANSPARENT, scene_state.lighting_type, clip);
239
240 resolve_ps_.init();
242 resolve_ps_.shader_set(ShaderCache::get().transparent_resolve.get());
243 resolve_ps_.bind_texture("transparentAccum", &accumulation_tx);
244 resolve_ps_.bind_texture("transparentRevealage", &reveal_tx);
245 resolve_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
246}
247
249 View &view,
250 SceneResources &resources,
251 int2 resolution)
252{
253 if (is_empty()) {
254 return;
255 }
256 accumulation_tx.acquire(
258 reveal_tx.acquire(
260
262
263 if (!accumulation_ps_.is_empty()) {
267 transparent_fb.bind();
268 manager.submit(accumulation_ps_, view);
269 resolve_fb.bind();
270 manager.submit(resolve_ps_, view);
271 }
272 if (!accumulation_in_front_ps_.is_empty()) {
276 transparent_fb.bind();
278 resolve_fb.bind();
279 manager.submit(resolve_ps_, view);
280 }
281
282 accumulation_tx.release();
283 reveal_tx.release();
284}
285
287{
288 return accumulation_ps_.is_empty() && accumulation_in_front_ps_.is_empty();
289}
290
292
293/* -------------------------------------------------------------------- */
296
297void TransparentDepthPass::sync(const SceneState &scene_state, SceneResources &resources)
298{
301
302 bool clip = scene_state.clip_planes.size() > 0;
303
304 DRWState in_front_state = state | DRW_STATE_STENCIL_ALWAYS;
305 in_front_ps_.init_pass(resources, in_front_state, scene_state.clip_planes.size());
306 in_front_ps_.state_stencil(uint8_t(StencilBits::OBJECT_IN_FRONT), 0xFF, 0x00);
308
309 merge_ps_.init();
310 merge_ps_.shader_set(ShaderCache::get().merge_depth.get());
313 merge_ps_.state_stencil(
315 merge_ps_.bind_texture("depth_tx", &resources.depth_in_front_tx);
316 merge_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
317
319 main_ps_.init_pass(resources, state, scene_state.clip_planes.size());
320 main_ps_.state_stencil(
323}
324
326{
327 if (is_empty()) {
328 return;
329 }
330
331 GPUAttachment object_id_attachment = GPU_ATTACHMENT_NONE;
332 if (resources.object_id_tx.is_valid()) {
333 object_id_attachment = GPU_ATTACHMENT_TEXTURE(resources.object_id_tx);
334 }
335
336 if (!in_front_ps_.is_empty()) {
340 object_id_attachment);
341 in_front_fb.bind();
342 manager.submit(in_front_ps_, view);
343
344 merge_fb.ensure(GPU_ATTACHMENT_TEXTURE(resources.depth_tx));
345 merge_fb.bind();
346 manager.submit(merge_ps_, view);
347 }
348
349 if (!main_ps_.is_empty()) {
350 main_fb.ensure(GPU_ATTACHMENT_TEXTURE(resources.depth_tx),
353 object_id_attachment);
354 main_fb.bind();
355 manager.submit(main_ps_, view);
356 }
357}
358
360{
361 return main_ps_.is_empty() && in_front_ps_.is_empty();
362}
363
365
366} // namespace blender::workbench
static AppView * view
#define GPU_ATTACHMENT_TEXTURE(_texture)
void GPU_framebuffer_clear_stencil(GPUFrameBuffer *fb, uint clear_stencil)
#define GPU_ATTACHMENT_NONE
@ GPU_PRIM_TRIS
void GPU_texture_copy(GPUTexture *dst, GPUTexture *src)
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_ATTACHMENT
@ GPU_TEXTURE_USAGE_FORMAT_VIEW
@ GPU_DEPTH24_STENCIL8
void submit(PassSimple &pass, View &view)
void bind_texture(const char *name, GPUTexture *texture, GPUSamplerState state=sampler_auto)
PassBase< DrawCommandBufType > & sub(const char *name)
Definition draw_pass.hh:616
void state_set(DRWState state, int clip_plane_count=0)
Definition draw_pass.hh:954
void bind_ubo(const char *name, GPUUniformBuf *buffer)
void push_constant(const char *name, const float &data)
void bind_ssbo(const char *name, GPUStorageBuf *buffer)
void shader_set(GPUShader *shader)
Definition draw_pass.hh:971
detail::PassBase< command::DrawMultiBuf > Sub
Definition draw_pass.hh:462
void setup_resolve_pass(PassSimple &pass, SceneResources &resources)
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, View &view, SceneResources &resources, int2 resolution, class ShadowPass *shadow_pass)
void draw(Manager &manager, View &view, SceneResources &resources, GPUTexture &depth_stencil_tx, bool force_fail_method)
GPUTexture * extract(Manager &manager, Texture &stencil_src)
void draw(Manager &manager, View &view, SceneResources &resources)
void sync(const SceneState &scene_state, SceneResources &resources)
void sync(const SceneState &scene_state, SceneResources &resources)
void draw(Manager &manager, View &view, SceneResources &resources, int2 resolution)
local_group_size(16, 16) .push_constant(Type texture
#define DRW_CLIPPING_UBO_SLOT
DRWState
Definition draw_state.hh:25
@ DRW_STATE_STENCIL_EQUAL
Definition draw_state.hh:47
@ DRW_STATE_BLEND_ALPHA
Definition draw_state.hh:55
@ DRW_STATE_STENCIL_ALWAYS
Definition draw_state.hh:46
@ DRW_STATE_DEPTH_LESS
Definition draw_state.hh:37
@ DRW_STATE_WRITE_DEPTH
Definition draw_state.hh:29
@ DRW_STATE_BLEND_OIT
Definition draw_state.hh:59
@ DRW_STATE_WRITE_COLOR
Definition draw_state.hh:30
@ DRW_STATE_DEPTH_LESS_EQUAL
Definition draw_state.hh:38
@ DRW_STATE_STENCIL_NEQUAL
Definition draw_state.hh:48
@ DRW_STATE_WRITE_STENCIL
Definition draw_state.hh:32
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
static ulong state[N]
detail::Pass< command::DrawMultiBuf > PassMain
static constexpr int geometry_type_len
static constexpr int shader_type_len
static const char * get_name(eGeometryType type)
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
#define FLT_MAX
Definition stdcycles.h:14
unsigned char uint8_t
Definition stdint.h:78
UniformBuffer< WorldData > world_buf
StorageVectorBuffer< Material > material_buf
UniformArrayBuffer< float4, 6 > clip_planes_buf
#define WB_TEXTURE_SLOT
#define WB_MATCAP_SLOT
#define WB_TILE_DATA_SLOT
#define WB_MATERIAL_SLOT
#define WB_WORLD_SLOT
#define WB_TILE_ARRAY_SLOT