Ren'Py Glassmorphic/Glassmorphism UI?

Jul 8, 2025
33
46
From what I've read in the Ren'Py docs so far, it sounds like something like this would be difficult to implement given how Ren'py works.

Is there some somewhat feasible way to implement it? Or is the only real way to make a static version of it in PS?

Thanks.

- naoko
 

osanaiko

Engaged Member
Modder
Jul 4, 2017
3,232
6,163
The "Glassomorphic" name is a perfidious attempt to rewrite history by the evil Apple Corporation. The true name of the effect you seek is "Aero Glass", as bestowed by his holiness Bill as he strode heroically at the head of the wholesome Windows Vista Crusade Army.

Anyway, here's how you can have a semi transparent background for your UI elements:

1. you need UI element background images that are PNGs with transparency information. For a test I made an image with varying transparencies
transparent_bg_test.png

2. Then you use the image as a background for the Screen elements that make up your UI. The details vary depending on what element you are using - in some cases you would "add" the image, but for a frame element you need the "background" instruction, as shown here:

Code:
screen transparent_screen():
    frame:
        xalign 0.5
        yalign 0.5
        xsize 1600
        ysize 800
        background "transparent_bg_test"
        vbox:
            xalign 0.5
            yalign 0.5
            text "This is a screen with a png background" xalign 0.5
            text "that has varying alpha values" xalign 0.5
3. Then in your code you call (or show) the Screen, and it displays with the background partially visible behind it:

1756178261455.png

4. To get an even more AeroGlass style "blurring transparency" effect rather than just a color overlay transparency... not sure how that would be accomplished. Some sort of Shader texture perhaps, which is possible in Renpy 7.x onwards.

I don't know enough Shaders to give you any help, but maybe others on this site do. There's also the Renpy Lemmasoft forums which are full of good stuff.
 
Jul 8, 2025
33
46
The "Glassomorphic" name is a perfidious attempt to rewrite history by the evil Apple Corporation. The true name of the effect you seek is "Aero Glass", as bestowed by his holiness Bill as he strode heroically at the head of the wholesome Windows Vista Crusade Army.
Huh. TIL. :PogChamp:

I've just always seen it referred to as Glassmorphic in web design, figured that was the proper term for it.

4. To get an even more AeroGlass style "blurring transparency" effect rather than just a color overlay transparency... not sure how that would be accomplished. Some sort of Shader texture perhaps, which is possible in Renpy 7.x onwards.

I don't know enough Shaders to give you any help, but maybe others on this site do. There's also the Renpy Lemmasoft forums which are full of good stuff.
I was aware of the forum, but having to through their discord to sign up is kind of a hassle that I was too lazy to do, figured I would try my luck here before going through all that.

Thanks for the help anyways! :)
 

osanaiko

Engaged Member
Modder
Jul 4, 2017
3,232
6,163
Huh. TIL. :PogChamp:
I've just always seen it referred to as Glassmorphic in web design, figured that was the proper term for it.
I may in fact be speaking entirely from my ass, driven by righteous hatred of Apple and the way they claim well known industry tech as "amazing new proprietary tech" in their annual dog-and-pony macos/iphone show.


I was aware of the forum, but having to through their discord to sign up is kind of a hassle that I was too lazy to do, figured I would try my luck here before going through all that.

Thanks for the help anyways! :)
I didn't think you need to be on discord to access the actual forums:

Although it's possible that these days there is proportionally excessive Renpy how-to chat trapped inside the closed-garden of Discord than is visible on the public web, more's the pity.

I did a quick search and there are many threads with people talking about using various GLSL shaders in renpy.
 

no_more_name

Member
Mar 3, 2024
111
56
I did a quick search and there are many threads with people talking about using various GLSL shaders in renpy.
I've just always seen it referred to as Glassmorphic in web design, figured that was the proper term for it.
I know nothing about Glassmorphic, but my best bet would be to look for a frosted glass shader and adapt it for Renpy.

Granted my coding skills are super shit, so take it with a grain of salt, but I've yet to see a game using GLSL shaders regulary on images that does not tank the engine to its knees (I don't play much game so maybe I talk shit). Often it doesn't matter that much because it's applied on a short transition or a single static image, but for a whole UI... Yeah.

I'm a complete moron, just disable renpy powersave option (preferences.gl_powersave).

Following Renpy forum, that was my attempt (probably wrong) from ages ago at using a GLSL shader (a simple animated film grain) as a transform for a different thing, but it does not goes well (but I guess it works at least).

Python:
init python hide:

    renpy.register_shader("FilmGrainShader", variables="""
        uniform float u_time;
        uniform sampler2D tex0;
        attribute vec2 a_tex_coord;
        varying vec2 v_tex_coord;
        """,
        vertex_100="""
        v_tex_coord = a_tex_coord;
        """,
        fragment_300="""
        {
            vec2 uv = v_tex_coord;
            vec4 color = texture2D(tex0, uv);
            float strength = 25.0;
            float x = (uv.x + 4.0 ) * (uv.y + 4.0 ) * (u_time * 10.0);
            vec4 grain = vec4(mod((mod(x, 10.0) + 10) * (mod(x, 10.0) + 10), 0.01)-0.005) * strength;
            gl_FragColor = color + grain;
        }
        """)
Python:
define config.detached_layers += ["PPshader"]
default preferences.gl_powersave = False
image PP = Layer("PPshader")

