1
\$\begingroup\$

In my OpenGL apps, one of my tricks that I've used often for displaying heads up displays and ui elements, is to have a sorted mesh of triangles and then only render a portion of them.

In one game I have a circular fuel gauge. I made a mesh of triangles using a triangle fan that spans around the circle. In code I can limit the number of triangles that it's drawing to make the fuel gauge appear at that % of fuel.

So in this example I take the % of fuel left, multiply by the number of segments in the fan, and then draw it:

    glDrawElements(GL_TRIANGLE_FAN, (int)remainingFuel+1, GL_UNSIGNED_INT, (void *) (0 * sizeof(GLuint)));

If 50% of the fuel is left it draws 50% of the triangles in the fan which appears to be half the circle shape.

Can this easily be replicated in Unity3D? Where I can limit the range of triangles of a mesh that will render to a specific start and stop range?

Does Unity3D even do triangle fans?

Or do I need to figure out a new way to do this?

By the way I do know how to create procedural meshes in unity code (C#) but am still fairly new to Unity. I know I could store the entire mesh in one class and then copy only a portion of it to a game object based on the fuel level. I'd rather not create a new version of the mesh for each frame because the fuel is constantly changing. It seems more efficient to just limit the count on a non-changing mesh.

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

Instead of manipulating meshes in Unity, I'd use a Shader instead. It gives you more control over the appearance of your gauge and will perform better.

For starters, you could use the built-in alpha cutoff shader and use a circular gradient as your cutoff ramp. Something like this should do the trick:

Circular gradient

Then you can manipulate the cutoff value like this:

renderer.material.SetFloat("_Cutoff", myCutOffValue);

where myCutOffValue is a float ranging from 0 to 1.

Update:

As requested in the comments, here's a shader-example that uses two textures. One for RGBA and the other for the cutoff. You can create a new shader in Unity and replace the automatically generated code with the following:

Shader "Custom/SeparateCutout" {
    Properties {
        _Color ("Main Color", Color) = (1,1,1,1)
        _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
        _CutTex ("Cutout Texture", 2D) = "white" {}
        _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
    }

    SubShader {
        Tags {
            "Queue"="Transparent" 
            "IgnoreProjector"="True" 
            "RenderType"="Transparent"
        }
        LOD 200

    CGPROGRAM
    #pragma surface surf Lambert alpha

        sampler2D _MainTex;
        sampler2D _CutTex;
        fixed4 _Color;
        float _Cutoff;

        struct Input {
            float2 uv_MainTex;
            float2 uv_CutTex;
        };

        void surf (Input IN, inout SurfaceOutput o) {
            fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
            fixed4 cut = tex2D(_CutTex, IN.uv_CutTex);
            clip(cut.a - _Cutoff);
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
    ENDCG
    }

    Fallback "Transparent/VertexLit"
}

You'll find this shader under Custom > SeparateCutout in the shaders dropdown. For the cutout texture, I recommend you set it to Alpha 8 (available under Format, when you switch the Texture type to "Advanced". Use "Alpha from Grayscale" setting if necessary). That way you'll save some GPU memory.

\$\endgroup\$
6
  • \$\begingroup\$ Looks like that shader only has 1 source texture. My texture already has transparency. So I'll need to write my own shader to use two textures. Hmmm... Or do the cutoff in code via a uniform variable. Hmmm... \$\endgroup\$
    – badweasel
    Jan 17, 2015 at 8:37
  • \$\begingroup\$ @badweasel You can download all built-in shaders from the download archive page. Then modify the shader according to your needs... I'll have a look and update the answer with an example for a separate cutout texture. \$\endgroup\$
    – bummzack
    Jan 17, 2015 at 20:41
  • \$\begingroup\$ Since my first need of this is not a circle but just a box I was considering using per vertex colors to make a cutoff varying. But then I have to add vertex colors to the verts of a sprite. If I use a texture can it be another sprite on the same sprite sheet? Or would it have to have the same uv. Obviously performance is important as well. \$\endgroup\$
    – badweasel
    Jan 17, 2015 at 22:30
  • \$\begingroup\$ Thanks for the update with code. Wish I could give you a second check mark. Is there a way to use different uv for the cut off texture? \$\endgroup\$
    – badweasel
    Jan 17, 2015 at 22:41
  • \$\begingroup\$ SWEET! Got it working. Thanks! My modification was to add an offset uv property, offset the main uv by this amount, and then did fixed4 cut = tex2D(_MainTex, uv_OffsetCoord); Since my thing is on a sprite sheet and my cutoff gradient was next to the thing. \$\endgroup\$
    – badweasel
    Jan 18, 2015 at 7:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .