굴절을 계산한다
셀마다 높이가 이어지는 유리판을 세우고, 공기에서 유리로 들어갔다 나오는 두 번의 굴절을 스넬 법칙으로 푼다. 경계의 반사량은 프레넬 식으로 구한다. 평균색 모자이크나 그려 넣은 격자가 아니다.
LETSPETS / PROJECT 01
눈앞의 장면을 패턴 유리 너머로 보는 iPhone 카메라
심사가 끝나면 이 자리에 App Store 링크를 답니다. 개인정보 처리 방침은 이 사이트의 처리방침 페이지에서 볼 수 있습니다.

촬영한 뒤에 씌우는 필터가 아닙니다. 빛이 공기에서 유리로, 다시 공기로 꺾이는 굴절을 매 프레임 계산해 미리보기에 그립니다. 그래서 유리를 조금 두껍게 하거나 셀을 조금 키우면 장면이 통째로 달라지고, 화면에 보이는 그대로 사진과 동영상이 됩니다. 계산은 아이폰의 GPU에서 끝나고 계정도 네트워크도 필요 없습니다. SwiftUI와 AVFoundation, Metal로 만들었고 외부 패키지를 하나도 쓰지 않습니다.
셀마다 높이가 이어지는 유리판을 세우고, 공기에서 유리로 들어갔다 나오는 두 번의 굴절을 스넬 법칙으로 푼다. 경계의 반사량은 프레넬 식으로 구한다. 평균색 모자이크나 그려 넣은 격자가 아니다.
넓은 사각 면이 부드럽게 이어지는 쿼드라, 굵은 십자 리브가 규칙적으로 지나가는 Cross Large, 대각선 면이 장면을 비스듬히 자르는 다이아몬드. 패턴을 바꿔도 맞춰 둔 다이얼 값은 그대로 둔다.
셀 크기, 굴곡, 모서리 둥글기, 두께, 경계 굴곡, 반사 밝기를 손끝으로 돌려 맞춘다. 조절 영역이 미리보기 아래에 있어 피사체를 가리지 않는다. 값은 저장되고 전체 초기화 한 번으로 처음으로 돌아간다.
원본 버튼을 누르면 유리 없는 장면이 바로 나온다. 두 번 눌러 무엇이 달라졌는지 확인한다.
1080×1440 H.264로 녹화하면서 패턴과 다이얼을 바꿀 수 있고, 바뀌는 과정이 그대로 영상에 담긴다. 마이크를 허용하면 소리도 함께 들어간다.
셔터는 마지막으로 제출된 재질 상태를 찍는다. 이후 다이얼을 움직여도 이미 찍은 사진은 변하지 않는다. 쓴 재질과 해시, 추정 형상, 반사 조명이 합성이라는 사실을 JPEG 메타데이터에 남긴다.



MAKING NOTES
처음 계획은 초타원 렌즈알을 격자로 까는 것이었는데, 처음 렌더한 결과가 부풀린 유리 단추 같았다. 셀마다 따로 놓는 대신 높이가 이어지는 한 장의 판으로 바꾸고 나서야 참고 사진의 결이 나왔다.
셀마다 기울기를 따로 구하면 맞닿는 선에서 상이 어긋난다. 이웃한 셀이 경계의 기울기를 공유하게 하고 밉맵을 비등방으로 걸어, 넓은 면은 남기고 이음매만 눌렀다.
미리보기용과 저장용 셰이더를 따로 두면 둘이 어긋나는 날이 온다. 하나로 합치고, 미리보기는 GPU 명령을 한 번에 하나만 띄워 프레임이 밀리지 않게 했다. 재질을 바꿔도 셰이더를 다시 컴파일하지 않는다.
결과물을 먼저 앱 안에 원자적으로 쓰고 나서 사진 보관함에 넣는다. 보관함 쪽이 실패해도 방금 찍은 것은 남아 있고, 다시 저장하거나 공유할 수 있다.
다이얼을 돌리면 그 시점부터 인코딩되는 프레임에 바로 반영된다. 열이나 부하로 프레임을 흘리더라도 촬영 시각은 유지해 영상 길이가 어긋나지 않게 했다.
스토어용 여섯 장은 UI 테스트를 시뮬레이터에서 돌려 만든다. 상태바를 9:41로 고정하고 샘플 사진을 띄운 뒤 1320×2868로 내보낸다. 이 페이지의 화면들도 같은 경로에서 나왔다.