Search Unity

Dynamically Paint A Texture - I'm halfway but stuck!

Discussion in 'Shaders' started by JohnEvelyn, Apr 20, 2018.

  1. JohnEvelyn

    JohnEvelyn

    Joined:
    Oct 28, 2016
    Posts:
    9
    Hi Everyone,

    I'm working on a thing where I have an object that paints surfaces.
    The problem is I'm clueless with shaders - my code currently has a base texture and a paint texture.

    - That configuration works fine.

    But(!)
    I would like to have a totally transparent object (ie no initial/base texture), that only shows the dynamic painted texture.

    any ideas? (my shader code is below)

    Thank you so much!

    Images to better explain:

    paintablesurface01.png
    paintablesurface02.png

    my shader:

    Code (CSharp):
    1.  
    2.  
    3. Shader "CA/Paint Surface" {
    4.  
    5.     Properties{
    6.         _MainTex("Main Texture", 2D) = "white" {}
    7.     _PaintMap("PaintMap", 2D) = "white" {} // texture to paint on
    8.     }
    9.  
    10.         SubShader{
    11.         Tags{ "RenderType" = "Opaque" "LightMode" = "ForwardBase" }
    12.  
    13.         Pass{
    14.         Lighting Off
    15.  
    16.         CGPROGRAM
    17.  
    18. #pragma vertex vert
    19. #pragma fragment frag
    20.  
    21.  
    22. #include "UnityCG.cginc"
    23. #include "AutoLight.cginc"
    24.  
    25.     struct v2f {
    26.         float4 pos : SV_POSITION;
    27.         float2 uv0 : TEXCOORD0;
    28.         float2 uv1 : TEXCOORD1;
    29.  
    30.     };
    31.  
    32.     struct appdata {
    33.         float4 vertex : POSITION;
    34.         float2 texcoord : TEXCOORD0;
    35.         float2 texcoord1 : TEXCOORD1;
    36.  
    37.     };
    38.  
    39.     sampler2D _PaintMap;
    40.     sampler2D _MainTex;
    41.     float4 _MainTex_ST;
    42.     v2f vert(appdata v) {
    43.         v2f o;
    44.  
    45.         o.pos = UnityObjectToClipPos(v.vertex);
    46.         o.uv0 = TRANSFORM_TEX(v.texcoord, _MainTex);
    47.  
    48.         o.uv1 = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;// lightmap uvs
    49.  
    50.         return o;
    51.     }
    52.  
    53.     half4 frag(v2f o) : COLOR{
    54.         half4 main_color = tex2D(_MainTex, o.uv0); // main texture
    55.         half4 paint = (tex2D(_PaintMap, o.uv1)); // painted on texture
    56.         main_color *= paint;
    57.  
    58.         return main_color;
    59.     }
    60.         ENDCG
    61.     }
    62.     }
    63. }
     
  2. Remy_Unity

    Remy_Unity

    Unity Technologies

    Joined:
    Oct 3, 2017
    Posts:
    703
    You need a way to store the opacity of your painted texture : probably use the alpha channel.
    Then you have 2 solutions :
    1. Alpha clip : In the fragment shader, use http://developer.download.nvidia.com/cg/clip.html to not render the pixels where the alpha of the paint texture is < a certain threshold.
    2. Alpha blend : set the proper render queue and blending value for your object to make the plane semi-transparent
    Both are nicely explained here : https://docs.unity3d.com/Manual/SL-Blend.html
     
  3. JohnEvelyn

    JohnEvelyn

    Joined:
    Oct 28, 2016
    Posts:
    9
    Thank you for the pointers @Remy_Unity I've got it all fixed up now!
     
  4. dmarfurt

    dmarfurt

    Joined:
    Apr 28, 2013
    Posts:
    9
    Hi John, I'm just getting started on a project with a similar use case. I'm also a shader newbie, would you mind expanding on the solution you used a little bit? Specifically, how did you tie the position (I assume) of the paintbrush object to the paintmap coordinates? Many thanks!
     
  5. JohnEvelyn

    JohnEvelyn

    Joined:
    Oct 28, 2016
    Posts:
    9
  6. dmarfurt

    dmarfurt

    Joined:
    Apr 28, 2013
    Posts:
    9