Search Unity

Writing a shader that alpha blends a portion of a sprite?

Discussion in 'Shaders' started by shwick, Nov 2, 2015.

  1. shwick

    shwick

    Joined:
    Jul 10, 2015
    Posts:
    31
    So I'm trying to write a shader that will alpha blend a circle shape into a sprite, like a hole slowly appearing. From what I've read I'm supposed to create a vertex or fragment shader http://docs.unity3d.com/Manual/SL-ShaderPrograms.html. I'm just not sure where to start or if I'm on the right track.
     
  2. StevenGerrard

    StevenGerrard

    Joined:
    Jun 1, 2015
    Posts:
    97
    Yes, you are on the right track to solve.
    => Alpha blend is controlled by alpha value from fragment shader output. Say " return float4(rgb, alpha); ".
    => A slowly appearing sprite means the value " alpha " is dynamic changed based on time.
    => You can change " alpha " value from script. Check http://docs.unity3d.com/ScriptReference/Material.html
    => If you are new to shader, maybe book <Unity Shaders and Effects Cookbook> will be helpful for you.
     
    shwick likes this.
  3. shwick

    shwick

    Joined:
    Jul 10, 2015
    Posts:
    31
    Thanks that helps a bit but I'm still lost. I've been googling around and haven't found many examples of what I want to do using the new physically based pipeline, only using old legacy examples with "setTexture" which I may have to resort to.

    I don't want to change the alpha of the entire texture, which I know I can do using scripting(but thanks). I want to slowly fade a hole into a texture, basically blend one texture into another, one alpha value at a time. So I'd have a background, then a circular texture on top of that with black(0) RGB values and the alpha would be like 1. Then I would blend(subtracting the alpha) of the black hole texture from the background, slowly creating a hole in the texture.
     
  4. smd863

    smd863

    Joined:
    Jan 26, 2014
    Posts:
    292
    You want to use the smoothstep function.

    Something like:
    Code (csharp):
    1. alpha = smoothstep(_Threshold.x, _Threshold.y, textureA.a);
    Use the alpha directly for the transparency of your shader, or use it to lerp with another texture.

    Code (csharp):
    1.  finalColor = lerp(textureA, textureB, alpha);
    I don't know exactly what you're trying to achieve, but if you want to use the new physically-based lighting then the easiest thing to do is create a new surface shader. Then you can smoothstep and lerp all you want inside the surf() function to get what you want.

    If you want to play around with an example, this will let you cut out a hole in a texture based on its alpha value. You control the size and sharpness of the cut with the _Threshold variable.

    Code (csharp):
    1.  
    2. Shader "Custom/AlphaThresholdSurfaceShader" {
    3.     Properties {
    4.         _Color ("Color", Color) = (1,1,1,1)
    5.         _MainTex ("Albedo (RGB)", 2D) = "white" {}
    6.         _Glossiness ("Smoothness", Range(0,1)) = 0.5
    7.         _Metallic ("Metallic", Range(0,1)) = 0.0
    8.         _Threshold ("Thresholds (X=Min, Y=Max)", Vector) = (0,1,0,0)
    9.     }
    10.     SubShader {
    11.         Tags { "RenderType"="Transparent" "Queue"="Transparent" }      
    12.        
    13.         CGPROGRAM
    14.         // Physically based Standard lighting model, and enable shadows on all light types
    15.         #pragma surface surf Standard fullforwardshadows alpha:fade
    16.  
    17.         // Use shader model 3.0 target, to get nicer looking lighting
    18.         #pragma target 3.0
    19.  
    20.         sampler2D _MainTex;      
    21.  
    22.         struct Input {
    23.             float2 uv_MainTex;
    24.         };
    25.  
    26.         half _Glossiness;
    27.         half _Metallic;
    28.         fixed4 _Color;
    29.         fixed4 _Threshold;
    30.  
    31.         void surf (Input IN, inout SurfaceOutputStandard o) {
    32.             // Albedo comes from a texture tinted by color
    33.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    34.             o.Albedo = c.rgb;
    35.             // Metallic and smoothness come from slider variables
    36.             o.Metallic = _Metallic;
    37.             o.Smoothness = _Glossiness;
    38.             o.Alpha = smoothstep(_Threshold.x, _Threshold.y, c.a);
    39.         }
    40.         ENDCG
    41.        
    42.     }
    43.     FallBack "Diffuse"
    44. }
    45.  
     
  5. shwick

    shwick

    Joined:
    Jul 10, 2015
    Posts:
    31
    Sick thanks I will give that a try!

    I can describe it better: In ms paint, create a solid black square. Then use the eraser tool on said square :)

    But I want the eraser tool to decrease the alpha by 1 at a time instead of fully erase the small portion of the image. But I would still be happy to start with the mspaint effect.

    And I want the effect to be permanent like the eraser tool. Which I'm not even sure a shader can do because I don't know much about them.

    From googling I've found setPixels and I'm going to try that.
     
    Last edited: Nov 27, 2015
  6. smd863

    smd863

    Joined:
    Jan 26, 2014
    Posts:
    292
    SetPixels is too slow; don't use it. Setting pixels is what shaders are for and they do it much, much faster.

    If you want it to be permanent (i.e. for some type of drawing program), you need to create two render textures and iterate between them. Use one as a texture input as you are drawing into the other, and then swap them for the next pass. You would use something like the shader I posted for the brush texture so you could use different textures as alpha masks and control the opacity and the edge softness. You'd just have to add in a the texture input for your last render texture (i.e. your canvas texture), and a vector for the offset of your brush so you could render it at the right place.

    Once you have the canvas color and the brush alpha value, you can use them to calculate any effect you want. Color it, erase it, apply a pattern, etc. and then just output the final color to the new canvas texture. Swap the canvas textures and repeat as needed.

    It's relatively easy once you know how everything fits together. You just need to run through a tutorial on render textures, and one on writing basic shaders.
     
  7. shwick

    shwick

    Joined:
    Jul 10, 2015
    Posts:
    31
    Ok thank you very much I will look into that more. I was just just reading about graphics.blit and rendertextures a bit. I'll see what I can find thanks.