first commit
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
# Depth 확장 구현 명세
|
||||
|
||||
## 판단과 범위
|
||||
|
||||
사용자 수정지시 원문은 `docs/depth-task-brief.txt`이다. 기존 main.ts 기반의 작은 앱을 유지하고, 조직만을 위한 SceneManager 등 전면 재구성은 하지 않는다. 현재 카메라도 실제로 이동하지만 피사체는 평면이며 Glass가 원본 이미지를 직접 읽는다. 이번 핵심은 이 두 지점을 depth mesh와 content render target으로 바꾸는 것이다. 기존 Mosaic의 셀별 normal/refract/lens variation은 보존한다.
|
||||
|
||||
첨부 사진의 깊이는 실측 또는 AI 추정 데이터가 없다. 따라서 테스트용 깊이는 사진을 직접 확인하여 만든 수작업 가상 깊이이며 UI/보고에서 이 사실을 밝힌다. 사용자 업로드에 샘플용 깊이를 적용하지 않는다. 업로드 후 깊이가 없으면 flat depth로 복귀한다. AI, segmentation, video depth estimation은 제외한다.
|
||||
|
||||
## 단계 1A: 샘플 깊이 자산
|
||||
|
||||
- 원본은 `public/assets/sample-pet.png` (415 × 739)를 그대로 사용한다.
|
||||
- 동일 크기 grayscale `public/assets/sample-pet-depth.png`와 재생성 가능한 작은 스크립트를 만든다. RGB 이미지 자체의 편집은 하지 않는다.
|
||||
- 좌표는 이미지 좌상단 원점이다. 사진을 직접 확인한 대략의 landmark: 코 (235,310), 왼쪽 눈 (198,278), 오른쪽 눈 (249,273), 얼굴 (221,267), 왼쪽 귀 (158,213), 오른쪽 귀 (262,206), 몸 (139,419). 좌우는 보는 사람 기준이다.
|
||||
- 0=뒤, 1=앞. 배경 약 .08, 몸 .30, 귀 .43, 얼굴 .60, 눈 .68, 주둥이 .82, 코 .98을 목표로 부드러운 타원/마스크를 합성한다. 단순 전체 gradient나 코와 눈이 같은 plateau인 map은 피한다. 겹친 영역의 최종 깊이를 실제 PNG에서 읽고 확인한다.
|
||||
- 얼굴/몸/귀의 크기를 사진에 맞춰 선택하고 타원 가장자리는 연속적으로 부드럽게 처리한다. 코와 눈은 별도의 작은 영역이며 사진 배경을 과도하게 앞으로 끌어오지 않는다.
|
||||
- CPU 측정과 shader에서 같은 좌표/값을 사용할 수 있도록 landmark 좌표와 grayscale 값을 보고한다. 이미지 상단 y와 texture UV의 v 반전을 명확히 한다.
|
||||
|
||||
## 단계 1B: Glass OFF 깊이 구현
|
||||
|
||||
이 단계에서는 RenderTarget과 Glass shader 변경을 금지한다. 검증 통과 후 별도 단계로 연결한다.
|
||||
|
||||
1. `DepthProvider`와 static loader를 최소한으로 추가한다. 입력은 별도 depth 이미지와 샘플 pair이며, 내부 depth texture는 NoColorSpace / 0뒤1앞이다. grayscale 및 필요 시 invert UI로 규칙을 명확히 한다. RGB와 depth의 aspect가 다르면 사용자가 알 수 있는 오류를 표시한다. async stale 요청을 무시하고 교체/실패/HMR에서 texture 및 object URL을 정리한다.
|
||||
2. `PetDepthMesh`를 추가한다. PlaneGeometry(1,1,128,128), RGB texture, depth texture, ShaderMaterial을 갖는다. vertex shader에서 z += (depth - bias) * scale을 실제로 적용한다. fragment는 RGB를 읽고 출력 색공간 처리를 한다. RGB는 sRGB, depth는 비색상 데이터다. 기존 VideoTexture는 flat depth 또는 명시 업로드한 static depth로 지원한다.
|
||||
3. Depth scale 기본 .25, 범위 0~.4. bias는 .08 정도의 고정값도 충분하다. 미디어 contain 계산은 기존 resize를 이용하고 z축 scale은 1을 유지한다. 기존 flat pet을 RGB/debug 또는 fallback으로 활용해도 된다.
|
||||
4. View mode: Final(기존 Glass 경로, 임시), RGB(평면 원본), Depth(평면 grayscale map), No Glass(depth mesh). 샘플 로드 시 No Glass를 선택해 단계 목표를 바로 보이게 한다. Depth view는 조명/굴절 없이 map을 확인할 수 있어야 한다.
|
||||
5. camera offset UI 기본 .3, 최대 .6, z=3, lookAt(0,0,0). 기존 target/current 보간, pointer, gyro, sensitivity/reset은 유지한다. viewOffset은 현 Glass용 보조 입력으로 그대로 남긴다. 실제 parallax 검증은 No Glass 경로만 대상으로 한다.
|
||||
6. 사진/영상 업로드와 sample pair 전환에서 이전 sample depth가 새 미디어에 남지 않게 한다. sample pair load도 기존 loader의 request lifetime과 충돌하지 않도록 하나의 로딩 경로를 재사용한다.
|
||||
|
||||
### 단계 1 게이트
|
||||
|
||||
- `npm run build` 통과를 기록한다. 이는 시각 동작 검증을 대체하지 않는다.
|
||||
- 실제 브라우저에서 샘플 RGB/Depth/No Glass를 확인한다. No Glass, scale .3, 카메라 왼쪽/중앙/오른쪽 이미지를 캡처한다. depth 0에서도 동일 카메라 조건을 캡처한다.
|
||||
- landmark별 실제 map 값을 읽고 world 위치 및 camera projection으로 CSS pixel 위치를 측정한다. mesh local x=u-.5, y=.5-yTop, z=(d-bias)*scale에 실제 mesh transform을 적용하고, 현재 camera matrix로 project한다. 측정에 사용한 depth 샘플링은 GPU linear sampling 및 UV 방향과 일치해야 한다.
|
||||
- 각 landmark i의 좌우 이동 D_i(scale)=x_i(right)-x_i(left)를 얻는다. depth로 추가된 이동 E_i=D_i(.3)-D_i(0)를 기록한다. flat 상태에서도 perspective/lookAt 때문에 영역별 움직임이 조금 다르므로 raw 이동만으로 성공을 주장하지 않는다.
|
||||
- 코-눈 평균 및 코-몸의 상대 이동 차이 E_nose-E_eyes, E_nose-E_body를 기록한다. 의도한 방향에서 코가 눈보다, 눈이 몸보다 크게 추가 이동해야 한다. 800px 안팎의 데스크톱 canvas에서 코-눈 상대 차이 절댓값 1 CSS px 이상을 목표로 하고 값이 작으면 map/offset을 허용 범위 안에서 조정한다. 코/눈/몸의 차이를 화면에서도 확인해야 한다.
|
||||
- scale 0에서 displaced mesh가 RGB와 맞고 Depth map의 코/눈/귀/몸 위치가 원본과 정렬되는지 확인한다. 정상 이미지 로딩, flat fallback, video 유지와 반복 콘솔 오류 없음도 확인한다.
|
||||
- 통과 판정 이전에는 단계 2를 구현하지 않는다.
|
||||
|
||||
## 단계 2: Content → RenderTarget → 기존 Glass
|
||||
|
||||
단계 1 통과 후 수행한다.
|
||||
|
||||
- contentScene에 depth mesh/배경을 두고 실제 이동 camera로 renderTarget에 렌더한다. 화면 출력을 위한 glassScene 또는 fullscreen surface는 별도로 둔다. contentScene에 glass 자체를 넣지 않아 feedback을 방지한다.
|
||||
- renderer/RT DPR을 최대 1.5로 제한하고 resize 시 실제 drawing buffer size에 맞춘다. target은 교체/teardown에서 dispose한다.
|
||||
- 기존 Mosaic 셀별 lens normal, variation, refract, viewOffset 보조 효과를 유지한다. Reel/Frosted도 source sampling만 scene texture로 전환한다. 새 입력 이름은 uSceneTexture 권장.
|
||||
- renderTarget은 전체 viewport 이미지이다. 기존 hitUv의 pet-local UV를 그대로 RT UV로 사용하면 contain/카메라 이동이 어긋난다. world hit를 현재 content camera의 view-projection matrix로 투영하거나 screen-space straight UV + projection된 refracted displacement로 바꾼다. strength=0에서 screen pixel의 원본 scene 결과가 정확히 유지되는 것을 기준으로 삼는다.
|
||||
- fullscreen quad를 택하면 실제 content camera 정보/virtual glass plane ray를 명시적으로 제공한다. post camera의 cameraPosition을 content camera로 잘못 사용하는 일이 없어야 한다. world-space GlassPlane을 유지하면 glass가 maximum displaced mesh보다 앞에 있도록 배치하고 나머지 화면에도 content가 보이게 한다.
|
||||
- RT의 linear color를 glass에서 다시 sRGB decode하지 않는다. video decode는 content 단계에서 끝낸다. 최종 screen 출력만 colorspace 변환한다. 밝기/색이 No Glass와 strength0 Final에서 일치해야 한다.
|
||||
- Final은 새 2-pass 결과, No Glass는 직접 content 렌더, RGB는 평면, Depth는 map, Glass Only는 중립 배경 위 lens 패턴의 진단이다. gridSize도 UI에 노출한다.
|
||||
|
||||
### 최종 검증
|
||||
|
||||
- stage1 parallax 게이트 재확인, Mosaic에서 좌우 이동 시 코/눈이 셀 안에서 달라지는 실제 화면 확인.
|
||||
- strength0 Final vs No Glass의 정렬/색 일치, 세 효과 모두 scene target sampling 확인.
|
||||
- 데스크톱/모바일 contain, resize, 사진 업로드→sample→video→image 전환, depth 교체, reset, build 및 반복 콘솔 오류 확인.
|
||||
- 보고: 수정/신규 파일, depth 규칙과 수작업 한계, 128 mesh 및 z displacement, camera 이동, 2-pass와 lens 보존, 측정 결과, 실행 방법, 미실행 검증, AI provider를 교체할 위치를 간단히 정리한다.
|
||||
Reference in New Issue
Block a user