Update highlight shader algorithm
This commit is contained in:
1 parent
80562325cf
commit
78d4393908
2 files changed
+70
-26
No files matched your search
@@ -66,6 +66,43 @@ sealed interface GlassHighlight {
|
||||
override val blendMode: BlendMode = BlendMode.Plus
|
||||
) : GlassHighlight
|
||||
|
||||
/**
|
||||
* Soft highlight effect with blur.
|
||||
*
|
||||
* @param width
|
||||
* The width of the highlight.
|
||||
*
|
||||
* @param color
|
||||
* The color of the highlight.
|
||||
*
|
||||
* @param blendMode
|
||||
* The blend mode of the highlight.
|
||||
*/
|
||||
@Immutable
|
||||
data class Soft(
|
||||
override val width: Dp = 1f.dp,
|
||||
override val color: Color = Color.White.copy(alpha = 0.4f),
|
||||
override val blendMode: BlendMode = BlendMode.Plus
|
||||
) : GlassHighlight {
|
||||
|
||||
override fun createRenderEffect(size: Size, density: Density, cornerRadius: Float): RenderEffect? {
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
val blurRadiusPx = with(density) { (width / 2f).toPx() }
|
||||
if (blurRadiusPx > 0f) {
|
||||
RenderEffect.createBlurEffect(
|
||||
blurRadiusPx,
|
||||
blurRadiusPx,
|
||||
Shader.TileMode.DECAL
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamic highlight effect with shimmering effect.
|
||||
*
|
||||
@@ -90,54 +127,63 @@ sealed interface GlassHighlight {
|
||||
override val color: Color = Color.White.copy(alpha = 0.4f),
|
||||
override val blendMode: BlendMode = BlendMode.Plus,
|
||||
val angle: Float = 45f,
|
||||
@param:FloatRange(from = 0.0) val falloff: Float = 1.5f
|
||||
@param:FloatRange(from = 0.0) val falloff: Float = 1f
|
||||
) : GlassHighlight {
|
||||
|
||||
private var highlightShaderCache: RuntimeShader? = null
|
||||
private var highlightShader: RuntimeShader? = null
|
||||
|
||||
override fun createRenderEffect(size: Size, density: Density, cornerRadius: Float): RenderEffect? {
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
val blurRadiusPx = with(density) { (width / 2f).toPx() }
|
||||
val blurRenderEffect =
|
||||
cachedBlurRenderEffect
|
||||
?: RenderEffect.createBlurEffect(
|
||||
with(density) { 0.5f.dp.toPx() },
|
||||
with(density) { 0.5f.dp.toPx() },
|
||||
if (blurRadiusPx > 0f) {
|
||||
RenderEffect.createBlurEffect(
|
||||
blurRadiusPx,
|
||||
blurRadiusPx,
|
||||
Shader.TileMode.DECAL
|
||||
).also { cachedBlurRenderEffect = it }
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
val highlightShader = highlightShaderCache
|
||||
val shader = highlightShader
|
||||
?: RuntimeShader(GlassShaders.highlightShaderString)
|
||||
.also { highlightShaderCache = it }
|
||||
.also { highlightShader = it }
|
||||
|
||||
val highlightRenderEffect =
|
||||
RenderEffect.createRuntimeShaderEffect(
|
||||
highlightShader.apply {
|
||||
shader.apply {
|
||||
setFloatUniform("size", size.width, size.height)
|
||||
setFloatUniform("cornerRadius", cornerRadius)
|
||||
|
||||
setFloatUniform("angle", angle * (PI / 180f).toFloat())
|
||||
setFloatUniform("falloff", falloff)
|
||||
},
|
||||
"image"
|
||||
)
|
||||
|
||||
RenderEffect.createChainEffect(
|
||||
highlightRenderEffect,
|
||||
blurRenderEffect
|
||||
)
|
||||
if (blurRenderEffect != null) {
|
||||
RenderEffect.createChainEffect(
|
||||
highlightRenderEffect,
|
||||
blurRenderEffect
|
||||
)
|
||||
} else {
|
||||
highlightRenderEffect
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
|
||||
var cachedBlurRenderEffect: RenderEffect? = null
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@Stable
|
||||
val Default: Dynamic = Dynamic()
|
||||
|
||||
@Stable
|
||||
val Solid: Solid = Solid()
|
||||
|
||||
@Stable
|
||||
val Soft: Soft = Soft()
|
||||
}
|
||||
}
|
||||
@@ -131,7 +131,7 @@ half4 main(float2 coord) {
|
||||
uniform shader image;
|
||||
|
||||
uniform float2 size;
|
||||
uniform float cornerRadius;
|
||||
|
||||
uniform float angle;
|
||||
uniform float falloff;
|
||||
|
||||
@@ -141,11 +141,9 @@ half4 main(float2 coord) {
|
||||
float2 halfSize = size * 0.5;
|
||||
float2 centeredCoord = coord - halfSize;
|
||||
|
||||
float2 grad = gradSdRoundedRectangle(centeredCoord, halfSize, cornerRadius);
|
||||
float2 topLightNormal = float2(-cos(angle), -sin(angle));
|
||||
float topLightFraction = dot(topLightNormal, grad);
|
||||
float bottomLightFraction = -topLightFraction;
|
||||
float fraction = pow(max(topLightFraction, bottomLightFraction), falloff);
|
||||
float2 grad = gradSdRoundedRectangle(centeredCoord, halfSize, min(halfSize.x, halfSize.y));
|
||||
float2 normal = float2(-cos(angle), -sin(angle));
|
||||
float fraction = pow(abs(dot(normal, grad)), falloff);
|
||||
|
||||
return image.eval(coord) * fraction;
|
||||
}"""
|
||||
|
||||
Reference in new issue
Block a user