904 lines
16 KiB
Plaintext
904 lines
16 KiB
Plaintext
[수정 작업지시서]
|
|
프로젝트명
|
|
Pet Glass / Pet Behind Glass
|
|
|
|
수정 목적
|
|
현재 진행 중인 구현은
|
|
"PetPlane 평면 Texture + GlassPlane Shader + viewOffset 기반 UV 왜곡"
|
|
방식으로 구성되어 있다.
|
|
|
|
하지만 이 방식만으로는
|
|
실제 사진에서 보이는 핵심 시각효과를 충분히 재현하기 어렵다.
|
|
|
|
실제 모자이크/굴절 유리에서 재미있는 변화는
|
|
유리 뒤 피사체의 눈, 코, 얼굴, 몸 등이 서로 다른 깊이에 있기 때문에
|
|
관찰 시점이 변할 때 각 부분이 서로 다른 위치로 보이는 데서 발생한다.
|
|
|
|
따라서 기존 구조를 전면 폐기하지 말고,
|
|
현재 구현을 기반으로 아래 방향으로 확장한다.
|
|
|
|
|
|
========================================
|
|
1. 핵심 변경사항
|
|
========================================
|
|
|
|
기존:
|
|
|
|
Camera
|
|
↓
|
|
Glass Plane
|
|
↓
|
|
Pet Plane (완전한 평면)
|
|
|
|
+
|
|
Pointer 위치를 uViewOffset으로 Shader에 전달
|
|
+
|
|
UV sampling 위치를 인위적으로 이동
|
|
|
|
|
|
변경:
|
|
|
|
Camera
|
|
↓
|
|
Glass Surface
|
|
↓
|
|
Depth-displaced Pet Mesh
|
|
↓
|
|
Background
|
|
|
|
즉,
|
|
Pet 이미지를 단순 평면으로 두지 않고
|
|
Depth Map을 이용하여 얕은 3D 형태의 Mesh로 변환한다.
|
|
|
|
카메라 이동에 따라
|
|
실제 perspective/parallax가 발생하도록 만들고,
|
|
Glass Shader는 이 결과를 굴절시킨다.
|
|
|
|
|
|
========================================
|
|
2. 기존 코드 유지 원칙
|
|
========================================
|
|
|
|
현재 작성된 코드를 전부 다시 만들지 않는다.
|
|
|
|
가능하면 다음 구조는 유지:
|
|
|
|
- SceneManager
|
|
- CameraController
|
|
- RendererManager
|
|
- MediaLoader
|
|
- PointerController
|
|
- GyroController
|
|
- GlassPlane
|
|
- 기존 UI
|
|
- 기존 Mosaic/Reeded/Frosted shader
|
|
|
|
수정 핵심은:
|
|
|
|
PetPlane
|
|
→
|
|
PetDepthMesh
|
|
|
|
로 확장하는 것.
|
|
|
|
기존 PetPlane 구현은 필요하면 fallback 용도로 남겨도 된다.
|
|
|
|
|
|
========================================
|
|
3. 새 구조
|
|
========================================
|
|
|
|
권장 구조:
|
|
|
|
src/
|
|
├─ scene/
|
|
│ ├─ SceneManager.ts
|
|
│ ├─ CameraController.ts
|
|
│ └─ RendererManager.ts
|
|
├─ objects/
|
|
│ ├─ PetPlane.ts
|
|
│ ├─ PetDepthMesh.ts // 신규
|
|
│ ├─ BackgroundPlane.ts // 선택
|
|
│ └─ GlassPlane.ts
|
|
├─ depth/
|
|
│ ├─ DepthMapLoader.ts // 신규
|
|
│ ├─ DepthProcessor.ts // 신규
|
|
│ └─ DepthProvider.ts // 신규 interface
|
|
├─ shaders/
|
|
│ ├─ common.vert
|
|
│ ├─ petDepth.vert // 신규
|
|
│ ├─ petDepth.frag // 필요시
|
|
│ ├─ mosaic.frag
|
|
│ ├─ reeded.frag
|
|
│ └─ frosted.frag
|
|
├─ input/
|
|
│ ├─ MediaLoader.ts
|
|
│ ├─ PointerController.ts
|
|
│ └─ GyroController.ts
|
|
└─ types/
|
|
├─ glass.ts
|
|
└─ depth.ts // 신규
|
|
|
|
|
|
========================================
|
|
4. Depth Map 우선 구현 전략
|
|
========================================
|
|
|
|
1차 수정에서는
|
|
AI depth estimation을 즉시 통합하지 않아도 된다.
|
|
|
|
먼저 Depth Map이 이미 존재한다고 가정하고
|
|
렌더링 파이프라인부터 완성한다.
|
|
|
|
즉:
|
|
|
|
RGB Image
|
|
+
|
|
Depth Image
|
|
|
|
두 장을 입력받아
|
|
Depth 기반 2.5D Mesh가 정상 동작하도록 구현한다.
|
|
|
|
개발 테스트용으로:
|
|
|
|
assets/
|
|
├─ sample-pet.jpg
|
|
└─ sample-pet-depth.png
|
|
|
|
형태를 지원.
|
|
|
|
실제 depth 이미지 파일이 없으면
|
|
gradient 또는 procedural depth texture를 생성해서
|
|
기능 검증 가능하도록 한다.
|
|
|
|
|
|
========================================
|
|
5. PetDepthMesh 구현
|
|
========================================
|
|
|
|
기존 PlaneGeometry보다 segment 수가 많은
|
|
PlaneGeometry를 사용.
|
|
|
|
예:
|
|
|
|
new THREE.PlaneGeometry(
|
|
width,
|
|
height,
|
|
128,
|
|
128
|
|
)
|
|
|
|
또는
|
|
|
|
256 x 256
|
|
|
|
모바일 성능을 고려하여
|
|
기본값은 128x128 정도에서 시작.
|
|
|
|
PetDepthMesh는:
|
|
|
|
- RGB Texture
|
|
- Depth Texture
|
|
- ShaderMaterial
|
|
- depthScale
|
|
- depthBias
|
|
|
|
를 가진다.
|
|
|
|
|
|
========================================
|
|
6. PetDepth Vertex Shader
|
|
========================================
|
|
|
|
새 vertex shader를 작성.
|
|
|
|
목적:
|
|
Depth Map의 값을 읽어서
|
|
각 vertex를 Z 방향으로 이동.
|
|
|
|
개념:
|
|
|
|
uniform sampler2D uDepthMap;
|
|
uniform float uDepthScale;
|
|
uniform float uDepthBias;
|
|
|
|
varying vec2 vUv;
|
|
|
|
void main() {
|
|
vUv = uv;
|
|
|
|
float depth =
|
|
texture2D(uDepthMap, uv).r;
|
|
|
|
depth =
|
|
(depth - uDepthBias)
|
|
* uDepthScale;
|
|
|
|
vec3 displacedPosition =
|
|
position;
|
|
|
|
displacedPosition.z += depth;
|
|
|
|
gl_Position =
|
|
projectionMatrix
|
|
* modelViewMatrix
|
|
* vec4(displacedPosition, 1.0);
|
|
}
|
|
|
|
|
|
주의:
|
|
|
|
Depth Map에 따라
|
|
흰색이 가까운지,
|
|
검정이 가까운지는
|
|
DepthProvider 쪽에서 통일할 것.
|
|
|
|
내부 규칙:
|
|
|
|
0.0 = 뒤
|
|
1.0 = 앞
|
|
|
|
으로 통일 권장.
|
|
|
|
|
|
========================================
|
|
7. Depth Scale
|
|
========================================
|
|
|
|
UI에 Depth Strength 또는 Depth Scale 추가.
|
|
|
|
예:
|
|
|
|
Depth
|
|
[----------]
|
|
|
|
기본값:
|
|
0.15 ~ 0.3 정도
|
|
|
|
목표는
|
|
실제 3D 모델처럼 과도하게 튀어나오게 만드는 것이 아니라
|
|
카메라 좌우 이동 시
|
|
코/눈/얼굴 간 parallax가 눈에 보이는 수준.
|
|
|
|
Depth Scale이 너무 크면
|
|
사진이 고무판처럼 찌그러져 보이므로
|
|
최대값 제한.
|
|
|
|
|
|
========================================
|
|
8. Camera 이동 방식 수정
|
|
========================================
|
|
|
|
기존에는 Pointer 값을
|
|
Shader의 uViewOffset에 직접 사용하는 비중이 컸다.
|
|
|
|
이제는 실제 Camera 이동을 우선한다.
|
|
|
|
예:
|
|
|
|
targetCameraX =
|
|
normalizedPointerX * maxCameraOffset;
|
|
|
|
targetCameraY =
|
|
normalizedPointerY * maxCameraOffsetY;
|
|
|
|
camera.position.x = lerp(...)
|
|
camera.position.y = lerp(...)
|
|
|
|
camera.lookAt(targetLookAt)
|
|
|
|
시점 변화의 핵심은
|
|
실제 PerspectiveCamera 위치 변화로 발생해야 한다.
|
|
|
|
|
|
========================================
|
|
9. Shader uViewOffset 역할 변경
|
|
========================================
|
|
|
|
기존 uViewOffset은 완전히 제거하지 않는다.
|
|
|
|
다만 역할을 변경.
|
|
|
|
기존:
|
|
uViewOffset이 시점 변화를 거의 전부 흉내냄
|
|
|
|
수정:
|
|
실제 Camera 이동이 기본 시점 변화를 담당
|
|
|
|
uViewOffset:
|
|
유리 표면 자체의 굴절 변화 보조용
|
|
|
|
즉,
|
|
|
|
Camera movement
|
|
=
|
|
피사체의 parallax
|
|
|
|
Glass uViewOffset
|
|
=
|
|
유리 렌즈를 비스듬히 보는 효과
|
|
|
|
이 두 가지를 분리.
|
|
|
|
|
|
========================================
|
|
10. Mosaic Shader 수정 방향
|
|
========================================
|
|
|
|
현재 Mosaic Shader가
|
|
단순하게 texture UV를 grid 단위로 왜곡한다면
|
|
구조를 수정.
|
|
|
|
중요:
|
|
|
|
이제 Glass Shader가 직접 원본 petTexture만 sampling하는 구조는
|
|
가능하면 줄인다.
|
|
|
|
최종 목표는:
|
|
|
|
PetDepthMesh가 먼저
|
|
카메라 기준으로 렌더링되고,
|
|
|
|
Glass 효과는
|
|
그 렌더 결과를 굴절시키는 구조.
|
|
|
|
즉:
|
|
|
|
PetDepth Scene
|
|
↓
|
|
Render Target
|
|
↓
|
|
Glass Shader
|
|
↓
|
|
Screen
|
|
|
|
|
|
========================================
|
|
11. RenderTarget 기반 구조
|
|
========================================
|
|
|
|
가능하면 이번 수정에서
|
|
WebGLRenderTarget 기반 2-pass rendering을 도입.
|
|
|
|
권장 파이프라인:
|
|
|
|
Pass 1:
|
|
PetDepthMesh + Background 렌더링
|
|
→ RenderTarget
|
|
|
|
Pass 2:
|
|
GlassPlane 또는 Fullscreen Quad
|
|
→ RenderTarget texture를 입력받아
|
|
굴절 처리
|
|
→ Screen
|
|
|
|
|
|
구조:
|
|
|
|
Scene A
|
|
- PetDepthMesh
|
|
- Background
|
|
|
|
↓ render
|
|
|
|
THREE.WebGLRenderTarget
|
|
|
|
↓ texture
|
|
|
|
Scene B
|
|
- Glass surface / fullscreen plane
|
|
|
|
↓ render
|
|
|
|
Screen
|
|
|
|
|
|
이 방식이 중요한 이유:
|
|
|
|
Glass Shader가
|
|
"원본 사진 Texture"를 직접 왜곡하는 것이 아니라
|
|
|
|
현재 카메라 시점에서 이미
|
|
Depth / parallax가 반영된 장면을
|
|
굴절시키게 됨.
|
|
|
|
|
|
========================================
|
|
12. SceneManager 수정
|
|
========================================
|
|
|
|
SceneManager를 필요하면 아래와 같이 분리.
|
|
|
|
- contentScene
|
|
- glassScene
|
|
|
|
또는
|
|
|
|
- contentScene
|
|
- postProcessScene
|
|
|
|
예:
|
|
|
|
private contentScene: THREE.Scene;
|
|
private glassScene: THREE.Scene;
|
|
private renderTarget: THREE.WebGLRenderTarget;
|
|
|
|
render loop:
|
|
|
|
renderer.setRenderTarget(renderTarget);
|
|
renderer.render(contentScene, camera);
|
|
|
|
renderer.setRenderTarget(null);
|
|
glassMaterial.uniforms.uSceneTexture.value =
|
|
renderTarget.texture;
|
|
|
|
renderer.render(glassScene, postCamera);
|
|
|
|
|
|
========================================
|
|
13. Glass Shader 입력 변경
|
|
========================================
|
|
|
|
기존:
|
|
|
|
uTexture = Pet Texture
|
|
|
|
수정 권장:
|
|
|
|
uSceneTexture = RenderTarget Texture
|
|
|
|
예:
|
|
|
|
uniform sampler2D uSceneTexture;
|
|
|
|
vec4 color =
|
|
texture2D(
|
|
uSceneTexture,
|
|
refractedUv
|
|
);
|
|
|
|
|
|
이렇게 해야
|
|
Depth 기반 시점변화가 적용된 결과 전체가
|
|
유리를 통해 보임.
|
|
|
|
|
|
========================================
|
|
14. Mosaic Lens 모델
|
|
========================================
|
|
|
|
Mosaic 셀마다
|
|
작은 독립 lens처럼 동작시키는 방향은 유지.
|
|
|
|
다만 기존처럼
|
|
|
|
"cell마다 petTexture UV 이동"
|
|
|
|
이 아니라
|
|
|
|
"현재 camera view가 반영된 scene texture를
|
|
cell마다 다른 refracted UV로 sample"
|
|
|
|
하도록 변경.
|
|
|
|
핵심:
|
|
|
|
vec2 gridUv = vUv * uGridSize;
|
|
vec2 cell = floor(gridUv);
|
|
vec2 local = fract(gridUv);
|
|
|
|
vec2 centered =
|
|
local - 0.5;
|
|
|
|
lens distortion 계산
|
|
|
|
+
|
|
view-dependent refraction
|
|
|
|
↓
|
|
|
|
sample uSceneTexture
|
|
|
|
|
|
========================================
|
|
15. 실제 시점 변화 확인 기준
|
|
========================================
|
|
|
|
아래 현상이 실제로 보여야 한다.
|
|
|
|
예:
|
|
|
|
강아지 얼굴에서
|
|
|
|
코:
|
|
depth 값 큼
|
|
|
|
눈:
|
|
중간
|
|
|
|
귀:
|
|
조금 뒤
|
|
|
|
몸:
|
|
더 뒤
|
|
|
|
|
|
사용자가 카메라를 왼쪽으로 이동하면
|
|
|
|
코가 가장 크게 이동
|
|
|
|
눈이 그보다 작게 이동
|
|
|
|
귀/몸이 더 작게 이동
|
|
|
|
그 결과
|
|
모자이크 셀 안에서
|
|
눈과 코가 서로 다른 위치에 나타남.
|
|
|
|
|
|
이 현상이 나오지 않으면
|
|
이번 수정 목적을 달성한 것이 아님.
|
|
|
|
|
|
========================================
|
|
16. Depth Debug Mode 추가
|
|
========================================
|
|
|
|
개발 편의를 위해
|
|
Debug UI 추가.
|
|
|
|
옵션:
|
|
|
|
View Mode:
|
|
|
|
- Final
|
|
- RGB
|
|
- Depth
|
|
- No Glass
|
|
- Glass Only
|
|
|
|
특히 Depth Map을
|
|
화면에 직접 확인할 수 있어야 함.
|
|
|
|
또한:
|
|
|
|
- depthScale
|
|
- gridSize
|
|
- glassStrength
|
|
- cameraOffset
|
|
|
|
값을 실시간 조절 가능하게 한다.
|
|
|
|
|
|
========================================
|
|
17. Background 처리
|
|
========================================
|
|
|
|
1차 구현에서는
|
|
사진 전체를 하나의 Depth Mesh로 사용해도 됨.
|
|
|
|
다만 구조적으로 향후:
|
|
|
|
Background
|
|
+
|
|
Pet Foreground
|
|
|
|
분리가 가능하도록 작성.
|
|
|
|
향후 개선:
|
|
|
|
Pet segmentation mask
|
|
↓
|
|
Pet Depth Mesh
|
|
|
|
Background
|
|
↓
|
|
Separate plane
|
|
|
|
|
|
지금은 필수 구현 아님.
|
|
|
|
|
|
========================================
|
|
18. Depth Map 생성 방식
|
|
========================================
|
|
|
|
이번 수정 범위에서는
|
|
DepthProvider 인터페이스만 정의.
|
|
|
|
예:
|
|
|
|
interface DepthProvider {
|
|
getDepthMap(
|
|
image: HTMLImageElement
|
|
): Promise<THREE.Texture>;
|
|
}
|
|
|
|
|
|
구현체:
|
|
|
|
StaticDepthProvider
|
|
- 현재는 사용자가 제공한 depth 이미지
|
|
- 또는 test asset 사용
|
|
|
|
|
|
향후:
|
|
|
|
AiDepthProvider
|
|
- Depth Anything
|
|
- MiDaS
|
|
- DPT
|
|
- ONNX Runtime Web
|
|
- Transformers.js
|
|
|
|
등으로 교체할 수 있도록 구조화.
|
|
|
|
|
|
========================================
|
|
19. AI Depth Estimation은 후순위
|
|
========================================
|
|
|
|
이번 작업에서
|
|
AI 모델 integration 때문에
|
|
렌더링 구조 완성이 늦어지지 않도록 한다.
|
|
|
|
우선순위:
|
|
|
|
1.
|
|
RGB + Depth Texture 입력
|
|
|
|
2.
|
|
PetDepthMesh 생성
|
|
|
|
3.
|
|
Camera parallax 확인
|
|
|
|
4.
|
|
RenderTarget 생성
|
|
|
|
5.
|
|
Glass shader 적용
|
|
|
|
6.
|
|
실제 Mosaic 시점 변화 확인
|
|
|
|
7.
|
|
그 후 AI Depth Provider 검토
|
|
|
|
|
|
========================================
|
|
20. Video 처리
|
|
========================================
|
|
|
|
동영상은 이번 수정에서
|
|
기존 VideoTexture 기능을 유지.
|
|
|
|
단,
|
|
동영상에 대해 매 프레임 depth estimation하는 것은
|
|
이번 범위에서 제외.
|
|
|
|
Video는 우선:
|
|
|
|
- RGB VideoTexture
|
|
- Flat depth
|
|
또는
|
|
- 사용자가 지정한 static depth map
|
|
|
|
으로 처리 가능.
|
|
|
|
동영상 depth estimation은
|
|
향후 별도 기능으로 남긴다.
|
|
|
|
|
|
========================================
|
|
21. 성능
|
|
========================================
|
|
|
|
Depth Mesh segment는
|
|
모바일 성능을 고려.
|
|
|
|
기본:
|
|
|
|
128 x 128
|
|
|
|
선택적으로:
|
|
|
|
64 x 64
|
|
128 x 128
|
|
256 x 256
|
|
|
|
Quality 설정 가능하게 해도 됨.
|
|
|
|
RenderTarget resolution도
|
|
devicePixelRatio 그대로 쓰지 말고
|
|
성능을 고려해 제한.
|
|
|
|
예:
|
|
|
|
Math.min(
|
|
window.devicePixelRatio,
|
|
1.5
|
|
)
|
|
|
|
|
|
========================================
|
|
22. 모바일 시점 제한
|
|
========================================
|
|
|
|
사진 기반 2.5D이므로
|
|
과도한 시점 이동 금지.
|
|
|
|
카메라 좌우 회전/이동은
|
|
약 ±5° ~ ±15° 범위 느낌으로 제한.
|
|
|
|
목표는
|
|
|
|
"옆에서 보는 느낌"
|
|
|
|
이지
|
|
|
|
"사진 주변을 3D 모델처럼 회전"
|
|
|
|
하는 것이 아님.
|
|
|
|
|
|
========================================
|
|
23. 기존 효과 재검증
|
|
========================================
|
|
|
|
Mosaic:
|
|
가장 중요
|
|
|
|
Reeded:
|
|
RenderTarget texture를 대상으로
|
|
X 방향 굴절
|
|
|
|
Frosted:
|
|
RenderTarget texture를 대상으로
|
|
blur/noise distortion
|
|
|
|
|
|
모든 효과는
|
|
원본 Texture가 아니라
|
|
가능하면 Scene RenderTarget을 기준으로 동작하도록 변경.
|
|
|
|
|
|
========================================
|
|
24. 완료 기준
|
|
========================================
|
|
|
|
수정 작업 완료 조건:
|
|
|
|
1.
|
|
기존 프로젝트가 정상 실행됨
|
|
|
|
2.
|
|
RGB Texture 로딩 가능
|
|
|
|
3.
|
|
Depth Texture 로딩 가능
|
|
|
|
4.
|
|
PetDepthMesh 생성됨
|
|
|
|
5.
|
|
Depth Map에 따라 Z displacement가 실제 적용됨
|
|
|
|
6.
|
|
Glass OFF 상태에서
|
|
카메라 좌우 이동 시
|
|
피사체 내부에 parallax가 보임
|
|
|
|
7.
|
|
코/눈/몸처럼 서로 다른 depth 영역이
|
|
다르게 이동함
|
|
|
|
8.
|
|
RenderTarget 기반 2-pass 구조 적용
|
|
|
|
9.
|
|
Mosaic Glass가
|
|
RenderTarget texture를 굴절시킴
|
|
|
|
10.
|
|
카메라 이동 시
|
|
Mosaic 셀 내부에 보이는 피사체가 동적으로 변경됨
|
|
|
|
11.
|
|
기존 단순 UV translate보다
|
|
확실한 깊이감 차이가 보임
|
|
|
|
12.
|
|
Depth Scale UI 동작
|
|
|
|
13.
|
|
Debug Depth View 제공
|
|
|
|
14.
|
|
기존 사진 업로드 기능 유지
|
|
|
|
15.
|
|
기존 동영상 기능이 깨지지 않음
|
|
|
|
16.
|
|
TypeScript 오류 없음
|
|
|
|
17.
|
|
콘솔 반복 오류 없음
|
|
|
|
|
|
========================================
|
|
25. 이번 수정에서 하지 않을 것
|
|
========================================
|
|
|
|
이번 작업에서는 아래는 후순위로 둔다.
|
|
|
|
- 완전한 3D pet reconstruction
|
|
- NeRF
|
|
- Gaussian Splatting
|
|
- multi-view reconstruction
|
|
- 실시간 video depth estimation
|
|
- 서버 AI 구축
|
|
- 복잡한 segmentation
|
|
- 물리적으로 완벽한 ray tracing
|
|
|
|
목표는
|
|
Monocular Depth 기반 2.5D로
|
|
실제 사진에서 느껴지는
|
|
"눈/코/얼굴의 서로 다른 깊이에 따른
|
|
시점별 유리 굴절 변화"
|
|
를 재현하는 것.
|
|
|
|
|
|
========================================
|
|
26. 가장 중요한 검증 포인트
|
|
========================================
|
|
|
|
이번 수정의 핵심은 아래다.
|
|
|
|
기존:
|
|
|
|
사진 전체가 평면이므로
|
|
카메라를 움직여도
|
|
눈/코/얼굴이 사실상 같은 깊이로 움직임.
|
|
|
|
수정 후:
|
|
|
|
Depth Map으로
|
|
코/눈/얼굴/몸의 Z 위치가 달라지고,
|
|
|
|
카메라 이동 시
|
|
각 영역에 서로 다른 parallax가 발생하며,
|
|
|
|
그 결과를
|
|
Mosaic Glass가 다시 굴절시킨다.
|
|
|
|
|
|
즉,
|
|
|
|
Depth
|
|
+
|
|
Perspective
|
|
+
|
|
Glass Refraction
|
|
|
|
세 요소가 실제로 연결되어야 한다.
|
|
|
|
|
|
========================================
|
|
27. 작업 완료 후 보고
|
|
========================================
|
|
|
|
작업 완료 후 아래를 정리해서 보고한다.
|
|
|
|
- 수정한 파일 목록
|
|
- 신규 파일 목록
|
|
- 기존 구조에서 변경된 부분
|
|
- PetDepthMesh 구현 방식
|
|
- RenderTarget 구성 방식
|
|
- Camera 이동 방식
|
|
- Mosaic Shader 변경점
|
|
- Depth Map 규칙
|
|
- 현재 한계
|
|
- AI Depth Estimation을 붙일 위치
|
|
- 다음 작업 추천 |