26void ShadowPass::ShadowView::setup(View &view,
float3 light_direction,
bool force_fail_method)
28 force_fail_method_ = force_fail_method;
29 light_direction_ = light_direction;
30 sync(view.viewmat(), view.winmat());
59 const int3 corner_faces[8] = {
60 {x_neg, y_neg, z_pos},
61 {x_neg, y_neg, z_neg},
62 {x_neg, y_pos, z_neg},
63 {x_neg, y_pos, z_pos},
64 {x_pos, y_neg, z_pos},
65 {x_pos, y_neg, z_neg},
66 {x_pos, y_pos, z_neg},
67 {x_pos, y_pos, z_pos},
70 const int2 edge_faces[12] = {
85 const int2 edge_corners[12] = {
105 Vector<float4> faces_result;
106 Vector<float3> corners_result;
111 for (
int i : IndexRange(6)) {
113 frustum_planes[i] *=
float4(-1, -1, -1, 1);
115 face_lit[i] =
math::dot(
float3(frustum_planes[i]), light_direction_) < 0;
117 faces_result.append(frustum_planes[i]);
123 for (
int i : IndexRange(12)) {
124 int2 f = edge_faces[i];
125 bool a_lit = face_lit[f[0]];
126 bool b_lit = face_lit[f[1]];
127 if (a_lit != b_lit) {
129 float3 corner_a = frustum_corners.
vec[edge_corners[i][0]];
130 float3 corner_b = frustum_corners.
vec[edge_corners[i][1]];
137 bool flipped =
false;
138 for (
float3 corner : frustum_corners.vec) {
139 if (
math::dot(
float3(extruded_face), corner) > (extruded_face.w + 0.1)) {
147 faces_result.append(extruded_face);
151 for (
int i_corner : IndexRange(8)) {
153 for (
int i_face : IndexRange(3)) {
154 lit_faces += face_lit[corner_faces[i_corner][i_face]] ? 1 : 0;
158 corners_result.append(frustum_corners.
vec[i_corner]);
162 corners_result.append(
float3(frustum_corners.
vec[i_corner]) - (light_direction_ * 1e4f));
167 for (
int i : corners_result.index_range()) {
172 for (
int i : faces_result.index_range()) {
173 extruded_frustum_.
planes[i] = faces_result[i];
180bool ShadowPass::ShadowView::debug_object_culling(
Object *ob)
186 for (
int p : IndexRange(extruded_frustum_.planes_count)) {
187 float4 plane = extruded_frustum_.planes[p];
188 bool separating_axis =
true;
189 for (
float3 corner : bb.vec) {
192 if (signed_distance <= 0) {
193 separating_axis =
false;
197 if (separating_axis) {
198 printf(
"Sepatating Axis >>> x: %f, y: %f, z: %f, w: %f \n",
UNPACK4(plane));
205void ShadowPass::ShadowView::set_mode(ShadowPass::PassType type)
207 current_pass_type_ = type;
210void ShadowPass::ShadowView::compute_visibility(
ObjectBoundsBuf &bounds,
219 uint word_per_draw = this->visibility_word_per_draw();
222 resource_len * word_per_draw;
226 if (current_pass_type_ == ShadowPass::PASS) {
228 pass_visibility_buf_.resize(words_len);
230 fail_visibility_buf_.resize(words_len);
233 else if (current_pass_type_ == ShadowPass::FAIL) {
239 visibility_buf_.resize(words_len);
243 if (do_visibility_) {
245 GPUShader *shader = current_pass_type_ == ShadowPass::FORCED_FAIL ?
256 if (current_pass_type_ == ShadowPass::FORCED_FAIL) {
273VisibilityBuf &ShadowPass::ShadowView::get_visibility_buffer()
275 switch (current_pass_type_) {
276 case ShadowPass::PASS:
277 return pass_visibility_buf_;
278 case ShadowPass::FAIL:
279 return fail_visibility_buf_;
280 case ShadowPass::FORCED_FAIL:
281 return visibility_buf_;
285 return visibility_buf_;
290 return passes_[type][manifold][cap];
303 float3 direction_ws = scene.display.light_direction;
305 std::swap(direction_ws.y, direction_ws.z);
306 direction_ws *=
float3(-1, 1, -1);
322 float focus =
clamp_f(scene.display.shadow_focus, 0.0001f, 0.99999f);
335#if DEBUG_SHADOW_VOLUME
353 forced_fail_ps_.
init();
354 forced_fail_ps_.
state_set(depth_fail_state);
358 for (
bool manifold : {
false,
true}) {
360 ps = &pass_ps_.
sub(manifold ?
"manifold" :
"non_manifold");
362 ps->
bind_ubo(
"pass_data", pass_data_);
364 for (PassType fail_type : {FAIL, FORCED_FAIL}) {
365 PassMain &ps_main = fail_type == FAIL ? fail_ps_ : forced_fail_ps_;
367 PassMain::Sub *&ps = get_pass_ptr(fail_type, manifold,
false);
368 ps = &ps_main.
sub(manifold ?
"NoCaps.manifold" :
"NoCaps.non_manifold");
370 ps->
bind_ubo(
"pass_data", pass_data_);
372 PassMain::Sub *&caps_ps = get_pass_ptr(fail_type, manifold,
true);
373 caps_ps = &ps_main.
sub(manifold ?
"Caps.manifold" :
"Caps.non_manifold");
375 caps_ps->
bind_ubo(
"pass_data", pass_data_);
383 const bool has_transp_mat)
392 if (geom_shadow ==
nullptr) {
396#define DEBUG_CULLING 0
399 ShadowView shadow_view = ShadowView(
"ShadowView", view, pass_data_.
light_direction_ws);
401 "%s culling : %s\n", ob->
id.
name, shadow_view.debug_object_culling(ob) ?
"true" :
"false");
406 bool force_fail_pass = has_transp_mat || (!is_manifold && (scene_state.
cull_state != 0));
408 PassType fail_type = force_fail_pass ? FORCED_FAIL : FAIL;
414 int tri_len = is_manifold ? 2 : 4;
416 if (!force_fail_pass) {
418 ps.
draw_expand(geom_shadow, prim, tri_len, 1, handle);
423 get_pass_ptr(fail_type, is_manifold,
true)->
draw_expand(geom_faces, prim, 2, 1, handle);
425 get_pass_ptr(fail_type, is_manifold,
false)->
draw_expand(geom_shadow, prim, tri_len, 1, handle);
431 GPUTexture &depth_stencil_tx,
432 bool force_fail_method)
444 view_.set_mode(PASS);
445 manager.
submit(pass_ps_, view_);
446 view_.set_mode(FAIL);
447 manager.
submit(fail_ps_, view_);
448 view_.set_mode(FORCED_FAIL);
449 manager.
submit(forced_fail_ps_, view_);
General operations, lookup, etc. for blender objects.
void BKE_boundbox_init_from_minmax(BoundBox *bb, const float min[3], const float max[3])
std::optional< blender::Bounds< blender::float3 > > BKE_object_boundbox_get(const Object *ob)
#define BLI_assert_unreachable()
MINLINE uint ceil_to_multiple_u(uint a, uint b)
MINLINE uint divide_ceil_u(uint a, uint b)
MINLINE float clamp_f(float value, float min, float max)
MINLINE int max_ii(int a, int b)
#define UNUSED_VARS_NDEBUG(...)
static void View(GHOST_IWindow *window, bool stereo, int eye=0)
void GPU_compute_dispatch(GPUShader *shader, uint groups_x_len, uint groups_y_len, uint groups_z_len)
void GPU_debug_group_end()
void GPU_debug_group_begin(const char *name)
#define GPU_ATTACHMENT_TEXTURE(_texture)
void GPU_shader_uniform_1i(GPUShader *sh, const char *name, int value)
int GPU_shader_get_ubo_binding(GPUShader *shader, const char *name)
void GPU_shader_uniform_3fv(GPUShader *sh, const char *name, const float data[3])
int GPU_shader_get_ssbo_binding(GPUShader *shader, const char *name)
void GPU_shader_bind(GPUShader *shader)
void GPU_shader_uniform_1b(GPUShader *sh, const char *name, bool value)
void GPU_memory_barrier(eGPUBarrier barrier)
@ GPU_BARRIER_SHADER_STORAGE
void GPU_storagebuf_bind(GPUStorageBuf *ssbo, int slot)
void GPU_storagebuf_clear(GPUStorageBuf *ssbo, uint32_t clear_value)
struct GPUShader GPUShader
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)
PassBase< DrawCommandBufType > & sub(const char *name)
void state_set(DRWState state, int clip_plane_count=0)
void bind_ubo(const char *name, GPUUniformBuf *buffer)
void state_stencil(uint8_t write_mask, uint8_t reference, uint8_t compare_mask)
void draw_expand(gpu::Batch *batch, GPUPrimType primitive_type, uint primitive_len, uint instance_len, uint vertex_len=-1, uint vertex_first=-1, ResourceHandle handle={0}, uint custom_id=0)
void shader_set(GPUShader *shader)
detail::PassBase< command::DrawMultiBuf > Sub
static ShaderCache & get()
GPUShader * shadow_get(bool depth_pass, bool manifold, bool cap=false)
StaticShader shadow_visibility_static
StaticShader shadow_visibility_dynamic
void init(const SceneState &scene_state, SceneResources &resources)
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)
blender::gpu::Batch * DRW_cache_object_surface_get(Object *ob)
blender::gpu::Batch * DRW_cache_object_edge_detection_get(Object *ob, bool *r_is_manifold)
#define DRW_VISIBILITY_GROUP_SIZE
#define DRW_VIEW_UBO_SLOT
const DRWView * DRW_view_default_get()
void DRW_view_viewmat_get(const DRWView *view, float mat[4][4], bool inverse)
void DRW_culling_frustum_planes_get(const DRWView *view, float planes[6][4])
void DRW_culling_frustum_corners_get(const DRWView *view, BoundBox *corners)
@ DRW_STATE_STENCIL_ALWAYS
@ DRW_STATE_DEPTH_GREATER_EQUAL
@ DRW_STATE_WRITE_STENCIL_SHADOW_FAIL
@ DRW_STATE_BLEND_ADD_FULL
@ DRW_STATE_WRITE_STENCIL_SHADOW_PASS
StorageArrayBuffer< ObjectBounds, 128 > ObjectBoundsBuf
StorageArrayBuffer< ObjectInfos, 128 > ObjectInfosBuf
StorageArrayBuffer< uint, 4, true > VisibilityBuf
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
AxisSigned cross(const AxisSigned a, const AxisSigned b)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
VecBase< T, 3 > transform_direction(const MatBase< T, 3, 3 > &mat, const VecBase< T, 3 > &direction)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
VecBase< float, 4 > float4
VecBase< float, 3 > float3
packed_float3 light_direction_ws
float4 shadow_direction_vs
const c_style_mat & ptr() const
UniformBuffer< WorldData > world_buf
#define DEBUG_SHADOW_VOLUME