0
\$\begingroup\$

I would like to draw a perspective green rectangle that glows (=it constantly changes its alpha between 0 an 1).

I already achieved this, but not as a GUI element, but as a real 3D object.

In order to show this rectangle in front of everything else, I have to turn this into a GUI element. And I don't know how I would draw a perspective rectangle that constantly changes its alpha on the GUI.

enter image description here

I do not only mean the math behind it, but also how to do it exacetly: Do I use actual materials, or do I use an image in the size of the green box?

Thank you.

Edit:

This is what I'm trying to rebuild: enter image description here

\$\endgroup\$
15
  • \$\begingroup\$ Have you taken a look at Unity - Camera.WorldToScreenPoint? \$\endgroup\$ Aug 14, 2019 at 10:26
  • \$\begingroup\$ @TomTsagk Yes, I have. However, I'm not sure how to deal with this case ideally. \$\endgroup\$
    – tmighty
    Aug 14, 2019 at 10:36
  • \$\begingroup\$ Well, in screen space, it wouldn't be a rectangle. \$\endgroup\$ Nov 7, 2019 at 19:34
  • 1
    \$\begingroup\$ Could you maybe elaborate on what you're trying to achieve some more? I didn't really understand what's your goal and why you're trying to do it this way. \$\endgroup\$
    – iQew
    Nov 9, 2019 at 10:29
  • 1
    \$\begingroup\$ "In order to show this rectangle in front of everything else, I have to turn this into a GUI element" do you really? Why not just modify the depth layering instead? Is your question really "How can I draw this rectangle in front of other content?" — ie. if we solve that without touching GUI, does that still achieve what you need? \$\endgroup\$
    – DMGregory
    Nov 11, 2019 at 19:30

1 Answer 1

4
+50
\$\begingroup\$

I recommend always asking about your goal, rather than the method you think might help you achieve your goal. ie. "How can I draw a rectangle over 3D content that's in front of it in HDRP?" rather than "How do I draw a world rectangle as GUI?"

This avoids the X/Y problem, helping you get the outcome you want without distractions or unnecessary constraints. You'll often get solutions much easier than the way you thought of so far.

Here, I think using the GUI is a red herring. We can do this much more easily using shaders.

Create a new unlit shader (the old way - we don't need a shader graph to work with HDRP if we're not using lighting for this effect), and modify it like so:

// I called mine "Always in Front"
Shader "Unlit/AlwaysInFront"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        // Add a color tint parameter so you can get your desired green.
        _Color ("Color", color) = (1, 1, 1, 1)
    }
    SubShader
    {
        // Add the transparent queue to render after the opaque objects.
        // You can use "Queue"="Transparent+100" if you need to get in front
        // of other stuff in the transparent queue, like a worldspace Canvas.
        Tags { "RenderType"="Transparent" "Queue"="Transparent" }
        LOD 100

        // Turn off the depth test, so we don't hide occluded fragments.
        // And also disable Z writes so we don't muck up the depth buffer.
        ZTest Off
        ZWrite Off
        // Enable alpha blending for transparency. You could use premultiplied 
        // alpha here if you want to tint and glow with one pass.
        Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
            // I stripped out the fog sections since I don't expect to need them.
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            // Add color parameter.
            fixed4 _Color;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // Tint the texture using our color.
                fixed4 col = tex2D(_MainTex, i.uv) * _Color;

                return col;
            }
            ENDCG
        }
    }
}

Here's the result in the HDRP test scene. The green quad is actually behind the workbench, and parallaxes as you'd expect for an object at that position, but renders over the opaque 3D objects in front of it. I also added a worldspace canvas with a gun sprite on it, in front of the workbench, to show we can render over worldspace GUI too, even when our quad is behind it.

Translucent green quad drawing over everything in HDRP construction scene

Screenspace GUI can still layer on top of this for drawing your "E" / "6" markers on top. The "always on top" behaviour applies only to depth-tested objects in the 3D scene drawn before this material in the queues.

\$\endgroup\$
1
  • \$\begingroup\$ Thank you very much! Please give me so time to test it. \$\endgroup\$
    – tmighty
    Nov 12, 2019 at 15:33

You must log in to answer this question.

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