Blender V5.0
draw_view.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2022 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
19
20#include "DNA_view3d_types.h"
21#include "DRW_gpu_wrapper.hh"
22#include "GPU_matrix.hh"
23
24#include "draw_shader_shared.hh"
25#include <atomic>
26#include <cstdint>
27
28namespace blender::draw {
29
30class Manager;
31
32/* TODO: de-duplicate. */
36
37class View {
38 friend Manager;
39
41 static std::atomic<uint32_t> global_sync_counter_;
42
43 /* Local sync counter. Used for fingerprint. */
44 uint32_t sync_counter_ = 0;
45
46 protected:
48
56 /* Fingerprint of the manager state when visibility was computed. */
58
59 const char *debug_name_;
60
61 int view_len_ = 0;
62
63 bool is_inverted_ = false;
64 bool do_visibility_ = true;
65 bool dirty_ = true;
66 bool frozen_ = false;
67 bool procedural_ = false;
68
69 public:
70 View(const char *name, int view_len = 1, bool procedural = false)
71 : visibility_buf_(name), debug_name_(name), view_len_(view_len), procedural_(procedural)
72 {
73 BLI_assert(view_len <= DRW_VIEW_MAX);
74 }
75
76 virtual ~View() = default;
77
78 void sync(const float4x4 &view_mat, const float4x4 &win_mat, int view_id = 0);
79
81 void visibility_test(bool enable)
82 {
83 do_visibility_ = enable;
84 }
85
92
93 bool is_persp(int view_id = 0) const
94 {
95 BLI_assert(view_id < view_len_);
96 return data_[view_id].winmat[3][3] == 0.0f;
97 }
98
99 bool is_inverted(int view_id = 0) const
100 {
101 BLI_assert(view_id < view_len_);
102 UNUSED_VARS_NDEBUG(view_id);
103 return is_inverted_;
104 }
105
106 float far_clip(int view_id = 0) const
107 {
108 BLI_assert(view_id < view_len_);
109 if (is_persp(view_id)) {
110 return -data_[view_id].winmat[3][2] / (data_[view_id].winmat[2][2] + 1.0f);
111 }
112 return -(data_[view_id].winmat[3][2] - 1.0f) / data_[view_id].winmat[2][2];
113 }
114
115 float near_clip(int view_id = 0) const
116 {
117 BLI_assert(view_id < view_len_);
118 if (is_persp(view_id)) {
119 return -data_[view_id].winmat[3][2] / (data_[view_id].winmat[2][2] - 1.0f);
120 }
121 return -(data_[view_id].winmat[3][2] + 1.0f) / data_[view_id].winmat[2][2];
122 }
123
124 const float3 &location(int view_id = 0) const
125 {
126 BLI_assert(view_id < view_len_);
127 return data_[view_id].viewinv.location();
128 }
129
130 const float3 &forward(int view_id = 0) const
131 {
132 BLI_assert(view_id < view_len_);
133 return data_[view_id].viewinv.z_axis();
134 }
135
136 const float4x4 &viewmat(int view_id = 0) const
137 {
138 BLI_assert(view_id < view_len_);
139 return data_[view_id].viewmat;
140 }
141
142 const float4x4 &viewinv(int view_id = 0) const
143 {
144 BLI_assert(view_id < view_len_);
145 return data_[view_id].viewinv;
146 }
147
148 const float4x4 &winmat(int view_id = 0) const
149 {
150 BLI_assert(view_id < view_len_);
151 return data_[view_id].winmat;
152 }
153
154 const float4x4 &wininv(int view_id = 0) const
155 {
156 BLI_assert(view_id < view_len_);
157 return data_[view_id].wininv;
158 }
159
160 /* Compute and return the perspective matrix. */
161 const float4x4 persmat(int view_id = 0) const
162 {
163 BLI_assert(view_id < view_len_);
164 return data_[view_id].winmat * data_[view_id].viewmat;
165 }
166
168 {
169 return (view_len_ == 1) ? 0 : divide_ceil_u(view_len_, 32);
170 }
171
176
177 /* TODO(fclem): Remove. Global DST access. */
178 static View &default_get();
179 static void default_set(const float4x4 &view_mat, const float4x4 &win_mat);
180
181 /* Data to save per overlay to not rely on rv3d for rendering.
182 * TODO(fclem): Compute offset directly from the view. */
183 struct OffsetData {
184 /* Copy of rv3d->dist. */
185 float dist = 0.0f;
186 /* Copy of rv3d->persp. */
187 char persp = 0;
188 /* Copy of rv3d->is_persp. */
189 bool is_persp = false;
190
191 OffsetData() = default;
193 : dist(rv3d.dist), persp(rv3d.persp), is_persp(rv3d.is_persp != 0)
194 {
195 }
196
198 {
199 float view_dist = dist;
200 /* Special exception for orthographic camera:
201 * `view_dist` isn't used as the depth range isn't the same. */
202 if (persp == RV3D_CAMOB && is_persp == false) {
203 view_dist = 1.0f / max_ff(fabsf(winmat[0][0]), fabsf(winmat[1][1]));
204 }
205
207 result[3][2] -= GPU_polygon_offset_calc(winmat.ptr(), view_dist, offset);
208 return result;
209 }
210
211 /* Return unit offset to apply to `gl_Position.z`. To be scaled depending on purpose. */
213 {
214 float view_dist = dist;
215 /* Special exception for orthographic camera:
216 * `view_dist` isn't used as the depth range isn't the same. */
217 if (persp == RV3D_CAMOB && is_persp == false) {
218 view_dist = 1.0f / max_ff(fabsf(winmat[0][0]), fabsf(winmat[1][1]));
219 }
220
221 return GPU_polygon_offset_calc(winmat.ptr(), view_dist, 1.0);
222 }
223 };
224
225 /* Returns frustum planes equations. Available only after sync. */
226 std::array<float4, 6> frustum_planes_get(int view_id = 0);
227 /* Returns frustum corners positions in world space. Available only after sync. */
228 std::array<float3, 8> frustum_corners_get(int view_id = 0);
229
230 protected:
232 void bind();
234 ObjectInfosBuf &infos,
235 uint resource_len,
236 bool debug_freeze);
238
240 {
241 /* NOTE: Even though manager fingerprint is not enough to check for update, it is still
242 * guaranteed to not be 0. So we can check weather or not this view has computed visibility
243 * after sync. Asserts will catch invalid usage . */
244 return manager_fingerprint_ != 0;
245 }
246
247 /* Fingerprint of the view for the current state.
248 * Not reliable enough for general update detection. Only to be used for debugging assertion. */
250 {
251 BLI_assert_msg(sync_counter_ != 0, "View should be synced at least once before use");
252 return sync_counter_;
253 }
254
256
257 /* WARNING: These 3 functions must be called in order */
258 void frustum_boundbox_calc(int view_id);
259 void frustum_culling_planes_calc(int view_id);
260 void frustum_culling_sphere_calc(int view_id);
261};
262
263} // namespace blender::draw
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
MINLINE float max_ff(float a, float b)
MINLINE uint divide_ceil_u(uint a, uint b)
unsigned int uint
#define UNUSED_VARS_NDEBUG(...)
@ RV3D_CAMOB
float GPU_polygon_offset_calc(const float(*winmat)[4], float viewdist, float dist)
unsigned long long int uint64_t
const float3 & location(int view_id=0) const
Definition draw_view.hh:124
UniformArrayBuffer< ViewCullingData, DRW_VIEW_MAX > culling_
Definition draw_view.hh:50
void visibility_test(bool enable)
Definition draw_view.hh:81
static void default_set(const float4x4 &view_mat, const float4x4 &win_mat)
Definition draw_view.cc:322
View(const char *name, int view_len=1, bool procedural=false)
Definition draw_view.hh:70
VisibilityBuf visibility_buf_
Definition draw_view.hh:55
bool is_inverted(int view_id=0) const
Definition draw_view.hh:99
bool is_persp(int view_id=0) const
Definition draw_view.hh:93
const float4x4 & winmat(int view_id=0) const
Definition draw_view.hh:148
const float4x4 persmat(int view_id=0) const
Definition draw_view.hh:161
const float4x4 & viewmat(int view_id=0) const
Definition draw_view.hh:136
float near_clip(int view_id=0) const
Definition draw_view.hh:115
bool has_computed_visibility() const
Definition draw_view.hh:239
void compute_procedural_bounds()
Definition draw_view.cc:238
UniformArrayBuffer< ViewMatrices, DRW_VIEW_MAX > data_freeze_
Definition draw_view.hh:52
virtual void compute_visibility(ObjectBoundsBuf &bounds, ObjectInfosBuf &infos, uint resource_len, bool debug_freeze)
Definition draw_view.cc:257
UniformArrayBuffer< ViewMatrices, DRW_VIEW_MAX > data_
Definition draw_view.hh:49
UniformArrayBuffer< ViewCullingData, DRW_VIEW_MAX > culling_freeze_
Definition draw_view.hh:53
static View & default_get()
Definition draw_view.cc:317
UniformArrayBuffer< ViewMatrices, DRW_VIEW_MAX > & matrices_ubo_get()
Definition draw_view.hh:172
const float4x4 & viewinv(int view_id=0) const
Definition draw_view.hh:142
virtual VisibilityBuf & get_visibility_buffer()
Definition draw_view.cc:312
uint64_t manager_fingerprint_
Definition draw_view.hh:57
void frustum_culling_sphere_calc(int view_id)
Definition draw_view.cc:111
const float4x4 & wininv(int view_id=0) const
Definition draw_view.hh:154
virtual ~View()=default
std::array< float3, 8 > frustum_corners_get(int view_id=0)
Definition draw_view.cc:337
const float3 & forward(int view_id=0) const
Definition draw_view.hh:130
int visibility_word_per_draw() const
Definition draw_view.hh:167
std::array< float4, 6 > frustum_planes_get(int view_id=0)
Definition draw_view.cc:327
void frustum_boundbox_calc(int view_id)
Definition draw_view.cc:46
float far_clip(int view_id=0) const
Definition draw_view.hh:106
uint64_t fingerprint_get() const
Definition draw_view.hh:249
const char * debug_name_
Definition draw_view.hh:59
void sync(const float4x4 &view_mat, const float4x4 &win_mat, int view_id=0)
Definition draw_view.cc:27
void frustum_culling_planes_calc(int view_id)
Definition draw_view.cc:92
#define DRW_VIEW_MAX
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
MatBase< float, 4, 4 > float4x4
VecBase< float, 3 > float3
const char * name
#define fabsf
OffsetData(const RegionView3D &rv3d)
Definition draw_view.hh:192
float polygon_offset_factor(const float4x4 &winmat)
Definition draw_view.hh:212
float4x4 winmat_polygon_offset(const float4x4 &winmat, float offset)
Definition draw_view.hh:197