Skip to content

Commit 4f5e344

Browse files
Decal projector minimal example
1 parent 1c666bb commit 4f5e344

File tree

2 files changed

+96
-0
lines changed

2 files changed

+96
-0
lines changed

Diff for: DecalPainter.cs

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using UnityEngine;
2+
3+
public class DecalPainter : MonoBehaviour
4+
{
5+
public GameObject TargetObject;
6+
public Shader DecalPainterShader;
7+
public Texture2D DecalTexture;
8+
public bool Debug = true;
9+
10+
private Matrix4x4 _DecalViewMatrix, _DecalProjectionMatrix;
11+
private Material _TargetMaterial;
12+
private Material _PaintMaterial; //unwrapped mesh
13+
private Mesh _TargetMesh;
14+
private Renderer _TargetRenderer;
15+
private RenderTexture _RenderTexture;
16+
17+
void Start()
18+
{
19+
_RenderTexture = new RenderTexture(4096, 4096, 0);
20+
_RenderTexture.Create();
21+
_PaintMaterial = new Material(DecalPainterShader);
22+
_TargetRenderer = TargetObject.GetComponent<Renderer>();
23+
_TargetMesh = TargetObject.GetComponent<MeshFilter>().sharedMesh;
24+
_TargetMaterial = _TargetRenderer.sharedMaterial;
25+
}
26+
27+
void Update()
28+
{
29+
_PaintMaterial.SetMatrix("_MeshModelMatrix", _TargetRenderer.localToWorldMatrix);
30+
RaycastHit hit;
31+
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
32+
if (Physics.Raycast(ray, out hit))
33+
{
34+
_DecalViewMatrix = Matrix4x4.TRS(hit.point + hit.normal, Quaternion.LookRotation(-hit.normal, Vector3.up), Vector3.one).inverse;
35+
_DecalProjectionMatrix = Matrix4x4.Ortho(-0.2f, 0.2f, -0.2f, 0.2f, 0.01f, 1.0f);
36+
_PaintMaterial.SetMatrix("_DecalViewMatrix", _DecalViewMatrix);
37+
_PaintMaterial.SetMatrix("_DecalProjectionMatrix", _DecalProjectionMatrix);
38+
_PaintMaterial.SetTexture("_DecalTexture", DecalTexture);
39+
}
40+
RenderTexture currentRT = RenderTexture.active;
41+
RenderTexture.active = _RenderTexture;
42+
GL.Clear(false, true, Color.black, 1.0f);
43+
_PaintMaterial.SetPass(0);
44+
Graphics.DrawMeshNow(_TargetMesh, Vector3.zero, Quaternion.identity);
45+
RenderTexture.active = currentRT;
46+
_TargetMaterial.mainTexture = _RenderTexture;
47+
}
48+
49+
void OnGUI()
50+
{
51+
if (Debug)
52+
GUI.DrawTexture(new Rect(0, 0, 512, 512), _RenderTexture, ScaleMode.ScaleToFit);
53+
}
54+
55+
void OnDestroy()
56+
{
57+
_RenderTexture.Release();
58+
Destroy(_PaintMaterial);
59+
}
60+
}

Diff for: DecalPainter.shader

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
Shader "DecalPainter"
2+
{
3+
SubShader
4+
{
5+
Pass
6+
{
7+
ZTest Off
8+
ZWrite Off
9+
Cull Off
10+
CGPROGRAM
11+
#pragma vertex VSMain
12+
#pragma fragment PSMain
13+
14+
float4x4 _MeshModelMatrix, _DecalViewMatrix, _DecalProjectionMatrix;
15+
sampler2D _DecalTexture;
16+
17+
void VSMain (inout float4 vertex:POSITION, inout float2 uv:TEXCOORD0, out float4 worldPos:TEXCOORD1, out float4 clipPos:TEXCOORD2)
18+
{
19+
worldPos = mul(_MeshModelMatrix, vertex);
20+
clipPos = mul(_DecalViewMatrix, worldPos);
21+
clipPos = mul(_DecalProjectionMatrix, clipPos);
22+
float2 texcoord = uv.xy;
23+
texcoord.y = 1.0 - texcoord.y;
24+
texcoord = texcoord * 2.0 - 1.0;
25+
vertex = float4(texcoord, 0.0, 1.0);
26+
}
27+
28+
float4 PSMain (float4 vertex:POSITION, float2 uv:TEXCOORD0, float4 worldPos:TEXCOORD1, float4 clipPos:TEXCOORD2) : SV_TARGET
29+
{
30+
float2 tc = float2( clipPos.x / clipPos.w, clipPos.y / clipPos.w) / 2.0 + 0.5;
31+
return (tc.x > 0.0 && tc.x < 1.0 && tc.y > 0.0 && tc.y < 1.0) ? tex2D(_DecalTexture, tc) : float4(1, 0, 0, 1);
32+
}
33+
ENDCG
34+
}
35+
}
36+
}

0 commit comments

Comments
 (0)