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\$
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\$
  • \$\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 '15 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 '15 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 '15 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 '15 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 '15 at 7:21

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.