// data.jsx — Portfolio project data for 방명환 · Change & Adapt
// Each project: meta + an array of image slides (captioned). The detail viewer
// prepends a "cover" overview slide automatically, so slide images here are the
// actual work shots.

const PROJECTS = [
  {
    id: "postprocess-helper",
    category: "Tech",
    title: "PostProcess Helper\n포스트프로세스·콘솔 통합 제어 패널",
    year: "2026",
    discipline: "Tools · Pipeline",
    role: "기획 · 개발 · 배포 단독 진행\nEditor Utility Widget + Python",
    tools: ["Unreal Engine 5.7", "Vibe Coding", "Python"],
    tagline: "흩어진 포스트프로세스·콘솔 설정을 하나의 패널에서 다룹니다.",
    description:
      "언리얼엔진에서 작업하며 PostProcess설정값들을 미세조정하고,\n\"그때 썼던 그 콘솔 명령어가 뭐였지\" 찾아 다니는 것까지가 작업의 일부였습니다.\n\nPostProcess Helper는 PostProcessVolume, 콘솔 커맨드, 레벨별 설정, 텍스처 메모리 관리까지\n더 나은 Look을 만들고 최적화하는 작업에 필요한 설정을 하나의 패널로 모은 에디터 전용 도구입니다.\n자주 쓰는 항목들을 목록화 해 여기저기 찾는 수고를 줄이고,\n적절한 권장값으로 원클릭 수치 변경이 가능하고, 엔진에 즉시 적용됩니다.\n\n언리얼엔진에 익숙하지 않아도 수준 이상의 룩을 다루며 최적화할 수 있고,\n항목마다 친절한 툴팁과 권장값 설명을 함께 설계했습니다.",
    slides: [
      {
        type: "split", media: "left",
        label: "PostProcess Helper 패널 전체 UI",
        heading: "하나의 패널, 6개 섹션",
        body: "여러 메뉴에 흩어져 있고 콘솔 명령으로 숨겨져있던 렌더링 관련 설정을 6개 섹션으로 정리해 한 패널에 모았습니다.\n현재 적용된 수치값들을 보여주는 즉시 Current Values는 갱신되므로,\n방금 바꾼 값이 실제로 적용됐는지 따로 확인할 필요가 없습니다.",
        points: [
          "Current Values · PostProcessVolume · Console Command",
          "XR 최적화 · 텍스처 스트리밍 풀 · 레벨별 콘솔 값",
          "섹션별 접기/펼치기 + 스크롤로 긴 목록 탐색",
        ],
      },
      {
        type: "split", media: "left",
        label: "PPV 생성 버튼 + 15종 제어 항목",
        heading: "PostProcessVolume\n원클릭 생성&적용",
        body: "PostProcessVolume을 매번 직접 배치하고 초기 설정은 잡는 일은\n지루하고 현학적입니다.\n이제 버튼 하나로 볼륨을 생성하고 패널 값을 곧바로 적용합니다.\n매번 체크하기 귀찮았던 무한규모(언바운드)는\n자동으로 활성화되며 생성됩니다.",
        points: [
          "적정값으로 설정된 Bloom · Exposure(자동 노출 범위·측정 방식)",
          "적정값으로 설정된 Film 톤 커브 — Slope / Toe / Shoulder / White Clip",
          "적정값으로 설정된 Lumen GI 품질 · Ambient Occlusion 강도·반경",
          "그 외 제어 가능한 PPV 항목 총 15종",
        ],
      },
      {
        type: "split", media: "left",
        label: "콘솔 항목 스핀박스 + 초기/적정/최대 프리셋 버튼",
        heading: "콘솔 커맨드 실시간 제어",
        body: "외워도 자꾸 까먹는 콘솔 커맨드, \"딸깍\"으로 간편하게 조절하세요.\n렌더 해상도, 그림자 거리, 블룸 품질을 비롯한 9종의 콘솔 변수(r.*)를 패널에서 바로 조절합니다.\n값을 바꾸면 엔진에 즉시 반영되고, 적정값을 판단하기 어려울 때는\n검증해 둔 초기값·적정값·최대값으로 한 번에 조절할 수 있습니다.",
        points: [
          "렌더 해상도 비율 · 톤매퍼 샤프닝 · 그림자 거리 배율",
          "AO 방식(SSAO/GTAO) · 블룸·모션블러·눈순응 품질",
          "볼류메트릭 포그 · 라이트 샤프트 ON/OFF",
          "제어 가능한 콘솔 항목 총 9종",
        ],
      },
      {
        type: "split", media: "left",
        label: "레벨별 콘솔 값 섹션 — 저장 / 불러오기 버튼",
        heading: "레벨별 콘솔 값 저장·복원",
        body: "레벨마다 필요한 렌더링 설정은 다르기 마련이고\n애써 세팅해둔 콘솔 값은 다른 레벨을 열고 다시 돌아오면\n초기화 되어있습니다.\n\n현재 콘솔 값을 레벨 이름으로 저장해 두면,\n레벨을 전환할 때 저장된 설정이 자동으로 복원됩니다.",
        points: [
          "저장 / 불러오기 / 레벨 전환 시 자동 복원",
          "Saved/PPH_LevelConsole/ 안에 JSON으로 안전하게 보관",
        ],
      },
      {
        type: "split", media: "left",
        label: "텍스처 스트리밍 풀 섹션 — 감지된 VRAM · 권장 풀 크기",
        heading: "텍스처 스트리밍 풀 개선",
        body: "'텍스처 스트리밍 풀 예산 초과' 경고는\n작업 중 자주 마주치게되는 반갑지 않은 친구입니다.\n하지만 이제 시스템 레지스트리에서 GPU VRAM을 읽어\n권장 풀 크기, 즉 전체 VRAM의 절반을 계산합니다.\n물론 풀 개선 이전 텍스처 최적화가 더 중요하기때문에,\n그에 대한 설명도 함께 첨부해됐습니다.",
        points: [
          "컴퓨터에 장착된 그래픽카드의 VRAM 정보를 불러와 자동으로 계산",
          "한번에 적정 VRAM값으로 변경 가능",
        ],
      },
      {
        type: "split", media: "left",
        label: "항목 위 마우스오버 시 뜨는 한국어 툴팁",
        heading: "여러분을 위한 항목별 툴팁? 꿀팁!",
        body: "이 명령이 어떤 기능을 하는지 모두 외우고 사용하긴 정말 어렵습니다.\n각 항목마다 마우스를 올리면 어떤 기능을 하는지에 대한 설명과 함께\n엔진 초기값, 권장값, 성능 영향을 쉬운 용어로 설명합니다.\n도구를 쓰면서 자연스럽게 학습이 되도록 설계했습니다.",
        points: [
          "역할 · 초기값 · 권장값 · 성능 영향을 한 번에",
          "도구가 곧 학습 자료가 되도록 설계",
        ],
      },
    ],
  },
  {
    id: "sequence-controller",
    category: "Tech",
    title: "Sequence Controller\n생방송용 시퀀서 컨트롤 블루프린트",
    year: "2026",
    discipline: "Tools · Realtime",
    role: "기획 · 개발 · 배포 단독 진행",
    tools: ["Unreal Engine 5.7", "Blueprint", "Vibe Coding"],
    tagline: "정해진 지점에서 자동으로 일시정지하는 시퀀서 구현",
    description:
      "뉴스, 선거방송, 중계방송 등 생방송 상황에서는\n정해진 타이밍 혹은 큐 신호에 맞춰 그래픽 연출을 재생/일시정지하며 순간을 연출하게 됩니다.\nSequence Controller는 그 흐름을 안전하게 제어하는 목적으로 제작된 블루프린트 도구입니다.\n\n디자이너가 시퀀서 작업을 하며 멈춰야 할 위치를 미리 마킹해두면\n생방송 중 해당 위치에 다다를때마다 자동으로 일시정지되는 기능을 가지고 있습니다.\n사람의 실수에 의한 '휴먼 에러'를 미연에 방지할 수 있는 안전장치입니다.\n\n오퍼레이터는 방송사고의 위험을 짊어지고 절묘한 타이밍에 일시정지 차력쇼를 하는\n위험한 곡예를 더이상 하지 않아도 될 지 모릅니다.",
    slides: [
      {
        type: "split", media: "left",
        label: "시퀀서 마커 → 자동 정지점 인식",
        heading: "안전제일 일시정지",
        body: "라이브는 한 번의 실수가 곧 방송 사고로 이어집니다.\n타임코드를 수동 입력하거나 타임라인을 직접 일시정지하는 방식은\n정밀하지도, 안전하지도 않습니다.\n그래서 시퀀서의 마커를 '일시정지의 기준'으로 삼았습니다.",
        points: [
          "디자이너가 멈출 지점마다 마커 배치",
          "블루프린트가 런타임 중 마커를 읽어 정지점 자동 구성",
          "마커를 추가·이동·삭제하거나 시퀀스를 교체해도 수정 불필요",
        ],
      },
      {
        type: "split", media: "left",
        label: "단축키 4동작 — 재생 / 되감기 / 처음으로 / 긴급정지",
        heading: "시퀀서, 야호-!",
        body: "정해진 마킹 지점까지 재생되면 시퀀서는 자동으로 일시정지 됩니다.\n생방송 상황에서 오퍼레이터가 해야 할 일은\n큐 사인에 맞춰 재생을 누르는 것 하나뿐입니다.\n하지만 리허설 중 시퀀서를 앞,뒤로 재생하거나\n긴급상황을 대비한 일시정지 버튼까지 모두 할당할 수 있습니다.",
        points: [
          "재생 : 다음 마킹 지점까지 재생 후 자동 일시정지",
          "되감기 : 현재 위치 기준 이전 마커로 역방향 재생",
          "처음으로 : 시퀀스 시작 지점으로 즉시 이동",
          "긴급 일시정지 : 재생 도중 어디서든 즉시 멈춤",
        ],
      },
      {
        type: "split", media: "left",
        label: "엣지 케이스까지 차단한 안전 설계",
        heading: "실수를 시스템으로 막는다",
        body: "단순히 '동작하는 것'을 넘어,\n라이브에서 사고가 날 수 있는 지점들을 의도적으로 차단했습니다.",
        points: [
          "모든 단축키 기본값 None : 인스턴스 간 충돌 원천 차단",
          "라이브 시작 시 시퀀스를 초기 위치로 자동 리셋",
          "끝 도달 시 마지막 프레임 유지 (시작점으로 되돌아가지 않음)",
          "긴급 정지 후 재생은 향하던 마커로 정확히 이어짐",
        ],
      },
      {
        type: "split", media: "left",
        label: "구조 — WasHotkeyPressed → PlayTo(Frame) → OnPause",
        heading: "무한한 확장성 저 너머로",
        body: "Ctrl · Alt · Shift 조합키로 다양한 단축키 활용 가능\n키보드 단축키 이외에도 마우스, 컨트롤러 등\n다양한 디바이스를 지원합니다.",
        points: [
          "추후 생방송 전용 컨트롤러 구축 시 확장성까지 고려",
          "테스트, 리허설, 생방송 등 다양한 환경에 맞춰 유동적으로 변경 가능",
        ],
      },
    ],
  },
  {
    id: "bang-toolbox",
    category: "Tech",
    title: "BANG_Toolbox\n애프터이펙트 기능성 도구모음",
    year: "2025",
    discipline: "Tools · Motion",
    role: "기획 · 개발 · 배포 단독 진행",
    tools: ["JavaScript", "Vibe Coding"],
    tagline: "매번 반복하던 클릭, 버튼 하나로.",
    description:
      "이 플러그인은 바이브코딩 등장 초기, AI를 활용해 어느정도 수준의 소프트웨어 제작이 가능한지\n테스트하기위한 첫번째 프로젝트의 결과입니다.\n사용이 익숙한 기능의 구현, 확실한 작업 효율성 개선을 목표로 삼고 개발했습니다.\n\n에프터이펙트를 사용해 그래픽 작업을 할 때 매번 반복되는 단순 작업이 있습니다.\nNull 레이어를 만들어 Parent로 묶고, 앵커포인트를 옮기고, 화면 색을 뽑는 일들...\n하나하나는 사소하지만 하루에도 수십 번, 그때마다 여러 번의 클릭과 메뉴 탐색을 요구합니다.\nBANG_Toolbox는 그 마찰을 없애기 위해 직접 제작한 플러그인입니다.",
    slides: [
      {
        type: "split", media: "left",
        label: "Green Null — 원클릭 Parent Null 생성",
        heading: "아는 맛이 무섭다",
        body: "BANG_Toolbox의 기능들은\n기존 에프터이펙트에서 많이 사용하는 플러그인과 같은 기능을 합니다.\n하지만 구현 알고리즘과 세세한 편의성에서 차별을 두고 있습니다.\n그리고 자주 쓰는 기능들을 한 플러그인 공간 안에 압축함으로\nUI 공간 활용 면에서도 득을 볼 수 있습니다.",
        points: [
          "Null 소스를 최초 1회만 생성, 솔리드 폴더 오염 없음",
          "없으면 아쉬운 앵커포인트 변경",
          "에펙에 왜 이게 없었지? Color Picker",
        ],
      },
      {
        type: "split", media: "left",
        label: "Anchor Point — 3×3 그리드 앵커 이동",
        heading: "움직이지 않는 앵커 이동",
        body: "3×3 그리드 버튼으로 앵커포인트를\n9개 기준점 중 하나로 즉시 옮깁니다.\n앵커가 이동해도 레이어는 화면에서 한 픽셀도 움직이지 않습니다.",
        points: [
          "sourceRectAtTime()으로 바운딩 박스 정밀 계산",
          "Scale · Z-Rotation을 반영한 Position 자동 보정",
          "다중 레이어 동시 처리 · 단일 Undo 그룹",
        ],
      },
      {
        type: "split", media: "left",
        label: "Color Picker — 네이티브 피커 + 히스토리",
        heading: "포토샵에서 쓰던 그 맛",
        body: "AE 네이티브 컬러 피커(스포이드 포함)를 패널에서 바로 호출하고,\n결과값을 HEX · RGB · HSB로 동시에 표시합니다.",
        points: [
          "빈 Dummy Comp를 만들어 색상을 입히는 알고리즘으로 구현",
          "에프터이펙트 바깥쪽의 색상도 선택 가능",
          "색상 히스토리 최대 8슬롯, LocalStorage 영속 저장",
        ],
      },
    ],
  },
  {
    id: "broadcast-graphics",
    category: "Tech",
    title: "실시간 방송 뉴스그래픽 시스템",
    year: "2023",
    discipline: "Realtime · Broadcast",
    role: "Realtime Graphics TA — 생방송용 그래픽 템플릿·연동 구축",
    tools: ["Unreal Engine", "nDisplay", "Notch", "After Effects"],
    tagline: "데이터가 들어오면 그대로 방송에 나가는 실시간 그래픽",
    description:
      "선거·스포츠 등 생방송에서 실시간 데이터를 받아 즉시 렌더링되는 뉴스그래픽 시스템을 구축했습니다. 운영진이 코드 없이 수치를 바꾸면 화면에 반영되도록 템플릿화하고, LED 월·AR과의 연동까지 안정적으로 동작하도록 했습니다.",
    slides: [
      {
        type: "split", media: "left",
        label: "선거 개표 실시간 그래픽",
        heading: "실시간 데이터 그래픽",
        body: "외부 데이터 피드를 받아 차트가 실시간으로 갱신·애니메이션되도록\n구성했습니다.",
        points: [
          "데이터 입력 즉시 화면 반영",
          "생방송 중에도 안정적 갱신",
        ],
      },
      {
        type: "split", media: "left",
        label: "AR 스튜디오 합성 샷",
        heading: "AR 스튜디오 합성",
        body: "카메라 트래킹 데이터를 기반으로 AR 그래픽을\n실제 스튜디오 영상에 합성했습니다.",
        points: [
          "카메라 트래킹 연동",
          "실사와 자연스러운 합성",
        ],
      },
      {
        type: "split", media: "left",
        label: "LED 월 백그라운드",
        heading: "LED 월 백그라운드",
        body: "nDisplay로 여러 디스플레이를 동기화해\n대형 LED 월 배경을 끊김 없이 출력했습니다.",
        points: [
          "멀티 디스플레이 프레임 동기화",
          "대형 LED 월 안정 출력",
        ],
      },
      {
        type: "split", media: "left",
        label: "데이터 바인딩 템플릿",
        heading: "코드 없는 데이터 바인딩",
        body: "운영진이 수치만 입력하면 그래픽에 그대로 반영되도록\n템플릿화했습니다.",
        points: [
          "코드 없이 수치만 입력",
          "방송 사고 위험 최소화",
        ],
      },
      {
        type: "split", media: "left",
        label: "온에어 화면 모음",
        heading: "온에어 결과",
        body: "실제 생방송에 송출된 장면들을 모았습니다.",
        points: [
          "실시간 송출 검증 완료",
          "선거·스포츠 등 다양한 포맷 대응",
        ],
      },
    ],
  },
  {
    id: "environment-lookdev",
    category: "Art",
    title: "3D 환경 & 룩데브",
    year: "2023",
    discipline: "3D · Environment",
    role: "Environment / Lookdev Artist — 모델링·셰이딩·라이팅",
    tools: ["Maya", "ZBrush", "Substance Painter", "Unreal Engine 5"],
    tagline: "분위기까지 설계하는 실시간 환경 룩데브",
    description:
      "콘셉트에서 출발해 모델링·텍스처링·셰이딩·라이팅까지 환경 한 신을 끝까지 완성했습니다. 실시간 엔진 안에서 시간대와 분위기를 바꿔가며 룩을 검증했고, 모듈식 에셋으로 재사용성을 확보했습니다.",
    slides: [
      {
        type: "split", media: "left",
        label: "환경 와이드 샷",
        heading: "최종 환경 와이드 샷",
        body: "콘셉트부터 라이팅까지 끝까지 완성한 환경의 전경입니다.\n실시간 엔진 안에서 렌더링했습니다.",
        points: [
          "콘셉트→완성까지 단독 진행",
          "실시간 엔진 내 룩 검증",
        ],
      },
      {
        type: "split", media: "left",
        label: "모듈러 에셋 키트",
        heading: "모듈러 에셋 키트",
        body: "재사용 가능한 모듈식 에셋으로 환경을 구성해\n다양한 신에 빠르게 재배치할 수 있습니다.",
        points: [
          "모듈 조합으로 빠른 신 구성",
          "에셋 재사용성 확보",
        ],
      },
      {
        type: "split", media: "left",
        label: "텍스처링 / 머티리얼 디테일",
        heading: "표면 디테일 룩데브",
        body: "Substance 기반으로 표면 디테일을 잡고\n실시간 머티리얼로 옮겼습니다.",
        points: [
          "Substance 텍스처링 워크플로우",
          "실시간 머티리얼로 최적 변환",
        ],
      },
      {
        type: "split", media: "left",
        label: "라이팅 무드 변주",
        heading: "시간대별 라이팅",
        body: "같은 환경에서 시간대와 분위기를 바꿔가며\n라이팅을 검증했습니다.",
        points: [
          "시간대별 무드 시나리오",
          "분위기까지 설계하는 룩데브",
        ],
      },
      {
        type: "split", media: "left",
        label: "와이어프레임 / 트라이앵글",
        heading: "폴리곤 예산 설계",
        body: "정해진 폴리곤 예산 안에서 실루엣과 디테일을 모두 살리도록\n형상을 설계했습니다.",
        points: [
          "예산 내 최적 토폴로지",
          "실루엣과 디테일 균형",
        ],
      },
      {
        type: "split", media: "left",
        label: "디테일 클로즈업",
        heading: "소품 디테일 클로즈업",
        body: "소품과 표면의 클로즈업 룩데브입니다.",
        points: [
          "근접 샷에서도 견디는 디테일",
          "재질감 일관성 유지",
        ],
      },
    ],
  },
  {
    id: "motion-reel",
    category: "Art",
    title: "모션그래픽 릴",
    year: "2022",
    discipline: "Motion · Design",
    role: "Motion Designer — 디자인·애니메이션·렌더링",
    tools: ["After Effects", "Cinema 4D", "Redshift"],
    tagline: "리듬과 타이포로 메시지를 움직이는 모션 릴",
    description:
      "브랜드·방송용 모션그래픽 작업을 모은 릴입니다. 타이포그래피·3D·셀 애니메이션을 오가며 메시지 전달에 맞는 리듬과 비주얼을 설계했습니다.",
    slides: [
      {
        type: "split", media: "left",
        label: "릴 오프닝 프레임",
        heading: "릴 오프닝",
        body: "릴을 여는 타이틀 시퀀스의 키 프레임입니다.",
        points: [
          "리듬으로 첫인상 설계",
          "브랜드 톤에 맞춘 오프닝",
        ],
      },
      {
        type: "split", media: "left",
        label: "키네틱 타이포 시퀀스",
        heading: "키네틱 타이포그래피",
        body: "사운드 리듬에 맞춰 타이포가 움직이며 메시지를 전달합니다.",
        points: [
          "리듬 기반 타이밍 설계",
          "가독성과 운동감의 균형",
        ],
      },
      {
        type: "split", media: "left",
        label: "3D 모션 샷",
        heading: "3D 모션",
        body: "Cinema 4D와 Redshift로 제작한 3D 모션 시퀀스입니다.",
        points: [
          "C4D + Redshift 파이프라인",
          "라이팅·머티리얼까지 직접",
        ],
      },
      {
        type: "split", media: "left",
        label: "인포그래픽 모션",
        heading: "인포그래픽 모션",
        body: "복잡한 데이터를 한눈에 들어오는 애니메이션으로 시각화했습니다.",
        points: [
          "데이터를 직관적 비주얼로",
          "단계적 정보 전달",
        ],
      },
      {
        type: "split", media: "left",
        label: "릴 엔딩 / 로고",
        heading: "릴 엔딩 · 로고",
        body: "릴을 닫는 클로징 로고 애니메이션입니다.",
        points: [
          "기억에 남는 마무리",
          "로고 모션 가이드 준수",
        ],
      },
    ],
  },
];

window.PROJECTS = PROJECTS;
