Chuyển đến nội dung chính

Bài đăng

Hiển thị các bài đăng có nhãn Graphics

Fragment shaders in Flutter: the GPU escape hatch, and its costs

There is a category of visual effect that widgets simply cannot produce: per-pixel distortion, procedural gradients that animate without rebuilding, dissolves, ripples, chromatic aberration. You can approximate some of them with enough Transform and Opacity layers, and the result will be slow and wrong. Flutter’s answer is a GLSL fragment shader compiled at build time and executed on the GPU. It is a genuinely powerful escape hatch. It is also a different programming model with its own costs, and the honest version of this article covers both. The minimum viable shader A fragment shader is a program that runs once per pixel and returns a colour. Flutter’s dialect is GLSL ES with a small set of Flutter-specific helpers from flutter/runtime_effect.glsl . shaders/ripple.frag : #version 460 core #include <flutter/runtime_effect.glsl> precision highp float ; uniform vec2 uSize; uniform float uTime; uniform vec4 uColor; out vec4 fragColor; void main () { ...

Fragment shaders: bind uniforms by name in Flutter — hướng dẫn Flutter

Recent shader APIs remove counting float slots by hand and one-frame texture lag. Bài này chuyển quan sát đó thành một mô hình nhỏ để bạn có thể kiểm thử, đo lường và giữ cho code dễ bảo trì khi app lớn lên. Vấn đề cốt lõi getUniformFloat, toImageSync, and high-bit textures for LUTs. Câu hỏi hữu ích không phải API hay pattern có đẹp riêng lẻ hay không, mà là state nằm ở đâu, boundary nào chịu trách nhiệm khi lỗi xảy ra, và người dùng phục hồi thế nào khi happy path biến mất. Mô hình thực tế High-bit formats unlock serious LUTs and SDFs for photo filters. Hãy bắt đầu bằng một owner rõ ràng cho behavior. Widget chỉ nên render và phát intent; IO, persistence, permission và retry nên nằm sau một interface nhỏ. Nhờ vậy bạn có seam để fake trong test và một chỗ ghi lại các dữ kiện cần theo dõi ở production. Trong app Flutter, boundary thường có dạng: Widget phát intent như load, submit, refresh hoặc retry. Controller hoặc use case validate intent rồi gọi boundary. Boundary trả về ...

Fragment shaders: bind uniforms by name in Flutter

Recent shader APIs remove counting float slots by hand and one-frame texture lag. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence getUniformFloat, toImageSync, and high-bit textures for LUTs. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model High-bit formats unlock serious LUTs and SDFs for photo filters. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or retry. A controlle...

Fragment shader trong Flutter: uniform theo tên và texture đồng bộ

Custom shader hết “ngách” khi Impeller nắm stack. API gần đây gỡ các nốt đau tồi tệ nhất. Bind uniform theo tên void setUp (ui. FragmentShader shader) { shader. getUniformFloat ( 'intensity' ). set ( 0.85 ); } Không còn đếm slot float thủ công — bớt bug off-by-one trên GPU. Texture đồng bộ trong cùng frame final image = picture. toImageSync ( 128 , 128 , targetFormat : ui. TargetPixelFormat .rFloat32, ); shader. setImageSampler ( 0 , image); decodeImageFromPixelsSync / toImageSync bỏ một frame lag khi tạo texture sampler. Format high-bit (tới 128-bit float) mở khóa LUT và SDF nghiêm túc. Workflow Viết .frag trong shaders/ . Load theo docs (ShaderLib / asset API). Preview cách ly; rồi mới integrate sau feature flag. Cạm bẫy Khác biệt tọa độ Skia vs Impeller vẫn cắn shader port. LUT lớn cần ngân sách memory — phải đo. Bài viết gốc đăng tại FlutterCook . Bản trên đó là bản được cập nhật mới nhất.

Fragment shaders in Flutter: uniforms by name and sync textures

