Add support for rounded images through shaders
caoimhebyrne opened this issue · 1 comments
caoimhebyrne commented
Is your feature request related to a problem? Please describe.
At the moment, images can only be rounded through stencil which can look very pixelated and ugly
Describe the solution you'd like
fsh:
#version 110
uniform float u_Radius;
uniform vec4 u_InnerRect;
uniform sampler2D u_Texture;
varying vec2 f_Position;
varying vec2 f_TexCoord;
void main() {
vec2 tl = u_InnerRect.xy - f_Position;
vec2 br = f_Position - u_InnerRect.zw;
vec2 dis = max(br, tl);
float v = length(max(vec2(0.0), dis)) - u_Radius;
float a = 1.0 - smoothstep(0.0, 1.0, v);
gl_FragColor = vec4(texture2D(u_Texture, f_TexCoord).rgb, a);
}
vsh:
#version 110
varying vec2 f_Position;
varying out vec2 f_TexCoord;
void main() {
f_Position = gl_Vertex.xy;
f_TexCoord = gl_MultiTexCoord0.xy;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_FrontColor = gl_Color;
}
effect:
class ShaderEffect(private val radius: Float) : Effect() {
private var shader: Shader = Shader("rounded_image", "rounded_image")
private var shaderRadiusUniform: FloatUniform = FloatUniform(shader.getUniformLocation("u_Radius"))
private var shaderInnerRectUniform = Vec4Uniform(shader.getUniformLocation("u_InnerRect"))
override fun beforeDraw() {
shader.bindIfUsable()
shaderRadiusUniform.setValue(radius)
shaderInnerRectUniform.setValue(
Vector4f(
boundComponent.getLeft() + radius,
boundComponent.getTop() + radius,
boundComponent.getRight() - radius,
boundComponent.getBottom() - radius
)
)
}
override fun afterDraw() {
shader.unbindIfUsable()
}
}
Describe alternatives you've considered
Stencil
mew commented
I think for the vast majority of cases StencilEffect
will be more than adequate.
which can look very pixelated and ugly.
I literally had to squint and toggle stencil on and off to see the difference. Yes, it's there, but it's so negligible and definitely doesn't warrant adding a whole new component / effect to remove a few pixels.