17 using BindFragmentCallback = std::function<bool(
RenderPass& pass)>;
18 using PipelineBuilderCallback =
20 using CreateGeometryCallback =
26 const int32_t kCurveResolution = 32;
28 uint8_t DoubleToUint8(
double x) {
29 return static_cast<uint8_t
>(std::clamp(std::round(
x * 255.0), 0.0, 255.0));
33 std::shared_ptr<Texture> CreateCurveTexture(
37 const std::shared_ptr<impeller::Context>& context) {
42 texture_descriptor.
size = {kCurveResolution, 1};
44 std::vector<uint8_t> curve_data =
47 return CreateTexture(texture_descriptor, curve_data, context,
"LineCurve");
50 std::pair<LineContents::EffectiveLineParameters, GeometryResult> CreateGeometry(
55 using PerVertexData = LineVertexShader::PerVertexData;
63 fml::StatusOr<LineContents::EffectiveLineParameters> calculate_status =
65 BufferView vertex_buffer = host_buffer.Emplace(
66 count *
sizeof(PerVertexData),
alignof(PerVertexData),
67 [line_geometry, &
transform, &calculate_status](uint8_t* buffer) {
68 auto vertices =
reinterpret_cast<PerVertexData*
>(buffer);
72 if (!calculate_status.ok()) {
73 return std::make_pair(
83 Scalar angle = std::atan2(diff.
y, diff.
x);
91 return std::make_pair(
92 calculate_status.value(),
94 .type = PrimitiveType::kTriangleStrip,
97 .vertex_buffer = vertex_buffer,
98 .vertex_count = count,
99 .index_type = IndexType::kNone,
114 float k = 2.0 / ((2.0 * radius + width) * sqrt(diff.Dot(diff)));
117 .e0 = Vector3(k * (p0.y - p1.y),
119 1.0 + k * (p0.x * p1.y - p1.x * p0.y)),
123 1.0 + k * (p0.x * p0.x + p0.y * p0.y - p0.x * p1.x - p0.y * p1.y)),
124 .e2 = Vector3(k * (p1.y - p0.y),
126 1.0 + k * (p1.x * p0.y - p0.x * p1.y)),
130 1.0 + k * (p1.x * p1.x + p1.y * p1.y - p0.x * p1.x - p0.y * p1.y)),
135 const Scalar LineContents::kSampleRadius = 1.f;
137 std::unique_ptr<LineContents> LineContents::Make(
138 std::unique_ptr<LineGeometry> geometry,
140 return std::unique_ptr<LineContents>(
144 LineContents::LineContents(std::unique_ptr<LineGeometry> geometry,
Color color)
145 : geometry_(
std::move(geometry)), color_(color) {}
152 VS::FrameInfo frame_info;
153 FS::FragInfo frag_info;
154 frag_info.color = color_;
158 auto geometry_result =
159 CreateGeometry(renderer, entity, pass, geometry_.get());
161 std::shared_ptr<Texture> curve_texture = CreateCurveTexture(
170 renderer.
GetContext()->GetSamplerLibrary()->GetSampler(sampler_desc));
172 PipelineBuilderCallback pipeline_callback =
177 return ColorSourceContents::DrawGeometry<VS>(
178 this, geometry_.get(), renderer, entity, pass, pipeline_callback,
181 [&frag_info, &host_buffer](
RenderPass& pass) {
182 FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
183 pass.SetCommandLabel(
"Line");
188 [geometry_result = std::move(geometry_result)](
191 const Geometry* geometry) { return geometry_result.second; });
201 std::vector<uint8_t> curve_data;
202 curve_data.reserve(kCurveResolution);
205 double slope = (scale * width + radius) / (radius * 2);
206 for (
int i = 0; i < kCurveResolution; ++i) {
208 (
static_cast<double>(i)) /
static_cast<double>(kCurveResolution - 1);
209 double scaled = slope * norm;
210 curve_data.push_back(DoubleToUint8(scaled));
216 void ExpandLine(std::array<Point, 4>& corners,
Point expansion) {
217 Point along = (corners[1] - corners[0]).Normalize();
218 Point across = (corners[2] - corners[0]).Normalize();
219 corners[0] += -1 * (across * expansion.
x) + -1 * (along * expansion.
y);
220 corners[1] += -1 * (across * expansion.
x) + (along * expansion.
y);
221 corners[2] += (across * expansion.
x) + -1 * (along * expansion.
y);
222 corners[3] += (across * expansion.
x) + (along * expansion.
y);
226 fml::StatusOr<LineContents::EffectiveLineParameters>
229 const Matrix& entity_transform) {
239 std::array<Point, 4> corners;
243 corners.data(), entity_transform,
246 return fml::Status(fml::StatusCode::kAborted,
"No valid corners");
248 Scalar effective_line_width = std::fabsf((corners[2] - corners[0]).y);
249 ExpandLine(corners,
Point(expand_size, expand_size));
250 Scalar padded_line_width = std::fabsf((corners[2] - corners[0]).y);
251 Scalar effective_sample_radius =
252 (padded_line_width - effective_line_width) / 2.f;
254 CalculateLineInfo(geometry->
GetP0(), p1_prime, effective_line_width,
255 effective_sample_radius);
256 for (
auto& corner : corners) {
267 .radius = effective_sample_radius};
HostBuffer & GetTransientsBuffer() const
Retrieve the currnent host buffer for transient storage.
PipelineRef GetLinePipeline(ContentContextOptions opts) const
std::shared_ptr< Context > GetContext() const
void SetTransform(const Matrix &transform)
Set the global transform matrix for this Entity.
Matrix GetShaderTransform(const RenderPass &pass) const
const Matrix & GetTransform() const
Get the global transform matrix for this Entity.
static std::vector< uint8_t > CreateCurveData(Scalar width, Scalar radius, Scalar scale)
std::optional< Rect > GetCoverage(const Entity &entity) const override
Get the area of the render pass that will be affected when this contents is rendered.
static const Scalar kSampleRadius
static fml::StatusOr< EffectiveLineParameters > CalculatePerVertex(LineVertexShader::PerVertexData *per_vertex, const LineGeometry *geometry, const Matrix &entity_transform)
bool Render(const ContentContext &renderer, const Entity &entity, RenderPass &pass) const override
static bool ComputeCorners(Point corners[4], const Matrix &transform, bool extend_endpoints, Point p0, Point p1, Scalar width)
Render passes encode render commands directed as one specific render target into an underlying comman...
VertexShader_ VertexShader
FragmentShader_ FragmentShader
raw_ptr< Pipeline< PipelineDescriptor > > PipelineRef
A raw ptr to a pipeline object.
LinePipeline::FragmentShader FS
static const GeometryResult kEmptyResult
LinePipeline::VertexShader VS
std::shared_ptr< Texture > CreateTexture(const TextureDescriptor &texture_descriptor, const std::vector< uint8_t > &data, const std::shared_ptr< impeller::Context > &context, std::string_view debug_label)
A 4x4 matrix using column-major storage.
static constexpr Matrix MakeTranslation(const Vector3 &t)
static Matrix MakeRotationZ(Radians r)
Scalar GetMaxBasisLengthXY() const
constexpr Type GetLength() const
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...