The question is answered, right answer was accepted
Help with a custom "painting" shader
I have tried and tried to make a shader that would allow me to "paint" on the surface of the object with another by hitting it, (like the water that appears on ground when you shoot water at it in Super Mario Sunshine) no luck so far I've been said and forwarded to vertex color changing, which meaby could work if I got it even working :( then also this was a reply I got:
I think having a lightmap-UV-mapped mask is a much more elegant solution.
You would need to implement a script that allows your water gun to paint into the mask texture. You could use a greyscale alpha "brush" texture to soften the edges painted in.
Then you would need to write a shader (I recommend a surface shader) that looks up the mask texture and blends the regular appearance of the face with whatever water effect you want to do (ie darken the albedo, increase the smoothness, perhaps apply a flowing water normal).
You can use a noise function or noise lookup texture to perturb the edges between your wet and dry areas, similar to the method described here to dissolve occlusion geometry:
http://glowfishinteractive.com/dissolving-the-world-part-1/
but the problem is that I can not figure to the end of me how would I do this that was said in this post and yes I'm a total noob with shaders xD, also I USE SHADER GRAPH! if that helps or IDK, but thanks if someone will try to help me.
Answer by no00ob · Jul 26, 2018 at 05:05 PM
Solution found and this system is in place and working :D shader:
Shader "Custom/StandardWet"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
_WetMaskTex ("Wet Map", 2D) = "black" {}
_WetTint("Wet Tint", Color) = (1,1,1,1)
_WetSmoothness("Wet Smoothness", Range(0,1)) = 0.85
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Standard fullforwardshadows
#pragma target 3.0
sampler2D _MainTex;
sampler2D _WetMaskTex;
struct Input
{
float2 uv_MainTex;
float2 uv2_WetMaskTex;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
half _WetSmoothness;
fixed4 _WetTint;
UNITY_INSTANCING_BUFFER_START(Props)
// put more per-instance properties here
UNITY_INSTANCING_BUFFER_END(Props)
void surf (Input IN, inout SurfaceOutputStandard o)
{
fixed4 baseAlbedo = tex2D (_MainTex, IN.uv_MainTex) * _Color;
fixed4 wetAlbedo = baseAlbedo * _WetTint;
float2 uv2 = IN.uv2_WetMaskTex * unity_LightmapST.xy + unity_LightmapST.zw;
half wetness = tex2D(_WetMaskTex, uv2).r;
fixed4 c = lerp(baseAlbedo, wetAlbedo, wetness);
o.Albedo = c;
o.Metallic = _Metallic;
o.Smoothness = min(1, _Glossiness + wetness * _WetSmoothness);
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
Painting Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Rtw
{
public class Painter : MonoBehaviour
{
[SerializeField]
int _canvasSize = 256;
Texture2D _canvas;
[SerializeField]
int _brushSize = 1;
[SerializeField]
AnimationCurve _falloff;
[SerializeField]
string _targetTextureName = "_WetMaskTex";
Mesh mesh;
void Start ()
{
_canvas = new Texture2D(_canvasSize, _canvasSize);
Color[] colours = _canvas.GetPixels();
for(int i = 0; i < colours.Length; i++ )
{
colours[i] = Color.black;
}
_canvas.SetPixels(colours);
_canvas.Apply();
}
void Update ()
{
if(!Input.GetMouseButton(0) && !Input.GetMouseButton(1))
{
return;
}
Paint();
}
void Paint()
{
List<Renderer> rends = new List<Renderer>();
Color targetColour = Color.white;
if (Input.GetMouseButton(1))
{
targetColour = Color.black;
}
for (int x = -_brushSize + 1; x < _brushSize; x++)
{
for (int y = -_brushSize + 1; y < _brushSize; y++)
{
Vector3 offset = new Vector3(x, y, 0f);
float offsetLength = offset.magnitude;
// Consider only a circular shape around centre point
if (offsetLength >= _brushSize)
{
continue;
}
float falloffValue = _falloff.Evaluate(Mathf.Clamp(offsetLength / (float)_brushSize, 0f, 1f));
if (falloffValue == 0f)
{
continue;
}
RaycastHit hit;
if (!Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition + offset), out hit))
{
continue;
}
Renderer rend = hit.transform.GetComponent<Renderer>();
if (rend == null)
{
continue;
}
if (!rends.Contains(rend))
{
rends.Add(rend);
}
Vector2 pixelLightmapUV = hit.lightmapCoord;
pixelLightmapUV.x *= _canvas.width;
pixelLightmapUV.y *= _canvas.height;
int pixelX = (int)pixelLightmapUV.x;
int pixelY = (int)pixelLightmapUV.y;
Color existingColour = _canvas.GetPixel(pixelX, pixelY);
Color updateColour = targetColour * falloffValue;
if( (targetColour.r > existingColour.r && updateColour.r > existingColour.r)
|| (targetColour.r < existingColour.r && updateColour.r < existingColour.r))
{
_canvas.SetPixel(pixelX, pixelY, updateColour);
}
}
}
_canvas.Apply();
MaterialPropertyBlock mpb = new MaterialPropertyBlock();
mpb.SetTexture(_targetTextureName, _canvas);
foreach (Renderer rend in rends)
{
rend.SetPropertyBlock(mpb);
}
}
}
}