Blender V4.3
basic_engine.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2016 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
12#include "DRW_render.hh"
13
14#include "BKE_global.hh"
15#include "BKE_object.hh"
16#include "BKE_object_types.hh"
17#include "BKE_paint.hh"
18#include "BKE_particle.h"
19
20#include "BLI_alloca.h"
21
22#include "DNA_particle_types.h"
23
24#include "GPU_shader.hh"
25
26#include "basic_engine.h"
27#include "basic_private.h"
28
29#define BASIC_ENGINE "BLENDER_BASIC"
30
31/* *********** LISTS *********** */
32
33/* GPUViewport.storage
34 * Is freed every time the viewport engine changes. */
38
44
52
53/* *********** STATIC *********** */
54
63
64static void basic_cache_init(void *vedata)
65{
66 BASIC_PassList *psl = ((BASIC_Data *)vedata)->psl;
67 BASIC_StorageList *stl = ((BASIC_Data *)vedata)->stl;
68 DRWShadingGroup *grp;
69
70 const DRWContextState *draw_ctx = DRW_context_state_get();
71
72 if (!stl->g_data) {
73 /* Alloc transient pointers */
74 stl->g_data = static_cast<BASIC_PrivateData *>(MEM_callocN(sizeof(*stl->g_data), __func__));
75 }
76
78
79 /* Twice for normal and in front objects. */
80 for (int i = 0; i < 2; i++) {
81 DRWState clip_state = DRWState(
83 DRWState infront_state = DRWState(
86
90
91 DRW_PASS_CREATE(psl->depth_pass[i], state | clip_state | infront_state);
92 stl->g_data->depth_shgrp[i] = grp = DRW_shgroup_create(sh, psl->depth_pass[i]);
93 DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
94
95 sh = DRW_state_is_select() ?
98 DRW_PASS_CREATE(psl->depth_pass_pointcloud[i], state | clip_state | infront_state);
100 sh, psl->depth_pass_pointcloud[i]);
101 DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
102
104 BASIC_shaders_depth_sh_get(draw_ctx->sh_cfg), psl->depth_pass[i]);
105 DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
106
109 DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
110
114 DRW_PASS_CREATE(psl->depth_pass_cull[i], state | clip_state | infront_state);
115 stl->g_data->depth_shgrp_cull[i] = grp = DRW_shgroup_create(sh, psl->depth_pass_cull[i]);
116 DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
117 }
118}
119
120/* TODO(fclem): DRW_cache_object_surface_material_get needs a refactor to allow passing nullptr
121 * instead of gpumat_array. Avoiding all this boilerplate code. */
122static blender::gpu::Batch **basic_object_surface_material_get(Object *ob)
123{
124 const int materials_len = DRW_cache_object_material_count_get(ob);
125 GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len);
126 memset(gpumat_array, 0, sizeof(*gpumat_array) * materials_len);
127
128 return DRW_cache_object_surface_material_get(ob, gpumat_array, materials_len);
129}
130
131static void basic_cache_populate_particles(void *vedata, Object *ob)
132{
133 const bool do_in_front = (ob->dtx & OB_DRAW_IN_FRONT) != 0;
134 BASIC_StorageList *stl = ((BASIC_Data *)vedata)->stl;
135 for (ParticleSystem *psys = static_cast<ParticleSystem *>(ob->particlesystem.first);
136 psys != nullptr;
137 psys = psys->next)
138 {
140 continue;
141 }
142 ParticleSettings *part = psys->part;
143 const int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as;
144 if (draw_as == PART_DRAW_PATH) {
145 blender::gpu::Batch *hairs = DRW_cache_particles_get_hair(ob, psys, nullptr);
147 const short material_slot = part->omat;
148 DRW_select_load_id(ob->runtime->select_id | (material_slot << 16));
149 }
150 DRW_shgroup_call(stl->g_data->depth_hair_shgrp[do_in_front], hairs, nullptr);
151 }
152 }
153}
154
155static void basic_cache_populate(void *vedata, Object *ob)
156{
157 using namespace blender::draw;
158 BASIC_StorageList *stl = ((BASIC_Data *)vedata)->stl;
159
160 /* TODO(fclem): fix selection of smoke domains. */
161
162 if (!DRW_object_is_renderable(ob) || (ob->dt < OB_SOLID)) {
163 return;
164 }
165
166 const DRWContextState *draw_ctx = DRW_context_state_get();
167 if (ob != draw_ctx->object_edit) {
169 }
170
171 const bool do_in_front = (ob->dtx & OB_DRAW_IN_FRONT) != 0;
172 if (ob->type == OB_CURVES) {
173 DRW_shgroup_curves_create_sub(ob, stl->g_data->depth_curves_shgrp[do_in_front], nullptr);
174 }
175
176 if (ob->type == OB_POINTCLOUD) {
177 DRW_shgroup_pointcloud_create_sub(
178 ob, stl->g_data->depth_pointcloud_shgrp[do_in_front], nullptr);
179 return;
180 }
181
182 /* Make flat object selectable in ortho view if wireframe is enabled. */
183 if ((draw_ctx->v3d->overlay.flag & V3D_OVERLAY_WIREFRAMES) ||
184 (draw_ctx->v3d->shading.type == OB_WIRE) || (ob->dtx & OB_DRAWWIRE) || (ob->dt == OB_WIRE))
185 {
186 int flat_axis = 0;
187 bool is_flat_object_viewed_from_side = ((draw_ctx->rv3d->persp == RV3D_ORTHO) &&
188 DRW_object_is_flat(ob, &flat_axis) &&
190
191 if (is_flat_object_viewed_from_side) {
192 /* Avoid losing flat objects when in ortho views (see #56549) */
193 blender::gpu::Batch *geom = DRW_cache_object_all_edges_get(ob);
194 if (geom) {
195 DRW_shgroup_call(stl->g_data->depth_shgrp[do_in_front], geom, ob);
196 }
197 return;
198 }
199 }
200
201 const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->rv3d) &&
203 const bool do_cull = (draw_ctx->v3d &&
205
206 DRWShadingGroup *shgrp = (do_cull) ? stl->g_data->depth_shgrp_cull[do_in_front] :
207 stl->g_data->depth_shgrp[do_in_front];
208
209 if (use_sculpt_pbvh) {
210 DRW_shgroup_call_sculpt(shgrp, ob, false, false, false, false, false);
211 }
212 else {
214 blender::gpu::Batch **geoms = basic_object_surface_material_get(ob);
215 if (geoms) {
216 const int materials_len = DRW_cache_object_material_count_get(ob);
217 for (int i = 0; i < materials_len; i++) {
218 if (geoms[i] == nullptr) {
219 continue;
220 }
221 const short material_slot_select_id = i + 1;
222 DRW_select_load_id(ob->runtime->select_id | (material_slot_select_id << 16));
223 DRW_shgroup_call(shgrp, geoms[i], ob);
224 }
225 }
226 }
227 else {
228 blender::gpu::Batch *geom = DRW_cache_object_surface_get(ob);
229 if (geom) {
230 DRW_shgroup_call(shgrp, geom, ob);
231 }
232 }
233
234 if (G.debug_value == 889 && ob->sculpt && blender::bke::object::pbvh_get(*ob)) {
235 int debug_node_nr = 0;
236 DRW_debug_modelmat(ob->object_to_world().ptr());
239 }
240 }
241}
242
243static void basic_cache_finish(void *vedata)
244{
245 BASIC_StorageList *stl = ((BASIC_Data *)vedata)->stl;
246
247 UNUSED_VARS(stl);
248}
249
250static void basic_draw_scene(void *vedata)
251{
252 BASIC_PassList *psl = ((BASIC_Data *)vedata)->psl;
253
254 DRW_draw_pass(psl->depth_pass[0]);
257 DRW_draw_pass(psl->depth_pass[1]);
260}
261
262static void basic_engine_free()
263{
265}
266
268
270 /*next*/ nullptr,
271 /*prev*/ nullptr,
272 /*idname*/ N_("Basic"),
273 /*vedata_size*/ &basic_data_size,
274 /*engine_init*/ nullptr,
275 /*engine_free*/ &basic_engine_free,
276 /*instance_free*/ nullptr,
277 /*cache_init*/ &basic_cache_init,
278 /*cache_populate*/ &basic_cache_populate,
279 /*cache_finish*/ &basic_cache_finish,
280 /*draw_scene*/ &basic_draw_scene,
281 /*view_update*/ nullptr,
282 /*id_update*/ nullptr,
283 /*render_to_image*/ nullptr,
284 /*store_metadata*/ nullptr,
285};
286
287#undef BASIC_ENGINE
General operations, lookup, etc. for blender objects.
bool BKE_object_supports_material_slots(Object *ob)
bool BKE_sculptsession_use_pbvh_draw(const Object *ob, const RegionView3D *rv3d)
Definition paint.cc:2862
void BKE_pbvh_draw_debug_cb(blender::bke::pbvh::Tree &pbvh, void(*draw_fn)(blender::bke::pbvh::Node *node, void *user_data, const float bmin[3], const float bmax[3], PBVHNodeFlags flag), void *user_data)
Definition pbvh.cc:2368
#define BLI_array_alloca(arr, realsize)
Definition BLI_alloca.h:25
#define UNUSED_VARS(...)
@ OB_WIRE
@ OB_SOLID
@ OB_POINTCLOUD
@ OB_CURVES
@ OB_DRAW_IN_FRONT
@ OB_DRAWWIRE
@ PART_DRAW_PATH
@ PART_DRAW_REND
@ V3D_OVERLAY_WIREFRAMES
@ V3D_SHADING_BACKFACE_CULLING
@ RV3D_ORTHO
char DRWViewportEmptyList
Definition DRW_render.hh:97
#define DRW_PASS_CREATE(pass, state)
#define DRW_shgroup_uniform_block(shgroup, name, ubo)
#define DRW_VIEWPORT_DATA_SIZE(ty)
#define DRW_shgroup_call(shgroup, geom, ob)
@ GPU_SHADER_CFG_CLIPPED
static void basic_engine_free()
static void basic_cache_populate(void *vedata, Object *ob)
static const DrawEngineDataSize basic_data_size
static void basic_cache_finish(void *vedata)
static blender::gpu::Batch ** basic_object_surface_material_get(Object *ob)
DrawEngineType draw_engine_basic_type
static void basic_cache_init(void *vedata)
static void basic_draw_scene(void *vedata)
static void basic_cache_populate_particles(void *vedata, Object *ob)
GPUShader * BASIC_shaders_pointcloud_depth_conservative_sh_get(eGPUShaderConfig config)
void BASIC_shaders_free(void)
GPUShader * BASIC_shaders_depth_sh_get(eGPUShaderConfig config)
GPUShader * BASIC_shaders_depth_conservative_sh_get(eGPUShaderConfig config)
GPUShader * BASIC_shaders_pointcloud_depth_sh_get(eGPUShaderConfig config)
GPUShader * BASIC_shaders_curves_depth_sh_get(eGPUShaderConfig config)
struct GPUShader GPUShader
blender::gpu::Batch * DRW_cache_object_surface_get(Object *ob)
blender::gpu::Batch * DRW_cache_object_all_edges_get(Object *ob)
blender::gpu::Batch * DRW_cache_particles_get_hair(Object *object, ParticleSystem *psys, ModifierData *md)
blender::gpu::Batch ** DRW_cache_object_surface_material_get(Object *ob, GPUMaterial **gpumat_array, uint gpumat_array_len)
int DRW_cache_object_material_count_get(const Object *ob)
bool DRW_object_is_flat(Object *ob, int *r_axis)
bool DRW_object_axis_orthogonal_to_view(Object *ob, int axis)
DRW_Global G_draw
void DRW_debug_modelmat(const float modelmat[4][4])
bool DRW_state_is_material_select()
bool DRW_object_is_renderable(const Object *ob)
bool DRW_state_is_image_render()
bool DRW_object_is_visible_psys_in_active_context(const Object *object, const ParticleSystem *psys)
const DRWContextState * DRW_context_state_get()
bool DRW_state_is_select()
DRWShadingGroup * DRW_shgroup_create(GPUShader *shader, DRWPass *pass)
void DRW_shgroup_call_sculpt(DRWShadingGroup *shgroup, Object *ob, bool use_wire, bool use_mask, bool use_fset, bool use_color, bool use_uv)
void DRW_sculpt_debug_cb(blender::bke::pbvh::Node *node, void *user_data, const float bmin[3], const float bmax[3], PBVHNodeFlags flag)
void DRW_draw_pass(DRWPass *pass)
void DRW_select_load_id(uint id)
DRWState
Definition draw_state.hh:25
@ DRW_STATE_CLIP_PLANES
Definition draw_state.hh:69
@ DRW_STATE_NO_DRAW
Definition draw_state.hh:27
@ DRW_STATE_IN_FRONT_SELECT
Definition draw_state.hh:67
@ DRW_STATE_WRITE_DEPTH
Definition draw_state.hh:29
@ DRW_STATE_DEPTH_LESS_EQUAL
Definition draw_state.hh:38
@ DRW_STATE_CULL_BACK
Definition draw_state.hh:43
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
static ulong state[N]
#define G(x, y, z)
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:2846
BASIC_StorageList * stl
DRWViewportEmptyList * fbl
void * engine_type
BASIC_PassList * psl
DRWViewportEmptyList * txl
DRWPass * depth_pass_pointcloud[2]
DRWPass * depth_pass[2]
DRWPass * depth_pass_cull[2]
DRWShadingGroup * depth_shgrp[2]
DRWShadingGroup * depth_hair_shgrp[2]
DRWShadingGroup * depth_shgrp_cull[2]
DRWShadingGroup * depth_pointcloud_shgrp[2]
bool use_material_slot_selection
DRWShadingGroup * depth_curves_shgrp[2]
struct BASIC_PrivateData * g_data
eGPUShaderConfig sh_cfg
Object * object_edit
RegionView3D * rv3d
GPUUniformBuf * block_ubo
void * first
ListBase particlesystem
ObjectRuntimeHandle * runtime
struct SculptSession * sculpt
struct ParticleSystem * next
View3DOverlay overlay
View3DShading shading
#define N_(msgid)