transform FilmGrainPP:
    shader "FilmGrainShader"

label start:

    show PP at FilmGrainPP
    scene postprocess onlayer PPshader

    "You've created a new Ren'Py game."

    return
pythonw_ma19u4Ei2q.jpg
 
Last edited:

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
12,389
19,909
Be also noted that if you don't want to bother with a shader, nor to have to define the transparency for every single image, you can also rely on for this.

Python:
screen myUI():

    fixed:
        #  The background for the bar
        add AlphaMask( "MyBackground.jpg", "transparencyMask.png" )
        #  The UI data
        hbox:
            text "whatever [itsValue]"
            null width 10
            text "another [value]"
            [...]

    #  A button.
    textbutton "some action":
        style "glassmoph"
        action NullAction()

# Style for the button
style glassmorph is button:
    background AlphaMask( "btnBackground.jpg", "btnMask.png" )

label whatever:
    show screen myUI
And if you want to add a blur effect, also use the transform property:
Python:
image blurredTransparency:
    "btnMask.png"
    blur 0.5

style glassmorph is button:
    background AlphaMask( "btnBackground.jpg", "blurredTransparency" )
If you want the effect to also apply to the text a shader is the best approach. Yet you can also do without it, as long as it's bit more complex:
Python:
screen myUI():

    fixed:
        add AlphaMask( "MyBackground.jpg", "blurredTransparency" )
        hbox:
            add AlphaMask( Text( "whatever [itsValue]" ), "blurredTransparency" )
            null width 10
            add AlphaMask( Text( "another [value]" ), "blurredTransparency" )
            [...]

    button:
        style "glassmoph"
        add AlphaMask( Text( "some action" ), "blurredTransparency" )
        action NullAction()

image blurredTransparency:
    "btnMask.png"
    blur 0.5

style glassmorph is button:
    background AlphaMask( "btnBackground.jpg", "blurredTransparency" )

label whatever:
    show screen myUI
So, in short, it's totally possible to do this with Ren'Py, and you now know three different way to do it.
 

no_more_name

Member
Mar 3, 2024
111
56
I tried out of curiosity and took a random frosted glass shader from shader toy (can't find the original).

Shader:
Python:
init python:

    frostedGlassVars = """
    uniform float u_lod_bias;
    uniform sampler2D tex0;
    varying vec2 v_tex_coord;
    uniform float u_intensity;
    uniform float u_scale;
    uniform float u_noise_intensity;
    """

    frostedGlassFunctions = """
    float rand(vec2 uv) {
        float a = dot(uv, vec2(92., 80.));
        float b = dot(uv, vec2(41., 62.));
        float x = sin(a) + cos(b) * 51.;
        return fract(x);
    }
    float noise(vec2 uv) {
        return rand(uv);
    }
    """

    frostedGlassShader = """
    vec2 uv = v_tex_coord * u_scale;
    vec2 rnd = vec2(rand(uv), rand(uv));
    uv += rnd * u_intensity;
    vec4 originalColor = texture2D(tex0, uv / u_scale, u_lod_bias);
    float n = noise(uv * 0.1);
    vec4 noisyColor = mix(originalColor, vec4(vec3(n), originalColor.a), u_noise_intensity);
    gl_FragColor = noisyColor;
    """

    renpy.register_shader("FrostedGlass",
        variables=frostedGlassVars,
        vertex_functions="",
        fragment_functions=frostedGlassFunctions,
        vertex_200="",
        fragment_300=frostedGlassShader)
Transform:
Python:
transform FrostedGlassTransform:
    mesh True
    shader "FrostedGlass"
    u_intensity(0.05)
    u_scale(10.0)
    u_noise_intensity(0.01)
    alpha 0.75
pythonw_ypbljEAPJH.jpg

It's not *that* bad for a quick test, but that's where I realized it ain't gonna work for a UI. It works here because when sampled, there is enough pixels variations to create the effect, but most UI works on plain color. And plain color means no variations, so no effect. That's where it comes tricky because you will need to get the background that is displayed, then crop/clip it to your need, apply the shader and render it.

Tried working on a something like that but it's way more than I can chew. Not sure how to handle the crop ( ) part from there, nor if it possible/the right approach (or a complete disaster).

Python:
init pyhton:
    class FrostedGlass(renpy.Displayable):
        def __init__(self, child, intensity=0.05, scale=10.0, noise_intensity=0.01):
            super(FrostedGlass, self).__init__()
            self.child = renpy.displayable(child)
            self.intensity = intensity
            self.scale = scale
            self.noise_intensity = noise_intensity

        def render(self, width, height, st, at):
            rv = renpy.Render(config.screen_width, config.screen_height)
            child = renpy.display.render.render(self.child, width, height, st, at)
            child_width, child_height = child.get_size()
            rv.add_shader("FrostedGlass")
            rv.add_uniform("u_intensity", self.intensity)
            rv.add_uniform("u_scale", self.scale)
            rv.add_uniform("u_noise_intensity", self.noise_intensity)
            rv.blit(child, (0, 0))
            return rv
            #rv.mesh = True

        def get_size(self):
            return self.child.get_size()

        def event(self, ev, x, y, st):
            return self.child.event(ev, x, y, st)

    renpy.register_sl_displayable("FrostedGlass", FrostedGlass, "", 1).add_property("intensity").add_property("scale").add_property("noise_intensity")
 
Last edited:
  • Like
Reactions: anne O'nymous