화면 효과 팩

화면 전체에 적용되는 후처리 팩(API 3): 색수차, 필름 그레인, CRT 등. 매니페스트 필드, PackEffect, 단계, 효과 스택, 온라인 갤러리를 설명합니다.

효과 팩이란

서피스 팩은 캐릭터 한 명의 재질 셰이딩을 바꿉니다. 효과 팩("type": "effect")은 대신 완성된 화면 전체에 적용됩니다. 색수차, 필름 그레인, CRT 스캔라인, 글리치, 나만의 비네트 같은 것들입니다. 효과는 모델이 아니라 화면 전체에 속합니다.

효과 팩은 앱에 내장되어 있지 않습니다. 셰이더 탭의 **온라인 목록(갤러리)**에서 설치하거나 zip을 가져오세요. 현재 갤러리에는 chromatic_aberration, film_grain, crt_scanlines가 올라와 있습니다. 효과 팩은 MMDX12 1.4.0 이상(API 버전 3)이 필요합니다.

효과 사용하기

  1. 셰이더 탭의 온라인 목록에서 효과 팩을 설치합니다.
  2. 로비의 셰이더 탭에서 화면 효과 행을 펼치거나, 재생 바의 반짝이 버튼을 누릅니다.
  3. 쓸 효과를 켜고, 화살표로 순서를 바꾸고, 슬라이더를 조정합니다.

스택은 최종 이미지에 위에서 아래로 실행됩니다. 재생 화면, 로비 미리보기, 실시간 영상·스틸 렌더(래스터, 실시간 RT, 실시간 PT)에 적용됩니다. 오프라인 GI 렌더러, 언릿·와이어프레임 보기, 스튜디오 쿼드 뷰에는 적용되지 않습니다. 켜진 효과가 없으면 추가 타깃도 추가 패스도 없어서, 이 기능이 없는 빌드와 프레임이 완전히 같습니다.

명령줄에서는 --effect <id>[,<id>...]로 한 번의 실행에 한해 스택을 바꾸고, --effect none으로 비웁니다.

폴더 구성

my_effect/
  pack.json      매니페스트 (서피스 팩과 같은 필드 + type / stage)
  effect.hlsl    PackEffect 구현
  preview.png    선택, 16:9 권장
  textures/      선택, pack.json "textures" (서피스 팩과 같은 규칙)

매니페스트 추가 항목

{
  "format": 1,
  "id": "film_grain",
  "version": "1.0.0",
  "apiVersion": 3,
  "minAppVersion": "1.4.0",
  "type": "effect",
  "stage": "post",
  "name": { "ko": "필름 그레인", "en": "Film grain" },
  "params": [
    { "key": "strength", "label": { "ko": "세기", "en": "Strength" }, "default": 0.12, "min": 0.0, "max": 0.6 }
  ]
}
  • "type": "effect"가 효과 팩입니다(기본값은 "surface").
  • "stage"는 "post"(기본) 또는 "pre-bloom"입니다.
  • classes는 쓰지 않습니다. params(최대 16개)와 textures(최대 16개)는 서피스 팩과 똑같이 동작합니다. 매니페스트를 참고하세요.
stage입력 / 출력용도
post톤맵과 컬러 LUT 이후의 디스플레이 sRGB, 8비트그레인, 스캔라인, 렌즈 번짐, 비네트
pre-bloom블룸 이전의 선형 HDR RGBA16F글로우 친화적이거나 노출을 고려하는 효과

두 단계의 효과를 한 스택에 섞을 수 있습니다. 각 단계는 자기 효과만 스택 순서대로 실행합니다.

effect.hlsl

팩은 함수 하나를 구현합니다.

float3 PackEffect(PackEffectInput i) { return i.color.rgb; }

PackEffectInput 필드:

필드의미
uv텍셀 중심, 0..1, 왼쪽 위 = (0, 0)
pixelSV_Position.xy (픽셀)
outputSize출력 해상도 (픽셀)
time장면 시작 후 경과 시간 (초)
frameIndex프레임 카운터 (64에서 순환)
color이 픽셀의 지금까지의 화면 (알파 유지)
depth원본 장치 깊이, 1 = 배경 (LinearZ()로 변환)
normal월드 공간 노멀, 배경에서는 정의되지 않음
motion모션 벡터, uv(현재) - uv(이전)

도우미:

  • gEffectSource.SampleLevel(gLinear, uv, 0)는 지금까지의 화면 임의 픽셀을 읽습니다(쌍선형, 클램프). 렌즈 효과가 주변 픽셀을 볼 때 쓰는 방법입니다.
  • PackParam(i)는 pack.json 순서대로 i번째 파라미터의 슬라이더 값(또는 기본값)입니다.
  • PackFxSampleTex(i, uv), PackFxSampleTexLevel, PackFxTexSize, PackFxTexCount로 팩 텍스처를 샘플링합니다. sRGB 텍스처는 선형 값을 돌려줍니다.
  • common.hlsli의 모든 것: Luminance, LinearZ, Ign, SrgbToLinear, gTime 등.

line은 HLSL 예약어입니다.

예제: 색수차

float3 PackEffect(PackEffectInput i) {
    const float2 dir = i.uv - 0.5;
    const float r = length(dir) * 1.41421356;   // 중심 0, 모서리 1
    const float2 offset = dir * (PackParam(0) * 0.03 * pow(r, PackParam(1)));
    float3 c;
    c.r = gEffectSource.SampleLevel(gLinear, i.uv + offset, 0).r;
    c.g = i.color.g;
    c.b = gEffectSource.SampleLevel(gLinear, i.uv - offset, 0).b;
    return c;
}

빨강과 파랑을 화면 중심에서 멀어지는 방향으로 샘플링하고, 가장자리로 갈수록 어긋남이 커집니다.

컴파일과 디버깅

셰이더는 실행 중 DXC(ps_6_0)로 컴파일됩니다. 컴파일 오류가 나면 그 효과를 건너뛰고 mmdx12.log에 [E] 줄을 남기며, 토스트와 셰이더 관리자의 상태로 알려 줍니다. 앱이 죽지 않습니다. 앱이 실행 중일 때 effect.hlsl을 저장하면 다시 불러옵니다.

명령줄에서는 pack_check <폴더|zip> --compile로 검사합니다. 디버깅을 참고하세요. 시작점이 필요하면 배포본의 shaders/pack_template_effect를 쓰세요.

배포

효과 팩도 서피스 팩과 같은 zip 구성, 버전, 심사 규칙을 따릅니다. 배포를 참고하세요. API 버전이 3이므로 "minAppVersion": "1.4.0"을 지정하세요.