9 #include "flutter/fml/make_copyable.h"
13 #include "impeller/entity/texture_downsample.frag.h"
14 #include "impeller/entity/texture_fill.frag.h"
15 #include "impeller/entity/texture_fill.vert.h"
27 constexpr
Scalar kMaxSigma = 500.0f;
65 return Vector2(std::clamp(vec2.
x, min, max),
66 std::clamp(vec2.
y, min, max));
93 BlurInfo CalculateBlurInfo(
const Entity& entity,
94 const Matrix& effect_transform,
101 ExtractScale(entity.GetTransform().Basis());
103 Vector2(entity.GetTransform().m[12], entity.GetTransform().m[13]);
128 std::optional<Snapshot> GetSnapshot(
const std::shared_ptr<FilterInput>& input,
129 const ContentContext& renderer,
130 const Entity& entity,
131 const std::optional<Rect>& coverage_hint) {
132 std::optional<Snapshot> input_snapshot =
133 input->GetSnapshot(
"GaussianBlur", renderer, entity,
135 if (!input_snapshot.has_value()) {
139 return input_snapshot;
144 Rect MakeReferenceUVs(
const Rect& reference,
const Rect& rect) {
147 return result.Scale(1.0f /
Vector2(reference.GetSize()));
150 Quad CalculateSnapshotUVs(
151 const Snapshot& input_snapshot,
152 const std::optional<Rect>& source_expanded_coverage_hint) {
153 std::optional<Rect> input_snapshot_coverage = input_snapshot.GetCoverage();
155 FML_DCHECK(input_snapshot.transform.IsTranslationScaleOnly());
156 if (source_expanded_coverage_hint.has_value() &&
157 input_snapshot_coverage.has_value()) {
159 std::optional<Rect>
uvs =
160 MakeReferenceUVs(input_snapshot_coverage.value(),
161 source_expanded_coverage_hint.value())
163 FML_DCHECK(
uvs.has_value());
164 if (
uvs.has_value()) {
165 blur_uvs[0] =
uvs->GetLeftTop();
166 blur_uvs[1] =
uvs->GetRightTop();
167 blur_uvs[2] =
uvs->GetLeftBottom();
168 blur_uvs[3] =
uvs->GetRightBottom();
175 if (divisor == 0.0f) {
179 Scalar remainder = fmod(val, divisor);
180 if (remainder != 0.0f) {
181 return val + (divisor - remainder);
188 if (divisor == 0.0f) {
192 Scalar remainder = fmod(val, divisor);
193 if (remainder != 0.0f) {
194 return val - remainder;
200 struct DownsamplePassArgs {
218 DownsamplePassArgs CalculateDownsamplePassArgs(
221 const Snapshot& input_snapshot,
222 const std::optional<Rect>& source_expanded_coverage_hint,
223 const std::shared_ptr<FilterInput>& input,
224 const Entity& snapshot_entity) {
232 Vector2 downsample_scalar(desired_scalar, desired_scalar);
242 std::optional<Rect> snapshot_coverage = input_snapshot.GetCoverage();
243 if (input_snapshot.transform.Equals(snapshot_entity.GetTransform()) &&
244 source_expanded_coverage_hint.has_value() &&
245 snapshot_coverage.has_value() &&
246 snapshot_coverage->Contains(source_expanded_coverage_hint.value())) {
255 int32_t divisor = std::round(1.0f / desired_scalar);
257 FloorToDivisible(source_expanded_coverage_hint->GetLeft(), divisor),
258 FloorToDivisible(source_expanded_coverage_hint->GetTop(), divisor),
259 source_expanded_coverage_hint->GetRight(),
260 source_expanded_coverage_hint->GetBottom());
262 aligned_coverage_hint.GetX(), aligned_coverage_hint.GetY(),
263 CeilToDivisible(aligned_coverage_hint.GetWidth(), divisor),
264 CeilToDivisible(aligned_coverage_hint.GetHeight(), divisor));
265 ISize source_size =
ISize(aligned_coverage_hint.GetSize().width,
266 aligned_coverage_hint.GetSize().height);
267 Vector2 downsampled_size = source_size * downsample_scalar;
269 FML_DCHECK(std::modf(downsampled_size.x, &int_part) == 0.0f);
270 FML_DCHECK(std::modf(downsampled_size.y, &int_part) == 0.0f);
276 Quad uvs = CalculateSnapshotUVs(input_snapshot, aligned_coverage_hint);
282 {aligned_coverage_hint.GetX(), aligned_coverage_hint.GetY(), 0})};
285 auto input_snapshot_size = input_snapshot.texture->GetSize();
288 Vector2 downsampled_size = source_rect_padded.GetSize() * downsample_scalar;
290 ISize(ceil(downsampled_size.x), ceil(downsampled_size.y));
291 Vector2 divisible_size(CeilToDivisible(source_rect_padded.GetSize().width,
292 1.0 / downsample_scalar.x),
293 CeilToDivisible(source_rect_padded.GetSize().height,
294 1.0 / downsample_scalar.y));
300 (divisible_size.x - source_rect_padded.GetSize().width) / 2.0
304 (divisible_size.y - source_rect_padded.GetSize().height) / 2.0
306 source_rect_padded = source_rect.Expand(divisible_padding);
311 input, snapshot_entity, source_rect_padded, input_snapshot_size);
316 .transform = input_snapshot.transform *
324 fml::StatusOr<RenderTarget> MakeDownsampleSubpass(
325 const ContentContext& renderer,
326 const std::shared_ptr<CommandBuffer>& command_buffer,
327 const std::shared_ptr<Texture>& input_texture,
328 const SamplerDescriptor& sampler_descriptor,
329 const DownsamplePassArgs& pass_args,
331 using VS = TextureFillVertexShader;
335 if (pass_args.effective_scalar.x >= 0.5f ||
336 (!input_texture->NeedsMipmapGeneration() &&
337 input_texture->GetTextureDescriptor().mip_count > 1)) {
339 [&](
const ContentContext& renderer, RenderPass& pass) {
340 HostBuffer& host_buffer = renderer.GetTransientsBuffer();
342 pass.SetCommandLabel(
"Gaussian blur downsample");
345 pass.SetPipeline(renderer.GetTexturePipeline(pipeline_options));
347 TextureFillVertexShader::FrameInfo frame_info;
349 frame_info.texture_sampler_y_coord_scale =
350 input_texture->GetYCoordScale();
352 TextureFillFragmentShader::FragInfo frag_info;
353 frag_info.alpha = 1.0;
355 const Quad&
uvs = pass_args.uvs;
356 std::array<VS::PerVertexData, 4> vertices = {
357 VS::PerVertexData{
Point(0, 0),
uvs[0]},
358 VS::PerVertexData{
Point(1, 0),
uvs[1]},
359 VS::PerVertexData{
Point(0, 1),
uvs[2]},
360 VS::PerVertexData{
Point(1, 1),
uvs[3]},
364 SamplerDescriptor linear_sampler_descriptor = sampler_descriptor;
365 SetTileMode(&linear_sampler_descriptor, renderer, tile_mode);
368 TextureFillVertexShader::BindFrameInfo(
369 pass, host_buffer.EmplaceUniform(frame_info));
370 TextureFillFragmentShader::BindFragInfo(
371 pass, host_buffer.EmplaceUniform(frag_info));
372 TextureFillFragmentShader::BindTextureSampler(
374 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
375 linear_sampler_descriptor));
377 return pass.Draw().ok();
379 return renderer.MakeSubpass(
"Gaussian Blur Filter", pass_args.subpass_size,
380 command_buffer, subpass_callback);
385 if (pass_args.effective_scalar.x <= 0.0625f) {
387 ratio = 1.0f / 64.0f;
388 }
else if (pass_args.effective_scalar.x <= 0.125f) {
390 ratio = 1.0f / 16.0f;
393 [&](
const ContentContext& renderer, RenderPass& pass) {
394 HostBuffer& host_buffer = renderer.GetTransientsBuffer();
396 pass.SetCommandLabel(
"Gaussian blur downsample");
399 #ifdef IMPELLER_ENABLE_OPENGLES
402 if (renderer.GetDeviceCapabilities()
403 .SupportsDecalSamplerAddressMode() ||
405 pass.SetPipeline(renderer.GetDownsamplePipeline(pipeline_options));
408 renderer.GetDownsampleTextureGlesPipeline(pipeline_options));
411 pass.SetPipeline(renderer.GetDownsamplePipeline(pipeline_options));
414 TextureFillVertexShader::FrameInfo frame_info;
416 frame_info.texture_sampler_y_coord_scale =
417 input_texture->GetYCoordScale();
419 TextureDownsampleFragmentShader::FragInfo frag_info;
420 frag_info.edge = edge;
421 frag_info.ratio = ratio;
422 frag_info.pixel_size =
Vector2(1.0f /
Size(input_texture->GetSize()));
424 const Quad&
uvs = pass_args.uvs;
425 std::array<VS::PerVertexData, 4> vertices = {
426 VS::PerVertexData{
Point(0, 0),
uvs[0]},
427 VS::PerVertexData{
Point(1, 0),
uvs[1]},
428 VS::PerVertexData{
Point(0, 1),
uvs[2]},
429 VS::PerVertexData{
Point(1, 1),
uvs[3]},
433 SamplerDescriptor linear_sampler_descriptor = sampler_descriptor;
434 SetTileMode(&linear_sampler_descriptor, renderer, tile_mode);
437 TextureFillVertexShader::BindFrameInfo(
438 pass, host_buffer.EmplaceUniform(frame_info));
439 TextureDownsampleFragmentShader::BindFragInfo(
440 pass, host_buffer.EmplaceUniform(frag_info));
441 TextureDownsampleFragmentShader::BindTextureSampler(
443 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
444 linear_sampler_descriptor));
446 return pass.Draw().ok();
448 return renderer.MakeSubpass(
"Gaussian Blur Filter", pass_args.subpass_size,
449 command_buffer, subpass_callback);
453 fml::StatusOr<RenderTarget> MakeBlurSubpass(
454 const ContentContext& renderer,
455 const std::shared_ptr<CommandBuffer>& command_buffer,
456 const RenderTarget& input_pass,
457 const SamplerDescriptor& sampler_descriptor,
459 const BlurParameters& blur_info,
460 std::optional<RenderTarget> destination_target,
461 const Quad& blur_uvs) {
468 const std::shared_ptr<Texture>& input_texture =
469 input_pass.GetRenderTargetTexture();
475 [&](
const ContentContext& renderer, RenderPass& pass) {
476 GaussianBlurVertexShader::FrameInfo frame_info;
478 frame_info.texture_sampler_y_coord_scale =
479 input_texture->GetYCoordScale();
481 HostBuffer& host_buffer = renderer.GetTransientsBuffer();
485 pass.SetPipeline(renderer.GetGaussianBlurPipeline(options));
487 std::array<VS::PerVertexData, 4> vertices = {
488 VS::PerVertexData{blur_uvs[0], blur_uvs[0]},
489 VS::PerVertexData{blur_uvs[1], blur_uvs[1]},
490 VS::PerVertexData{blur_uvs[2], blur_uvs[2]},
491 VS::PerVertexData{blur_uvs[3], blur_uvs[3]},
495 SamplerDescriptor linear_sampler_descriptor = sampler_descriptor;
498 GaussianBlurFragmentShader::BindTextureSampler(
500 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
501 linear_sampler_descriptor));
502 GaussianBlurVertexShader::BindFrameInfo(
503 pass, host_buffer.EmplaceUniform(frame_info));
504 GaussianBlurFragmentShader::BindKernelSamples(
505 pass, host_buffer.EmplaceUniform(
507 return pass.Draw().ok();
509 if (destination_target.has_value()) {
510 return renderer.MakeSubpass(
"Gaussian Blur Filter",
511 destination_target.value(), command_buffer,
514 return renderer.MakeSubpass(
"Gaussian Blur Filter",
subpass_size,
515 command_buffer, subpass_callback);
520 return static_cast<int>(std::round(radius * scalar));
524 const Entity& entity,
525 const std::shared_ptr<FilterInput>& input,
526 const Snapshot& input_snapshot,
528 const Geometry* geometry) {
529 Matrix entity_transform = entity.GetTransform();
530 Matrix blur_transform = blur_entity.GetTransform();
533 fml::MakeCopyable([blur_entity = blur_entity.Clone(), clip_operation,
534 entity_transform, blur_transform, geometry](
535 const ContentContext& renderer,
536 const Entity& entity, RenderPass& pass)
mutable {
538 clipper.SetClipDepth(entity.GetClipDepth());
539 clipper.SetTransform(entity.GetTransform() * entity_transform);
541 auto geom_result = geometry->GetPositionBuffer(renderer, clipper, pass);
543 ClipContents clip_contents(geometry->GetCoverage(clipper.GetTransform())
544 .value_or(Rect::MakeLTRB(0, 0, 0, 0)),
546 clip_contents.SetClipOperation(clip_operation);
547 clip_contents.SetGeometry(std::move(geom_result));
549 if (!clip_contents.Render(renderer, pass, entity.GetClipDepth())) {
552 blur_entity.SetClipDepth(entity.GetClipDepth());
553 blur_entity.SetTransform(entity.GetTransform() * blur_transform);
555 return blur_entity.Render(renderer, pass);
558 fml::MakeCopyable([blur_entity = std::move(blur_entity),
559 blur_transform](
const Entity& entity)
mutable {
560 blur_entity.SetTransform(entity.GetTransform() * blur_transform);
561 return blur_entity.GetCoverage();
569 const Entity& entity,
570 const std::shared_ptr<FilterInput>& input,
571 const Snapshot& input_snapshot,
573 const Geometry* geometry,
576 switch (blur_style) {
581 input, input_snapshot,
582 std::move(blur_entity), geometry);
586 input, input_snapshot,
587 std::move(blur_entity), geometry);
589 Entity snapshot_entity =
592 Matrix blurred_transform = blur_entity.GetTransform();
593 Matrix snapshot_transform =
594 entity.GetTransform() *
597 input_snapshot.transform;
599 fml::MakeCopyable([blur_entity = blur_entity.Clone(),
600 blurred_transform, snapshot_transform,
601 snapshot_entity = std::move(snapshot_entity)](
602 const ContentContext& renderer,
603 const Entity& entity,
604 RenderPass& pass)
mutable {
605 snapshot_entity.SetTransform(entity.GetTransform() *
607 snapshot_entity.SetClipDepth(entity.GetClipDepth());
608 if (!snapshot_entity.Render(renderer, pass)) {
611 blur_entity.SetClipDepth(entity.GetClipDepth());
612 blur_entity.SetTransform(entity.GetTransform() * blurred_transform);
613 return blur_entity.Render(renderer, pass);
615 fml::MakeCopyable([blur_entity = blur_entity.Clone(),
616 blurred_transform](
const Entity& entity)
mutable {
617 blur_entity.SetTransform(entity.GetTransform() * blurred_transform);
618 return blur_entity.GetCoverage();
626 GaussianBlurFilterContents::GaussianBlurFilterContents(
632 : sigma_(sigma_x, sigma_y),
633 tile_mode_(tile_mode),
634 mask_blur_style_(mask_blur_style),
635 mask_geometry_(mask_geometry) {
647 Scalar raw_result = 4.0 / sigma;
649 Scalar exponent = round(log2f(raw_result));
651 exponent = std::max(-4.0f, exponent);
652 Scalar rounded = powf(2.0f, exponent);
656 if (rounded < 0.125f) {
657 Scalar rounded_plus = powf(2.0f, exponent + 1);
659 int kernel_size_plus = (ScaleBlurRadius(
blur_radius, rounded_plus) * 2) + 1;
663 static constexpr int32_t kEighthDownsampleKernalWidthMax = 41;
664 result = kernel_size_plus <= kEighthDownsampleKernalWidthMax ? rounded_plus
671 const Matrix& effect_transform,
672 const Rect& output_limit)
const {
678 return output_limit.
Expand(
Point(blur_radii.
x, blur_radii.
y));
684 const Matrix& effect_transform)
const {
685 if (inputs.empty()) {
688 std::optional<Rect> input_coverage = inputs[0]->GetCoverage(entity);
689 if (!input_coverage.has_value()) {
693 BlurInfo blur_info = CalculateBlurInfo(entity, effect_transform, sigma_);
694 return input_coverage.value().Expand(
695 Point(blur_info.local_padding.x, blur_info.local_padding.y));
706 std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
710 const Matrix& effect_transform,
711 const Rect& coverage,
712 const std::optional<Rect>& coverage_hint)
const {
713 if (inputs.empty()) {
717 BlurInfo blur_info = CalculateBlurInfo(entity, effect_transform, sigma_);
722 std::optional<Rect> expanded_coverage_hint;
723 if (coverage_hint.has_value()) {
724 expanded_coverage_hint = coverage_hint->Expand(blur_info.local_padding);
727 Entity snapshot_entity = entity.
Clone();
732 std::optional<Rect> source_expanded_coverage_hint;
733 if (expanded_coverage_hint.has_value()) {
734 source_expanded_coverage_hint = expanded_coverage_hint->TransformBounds(
740 std::optional<Snapshot> input_snapshot = GetSnapshot(
741 inputs[0], renderer, snapshot_entity, source_expanded_coverage_hint);
742 if (!input_snapshot.has_value()) {
755 input_snapshot->transform);
765 std::shared_ptr<CommandBuffer> command_buffer_1 =
767 if (!command_buffer_1) {
771 DownsamplePassArgs downsample_pass_args = CalculateDownsamplePassArgs(
772 blur_info.scaled_sigma, blur_info.padding, input_snapshot.value(),
773 source_expanded_coverage_hint, inputs[0], snapshot_entity);
775 fml::StatusOr<RenderTarget> pass1_out = MakeDownsampleSubpass(
776 renderer, command_buffer_1, input_snapshot->texture,
777 input_snapshot->sampler_descriptor, downsample_pass_args, tile_mode_);
779 if (!pass1_out.ok()) {
784 1.0 /
Vector2(pass1_out.value().GetRenderTargetTexture()->GetSize());
788 std::shared_ptr<CommandBuffer> command_buffer_2 =
790 if (!command_buffer_2) {
794 fml::StatusOr<RenderTarget> pass2_out = MakeBlurSubpass(
795 renderer, command_buffer_2, pass1_out.value(),
796 input_snapshot->sampler_descriptor, tile_mode_,
798 .blur_uv_offset = Point(0.0, pass1_pixel_size.y),
799 .blur_sigma = blur_info.scaled_sigma.y *
800 downsample_pass_args.effective_scalar.y,
801 .blur_radius = ScaleBlurRadius(
802 blur_info.blur_radius.y, downsample_pass_args.effective_scalar.y),
805 std::nullopt, blur_uvs);
807 if (!pass2_out.ok()) {
811 std::shared_ptr<CommandBuffer> command_buffer_3 =
813 if (!command_buffer_3) {
818 auto pass3_destination = pass2_out.value().GetRenderTargetTexture() !=
819 pass1_out.value().GetRenderTargetTexture()
820 ? std::optional<RenderTarget>(pass1_out.value())
821 :
std::optional<RenderTarget>(
std::nullopt);
823 fml::StatusOr<RenderTarget> pass3_out = MakeBlurSubpass(
824 renderer, command_buffer_3, pass2_out.value(),
825 input_snapshot->sampler_descriptor, tile_mode_,
827 .blur_uv_offset = Point(pass1_pixel_size.x, 0.0),
828 .blur_sigma = blur_info.scaled_sigma.x *
829 downsample_pass_args.effective_scalar.x,
830 .blur_radius = ScaleBlurRadius(
831 blur_info.blur_radius.x, downsample_pass_args.effective_scalar.x),
834 pass3_destination, blur_uvs);
836 if (!pass3_out.ok()) {
840 if (!(renderer.
GetContext()->EnqueueCommandBuffer(
841 std::move(command_buffer_1)) &&
843 std::move(command_buffer_2)) &&
845 std::move(command_buffer_3)))) {
851 FML_DCHECK((pass1_out.value().GetRenderTargetSize() ==
852 pass2_out.value().GetRenderTargetSize()) &&
853 (pass2_out.value().GetRenderTargetSize() ==
854 pass3_out.value().GetRenderTargetSize()));
856 SamplerDescriptor sampler_desc = MakeSamplerDescriptor(
860 Snapshot{.texture = pass3_out.value().GetRenderTargetTexture(),
865 downsample_pass_args.transform *
867 .sampler_descriptor = sampler_desc,
868 .opacity = input_snapshot->opacity},
871 return ApplyBlurStyle(mask_blur_style_, entity, inputs[0],
872 input_snapshot.value(), std::move(blur_output_entity),
873 mask_geometry_, blur_info.source_space_scalar,
874 blur_info.source_space_offset);
882 const std::shared_ptr<FilterInput>& filter_input,
884 const Rect& source_rect,
885 const ISize& texture_size) {
886 Matrix input_transform = filter_input->GetLocalTransform(entity);
890 {1.0f / texture_size.
width, 1.0f / texture_size.
height, 1.0f});
891 return uv_transform.
Transform(coverage_quad);
899 Scalar clamped = std::min(sigma, kMaxSigma);
900 constexpr
Scalar a = 3.4e-06;
903 Scalar scalar = c +
b * clamped + a * clamped * clamped;
904 return clamped * scalar;
937 .coefficient = expf(-0.5f * (
x *
x) /
945 for (
auto& sample : result.samples) {
946 sample.coefficient /= tally;
956 GaussianBlurPipeline::FragmentShader::KernelSamples result = {};
957 result.sample_count = ((parameters.
sample_count - 1) / 2) + 1;
958 int32_t middle = result.sample_count / 2;
961 static_assert(
sizeof(result.sample_data) ==
962 sizeof(std::array<Vector4, kGaussianBlurMaxKernelSize>));
964 for (
int i = 0; i < result.sample_count; i++) {
979 result.sample_data[i].
x = uv.
x;
980 result.sample_data[i].y = uv.
y;
virtual bool SupportsDecalSamplerAddressMode() const =0
Whether the context backend supports SamplerAddressMode::Decal.
const Capabilities & GetDeviceCapabilities() const
std::function< bool(const ContentContext &, RenderPass &)> SubpassCallback
std::shared_ptr< Context > GetContext() const
static std::shared_ptr< Contents > MakeAnonymous(RenderProc render_proc, CoverageProc coverage_proc)
void SetTransform(const Matrix &transform)
Set the global transform matrix for this Entity.
static Entity FromSnapshot(const Snapshot &snapshot, BlendMode blend_mode=BlendMode::kSourceOver)
Create an entity that can be used to render a given snapshot.
BlendMode GetBlendMode() const
const Matrix & GetTransform() const
Get the global transform matrix for this Entity.
@ kNormal
Blurred inside and outside.
@ kOuter
Nothing inside, blurred outside.
@ kInner
Blurred inside, nothing outside.
@ kSolid
Solid inside, blurred outside.
static Scalar CalculateBlurRadius(Scalar sigma)
static Scalar ScaleSigma(Scalar sigma)
std::optional< Rect > GetFilterSourceCoverage(const Matrix &effect_transform, const Rect &output_limit) const override
Internal utility method for |GetSourceCoverage| that computes the inverse effect of this transform on...
std::optional< Rect > GetFilterCoverage(const FilterInput::Vector &inputs, const Entity &entity, const Matrix &effect_transform) const override
Internal utility method for |GetLocalCoverage| that computes the output coverage of this filter acros...
static Scalar CalculateScale(Scalar sigma)
static Quad CalculateUVs(const std::shared_ptr< FilterInput > &filter_input, const Entity &entity, const Rect &source_rect, const ISize &texture_size)
VertexShader_ VertexShader
FragmentShader_ FragmentShader
Vector2 local_padding
Padding in unrotated local space.
Vector2 blur_radius
Blur radius in source pixels based on scaled_sigma.
ISize subpass_size
The output size of the down-sampling pass.
Vector2 source_space_offset
Vector2 source_space_scalar
The scalar that is used to get from source space to unrotated local space.
Vector2 padding
The halo padding in source space.
Vector2 scaled_sigma
Sigma when considering an entity's scale and the effect transform.
static constexpr int32_t kGaussianBlurMaxKernelSize
@ kDecal
decal sampling mode is only supported on devices that pass the Capabilities.SupportsDecalSamplerAddre...
constexpr float kEhCloseEnough
GlyphAtlasPipeline::VertexShader VS
VertexBuffer CreateVertexBuffer(std::array< VertexType, size > input, HostBuffer &host_buffer)
Create an index-less vertex buffer from a fixed size array.
KernelSamples GenerateBlurInfo(BlurParameters parameters)
ContentContextOptions OptionsFromPass(const RenderPass &pass)
MinMagFilter
Describes how the texture should be sampled when the texture is being shrunk (minified) or expanded (...
std::array< Point, 4 > Quad
GaussianBlurPipeline::FragmentShader GaussianBlurFragmentShader
GaussianBlurPipeline::FragmentShader::KernelSamples LerpHackKernelSamples(KernelSamples parameters)
GaussianBlurPipeline::VertexShader GaussianBlurVertexShader
static constexpr int kMaxKernelSize
KernelSample samples[kMaxKernelSize]
A 4x4 matrix using column-major storage.
static constexpr Matrix MakeOrthographic(TSize< T > size)
static constexpr Matrix MakeTranslation(const Vector3 &t)
constexpr Matrix Basis() const
The Matrix without its w components (without translation).
constexpr Quad Transform(const Quad &quad) const
static constexpr Matrix MakeScale(const Vector3 &s)
For convolution filters, the "radius" is the size of the convolution kernel to use on the local space...
SamplerAddressMode width_address_mode
SamplerAddressMode height_address_mode
In filters that use Gaussian distributions, "sigma" is a size of one standard deviation in terms of t...
constexpr Type GetLength() const
constexpr TRect< T > Expand(T left, T top, T right, T bottom) const
Returns a rectangle with expanded edges. Negative expansion results in shrinking.
constexpr static TRect MakeOriginSize(const TPoint< Type > &origin, const TSize< Type > &size)
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
constexpr std::array< TPoint< T >, 4 > GetTransformedPoints(const Matrix &transform) const
constexpr static TRect MakeSize(const TSize< U > &size)
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)