0
\$\begingroup\$

The code below generate angle and radius based brightness gradient. As you can see I need to use 3 if statement to define 3 circle, wonder is there a single code that can create nth circle corresponding to brightness gradient, imagine I want to create 20 circle, using 20 if statement is very unpractical.

Shader "Unlit/testDisplay"
{
   Properties
  {
       _MainTex ("Texture", 2D) = "white" {}
 }
SubShader
{
    // Render with transparent objects, after the opaque pass.
    Tags { "RenderType"="Transparent" "Queue"="Transparent"}
    LOD 100

    // Don't write to the depth buffer.
    ZWrite Off
    // Additive blending (add light/glow).
    Blend One One

    Pass
    {
        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;

        v2f vert (appdata v)
        {
            v2f o;
            o.vertex = UnityObjectToClipPos(v.vertex);
            // Shift our texture coordinates so 0 is in the center,
            // and we go to -2 ... +2 at the edges.
            o.uv = (v.uv -0.5f) *4.0f;
            return o;
        }

        fixed4 frag (v2f i) : SV_Target
        {
            //Define boundary value for radius
            float radius=length(i.uv);
            if(radius>0&radius<0.5)
            radius=0.5;
            if(radius<1&radius>=0.6)
            radius=1;

            if(radius<1.5&radius>=1.01)
            radius=1.5;

            if(radius<2&radius>=1.51)
            radius=2;

            

            //convert to polar coordinates
            float angle=atan2(i.uv.y,i.uv.x);
            float angle1=frac(angle/(2*3.142f));
            float result=-4*radius+angle1+13*frac(_Time.x);  
            return result;
            
        }
        ENDCG
    }
}

}

enter image description here

\$\endgroup\$
3
  • \$\begingroup\$ What happens when your radius is 0.55? \$\endgroup\$ – Zibelas Feb 2 at 8:48
  • \$\begingroup\$ Yeah there errors in the code. My guess is that specific boundary would have a continuous brightness gradient that is proportional to radius rather than a discrete value.I haven't try it out yet \$\endgroup\$ – chuackt Feb 2 at 10:23
  • \$\begingroup\$ This kind of code optimization is not specific to game development. \$\endgroup\$ – Vaillancourt Feb 2 at 15:26
1
\$\begingroup\$

You can shorten the conditions with the modulus operator. All if conditions can be reduced to

 radius = radius - (radius % 0.5) + 0.5;

The % returns the reminder of the calculation.

0.4 % 0.5 = 0.4
0.6 % 0.5 = 0.1
0.8 % 0.5 = 0.3
  1 % 0.5 = 0

We substract the result from our original radius to get into the correct interval. The last + 0.5 is for shifting the result.

Your original code though has some undefined areas for the radius if for example the value is 0.55.

\$\endgroup\$
2
  • \$\begingroup\$ For your proposed method is it after the line"float radius=length(i.uv);" add in the next line " radius=(radius%0.5)*0.5+0.5;"? I not sure why I got other result. It generate a ripple image. Indeed what you suggested should have return the same boundary value as my original code using the if statement but I also fail to identify what causing a different result 😅 \$\endgroup\$ – chuackt Feb 2 at 10:54
  • \$\begingroup\$ @chuackt I made small before coffee mistake :) \$\endgroup\$ – Zibelas Feb 2 at 10:55
1
\$\begingroup\$

Repetitive actions very very often means a loop. If you don't know how many repetitions, that almost always forces a loop.
To keep the code clean, I suggest a function with the radius as parameters, and 2 more parameters describing your data: the step increment and the number of steps (you could also use the step increment and the maximum radius if you wanted).
The function returns the rounded radius.

float getRoundedRadius(float radius, flot stepIncrement, int nbSteps)
{
    for (int i = 0 ; i < nbSteps ; i++)
    {
        if (radius >= i*stepIncrement && radius <= (i+1)*stepIncrement)
            return i*stepIncrement;
    }
}

Your function frag becomes:

fixed4 frag (v2f i) : SV_Target
{
    //Define boundary value for radius
    float radius= getRoundedRadius(length(i.uv), 0.5, 4);

    //convert to polar coordinates
    float angle=atan2(i.uv.y,i.uv.x);
    float angle1=frac(angle/(2*3.142f));
    float result=-4*radius+angle1+13*frac(_Time.x);  
    return result;
        
}
\$\endgroup\$

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