Files
chameleon/Assets/Shaders/MeshPaintBrush.shader
T
adminandClaude Opus 4.8 fa4474f6d4 Initial commit: Unity mesh painter project
Unity 6000.3 (URP) project with live mesh painting in play mode.

- MeshPainter.cs: paint a SkinnedMesh with the mouse, seamless across
  UV islands via 3D-space painting, GPU and CPU backends (switchable),
  edge-padding/dilation against bilinear seam bleed
- FrameRateLimiter.cs: simple frame rate limiting component
- MeshPaintBrush / MeshPaintDilate shaders for the GPU paint path
- Unity-specific .gitignore and .gitattributes

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 12:03:24 +02:00

75 lines
2.5 KiB
Plaintext

// GPU brush: paints a 3D sphere seamlessly into the paint texture.
//
// In the vertex shader the mesh is "unwrapped" into the texture layout using its
// UVs (uv -> clip space), while the actual local 3D position of the vertex is
// passed through to the fragment shader. There, per texel, the distance to the
// brush center (_BrushCenter, in local mesh space) is tested against _BrushRadius.
//
// This bridges UV seams automatically: triangles on both sides of a seam share
// the same 3D edge and are captured by the same brush stroke, no matter where
// they lie in the UV layout (identical behavior to the CPU path).
Shader "Hidden/MeshPaintBrush"
{
Properties
{
_BrushColor ("Brush Color", Color) = (1,0,0,1)
}
SubShader
{
Tags { "RenderType" = "Opaque" }
Pass
{
ZTest Always
ZWrite Off
Cull Off
Blend Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
float4 _BrushColor;
float3 _BrushCenter; // brush center in local mesh space
float _BrushRadius; // brush radius in local mesh space
struct appdata
{
float4 vertex : POSITION; // local 3D position
float2 uv : TEXCOORD0; // UV (target in the texture layout)
};
struct v2f
{
float4 pos : SV_POSITION;
float3 local : TEXCOORD0; // interpolated local 3D position
};
v2f vert (appdata v)
{
v2f o;
// UV (0..1) -> clip space (-1..1). This makes the GPU rasterize
// each triangle exactly at its place in the texture.
float2 p = v.uv * 2.0 - 1.0;
#if UNITY_UV_STARTS_AT_TOP
p.y = -p.y; // compensate the RenderTexture Y-flip (D3D etc.)
#endif
o.pos = float4(p, 0.0, 1.0);
o.local = v.vertex.xyz;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// Only color texels inside the 3D brush sphere.
float d = distance(i.local, _BrushCenter);
clip(_BrushRadius - d);
// Alpha = 1 marks "painted by the brush" (source for the edge padding).
return fixed4(_BrushColor.rgb, 1.0);
}
ENDCG
}
}
Fallback Off
}