This article is a case of UV smearing of the model. According to the usual practice, let’s start with the picture above:
Alright, let’s start to explain:
1. In order to allow rays to detect the surface of the model, we need to add a MeshCollider to the model, and the model material uses ordinary Standard preparation materials That's it.
2. Prepare the brush material. If you don’t need the target texture, just don’t assign a value. The following is the material code.
Brush Shader original code:
Shader "Giraffe/SingleBursh"
{
Properties
{
_TargetTex("目标图形",2D) = "white" {}
_BrushTex("刷子形状",2D) = "white" {}
_Color("Color",Color) = (1,1,1,1)
_UV("UV",Vector) = (0,0,0,0)
_SizeX("SizeX",Range(1,100)) = 1
_SizeY("SizeY",Range(1,100)) = 1
_Alpha("刷子权重",Range(0,1)) = 0.2
}
SubShader
{
Tags { "RenderType" = "Transparent" }
LOD 100
ZTest Always Cull Off ZWrite Off Fog{ Mode Off }
Blend SrcAlpha OneMinusSrcAlpha
//Blend One DstColor
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _BrushTex;
sampler2D _TargetTex;
float4 _TargetTex_ST;
fixed4 _UV;
float _SizeX;
float _SizeY;
fixed4 _Color;
float _Alpha;
v2f vert(appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _TargetTex);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
float2 _Size = float2(_SizeX,_SizeY);
float2 uv = i.uv + (0.5f / _Size);
uv = uv - _UV.xy;
uv *= _Size;
fixed4 col = tex2D(_BrushTex, uv);
col.rgb = 1;
fixed4 col2 = tex2D(_TargetTex, i.uv);
col *= _Color;
half4 RGB = col* col2;
return half4(RGB.rgb, RGB.a*_Alpha);
}
ENDCG
}
}
}
3. The following is the mouse click part. The UV of the clicked position is detected by emitting rays. The code is as follows:
RaycastHit hit;
Ray ray;
ray = Camera.main.ScreenPointToRay(Input.mousePosition); //摄像机发射射线到屏幕点。
Debug.DrawRay(ray.origin, ray.direction * 100, Color.red, 0.1f); //可以在Screen窗口看到射线轨迹
if (Physics.Raycast(ray, out hit, 100f))
{
Vector2 pixelUV = hit.textureCoord; //得到点击位置所在UV值
BrushHandle(pixelUV);
}
Fourth, the main logic part, this can be directly hung up with MonoBehaviour.
public RenderTexture m_renderTex; //渲染图
public Texture m_texOriginal; //起始模型图
public Texture m_texTarget; //笔刷纹理图
public Material m_matMain; //星球材质
public Material m_matBrush; //刷子材质
private void ReadyBrushObj()
{
//创建渲染纹理
m_renderTex = RenderTexture.GetTemporary(2048, 2048, 24);
//将默认图片赋值给渲染纹理
Graphics.Blit(m_texOriginal, m_renderTex);
//将默渲染纹理赋值给模型材质主图
m_matMain.SetTexture("_MainTex", m_renderTex);
//将笔刷纹理赋值给纹理图(可选)
m_matBrush.SetTexture("_TargetTex", m_texTarget);
}
private void __BrushHandle(Vector2 minUv)
{
m_matBrush.SetVector("_UV", minUv);
Graphics.Blit(m_renderTex, m_renderTex, m_matBrush);
}
The above is the complete content.
The following is the project demo, if you have any questions, you can private message me:
https://download.csdn.net/download/ww1351646544/21043484?spm=1001.2014.3001.5503