今回やること
まずはソースコード
public class TexturePaint : MonoBehaviour { private RenderTexture mainRenderTexture; [SerializeField] private Texture mainTexture; [SerializeField] private Material paintMaterial; [SerializeField, Range(0.001f, 0.01f)] private float size; [SerializeField] private Color color; private void Awake() { mainRenderTexture = new RenderTexture(mainTexture.width, mainTexture.height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default); Graphics.Blit(mainTexture, mainRenderTexture); GetComponent<Renderer>().material.SetTexture("_MainTex", mainRenderTexture); } void Update() { if (Input.GetMouseButton(0)) { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ray, out hit, 100.0f)) { Paint(hit.textureCoord); } } } private void Paint(Vector2 uv) { Vector4 vec = new Vector4(uv.x, uv.y, 0, 0); paintMaterial.SetVector("_UV", vec); paintMaterial.SetColor("_Color",color); paintMaterial.SetFloat("_Size",size); var tmpBuffer = RenderTexture.GetTemporary(mainRenderTexture.width, mainRenderTexture.height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default); Graphics.Blit(mainRenderTexture, tmpBuffer, paintMaterial); Graphics.Blit(tmpBuffer, mainRenderTexture); RenderTexture.ReleaseTemporary(tmpBuffer); } private void OnDestroy() { mainRenderTexture.Release(); } }
Shader "Unlit/Paint" { Properties { _MainTex ("Texture", 2D) = "white" {} _UV("UV",Vector) = (0.5,0.5,0,0) _Color("Color",Color)=(1,1,1,1) _Size("Size",float)=0.2 } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; UNITY_FOG_COORDS(1) float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; float2 _UV; float4 _Color; float _Size; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); UNITY_TRANSFER_FOG(o,o.vertex); return o; } fixed4 frag (v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.uv); if (length(i.uv - _UV.xy) < _Size) { col.xyz = _Color.xyz; } UNITY_APPLY_FOG(i.fogCoord, col); return col; } ENDCG } } }
Graphics.Blit関数によりShaderで加工したTextureをコピーするというのを繰り返すことでお絵描きしているように見せてます。
shader側では送られてきたUV座標と現在処理しているUV座標の差がsize以下なら塗りつぶし、それ以外はもとのTextureのまま処理するということをしています。
絵を描くだけではなくVTFを利用したりすることで応用もできます。
参考
nn-hokuson.hatenablog.com
esprog.hatenablog.com
www.youtube.com