1. 멀티-렌더러 페인팅 이슈
- 문제 발견
프로젝트 초기엔 구조물 하나에 PaintableObject 컴포넌트를 달고, 자식에 달린 여러 MeshRenderer를 한 번에 순회하면서 그리도록 구현했다. 그런데 실험해 보니, 총알이 자식 A에만 충돌해 페인트가 찍혔음에도 자식 B, C에도 똑같이 칠해지는 현상이 발생했다. - 원인 분석
- 머티리얼 인스턴스 공유
MeshRenderer.material 프로퍼티를 통해 접근하면, Unity는 내부적으로 shared material이 아닌 인스턴스를 만들어 모든 렌더러가 같은 인스턴스를 바라보게 된다. - 커맨드 버퍼 DrawRenderer 순회
CommandBuffer.DrawRenderer 호출 시도 모두 동일 머티리얼 인스턴스를 참조하므로, “A만 그릴” 페인트 셋업과 “B에도 그려” 셋업이 뒤섞인다.
- 머티리얼 인스턴스 공유
- 해결: 개별 인스턴스 분리
- 이렇게 하면 A에만 속한 Renderer는 각자 고유한 머티리얼을 갖고, B/C와 충돌 없이 독립적으로 칠해진다.
// PaintableSetup.cs (Awake)
var renders = GetComponentsInChildren<Renderer>();
foreach(var r in renders) {
// 각 렌더러마다 별도 복제(Material.Instantiate)한 머티리얼을 할당
var mats = r.sharedMaterials;
for(int i=0; i<mats.Length; i++){
mats[i] = new Material(paintableMaterial);
mats[i].SetTexture("_MainTex", originalTextures[i]);
}
r.materials = mats;
}
이렇게 하면 A에만 속한 Renderer는 각자 고유한 머티리얼을 갖고, B/C와 충돌 없이 독립적으로 칠해진다.
2. CommandBuffer 기반 GPU 페인팅
왜 CommandBuffer인가?
CPU에서 즉시 렌더링 API를 호출(Graphics.DrawMesh, Graphics.Blit 등)하면 GPU 동기화가 반복되어 프레임 드롭이 발생할 수 있다. CommandBuffer에 모든 그리기 명령을 모아뒀다가 한 번에 실행하면, 드라이버·GPU 왕복을 최소화하며 높은 퍼포먼스를 얻을 수 있다.
준비과정이다.
var cmd = new CommandBuffer { name = "PaintMask" };
cmd.SetRenderTarget(maskRT);
페인트 셋업은 아래와같이할수있따.
// Prepare UV (마스크 초기화)
paintMat.SetFloat(_PrepareUV, 1);
cmd.DrawRenderer(targetRenderer, paintMat, 0 /*패스 인덱스*/);
아래처럼
스탬프(페인트 하나)를 찍을수있다.
paintMat.SetFloat(_PrepareUV, 0);
paintMat.SetVector(_PainterPosition, worldPos);
paintMat.SetFloat(_Radius, radius);
cmd.SetRenderTarget(maskRT);
cmd.DrawRenderer(targetRenderer, paintMat, 0);
누적은 Blit을 이용해가능하다
// 방금 그린 마스크(maskRT)를 누적(maskTmp)→ 최종 텍스처(resultRT)
cmd.Blit(maskRT, maskTmp);
cmd.Blit(maskTmp, resultRT, extendMat);
실행및 클리어는
Graphics.ExecuteCommandBuffer(cmd);
cmd.Clear();
정리:
DrawRenderer로 GPU 내부에 물감 찍기 작업을 모아두고, Blit으로 누적·확장 셰이더를 한 번에 처리.
CPU<–>GPU 걸리는 오버헤드를 크게 줄여, 복잡한 씬에서도 매 초당 수백 번 그리기가 가능.
실제 페인트칠 예제
void Paint(Renderer target, Vector3 pos){
cmd.SetRenderTarget(maskRT);
paintMat.SetFloat(_PrepareUV, 0);
paintMat.SetVector(_PainterPosition, pos);
cmd.DrawRenderer(target, paintMat);
cmd.Blit(maskRT, maskTmp);
cmd.Blit(maskTmp, resultRT, extendMat);
Graphics.ExecuteCommandBuffer(cmd);
cmd.Clear();
}'Unity 개발 공부' 카테고리의 다른 글
| [내배캠] 본캠 86 Photon pun2 hashtable 관련 이슈 해결 ft: remove (3) | 2025.08.06 |
|---|---|
| [내배캠] 본캠 81 게임 씬 카운트다운 및 게임 타이머 동기화 via Photon RPC (0) | 2025.07.30 |
| [내배캠] 본캠 63 쉐이더공부를 위한 기본이론공부 (6) | 2025.07.04 |
| [내배캠] 본캠 57 pun2 공부5 (2) | 2025.07.03 |
| [내배캠] 본캠 60 pun2 공부7, 시간 (1) | 2025.07.03 |