Blender V5.0
workbench_effect_cavity.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
15
16#include "BLI_rand.h"
17#include "DNA_scene_types.h"
18#include "workbench_private.hh"
19
20namespace blender::workbench {
21
22void CavityEffect::init(const SceneState &scene_state, SceneResources &resources)
23{
24 cavity_enabled_ = scene_state.draw_cavity;
25 curvature_enabled_ = scene_state.draw_curvature;
26
27 const int ssao_samples = scene_state.scene->display.matcap_ssao_samples;
28 int sample_count = min_ii(scene_state.samples_len * ssao_samples, max_samples_);
29 const int max_iter_count = sample_count / ssao_samples;
30
31 sample_ = scene_state.sample % max_iter_count;
32
33 UniformBuffer<WorldData> &world_buf = resources.world_buf;
34
35 world_buf.cavity_sample_start = ssao_samples * sample_;
36 world_buf.cavity_sample_end = ssao_samples * (sample_ + 1);
37
38 world_buf.cavity_sample_count_inv = 1.0f / (world_buf.cavity_sample_end -
39 world_buf.cavity_sample_start);
40 world_buf.cavity_jitter_scale = 1.0f / 64.0f;
41
42 world_buf.cavity_valley_factor = scene_state.shading.cavity_valley_factor;
43 world_buf.cavity_ridge_factor = scene_state.shading.cavity_ridge_factor;
44 world_buf.cavity_attenuation = scene_state.scene->display.matcap_ssao_attenuation;
45 world_buf.cavity_distance = scene_state.scene->display.matcap_ssao_distance;
46
47 world_buf.curvature_ridge = 0.5f /
48 max_ff(square_f(scene_state.shading.curvature_ridge_factor), 1e-4f);
49 world_buf.curvature_valley = 0.7f / max_ff(square_f(scene_state.shading.curvature_valley_factor),
50 1e-4f);
51
52 if (cavity_enabled_ && sample_count_ != sample_count) {
53 sample_count_ = sample_count;
54 load_samples_buf(ssao_samples);
55 resources.load_jitter_tx(sample_count_);
56 }
57}
58
59void CavityEffect::load_samples_buf(int ssao_samples)
60{
61 const float iteration_samples_inv = 1.0f / ssao_samples;
62
63 /* Create disk samples using Hammersley distribution */
64 for (int i : IndexRange(sample_count_)) {
65 float it_add = (i / ssao_samples) * 0.499f;
66 float r = fmodf((i + 0.5f + it_add) * iteration_samples_inv, 1.0f);
67 double dphi;
68 BLI_hammersley_1d(i, &dphi);
69
70 float phi = float(dphi) * 2.0f * M_PI + it_add;
71 samples_buf[i].x = math::cos(phi);
72 samples_buf[i].y = math::sin(phi);
73 /* This deliberately distribute more samples
74 * at the center of the disk (and thus the shadow). */
75 samples_buf[i].z = r;
76 }
77
78 samples_buf.push_update();
79}
80
82{
83 if (cavity_enabled_) {
84 pass.bind_ubo("cavity_samples", samples_buf);
85 pass.bind_texture("jitter_tx",
86 &resources.jitter_tx,
87 {GPU_SAMPLER_FILTERING_DEFAULT,
88 GPU_SAMPLER_EXTEND_MODE_REPEAT,
89 GPU_SAMPLER_EXTEND_MODE_REPEAT});
90 }
91 if (curvature_enabled_) {
92 pass.bind_texture("object_id_tx", &resources.object_id_tx);
93 }
94}
95
96} // namespace blender::workbench
MINLINE float max_ff(float a, float b)
MINLINE int min_ii(int a, int b)
MINLINE float square_f(float a)
#define M_PI
Random number functions.
void BLI_hammersley_1d(unsigned int n, double *r)
Definition rand.cc:281
void bind_texture(const char *name, gpu::Texture *texture, GPUSamplerState state=sampler_auto)
void bind_ubo(const char *name, gpu::UniformBuf *buffer)
void setup_resolve_pass(PassSimple &pass, SceneResources &resources)
void init(const SceneState &scene_state, SceneResources &resources)
nullptr float
#define fmodf(x, y)
detail::Pass< command::DrawCommandBuf > PassSimple
T cos(const AngleRadianBase< T > &a)
T sin(const AngleRadianBase< T > &a)
float matcap_ssao_attenuation
struct SceneDisplay display
float curvature_valley_factor
UniformBuffer< WorldData > world_buf
i
Definition text_draw.cc:230