35 morph_type_ = morph_type;
38 std::optional<Entity> DirectionalMorphologyFilterContents::RenderFilter(
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()) {
66 auto maybe_input_uvs = input_snapshot->GetCoverageUVs(coverage);
67 if (!maybe_input_uvs.has_value()) {
70 auto input_uvs = maybe_input_uvs.value();
78 auto& host_buffer = renderer.GetTransientsBuffer();
80 VertexBufferBuilder<VS::PerVertexData> vtx_builder;
81 vtx_builder.AddVertices({
82 {
Point(0, 0), input_uvs[0]},
83 {
Point(1, 0), input_uvs[1]},
84 {
Point(0, 1), input_uvs[2]},
85 {
Point(1, 1), input_uvs[3]},
88 VS::FrameInfo frame_info;
90 frame_info.texture_sampler_y_coord_scale =
91 input_snapshot->texture->GetYCoordScale();
94 auto transformed_radius =
96 auto transformed_texture_vertices =
99 auto transformed_texture_width =
100 transformed_texture_vertices[0].GetDistance(
101 transformed_texture_vertices[1]);
102 auto transformed_texture_height =
103 transformed_texture_vertices[0].GetDistance(
104 transformed_texture_vertices[2]);
106 FS::FragInfo frag_info;
107 frag_info.radius = std::round(transformed_radius.GetLength());
108 frag_info.morph_type =
static_cast<Scalar>(morph_type_);
109 frag_info.uv_offset =
110 input_snapshot->transform.Invert()
111 .TransformDirection(transformed_radius)
113 Point(transformed_texture_width, transformed_texture_height);
115 pass.SetCommandLabel(
"Morphology Filter");
119 pass.SetPipeline(renderer.GetMorphologyFilterPipeline(options));
120 pass.SetVertexBuffer(vtx_builder.CreateVertexBuffer(host_buffer));
122 auto sampler_descriptor = input_snapshot->sampler_descriptor;
123 if (renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
128 FS::BindTextureSampler(
129 pass, input_snapshot->texture,
130 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
131 sampler_descriptor));
132 VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));
133 FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
135 return pass.Draw().ok();
138 fml::StatusOr<RenderTarget> render_target = renderer.MakeSubpass(
139 "Directional Morphology Filter",
ISize(coverage.
GetSize()), callback);
140 if (!render_target.ok()) {
144 SamplerDescriptor sampler_desc;
149 Snapshot{.texture = render_target.value().GetRenderTargetTexture(),
151 .sampler_descriptor = sampler_desc,
152 .opacity = input_snapshot->opacity},
159 const Matrix& effect_transform)
const {
160 if (inputs.empty()) {
164 auto coverage = inputs[0]->GetCoverage(entity);
165 if (!coverage.has_value()) {
168 auto transform = inputs[0]->GetTransform(entity) * effect_transform.
Basis();
169 auto transformed_vector =
174 switch (morph_type_) {
176 origin -= transformed_vector;
177 size += transformed_vector * 2;
180 origin += transformed_vector;
181 size -= transformed_vector * 2;
184 if (size.x < 0 || size.y < 0) {
192 const Matrix& effect_transform,
193 const Rect& output_limit)
const {
194 auto transformed_vector =
196 switch (morph_type_) {
198 return output_limit.
Expand(-transformed_vector);
200 return output_limit.
Expand(transformed_vector);