[Impeller] Make gradients work as expected (flutter/engine#36140)

This commit is contained in:
ColdPaleLight 2022-09-16 02:17:17 +08:00 committed by GitHub
parent be6a4135d3
commit ab5cbe1c52
7 changed files with 59 additions and 6 deletions

View File

@ -19,6 +19,18 @@ vec4 IPSample(sampler2D texture_sampler, vec2 coords, float y_coord_scale) {
return texture(texture_sampler, coords);
}
/// Sample from a texture.
///
/// If `y_coord_scale` < 0.0, the Y coordinate is flipped. This is useful
/// for Impeller graphics backends that use a flipped framebuffer coordinate
/// space.
/// The range of `coods` will be mapped from [0, 1] to [half_texel, 1 - half_texel]
vec4 IPSampleLinear(sampler2D texture_sampler, vec2 coords, float y_coord_scale, vec2 half_texel) {
coords.x = mix(half_texel.x, 1 - half_texel.x, coords.x);
coords.y = mix(half_texel.y, 1 - half_texel.y, coords.y);
return IPSample(texture_sampler, coords, y_coord_scale);
}
// These values must correspond to the order of the items in the
// 'Entity::TileMode' enum class.
const float kTileModeClamp = 0;
@ -81,4 +93,36 @@ vec4 IPSampleWithTileMode(sampler2D tex,
return IPSampleWithTileMode(tex, coords, y_coord_scale, tile_mode, tile_mode);
}
/// Sample a texture, emulating a specific tile mode.
///
/// This is useful for Impeller graphics backend that don't have native support
/// for Decal.
/// The range of `coods` will be mapped from [0, 1] to [half_texel, 1 - half_texel]
vec4 IPSampleLinearWithTileMode(sampler2D tex,
vec2 coords,
float y_coord_scale,
vec2 half_texel,
float x_tile_mode,
float y_tile_mode) {
if (x_tile_mode == kTileModeDecal && (coords.x < 0 || coords.x >= 1) ||
y_tile_mode == kTileModeDecal && (coords.y < 0 || coords.y >= 1)) {
return vec4(0);
}
return IPSampleLinear(tex, IPVec2Tile(coords, x_tile_mode, y_tile_mode), y_coord_scale, half_texel);
}
/// Sample a texture, emulating a specific tile mode.
///
/// This is useful for Impeller graphics backend that don't have native support
/// for Decal.
/// The range of `coods` will be mapped from [0, 1] to [half_texel, 1 - half_texel]
vec4 IPSampleLinearWithTileMode(sampler2D tex,
vec2 coords,
float y_coord_scale,
vec2 half_texel,
float tile_mode) {
return IPSampleLinearWithTileMode(tex, coords, y_coord_scale, half_texel, tile_mode, tile_mode);
}
#endif

View File

@ -64,6 +64,8 @@ bool LinearGradientContents::Render(const ContentContext& renderer,
gradient_info.texture_sampler_y_coord_scale =
gradient_texture->GetYCoordScale();
gradient_info.alpha = GetAlpha();
gradient_info.half_texel = Vector2(0.5 / gradient_texture->GetSize().width,
0.5 / gradient_texture->GetSize().height);
VS::FrameInfo frame_info;
frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *

View File

@ -63,6 +63,8 @@ bool RadialGradientContents::Render(const ContentContext& renderer,
gradient_info.texture_sampler_y_coord_scale =
gradient_texture->GetYCoordScale();
gradient_info.alpha = GetAlpha();
gradient_info.half_texel = Vector2(0.5 / gradient_texture->GetSize().width,
0.5 / gradient_texture->GetSize().height);
VS::FrameInfo frame_info;
frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *

View File

@ -70,6 +70,8 @@ bool SweepGradientContents::Render(const ContentContext& renderer,
gradient_texture->GetYCoordScale();
gradient_info.tile_mode = static_cast<Scalar>(tile_mode_);
gradient_info.alpha = GetAlpha();
gradient_info.half_texel = Vector2(0.5 / gradient_texture->GetSize().width,
0.5 / gradient_texture->GetSize().height);
VS::FrameInfo frame_info;
frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *

View File

@ -12,6 +12,7 @@ uniform GradientInfo {
float tile_mode;
float texture_sampler_y_coord_scale;
float alpha;
vec2 half_texel;
} gradient_info;
in vec2 v_position;
@ -25,11 +26,11 @@ void main() {
gradient_info.end_point - gradient_info.start_point
);
float t = dot / (len * len);
frag_color = IPSampleWithTileMode(
frag_color = IPSampleLinearWithTileMode(
texture_sampler,
vec2(t, 0.5),
gradient_info.texture_sampler_y_coord_scale,
gradient_info.tile_mode,
gradient_info.half_texel,
gradient_info.tile_mode);
frag_color = vec4(frag_color.xyz * frag_color.a, frag_color.a) * gradient_info.alpha;
}

View File

@ -12,6 +12,7 @@ uniform GradientInfo {
float tile_mode;
float texture_sampler_y_coord_scale;
float alpha;
vec2 half_texel;
} gradient_info;
in vec2 v_position;
@ -21,11 +22,11 @@ out vec4 frag_color;
void main() {
float len = length(v_position - gradient_info.center);
float t = len / gradient_info.radius;
frag_color = IPSampleWithTileMode(
frag_color = IPSampleLinearWithTileMode(
texture_sampler,
vec2(t, 0.5),
gradient_info.texture_sampler_y_coord_scale,
gradient_info.tile_mode,
gradient_info.half_texel,
gradient_info.tile_mode);
frag_color = vec4(frag_color.xyz * frag_color.a, frag_color.a) * gradient_info.alpha;
}

View File

@ -14,6 +14,7 @@ uniform GradientInfo {
float tile_mode;
float texture_sampler_y_coord_scale;
float alpha;
vec2 half_texel;
} gradient_info;
in vec2 v_position;
@ -25,11 +26,11 @@ void main() {
float angle = atan(-coord.y, -coord.x);
float t = (angle * k1Over2Pi + 0.5 + gradient_info.bias) * gradient_info.scale;
frag_color = IPSampleWithTileMode(
frag_color = IPSampleLinearWithTileMode(
texture_sampler,
vec2(t, 0.5),
gradient_info.texture_sampler_y_coord_scale,
gradient_info.tile_mode,
gradient_info.half_texel,
gradient_info.tile_mode);
frag_color = vec4(frag_color.xyz * frag_color.a, frag_color.a) * gradient_info.alpha;
}