
지금의 ShellProtector는 VRChat 아바타 텍스쳐를 그대로 뜯어가도 정상적으로 보이지 않게 하는 도구임.
쉽게 말하면, 아바타 옷이나 피부 텍스쳐를 업로드 전에 암호화해서 망가진 그림처럼 바꿔두고, VRChat 안에서는 전용 셰이더가 비밀번호를 이용해 다시 정상 이미지처럼 보이게 하는 방식이야.
전체구조는 대충 이래.
1. 유니티에서 아바타에 ShellProtector를 붙인다.
2. 보호할 마테나 옵젝을 고른다.
3. 비번 정한다.
4. 암호화 한다.
5. 원본은 건들지 않고 암호화된 사본을 만든다.
6. 업로드하면 서버에 암호화된 텍스쳐가 올라간다.
7. 게임에서는 키를 받아 복호화한다.
쉽게 비유하면 사진 파일을 자물쇠가 걸린 퍼즐 조각으로 바꿔서 업로드하고, 게임 안에서만 맞는 열쇠로 다시 맞춰 쓰는거야.
지금 암호화는 뭘 쓰냐면
Chacha8이랑 XXTEA 두개거든?
Chacha8은 빠른 스트림 암호 계열 방식이고
XXTEA는 블록 암호 방식이야
자세히는 알 필요 없고
암호화된 텍스쳐가 런타임에서 어케 보이는지를 보자.
암호화된 텍스쳐는 그냥 보면 깨진 이미지인데, ShellProtector가 만든 쉐이더는 픽셀을 그릴때 이런 작업을 수행해.
1. 현재 픽셀 위치를 확인한다.
2. _Key0부터 _Key15까지의 키 값을 읽는다.
3. 암호화된 텍스쳐에서 데이터를 가져온다.
4. 암호화 방식으로 복호화한다.
5. 복호화된 색을 출력한다.
그래서 사용자는 정상 아바타로 보이는데, 텍만 뜯어가면 암호화된 이미지만 얻을 수 있는 거임.
그래서 DXT1/DXT5는 왜 가능하냐?
이 둘은 게임에서 흔히 쓰는 방식인데, 내부 구조가 단순해.
간단히 말하면 한 블록 안에
- 기준색 2개
- 각 픽셀이 기준 색을 어떻게 섞을지 알려주는 번호
가 들어있어
툴은 이 구조를 써서 기준 색만 암호화해서 따로 저장하고, 번호 정보는 GPU가 읽을 수 있게 남겨둬. 그러면 쉐이더가 기준 색을 복호화 한 뒤에 남은 번호를 이용해 원래 색을 다시 만드는거지.
즉, DXT는 구조가 단순해서, "일부만 암호화하고 나머지는 힌트로 사용하는 방식"이 가능해.
그래서 BC7은 왜 안되는데?
BC7도 압축 텍스쳐 형식이긴 한데, DXT보다 훨씬 복잡해.
DXT가 단순한 번호표라면, BC7은 여러 규칙이 섞인 고급 압축 방식이야.
블록마다 내부 모드가 다를 수 있고, 색 정보와 번호 정보가 고정된 위치에 있지 않아.
BC7 안에는 이런 요소가 들어가.
- 어떤 압축 모드를 쓰는지
- 색 기준점이 몇 개인지
- 영역을 몇 개로 나누는지
- 픽셀이 어느 영역에 속해있는지
- 알파 정보가 있는지
- 색 번호가 몇 비트인지
- 보정용 p-bit가 있는지
그래서 DXT처럼 "이 부분이 기준 색이니까 여기만 암호화 하자"라고 단순처리가 어려운거야.
또 중요한 문제는, 쉐이더는 보통 BC7의 원본 압축 데이터를 볼 수 없어.
GPU가 먼저 BC7을 풀고, 쉐이더에는 최종 색만 줘.
원본 압축 블록의 128비트 데이터를 보려면 별도 텍스쳐에 raw data로 저장해야해고, 쉐이더에서 BC7 해석기를 직접 만들어야해.
그러면 쉐이더가 할 일이 크게 늘지
- BC7 모드 분석
- 비트 단위 데이터 추출
- 영역 분할 계산
- 색 기준점 복원
- 픽셀별 색 보간
- 그 위에 암호화 복호화까지 실행
VRChat 쉐이더에서 이 작업은 성능과 호환성 면에서 부담이 큰거야.
결론
BC7 지원이 어려운 이유는 암호화 알고리즘 때문이 아니라, BC7 압축 구조를 쉐이더에서 다시 해석해야하기 때문이다.
현실적으로는 DXT5로 변환해서 품질이 떨어지는걸 감안하고 쓰기나, RGBA32로 풀어서 품질은 유지하지만 용량과 메모리를 크게 늘려서 쓰거나임
진짜로 BC7 복호화 쉐이더는 구현할 수 있는데, 난이도, 성능 비용, 유지보수 비용이 커짐
Q.E.D.