42 const Matrix& effect_transform,
44 const std::optional<Rect>& coverage_hint)
const {
56 auto input_snapshot = inputs[0]->GetSnapshot(
"Morphology", renderer, entity);
57 if (!input_snapshot.has_value()) {
65 auto maybe_input_uvs = input_snapshot->GetCoverageUVs(coverage);
66 if (!maybe_input_uvs.has_value()) {
69 auto input_uvs = maybe_input_uvs.value();
77 auto& host_buffer = renderer.GetTransientsBuffer();
81 {
Point(0, 0), input_uvs[0]},
82 {
Point(1, 0), input_uvs[1]},
83 {
Point(0, 1), input_uvs[2]},
84 {
Point(1, 1), input_uvs[3]},
87 VS::FrameInfo frame_info;
89 frame_info.texture_sampler_y_coord_scale =
90 input_snapshot->texture->GetYCoordScale();
93 auto transformed_radius =
95 auto transformed_texture_vertices =
98 auto transformed_texture_width =
99 transformed_texture_vertices[0].GetDistance(
100 transformed_texture_vertices[1]);
101 auto transformed_texture_height =
102 transformed_texture_vertices[0].GetDistance(
103 transformed_texture_vertices[2]);
105 FS::FragInfo frag_info;
106 frag_info.radius = std::round(transformed_radius.GetLength());
107 frag_info.morph_type =
static_cast<Scalar>(morph_type_);
108 frag_info.uv_offset =
109 input_snapshot->transform.Invert()
110 .TransformDirection(transformed_radius)
112 Point(transformed_texture_width, transformed_texture_height);
114 pass.SetCommandLabel(
"Morphology Filter");
118 pass.SetPipeline(renderer.GetMorphologyFilterPipeline(
options));
121 auto sampler_descriptor = input_snapshot->sampler_descriptor;
122 if (renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
127 FS::BindTextureSampler(
128 pass, input_snapshot->texture,
129 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
130 sampler_descriptor));
131 VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));
132 FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
134 return pass.Draw().ok();
136 std::shared_ptr<CommandBuffer> command_buffer =
137 renderer.GetContext()->CreateCommandBuffer();
138 if (command_buffer ==
nullptr) {
143 renderer.MakeSubpass(
"Directional Morphology Filter",
145 if (!render_target.
ok()) {
148 if (!renderer.GetContext()
150 ->Submit({std::move(command_buffer)})
162 .sampler_descriptor = sampler_desc,
163 .opacity = input_snapshot->opacity},
170 const Matrix& effect_transform)
const {
171 if (inputs.empty()) {
175 auto coverage = inputs[0]->GetCoverage(entity);
176 if (!coverage.has_value()) {
179 auto transform = inputs[0]->GetTransform(entity) * effect_transform.
Basis();
180 auto transformed_vector =
183 auto origin = coverage->GetOrigin();
184 auto size =
Vector2(coverage->GetSize());
185 switch (morph_type_) {
187 origin -= transformed_vector;
188 size += transformed_vector * 2;
191 origin += transformed_vector;
192 size -= transformed_vector * 2;
195 if (size.x < 0 || size.y < 0) {
std::function< bool(const ContentContext &, RenderPass &)> SubpassCallback
DirectionalMorphologyFilterContents()
std::optional< Entity > RenderFilter(const FilterInput::Vector &input_textures, const ContentContext &renderer, const Entity &entity, const Matrix &effect_transform, const Rect &coverage, const std::optional< Rect > &coverage_hint) const override
Converts zero or more filter inputs into a render instruction.
void SetRadius(Radius radius)
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...
void SetMorphType(MorphType morph_type)
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...
~DirectionalMorphologyFilterContents() override
void SetDirection(Vector2 direction)
constexpr TRect< T > Expand(T left, T top, T right, T bottom) const
Returns a rectangle with expanded edges. Negative expansion results in shrinking.