Blender V4.5
gpencil_antialiasing.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2019 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "BLI_rand.h"
10#include "DNA_scene_types.h"
11#include "DRW_render.hh"
12
14
15#include "BLI_smaa_textures.h"
16
18
19void Instance::antialiasing_init()
20{
21 const float2 size_f = this->draw_ctx->viewport_size_get();
22 const int2 size(size_f[0], size_f[1]);
23 const float4 metrics = {1.0f / size[0], 1.0f / size[1], float(size[0]), float(size[1])};
24
25 if (this->simplify_antialias) {
26 /* No AA fallback. */
27 PassSimple &pass = this->smaa_resolve_ps;
28 pass.init();
30 pass.shader_set(ShaderCache::get().antialiasing[2].get());
31 pass.bind_texture("blend_tx", &this->color_tx);
32 pass.bind_texture("color_tx", &this->color_tx);
33 pass.bind_texture("reveal_tx", &this->reveal_tx);
34 pass.push_constant("do_anti_aliasing", false);
35 pass.push_constant("only_alpha", this->draw_wireframe);
36 pass.push_constant("viewport_metrics", metrics);
38 return;
39 }
40
41 if (!this->smaa_search_tx.is_valid()) {
45
48
51 }
52
53 {
55 this->smaa_edge_tx.acquire(size, GPU_RG8, usage);
56 this->smaa_weight_tx.acquire(size, GPU_RGBA8, usage);
57
60 }
61
62 SceneGpencil gpencil_settings = this->scene->grease_pencil_settings;
63 const float luma_weight = this->is_viewport ? gpencil_settings.smaa_threshold :
64 gpencil_settings.smaa_threshold_render;
65
66 {
67 /* Stage 1: Edge detection. */
68 PassSimple &pass = this->smaa_edge_ps;
69 pass.init();
71 pass.shader_set(ShaderCache::get().antialiasing[0].get());
72 pass.bind_texture("color_tx", &this->color_tx);
73 pass.bind_texture("reveal_tx", &this->reveal_tx);
74 pass.push_constant("viewport_metrics", metrics);
75 pass.push_constant("luma_weight", luma_weight);
76 pass.clear_color(float4(0.0f));
78 }
79 {
80 /* Stage 2: Blend Weight/Coord. */
81 PassSimple &pass = this->smaa_weight_ps;
82 pass.init();
84 pass.shader_set(ShaderCache::get().antialiasing[1].get());
85 pass.bind_texture("edges_tx", &this->smaa_edge_tx);
86 pass.bind_texture("area_tx", &this->smaa_area_tx);
87 pass.bind_texture("search_tx", &this->smaa_search_tx);
88 pass.push_constant("viewport_metrics", metrics);
89 pass.clear_color(float4(0.0f));
91 }
92 {
93 /* Stage 3: Resolve. */
94 PassSimple &pass = this->smaa_resolve_ps;
95 pass.init();
97 pass.shader_set(ShaderCache::get().antialiasing[2].get());
98 pass.bind_texture("blend_tx", &this->smaa_weight_tx);
99 pass.bind_texture("color_tx", &this->color_tx);
100 pass.bind_texture("reveal_tx", &this->reveal_tx);
101 pass.push_constant("do_anti_aliasing", true);
102 pass.push_constant("only_alpha", this->draw_wireframe);
103 pass.push_constant("viewport_metrics", metrics);
104 pass.draw_procedural(GPU_PRIM_TRIS, 1, 3);
105 }
106}
107
108void Instance::antialiasing_draw(Manager &manager)
109{
110 if (!this->simplify_antialias) {
112 manager.submit(this->smaa_edge_ps);
113
115 manager.submit(this->smaa_weight_ps);
116 }
117
119 manager.submit(this->smaa_resolve_ps);
120}
121
122static float erfinv_approx(const float x)
123{
124 /* From: Approximating the `erfinv` function by Mike Giles. */
125 /* To avoid trouble at the limit, clamp input to 1-epsilon. */
126 const float a = math::min(fabsf(x), 0.99999994f);
127 float w = -logf((1.0f - a) * (1.0f + a));
128 float p;
129 if (w < 5.0f) {
130 w = w - 2.5f;
131 p = 2.81022636e-08f;
132 p = p * w + 3.43273939e-07f;
133 p = p * w + -3.5233877e-06f;
134 p = p * w + -4.39150654e-06f;
135 p = p * w + 0.00021858087f;
136 p = p * w + -0.00125372503f;
137 p = p * w + -0.00417768164f;
138 p = p * w + 0.246640727f;
139 p = p * w + 1.50140941f;
140 }
141 else {
142 w = sqrtf(w) - 3.0f;
143 p = -0.000200214257f;
144 p = p * w + 0.000100950558f;
145 p = p * w + 0.00134934322f;
146 p = p * w + -0.00367342844f;
147 p = p * w + 0.00573950773f;
148 p = p * w + -0.0076224613f;
149 p = p * w + 0.00943887047f;
150 p = p * w + 1.00167406f;
151 p = p * w + 2.83297682f;
152 }
153 return p * x;
154}
155
156float2 Instance::antialiasing_sample_get(const int sample_index, const int sample_count)
157{
158 if (sample_count < 2) {
159 return float2(0.0f);
160 }
161
162 double halton[2];
163 {
164 uint primes[2] = {2, 3};
165 double ofs[2] = {0, 0};
166 BLI_halton_2d(primes, ofs, sample_index, halton);
167 }
168 /* Uniform distribution [0..1]. */
169 const float2 rand = float2(halton[0], halton[1]);
170 /* Uniform distribution [-1..1]. */
171 const float2 rand_remap = rand * 2.0f - 1.0f;
172 /* Limit sampling region to avoid outliers. */
173 const float2 rand_adjusted = rand_remap * 0.93f;
174 /* Gaussian distribution [-1..1]. */
175 const float2 offset = float2(erfinv_approx(rand_adjusted.x), erfinv_approx(rand_adjusted.y));
176 /* Gaussian fitted to Blackman-Harris (follows EEVEE). */
177 const float sigma = 0.284f;
178 /* NOTE(fclem): Not sure where this sqrt comes from but is needed to match EEVEE. */
179 return offset * sqrt(sigma);
180}
181
182void Instance::antialiasing_accumulate(Manager &manager, const float alpha)
183{
184 BLI_assert_msg(this->render_color_tx.gpu_texture() != nullptr,
185 "This should only be called during render");
186 const int2 size = this->render_color_tx.size().xy();
187
190 accumulation_tx.ensure_2d(GPENCIL_ACCUM_FORMAT, size, usage);
191
192 {
193 PassSimple &pass = this->accumulate_ps;
194 pass.init();
195 pass.state_set(DRW_STATE_WRITE_DEPTH /* There is no depth, but avoid blank state. */);
196 pass.shader_set(ShaderCache::get().accumulation.get());
197 pass.bind_image("src_img", &this->render_color_tx);
198 pass.bind_image("dst_img", &this->accumulation_tx);
199 pass.push_constant("weight_src", alpha);
200 pass.push_constant("weight_dst", 1.0f - alpha);
201 pass.draw_procedural(GPU_PRIM_TRIS, 1, 3);
202 }
203
204 accumulation_fb.ensure(size);
206 manager.submit(this->accumulate_ps);
207}
208
209} // namespace blender::draw::gpencil
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
Random number functions.
void BLI_halton_2d(const unsigned int prime[2], double offset[2], int n, double *r)
Definition rand.cc:237
#define SEARCHTEX_HEIGHT
const unsigned char searchTexBytes[]
#define SEARCHTEX_WIDTH
#define AREATEX_HEIGHT
const unsigned char areaTexBytes[]
#define AREATEX_WIDTH
#define GPU_ATTACHMENT_TEXTURE(_texture)
#define GPU_ATTACHMENT_NONE
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
@ GPU_PRIM_TRIS
@ GPU_DATA_UBYTE
eGPUTextureUsage
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_SHADER_WRITE
@ GPU_TEXTURE_USAGE_HOST_READ
@ GPU_TEXTURE_USAGE_ATTACHMENT
void GPU_texture_filter_mode(GPUTexture *texture, bool use_filter)
@ GPU_RG8
@ GPU_R8
@ GPU_RGBA8
void GPU_texture_update(GPUTexture *texture, eGPUDataFormat data_format, const void *data)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
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)
void acquire(int2 extent, eGPUTextureFormat format, eGPUTextureUsage usage=GPU_TEXTURE_USAGE_GENERAL)
bool ensure_2d(eGPUTextureFormat format, int2 extent, eGPUTextureUsage usage=GPU_TEXTURE_USAGE_GENERAL, const float *data=nullptr, int mip_len=1)
void bind_texture(const char *name, GPUTexture *texture, GPUSamplerState state=sampler_auto)
void bind_image(const char *name, GPUTexture *image)
void clear_color(float4 color)
void state_set(DRWState state, int clip_plane_count=0)
void push_constant(const char *name, const float &data)
void draw_procedural(GPUPrimType primitive, uint instance_len, uint vertex_len, uint vertex_first=-1, ResourceHandleRange handle={0}, uint custom_id=0)
Definition draw_pass.hh:953
void shader_set(GPUShader *shader)
#define logf(x)
#define fabsf(x)
#define sqrtf(x)
@ DRW_STATE_WRITE_DEPTH
Definition draw_state.hh:29
@ DRW_STATE_WRITE_COLOR
Definition draw_state.hh:30
@ DRW_STATE_BLEND_CUSTOM
Definition draw_state.hh:63
#define GPENCIL_ACCUM_FORMAT
#define sqrt
static float erfinv_approx(const float x)
detail::Pass< command::DrawCommandBuf > PassSimple
T min(const T &a, const T &b)
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
blender::float2 viewport_size_get() const
float smaa_threshold_render
struct SceneGpencil grease_pencil_settings
static float2 antialiasing_sample_get(int sample_index, int sample_count)
void antialiasing_accumulate(Manager &manager, float alpha)