1
\$\begingroup\$

I'm wondering how people here on GameDev stack exchange would handle curved meter GUI elements for things such as life bars or energy bars.

My thought on the matter was that you could use a shader with a cutoff value and an image which has one channel dedicated to masking the image (alpha) and one that also has a gradient which I compare to a uniform float to determine whether or not the fragment should be fully transparent.

However, I've been running into some strange behavior when writing this shader. Specifically, the shader's output has a weird artifact where the cutoff begins that looks almost like ripped paper -- the line that indicates the end of the meter has a sloppy contour.

Lifebar with distortion where the fragment is discarded due to cutoff value parameter.

This image has some distortion effect going on with the pixels where the lifebar is supposed to end via the cutoff uniform. There's definitely got to be a better way of doing this same thing in a more tactful way. Shader code is below:

   CGPROGRAM
   #pragma vertex vert
   #pragma fragment frag

        sampler2D _MainTex;
        float4 _Color;
        float _Cutoff;

        struct Vert_IN {
            float4 loc : POSITION;
            float4 texcoords : TEXCOORD0;
        };

        struct Frag_IN
        {
            float4 pos : SV_POSITION;
            float4 uv : TEXCOORD0;
        };

        Frag_IN vert( Vert_IN input )
        {
            Frag_IN output;
            output.uv = input.texcoords;
            output.pos = mul( UNITY_MATRIX_MVP, input.loc );
            return output;
        }

        float4 frag( Frag_IN input ) : COLOR
        {
            float4 value = _Color;
            float4 valueFromMask = tex2D( _MainTex, input.uv.xy );


            value.w = valueFromMask.w;
            float desiredTransparency = step( valueFromMask.x, _Cutoff );
            value.w = min( value.w, desiredTransparency );



            return value;
        }


        ENDCG

(Again, the red channel of this image is actually a gradient mask used to determine where the cutoff point should be. Other channels were going to be used for something else (like special scrolling patterns or what not) )

Example of the asset used in the shader: Asset used for the cutoff comparison.

I'm assuming there's probably something I'm missing when using the step function that could help ease the fade-dropoff in order to make a better looking end result?

What do you think is a good method for making curved meter GUI elements? Is there something wrong with the shader code presented above that causes this strange page tearing artifact?

\$\endgroup\$
4
\$\begingroup\$

Your graphic tool probably adds dithering (both Gimp and Photoshop does by default) which causes some pixels to be below or above the exact color value or you are using a compressed texture format which causes some pixels to have the wrong color value.

There might be an option in your graphic tool or texture importer to disable dithering or compression.

Here is an example of what happens in Gimp with dithering enabled in the gradient tool. The small section of the gradient has been scaled up and levels boosted using the Colors->Levels... tool to clearly show the gradient dithering.

enter image description here

Another option is using smoothstep to add a small gradient to the cutoff point. That would help hiding those errors.

\$\endgroup\$
  • \$\begingroup\$ @Krom, Yes he does. Look at his screenshot above **This image has some distortion effect going on with the pixels where the lifebar is supposed to end via the cutoff uniform. ** \$\endgroup\$ – Stephane Hockenhull Feb 12 '15 at 13:54
  • \$\begingroup\$ Hmm.. Yeah, it could be it under some circumstances. +1 \$\endgroup\$ – Kromster says support Monica Feb 12 '15 at 13:57
3
\$\begingroup\$

Tearing is caused by the nature of step function. It outputs 0 or 1, causing pixel either to be rendered or not. If you try it with smoothstep function you will get smeared edge instead.

enter image description here

You can fix tearing artifact by rendering a line on top of the gauge (shown in green). Render the line with the same texture attached, just without the step( code - only the blue portion will be visible then.

enter image description here

\$\endgroup\$
  • \$\begingroup\$ Adding that rendering points and lines is not very consistent and should be used only as a debug tool. For more consistent results use triangles to draw lines yourself or else you'll hit graphic glitches between drivers and even driver settings. \$\endgroup\$ – Stephane Hockenhull Feb 12 '15 at 14:02
  • 1
    \$\begingroup\$ True. Rendering lines with custom quads is more reliable. \$\endgroup\$ – Kromster says support Monica Feb 12 '15 at 14:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.