0

I am trying to draw a circle, fill the inside with a red color and the outside with a black color.

I want to set the size of the circle from code. With 0 being the smallest size and 100 being the maximum size of the circle and 100 means that the circle must cover the screen.

Here is the code:

Shader "Hidden/Circle"
{
    Properties
    {
        _MainTex("Texture", 2D) = "white" {}
    _radius("Radius",Range(0, 100)) = 100
        _radiusOffet("Offset",Range(0, 100)) = 72
        _discardedColor("Dicard Color", Color) = (0, 0, 0, 0) // color
    }
        SubShader
    {
        //Tags{ "Queue" = "Transparent" }
        // No culling or depth
        Cull Off ZWrite Off ZTest Always

        Pass
    {
        CGPROGRAM
#pragma vertex vert
#pragma fragment frag

#include "UnityCG.cginc"


    sampler2D _MainTex;
    float4 _discardedColor;

    float _radius;
    float _radiusOffet;

    float minMinSlide = 0; //0.314
    float minMaxSlide = 100.0;

    struct v2f
    {
        float2 uv : TEXCOORD0;
    };

    v2f vert(
        float4 vertex : POSITION, // vertex position input
        float2 uv : TEXCOORD0, // texture coordinate input
        out float4 outpos : SV_POSITION // clip space position output
    )
    {
        v2f o;
        o.uv = uv;
        outpos = UnityObjectToClipPos(vertex);
        return o;
    }

    float mapValue(float mainValue, float inValueMin, float inValueMax, float outValueMin, float outValueMax)
    {
        return (mainValue - inValueMin) * (outValueMax - outValueMin) / (inValueMax - inValueMin) + outValueMin;
    }

    fixed4 frag(v2f i, UNITY_VPOS_TYPE screenPos : VPOS) : SV_Target
    {
        //Set default values
        minMinSlide = 0;
    minMaxSlide = 100;

    //fixed4 col = tex2D(_MainTex, i.uv);

    float4 fragColor = 0;
    //float2 fragCoord = i.vertex.xy;
    float2 fragCoord = screenPos;
    float2 screenCoord = fragCoord.xy;

    float minOutRadius = 0;

    //THIS IS WRONG? WHAT'S THE PROPER WAY OF DOING THIS?
    float maxOutRadius = (_ScreenParams.x / 2) + _radiusOffet;

    //Calcuate the scaled radius
    float rad = mapValue(_radius, minMinSlide, minMaxSlide, minOutRadius, maxOutRadius);

    float2 middlePoint = _ScreenParams.xy * 0.5 - screenCoord;
    float middleLength = middlePoint.x * middlePoint.x + middlePoint.y * middlePoint.y;
    if (middleLength > rad * rad)
    {
        //Use black color
        fragColor = _discardedColor;
    }
    else {
        //Use red color
        fragColor = float4(1, 0, 0, 0);
    }
    return fragColor;
    }
        ENDCG
    }
    }
}

This code works 100% on the Editor.

There is a minor problem in the Windows and Android build.

The problem is that the circle does not totally cover the screen 100% when the value is to set to 100. This works fine in the Editor though.

I believe that the problem is this line:

float maxOutRadius = (_ScreenParams.x / 2) + _radiusOffet;

How do I properly calculate the max radius of the circle based on the screen size of the device?

That line of code is only working properly on the Editor.

PassetCronUs
  • 447
  • 4
  • 11

1 Answers1

2

The maximum radius of the circle is the distance from the center to the corner of the screen. That would be:

float x = _ScreenParams.x / 2;
float y = _ScreenParams.y / 2;
float maxOutRadius = sqrt(x*x+y*y); // + _radiusOffet; 

You can make the shader a lot simpler btw. For ex:

uniform float _Percent;   
fixed4 frag (float4 pos:VPOS) : SV_Target
{
    float4 col;
    float2 center = _ScreenParams.xy/2;

    float maxradius = length(center); 
    float radius = maxradius * abs(sin(_Time.y)); // * (_Percent/100);

    if(distance(pos.xy, center) > radius){
        col = float4(0,0,0,1);
    }else{
        col = float4(1,0,0,1);
    }
    return col;
} 
Pluto
  • 3,911
  • 13
  • 21
  • Thanks. Not on my computer to test this now but will be in few hours and will try it then accept this as the answer. Mean while, what if I want to change the center position of the circle? Let's say I want to change where the circle will start to to draw, will this solution also work? – PassetCronUs Aug 02 '17 at 21:15
  • Sure but you have to set the maxradius to `max( distance( center, topLeftCorner), distance( center, topRightCorner), ...` if you want it to cover the whole screen. – Pluto Aug 02 '17 at 21:41
  • I got the time to try it. It works fine on Windows build now but it **doesn't** work at-all on Android. There is no circle visible on Android itself. That's weird. You can try it and see for yourself. – PassetCronUs Aug 03 '17 at 07:11
  • It works just fine on Android (GLES 2.0). Try the edited version, it should change the radius for you. – Pluto Aug 03 '17 at 10:35
  • I am not lying. I just spent the whole day trying to get this working but it's not. Even your second code is not working on Android with GLES 2.0. The screen is covered in red and it's not animation. The weird thing is that it perfectly work on Windows. – PassetCronUs Aug 03 '17 at 23:20
  • I tried this on another Android device with GLES 2.0 and it works. What is going on? Do you know why it would work on one Android device but not on another one? – PassetCronUs Aug 04 '17 at 09:49