How to create a circular and rectangular bar?

Hi everyone, I’d like to know if there is an easy way to create with JME a circular and rectangular bar typically used in video games to create interactions with objects that require a long press of a key to complete the action or for GUI elements such as energy or loading bars.

Here is a sample video:

2 Likes

For a rectangular bar you can use Lemur ProgressBar

3 Likes

For circular progress bar I think we do not have one made. But once somebody said you can do it like this

a circle progress bar imho should be a gradient circle texture and some discard shader. no new meshes, one single textured quad. good to go

1 Like

Unfortunately I’m not good with shaders :woozy_face:

You can also do this with pure geometry, though the math & logic to handle all the vertices will be much trickier than copying a simple built-in shader & adapting its logic to manage the ring shape.

1 Like

Is there an option to use a single texture color & change the UV Map coordinates accordingly so that when the progress at it’s half then the cylinder face is half textured ?

i think about circle one(well first one too), it can be done “really easy way” in shader.

you just need have “full circle texture” and in shader drop pixels based on percentage value provided.

if you dont have shader knowledge(but i suggest try make one) then you could always try make it using custom mesh solution(see wiki).

But still, most “elegant” solution would be to use shader IMO. Then you can even make really custom things, not just circle :wink: (for example heralth like in diablo game, or custom bar shapes)

2 Likes

I agree with @oxplay2 that the shader would be the cleanest way. I use to have geometry based progress bars, but got rid of them when I figured out how to do it in a simple shader. I made a circle progress bar in the shader by using an alpha map that matches my progress bar texture:

and then I can smoothly change the texture in the shader for the blue part of the alpha map based on the progress percentage, while leaving the non-blue areas alone. When the progress bar fills up, I also make the red area on the border flash yellow:

But if you wanted to do something that is C- shaped like your original post’s screenshot (or anything that isn’t a simple circle that grows from the center), then you’d also need a grayscale gradient texture. Something like this to represent the percentages for each pixel in the texture:

4 Likes

Thank you all for your help and your ideas. As I said before, I don’t know how to use shaders yet, but I could learn. I would like to see a shader example of the techniques you proposed in the JME supported format. I’m sure many curious like me would appreciate this opportunity to find out more. :heartpulse:
@oxplay2 @yaRnMcDonuts @danielp @Ali_RS

give me moment, i will prepare something for you

1 Like

here you go, video:

how i made progress Image:

code:

Progress.j3md:

MaterialDef GrrDefault {

    MaterialParameters {
        Texture2D ProgressMap
        Color Color (Color)
        Float Progress : 0.5
    }

    Technique {
        VertexShader GLSL100 GLSL150:   Shaders/Progress/Progress.vert
        FragmentShader GLSL100 GLSL150: Shaders/Progress/Progress.frag

        RenderState {
            FaceCull Off
        }

        WorldParameters {
            WorldViewProjectionMatrix
            ViewProjectionMatrix
            ViewMatrix
            Time
        }

        Defines {
            HAS_COLORMAP : ColorMap
            HAS_COLOR : Color
            COLOR : Color
            PROGRESS : Progress
        }
    }
}

Progress.vert:

#import "Common/ShaderLib/GLSLCompat.glsllib"
#import "Common/ShaderLib/Instancing.glsllib"

attribute vec3 inPosition;
attribute vec2 inTexCoord;
varying vec2 texCoord;

void main() {
    texCoord = vec2(inTexCoord.x, inTexCoord.y);
    vec4 modelSpacePos = vec4(inPosition, 1.0);
    gl_Position = TransformWorldViewProjection(modelSpacePos);
}

Progress.frag:

#import "Common/ShaderLib/GLSLCompat.glsllib"

uniform sampler2D m_ProgressMap;
varying vec2 texCoord;
uniform vec4 m_Color;

void main(){
    vec4 color = texture2D(m_ProgressMap, texCoord); 
    if(color.x < PROGRESS){
        discard;
    }
    color = clamp(color, 1, 1);
    color *= m_Color;
    gl_FragColor = color;
}

ANIMATED TIME (DEMO VERSION) Progress.frag:

#import "Common/ShaderLib/GLSLCompat.glsllib"

uniform sampler2D m_ProgressMap;
varying vec2 texCoord;
uniform vec4 m_Color;
uniform float g_Time;


void main(){
    vec4 color = texture2D(m_ProgressMap, texCoord); 
    if(color.x < cos(g_Time)){
        discard;
    }
    color = clamp(color, 1, 1);
    color *= m_Color;
    gl_FragColor = color;
}

Material usage:

mat = new Material(app.getAssetManager(),"Shaders/Progress/Progress.j3md");
Texture tex = app.getAssetManager().loadTexture("Textures/progress3.png");
tex.setWrap(Texture.WrapMode.Repeat);
mat.setTexture("ProgressMap", tex);
mat.setColor("Color", new ColorRGBA(1, 0, 0, 1));
mat.setFloat("Progress", 0.5f);

Also if you need transparency ON, remember about Transparent Bucket and additional render state alpha.

5 Likes

also it would require some cleanup, as it was “quick-made”

but its for you to start play with it, and try shaders yourself.

for example:
color = clamp(color, 1, 1);
this was not needed, it can be just color=vec4(1), since color was discarded anyway for other pixels.
Or you can use “darker” color, maybe it will have better effect. so just skip(remove) this line.

here is also some usefull info:

edit:

also remember, you have a good reference of ready2use JME shaders:

2 Likes

thank you very much for the example and documentation. I have to study the language of the shaders which is not very clear to me. :laughing:

2 Likes