Custom shaders stop being a niche once Impeller owns the stack. The recent API work removes the worst papercuts. Bind uniforms by name void setUp (ui. FragmentShader shader) { shader. getUniformFloat ( 'intensity' ). set ( 0.85 ); } No more counting float slots by hand — fewer off-by-one GPU bugs. Sync textures in the same frame final image = picture. toImageSync ( 128 , 128 , targetFormat : ui. TargetPixelFormat .rFloat32, ); shader. setImageSampler ( 0 , image); decodeImageFromPixelsSync / toImageSync remove a frame of lag when creating sampler textures. High-bit formats (up to 128-bit float) unlock serious LUTs and SDFs. Workflow Author .frag under shaders/ . Load via ShaderLib / asset API in docs. Preview in isolation; then integrate behind a feature flag. Pitfalls Skia vs Impeller coordinate differences still bite ported shaders. Big LUTs need memory budgets — measure, do not assume. Originally published on FlutterCook . Read the...

Fragment shader trong Flutter: uniform theo tên và texture đồng bộ

Custom shader hết “ngách” khi Impeller nắm stack. API gần đây gỡ các nốt đau tồi tệ nhất. Bind uniform theo tên void setUp (ui. FragmentShader shader) { shader. getUniformFloat ( 'intensity' ). set ( 0.85 ); } Không còn đếm slot float thủ công — bớt bug off-by-one trên GPU. Texture đồng bộ trong cùng frame final image = picture. toImageSync ( 128 , 128 , targetFormat : ui. TargetPixelFormat .rFloat32, ); shader. setImageSampler ( 0 , image); decodeImageFromPixelsSync / toImageSync bỏ một frame lag khi tạo texture sampler. Format high-bit (tới 128-bit float) mở khóa LUT và SDF nghiêm túc. Workflow Viết .frag trong shaders/ . Load theo docs (ShaderLib / asset API). Preview cách ly; rồi mới integrate sau feature flag. Cạm bẫy Khác biệt tọa độ Skia vs Impeller vẫn cắn shader port. LUT lớn cần ngân sách memory — phải đo. Bài viết gốc đăng tại FlutterCook . Bản trên đó là bản được cập nhật mới nhất.

Fragment shaders in Flutter: uniforms by name and sync textures

Custom shaders stop being a niche once Impeller owns the stack. The recent API work removes the worst papercuts. Bind uniforms by name void setUp (ui. FragmentShader shader) { shader. getUniformFloat ( 'intensity' ). set ( 0.85 ); } No more counting float slots by hand — fewer off-by-one GPU bugs. Sync textures in the same frame final image = picture. toImageSync ( 128 , 128 , targetFormat : ui. TargetPixelFormat .rFloat32, ); shader. setImageSampler ( 0 , image); decodeImageFromPixelsSync / toImageSync remove a frame of lag when creating sampler textures. High-bit formats (up to 128-bit float) unlock serious LUTs and SDFs. Workflow Author .frag under shaders/ . Load via ShaderLib / asset API in docs. Preview in isolation; then integrate behind a feature flag. Pitfalls Skia vs Impeller coordinate differences still bite ported shaders. Big LUTs need memory budgets — measure, do not assume. Originally published on FlutterCook . Read the...

Flutter GPU and 3D: what Impeller unlocked, and how far it actually goes

The most interesting consequence of Impeller is not smoother scrolling. It is that Flutter now has a rendering backend modern enough to expose a low-level graphics API — flutter_gpu — and that a real 3D engine has been built on top of it. Now that Impeller is the default renderer on every platform except web, that API’s reach is wider than it has ever been. This article is about what actually exists today, and where the line between “impressive demo” and “ship it” currently sits. What Flutter GPU is flutter_gpu is a thin, low-level API over Impeller’s rendering primitives — command buffers, render passes, textures, and shader pipelines. It is not a scene graph and it is not widgets. It is the layer you use when you want to draw things Flutter’s painting API cannot express: custom renderers, particle systems, post-processing, 3D. Shaders are authored separately and compiled into shader bundles at build time, using flutter_gpu_shaders and build_runner . That is consistent with I...